import UBI passt-0^20250512.g8ec1341-5.el10_1
This commit is contained in:
parent
58c7214df8
commit
7e5a554ec1
@ -0,0 +1,49 @@
|
||||
From a7d9ce6cacf8d62ca78fa98d469902c900659cb9 Mon Sep 17 00:00:00 2001
|
||||
From: David Gibson <david@gibson.dropbear.id.au>
|
||||
Date: Tue, 4 Nov 2025 16:40:43 +1100
|
||||
Subject: [PATCH 4/8] tcp: Properly remove sockets from epoll loop when
|
||||
connection is closed
|
||||
|
||||
Most of the handling for closing a TCP connectin is in conn_event_do() when
|
||||
it receives a 'CLOSED' event. We specifically check for this case and,
|
||||
correctly, remove the connection from the flow hash table. However, we
|
||||
also bypass the call tp tcp_epoll_ctl() which is not correct. By skipping
|
||||
tcp_epoll_ctl() we skip it's specific handling of the CLOSED event, which
|
||||
includes removing the TCP socket from epoll.
|
||||
|
||||
If we somehow get an event on such a stale socket, we'll get a stale flow
|
||||
reference. That flow slot might have been re-used, leading to to a crash
|
||||
in conn_at_sidx().
|
||||
|
||||
Fixes: b86afe3559c0 ("tcp: Don't defer hash table removal")
|
||||
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
|
||||
(cherry picked from commit 60ade6cae70dc48f7f777c38e7c70fc3696784c4)
|
||||
---
|
||||
tcp.c | 9 +++++----
|
||||
1 file changed, 5 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/tcp.c b/tcp.c
|
||||
index 0ac298a..17e99af 100644
|
||||
--- a/tcp.c
|
||||
+++ b/tcp.c
|
||||
@@ -681,12 +681,13 @@ void conn_event_do(const struct ctx *c, struct tcp_tap_conn *conn,
|
||||
flow_dbg(conn, "%s",
|
||||
num == -1 ? "CLOSED" : tcp_event_str[num]);
|
||||
|
||||
- if (event == CLOSED)
|
||||
- flow_hash_remove(c, TAP_SIDX(conn));
|
||||
- else if ((event == TAP_FIN_RCVD) && !(conn->events & SOCK_FIN_RCVD))
|
||||
+ if ((event == TAP_FIN_RCVD) && !(conn->events & SOCK_FIN_RCVD)) {
|
||||
conn_flag(c, conn, ACTIVE_CLOSE);
|
||||
- else
|
||||
+ } else {
|
||||
+ if (event == CLOSED)
|
||||
+ flow_hash_remove(c, TAP_SIDX(conn));
|
||||
tcp_epoll_ctl(c, conn);
|
||||
+ }
|
||||
|
||||
if (CONN_HAS(conn, SOCK_FIN_SENT | TAP_FIN_ACKED))
|
||||
tcp_timer_ctl(c, conn);
|
||||
--
|
||||
2.47.1
|
||||
|
||||
80
0005-tcp-Remove-non-working-activity-timeout-mechanism.patch
Normal file
80
0005-tcp-Remove-non-working-activity-timeout-mechanism.patch
Normal file
@ -0,0 +1,80 @@
|
||||
From 34a346e3eb83b33bd6d62a57e0e990c5c698fe85 Mon Sep 17 00:00:00 2001
|
||||
From: David Gibson <david@gibson.dropbear.id.au>
|
||||
Date: Wed, 4 Feb 2026 21:41:34 +1000
|
||||
Subject: [PATCH 5/8] tcp: Remove non-working activity timeout mechanism
|
||||
|
||||
This mechanism was intended to remove connections which have had no
|
||||
activity for two hours, even if they haven't closed or been reset
|
||||
internally. It operated by setting the two hour timeout if there are
|
||||
no sooner TCP timeouts to schedule.
|
||||
|
||||
However, when the timer fires, the way we detect the case of the activity
|
||||
timeout doesn't work: it resets the timer for another two hours, then
|
||||
checks if the old timeout was two hours. But the old timeout returned
|
||||
by timerfd_settime() is not the original value of the timer, but the
|
||||
remaining time. Since the timer has just fired it will essentially always
|
||||
be 0.
|
||||
|
||||
For now, just remove the mechanism, disarming the timer entirely if there
|
||||
isn't another upcoming event. We'll re-introduce some sort of activity
|
||||
timeout by a different means later.
|
||||
|
||||
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
|
||||
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
|
||||
(cherry picked from commit e48ce41a1ec2f05846fb66d3847c2c2b6448ca71)
|
||||
---
|
||||
tcp.c | 24 +++---------------------
|
||||
1 file changed, 3 insertions(+), 21 deletions(-)
|
||||
|
||||
diff --git a/tcp.c b/tcp.c
|
||||
index 17e99af..7a7ca24 100644
|
||||
--- a/tcp.c
|
||||
+++ b/tcp.c
|
||||
@@ -197,9 +197,6 @@
|
||||
* TAP_FIN_ACKED), but no socket activity is detected from the socket within
|
||||
* this time, reset the connection
|
||||
*
|
||||
- * - ACT_TIMEOUT, in the presence of any event: if no activity is detected on
|
||||
- * either side, the connection is reset
|
||||
- *
|
||||
* - ACK_INTERVAL elapsed after data segment received from tap without having
|
||||
* sent an ACK segment, or zero-sized window advertised to tap/guest (flag
|
||||
* ACK_TO_TAP_DUE): forcibly check if an ACK segment can be sent
|
||||
@@ -578,7 +575,9 @@ static void tcp_timer_ctl(const struct ctx *c, struct tcp_tap_conn *conn)
|
||||
} else if (CONN_HAS(conn, SOCK_FIN_SENT | TAP_FIN_ACKED)) {
|
||||
it.it_value.tv_sec = FIN_TIMEOUT;
|
||||
} else {
|
||||
- it.it_value.tv_sec = ACT_TIMEOUT;
|
||||
+ /* Disarm */
|
||||
+ it.it_value.tv_sec = 0;
|
||||
+ it.it_value.tv_nsec = 0;
|
||||
}
|
||||
|
||||
flow_dbg(conn, "timer expires in %llu.%03llus",
|
||||
@@ -2294,23 +2293,6 @@ void tcp_timer_handler(const struct ctx *c, union epoll_ref ref)
|
||||
tcp_timer_ctl(c, conn);
|
||||
}
|
||||
}
|
||||
- } else {
|
||||
- struct itimerspec new = { { 0 }, { ACT_TIMEOUT, 0 } };
|
||||
- struct itimerspec old = { { 0 }, { 0 } };
|
||||
-
|
||||
- /* Activity timeout: if it was already set, reset the
|
||||
- * connection, otherwise, it was a left-over from ACK_TO_TAP_DUE
|
||||
- * or ACK_FROM_TAP_DUE, so just set the long timeout in that
|
||||
- * case. This avoids having to preemptively reset the timer on
|
||||
- * ~ACK_TO_TAP_DUE or ~ACK_FROM_TAP_DUE.
|
||||
- */
|
||||
- if (timerfd_settime(conn->timer, 0, &new, &old))
|
||||
- flow_perror(conn, "failed to set timer");
|
||||
-
|
||||
- if (old.it_value.tv_sec == ACT_TIMEOUT) {
|
||||
- flow_dbg(conn, "activity timeout");
|
||||
- tcp_rst(c, conn);
|
||||
- }
|
||||
}
|
||||
}
|
||||
|
||||
--
|
||||
2.47.1
|
||||
|
||||
181
0006-tcp-Re-introduce-inactivity-timeouts-based-on-a-cloc.patch
Normal file
181
0006-tcp-Re-introduce-inactivity-timeouts-based-on-a-cloc.patch
Normal file
@ -0,0 +1,181 @@
|
||||
From 479c464c767e655fad65b9bedc496570bb40c997 Mon Sep 17 00:00:00 2001
|
||||
From: David Gibson <david@gibson.dropbear.id.au>
|
||||
Date: Wed, 4 Feb 2026 21:41:35 +1000
|
||||
Subject: [PATCH 6/8] tcp: Re-introduce inactivity timeouts based on a clock
|
||||
algorithm
|
||||
|
||||
We previously had a mechanism to remove TCP connections which were
|
||||
inactive for 2 hours. That was broken for a long time, due to poor
|
||||
interactions with the timerfd handling, so we removed it.
|
||||
|
||||
Adding this long scale timer onto the timerfd handling, which mostly
|
||||
handles much shorter timeouts is tricky to reason about. However, for the
|
||||
inactivity timeouts, we don't require precision. Instead, we can use
|
||||
a 1-bit page replacement / "clock" algorithm. Every INACTIVITY_INTERVAL
|
||||
(2 hours), a global timer marks every TCP connection as tentatively
|
||||
inactive. That flag is cleared if we get any events, either tap side or
|
||||
socket side.
|
||||
|
||||
If the inactive flag is still set when the next INACTIVITY_INTERVAL expires
|
||||
then the connection has been inactive for an extended period and we reset
|
||||
and close it. In practice this means that connections will be removed
|
||||
after 2-4 hours of inactivity.
|
||||
|
||||
This is not a true fix for bug 179, but it does mitigate the damage, by
|
||||
limiting the time that inactive connections will remain around,
|
||||
|
||||
Link: https://bugs.passt.top/show_bug.cgi?id=179
|
||||
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
|
||||
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
|
||||
(cherry picked from commit 1820103fbbf13df98257a3f5c3ba625de624b0b3)
|
||||
---
|
||||
tcp.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++++-
|
||||
tcp.h | 2 ++
|
||||
tcp_conn.h | 3 +++
|
||||
3 files changed, 53 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/tcp.c b/tcp.c
|
||||
index 7a7ca24..394fc35 100644
|
||||
--- a/tcp.c
|
||||
+++ b/tcp.c
|
||||
@@ -201,6 +201,13 @@
|
||||
* sent an ACK segment, or zero-sized window advertised to tap/guest (flag
|
||||
* ACK_TO_TAP_DUE): forcibly check if an ACK segment can be sent
|
||||
*
|
||||
+ * We also use a global interval timer for an activity timeout which doesn't
|
||||
+ * require precision:
|
||||
+ *
|
||||
+ * - INACTIVITY_INTERVAL: if a connection has had no activity for an entire
|
||||
+ * interval, close and reset it. This means that idle connections (without
|
||||
+ * keepalives) will be removed between INACTIVITY_INTERVAL s and
|
||||
+ * 2*INACTIVITY_INTERVAL s after the last activity.
|
||||
*
|
||||
* Summary of data flows (with ESTABLISHED event)
|
||||
* ----------------------------------------------
|
||||
@@ -330,7 +337,8 @@ enum {
|
||||
#define SYN_TIMEOUT 10 /* s */
|
||||
#define ACK_TIMEOUT 2
|
||||
#define FIN_TIMEOUT 60
|
||||
-#define ACT_TIMEOUT 7200
|
||||
+
|
||||
+#define INACTIVITY_INTERVAL 7200 /* s */
|
||||
|
||||
#define LOW_RTT_TABLE_SIZE 8
|
||||
#define LOW_RTT_THRESHOLD 10 /* us */
|
||||
@@ -2000,6 +2008,8 @@ int tcp_tap_handler(const struct ctx *c, uint8_t pif, sa_family_t af,
|
||||
return 1;
|
||||
}
|
||||
|
||||
+ conn->inactive = false;
|
||||
+
|
||||
if (th->ack && !(conn->events & ESTABLISHED))
|
||||
tcp_update_seqack_from_tap(c, conn, ntohl(th->ack_seq));
|
||||
|
||||
@@ -2318,6 +2328,8 @@ void tcp_sock_handler(const struct ctx *c, union epoll_ref ref,
|
||||
return;
|
||||
}
|
||||
|
||||
+ conn->inactive = false;
|
||||
+
|
||||
if ((conn->events & TAP_FIN_SENT) && (events & EPOLLHUP)) {
|
||||
conn_event(c, conn, CLOSED);
|
||||
return;
|
||||
@@ -2696,6 +2708,7 @@ static void tcp_port_rebind(struct ctx *c, bool outbound)
|
||||
}
|
||||
}
|
||||
|
||||
+
|
||||
/**
|
||||
* tcp_port_rebind_outbound() - Rebind ports in namespace
|
||||
* @arg: Execution context
|
||||
@@ -2714,6 +2727,38 @@ static int tcp_port_rebind_outbound(void *arg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
+/**
|
||||
+ * tcp_inactivity() - Scan for and close long-inactive connections
|
||||
+ * @: Execution context
|
||||
+ */
|
||||
+static void tcp_inactivity(struct ctx *c, const struct timespec *now)
|
||||
+{
|
||||
+ union flow *flow;
|
||||
+
|
||||
+ if (now->tv_sec - c->tcp.inactivity_run < INACTIVITY_INTERVAL)
|
||||
+ return;
|
||||
+
|
||||
+ debug("TCP inactivity scan");
|
||||
+ c->tcp.inactivity_run = now->tv_sec;
|
||||
+
|
||||
+ flow_foreach(flow) {
|
||||
+ struct tcp_tap_conn *conn = &flow->tcp;
|
||||
+
|
||||
+ if (flow->f.type != FLOW_TCP)
|
||||
+ continue;
|
||||
+
|
||||
+ if (conn->inactive) {
|
||||
+ /* No activity in this interval, reset */
|
||||
+ flow_dbg(conn, "Inactive for at least %us, resetting",
|
||||
+ INACTIVITY_INTERVAL);
|
||||
+ tcp_rst(c, conn);
|
||||
+ }
|
||||
+
|
||||
+ /* Ready to check fot next interval */
|
||||
+ conn->inactive = true;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
/**
|
||||
* tcp_timer() - Periodic tasks: port detection, closed connections, pool refill
|
||||
* @c: Execution context
|
||||
@@ -2738,6 +2783,8 @@ void tcp_timer(struct ctx *c, const struct timespec *now)
|
||||
tcp_sock_refill_init(c);
|
||||
if (c->mode == MODE_PASTA)
|
||||
tcp_splice_refill(c);
|
||||
+
|
||||
+ tcp_inactivity(c, now);
|
||||
}
|
||||
|
||||
/**
|
||||
diff --git a/tcp.h b/tcp.h
|
||||
index 234a803..b75e9a7 100644
|
||||
--- a/tcp.h
|
||||
+++ b/tcp.h
|
||||
@@ -59,12 +59,14 @@ union tcp_listen_epoll_ref {
|
||||
* @fwd_out: Port forwarding configuration for outbound packets
|
||||
* @timer_run: Timestamp of most recent timer run
|
||||
* @pipe_size: Size of pipes for spliced connections
|
||||
+ * @inactivity_run: Time we last scanned for inactive connections
|
||||
*/
|
||||
struct tcp_ctx {
|
||||
struct fwd_ports fwd_in;
|
||||
struct fwd_ports fwd_out;
|
||||
struct timespec timer_run;
|
||||
size_t pipe_size;
|
||||
+ time_t inactivity_run;
|
||||
};
|
||||
|
||||
#endif /* TCP_H */
|
||||
diff --git a/tcp_conn.h b/tcp_conn.h
|
||||
index 35d813d..93f9440 100644
|
||||
--- a/tcp_conn.h
|
||||
+++ b/tcp_conn.h
|
||||
@@ -17,6 +17,7 @@
|
||||
* @ws_from_tap: Window scaling factor advertised from tap/guest
|
||||
* @ws_to_tap: Window scaling factor advertised to tap/guest
|
||||
* @tap_mss: MSS advertised by tap/guest, rounded to 2 ^ TCP_MSS_BITS
|
||||
+ * @inactive: No activity within the current INACTIVITY_INTERVAL
|
||||
* @sock: Socket descriptor number
|
||||
* @events: Connection events, implying connection states
|
||||
* @listening_sock: Listening socket this socket was accept()ed from, or -1
|
||||
@@ -52,6 +53,8 @@ struct tcp_tap_conn {
|
||||
#define MSS_SET(conn, mss) (conn->tap_mss = (mss >> (16 - TCP_MSS_BITS)))
|
||||
#define MSS_GET(conn) (conn->tap_mss << (16 - TCP_MSS_BITS))
|
||||
|
||||
+ bool inactive :1;
|
||||
+
|
||||
int sock :FD_REF_BITS;
|
||||
|
||||
uint8_t events;
|
||||
--
|
||||
2.47.1
|
||||
|
||||
@ -0,0 +1,66 @@
|
||||
From d2f7c36df97e287e2c665d4caedf1137755bfd54 Mon Sep 17 00:00:00 2001
|
||||
From: David Gibson <david@gibson.dropbear.id.au>
|
||||
Date: Wed, 4 Feb 2026 21:41:36 +1000
|
||||
Subject: [PATCH 7/8] tcp: Extend tcp_send_flag() to send TCP keepalive
|
||||
segments
|
||||
|
||||
TCP keepalives aren't technically a flag, but they are a zero-data segment
|
||||
so they can be generated with only a small modification to
|
||||
tcp_{buf,vu}_send_flag(). Implement this, using a new "pseudo-flag"
|
||||
value (similar to DUP_ACK), KEEPALIVE.
|
||||
|
||||
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
|
||||
[sbrivio: Fix trivial merge conflict with 812cdb802c6e]
|
||||
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
|
||||
(cherry picked from commit a681e44ec60179567fb10f34351d7dfdbd2e7c7e)
|
||||
---
|
||||
tcp_buf.c | 4 ++++
|
||||
tcp_internal.h | 2 ++
|
||||
tcp_vu.c | 3 +++
|
||||
3 files changed, 9 insertions(+)
|
||||
|
||||
diff --git a/tcp_buf.c b/tcp_buf.c
|
||||
index 0530563..a324eee 100644
|
||||
--- a/tcp_buf.c
|
||||
+++ b/tcp_buf.c
|
||||
@@ -212,6 +212,10 @@ int tcp_buf_send_flag(const struct ctx *c, struct tcp_tap_conn *conn, int flags)
|
||||
tcp_payload_used++;
|
||||
l4len = optlen + sizeof(struct tcphdr);
|
||||
iov[TCP_IOV_PAYLOAD].iov_len = l4len;
|
||||
+
|
||||
+ if (flags & KEEPALIVE)
|
||||
+ seq--;
|
||||
+
|
||||
tcp_l2_buf_fill_headers(conn, iov, NULL, seq, false);
|
||||
|
||||
if (flags & DUP_ACK) {
|
||||
diff --git a/tcp_internal.h b/tcp_internal.h
|
||||
index 36c6533..371a5f5 100644
|
||||
--- a/tcp_internal.h
|
||||
+++ b/tcp_internal.h
|
||||
@@ -30,6 +30,8 @@
|
||||
|
||||
/* Flags for internal usage */
|
||||
#define DUP_ACK (1 << 5)
|
||||
+#define KEEPALIVE (1 << 6)
|
||||
+
|
||||
#define OPT_EOL 0
|
||||
#define OPT_NOP 1
|
||||
#define OPT_MSS 2
|
||||
diff --git a/tcp_vu.c b/tcp_vu.c
|
||||
index 57587cc..cb3f80f 100644
|
||||
--- a/tcp_vu.c
|
||||
+++ b/tcp_vu.c
|
||||
@@ -135,6 +135,9 @@ int tcp_vu_send_flag(const struct ctx *c, struct tcp_tap_conn *conn, int flags)
|
||||
flags_elem[0].in_sg[0].iov_len = hdrlen + optlen;
|
||||
payload = IOV_TAIL(flags_elem[0].in_sg, 1, hdrlen);
|
||||
|
||||
+ if (flags & KEEPALIVE)
|
||||
+ seq--;
|
||||
+
|
||||
tcp_fill_headers(conn, NULL, ip4h, ip6h, th, &payload,
|
||||
NULL, seq, !*c->pcap);
|
||||
|
||||
--
|
||||
2.47.1
|
||||
|
||||
161
0008-tcp-Send-TCP-keepalive-segments-after-a-period-of-ta.patch
Normal file
161
0008-tcp-Send-TCP-keepalive-segments-after-a-period-of-ta.patch
Normal file
@ -0,0 +1,161 @@
|
||||
From e349a1b2416f220a8cf518c88bec8b6a7dea201d Mon Sep 17 00:00:00 2001
|
||||
From: David Gibson <david@gibson.dropbear.id.au>
|
||||
Date: Wed, 4 Feb 2026 21:41:37 +1000
|
||||
Subject: [PATCH 8/8] tcp: Send TCP keepalive segments after a period of
|
||||
tap-side inactivity
|
||||
|
||||
There are several circumstances in which a live, but idle TCP connection
|
||||
can be forgotten by a guest, with no "on the wire" indication that this has
|
||||
happened. The most obvious is if the guest abruptly reboots. A more
|
||||
subtle case can happen with a half-closed connection, specifically one
|
||||
in FIN_WAIT_2 state on the guest. A connection can, legitimately, remain
|
||||
in this state indefinitely. If however, a socket in this state is closed
|
||||
by userspace, Linux at least will remove the kernel socket after 60s
|
||||
(or as configured in the net.ipv4.tcp_fin_timeout sysctl).
|
||||
|
||||
Because there's no on the wire indication in these cases, passt will
|
||||
pointlessly retain the connection in its flow table, at least until it is
|
||||
removed by the inactivity timeout after several hours.
|
||||
|
||||
To avoid keeping connections around for so long in this state, add
|
||||
functionality to periodically send TCP keepalive segments to the guest if
|
||||
we've seen no activity on the tap interface. If the guest is no longer
|
||||
aware of the connection, it should respond with an RST which will let
|
||||
passt remove the stale entry.
|
||||
|
||||
To do this we use a method similar to the inactivity timeout - a 1-bit
|
||||
page replacement / clock algorithm, but with a shorter interval, and only
|
||||
checking for tap side activity. Currently we use a 300s interval, meaning
|
||||
we'll send a keepalive after 5-10 minutes of (tap side) inactivity.
|
||||
|
||||
Link: https://bugs.passt.top/show_bug.cgi?id=179
|
||||
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
|
||||
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
|
||||
(cherry picked from commit d2f7c21cfb949f2b1587b9475917efdd6ac549fd)
|
||||
---
|
||||
tcp.c | 39 +++++++++++++++++++++++++++++++++++++++
|
||||
tcp.h | 2 ++
|
||||
tcp_conn.h | 2 ++
|
||||
3 files changed, 43 insertions(+)
|
||||
|
||||
diff --git a/tcp.c b/tcp.c
|
||||
index 394fc35..8ea7794 100644
|
||||
--- a/tcp.c
|
||||
+++ b/tcp.c
|
||||
@@ -209,6 +209,12 @@
|
||||
* keepalives) will be removed between INACTIVITY_INTERVAL s and
|
||||
* 2*INACTIVITY_INTERVAL s after the last activity.
|
||||
*
|
||||
+ * - KEEPALIVE_INTERVAL: if a connection has had no tap-side activity for an
|
||||
+ * entire interval, send a tap-side keepalive. If the endpoint is no longer
|
||||
+ * aware of the connection (due to a reboot, or a kernel timeout in FIN_WAIT_2
|
||||
+ * state) that should trigger an RST, so we won't keep track of connections
|
||||
+ * that the guest endpoint no longer cares about.
|
||||
+ *
|
||||
* Summary of data flows (with ESTABLISHED event)
|
||||
* ----------------------------------------------
|
||||
*
|
||||
@@ -339,6 +345,7 @@ enum {
|
||||
#define FIN_TIMEOUT 60
|
||||
|
||||
#define INACTIVITY_INTERVAL 7200 /* s */
|
||||
+#define KEEPALIVE_INTERVAL 30 /* s */
|
||||
|
||||
#define LOW_RTT_TABLE_SIZE 8
|
||||
#define LOW_RTT_THRESHOLD 10 /* us */
|
||||
@@ -2009,6 +2016,7 @@ int tcp_tap_handler(const struct ctx *c, uint8_t pif, sa_family_t af,
|
||||
}
|
||||
|
||||
conn->inactive = false;
|
||||
+ conn->tap_inactive = false;
|
||||
|
||||
if (th->ack && !(conn->events & ESTABLISHED))
|
||||
tcp_update_seqack_from_tap(c, conn, ntohl(th->ack_seq));
|
||||
@@ -2727,6 +2735,36 @@ static int tcp_port_rebind_outbound(void *arg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
+/**
|
||||
+ * tcp_keepalive() - Send keepalives for connections which need it
|
||||
+ * @: Execution context
|
||||
+ */
|
||||
+static void tcp_keepalive(struct ctx *c, const struct timespec *now)
|
||||
+{
|
||||
+ union flow *flow;
|
||||
+
|
||||
+ if (now->tv_sec - c->tcp.keepalive_run < KEEPALIVE_INTERVAL)
|
||||
+ return;
|
||||
+
|
||||
+ c->tcp.keepalive_run = now->tv_sec;
|
||||
+
|
||||
+ flow_foreach(flow) {
|
||||
+ struct tcp_tap_conn *conn = &flow->tcp;
|
||||
+
|
||||
+ if (flow->f.type != FLOW_TCP)
|
||||
+ continue;
|
||||
+
|
||||
+ if (conn->tap_inactive) {
|
||||
+ flow_dbg(conn, "No tap activity for least %us, send keepalive",
|
||||
+ KEEPALIVE_INTERVAL);
|
||||
+ tcp_send_flag(c, conn, KEEPALIVE);
|
||||
+ }
|
||||
+
|
||||
+ /* Ready to check fot next interval */
|
||||
+ conn->tap_inactive = true;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
/**
|
||||
* tcp_inactivity() - Scan for and close long-inactive connections
|
||||
* @: Execution context
|
||||
@@ -2784,6 +2822,7 @@ void tcp_timer(struct ctx *c, const struct timespec *now)
|
||||
if (c->mode == MODE_PASTA)
|
||||
tcp_splice_refill(c);
|
||||
|
||||
+ tcp_keepalive(c, now);
|
||||
tcp_inactivity(c, now);
|
||||
}
|
||||
|
||||
diff --git a/tcp.h b/tcp.h
|
||||
index b75e9a7..7433f15 100644
|
||||
--- a/tcp.h
|
||||
+++ b/tcp.h
|
||||
@@ -59,6 +59,7 @@ union tcp_listen_epoll_ref {
|
||||
* @fwd_out: Port forwarding configuration for outbound packets
|
||||
* @timer_run: Timestamp of most recent timer run
|
||||
* @pipe_size: Size of pipes for spliced connections
|
||||
+ * @keepalive_run: Time we last issued tap-side keepalives
|
||||
* @inactivity_run: Time we last scanned for inactive connections
|
||||
*/
|
||||
struct tcp_ctx {
|
||||
@@ -66,6 +67,7 @@ struct tcp_ctx {
|
||||
struct fwd_ports fwd_out;
|
||||
struct timespec timer_run;
|
||||
size_t pipe_size;
|
||||
+ time_t keepalive_run;
|
||||
time_t inactivity_run;
|
||||
};
|
||||
|
||||
diff --git a/tcp_conn.h b/tcp_conn.h
|
||||
index 93f9440..23ef5bd 100644
|
||||
--- a/tcp_conn.h
|
||||
+++ b/tcp_conn.h
|
||||
@@ -17,6 +17,7 @@
|
||||
* @ws_from_tap: Window scaling factor advertised from tap/guest
|
||||
* @ws_to_tap: Window scaling factor advertised to tap/guest
|
||||
* @tap_mss: MSS advertised by tap/guest, rounded to 2 ^ TCP_MSS_BITS
|
||||
+ * @tapinactive: No tao activity within the current KEEPALIVE_INTERVAL
|
||||
* @inactive: No activity within the current INACTIVITY_INTERVAL
|
||||
* @sock: Socket descriptor number
|
||||
* @events: Connection events, implying connection states
|
||||
@@ -53,6 +54,7 @@ struct tcp_tap_conn {
|
||||
#define MSS_SET(conn, mss) (conn->tap_mss = (mss >> (16 - TCP_MSS_BITS)))
|
||||
#define MSS_GET(conn) (conn->tap_mss << (16 - TCP_MSS_BITS))
|
||||
|
||||
+ bool tap_inactive :1;
|
||||
bool inactive :1;
|
||||
|
||||
int sock :FD_REF_BITS;
|
||||
--
|
||||
2.47.1
|
||||
|
||||
10
passt.spec
10
passt.spec
@ -12,7 +12,7 @@
|
||||
|
||||
Name: passt
|
||||
Version: 0^20250512.g8ec1341
|
||||
Release: 4%{?dist}
|
||||
Release: 5%{?dist}
|
||||
Summary: User-mode networking daemons for virtual machines and namespaces
|
||||
License: GPL-2.0-or-later AND BSD-3-Clause
|
||||
Group: System Environment/Daemons
|
||||
@ -22,6 +22,11 @@ Source: https://passt.top/passt/snapshot/passt-%{git_hash}.tar.xz
|
||||
Patch1: 0001-treewide-By-default-don-t-quit-source-after-migratio.patch
|
||||
Patch2: 0002-tcp-Cast-operands-of-sequence-comparison-macros-to-u.patch
|
||||
Patch3: 0003-tcp-Don-t-consider-FIN-flags-with-mismatching-sequen.patch
|
||||
Patch4: 0004-tcp-Properly-remove-sockets-from-epoll-loop-when-con.patch
|
||||
Patch5: 0005-tcp-Remove-non-working-activity-timeout-mechanism.patch
|
||||
Patch6: 0006-tcp-Re-introduce-inactivity-timeouts-based-on-a-cloc.patch
|
||||
Patch7: 0007-tcp-Extend-tcp_send_flag-to-send-TCP-keepalive-segme.patch
|
||||
Patch8: 0008-tcp-Send-TCP-keepalive-segments-after-a-period-of-ta.patch
|
||||
|
||||
BuildRequires: gcc, make, git, checkpolicy, selinux-policy-devel
|
||||
Requires: (%{name}-selinux = %{version}-%{release} if selinux-policy-%{selinuxtype})
|
||||
@ -134,6 +139,9 @@ fi
|
||||
%{_datadir}/selinux/packages/%{selinuxtype}/passt-repair.pp
|
||||
|
||||
%changelog
|
||||
* Wed Apr 22 2026 Stefano Brivio <sbrivio@redhat.com> - 0^20250512.g8ec1341-5
|
||||
- Resolves: RHEL-169974 RHEL-169634
|
||||
|
||||
* Thu Oct 23 2025 Stefano Brivio <sbrivio@redhat.com> - 0^20250512.g8ec1341-4
|
||||
- Resolves: RHEL-123415 RHEL-123424
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user