aboutgitcodebugslistschat
diff options
context:
space:
mode:
authorLaurent Vivier <lvivier@redhat.com>2025-09-02 09:52:53 +0200
committerStefano Brivio <sbrivio@redhat.com>2025-09-03 20:43:51 +0200
commitca38be0141d17cbdd419fc49fb028a96612aa3b5 (patch)
tree0b4bdbb933ba7e6d0519a2beadf7e27162cfbf7b
parent3e43e1a36c2cf138552bf6dc4666ff9fe6e00448 (diff)
downloadpasst-ca38be0141d17cbdd419fc49fb028a96612aa3b5.tar
passt-ca38be0141d17cbdd419fc49fb028a96612aa3b5.tar.gz
passt-ca38be0141d17cbdd419fc49fb028a96612aa3b5.tar.bz2
passt-ca38be0141d17cbdd419fc49fb028a96612aa3b5.tar.lz
passt-ca38be0141d17cbdd419fc49fb028a96612aa3b5.tar.xz
passt-ca38be0141d17cbdd419fc49fb028a96612aa3b5.tar.zst
passt-ca38be0141d17cbdd419fc49fb028a96612aa3b5.zip
packet: Add support for multi-vector packetsHEADmaster
The packet pool was previously limited to handling packets contained within a single buffer. This patch extends the packet pool to support iovec array, allowing a single logical packet to be composed of multiple iovec. To accommodate this, the storage format within the pool is modified. For a multi-vector packet, a header entry is now stored first with iov_base = NULL and iov_len holding the number of subsequent vectors. The actual data vectors are then stored in the following pool slots. The packet_add_do() and packet_get_do() functions are updated to manage this new format for storing and retrieving packets. The pool_full() check is also adjusted to ensure there is enough space for all vectors of a new packet before adding it. Signed-off-by: Laurent Vivier <lvivier@redhat.com> Reviewed-by: David Gibson <david@gibson.dropbear.id.au> Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
-rw-r--r--packet.c54
-rw-r--r--packet.h2
-rw-r--r--tap.c4
3 files changed, 39 insertions, 21 deletions
diff --git a/packet.c b/packet.c
index 27693c5..890561b 100644
--- a/packet.c
+++ b/packet.c
@@ -91,14 +91,17 @@ static int packet_check_range(const struct pool *p, const char *ptr, size_t len,
return 0;
}
/**
- * pool_full() - Is a packet pool full?
+ * pool_can_fit() - Can a new packet fit in the pool?
* @p: Pointer to packet pool
+ * @data: check data can fit in the pool
*
- * Return: true if the pool is full, false if more packets can be added
+ * Return: true if @data can be added, false otherwise
*/
-bool pool_full(const struct pool *p)
+bool pool_can_fit(const struct pool *p, struct iov_tail *data)
{
- return p->count >= p->size;
+ iov_tail_prune(data);
+
+ return p->count + data->cnt + (data->cnt > 1) <= p->size;
}
/**
@@ -111,11 +114,9 @@ bool pool_full(const struct pool *p)
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;
+ size_t idx = p->count, i, offset;
- if (pool_full(p)) {
+ if (!pool_can_fit(p, data)) {
debug("add packet index %zu to pool with size %zu, %s:%i",
idx, p->size, func, line);
return;
@@ -124,18 +125,30 @@ void packet_add_do(struct pool *p, struct iov_tail *data,
if (!iov_tail_prune(data))
return;
- ASSERT(data->cnt == 1); /* we don't support iovec */
+ if (data->cnt > 1) {
+ p->pkt[idx].iov_base = NULL;
+ p->pkt[idx].iov_len = data->cnt;
+ idx++;
+ }
- len = data->iov[0].iov_len - data->off;
- start = (char *)data->iov[0].iov_base + data->off;
+ offset = data->off;
+ for (i = 0; i < data->cnt; i++) {
+ const char *start;
+ size_t len;
- if (packet_check_range(p, start, len, func, line))
- return;
+ len = data->iov[i].iov_len - offset;
+ start = (char *)data->iov[i].iov_base + offset;
+ offset = 0;
- p->pkt[idx].iov_base = (void *)start;
- p->pkt[idx].iov_len = len;
+ if (packet_check_range(p, start, len, func, line))
+ return;
- p->count++;
+ p->pkt[idx].iov_base = (void *)start;
+ p->pkt[idx].iov_len = len;
+ idx++;
+ }
+
+ p->count = idx;
}
/**
@@ -165,9 +178,14 @@ bool packet_get_do(const struct pool *p, size_t idx,
return false;
}
- data->cnt = 1;
+ if (p->pkt[idx].iov_base) {
+ data->cnt = 1;
+ data->iov = &p->pkt[idx];
+ } else {
+ data->cnt = p->pkt[idx].iov_len;
+ data->iov = &p->pkt[idx + 1];
+ }
data->off = 0;
- data->iov = &p->pkt[idx];
for (i = 0; i < data->cnt; i++) {
ASSERT_WITH_MSG(!packet_check_range(p, data->iov[i].iov_base,
diff --git a/packet.h b/packet.h
index e51cbd1..ba8d5c2 100644
--- a/packet.h
+++ b/packet.h
@@ -37,7 +37,7 @@ void packet_add_do(struct pool *p, struct iov_tail *data,
const char *func, int line);
bool packet_get_do(const struct pool *p, const size_t idx,
struct iov_tail *data, const char *func, int line);
-bool pool_full(const struct pool *p);
+bool pool_can_fit(const struct pool *p, struct iov_tail *data);
void pool_flush(struct pool *p);
#define packet_add(p, data) \
diff --git a/tap.c b/tap.c
index 5e0173b..7ba6399 100644
--- a/tap.c
+++ b/tap.c
@@ -1103,14 +1103,14 @@ void tap_add_packet(struct ctx *c, struct iov_tail *data,
switch (ntohs(eh->h_proto)) {
case ETH_P_ARP:
case ETH_P_IP:
- if (pool_full(pool_tap4)) {
+ if (!pool_can_fit(pool_tap4, data)) {
tap4_handler(c, pool_tap4, now);
pool_flush(pool_tap4);
}
packet_add(pool_tap4, data);
break;
case ETH_P_IPV6:
- if (pool_full(pool_tap6)) {
+ if (!pool_can_fit(pool_tap6, data)) {
tap6_handler(c, pool_tap6, now);
pool_flush(pool_tap6);
}