From de469a3e85b06377762a52c82269ff3eaf2ae3ea Mon Sep 17 00:00:00 2001 From: Laurent Vivier Date: Tue, 2 Sep 2025 09:52:28 +0200 Subject: packet: Use iov_tail with packet_add() Modify the interface of packet_add_do() to take an iov_tail rather than a memory pointer and length. Internally it only supports iovec array with only one entry, after being pruned. We can accept iovec array with several entries if the offset allows the function to reduce the number of entries to 1. tap4_handler() is updated to create an iov_tail value using IOV_TAIL_FROM_BUF() from the buffer and the length. Signed-off-by: Laurent Vivier Reviewed-by: David Gibson Signed-off-by: Stefano Brivio --- packet.c | 15 ++++++++++++--- packet.h | 7 ++++--- tap.c | 32 ++++++++++++++++++-------------- 3 files changed, 34 insertions(+), 20 deletions(-) diff --git a/packet.c b/packet.c index 72c6158..98ded4e 100644 --- a/packet.c +++ b/packet.c @@ -87,15 +87,16 @@ bool pool_full(const struct pool *p) /** * packet_add_do() - Add data as packet descriptor to given pool * @p: Existing pool - * @len: Length of new descriptor - * @start: Start of data + * @data: Data to add * @func: For tracing: name of calling function * @line: For tracing: caller line of function call */ -void packet_add_do(struct pool *p, size_t len, const char *start, +void packet_add_do(struct pool *p, struct iov_tail *data, const char *func, int line) { size_t idx = p->count; + const char *start; + size_t len; if (pool_full(p)) { debug("add packet index %zu to pool with size %zu, %s:%i", @@ -103,6 +104,14 @@ void packet_add_do(struct pool *p, size_t len, const char *start, return; } + if (!iov_tail_prune(data)) + return; + + ASSERT(data->cnt == 1); /* we don't support iovec */ + + len = data->iov[0].iov_len - data->off; + start = (char *)data->iov[0].iov_base + data->off; + if (packet_check_range(p, start, len, func, line)) return; diff --git a/packet.h b/packet.h index c94780a..af40b39 100644 --- a/packet.h +++ b/packet.h @@ -7,6 +7,7 @@ #define PACKET_H #include +#include "iov.h" /* Maximum size of a single packet stored in pool, including headers */ #define PACKET_MAX_LEN ((size_t)UINT16_MAX) @@ -30,7 +31,7 @@ struct pool { }; int vu_packet_check_range(void *buf, const char *ptr, size_t len); -void packet_add_do(struct pool *p, size_t len, const char *start, +void packet_add_do(struct pool *p, struct iov_tail *data, const char *func, int line); void *packet_get_try_do(const struct pool *p, const size_t idx, size_t offset, size_t len, size_t *left, @@ -41,8 +42,8 @@ void *packet_get_do(const struct pool *p, const size_t idx, bool pool_full(const struct pool *p); void pool_flush(struct pool *p); -#define packet_add(p, len, start) \ - packet_add_do(p, len, start, __func__, __LINE__) +#define packet_add(p, data) \ + packet_add_do(p, data, __func__, __LINE__) #define packet_get_try(p, idx, offset, len, left) \ packet_get_try_do(p, idx, offset, len, left, __func__, __LINE__) diff --git a/tap.c b/tap.c index b1de0c5..7cb7494 100644 --- a/tap.c +++ b/tap.c @@ -709,6 +709,7 @@ resume: size_t l2len, l3len, hlen, l4len; const struct ethhdr *eh; const struct udphdr *uh; + struct iov_tail data; struct iphdr *iph; const char *l4h; @@ -720,7 +721,8 @@ resume: if (ntohs(eh->h_proto) == ETH_P_ARP) { PACKET_POOL_P(pkt, 1, in->buf, in->buf_size); - packet_add(pkt, l2len, (char *)eh); + data = IOV_TAIL_FROM_BUF((void *)eh, l2len, 0); + packet_add(pkt, &data); arp(c, pkt); continue; } @@ -765,7 +767,8 @@ resume: tap_packet_debug(iph, NULL, NULL, 0, NULL, 1); - packet_add(pkt, l4len, l4h); + data = IOV_TAIL_FROM_BUF((void *)l4h, l4len, 0); + packet_add(pkt, &data); icmp_tap_handler(c, PIF_TAP, AF_INET, &iph->saddr, &iph->daddr, pkt, now); @@ -779,7 +782,8 @@ resume: if (iph->protocol == IPPROTO_UDP) { PACKET_POOL_P(pkt, 1, in->buf, in->buf_size); - packet_add(pkt, l2len, (char *)eh); + data = IOV_TAIL_FROM_BUF((void *)eh, l2len, 0); + packet_add(pkt, &data); if (dhcp(c, pkt)) continue; } @@ -830,7 +834,8 @@ resume: #undef L4_SET append: - packet_add((struct pool *)&seq->p, l4len, l4h); + data = IOV_TAIL_FROM_BUF((void *)l4h, l4len, 0); + packet_add((struct pool *)&seq->p, &data); } for (j = 0, seq = tap4_l4; j < seq_count; j++, seq++) { @@ -886,6 +891,7 @@ resume: struct in6_addr *saddr, *daddr; const struct ethhdr *eh; const struct udphdr *uh; + struct iov_tail data; struct ipv6hdr *ip6h; uint8_t proto; char *l4h; @@ -939,7 +945,8 @@ resume: if (l4len < sizeof(struct icmp6hdr)) continue; - packet_add(pkt, l4len, l4h); + data = IOV_TAIL_FROM_BUF(l4h, l4len, 0); + packet_add(pkt, &data); if (ndp(c, (struct icmp6hdr *)l4h, saddr, pkt)) continue; @@ -958,7 +965,8 @@ resume: if (proto == IPPROTO_UDP) { PACKET_POOL_P(pkt, 1, in->buf, in->buf_size); - packet_add(pkt, l4len, l4h); + data = IOV_TAIL_FROM_BUF(l4h, l4len, 0); + packet_add(pkt, &data); if (dhcpv6(c, pkt, saddr, daddr)) continue; @@ -1014,7 +1022,8 @@ resume: #undef L4_SET append: - packet_add((struct pool *)&seq->p, l4len, l4h); + data = IOV_TAIL_FROM_BUF(l4h, l4len, 0); + packet_add((struct pool *)&seq->p, &data); } for (j = 0, seq = tap6_l4; j < seq_count; j++, seq++) { @@ -1090,9 +1099,6 @@ void tap_add_packet(struct ctx *c, struct iov_tail *data, proto_update_l2_buf(c->guest_mac, NULL); } - iov_tail_prune(data); - ASSERT(data->cnt == 1); /* packet_add() doesn't support iovec */ - switch (ntohs(eh->h_proto)) { case ETH_P_ARP: case ETH_P_IP: @@ -1100,16 +1106,14 @@ void tap_add_packet(struct ctx *c, struct iov_tail *data, tap4_handler(c, pool_tap4, now); pool_flush(pool_tap4); } - packet_add(pool_tap4, data->iov[0].iov_len - data->off, - (char *)data->iov[0].iov_base + data->off); + packet_add(pool_tap4, data); break; case ETH_P_IPV6: if (pool_full(pool_tap6)) { tap6_handler(c, pool_tap6, now); pool_flush(pool_tap6); } - packet_add(pool_tap6, data->iov[0].iov_len - data->off, - (char *)data->iov[0].iov_base + data->off); + packet_add(pool_tap6, data); break; default: break; -- cgit v1.2.3