From 36802305b41feff59f0e3c346a595f286979fcab Mon Sep 17 00:00:00 2001 From: Alex Williams Date: Fri, 15 Mar 2019 15:05:45 -0700 Subject: transport: Make dpdk_simple subclass udp_simple With the same APIs, this will make it easier to add support for X310. --- host/lib/include/uhdlib/transport/dpdk_simple.hpp | 41 +++----- host/lib/transport/dpdk_simple.cpp | 121 +++++++++++----------- 2 files changed, 77 insertions(+), 85 deletions(-) diff --git a/host/lib/include/uhdlib/transport/dpdk_simple.hpp b/host/lib/include/uhdlib/transport/dpdk_simple.hpp index 62728b38d..86abaeff8 100644 --- a/host/lib/include/uhdlib/transport/dpdk_simple.hpp +++ b/host/lib/include/uhdlib/transport/dpdk_simple.hpp @@ -7,15 +7,14 @@ #ifndef INCLUDED_DPDK_SIMPLE_HPP #define INCLUDED_DPDK_SIMPLE_HPP +#include #include namespace uhd { namespace transport { -class dpdk_simple : boost::noncopyable +class dpdk_simple : public udp_simple { public: - typedef boost::shared_ptr sptr; - virtual ~dpdk_simple(void) = 0; /*! @@ -30,7 +29,7 @@ public: * \param addr a string representing the destination address * \param port a string representing the destination port */ - static sptr make_connected(struct uhd_dpdk_ctx &ctx, + static udp_simple::sptr make_connected(struct uhd_dpdk_ctx &ctx, const std::string &addr, const std::string &port); /*! @@ -45,38 +44,26 @@ public: * \param addr a string representing the destination address * \param port a string representing the destination port */ - static sptr make_broadcast(struct uhd_dpdk_ctx &ctx, + static udp_simple::sptr make_broadcast(struct uhd_dpdk_ctx &ctx, const std::string &addr, const std::string &port); /*! - * Request a single send buffer of specified size. - * - * \param buf a pointer to place to write buffer location - * \return the maximum length of the buffer in Bytes - */ - virtual size_t get_tx_buf(void** buf) = 0; - - /*! - * Send and release outstanding buffer - * - * \param number of bytes sent (releases buffer if sent) + * Send a single buffer. + * Blocks until the data is sent. + * \param buff single asio buffer + * \return the number of bytes sent */ - virtual size_t send(size_t length) = 0; + virtual size_t send(const boost::asio::const_buffer& buff) = 0; /*! - * Receive a single packet. - * Buffer provided by transport (must be freed). - * - * \param buf a pointer to place to write buffer location + * Receive into the provided buffer. + * Blocks until data is received or a timeout occurs. + * \param buff a mutable buffer to receive into * \param timeout the timeout in seconds * \return the number of bytes received or zero on timeout */ - virtual size_t recv(void **buf, double timeout = 0.1) = 0; - - /*! - * Return/free receive buffer - */ - virtual void put_rx_buf(void) = 0; + virtual size_t recv( + const boost::asio::mutable_buffer& buff, double timeout = 0.1) = 0; /*! * Get the last IP address as seen by recv(). diff --git a/host/lib/transport/dpdk_simple.cpp b/host/lib/transport/dpdk_simple.cpp index 74bb979ef..001775934 100644 --- a/host/lib/transport/dpdk_simple.cpp +++ b/host/lib/transport/dpdk_simple.cpp @@ -56,31 +56,7 @@ public: << "):" << ntohs(sockarg.local_port)); } - ~dpdk_simple_impl(void) - { - if (_rx_mbuf) - uhd_dpdk_free_buf(_rx_mbuf); - if (_tx_mbuf) - uhd_dpdk_free_buf(_tx_mbuf); - } - - /*! - * Request a single send buffer of specified size. - * - * \param buf a pointer to place to write buffer location - * \return the maximum length of the buffer - */ - size_t get_tx_buf(void** buf) - { - UHD_ASSERT_THROW(!_tx_mbuf); - int bufs = uhd_dpdk_request_tx_bufs(_tx_sock, &_tx_mbuf, 1, 0); - if (bufs != 1 || !_tx_mbuf) { - *buf = nullptr; - return 0; - } - *buf = uhd_dpdk_buf_to_data(_tx_sock, _tx_mbuf); - return _mtu - DPDK_SIMPLE_NONDATA_SIZE; - } + ~dpdk_simple_impl(void) {} /*! * Send and release outstanding buffer @@ -88,16 +64,24 @@ public: * \param length bytes of data to send * \return number of bytes sent (releases buffer if sent) */ - size_t send(size_t length) + size_t send(const boost::asio::const_buffer& buff) { - UHD_ASSERT_THROW(_tx_mbuf) - _tx_mbuf->pkt_len = length; - _tx_mbuf->data_len = length; - int num_tx = uhd_dpdk_send(_tx_sock, &_tx_mbuf, 1); + struct rte_mbuf* tx_mbuf; + size_t frame_size = _get_tx_buf(&tx_mbuf); + UHD_ASSERT_THROW(tx_mbuf) + size_t nbytes = boost::asio::buffer_size(buff); + UHD_ASSERT_THROW(nbytes <= frame_size) + const uint8_t* user_data = boost::asio::buffer_cast(buff); + + uint8_t* pkt_data = (uint8_t*) uhd_dpdk_buf_to_data(_tx_sock, tx_mbuf); + std::memcpy(pkt_data, user_data, nbytes); + tx_mbuf->pkt_len = nbytes; + tx_mbuf->data_len = nbytes; + + int num_tx = uhd_dpdk_send(_tx_sock, &tx_mbuf, 1); if (num_tx == 0) return 0; - _tx_mbuf = nullptr; - return length; + return nbytes; } /*! @@ -108,32 +92,29 @@ public: * \param timeout the timeout in seconds * \return the number of bytes received or zero on timeout */ - size_t recv(void **buf, double timeout) + size_t recv(const boost::asio::mutable_buffer& buff, double timeout) { - UHD_ASSERT_THROW(!_rx_mbuf); - int bufs = uhd_dpdk_recv(_rx_sock, &_rx_mbuf, 1, (int) (timeout*USEC)); - if (bufs != 1 || _rx_mbuf == nullptr) { - *buf = nullptr; + struct rte_mbuf *rx_mbuf; + size_t buff_size = boost::asio::buffer_size(buff); + uint8_t* user_data = boost::asio::buffer_cast(buff); + + int bufs = uhd_dpdk_recv(_rx_sock, &rx_mbuf, 1, (int) (timeout*USEC)); + if (bufs != 1 || rx_mbuf == nullptr) { return 0; } - if ((_tx_mbuf->ol_flags & PKT_RX_IP_CKSUM_MASK) == PKT_RX_IP_CKSUM_BAD) { - uhd_dpdk_free_buf(_rx_mbuf); - _rx_mbuf = nullptr; + if ((rx_mbuf->ol_flags & PKT_RX_IP_CKSUM_MASK) == PKT_RX_IP_CKSUM_BAD) { + uhd_dpdk_free_buf(rx_mbuf); return 0; } - uhd_dpdk_get_src_ipv4(_rx_sock, _rx_mbuf, &_last_recv_addr); - *buf = uhd_dpdk_buf_to_data(_rx_sock, _rx_mbuf); - return uhd_dpdk_get_len(_rx_sock, _rx_mbuf); - } + uhd_dpdk_get_src_ipv4(_rx_sock, rx_mbuf, &_last_recv_addr); - /*! - * Return/free receive buffer - * Can also use to free un-sent TX bufs - */ - void put_rx_buf(void) - { - UHD_ASSERT_THROW(_rx_mbuf) - uhd_dpdk_free_buf(_rx_mbuf); + const size_t nbytes = uhd_dpdk_get_len(_rx_sock, rx_mbuf); + UHD_ASSERT_THROW(nbytes <= buff_size); + + uint8_t* pkt_data = (uint8_t*) uhd_dpdk_buf_to_data(_rx_sock, rx_mbuf); + std::memcpy(user_data, pkt_data, nbytes); + _put_rx_buf(rx_mbuf); + return nbytes; } /*! @@ -162,12 +143,36 @@ public: return std::string(addr_str); } private: + /*! + * Request a single send buffer of specified size. + * + * \param buf a pointer to place to write buffer location + * \return the maximum length of the buffer + */ + size_t _get_tx_buf(struct rte_mbuf** buf) + { + int bufs = uhd_dpdk_request_tx_bufs(_tx_sock, buf, 1, 0); + if (bufs != 1) { + *buf = nullptr; + return 0; + } + return _mtu - DPDK_SIMPLE_NONDATA_SIZE; + } + + /*! + * Return/free receive buffer + * Can also use to free un-sent TX bufs + */ + void _put_rx_buf(struct rte_mbuf *rx_mbuf) + { + UHD_ASSERT_THROW(rx_mbuf) + uhd_dpdk_free_buf(rx_mbuf); + } + unsigned int _port_id; size_t _mtu; struct uhd_dpdk_socket *_tx_sock; - struct rte_mbuf *_tx_mbuf = nullptr; struct uhd_dpdk_socket *_rx_sock; - struct rte_mbuf *_rx_mbuf = nullptr; uint32_t _last_recv_addr; }; @@ -176,16 +181,16 @@ dpdk_simple::~dpdk_simple(void) {} /*********************************************************************** * DPDK simple transport public make functions **********************************************************************/ -dpdk_simple::sptr dpdk_simple::make_connected( +udp_simple::sptr dpdk_simple::make_connected( struct uhd_dpdk_ctx &ctx, const std::string &addr, const std::string &port ){ - return sptr(new dpdk_simple_impl(ctx, addr, port, true)); + return udp_simple::sptr(new dpdk_simple_impl(ctx, addr, port, true)); } -dpdk_simple::sptr dpdk_simple::make_broadcast( +udp_simple::sptr dpdk_simple::make_broadcast( struct uhd_dpdk_ctx &ctx, const std::string &addr, const std::string &port ){ - return sptr(new dpdk_simple_impl(ctx, addr, port, false)); + return udp_simple::sptr(new dpdk_simple_impl(ctx, addr, port, false)); } }} // namespace uhd::transport -- cgit v1.2.3