From e07f539ae0aa3ad623c4e8afcaca26906fd1eb17 Mon Sep 17 00:00:00 2001 From: Stefano Brivio Date: Fri, 30 Apr 2021 14:52:18 +0200 Subject: udp, passt: Introduce socket packet buffer, avoid getsockname() for UDP This is in preparation for scatter-gather IO on the UDP receive path: save a getsockname() syscall by setting a flag if we get the numbering of all bound sockets in a strict sequence (expected, in practice) and repurpose the tap buffer to be also a socket receive buffer, passing it down to protocol handlers. Signed-off-by: Stefano Brivio --- util.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) (limited to 'util.c') diff --git a/util.c b/util.c index c48f2f6..9ccd9f6 100644 --- a/util.c +++ b/util.c @@ -189,11 +189,6 @@ int sock_l4(struct ctx *c, int af, uint16_t proto, uint16_t port) return -1; } - CHECK_SET_MIN_MAX_PROTO_FD(proto, IPPROTO_ICMP, icmp, fd); - CHECK_SET_MIN_MAX_PROTO_FD(proto, IPPROTO_ICMPV6, icmp, fd); - CHECK_SET_MIN_MAX_PROTO_FD(proto, IPPROTO_TCP, tcp, fd); - CHECK_SET_MIN_MAX_PROTO_FD(proto, IPPROTO_UDP, udp, fd); - if (proto == IPPROTO_ICMP || proto == IPPROTO_ICMPV6) goto epoll_add; @@ -207,16 +202,29 @@ int sock_l4(struct ctx *c, int af, uint16_t proto, uint16_t port) setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(one)); } + CHECK_SET_MIN_MAX_PROTO_FD(proto, IPPROTO_ICMP, icmp, fd); + CHECK_SET_MIN_MAX_PROTO_FD(proto, IPPROTO_ICMPV6, icmp, fd); + CHECK_SET_MIN_MAX_PROTO_FD(proto, IPPROTO_TCP, tcp, fd); + CHECK_SET_MIN_MAX_PROTO_FD(proto, IPPROTO_UDP, udp, fd); + if (proto == IPPROTO_UDP && PORT_IS_EPHEMERAL(port)) goto epoll_add; if (bind(fd, sa, sl) < 0) { /* We'll fail to bind to low ports if we don't have enough * capabilities, and we'll fail to bind on already bound ports, - * this is fine. + * this is fine. If this isn't the socket with the lowest number + * for a given protocol, leave it open, to avoid unnecessary + * holes in the numbering. */ - close(fd); - return 0; + if ((proto == IPPROTO_TCP && fd == c->tcp.fd_min) || + (proto == IPPROTO_UDP && fd == c->udp.fd_min) || + ((proto == IPPROTO_ICMP || proto == IPPROTO_ICMPV6) && + fd == c->icmp.fd_min)) { + close(fd); + return 0; + } + return fd; } if (proto == IPPROTO_TCP && listen(fd, 128) < 0) { -- cgit v1.2.3