diff options
-rw-r--r-- | host/docs/dpdk.dox | 12 | ||||
-rw-r--r-- | host/lib/CMakeLists.txt | 2 | ||||
-rw-r--r-- | host/lib/include/uhdlib/transport/dpdk/udp.hpp | 25 | ||||
-rw-r--r-- | host/lib/transport/udp_dpdk_link.cpp | 5 | ||||
-rw-r--r-- | host/lib/transport/uhd-dpdk/dpdk_common.cpp | 71 | ||||
-rw-r--r-- | host/lib/transport/uhd-dpdk/dpdk_io_service.cpp | 34 |
6 files changed, 100 insertions, 49 deletions
diff --git a/host/docs/dpdk.dox b/host/docs/dpdk.dox index 54ed1c6e4..539a6ce18 100644 --- a/host/docs/dpdk.dox +++ b/host/docs/dpdk.dox @@ -26,7 +26,7 @@ computer. \subsection dpdk_installation DPDK Installation Instructions As a new and developing technology, the DPDK APIs are unstable. UHD requires -version 19.11 or 20.11. +version 19.11, 20.11 or 21.11. On Ubuntu 20.04, Fedora 33-36, or Debian Bullseye/Buster (via backports), DPDK is available in your distribution's repositories. For example, on Debian @@ -35,8 +35,8 @@ systems, it can be obtained with the following command: sudo apt install dpdk dpdk-dev Otherwise, you'll need to follow the build guide at -https://doc.dpdk.org/guides-20.11/linux_gsg/build_dpdk.html . The software -releases can be found at https://core.dpdk.org/download/. Version 20.11 builds +https://doc.dpdk.org/guides-21.11/linux_gsg/build_dpdk.html . The software +releases can be found at https://core.dpdk.org/download/. Version >=20.11 builds with appropriate options when using the default build procedure. Note that if you are using a Mellanox NIC, the MLNX-OFED drivers available from @@ -61,7 +61,7 @@ following line: \subsection dpdk_system_configuration System Configuration The official documentation regarding system configuration can be found at -https://doc.dpdk.org/guides-20.11/linux_gsg/sys_reqs.html. +https://doc.dpdk.org/guides-21.11/linux_gsg/sys_reqs.html. First, you'll need to enable the IOMMU and set up some hugepages. DPDK will completely take over all available hugepages, so don't allocate all your memory @@ -107,7 +107,7 @@ If successful, the script might provide an updated status like this: [...] -See https://doc.dpdk.org/guides-20.11/linux_gsg/linux_drivers.html#binding-and-unbinding-network-ports-to-from-the-kernel-modules +See https://doc.dpdk.org/guides-21.11/linux_gsg/linux_drivers.html#binding-and-unbinding-network-ports-to-from-the-kernel-modules for more details. With the hugepages, IOMMU, and drivers set up, the system is ready for DPDK to @@ -141,7 +141,7 @@ options: ;create a separate folder with symlinks to the librte_pmd_* and librte_mempool_* libraries. dpdk_driver=/usr/local/lib/x86_64-linux-gnu/dpdk/pmds-21.0/ ;dpdk_corelist is the -l flag for the DPDK EAL. See more at the link - ; https://doc.dpdk.org/guides-20.11/linux_gsg/build_sample_apps.html#running-a-sample-application + ; https://doc.dpdk.org/guides-21.11/linux_gsg/build_sample_apps.html#running-a-sample-application dpdk_corelist=0,1 ;dpdk_num_mbufs is the total number of packet buffers allocated ;to each direction's packet buffer pool diff --git a/host/lib/CMakeLists.txt b/host/lib/CMakeLists.txt index 00da8b75c..094827d2a 100644 --- a/host/lib/CMakeLists.txt +++ b/host/lib/CMakeLists.txt @@ -60,7 +60,7 @@ endmacro(INCLUDE_SUBDIRECTORY) message(STATUS "") # Dependencies find_package(LIBUSB) -find_package(DPDK 19.11...20.11) +find_package(DPDK 19.11...21.11) LIBUHD_REGISTER_COMPONENT("USB" ENABLE_USB ON "ENABLE_LIBUHD;LIBUSB_FOUND" OFF OFF) # Devices LIBUHD_REGISTER_COMPONENT("B100" ENABLE_B100 ON "ENABLE_LIBUHD;ENABLE_USB" OFF OFF) diff --git a/host/lib/include/uhdlib/transport/dpdk/udp.hpp b/host/lib/include/uhdlib/transport/dpdk/udp.hpp index 712b73d81..d43fa3959 100644 --- a/host/lib/include/uhdlib/transport/dpdk/udp.hpp +++ b/host/lib/include/uhdlib/transport/dpdk/udp.hpp @@ -15,7 +15,8 @@ namespace uhd { namespace transport { namespace dpdk { constexpr size_t HDR_SIZE_UDP_IPV4 = - (sizeof(struct rte_ether_hdr) + sizeof(struct rte_ipv4_hdr) + sizeof(struct rte_udp_hdr)); + (sizeof(struct rte_ether_hdr) + sizeof(struct rte_ipv4_hdr) + + sizeof(struct rte_udp_hdr)); /*! * An enumerated type representing the type of flow for an IPv4 client @@ -57,12 +58,17 @@ inline void fill_rte_ipv4_hdr(struct rte_mbuf* mbuf, ip_hdr->hdr_checksum = 0; // Require HW offload ip_hdr->src_addr = port->get_ipv4(); ip_hdr->dst_addr = dst_rte_ipv4_addr; - +#if RTE_VER_YEAR > 21 || (RTE_VER_YEAR == 21 && RTE_VER_MONTH == 11) + mbuf->ol_flags = RTE_MBUF_F_TX_IP_CKSUM | RTE_MBUF_F_TX_IPV4; +#else mbuf->ol_flags = PKT_TX_IP_CKSUM | PKT_TX_IPV4; - mbuf->l2_len = sizeof(struct rte_ether_hdr); - mbuf->l3_len = sizeof(struct rte_ipv4_hdr); - mbuf->pkt_len = sizeof(struct rte_ether_hdr) + sizeof(struct rte_ipv4_hdr) + payload_len; - mbuf->data_len = sizeof(struct rte_ether_hdr) + sizeof(struct rte_ipv4_hdr) + payload_len; +#endif + mbuf->l2_len = sizeof(struct rte_ether_hdr); + mbuf->l3_len = sizeof(struct rte_ipv4_hdr); + mbuf->pkt_len = + sizeof(struct rte_ether_hdr) + sizeof(struct rte_ipv4_hdr) + payload_len; + mbuf->data_len = + sizeof(struct rte_ether_hdr) + sizeof(struct rte_ipv4_hdr) + payload_len; } /* All values except payload length must be in network order */ @@ -77,8 +83,11 @@ inline void fill_rte_udp_hdr(struct rte_mbuf* mbuf, struct rte_ipv4_hdr* ip_hdr; struct rte_udp_hdr* tx_hdr; - fill_rte_ipv4_hdr( - mbuf, port, dst_rte_ipv4_addr, IPPROTO_UDP, sizeof(struct rte_udp_hdr) + payload_len); + fill_rte_ipv4_hdr(mbuf, + port, + dst_rte_ipv4_addr, + IPPROTO_UDP, + sizeof(struct rte_udp_hdr) + payload_len); eth_hdr = rte_pktmbuf_mtod(mbuf, struct rte_ether_hdr*); ip_hdr = (struct rte_ipv4_hdr*)ð_hdr[1]; diff --git a/host/lib/transport/udp_dpdk_link.cpp b/host/lib/transport/udp_dpdk_link.cpp index 194b0536c..4249d4bb8 100644 --- a/host/lib/transport/udp_dpdk_link.cpp +++ b/host/lib/transport/udp_dpdk_link.cpp @@ -175,8 +175,13 @@ void udp_dpdk_link::release_send_buff(frame_buff::uptr buff) // Fill in L2 header auto local_mac = _port->get_mac_addr(); struct rte_ether_hdr* l2_hdr = rte_pktmbuf_mtod(mbuf, struct rte_ether_hdr*); +#if RTE_VER_YEAR > 21 || (RTE_VER_YEAR == 21 && RTE_VER_MONTH == 11) + rte_ether_addr_copy(&_remote_mac, &l2_hdr->dst_addr); + rte_ether_addr_copy(&local_mac, &l2_hdr->src_addr); +#else rte_ether_addr_copy(&_remote_mac, &l2_hdr->d_addr); rte_ether_addr_copy(&local_mac, &l2_hdr->s_addr); +#endif l2_hdr->ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4); // Fill in L3 and L4 headers dpdk::fill_rte_udp_hdr(mbuf, diff --git a/host/lib/transport/uhd-dpdk/dpdk_common.cpp b/host/lib/transport/uhd-dpdk/dpdk_common.cpp index a84b0f4a3..55bf57cdc 100644 --- a/host/lib/transport/uhd-dpdk/dpdk_common.cpp +++ b/host/lib/transport/uhd-dpdk/dpdk_common.cpp @@ -49,9 +49,9 @@ inline void separate_rte_ipv4_addr( boost::algorithm::split( result, ipv4, [](const char& in) { return in == '/'; }, boost::token_compress_on); UHD_ASSERT_THROW(result.size() == 2); - rte_ipv4_addr = (uint32_t)inet_addr(result[0].c_str()); - int netbits = std::atoi(result[1].c_str()); - netmask = htonl(0xffffffff << (32 - netbits)); + rte_ipv4_addr = (uint32_t)inet_addr(result[0].c_str()); + int netbits = std::atoi(result[1].c_str()); + netmask = htonl(0xffffffff << (32 - netbits)); } } // namespace @@ -63,8 +63,13 @@ dpdk_port::uptr dpdk_port::make(port_id_t port, struct rte_mempool* tx_pktbuf_pool, std::string rte_ipv4_address) { - return std::make_unique<dpdk_port>( - port, mtu, num_queues, num_desc, rx_pktbuf_pool, tx_pktbuf_pool, rte_ipv4_address); + return std::make_unique<dpdk_port>(port, + mtu, + num_queues, + num_desc, + rx_pktbuf_pool, + tx_pktbuf_pool, + rte_ipv4_address); } dpdk_port::dpdk_port(port_id_t port, @@ -83,17 +88,6 @@ dpdk_port::dpdk_port(port_id_t port, /* Set MTU and IPv4 address */ int retval; - retval = rte_eth_dev_set_mtu(_port, _mtu); - if (retval) { - uint16_t actual_mtu; - UHD_LOGGER_WARNING("DPDK") - << boost::format("Port %d: Could not set mtu to %d") % _port % _mtu; - rte_eth_dev_get_mtu(_port, &actual_mtu); - UHD_LOGGER_WARNING("DPDK") - << boost::format("Port %d: Current mtu=%d") % _port % actual_mtu; - _mtu = actual_mtu; - } - separate_rte_ipv4_addr(rte_ipv4_address, _ipv4, _netmask); /* Set hardware offloads */ @@ -121,11 +115,19 @@ dpdk_port::dpdk_port(port_id_t port, _num_queues = num_queues; } - struct rte_eth_conf port_conf = {}; - port_conf.rxmode.offloads = rx_offloads | DEV_RX_OFFLOAD_JUMBO_FRAME; + struct rte_eth_conf port_conf = {}; +#ifdef DEV_RX_OFFLOAD_JUMBO_FRAME + port_conf.rxmode.offloads = rx_offloads | DEV_RX_OFFLOAD_JUMBO_FRAME; +#else + port_conf.rxmode.offloads = rx_offloads; +#endif +#if RTE_VER_YEAR > 21 || (RTE_VER_YEAR == 21 && RTE_VER_MONTH == 11) + port_conf.rxmode.mtu = _mtu; +#else port_conf.rxmode.max_rx_pkt_len = _mtu; - port_conf.txmode.offloads = tx_offloads; - port_conf.intr_conf.lsc = 1; +#endif + port_conf.txmode.offloads = tx_offloads; + port_conf.intr_conf.lsc = 1; retval = rte_eth_dev_configure(_port, _num_queues, _num_queues, &port_conf); if (retval != 0) { @@ -133,6 +135,17 @@ dpdk_port::dpdk_port(port_id_t port, throw uhd::runtime_error("DPDK: Failed to configure the device"); } + retval = rte_eth_dev_set_mtu(_port, _mtu); + if (retval) { + uint16_t actual_mtu; + UHD_LOGGER_WARNING("DPDK") + << boost::format("Port %d: Could not set mtu to %d") % _port % _mtu; + rte_eth_dev_get_mtu(_port, &actual_mtu); + UHD_LOGGER_WARNING("DPDK") + << boost::format("Port %d: Current mtu=%d") % _port % actual_mtu; + _mtu = actual_mtu; + } + /* Set descriptor ring sizes */ uint16_t rx_desc = num_desc; if (dev_info.rx_desc_lim.nb_max < rx_desc || dev_info.rx_desc_lim.nb_min > rx_desc @@ -266,18 +279,27 @@ int dpdk_port::_arp_reply(queue_id_t queue_id, struct rte_arp_hdr* arp_req) hdr = rte_pktmbuf_mtod(mbuf, struct rte_ether_hdr*); arp_frame = (struct rte_arp_hdr*)&hdr[1]; +#if RTE_VER_YEAR > 21 || (RTE_VER_YEAR == 21 && RTE_VER_MONTH == 11) + rte_ether_addr_copy(&arp_req->arp_data.arp_sha, &hdr->dst_addr); + rte_ether_addr_copy(&_mac_addr, &hdr->src_addr); +#else rte_ether_addr_copy(&arp_req->arp_data.arp_sha, &hdr->d_addr); rte_ether_addr_copy(&_mac_addr, &hdr->s_addr); +#endif hdr->ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_ARP); arp_frame->arp_hardware = rte_cpu_to_be_16(RTE_ARP_HRD_ETHER); arp_frame->arp_protocol = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4); - arp_frame->arp_hlen = 6; - arp_frame->arp_plen = 4; - arp_frame->arp_opcode = rte_cpu_to_be_16(RTE_ARP_OP_REPLY); + arp_frame->arp_hlen = 6; + arp_frame->arp_plen = 4; + arp_frame->arp_opcode = rte_cpu_to_be_16(RTE_ARP_OP_REPLY); rte_ether_addr_copy(&_mac_addr, &arp_frame->arp_data.arp_sha); arp_frame->arp_data.arp_sip = _ipv4; +#if RTE_VER_YEAR > 21 || (RTE_VER_YEAR == 21 && RTE_VER_MONTH == 11) + rte_ether_addr_copy(&hdr->dst_addr, &arp_frame->arp_data.arp_tha); +#else rte_ether_addr_copy(&hdr->d_addr, &arp_frame->arp_data.arp_tha); +#endif arp_frame->arp_data.arp_tip = arp_req->arp_data.arp_sip; mbuf->pkt_len = 42; @@ -619,7 +641,8 @@ struct rte_mempool* dpdk_ctx::_get_rx_pktbuf_pool( unsigned int cpu_socket, size_t num_bufs) { if (!_rx_pktbuf_pools.at(cpu_socket)) { - const int mbuf_size = _mtu + RTE_PKTMBUF_HEADROOM; + const int mbuf_size = + _mtu + RTE_PKTMBUF_HEADROOM + RTE_ETHER_HDR_LEN + RTE_ETHER_CRC_LEN; char name[32]; snprintf(name, sizeof(name), "rx_mbuf_pool_%u", cpu_socket); _rx_pktbuf_pools[cpu_socket] = rte_pktmbuf_pool_create(name, diff --git a/host/lib/transport/uhd-dpdk/dpdk_io_service.cpp b/host/lib/transport/uhd-dpdk/dpdk_io_service.cpp index 4c8fa3f35..4133697ea 100644 --- a/host/lib/transport/uhd-dpdk/dpdk_io_service.cpp +++ b/host/lib/transport/uhd-dpdk/dpdk_io_service.cpp @@ -570,10 +570,10 @@ void dpdk_io_service::_service_xport_disconnect(dpdk::wait_req* req) int dpdk_io_service::_service_arp_request(dpdk::wait_req* req) { - int status = 0; - auto arp_req_data = (struct dpdk::arp_request*)req->data; + int status = 0; + auto arp_req_data = (struct dpdk::arp_request*)req->data; dpdk::rte_ipv4_addr dst_addr = arp_req_data->tpa; - auto ctx_sptr = _ctx.lock(); + auto ctx_sptr = _ctx.lock(); UHD_ASSERT_THROW(ctx_sptr); dpdk::dpdk_port* port = ctx_sptr->get_port(arp_req_data->port); UHD_LOG_TRACE("DPDK::IO_SERVICE", @@ -629,15 +629,20 @@ int dpdk_io_service::_send_arp_request( hdr = rte_pktmbuf_mtod(mbuf, struct rte_ether_hdr*); arp_frame = (struct rte_arp_hdr*)&hdr[1]; +#if RTE_VER_YEAR > 21 || (RTE_VER_YEAR == 21 && RTE_VER_MONTH == 11) + memset(hdr->dst_addr.addr_bytes, 0xFF, RTE_ETHER_ADDR_LEN); + hdr->src_addr = port->get_mac_addr(); +#else memset(hdr->d_addr.addr_bytes, 0xFF, RTE_ETHER_ADDR_LEN); - hdr->s_addr = port->get_mac_addr(); + hdr->s_addr = port->get_mac_addr(); +#endif hdr->ether_type = rte_cpu_to_be_16(RTE_ETHER_TYPE_ARP); - arp_frame->arp_hardware = rte_cpu_to_be_16(RTE_ARP_HRD_ETHER); - arp_frame->arp_protocol = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4); - arp_frame->arp_hlen = 6; - arp_frame->arp_plen = 4; - arp_frame->arp_opcode = rte_cpu_to_be_16(RTE_ARP_OP_REQUEST); + arp_frame->arp_hardware = rte_cpu_to_be_16(RTE_ARP_HRD_ETHER); + arp_frame->arp_protocol = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4); + arp_frame->arp_hlen = 6; + arp_frame->arp_plen = 4; + arp_frame->arp_opcode = rte_cpu_to_be_16(RTE_ARP_OP_REQUEST); arp_frame->arp_data.arp_sha = port->get_mac_addr(); arp_frame->arp_data.arp_sip = port->get_ipv4(); memset(arp_frame->arp_data.arp_tha.addr_bytes, 0x00, RTE_ETHER_ADDR_LEN); @@ -676,9 +681,18 @@ int dpdk_io_service::_rx_burst(dpdk::dpdk_port* port, dpdk::queue_id_t queue) rte_pktmbuf_free(bufs[buf]); break; case RTE_ETHER_TYPE_IPV4: + +#if RTE_VER_YEAR > 21 || (RTE_VER_YEAR == 21 && RTE_VER_MONTH == 11) + if ((ol_flags & RTE_MBUF_F_RX_IP_CKSUM_MASK) + == RTE_MBUF_F_RX_IP_CKSUM_BAD) { + UHD_LOG_WARNING("DPDK::IO_SERVICE", "RX packet has bad IP cksum"); + } else if ((ol_flags & RTE_MBUF_F_RX_IP_CKSUM_MASK) + == RTE_MBUF_F_RX_IP_CKSUM_NONE) { +#else if ((ol_flags & PKT_RX_IP_CKSUM_MASK) == PKT_RX_IP_CKSUM_BAD) { UHD_LOG_WARNING("DPDK::IO_SERVICE", "RX packet has bad IP cksum"); } else if ((ol_flags & PKT_RX_IP_CKSUM_MASK) == PKT_RX_IP_CKSUM_NONE) { +#endif UHD_LOG_WARNING("DPDK::IO_SERVICE", "RX packet missing IP cksum"); } else { _process_ipv4(port, bufs[buf], (struct rte_ipv4_hdr*)l2_data); @@ -695,7 +709,7 @@ int dpdk_io_service::_rx_burst(dpdk::dpdk_port* port, dpdk::queue_id_t queue) int dpdk_io_service::_process_arp( dpdk::dpdk_port* port, dpdk::queue_id_t queue_id, struct rte_arp_hdr* arp_frame) { - uint32_t dest_ip = arp_frame->arp_data.arp_sip; + uint32_t dest_ip = arp_frame->arp_data.arp_sip; struct rte_ether_addr dest_addr = arp_frame->arp_data.arp_sha; UHD_LOG_TRACE("DPDK::IO_SERVICE", "Processing ARP packet: " << dpdk::ipv4_num_to_str(dest_ip) << " -> " |