From 2ea8accb9c0b8c489eefb779a2d3c2def11b1da2 Mon Sep 17 00:00:00 2001 From: Brian Armstrong Date: Mon, 30 Sep 2019 16:35:33 -0700 Subject: [PATCH 1/7] max bound on write queue length --- include/uv.h | 1 + src/unix/netmap-udp.c | 17 +++++++++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/include/uv.h b/include/uv.h index 7a83bd34f4b..261e8fd9653 100644 --- a/include/uv.h +++ b/include/uv.h @@ -1691,6 +1691,7 @@ struct uv_netmap_s { unsigned char socket_tos[NM_NUM_UDP_SOCKETS]; void* write_queue[2]; void* write_completed_queue[2]; + unsigned int write_queue_length; unsigned char src_mac[6]; unsigned char dst_mac[6]; unsigned char src_ip[4]; diff --git a/src/unix/netmap-udp.c b/src/unix/netmap-udp.c index a7eb5ffc95b..7347e31d346 100644 --- a/src/unix/netmap-udp.c +++ b/src/unix/netmap-udp.c @@ -39,6 +39,7 @@ #include + static uint16_t ip_checksum(struct ip* ip); static void uv__udp_netmap_recv_packet(uv_loop_t* loop, struct netmap_slot* slot, uint8_t* p); static size_t uv__udp_netmap_generate_udp(uv_loop_t* loop, unsigned int src_port, struct msghdr* h, uint8_t* pkt); @@ -49,6 +50,7 @@ static void uv__udp_netmap_io(uv_loop_t* loop, uv__io_t* w, unsigned int revents static const size_t ETH_LEN = sizeof(struct ether_header); static const size_t ETH_IP_LEN = ETH_LEN + sizeof(struct ip); static const size_t ETH_IP_UDP_LEN = ETH_IP_LEN + sizeof(struct udphdr); +static const size_t NETMAP_WRITE_QUEUE_MAX_LENGTH = (1 << 16); static uint16_t ip_checksum(struct ip* ip) { @@ -354,7 +356,11 @@ static void uv__udp_netmap_io(uv_loop_t* loop, uv__io_t* w, unsigned int revents q = QUEUE_HEAD(&loop->netmap->write_queue); req = QUEUE_DATA(q, uv_udp_send_t, queue); - uv__udp_netmap_send_udp(loop, req, ring); + if (uv__udp_netmap_send_udp(loop, req, ring) == -1) { + break; + } + + loop->netmap->write_queue_length--; uv__io_feed(loop, &loop->netmap->io_watcher); pkt_num++; @@ -386,6 +392,7 @@ int uv_udp_netmap_init(uv_loop_t* loop, const char* fname) { uv__io_init(&loop->netmap->io_watcher, uv__udp_netmap_io, loop->netmap->intf->fd); QUEUE_INIT(&loop->netmap->write_queue); QUEUE_INIT(&loop->netmap->write_completed_queue); + loop->netmap->write_queue_length = 0; return 0; } @@ -454,6 +461,7 @@ void uv__udp_netmap_finish_close_handle(uv_udp_t* handle) { if (req->handle == handle) { q = QUEUE_PREV(q); QUEUE_REMOVE(&req->queue); + handle->loop->netmap->write_queue_length--; req->status = UV_ECANCELED; QUEUE_INSERT_TAIL(&handle->loop->netmap->write_completed_queue, &req->queue); removed = 1; @@ -588,7 +596,12 @@ int uv__udp_netmap_send(uv_udp_send_t* req, // no space left, stash it locally if (!enqueued) { - QUEUE_INSERT_TAIL(&handle->loop->netmap->write_queue, &req->queue); + if (handle->loop->netmap->write_queue_length < NETMAP_WRITE_QUEUE_MAX_LENGTH) { + QUEUE_INSERT_TAIL(&handle->loop->netmap->write_queue, &req->queue); + handle->loop->netmap->write_queue_length++; + } else { + return -1; + } } // even if we put the packet in a ring, we still need to do a POLLOUT From 5a9d7e30bb5b71970539af2426e2ef0455a9aec6 Mon Sep 17 00:00:00 2001 From: Brian Armstrong Date: Mon, 30 Sep 2019 18:30:54 -0700 Subject: [PATCH 2/7] 2^17 --- src/unix/netmap-udp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/unix/netmap-udp.c b/src/unix/netmap-udp.c index 7347e31d346..c769ac28f88 100644 --- a/src/unix/netmap-udp.c +++ b/src/unix/netmap-udp.c @@ -50,7 +50,7 @@ static void uv__udp_netmap_io(uv_loop_t* loop, uv__io_t* w, unsigned int revents static const size_t ETH_LEN = sizeof(struct ether_header); static const size_t ETH_IP_LEN = ETH_LEN + sizeof(struct ip); static const size_t ETH_IP_UDP_LEN = ETH_IP_LEN + sizeof(struct udphdr); -static const size_t NETMAP_WRITE_QUEUE_MAX_LENGTH = (1 << 16); +static const size_t NETMAP_WRITE_QUEUE_MAX_LENGTH = (1 << 17); static uint16_t ip_checksum(struct ip* ip) { From 22e45a03d64b4b5a3fef6c1da9acbc796e5a37e2 Mon Sep 17 00:00:00 2001 From: Brian Armstrong Date: Mon, 14 Oct 2019 16:50:04 -0700 Subject: [PATCH 3/7] check for recv fail --- src/unix/netmap-udp.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/src/unix/netmap-udp.c b/src/unix/netmap-udp.c index c769ac28f88..1b7b4293af9 100644 --- a/src/unix/netmap-udp.c +++ b/src/unix/netmap-udp.c @@ -41,7 +41,7 @@ static uint16_t ip_checksum(struct ip* ip); -static void uv__udp_netmap_recv_packet(uv_loop_t* loop, struct netmap_slot* slot, uint8_t* p); +static int uv__udp_netmap_recv_packet(uv_loop_t* loop, struct netmap_slot* slot, uint8_t* p); static size_t uv__udp_netmap_generate_udp(uv_loop_t* loop, unsigned int src_port, struct msghdr* h, uint8_t* pkt); static int uv__udp_netmap_send_udp(uv_loop_t* loop, uv_udp_send_t* req, struct netmap_ring* ring); static void uv__udp_netmap_run_completed(uv_loop_t* loop); @@ -106,7 +106,7 @@ static uint16_t udp_checksum(struct ip* ip, struct udphdr* udp, uint8_t* payload } -static void uv__udp_netmap_recv_packet(uv_loop_t* loop, struct netmap_slot* slot, uint8_t* p) { +static int uv__udp_netmap_recv_packet(uv_loop_t* loop, struct netmap_slot* slot, uint8_t* p) { struct ether_header* eth; struct ip* ip; struct udphdr* udp; @@ -117,23 +117,23 @@ static void uv__udp_netmap_recv_packet(uv_loop_t* loop, struct netmap_slot* slot uint16_t udp_chksum; if (slot->len < ETH_IP_UDP_LEN) { - return; + return 0; } eth = (struct ether_header*)p; if (eth->ether_type != htons(ETHERTYPE_IP)) { - return; + return 0; } ip = (struct ip*)(p + ETH_LEN); if (ip->ip_v != IPVERSION) { - return; + return 0; } if (ip->ip_p != IPPROTO_UDP) { - return; + return 0; } udp = (struct udphdr*)(p + ETH_IP_LEN); @@ -148,7 +148,7 @@ static void uv__udp_netmap_recv_packet(uv_loop_t* loop, struct netmap_slot* slot payload = p + ETH_IP_UDP_LEN; if (udp->check != udp_checksum(ip, udp, payload, payload_len)) { - return; + return 0; } if (loop->netmap->sockets[dest_port]) { @@ -159,7 +159,7 @@ static void uv__udp_netmap_recv_packet(uv_loop_t* loop, struct netmap_slot* slot if (buf.base == NULL || buf.len == 0) { socket_handle->recv_cb(socket_handle, UV_ENOBUFS, &buf, NULL, 0); - return; + return -1; } assert(buf.base != NULL); @@ -172,6 +172,8 @@ static void uv__udp_netmap_recv_packet(uv_loop_t* loop, struct netmap_slot* slot socket_handle->recv_cb(socket_handle, payload_len, &buf, (const struct sockaddr*)&addr, 0); } + + return 0; } static size_t uv__udp_netmap_generate_udp(uv_loop_t* loop, unsigned int src_port, struct msghdr* h, uint8_t* pkt) { @@ -326,7 +328,10 @@ static void uv__udp_netmap_io(uv_loop_t* loop, uv__io_t* w, unsigned int revents slot = &ring->slot[ring->cur]; p = (uint8_t*)NETMAP_BUF(ring, slot->buf_idx); - uv__udp_netmap_recv_packet(loop, slot, p); + if (uv__udp_netmap_recv_packet(loop, slot, p) < 0) { + // ran out of space, stop receiving + break; + } ring->head = ring->cur = nm_ring_next(ring, ring->cur); } From 3b78a6f615b51c2231bb83f35ef70c2fccacb3e8 Mon Sep 17 00:00:00 2001 From: Brian Armstrong Date: Tue, 15 Oct 2019 13:04:47 -0700 Subject: [PATCH 4/7] 2^20 --- src/unix/netmap-udp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/unix/netmap-udp.c b/src/unix/netmap-udp.c index 1b7b4293af9..93bf31cdf17 100644 --- a/src/unix/netmap-udp.c +++ b/src/unix/netmap-udp.c @@ -50,7 +50,7 @@ static void uv__udp_netmap_io(uv_loop_t* loop, uv__io_t* w, unsigned int revents static const size_t ETH_LEN = sizeof(struct ether_header); static const size_t ETH_IP_LEN = ETH_LEN + sizeof(struct ip); static const size_t ETH_IP_UDP_LEN = ETH_IP_LEN + sizeof(struct udphdr); -static const size_t NETMAP_WRITE_QUEUE_MAX_LENGTH = (1 << 17); +static const size_t NETMAP_WRITE_QUEUE_MAX_LENGTH = (1 << 20); static uint16_t ip_checksum(struct ip* ip) { From d5a3bd3fa78a9fd7c95b53bf848b8e6774390485 Mon Sep 17 00:00:00 2001 From: Brian Armstrong Date: Fri, 1 Nov 2019 18:12:01 -0700 Subject: [PATCH 5/7] get_write_queue_length --- include/uv.h | 1 + src/unix/netmap-udp.c | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/include/uv.h b/include/uv.h index 261e8fd9653..05691434e0e 100644 --- a/include/uv.h +++ b/include/uv.h @@ -690,6 +690,7 @@ UV_EXTERN size_t uv_udp_get_send_queue_count(const uv_udp_t* handle); UV_EXTERN int uv_udp_netmap_init(uv_loop_t* loop, const char* fname); UV_EXTERN void uv_udp_netmap_set_network(uv_loop_t* loop, unsigned char* src_mac, unsigned char* dst_mac, unsigned char* src_ip); UV_EXTERN int uv_udp_netmap_close(uv_loop_t* loop); +UV_EXTERNA unsigned int uv_udp_netmap_get_write_queue_length(uv_loop_t* loop); #endif /* diff --git a/src/unix/netmap-udp.c b/src/unix/netmap-udp.c index 93bf31cdf17..00ccda2fdc6 100644 --- a/src/unix/netmap-udp.c +++ b/src/unix/netmap-udp.c @@ -375,6 +375,13 @@ static void uv__udp_netmap_io(uv_loop_t* loop, uv__io_t* w, unsigned int revents } } +unsigned int uv_udp_netmap_get_write_queue_length(uv_loop_t* loop) { + if (loop->netmap == NULL) { + return 0; + } + return loop->netmap->write_queue_length; +} + int uv_udp_netmap_init(uv_loop_t* loop, const char* fname) { nm_desc_t* netmap_desc; @@ -605,6 +612,7 @@ int uv__udp_netmap_send(uv_udp_send_t* req, QUEUE_INSERT_TAIL(&handle->loop->netmap->write_queue, &req->queue); handle->loop->netmap->write_queue_length++; } else { + req->send_cb(req, 0) return -1; } } From d4b3d56528ba7d137ad9883c5dfdf2ce6b402d81 Mon Sep 17 00:00:00 2001 From: Brian Armstrong Date: Fri, 1 Nov 2019 18:14:57 -0700 Subject: [PATCH 6/7] queue capacity --- include/uv.h | 3 ++- src/unix/netmap-udp.c | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/include/uv.h b/include/uv.h index 05691434e0e..8abe9f82216 100644 --- a/include/uv.h +++ b/include/uv.h @@ -690,7 +690,8 @@ UV_EXTERN size_t uv_udp_get_send_queue_count(const uv_udp_t* handle); UV_EXTERN int uv_udp_netmap_init(uv_loop_t* loop, const char* fname); UV_EXTERN void uv_udp_netmap_set_network(uv_loop_t* loop, unsigned char* src_mac, unsigned char* dst_mac, unsigned char* src_ip); UV_EXTERN int uv_udp_netmap_close(uv_loop_t* loop); -UV_EXTERNA unsigned int uv_udp_netmap_get_write_queue_length(uv_loop_t* loop); +UV_EXTERN unsigned int uv_udp_netmap_get_write_queue_length(uv_loop_t* loop); +UV_EXTERN unsigned int uv_udp_netmap_get_send_queue_capacity(uv_loop_t* loop); #endif /* diff --git a/src/unix/netmap-udp.c b/src/unix/netmap-udp.c index 00ccda2fdc6..aa391f9259a 100644 --- a/src/unix/netmap-udp.c +++ b/src/unix/netmap-udp.c @@ -382,6 +382,25 @@ unsigned int uv_udp_netmap_get_write_queue_length(uv_loop_t* loop) { return loop->netmap->write_queue_length; } +unsigned int uv_udp_netmap_get_send_queue_capacity(uv_loop_t* loop) { + int i; + unsigned int cap; + struct netmap_ring* ring; + + if (loop->netmap == NULL) { + return 0; + } + + cap = 0; + + for (i = loop->netmap->intf->first_rx_ring; i <= loop->netmap->intf->last_rx_ring; i++) { + ring = NETMAP_TXRING(loop->netmap->intf->nifp, i); + cap += nm_ring_space(ring); + } + + return cap; +} + int uv_udp_netmap_init(uv_loop_t* loop, const char* fname) { nm_desc_t* netmap_desc; From 36920b84b43ce8ca351ea869c196940c32bc6b25 Mon Sep 17 00:00:00 2001 From: Brian Armstrong Date: Wed, 6 Nov 2019 18:27:08 -0800 Subject: [PATCH 7/7] ; --- src/unix/netmap-udp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/unix/netmap-udp.c b/src/unix/netmap-udp.c index aa391f9259a..a38707581cb 100644 --- a/src/unix/netmap-udp.c +++ b/src/unix/netmap-udp.c @@ -631,7 +631,7 @@ int uv__udp_netmap_send(uv_udp_send_t* req, QUEUE_INSERT_TAIL(&handle->loop->netmap->write_queue, &req->queue); handle->loop->netmap->write_queue_length++; } else { - req->send_cb(req, 0) + req->send_cb(req, 0); return -1; } }