public inbox for passt-dev@passt.top
 help / color / mirror / code / Atom feed
From: David Gibson <david@gibson.dropbear.id.au>
To: passt-dev@passt.top, Stefano Brivio <sbrivio@redhat.com>
Cc: David Gibson <david@gibson.dropbear.id.au>
Subject: [PATCH v2 08/10] tcp: Keep track of connections blocked due to a full tap interface
Date: Fri, 13 Sep 2024 14:32:12 +1000	[thread overview]
Message-ID: <20240913043214.1753014-9-david@gibson.dropbear.id.au> (raw)
In-Reply-To: <20240913043214.1753014-1-david@gibson.dropbear.id.au>

When we receive new data on a TCP socket, we attempt to forward all of it
to the tap interface immediately.  However, if the tap buffers fill up,
we might fail to transfer some of it.  In that case we'll need to try
again later.  Currently that's handled by the EPOLLIN event being
re-asserted in level mode at some point by complicated fiddling of the
event masks.  In preparation for a simpler way of triggering the retry,
keep track of which connections are in this state with a new TAP_FULL flag.
We also keep a count of the total number of connections currently in the
TAP_FULL state.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 tcp.c      | 12 +++++++++++-
 tcp_buf.c  |  3 +++
 tcp_conn.h |  1 +
 3 files changed, 15 insertions(+), 1 deletion(-)

diff --git a/tcp.c b/tcp.c
index 32e45e09..4b478432 100644
--- a/tcp.c
+++ b/tcp.c
@@ -349,7 +349,7 @@ static const char *tcp_state_str[] __attribute((__unused__)) = {
 
 static const char *tcp_flag_str[] __attribute((__unused__)) = {
 	"STALLED", "LOCAL", "ACTIVE_CLOSE", "ACK_TO_TAP_DUE",
-	"ACK_FROM_TAP_DUE",
+	"ACK_FROM_TAP_DUE", "TAP_FULL",
 };
 
 /* Listening sockets, used for automatic port forwarding in pasta mode only */
@@ -381,6 +381,11 @@ static struct iovec	tcp_iov			[UIO_MAXIOV];
 int init_sock_pool4		[TCP_SOCK_POOL_SIZE];
 int init_sock_pool6		[TCP_SOCK_POOL_SIZE];
 
+/* Number of connections with pending socket data that couldn't be sent because
+ * we ran out of buffer space on the tap side
+ */
+unsigned num_tap_full;
+
 /**
  * conn_at_sidx() - Get TCP connection specific flow at given sidx
  * @sidx:	Flow and side to retrieve
@@ -597,6 +602,11 @@ void conn_flag_do(const struct ctx *c, struct tcp_tap_conn *conn,
 	    (flag == ~ACK_FROM_TAP_DUE && (conn->flags & ACK_TO_TAP_DUE)) ||
 	    (flag == ~ACK_TO_TAP_DUE   && (conn->flags & ACK_FROM_TAP_DUE)))
 		tcp_timer_ctl(c, conn);
+
+	if (flag == TAP_FULL)
+		num_tap_full++;
+	else if (flag == ~TAP_FULL)
+		num_tap_full--;
 }
 
 /**
diff --git a/tcp_buf.c b/tcp_buf.c
index 83f91a37..0ccb9e6b 100644
--- a/tcp_buf.c
+++ b/tcp_buf.c
@@ -250,6 +250,8 @@ static void tcp_revert_seq(const struct ctx *c, struct tcp_tap_conn **conns,
 		uint32_t seq = ntohl(th->seq);
 		uint32_t peek_offset;
 
+		conn_flag(c, conn, TAP_FULL);
+
 		if (SEQ_LE(conn->seq_to_tap, seq))
 			continue;
 
@@ -526,6 +528,7 @@ int tcp_buf_data_from_sock(const struct ctx *c, struct tcp_tap_conn *conn)
 		seq += dlen;
 	}
 
+	conn_flag(c, conn, ~TAP_FULL);
 	conn_flag(c, conn, ACK_FROM_TAP_DUE);
 
 	return 0;
diff --git a/tcp_conn.h b/tcp_conn.h
index 6ae05115..9677678c 100644
--- a/tcp_conn.h
+++ b/tcp_conn.h
@@ -77,6 +77,7 @@ struct tcp_tap_conn {
 #define ACTIVE_CLOSE		BIT(2)
 #define ACK_TO_TAP_DUE		BIT(3)
 #define ACK_FROM_TAP_DUE	BIT(4)
+#define TAP_FULL		BIT(5)
 
 #define SNDBUF_BITS		24
 	unsigned int	sndbuf		:SNDBUF_BITS;
-- 
@@ -77,6 +77,7 @@ struct tcp_tap_conn {
 #define ACTIVE_CLOSE		BIT(2)
 #define ACK_TO_TAP_DUE		BIT(3)
 #define ACK_FROM_TAP_DUE	BIT(4)
+#define TAP_FULL		BIT(5)
 
 #define SNDBUF_BITS		24
 	unsigned int	sndbuf		:SNDBUF_BITS;
-- 
2.46.0


  parent reply	other threads:[~2024-09-13  4:32 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-09-13  4:32 [PATCH v2 00/10] RFC: Clean up TCP epoll mask handling David Gibson
2024-09-13  4:32 ` [PATCH v2 01/10] tcp: Make some extra functions private David Gibson
2024-09-13  4:32 ` [PATCH v2 02/10] tcp: Clean up tcpi_snd_wnd probing David Gibson
2024-09-17 21:54   ` Stefano Brivio
2024-09-18  1:27     ` David Gibson
2024-09-13  4:32 ` [PATCH v2 03/10] tcp: Simplify ifdef logic in tcp_update_seqack_wnd() David Gibson
2024-09-17 21:54   ` Stefano Brivio
2024-09-18  1:31     ` David Gibson
2024-09-13  4:32 ` [PATCH v2 04/10] tcp: Make tcp_update_seqack_wnd()s force_seq parameter explicitly boolean David Gibson
2024-09-13  4:32 ` [PATCH v2 05/10] tcp: On socket EPOLLOUT, send new ACK to tap immediately David Gibson
2024-09-13  4:32 ` [PATCH v2 06/10] tap: Re-introduce EPOLLET for tap connections David Gibson
2024-09-13  4:32 ` [PATCH v2 07/10] tap: Keep track of whether there might be space in the tap buffers David Gibson
2024-09-13  4:32 ` David Gibson [this message]
2024-09-13  4:32 ` [PATCH v2 09/10] tcp: Move deferred handling functions later in tcp.c David Gibson
2024-09-13  4:32 ` [PATCH v2 10/10] tcp: Simplify epoll event mask management 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=20240913043214.1753014-9-david@gibson.dropbear.id.au \
    --to=david@gibson.dropbear.id.au \
    --cc=passt-dev@passt.top \
    --cc=sbrivio@redhat.com \
    /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).