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>
Subject: [PATCH 5/7] tcp: Use iov_tail to access headers in tcp_prepare_flags()
Date: Mon, 23 Mar 2026 17:52:57 +0100	[thread overview]
Message-ID: <20260323165259.1253482-6-lvivier@redhat.com> (raw)
In-Reply-To: <20260323165259.1253482-1-lvivier@redhat.com>

Instead of passing separate pointers to the TCP header and SYN options,
pass an iov_tail pointing to the start of the TCP payload area.
tcp_prepare_flags() then uses with_header() and IOV_DROP_HEADER() to
access the TCP header and SYN options directly within the iov, matching
the iov_tail-based approach already used by tcp_fill_headers().

Signed-off-by: Laurent Vivier <lvivier@redhat.com>
---
 tcp.c          | 71 +++++++++++++++++++++++++++-----------------------
 tcp_buf.c      |  8 +++---
 tcp_internal.h |  2 +-
 tcp_vu.c       |  9 +++----
 4 files changed, 48 insertions(+), 42 deletions(-)

diff --git a/tcp.c b/tcp.c
index 058792d5b184..ad601567d39f 100644
--- a/tcp.c
+++ b/tcp.c
@@ -1295,8 +1295,7 @@ static int tcp_rewind_seq(const struct ctx *c, struct tcp_tap_conn *conn)
  * @c:		Execution context
  * @conn:	Connection pointer
  * @flags:	TCP flags: if not set, send segment only if ACK is due
- * @th:		TCP header to update
- * @opts:	TCP option buffer (output parameter)
+ * @payload:	TCP payload including TCP header
  * @optlen:	size of the TCP option buffer (output parameter)
  *
  * Return: < 0 error code on connection reset,
