public inbox for passt-dev@passt.top
 help / color / mirror / code / Atom feed
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


  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).