From d4598e1d18ac2b0ff95e34cf788a0fcab98cc405 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Wed, 1 May 2024 18:31:09 +1000 Subject: [PATCH] udp: Use the same buffer for the L2 header for all frames Currently each tap-bound frame buffer has room for its own ethernet header. However the ethernet header is always the same for such frames, so now that we're indirectly referencing the ethernet header via iov, we can use a single buffer for all of them. Signed-off-by: David Gibson Signed-off-by: Stefano Brivio --- udp.c | 36 +++++++++++++++--------------------- 1 file changed, 15 insertions(+), 21 deletions(-) diff --git a/udp.c b/udp.c index adca819..c940749 100644 --- a/udp.c +++ b/udp.c @@ -186,39 +186,40 @@ static struct udp_payload_t { #endif udp_payload[UDP_MAX_FRAMES]; +/* Ethernet header for IPv4 frames */ +static struct ethhdr udp4_eth_hdr; + /** * udp4_l2_buf_t - Pre-cooked IPv4 packet buffers for tap connections * @s_in: Source socket address, filled in by recvmmsg() * @taph: Tap backend specific header - * @eh: Prefilled ethernet header * @iph: Pre-filled IP header (except for tot_len and saddr) */ static struct udp4_l2_buf_t { struct sockaddr_in s_in; struct tap_hdr taph; - struct ethhdr eh; struct iphdr iph; } __attribute__ ((packed, aligned(__alignof__(unsigned int)))) udp4_l2_buf[UDP_MAX_FRAMES]; +/* Ethernet header for IPv6 frames */ +static struct ethhdr udp6_eth_hdr; + /** * udp6_l2_buf_t - Pre-cooked IPv6 packet buffers for tap connections * @s_in6: Source socket address, filled in by recvmmsg() * @taph: Tap backend specific header - * @eh: Pre-filled ethernet header * @ip6h: Pre-filled IP header (except for payload_len and addresses) */ struct udp6_l2_buf_t { struct sockaddr_in6 s_in6; #ifdef __AVX2__ /* Align ip6h to 32-byte boundary. */ - uint8_t pad[64 - (sizeof(struct sockaddr_in6) + sizeof(struct ethhdr) + - sizeof(struct tap_hdr))]; + uint8_t pad[64 - (sizeof(struct sockaddr_in6) + sizeof(struct tap_hdr))]; #endif struct tap_hdr taph; - struct ethhdr eh; struct ipv6hdr ip6h; #ifdef __AVX2__ } __attribute__ ((packed, aligned(32))) @@ -307,15 +308,8 @@ static void udp_invert_portmap(struct udp_fwd_ports *fwd) */ void udp_update_l2_buf(const unsigned char *eth_d, const unsigned char *eth_s) { - int i; - - for (i = 0; i < UDP_MAX_FRAMES; i++) { - struct udp4_l2_buf_t *b4 = &udp4_l2_buf[i]; - struct udp6_l2_buf_t *b6 = &udp6_l2_buf[i]; - - eth_update_mac(&b4->eh, eth_d, eth_s); - eth_update_mac(&b6->eh, eth_d, eth_s); - } + eth_update_mac(&udp4_eth_hdr, eth_d, eth_s); + eth_update_mac(&udp6_eth_hdr, eth_d, eth_s); } /** @@ -329,6 +323,8 @@ static void udp_iov_init_one(const struct ctx *c, size_t i) struct iovec *siov = &udp_l2_iov_sock[i]; *siov = IOV_OF_LVALUE(payload->data); + udp4_eth_hdr.h_proto = htons_constant(ETH_P_IP); + udp6_eth_hdr.h_proto = htons_constant(ETH_P_IPV6); if (c->ifi4) { struct msghdr *mh = &udp4_l2_mh_sock[i].msg_hdr; @@ -336,7 +332,6 @@ static void udp_iov_init_one(const struct ctx *c, size_t i) struct iovec *tiov = udp4_l2_iov_tap[i]; *buf = (struct udp4_l2_buf_t) { - .eh = ETH_HDR_INIT(ETH_P_IP), .iph = L2_BUF_IP4_INIT(IPPROTO_UDP) }; @@ -346,7 +341,7 @@ static void udp_iov_init_one(const struct ctx *c, size_t i) mh->msg_iovlen = 1; tiov[UDP_IOV_TAP] = tap_hdr_iov(c, &buf->taph); - tiov[UDP_IOV_ETH] = IOV_OF_LVALUE(buf->eh); + tiov[UDP_IOV_ETH] = IOV_OF_LVALUE(udp4_eth_hdr); tiov[UDP_IOV_IP] = IOV_OF_LVALUE(buf->iph); tiov[UDP_IOV_PAYLOAD].iov_base = payload; } @@ -357,7 +352,6 @@ static void udp_iov_init_one(const struct ctx *c, size_t i) struct iovec *tiov = udp6_l2_iov_tap[i]; *buf = (struct udp6_l2_buf_t) { - .eh = ETH_HDR_INIT(ETH_P_IPV6), .ip6h = L2_BUF_IP6_INIT(IPPROTO_UDP) }; @@ -367,7 +361,7 @@ static void udp_iov_init_one(const struct ctx *c, size_t i) mh->msg_iovlen = 1; tiov[UDP_IOV_TAP] = tap_hdr_iov(c, &buf->taph); - tiov[UDP_IOV_ETH] = IOV_OF_LVALUE(buf->eh); + tiov[UDP_IOV_ETH] = IOV_OF_LVALUE(udp6_eth_hdr); tiov[UDP_IOV_IP] = IOV_OF_LVALUE(buf->ip6h); tiov[UDP_IOV_PAYLOAD].iov_base = payload; } @@ -631,7 +625,7 @@ static size_t udp_update_hdr4(const struct ctx *c, struct udp4_l2_buf_t *bh, bp->uh.len = htons(l4len); csum_udp4(&bp->uh, src, dst, bp->data, dlen); - tap_hdr_update(&bh->taph, l3len + sizeof(bh->eh)); + tap_hdr_update(&bh->taph, l3len + sizeof(udp4_eth_hdr)); return l4len; } @@ -702,7 +696,7 @@ static size_t udp_update_hdr6(const struct ctx *c, struct udp6_l2_buf_t *bh, bp->uh.len = bh->ip6h.payload_len; csum_udp6(&bp->uh, src, dst, bp->data, dlen); - tap_hdr_update(&bh->taph, l4len + sizeof(bh->ip6h) + sizeof(bh->eh)); + tap_hdr_update(&bh->taph, l4len + sizeof(bh->ip6h) + sizeof(udp6_eth_hdr)); return l4len; }