@@ -1304,10 +1303,11 @@ static int tcp_rewind_seq(const struct ctx *c, struct tcp_tap_conn *conn)
  *	     1 otherwise
  */
 int tcp_prepare_flags(const struct ctx *c, struct tcp_tap_conn *conn,
-		      int flags, struct tcphdr *th, struct tcp_syn_opts *opts,
+		      int flags, const struct iov_tail *payload,
 		      size_t *optlen)
 {
 	struct tcp_info_linux tinfo = { 0 };
+	struct iov_tail current = *payload;
 	socklen_t sl = sizeof(tinfo);
 	int s = conn->sock;
 
@@ -1330,6 +1330,40 @@ int tcp_prepare_flags(const struct ctx *c, struct tcp_tap_conn *conn,
 
 	*optlen = 0;
 	if (flags & SYN) {
+		conn->ws_to_tap = MIN(MAX_WS, tinfo.tcpi_snd_wscale);
+
+		*optlen = sizeof(struct tcp_syn_opts);
+	} else {
+		flags |= ACK;
+	}
+
+	with_header(struct tcphdr, th, &current) {
+		th->doff = (sizeof(*th) + *optlen) / 4;
+
+		th->ack = !!(flags & ACK);
+		th->psh = !!(flags & PSH);
+		th->rst = !!(flags & RST);
+		th->syn = !!(flags & SYN);
+		th->fin = !!(flags & FIN);
+
+		if (th->ack) {
+			if (SEQ_GE(conn->seq_ack_to_tap, conn->seq_from_tap) &&
+			    conn->wnd_to_tap)
+				conn_flag(c, conn, ~ACK_TO_TAP_DUE);
+			else
+				conn_flag(c, conn, ACK_TO_TAP_DUE);
+		}
+
+		if (th->fin)
+			conn_flag(c, conn, ACK_FROM_TAP_DUE);
+
+		/* RFC 793, 3.1: "[...] and the first data octet is ISN+1." */
+		if (th->fin || th->syn)
+			conn->seq_to_tap++;
+	}
+	IOV_DROP_HEADER(&current, struct tcphdr);
+
+	if (*optlen) {
 		int mss;
 
 		if (!c->mtu) {
@@ -1348,37 +1382,10 @@ int tcp_prepare_flags(const struct ctx *c, struct tcp_tap_conn *conn,
 				mss = ROUND_DOWN(mss, PAGE_SIZE);
 		}
 
-		conn->ws_to_tap = MIN(MAX_WS, tinfo.tcpi_snd_wscale);
-
-		*opts = TCP_SYN_OPTS(mss, conn->ws_to_tap);
-		*optlen = sizeof(*opts);
-	} else {
-		flags |= ACK;
+		with_header(struct tcp_syn_opts, opts, &current)
+			*opts = TCP_SYN_OPTS(mss, conn->ws_to_tap);
 	}
 
-	th->doff = (sizeof(*th) + *optlen) / 4;
-
-	th->ack = !!(flags & ACK);
-	th->psh = !!(flags & PSH);
-	th->rst = !!(flags & RST);
-	th->syn = !!(flags & SYN);
-	th->fin = !!(flags & FIN);
-
-	if (th->ack) {
-		if (SEQ_GE(conn->seq_ack_to_tap, conn->seq_from_tap) &&
-		    conn->wnd_to_tap)
-			conn_flag(c, conn, ~ACK_TO_TAP_DUE);
-		else
-			conn_flag(c, conn, ACK_TO_TAP_DUE);
-	}
-
-	if (th->fin)
-		conn_flag(c, conn, ACK_FROM_TAP_DUE);
-
-	/* RFC 793, 3.1: "[...] and the first data octet is ISN+1." */
-	if (th->fin || th->syn)
-		conn->seq_to_tap++;
-
 	return 1;
 }
 
diff --git a/tcp_buf.c b/tcp_buf.c
index 891043c96dcb..ffd250c8798f 100644
--- a/tcp_buf.c
+++ b/tcp_buf.c
@@ -197,7 +197,7 @@ static void tcp_l2_buf_fill_headers(const struct ctx *c,
  */
 int tcp_buf_send_flag(const struct ctx *c, struct tcp_tap_conn *conn, int flags)
 {
-	struct tcp_payload_t *payload;
+	struct iov_tail tail;
 	struct iovec *iov;
 	size_t optlen;
 	size_t l4len;
@@ -211,10 +211,10 @@ int tcp_buf_send_flag(const struct ctx *c, struct tcp_tap_conn *conn, int flags)
 		iov[TCP_IOV_IP] = IOV_OF_LVALUE(tcp6_payload_ip[tcp_payload_used]);
 
 	iov[TCP_IOV_ETH] = IOV_OF_LVALUE(tcp_eth_hdr[tcp_payload_used]);
-	payload = iov[TCP_IOV_PAYLOAD].iov_base;
+	iov[TCP_IOV_PAYLOAD].iov_len = sizeof(struct tcp_payload_t);
+	tail = IOV_TAIL(&iov[TCP_IOV_PAYLOAD], 1, 0);
 	seq = conn->seq_to_tap;
-	ret = tcp_prepare_flags(c, conn, flags, &payload->th,
-				(struct tcp_syn_opts *)&payload->data, &optlen);
+	ret = tcp_prepare_flags(c, conn, flags, &tail, &optlen);
 	if (ret <= 0)
 		return ret;
 
diff --git a/tcp_internal.h b/tcp_internal.h
index 136e947f6e70..9f745d0752ff 100644
--- a/tcp_internal.h
+++ b/tcp_internal.h
@@ -190,7 +190,7 @@ size_t tcp_fill_headers(const struct ctx *c, struct tcp_tap_conn *conn,
 int tcp_update_seqack_wnd(const struct ctx *c, struct tcp_tap_conn *conn,
 			  bool force_seq, struct tcp_info_linux *tinfo);
 int tcp_prepare_flags(const struct ctx *c, struct tcp_tap_conn *conn,
-		      int flags, struct tcphdr *th, struct tcp_syn_opts *opts,
+		      int flags, const struct iov_tail *payload,
 		      size_t *optlen);
 int tcp_set_peek_offset(const struct tcp_tap_conn *conn, int offset);
 
diff --git a/tcp_vu.c b/tcp_vu.c
index 96cd9da1caae..d6bd6a34d6da 100644
--- a/tcp_vu.c
+++ b/tcp_vu.c
@@ -90,7 +90,6 @@ int tcp_vu_send_flag(const struct ctx *c, struct tcp_tap_conn *conn, int flags)
 	struct ipv6hdr *ip6h = NULL;
 	struct iphdr *ip4h = NULL;
 	struct iovec flags_iov[2];
-	struct tcp_syn_opts *opts;
 	struct iov_tail payload;
 	size_t optlen, hdrlen;
 	struct tcphdr *th;
@@ -104,13 +103,13 @@ int tcp_vu_send_flag(const struct ctx *c, struct tcp_tap_conn *conn, int flags)
 
 	elem_cnt = vu_collect(vdev, vq, &flags_elem[0], 1,
 			      &flags_iov[0], 1, NULL,
-			      hdrlen + sizeof(*opts), NULL);
+			      hdrlen + sizeof(struct tcp_syn_opts), NULL);
 	if (elem_cnt != 1)
 		return -1;
 
 	assert(flags_elem[0].in_num == 1);
 	assert(flags_elem[0].in_sg[0].iov_len >=
-	       MAX(hdrlen + sizeof(*opts), ETH_ZLEN + VNET_HLEN));
+	       MAX(hdrlen + sizeof(struct tcp_syn_opts), ETH_ZLEN + VNET_HLEN));
 
 	vu_set_vnethdr(flags_elem[0].in_sg[0].iov_base, 1);
 
@@ -139,8 +138,8 @@ int tcp_vu_send_flag(const struct ctx *c, struct tcp_tap_conn *conn, int flags)
 	th->ack = 1;
 
 	seq = conn->seq_to_tap;
-	opts = (struct tcp_syn_opts *)(th + 1);
-	ret = tcp_prepare_flags(c, conn, flags, th, opts, &optlen);
+	payload = IOV_TAIL(flags_elem[0].in_sg, 1, hdrlen - sizeof(*th));
+	ret = tcp_prepare_flags(c, conn, flags, &payload, &optlen);
 	if (ret <= 0) {
 		vu_queue_rewind(vq, 1);
 		return ret;
-- 
2.53.0


  parent reply	other threads:[~2026-03-23 16:53 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-03-23 16:52 [PATCH 0/7] vhost-user,tcp: Handle multiple iovec entries per virtqueue element Laurent Vivier
2026-03-23 16:52 ` [PATCH 1/7] tcp: pass ipv4h checksum, not a pointer to the checksum Laurent Vivier
2026-03-24  3:53   ` David Gibson
2026-03-24  7:56     ` Laurent Vivier
2026-03-24 23:49       ` David Gibson
2026-03-23 16:52 ` [PATCH 2/7] tcp: use iov_tail to access headers in tcp_fill_headers() Laurent Vivier
2026-03-24  3:58   ` David Gibson
2026-03-23 16:52 ` [PATCH 3/7] tcp_vu: Use iov_tail helpers to build headers in tcp_vu_prepare() Laurent Vivier
2026-03-25  4:46   ` David Gibson
2026-03-23 16:52 ` [PATCH 4/7] tcp_vu: Support multibuffer frames in tcp_vu_sock_recv() Laurent Vivier
2026-03-25  5:06   ` David Gibson
2026-03-23 16:52 ` Laurent Vivier [this message]
2026-03-23 16:52 ` [PATCH 6/7] iov: introduce iov_memcopy() Laurent Vivier
2026-03-23 16:52 ` [PATCH 7/7] tcp_vu: Use iov_tail helpers to build headers in tcp_vu_send_flag() Laurent Vivier
2026-03-25  5:07 ` [PATCH 0/7] vhost-user,tcp: Handle multiple iovec entries per virtqueue element David Gibson

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=20260323165259.1253482-6-lvivier@redhat.com \
    --to=lvivier@redhat.com \
    --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).