From e2cde21ceb7497dcc1ef25156afa6472fe64f009 Mon Sep 17 00:00:00 2001 From: Alex Williams Date: Fri, 31 Aug 2018 11:52:04 -0700 Subject: uhd-dpdk: Add ARP responder, set MTU, and clean up API Set MTU of Ethernet ports: Some NICs (like the Mellanox ones) require this to work. Add ARP responder to uhd-dpdk. Clean up pending ARP request list when done: Threads waiting for an ARP request to complete would be woken up when the request completed, but they wouldn't get removed from the list of pending requests. This fixes the issue. --- host/lib/transport/uhd-dpdk/uhd_dpdk.c | 10 ++++- host/lib/transport/uhd-dpdk/uhd_dpdk_ctx.h | 9 +++++ host/lib/transport/uhd-dpdk/uhd_dpdk_driver.c | 53 ++++++++++++++++++++++++++- host/lib/transport/uhd-dpdk/uhd_dpdk_fops.c | 6 ++- 4 files changed, 73 insertions(+), 5 deletions(-) (limited to 'host/lib/transport/uhd-dpdk') diff --git a/host/lib/transport/uhd-dpdk/uhd_dpdk.c b/host/lib/transport/uhd-dpdk/uhd_dpdk.c index 2ee74a201..d6a8a5aa6 100644 --- a/host/lib/transport/uhd-dpdk/uhd_dpdk.c +++ b/host/lib/transport/uhd-dpdk/uhd_dpdk.c @@ -87,6 +87,12 @@ static inline int uhd_dpdk_port_init(struct uhd_dpdk_port *port, return -ENODEV; /* Set up Ethernet device with defaults (1 RX ring, 1 TX ring) */ + retval = rte_eth_dev_set_mtu(port->id, mtu); + if (retval) { + RTE_LOG(WARNING, EAL, "%d: Could not set mtu to %d\n", retval, mtu); + rte_eth_dev_get_mtu(port->id, &mtu); + RTE_LOG(WARNING, EAL, "Current mtu=%d\n", mtu); + } /* FIXME: Check if hw_ip_checksum is possible */ struct rte_eth_conf port_conf = { .rxmode = { @@ -194,7 +200,7 @@ static int uhd_dpdk_thread_init(struct uhd_dpdk_thread *thread, unsigned int id) } -int uhd_dpdk_init(int argc, char **argv, unsigned int num_ports, +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) { @@ -207,7 +213,7 @@ int uhd_dpdk_init(int argc, char **argv, unsigned int num_ports, } /* Grabs arguments intended for DPDK's EAL */ - int ret = rte_eal_init(argc, argv); + int ret = rte_eal_init(argc, (char **) argv); if (ret < 0) rte_exit(EXIT_FAILURE, "Error with EAL initialization\n"); diff --git a/host/lib/transport/uhd-dpdk/uhd_dpdk_ctx.h b/host/lib/transport/uhd-dpdk/uhd_dpdk_ctx.h index 31c9dba0c..c6afab85d 100644 --- a/host/lib/transport/uhd-dpdk/uhd_dpdk_ctx.h +++ b/host/lib/transport/uhd-dpdk/uhd_dpdk_ctx.h @@ -106,6 +106,15 @@ struct uhd_dpdk_ipv4_5tuple { uint16_t dst_port; }; +/** + * Used for blocking calls to RX + */ +struct uhd_dpdk_sock_cond { + struct uhd_dpdk_socket *sock; + pthread_cond_t cond; + pthread_mutex_t mutex; +}; + /************************************************ * TX Queues * diff --git a/host/lib/transport/uhd-dpdk/uhd_dpdk_driver.c b/host/lib/transport/uhd-dpdk/uhd_dpdk_driver.c index 0af9cc4e5..8388359e7 100644 --- a/host/lib/transport/uhd-dpdk/uhd_dpdk_driver.c +++ b/host/lib/transport/uhd-dpdk/uhd_dpdk_driver.c @@ -11,11 +11,53 @@ #include #include +int _uhd_dpdk_arp_reply(struct uhd_dpdk_port *port, struct arp_hdr *arp_req) +{ + struct rte_mbuf *mbuf; + struct ether_hdr *hdr; + struct arp_hdr *arp_frame; + + mbuf = rte_pktmbuf_alloc(port->parent->tx_pktbuf_pool); + if (unlikely(mbuf == NULL)) { + RTE_LOG(WARNING, MEMPOOL, "Could not allocate packet buffer for ARP response\n"); + return -ENOMEM; + } + + hdr = rte_pktmbuf_mtod(mbuf, struct ether_hdr *); + arp_frame = (struct arp_hdr *) &hdr[1]; + + ether_addr_copy(&arp_req->arp_data.arp_sha, &hdr->d_addr); + ether_addr_copy(&port->mac_addr, &hdr->s_addr); + hdr->ether_type = rte_cpu_to_be_16(ETHER_TYPE_ARP); + + arp_frame->arp_hrd = rte_cpu_to_be_16(ARP_HRD_ETHER); + arp_frame->arp_pro = rte_cpu_to_be_16(ETHER_TYPE_IPv4); + arp_frame->arp_hln = 6; + arp_frame->arp_pln = 4; + arp_frame->arp_op = rte_cpu_to_be_16(ARP_OP_REPLY); + ether_addr_copy(&port->mac_addr, &arp_frame->arp_data.arp_sha); + arp_frame->arp_data.arp_sip = port->ipv4_addr; + ether_addr_copy(&hdr->d_addr, &arp_frame->arp_data.arp_tha); + arp_frame->arp_data.arp_tip = arp_req->arp_data.arp_sip; + + mbuf->pkt_len = 42; + mbuf->data_len = 42; + mbuf->ol_flags = PKT_TX_IP_CKSUM; + + if (rte_eth_tx_burst(port->id, 0, &mbuf, 1) != 1) { + RTE_LOG(WARNING, RING, "%s: TX descriptor ring is full\n", __func__); + rte_pktmbuf_free(mbuf); + return -EAGAIN; + } + return 0; +} + int _uhd_dpdk_process_arp(struct uhd_dpdk_port *port, struct arp_hdr *arp_frame) { uint32_t dest_ip = arp_frame->arp_data.arp_sip; struct ether_addr dest_addr = arp_frame->arp_data.arp_sha; + /* Add entry to ARP table */ struct uhd_dpdk_arp_entry *entry = NULL; rte_hash_lookup_data(port->arp_table, &dest_ip, (void **) &entry); if (!entry) { @@ -36,11 +78,21 @@ int _uhd_dpdk_process_arp(struct uhd_dpdk_port *port, struct arp_hdr *arp_frame) LIST_FOREACH(req, &entry->pending_list, entry) { _uhd_dpdk_config_req_compl(req, 0); } + while (entry->pending_list.lh_first != NULL) { + LIST_REMOVE(entry->pending_list.lh_first, entry); + } + } + + /* Respond if this was an ARP request */ + if (arp_frame->arp_op == rte_cpu_to_be_16(ARP_OP_REQUEST) && + arp_frame->arp_data.arp_tip == port->ipv4_addr) { + _uhd_dpdk_arp_reply(port, arp_frame); } return 0; } +/* Send ARP request */ int _uhd_dpdk_arp_request(struct uhd_dpdk_port *port, uint32_t ip) { struct rte_mbuf *mbuf; @@ -82,7 +134,6 @@ int _uhd_dpdk_arp_request(struct uhd_dpdk_port *port, uint32_t ip) return 0; } - int _uhd_dpdk_process_udp(struct uhd_dpdk_port *port, struct rte_mbuf *mbuf, struct udp_hdr *pkt) { int status = 0; diff --git a/host/lib/transport/uhd-dpdk/uhd_dpdk_fops.c b/host/lib/transport/uhd-dpdk/uhd_dpdk_fops.c index 3acc3d709..309e5e643 100644 --- a/host/lib/transport/uhd-dpdk/uhd_dpdk_fops.c +++ b/host/lib/transport/uhd-dpdk/uhd_dpdk_fops.c @@ -215,7 +215,7 @@ int uhd_dpdk_send(struct uhd_dpdk_socket *sock, struct rte_mbuf **bufs, * Add blocking calls with timeout */ int uhd_dpdk_recv(struct uhd_dpdk_socket *sock, struct rte_mbuf **bufs, - unsigned int num_bufs, unsigned int timeout) + unsigned int num_bufs, int timeout) { if (!sock || !bufs || !num_bufs) return -EINVAL; @@ -223,7 +223,9 @@ int uhd_dpdk_recv(struct uhd_dpdk_socket *sock, struct rte_mbuf **bufs, return -EINVAL; unsigned int num_rx = rte_ring_count(sock->rx_ring); num_rx = (num_rx < num_bufs) ? num_rx : num_bufs; - if (num_rx) { + /* if ((timeout > 0) && (num_rx != num_bufs)) { + // Wait for enough bufs + } else*/ if (num_rx) { unsigned int avail = 0; unsigned int status = rte_ring_dequeue_bulk(sock->rx_ring, (void **) bufs, num_rx, &avail); -- cgit v1.2.3