aboutsummaryrefslogtreecommitdiffstats
path: root/host
diff options
context:
space:
mode:
Diffstat (limited to 'host')
-rw-r--r--host/include/uhd/transport/CMakeLists.txt1
-rw-r--r--host/include/uhd/transport/frame_buff.hpp69
-rw-r--r--host/lib/include/uhdlib/transport/link_base.hpp233
-rw-r--r--host/lib/include/uhdlib/transport/link_if.hpp101
4 files changed, 404 insertions, 0 deletions
diff --git a/host/include/uhd/transport/CMakeLists.txt b/host/include/uhd/transport/CMakeLists.txt
index d0810e502..400b3db0b 100644
--- a/host/include/uhd/transport/CMakeLists.txt
+++ b/host/include/uhd/transport/CMakeLists.txt
@@ -10,6 +10,7 @@ UHD_INSTALL(FILES
bounded_buffer.ipp
buffer_pool.hpp
chdr.hpp
+ frame_buff.hpp
if_addrs.hpp
udp_constants.hpp
udp_simple.hpp
diff --git a/host/include/uhd/transport/frame_buff.hpp b/host/include/uhd/transport/frame_buff.hpp
new file mode 100644
index 000000000..c335f0c4b
--- /dev/null
+++ b/host/include/uhd/transport/frame_buff.hpp
@@ -0,0 +1,69 @@
+//
+// Copyright 2019 Ettus Research, a National Instruments Brand
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+//
+
+#ifndef INCLUDED_UHD_TRANSPORT_FRAME_BUFF_HPP
+#define INCLUDED_UHD_TRANSPORT_FRAME_BUFF_HPP
+
+#include <memory>
+
+namespace uhd { namespace transport {
+
+/*!
+ * Contains a reference to a frame buffer managed by a link.
+ */
+class frame_buff
+{
+public:
+ /*!
+ * No-op deleter to prevent unique_ptr from deleting the buffer if the
+ * pointer goes out of scope. The lifetime of the buffers is controlled
+ * by the links.
+ */
+ struct deleter
+ {
+ void operator()(frame_buff*) {}
+ };
+
+ using uptr = std::unique_ptr<frame_buff, deleter>;
+
+ /*!
+ * Get the raw data buffer contained within the frame buffer
+ * \return a pointer to the buffer memory.
+ */
+ void* data() const
+ {
+ return _data;
+ }
+
+ /*!
+ * Returns the size of the packet
+ * \return the size of the packet contained in the frame buffer, in bytes.
+ */
+ size_t packet_size() const
+ {
+ return _packet_size;
+ }
+
+ /*!
+ * Sets the size of the packet contained in the frame buffer, in bytes.
+ * \param size Number of bytes occupied in the buffer
+ */
+ void set_packet_size(size_t size)
+ {
+ _packet_size = size;
+ }
+
+protected:
+ /*! Pointer to data of current frame */
+ void* _data = nullptr;
+
+ /*! Size of packet in current frame */
+ size_t _packet_size = 0;
+};
+
+}} // namespace uhd::transport
+
+#endif /* INCLUDED_UHD_TRANSPORT_FRAME_BUFF_HPP */
diff --git a/host/lib/include/uhdlib/transport/link_base.hpp b/host/lib/include/uhdlib/transport/link_base.hpp
new file mode 100644
index 000000000..e4d329e2a
--- /dev/null
+++ b/host/lib/include/uhdlib/transport/link_base.hpp
@@ -0,0 +1,233 @@
+//
+// Copyright 2019 Ettus Research, a National Instruments Brand
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+//
+
+#ifndef INCLUDED_UHDLIB_TRANSPORT_LINK_BASE_HPP
+#define INCLUDED_UHDLIB_TRANSPORT_LINK_BASE_HPP
+
+#include <uhdlib/transport/link_if.hpp>
+#include <cassert>
+#include <vector>
+
+namespace uhd { namespace transport {
+namespace detail {
+
+/*!
+ * Container for free buffers used by link base classes.
+ */
+class free_buff_pool
+{
+public:
+ free_buff_pool(const size_t capacity)
+ {
+ _buffs.reserve(capacity);
+ }
+
+ frame_buff* pop()
+ {
+ // Free buffer pool should not be empty unless user has requested more
+ // buffers than the number of frames in the link.
+ assert(!_buffs.empty());
+
+ frame_buff* buff = _buffs.back();
+ _buffs.pop_back();
+ return buff;
+ }
+
+ void push(frame_buff* buff)
+ {
+ _buffs.push_back(buff);
+ }
+
+private:
+ std::vector<frame_buff*> _buffs;
+};
+
+} // namespace detail
+
+/*!
+ * Reusable base class implementation of send_link_iface. Link implementations
+ * should derive from this template and pass their own type as the derived_t
+ * template parameter.
+ *
+ * The base class template manages a pool of frame_buff pointers and implements
+ * the link interface methods.
+ *
+ * This template requires the following methods in the derived class:
+ * bool get_send_buf_derived(frame_buff& buf, int32_t timeout_ms);
+ * void release_send_buf_derived(frame_buff& buf);
+ *
+ * Additionally, the subclass must call preload_free_buf for each frame_buff
+ * object it owns during initialization to add it to the free buffer pool.
+ *
+ * \param derived_t type of the derived class
+ */
+template <typename derived_t>
+class send_link_base : public virtual send_link_if
+{
+public:
+ send_link_base(const size_t num_frames, const size_t frame_size)
+ : _send_frame_size(frame_size)
+ , _num_send_frames(num_frames)
+ , _free_send_buffs(num_frames)
+ {
+ }
+
+ virtual size_t get_num_send_frames() const
+ {
+ return _num_send_frames;
+ }
+
+ virtual size_t get_send_frame_size() const
+ {
+ return _send_frame_size;
+ }
+
+ virtual frame_buff::uptr get_send_buff(int32_t timeout_ms)
+ {
+ frame_buff* buff = _free_send_buffs.pop();
+
+ // Call the derived class for link-specific implementation
+ auto* derived = static_cast<derived_t*>(this);
+
+ if (!derived->get_send_buff_derived(*buff, timeout_ms)) {
+ _free_send_buffs.push(buff);
+ return frame_buff::uptr();
+ }
+
+ return frame_buff::uptr(buff);
+ }
+
+ virtual void release_send_buff(frame_buff::uptr buff)
+ {
+ frame_buff* buff_ptr = buff.release();
+ assert(buff_ptr);
+
+ if (buff_ptr->packet_size() != 0) {
+ // Call the derived class for link-specific implementation
+ auto* derived = static_cast<derived_t*>(this);
+ derived->release_send_buff_derived(*buff_ptr);
+ }
+
+ // Reset buff and re-add to free pool
+ buff_ptr->set_packet_size(0);
+ _free_send_buffs.push(buff_ptr);
+ }
+
+protected:
+ /*!
+ * Add buffer pointer to free buffer pool.
+ *
+ * Derived classes should call this method during initialization for each
+ * frame buffer it owns.
+ *
+ * \param buffer pointer to the buffer to add to the free buffer pool.
+ */
+ void preload_free_buff(frame_buff* buff)
+ {
+ _free_send_buffs.push(buff);
+ }
+
+private:
+ size_t _send_frame_size;
+ size_t _num_send_frames;
+ detail::free_buff_pool _free_send_buffs;
+};
+
+/*!
+ * Reusable base class implementation of recv_link_if. Link implementations
+ * should derive from this template and pass their own type as the derived_t
+ * template parameter.
+ *
+ * The base class template manages a pool of free_buff pointers and implements
+ * the link interface methods.
+ *
+ * This template requires the following methods in the derived class:
+ * bool get_recv_buff_derived(frame_buff& buff, int32_t timeout_ms);
+ * void release_recv_buff_derived(frame_buff& buff);
+ *
+ * Additionally, the subclass must call preload_free_buff for each
+ * frame_buff object it owns during initialization to add it to the free
+ * buff pool.
+ *
+ * \param derived_t type of the derived class
+ */
+template <typename derived_t>
+class recv_link_base : public virtual recv_link_if
+{
+public:
+ recv_link_base(const size_t num_frames, const size_t frame_size)
+ : _recv_frame_size(frame_size)
+ , _num_recv_frames(num_frames)
+ , _free_recv_buffs(num_frames)
+ {
+ }
+
+ virtual size_t get_num_recv_frames() const
+ {
+ return _num_recv_frames;
+ }
+
+ virtual size_t get_recv_frame_size() const
+ {
+ return _recv_frame_size;
+ }
+
+ virtual frame_buff::uptr get_recv_buff(int32_t timeout_ms)
+ {
+ frame_buff* buff = _free_recv_buffs.pop();
+
+ // Call the derived class for link specific implementation
+ auto* derived = static_cast<derived_t*>(this);
+
+ size_t len = derived->get_recv_buff_derived(*buff, timeout_ms);
+
+ if (len == 0) {
+ _free_recv_buffs.push(buff);
+ return frame_buff::uptr();
+ } else {
+ buff->set_packet_size(len);
+ return frame_buff::uptr(buff);
+ }
+ }
+
+ virtual void release_recv_buff(frame_buff::uptr buff)
+ {
+ frame_buff* buff_ptr = buff.release();
+ assert(buff_ptr);
+
+ // Call the derived class for link specific implementation
+ auto* derived = static_cast<derived_t*>(this);
+
+ derived->release_recv_buff_derived(*buff_ptr);
+
+ // Reset buffer and re-add to free pool
+ buff_ptr->set_packet_size(0);
+ _free_recv_buffs.push(buff_ptr);
+ }
+
+protected:
+ /*!
+ * Add buffer pointer to free buffer pool.
+ *
+ * Derived classes should call this method during initialization for each
+ * frame buffer it owns.
+ *
+ * \param buffer pointer to the buffer to add to the free buffer pool.
+ */
+ void preload_free_buff(frame_buff* buff)
+ {
+ _free_recv_buffs.push(buff);
+ }
+
+private:
+ size_t _recv_frame_size;
+ size_t _num_recv_frames;
+ detail::free_buff_pool _free_recv_buffs;
+};
+
+}} // namespace uhd::transport
+
+#endif /* INCLUDED_UHDLIB_TRANSPORT_LINK_BASE_HPP */
diff --git a/host/lib/include/uhdlib/transport/link_if.hpp b/host/lib/include/uhdlib/transport/link_if.hpp
new file mode 100644
index 000000000..60376e571
--- /dev/null
+++ b/host/lib/include/uhdlib/transport/link_if.hpp
@@ -0,0 +1,101 @@
+//
+// Copyright 2019 Ettus Research, a National Instruments Brand
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+//
+
+#include <uhd/transport/frame_buff.hpp>
+#include <memory>
+
+#ifndef INCLUDED_UHDLIB_TRANSPORT_LINK_IF_HPP
+# define INCLUDED_UHDLIB_TRANSPORT_LINK_IF_HPP
+
+namespace uhd { namespace transport {
+
+/*!
+ * Link interface for transmitting packets.
+ */
+class send_link_if
+{
+public:
+ using sptr = std::shared_ptr<send_link_if>;
+
+ /*!
+ * Get the number of frame buffers that can be queued by this link.
+ */
+ virtual size_t get_num_send_frames() const = 0;
+
+ /*!
+ * Get the maximum capacity of a frame buffer.
+ */
+ virtual size_t get_send_frame_size() const = 0;
+
+ /*!
+ * Get an empty frame buffer in which to write packet contents.
+ *
+ * \param timeout_ms a positive timeout value specifies the maximum number
+ of ms to wait, a negative value specifies to block
+ until successful, and a value of 0 specifies no wait.
+ * \return a frame buffer, or null uptr if timeout occurs
+ */
+ virtual frame_buff::uptr get_send_buff(int32_t timeout_ms) = 0;
+
+ /*!
+ * Send a packet with the contents of the frame buffer and release the
+ * buffer, allowing the link driver to reuse it. If the size of the frame
+ * buffer is 0, the buffer is released with no packet being sent.
+ *
+ * \param buffer frame buffer containing packet data
+ *
+ * Throws an exception if an I/O error occurs while sending
+ */
+ virtual void release_send_buff(frame_buff::uptr buff) = 0;
+
+ send_link_if() = default;
+ send_link_if(const send_link_if&) = delete;
+ send_link_if& operator=(const send_link_if&) = delete;
+};
+
+/*!
+ * Link interface for receiving packets.
+ */
+class recv_link_if
+{
+public:
+ using sptr = std::shared_ptr<recv_link_if>;
+
+ /*!
+ * Get the number of frame buffers that can be queued by this link.
+ */
+ virtual size_t get_num_recv_frames() const = 0;
+
+ /*!
+ * Get the maximum capacity of a frame buffer.
+ */
+ virtual size_t get_recv_frame_size() const = 0;
+
+ /*!
+ * Receive a packet and return a frame buffer containing the packet data.
+ *
+ * \param timeout_ms a positive timeout value specifies the maximum number
+ of ms to wait, a negative value specifies to block
+ until successful, and a value of 0 specifies no wait.
+ * \return a frame buffer, or null uptr if timeout occurs
+ */
+ virtual frame_buff::uptr get_recv_buff(int32_t timeout_ms) = 0;
+
+ /*!
+ * Release a frame buffer, allowing the link driver to reuse it.
+ *
+ * \param buffer frame buffer to release for reuse by the link
+ */
+ virtual void release_recv_buff(frame_buff::uptr buff) = 0;
+
+ recv_link_if() = default;
+ recv_link_if(const recv_link_if&) = delete;
+ recv_link_if& operator=(const recv_link_if&) = delete;
+};
+
+}} // namespace uhd::transport
+
+#endif /* INCLUDED_UHDLIB_TRANSPORT_LINK_IF_HPP */