aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Williams <alex.williams@ni.com>2019-01-25 09:50:32 -0800
committerAshish Chaudhari <ashish.chaudhari@ettus.com>2019-01-25 13:30:22 -0800
commita293410435d085cf8e2e736d68197e10709c92f4 (patch)
treeff5e5b9fff1228c409385608f3c394dc33dc9ec4
parent090bd9a625570c0f8a357cfb15074011c1c4b908 (diff)
downloaduhd-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.
-rw-r--r--host/lib/transport/uhd-dpdk/uhd_dpdk.c43
-rw-r--r--host/lib/transport/uhd-dpdk/uhd_dpdk_driver.c22
-rw-r--r--host/lib/transport/uhd-dpdk/uhd_dpdk_udp.c7
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;
}