diff options
author | Alex Williams <alex.williams@ni.com> | 2019-01-25 09:50:32 -0800 |
---|---|---|
committer | Ashish Chaudhari <ashish.chaudhari@ettus.com> | 2019-01-25 13:30:22 -0800 |
commit | a293410435d085cf8e2e736d68197e10709c92f4 (patch) | |
tree | ff5e5b9fff1228c409385608f3c394dc33dc9ec4 /host | |
parent | 090bd9a625570c0f8a357cfb15074011c1c4b908 (diff) | |
download | uhd-a293410435d085cf8e2e736d68197e10709c92f4.tar.gz uhd-a293410435d085cf8e2e736d68197e10709c92f4.tar.bz2 uhd-a293410435d085cf8e2e736d68197e10709c92f4.zip |
uhd-dpdk: Cover all paths to request TX offloads
Some NICs were not enabling TX IP checksum offloads. This fixes that
issue.
Diffstat (limited to 'host')
-rw-r--r-- | host/lib/transport/uhd-dpdk/uhd_dpdk.c | 43 | ||||
-rw-r--r-- | host/lib/transport/uhd-dpdk/uhd_dpdk_driver.c | 22 | ||||
-rw-r--r-- | host/lib/transport/uhd-dpdk/uhd_dpdk_udp.c | 7 |
3 files changed, 61 insertions, 11 deletions
diff --git a/host/lib/transport/uhd-dpdk/uhd_dpdk.c b/host/lib/transport/uhd-dpdk/uhd_dpdk.c index 09897eb11..dd09525f1 100644 --- a/host/lib/transport/uhd-dpdk/uhd_dpdk.c +++ b/host/lib/transport/uhd-dpdk/uhd_dpdk.c @@ -13,7 +13,7 @@ #include <rte_malloc.h> #include <rte_log.h> -/* FIXME: Replace with configurable values */ +/* FIXME: Descriptor ring size: Replace with configurable values */ #define DEFAULT_RING_SIZE 512 /* FIXME: This needs to be protected */ @@ -111,25 +111,58 @@ static inline int uhd_dpdk_port_init(struct uhd_dpdk_port *port, RTE_LOG(WARNING, EAL, "Current mtu=%d\n", actual_mtu); mtu = actual_mtu; } - /* FIXME: Check if hw_ip_checksum is possible */ + + // Require checksum offloads + struct rte_eth_dev_info dev_info; + rte_eth_dev_info_get(port->id, &dev_info); + uint64_t rx_offloads = DEV_RX_OFFLOAD_IPV4_CKSUM; + uint64_t tx_offloads = DEV_TX_OFFLOAD_IPV4_CKSUM; + if ((dev_info.rx_offload_capa & rx_offloads) != rx_offloads) { + RTE_LOG(WARNING, EAL, "%d: Only supports RX offloads 0x%0llx\n", port->id, dev_info.rx_offload_capa); + rte_exit(EXIT_FAILURE, "Missing required RX offloads\n"); + } + if ((dev_info.tx_offload_capa & tx_offloads) != tx_offloads) { + RTE_LOG(WARNING, EAL, "%d: Only supports TX offloads 0x%0llx\n", port->id, dev_info.tx_offload_capa); + rte_exit(EXIT_FAILURE, "Missing required TX offloads\n"); + } + struct rte_eth_conf port_conf = { .rxmode = { + .offloads = rx_offloads | DEV_RX_OFFLOAD_JUMBO_FRAME, .max_rx_pkt_len = mtu, .jumbo_frame = 1, .hw_ip_checksum = 1, + .ignore_offload_bitfield = 0, + }, + .txmode = { + .offloads = tx_offloads, } }; retval = rte_eth_dev_configure(port->id, 1, 1, &port_conf); if (retval != 0) return retval; - retval = rte_eth_rx_queue_setup(port->id, 0, DEFAULT_RING_SIZE, + uint16_t rx_desc = DEFAULT_RING_SIZE; + uint16_t tx_desc = DEFAULT_RING_SIZE; + retval = rte_eth_dev_adjust_nb_rx_tx_desc(port->id, &rx_desc, &tx_desc); + if (retval != 0) + return retval; + + if (rx_desc != DEFAULT_RING_SIZE) + RTE_LOG(WARNING, EAL, "RX descriptors changed to %d\n", rx_desc); + if (tx_desc != DEFAULT_RING_SIZE) + RTE_LOG(WARNING, EAL, "TX descriptors changed to %d\n", tx_desc); + + retval = rte_eth_rx_queue_setup(port->id, 0, rx_desc, rte_eth_dev_socket_id(port->id), NULL, rx_mbuf_pool); if (retval < 0) return retval; - retval = rte_eth_tx_queue_setup(port->id, 0, DEFAULT_RING_SIZE, - rte_eth_dev_socket_id(port->id), NULL); + struct rte_eth_txconf txconf = { + .offloads = DEV_TX_OFFLOAD_IPV4_CKSUM + }; + retval = rte_eth_tx_queue_setup(port->id, 0, tx_desc, + rte_eth_dev_socket_id(port->id), &txconf); if (retval < 0) goto port_init_fail; diff --git a/host/lib/transport/uhd-dpdk/uhd_dpdk_driver.c b/host/lib/transport/uhd-dpdk/uhd_dpdk_driver.c index 61ed836df..7b4cf8df5 100644 --- a/host/lib/transport/uhd-dpdk/uhd_dpdk_driver.c +++ b/host/lib/transport/uhd-dpdk/uhd_dpdk_driver.c @@ -233,13 +233,25 @@ static int _uhd_dpdk_send(struct uhd_dpdk_port *port, } } + status = rte_eth_tx_prepare(port->id, 0, &buf, 1); + if (status != 1) { + status = rte_ring_enqueue(txq->retry_queue, buf); + if (status) { + RTE_LOG(WARNING, USER1, "%s: Could not re-enqueue pkt %d\n", __func__, i); + rte_pktmbuf_free(buf); + } + num_tx = i; + break; + } + status = rte_eth_tx_burst(port->id, 0, &buf, 1); /* Automatically frees mbuf */ if (status != 1) { status = rte_ring_enqueue(txq->retry_queue, buf); - if (status) + if (status) { RTE_LOG(WARNING, USER1, "%s: Could not re-enqueue pkt %d\n", __func__, i); + rte_pktmbuf_free(buf); + } num_tx = i; - rte_pktmbuf_free(buf); break; } } @@ -422,8 +434,10 @@ static inline void _uhd_dpdk_rx_burst(struct uhd_dpdk_port *port) rte_pktmbuf_free(bufs[buf]); break; case ETHER_TYPE_IPv4: - if (ol_flags & PKT_RX_IP_CKSUM_BAD) { + if ((ol_flags & PKT_RX_IP_CKSUM_MASK) == PKT_RX_IP_CKSUM_BAD) { RTE_LOG(WARNING, RING, "Buf %d: Bad IP cksum\n", buf); + } else if ((ol_flags & PKT_RX_IP_CKSUM_MASK) == PKT_RX_IP_CKSUM_NONE) { + RTE_LOG(WARNING, RING, "Buf %d: Missing IP cksum\n", buf); } else { _uhd_dpdk_process_ipv4(port, bufs[buf], (struct ipv4_hdr *) l2_data); } @@ -510,7 +524,7 @@ static inline void _uhd_dpdk_process_tx_buf_wait(struct uhd_dpdk_thread *t, // Attempt to restore bufs only if failed before unsigned int num_bufs = sock->tx_buf_count + rte_ring_count(q->queue) + rte_ring_count(q->retry_queue); - unsigned int max_bufs = rte_ring_get_size(q->freebufs); + unsigned int max_bufs = rte_ring_get_capacity(q->freebufs); if (num_bufs < max_bufs) { _uhd_dpdk_restore_bufs(sock->port, q, max_bufs - num_bufs); } diff --git a/host/lib/transport/uhd-dpdk/uhd_dpdk_udp.c b/host/lib/transport/uhd-dpdk/uhd_dpdk_udp.c index 4fc375b77..9429cd6cb 100644 --- a/host/lib/transport/uhd-dpdk/uhd_dpdk_udp.c +++ b/host/lib/transport/uhd-dpdk/uhd_dpdk_udp.c @@ -457,11 +457,13 @@ static void uhd_dpdk_ipv4_prep(struct uhd_dpdk_port *port, ip_hdr->fragment_offset = rte_cpu_to_be_16(IPV4_HDR_DF_FLAG); ip_hdr->time_to_live = 64; ip_hdr->next_proto_id = proto_id; - ip_hdr->hdr_checksum = 0; /* FIXME: Assuming hardware can offload */ - mbuf->ol_flags |= PKT_TX_IP_CKSUM; + ip_hdr->hdr_checksum = 0; // Require HW offload ip_hdr->src_addr = port->ipv4_addr; ip_hdr->dst_addr = dst_ipv4_addr; + mbuf->ol_flags = PKT_TX_IP_CKSUM | PKT_TX_IPV4; + mbuf->l2_len = sizeof(struct ether_hdr); + mbuf->l3_len = sizeof(struct ipv4_hdr); mbuf->pkt_len = sizeof(struct ether_hdr) + sizeof(struct ipv4_hdr) + payload_len; mbuf->data_len = sizeof(struct ether_hdr) + sizeof(struct ipv4_hdr) + payload_len; } @@ -493,6 +495,7 @@ int uhd_dpdk_udp_prep(struct uhd_dpdk_socket *sock, tx_hdr->dst_port = pdata->dst_port; tx_hdr->dgram_len = rte_cpu_to_be_16(8 + udp_data_len); tx_hdr->dgram_cksum = 0; + mbuf->l4_len = sizeof(struct udp_hdr); return 0; } |