diff options
author | Alex Williams <alex.williams@ni.com> | 2018-09-25 14:49:45 -0700 |
---|---|---|
committer | Ashish Chaudhari <ashish.chaudhari@ettus.com> | 2019-01-25 13:30:22 -0800 |
commit | ad2720d7188aece35e8aa4c65118a33b8b9ae690 (patch) | |
tree | 2d834deb728e0d59a60b8c23fa85da9db59df8af /host/lib/include | |
parent | 3c821adfedf859ffb689136eea2ac6fa6b48916a (diff) | |
download | uhd-ad2720d7188aece35e8aa4c65118a33b8b9ae690.tar.gz uhd-ad2720d7188aece35e8aa4c65118a33b8b9ae690.tar.bz2 uhd-ad2720d7188aece35e8aa4c65118a33b8b9ae690.zip |
mpmd,transport,prefs: Add xport_mgr for dpdk_zero_copy
Add configuration sections to the UHD config file for NIC entries. Keys
are based on MAC addresses, and the entries beneath the section describe
which CPU and I/O thread to use for the NIC and its IPv4 address.
Make ring sizes configurable for uhd-dpdk. Ring size is now an argument
for packet buffers. Note that the maximum number of available buffers
is still determined at init!
Add ability to receive broadcasts to uhd-dpdk. This is controllable by
a boolean in the sockarg during socket creation. dpdk_zero_copy will
filter broadcast packets out.
Add dpdk_simple transport (to mirror udp_simple). This transport allows
receiving from broadcast addresses, but it only permits one outstanding
buffer at a time.
Fix IP checksum handling in UHD-DPDK.
TX checksums were not being calculated in the NIC, and in RX, the check
for IP checksums allowed values of zero (reported as none). Now packets
with bad IP checksums will be dropped.
Diffstat (limited to 'host/lib/include')
-rw-r--r-- | host/lib/include/uhdlib/transport/dpdk_common.hpp | 80 | ||||
-rw-r--r-- | host/lib/include/uhdlib/transport/dpdk_simple.hpp | 95 | ||||
-rw-r--r-- | host/lib/include/uhdlib/transport/uhd-dpdk.h | 33 | ||||
-rw-r--r-- | host/lib/include/uhdlib/utils/prefs.hpp | 34 |
4 files changed, 235 insertions, 7 deletions
diff --git a/host/lib/include/uhdlib/transport/dpdk_common.hpp b/host/lib/include/uhdlib/transport/dpdk_common.hpp new file mode 100644 index 000000000..2f320e79e --- /dev/null +++ b/host/lib/include/uhdlib/transport/dpdk_common.hpp @@ -0,0 +1,80 @@ +// +// Copyright 2018 Ettus Research, a National Instruments Company +// +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#ifndef INCLUDED_DPDK_COMMON_HPP +#define INCLUDED_DPDK_COMMON_HPP + +#include <uhd/config.hpp> +#include <uhd/types/device_addr.hpp> +#include <uhd/utils/static.hpp> +#include <array> +#include <atomic> +#include <mutex> +#include <string> + +namespace uhd { namespace transport { + +class uhd_dpdk_ctx : boost::noncopyable { +public: + UHD_SINGLETON_FCN(uhd_dpdk_ctx, get); + + ~uhd_dpdk_ctx(void); + + /*! + * Initialize uhd-dpdk (and do only once) + * \param user_args User args passed in to override config files + */ + void init(const device_addr_t &user_args); + + /*! + * Get MTU of NICs used by DPDK + * + * \return Number of Bytes in MTU + */ + size_t get_mtu(void) const; + + /*! + * Get port ID from provided MAC address + * \param mac_addr MAC address + * \param port_id Int to write ID of port corresponding to MAC address + * \return 0 if match found, else no match + */ + int get_port_id(std::array<uint8_t, 6> mac_addr, unsigned int &port_id) const; + + /*! + * Get port ID for routing packet destined for given address + * \param addr Destination address + * \return port ID from routing table + */ + int get_route(const std::string &addr) const; + + /*! + * Set IPv4 address and subnet mask of given NIC port + * Not thread-safe. Should only be written before ports are in use. + * \param port_id NIC port ID + * \param ipv4_addr IPv4 address to write + * \param netmask Subnet mask identifying network number in ipv4_addr + * \return 0 if successful, else error + */ + int set_ipv4_addr(unsigned int port_id, uint32_t ipv4_addr, uint32_t netmask); + + /*! + * \return whether init() has been called + */ + bool is_init_done(void) const; + +private: + uhd_dpdk_ctx(void); + + size_t _mtu; + std::mutex _init_mutex; + std::atomic<bool> _init_done; + uhd::dict<uint32_t, unsigned int> _routes; +}; + +}} // namespace uhd::transport + +#endif /* INCLUDED_DPDK_COMMON_HPP */ diff --git a/host/lib/include/uhdlib/transport/dpdk_simple.hpp b/host/lib/include/uhdlib/transport/dpdk_simple.hpp new file mode 100644 index 000000000..62728b38d --- /dev/null +++ b/host/lib/include/uhdlib/transport/dpdk_simple.hpp @@ -0,0 +1,95 @@ +// +// Copyright 2019 Ettus Research, a National Instruments Company +// +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#ifndef INCLUDED_DPDK_SIMPLE_HPP +#define INCLUDED_DPDK_SIMPLE_HPP + +#include <uhdlib/transport/dpdk_common.hpp> + +namespace uhd { namespace transport { + +class dpdk_simple : boost::noncopyable +{ +public: + typedef boost::shared_ptr<dpdk_simple> sptr; + + virtual ~dpdk_simple(void) = 0; + + /*! + * Make a new connected dpdk transport: + * This transport is for sending and receiving + * between this host and a single endpoint. + * The primary usage for this transport will be control transactions. + * + * The address must be an ipv4 address. + * The port must be a number. + * + * \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, + const std::string &addr, const std::string &port); + + /*! + * Make a new broadcasting dpdk transport: + * This transport can send broadcast datagrams + * and receive datagrams from multiple sources. + * The primary usage for this transport will be to discover devices. + * + * The address must be an ipv4 address. + * The port must be a number. + * + * \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, + 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) + */ + virtual size_t send(size_t length) = 0; + + /*! + * Receive a single packet. + * Buffer provided by transport (must be freed). + * + * \param buf a pointer to place to write buffer location + * \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; + + /*! + * Get the last IP address as seen by recv(). + * Only use this with the broadcast socket. + */ + virtual std::string get_recv_addr(void) = 0; + + /*! + * Get the IP address for the destination + */ + virtual std::string get_send_addr(void) = 0; +}; + +}} // namespace uhd::transport + +#endif /* INCLUDED_DPDK_SIMPLE_HPP */ diff --git a/host/lib/include/uhdlib/transport/uhd-dpdk.h b/host/lib/include/uhdlib/transport/uhd-dpdk.h index 8d46912bd..ae7d31383 100644 --- a/host/lib/include/uhdlib/transport/uhd-dpdk.h +++ b/host/lib/include/uhdlib/transport/uhd-dpdk.h @@ -31,12 +31,22 @@ enum uhd_dpdk_sock_type { }; /** - * Init UHD-DPDK environment and bring up ports (link UP). - * - * Offload capabilities will be used if available + * Init UHD-DPDK environment, including DPDK's EAL. + * This will make available information about the DPDK-assigned NIC devices. * * @param argc passed directly to rte_eal_init() * @param argv passed directly to rte_eal_init() + * + * @return Returns negative error code if there were issues, else 0 + */ +int uhd_dpdk_init(int argc, const char **argv); + +/** + * Start UHD-DPDK networking stack. Bring ports up (link UP). + * uhd_dpdk_init() must be called first. + * + * Offload capabilities will be used if available + * * @param num_ports number of network interfaces to map * @param port_thread_mapping array of num_ports entries specifying which thread * will drive the I/O for a given port (determined by array index) @@ -47,9 +57,8 @@ enum uhd_dpdk_sock_type { * * @return Returns negative error code if there were issues, else 0 */ -int uhd_dpdk_init(int argc, const char **argv, unsigned int num_ports, - int *port_thread_mapping, int num_mbufs, int mbuf_cache_size, - int mtu); +int uhd_dpdk_start(unsigned int num_ports, int *port_thread_mapping, + int num_mbufs, int mbuf_cache_size, int mtu); /** * @return Returns number of ports registered to DPDK. @@ -58,6 +67,12 @@ int uhd_dpdk_init(int argc, const char **argv, unsigned int num_ports, int uhd_dpdk_port_count(void); /** + * @return Returns 0 if link is down, 1 if link is up, and negative error code + * if error occurred. + */ +int uhd_dpdk_port_link_status(unsigned int portid); + +/** * @return Returns Ethernet MAC address of requested port * * @param portid ID number of network interface @@ -121,17 +136,21 @@ int uhd_dpdk_sock_close(struct uhd_dpdk_socket *sock); /** * Arguments for a UDP socket - * All data should be provided in network format + * All address/port data should be provided in network format */ struct uhd_dpdk_sockarg_udp { /*! True for TX socket, false for RX socket */ bool is_tx; + /*! True to filter broadcast packets, else recv */ + bool filter_bcast; /*! Local udp port. This is dst_port for RX, src_port for TX */ uint16_t local_port; /*! Remote udp port. This is dst_port for TX */ uint16_t remote_port; /*! IPv4 address for destination (TX) */ uint32_t dst_addr; + /*! Number of buffers in ring */ + size_t num_bufs; }; /** diff --git a/host/lib/include/uhdlib/utils/prefs.hpp b/host/lib/include/uhdlib/utils/prefs.hpp index 62831a875..e528450cd 100644 --- a/host/lib/include/uhdlib/utils/prefs.hpp +++ b/host/lib/include/uhdlib/utils/prefs.hpp @@ -48,6 +48,40 @@ namespace uhd { namespace prefs { */ uhd::device_addr_t get_usrp_args(const uhd::device_addr_t &user_args); + /*! Convenience function to update global DPDK args with settings from + * config files. + * + * Searches for a profile attached to the dpdk-conf key, like this: + * [dpdk-conf=myconfig] + * num_mbufs=4095 + * mbuf_cache_size=315 + * mtu=8000 + * + * \param user_args After getting the device args from the config + * files, all of these key/value pairs will be applied + * and will overwrite the settings from config files + * if they exist. + */ + uhd::device_addr_t get_dpdk_args(const uhd::device_addr_t &user_args); + + /*! Convenience function to update per-NIC DPDK args with settings from + * config files. + * + * Grabs settings based on provided MAC address. Sections created like so: + * [dpdk-mac=00:01:02:03:04:05] + * dpdk-ipv4 = 192.168.20.1/24 + * dpdk-io-cpu = 1 + * + * [dpdk-mac=00:01:02:03:04:06] + * dpdk-ipv4 = 192.168.40.1/24 + * dpdk-io-cpu = 1 + * + * \param user_args After getting the device args from the config + * files, all of these key/value pairs will be applied + * and will overwrite the settings from config files + * if they exist. + */ + uhd::device_addr_t get_dpdk_nic_args(const uhd::device_addr_t &user_args); }} /* namespace uhd::prefs */ #endif /* INCLUDED_LIBUHD_UTILS_PREFS_HPP */ |