Modify the interface of packet_add_do() to take an iov_tail rather than a memory pointer aand length. Internally it only supports iovec array with only one entries, 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 <lvivier(a)redhat.com> Reviewed-by: David Gibson <david(a)gibson.dropbear.id.au> --- iov.h | 1 + packet.c | 15 ++++++++++++--- packet.h | 7 ++++--- tap.c | 32 ++++++++++++++++++-------------- 4 files changed, 35 insertions(+), 20 deletions(-) diff --git a/iov.h b/iov.h index a63d8f21857a..b412a96b1090 100644 --- a/iov.h +++ b/iov.h @@ -17,6 +17,7 @@ #include <unistd.h> #include <string.h> +#include <stdbool.h> #define IOV_OF_LVALUE(lval) \ (struct iovec){ .iov_base = &(lval), .iov_len = sizeof(lval) } diff --git a/packet.c b/packet.c index 72c61580be1e..98ded4e27aae 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 c94780a5ea54..af40b39b5251 100644 --- a/packet.h +++ b/packet.h @@ -7,6 +7,7 @@ #define PACKET_H #include <stdbool.h> +#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 e247a8f5ebc2..52a94f9f8be2 100644 --- a/tap.c +++ b/tap.c @@ -702,6 +702,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; @@ -713,7 +714,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; } @@ -758,7 +760,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); @@ -772,7 +775,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; } @@ -821,7 +825,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++) { @@ -877,6 +882,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; @@ -930,7 +936,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; @@ -949,7 +956,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; @@ -1003,7 +1011,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++) { @@ -1079,9 +1088,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: @@ -1089,16 +1095,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; -- 2.49.0