From: Laurent Vivier <lvivier@redhat.com>
To: passt-dev@passt.top
Cc: Laurent Vivier <lvivier@redhat.com>,
David Gibson <david@gibson.dropbear.id.au>
Subject: [PATCH v2 04/20] tap: Use iov_tail with tap_add_packet()
Date: Fri, 11 Apr 2025 15:10:14 +0200 [thread overview]
Message-ID: <20250411131031.1398006-5-lvivier@redhat.com> (raw)
In-Reply-To: <20250411131031.1398006-1-lvivier@redhat.com>
Use IOV_PEEK_HEADER() to get the ethernet header from the iovec.
Move the workaround about multiple iovec array from vu_handle_tx() to
tap_add_packet(). Removing the offset out of the iovec array should
reduce the iovec count to 1.
Signed-off-by: Laurent Vivier <lvivier@redhat.com>
Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
---
iov.c | 1 -
pcap.c | 1 +
tap.c | 30 +++++++++++++++++++++---------
tap.h | 3 +--
vu_common.c | 26 +++++---------------------
5 files changed, 28 insertions(+), 33 deletions(-)
diff --git a/iov.c b/iov.c
index ae8eca26f295..98d5fecbdc8f 100644
--- a/iov.c
+++ b/iov.c
@@ -252,7 +252,6 @@ size_t iov_tail_size(struct iov_tail *tail)
*
* Returns: true if the tail still contains any bytes, otherwise false
*/
-/* cppcheck-suppress unusedFunction */
bool iov_tail_drop(struct iov_tail *tail, size_t len)
{
tail->off = tail->off + len;
diff --git a/pcap.c b/pcap.c
index e95aa6fe29a6..404043a27e22 100644
--- a/pcap.c
+++ b/pcap.c
@@ -76,6 +76,7 @@ static void pcap_frame(const struct iovec *iov, size_t iovcnt,
* @pkt: Pointer to data buffer, including L2 headers
* @l2len: L2 frame length
*/
+/* cppcheck-suppress unusedFunction */
void pcap(const char *pkt, size_t l2len)
{
struct iovec iov = { (char *)pkt, l2len };
diff --git a/tap.c b/tap.c
index 3a6fcbe85a42..e247a8f5ebc2 100644
--- a/tap.c
+++ b/tap.c
@@ -1059,24 +1059,29 @@ void tap_handler(struct ctx *c, const struct timespec *now)
/**
* tap_add_packet() - Queue/capture packet, update notion of guest MAC address
* @c: Execution context
- * @l2len: Total L2 packet length
- * @p: Packet buffer
+ * @data: Packet to add to the pool
* @now: Current timestamp
*/
-void tap_add_packet(struct ctx *c, ssize_t l2len, char *p,
+void tap_add_packet(struct ctx *c, struct iov_tail *data,
const struct timespec *now)
{
const struct ethhdr *eh;
+ struct ethhdr ehc;
- pcap(p, l2len);
+ pcap_iov(data->iov, data->cnt, data->off);
- eh = (struct ethhdr *)p;
+ eh = IOV_PEEK_HEADER(data, ehc);
+ if (!eh)
+ return;
if (memcmp(c->guest_mac, eh->h_source, ETH_ALEN)) {
memcpy(c->guest_mac, eh->h_source, ETH_ALEN);
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:
@@ -1084,14 +1089,16 @@ void tap_add_packet(struct ctx *c, ssize_t l2len, char *p,
tap4_handler(c, pool_tap4, now);
pool_flush(pool_tap4);
}
- packet_add(pool_tap4, l2len, p);
+ packet_add(pool_tap4, data->iov[0].iov_len - data->off,
+ (char *)data->iov[0].iov_base + data->off);
break;
case ETH_P_IPV6:
if (pool_full(pool_tap6)) {
tap6_handler(c, pool_tap6, now);
pool_flush(pool_tap6);
}
- packet_add(pool_tap6, l2len, p);
+ packet_add(pool_tap6, data->iov[0].iov_len - data->off,
+ (char *)data->iov[0].iov_base + data->off);
break;
default:
break;
@@ -1157,6 +1164,7 @@ static void tap_passt_input(struct ctx *c, const struct timespec *now)
while (n >= (ssize_t)sizeof(uint32_t)) {
uint32_t l2len = ntohl_unaligned(p);
+ struct iov_tail data;
if (l2len < sizeof(struct ethhdr) || l2len > L2_MAX_LEN_PASST) {
err("Bad frame size from guest, resetting connection");
@@ -1171,7 +1179,8 @@ static void tap_passt_input(struct ctx *c, const struct timespec *now)
p += sizeof(uint32_t);
n -= sizeof(uint32_t);
- tap_add_packet(c, l2len, p, now);
+ data = IOV_TAIL_FROM_BUF(p, l2len, 0);
+ tap_add_packet(c, &data, now);
p += l2len;
n -= l2len;
@@ -1215,6 +1224,8 @@ static void tap_pasta_input(struct ctx *c, const struct timespec *now)
for (n = 0;
n <= (ssize_t)(sizeof(pkt_buf) - L2_MAX_LEN_PASTA);
n += len) {
+ struct iov_tail data;
+
len = read(c->fd_tap, pkt_buf + n, L2_MAX_LEN_PASTA);
if (len == 0) {
@@ -1236,7 +1247,8 @@ static void tap_pasta_input(struct ctx *c, const struct timespec *now)
len > (ssize_t)L2_MAX_LEN_PASTA)
continue;
- tap_add_packet(c, len, pkt_buf + n, now);
+ data = IOV_TAIL_FROM_BUF(pkt_buf + n, len, 0);
+ tap_add_packet(c, &data, now);
}
tap_handler(c, now);
diff --git a/tap.h b/tap.h
index 6fe3d15d1337..954ad440a287 100644
--- a/tap.h
+++ b/tap.h
@@ -119,7 +119,6 @@ void tap_sock_update_pool(void *base, size_t size);
void tap_backend_init(struct ctx *c);
void tap_flush_pools(void);
void tap_handler(struct ctx *c, const struct timespec *now);
-void tap_add_packet(struct ctx *c, ssize_t l2len, char *p,
+void tap_add_packet(struct ctx *c, struct iov_tail *data,
const struct timespec *now);
-
#endif /* TAP_H */
diff --git a/vu_common.c b/vu_common.c
index 5e6fd4a8261f..b77b21420c57 100644
--- a/vu_common.c
+++ b/vu_common.c
@@ -163,7 +163,6 @@ static void vu_handle_tx(struct vu_dev *vdev, int index,
struct vu_virtq_element elem[VIRTQUEUE_MAX_SIZE];
struct iovec out_sg[VIRTQUEUE_MAX_SIZE];
struct vu_virtq *vq = &vdev->vq[index];
- int hdrlen = sizeof(struct virtio_net_hdr_mrg_rxbuf);
int out_sg_count;
int count;
@@ -176,6 +175,7 @@ static void vu_handle_tx(struct vu_dev *vdev, int index,
while (count < VIRTQUEUE_MAX_SIZE &&
out_sg_count + VU_MAX_TX_BUFFER_NB <= VIRTQUEUE_MAX_SIZE) {
int ret;
+ struct iov_tail data;
elem[count].out_num = VU_MAX_TX_BUFFER_NB;
elem[count].out_sg = &out_sg[out_sg_count];
@@ -191,26 +191,10 @@ static void vu_handle_tx(struct vu_dev *vdev, int index,
warn("virtio-net transmit queue contains no out buffers");
break;
}
- if (elem[count].out_num == 1) {
- tap_add_packet(vdev->context,
- elem[count].out_sg[0].iov_len - hdrlen,
- (char *)elem[count].out_sg[0].iov_base +
- hdrlen, now);
- } else {
- /* vnet header can be in a separate iovec */
- if (elem[count].out_num != 2) {
- debug("virtio-net transmit queue contains more than one buffer ([%d]: %u)",
- count, elem[count].out_num);
- } else if (elem[count].out_sg[0].iov_len != (size_t)hdrlen) {
- debug("virtio-net transmit queue entry not aligned on hdrlen ([%d]: %d != %zu)",
- count, hdrlen, elem[count].out_sg[0].iov_len);
- } else {
- tap_add_packet(vdev->context,
- elem[count].out_sg[1].iov_len,
- (char *)elem[count].out_sg[1].iov_base,
- now);
- }
- }
+
+ data = IOV_TAIL(elem[count].out_sg, elem[count].out_num, 0);
+ if (IOV_DROP_HEADER(&data, struct virtio_net_hdr_mrg_rxbuf))
+ tap_add_packet(vdev->context, &data, now);
count++;
}
--
@@ -163,7 +163,6 @@ static void vu_handle_tx(struct vu_dev *vdev, int index,
struct vu_virtq_element elem[VIRTQUEUE_MAX_SIZE];
struct iovec out_sg[VIRTQUEUE_MAX_SIZE];
struct vu_virtq *vq = &vdev->vq[index];
- int hdrlen = sizeof(struct virtio_net_hdr_mrg_rxbuf);
int out_sg_count;
int count;
@@ -176,6 +175,7 @@ static void vu_handle_tx(struct vu_dev *vdev, int index,
while (count < VIRTQUEUE_MAX_SIZE &&
out_sg_count + VU_MAX_TX_BUFFER_NB <= VIRTQUEUE_MAX_SIZE) {
int ret;
+ struct iov_tail data;
elem[count].out_num = VU_MAX_TX_BUFFER_NB;
elem[count].out_sg = &out_sg[out_sg_count];
@@ -191,26 +191,10 @@ static void vu_handle_tx(struct vu_dev *vdev, int index,
warn("virtio-net transmit queue contains no out buffers");
break;
}
- if (elem[count].out_num == 1) {
- tap_add_packet(vdev->context,
- elem[count].out_sg[0].iov_len - hdrlen,
- (char *)elem[count].out_sg[0].iov_base +
- hdrlen, now);
- } else {
- /* vnet header can be in a separate iovec */
- if (elem[count].out_num != 2) {
- debug("virtio-net transmit queue contains more than one buffer ([%d]: %u)",
- count, elem[count].out_num);
- } else if (elem[count].out_sg[0].iov_len != (size_t)hdrlen) {
- debug("virtio-net transmit queue entry not aligned on hdrlen ([%d]: %d != %zu)",
- count, hdrlen, elem[count].out_sg[0].iov_len);
- } else {
- tap_add_packet(vdev->context,
- elem[count].out_sg[1].iov_len,
- (char *)elem[count].out_sg[1].iov_base,
- now);
- }
- }
+
+ data = IOV_TAIL(elem[count].out_sg, elem[count].out_num, 0);
+ if (IOV_DROP_HEADER(&data, struct virtio_net_hdr_mrg_rxbuf))
+ tap_add_packet(vdev->context, &data, now);
count++;
}
--
2.49.0
next prev parent reply other threads:[~2025-04-11 13:10 UTC|newest]
Thread overview: 31+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-04-11 13:10 [PATCH v2 00/20] Introduce discontiguous frames management Laurent Vivier
2025-04-11 13:10 ` [PATCH v2 01/20] arp: Don't mix incoming and outgoing buffers Laurent Vivier
2025-04-11 13:10 ` [PATCH v2 02/20] iov: Introduce iov_tail_drop() and iov_slice() Laurent Vivier
2025-04-14 2:14 ` David Gibson
2025-04-11 13:10 ` [PATCH v2 03/20] iov: Update IOV_REMOVE_HEADER() and IOV_PEEK_HEADER() Laurent Vivier
2025-04-14 2:19 ` David Gibson
2025-04-11 13:10 ` Laurent Vivier [this message]
2025-04-11 13:10 ` [PATCH v2 05/20] packet: Use iov_tail with packet_add() Laurent Vivier
2025-04-11 13:10 ` [PATCH v2 06/20] packet: Add packet_base() Laurent Vivier
2025-04-14 2:29 ` David Gibson
2025-04-11 13:10 ` [PATCH v2 07/20] arp: Convert to iov_tail Laurent Vivier
2025-04-11 13:10 ` [PATCH v2 08/20] ndp: " Laurent Vivier
2025-04-11 13:10 ` [PATCH v2 09/20] icmp: " Laurent Vivier
2025-04-14 3:14 ` David Gibson
2025-04-11 13:10 ` [PATCH v2 10/20] udp: " Laurent Vivier
2025-04-14 3:21 ` David Gibson
2025-04-11 13:10 ` [PATCH v2 11/20] tcp: Convert tcp_tap_handler() to use iov_tail Laurent Vivier
2025-04-14 3:26 ` David Gibson
2025-04-11 13:10 ` [PATCH v2 12/20] tcp: Convert tcp_data_from_tap() " Laurent Vivier
2025-04-14 3:28 ` David Gibson
2025-04-11 13:10 ` [PATCH v2 13/20] dhcpv6: move offset initialization out of dhcpv6_opt() Laurent Vivier
2025-04-14 4:07 ` David Gibson
2025-04-11 13:10 ` [PATCH v2 14/20] dhcpv6: Extract sending of NotOnLink status Laurent Vivier
2025-04-14 4:10 ` David Gibson
2025-04-11 13:10 ` [PATCH v2 15/20] dhcpv6: Convert to iov_tail Laurent Vivier
2025-04-14 4:12 ` David Gibson
2025-04-11 13:10 ` [PATCH v2 16/20] dhcpv6: Use iov_tail in dhcpv6_opt() Laurent Vivier
2025-04-11 13:10 ` [PATCH v2 17/20] dhcp: Convert to iov_tail Laurent Vivier
2025-04-11 13:10 ` [PATCH v2 18/20] ip: Use iov_tail in ipv6_l4hdr() Laurent Vivier
2025-04-11 13:10 ` [PATCH v2 19/20] tap: Convert tap4_handler() to iov_tail Laurent Vivier
2025-04-11 13:10 ` [PATCH v2 20/20] tap: Convert tap6_handler() " Laurent Vivier
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250411131031.1398006-5-lvivier@redhat.com \
--to=lvivier@redhat.com \
--cc=david@gibson.dropbear.id.au \
--cc=passt-dev@passt.top \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://passt.top/passt
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for IMAP folder(s).