From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: passt.top; dmarc=none (p=none dis=none) header.from=gibson.dropbear.id.au Authentication-Results: passt.top; dkim=pass (2048-bit key; secure) header.d=gibson.dropbear.id.au header.i=@gibson.dropbear.id.au header.a=rsa-sha256 header.s=202606 header.b=AxP+1dIo; dkim-atps=neutral Received: from mail.ozlabs.org (mail.ozlabs.org [IPv6:2404:9400:2221:ea00::3]) by passt.top (Postfix) with ESMTPS id 59D5B5A026D for ; Mon, 15 Jun 2026 10:18:39 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gibson.dropbear.id.au; s=202606; t=1781511516; bh=K/2GyDehKQ6Yh+9++t4Xfdb0M47H2ieC4sFg0+C0fM8=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=AxP+1dIoKf3UTKZ5NsW9lITHQOWcN+eYMVCIUVK7NOQrmJNMUaytVZLasVjgXYMIR /+uA+4kgBvZyeDQgJyWd6meRTugP7EcHkbWIy0xjEmef8QAYErRsc1li+ftuiUGwAZ h7CTCXuYEKhEghosAm68onUQqXcUmEcp7NJ+uly2lSJMnnKYGKoJ9P9XmNA/SbVrl7 icLXMeoBLvr8FYCRFQJxIoScmUviiqFeHBUBD9QLJk7J5kVarzvrrzfAAvqifzpexQ ovxsGOVracmiCQR3mlTLVGgDFqnxrFgtRZHujU4q04ui35o1lGBt5kij57G/4E/eK5 mdedPph/+nJ5g== Received: by gandalf.ozlabs.org (Postfix, from userid 1007) id 4gf30r1gbtz4wTY; Mon, 15 Jun 2026 18:18:36 +1000 (AEST) From: David Gibson To: Stefano Brivio , passt-dev@passt.top Subject: [PATCH 3/5] tcp: Merge common sequence logic from tcp_{buf,vu}_data_from_sock() Date: Mon, 15 Jun 2026 18:18:31 +1000 Message-ID: <20260615081833.1061725-4-david@gibson.dropbear.id.au> X-Mailer: git-send-email 2.54.0 In-Reply-To: <20260615081833.1061725-1-david@gibson.dropbear.id.au> References: <20260615081833.1061725-1-david@gibson.dropbear.id.au> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Message-ID-Hash: RZONS3CUPDSNJJX2ENEN7FC6OLXAN3R2 X-Message-ID-Hash: RZONS3CUPDSNJJX2ENEN7FC6OLXAN3R2 X-MailFrom: dgibson@gandalf.ozlabs.org X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: David Gibson , Laurent Vivier X-Mailman-Version: 3.3.8 Precedence: list List-Id: Development discussion and patches for passt Archived-At: Archived-At: List-Archive: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: tcp_buf_data_from_sock() and tcp_vu_data_from_sock() start with some identical logic to compute the amount of data from the socket that has already been sent to tap but not acked. Replace it with a single copy in their common caller tcp_data_from_sock(), passing the already_sent amount in as a parameter. This does mean that we now execute this logic in the VU case even if the queue is not active. The logic is still valid in this case, and we don't need to worry too much about wasting cycles in this edge case. Cc: Laurent Vivier Signed-off-by: David Gibson --- tcp.c | 29 +++++++++++++++++++++++++++-- tcp_buf.c | 28 ++++------------------------ tcp_buf.h | 3 ++- tcp_vu.c | 27 ++++----------------------- tcp_vu.h | 3 ++- 5 files changed, 39 insertions(+), 51 deletions(-) diff --git a/tcp.c b/tcp.c index c4000754..dcadc765 100644 --- a/tcp.c +++ b/tcp.c @@ -1837,10 +1837,35 @@ static int tcp_sock_consume(const struct tcp_tap_conn *conn, uint32_t ack_seq) */ static int tcp_data_from_sock(const struct ctx *c, struct tcp_tap_conn *conn) { + uint32_t wnd_scaled = conn->wnd_from_tap << conn->ws_from_tap; + uint32_t already_sent; + + /* How much have we read/sent since last received ack ? */ + already_sent = conn->seq_to_tap - conn->seq_ack_from_tap; + + if (SEQ_LT(already_sent, 0)) { + /* RFC 761, section 2.1. */ + flow_trace(conn, "ACK sequence gap: ACK for %u, sent: %u", + conn->seq_ack_from_tap, conn->seq_to_tap); + conn->seq_to_tap = conn->seq_ack_from_tap; + already_sent = 0; + if (tcp_set_peek_offset(conn, 0)) { + tcp_rst(c, conn); + return -1; + } + } + + if (!wnd_scaled || already_sent >= wnd_scaled) { + conn_flag(c, conn, ACK_FROM_TAP_BLOCKS); + conn_flag(c, conn, STALLED); + conn_flag(c, conn, ACK_FROM_TAP_DUE); + return 0; + } + if (c->mode == MODE_VU) - return tcp_vu_data_from_sock(c, conn); + return tcp_vu_data_from_sock(c, conn, already_sent); - return tcp_buf_data_from_sock(c, conn); + return tcp_buf_data_from_sock(c, conn, already_sent); } /** diff --git a/tcp_buf.c b/tcp_buf.c index ca356089..1fc49959 100644 --- a/tcp_buf.c +++ b/tcp_buf.c @@ -309,42 +309,22 @@ static void tcp_data_to_tap(const struct ctx *c, struct tcp_tap_conn *conn, * tcp_buf_data_from_sock() - Handle new data from socket, queue to tap, in window * @c: Execution context * @conn: Connection pointer + * @already_sent: Number of bytes already sent to tap, but not acked * * Return: negative on connection reset, 0 otherwise * * #syscalls recvmsg */ -int tcp_buf_data_from_sock(const struct ctx *c, struct tcp_tap_conn *conn) +int tcp_buf_data_from_sock(const struct ctx *c, struct tcp_tap_conn *conn, + uint32_t already_sent) { uint32_t wnd_scaled = conn->wnd_from_tap << conn->ws_from_tap; int fill_bufs, send_bufs = 0, last_len, iov_rem = 0; int len, dlen, i, s = conn->sock; struct msghdr mh_sock = { 0 }; uint16_t mss = MSS_GET(conn); - uint32_t already_sent, seq; struct iovec *iov; - - /* How much have we read/sent since last received ack ? */ - already_sent = conn->seq_to_tap - conn->seq_ack_from_tap; - - if (SEQ_LT(already_sent, 0)) { - /* RFC 761, section 2.1. */ - flow_trace(conn, "ACK sequence gap: ACK for %u, sent: %u", - conn->seq_ack_from_tap, conn->seq_to_tap); - conn->seq_to_tap = conn->seq_ack_from_tap; - already_sent = 0; - if (tcp_set_peek_offset(conn, 0)) { - tcp_rst(c, conn); - return -1; - } - } - - if (!wnd_scaled || already_sent >= wnd_scaled) { - conn_flag(c, conn, ACK_FROM_TAP_BLOCKS); - conn_flag(c, conn, STALLED); - conn_flag(c, conn, ACK_FROM_TAP_DUE); - return 0; - } + uint32_t seq; /* Set up buffer descriptors we'll fill completely and partially. */ fill_bufs = DIV_ROUND_UP(wnd_scaled - already_sent, mss); diff --git a/tcp_buf.h b/tcp_buf.h index 54f5e53f..710ed377 100644 --- a/tcp_buf.h +++ b/tcp_buf.h @@ -8,7 +8,8 @@ void tcp_sock_iov_init(const struct ctx *c); void tcp_payload_flush(const struct ctx *c); -int tcp_buf_data_from_sock(const struct ctx *c, struct tcp_tap_conn *conn); +int tcp_buf_data_from_sock(const struct ctx *c, struct tcp_tap_conn *conn, + uint32_t already_sent); int tcp_buf_send_flag(const struct ctx *c, struct tcp_tap_conn *conn, int flags); #endif /*TCP_BUF_H */ diff --git a/tcp_vu.c b/tcp_vu.c index 7e2a7dbc..00616955 100644 --- a/tcp_vu.c +++ b/tcp_vu.c @@ -423,46 +423,27 @@ static void tcp_vu_prepare(const struct ctx *c, struct tcp_tap_conn *conn, * in window * @c: Execution context * @conn: Connection pointer + * @already_sent: Number of bytes already sent to tap, but not acked * * Return: negative on connection reset, 0 otherwise */ -int tcp_vu_data_from_sock(const struct ctx *c, struct tcp_tap_conn *conn) +int tcp_vu_data_from_sock(const struct ctx *c, struct tcp_tap_conn *conn, + uint32_t already_sent) { uint32_t wnd_scaled = conn->wnd_from_tap << conn->ws_from_tap; struct vu_dev *vdev = c->vdev; struct vu_virtq *vq = &vdev->vq[VHOST_USER_RX_QUEUE]; - uint32_t already_sent, check; ssize_t len, previous_dlen; int i, elem_cnt, frame_cnt; size_t hdrlen, fillsize; int v6 = CONN_V6(conn); + uint32_t check; if (!vu_queue_enabled(vq) || !vu_queue_started(vq)) { debug("Got packet, but RX virtqueue not usable yet"); return 0; } - already_sent = conn->seq_to_tap - conn->seq_ack_from_tap; - - if (SEQ_LT(already_sent, 0)) { - /* RFC 761, section 2.1. */ - flow_trace(conn, "ACK sequence gap: ACK for %u, sent: %u", - conn->seq_ack_from_tap, conn->seq_to_tap); - conn->seq_to_tap = conn->seq_ack_from_tap; - already_sent = 0; - if (tcp_set_peek_offset(conn, 0)) { - tcp_rst(c, conn); - return -1; - } - } - - if (!wnd_scaled || already_sent >= wnd_scaled) { - conn_flag(c, conn, ACK_FROM_TAP_BLOCKS); - conn_flag(c, conn, STALLED); - conn_flag(c, conn, ACK_FROM_TAP_DUE); - return 0; - } - /* Set up buffer descriptors we'll fill completely and partially. */ fillsize = wnd_scaled - already_sent; diff --git a/tcp_vu.h b/tcp_vu.h index 6ab6057f..30e46925 100644 --- a/tcp_vu.h +++ b/tcp_vu.h @@ -7,6 +7,7 @@ #define TCP_VU_H int tcp_vu_send_flag(const struct ctx *c, struct tcp_tap_conn *conn, int flags); -int tcp_vu_data_from_sock(const struct ctx *c, struct tcp_tap_conn *conn); +int tcp_vu_data_from_sock(const struct ctx *c, struct tcp_tap_conn *conn, + uint32_t already_sent); #endif /*TCP_VU_H */ -- 2.54.0