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 2/8] tcp, udp, fwd: Run all port scanning from a single timer
Date: Sat, 11 Oct 2025 15:48:21 +1100	[thread overview]
Message-ID: <20251011044827.862757-3-david@gibson.dropbear.id.au> (raw)
In-Reply-To: <20251011044827.862757-1-david@gibson.dropbear.id.au>

With -t auto and similar options we need to periodically scan /proc for
listening ports.  Currently we do this separately for TCP and UDP, from
tcp_timer() and udp_timer().

For upcoming changes (leading eventually to a more general forwarding
table), it's awkward to have these separate.  Move them to a single common
timer.  For now this just calls new tcp_scan_ports() and udp_scan_ports()
functions, but we'll consolidate more thoroughly in later patches.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 fwd.c   | 24 ++++++++++++++++++++++++
 fwd.h   |  3 +++
 passt.c |  7 +++----
 tcp.c   | 33 ++++++++++++++++++++-------------
 tcp.h   |  3 ++-
 udp.c   | 29 ++++++++++++-----------------
 udp.h   |  4 +---
 7 files changed, 65 insertions(+), 38 deletions(-)

diff --git a/fwd.c b/fwd.c
index 250cf564..bd89a94a 100644
--- a/fwd.c
+++ b/fwd.c
@@ -230,6 +230,30 @@ void fwd_scan_ports_init(struct ctx *c)
 	}
 }
 
+/* Last time we scanned for open ports */
+static struct timespec scan_ports_run;
+
+/**
+ * fwd_scan_ports_timer() - Rescan open port information when necessary
+ * @c:		Execution context
+ * @now:	Current (monotonic) time
+ */
+void fwd_scan_ports_timer(struct ctx *c, const struct timespec *now)
+{
+	if (c->mode != MODE_PASTA)
+		return;
+
+	if (timespec_diff_ms(now, &scan_ports_run) < FWD_PORT_SCAN_INTERVAL)
+		return;
+
+	scan_ports_run = *now;
+
+	if (!c->no_tcp)
+		tcp_scan_ports(c);
+	if (!c->no_udp)
+		udp_scan_ports(c);
+}
+
 /**
  * is_dns_flow() - Determine if flow appears to be a DNS request
  * @proto:	Protocol (IP L4 protocol number)
diff --git a/fwd.h b/fwd.h
index 65c7c964..385e5bd8 100644
--- a/fwd.h
+++ b/fwd.h
@@ -42,11 +42,14 @@ struct fwd_ports {
 	in_port_t delta[NUM_PORTS];
 };
 
+#define FWD_PORT_SCAN_INTERVAL		1000	/* ms */
+
 void fwd_scan_ports_tcp(struct fwd_ports *fwd, const struct fwd_ports *rev);
 void fwd_scan_ports_udp(struct fwd_ports *fwd, const struct fwd_ports *rev,
 			const struct fwd_ports *tcp_fwd,
 			const struct fwd_ports *tcp_rev);
 void fwd_scan_ports_init(struct ctx *c);
+void fwd_scan_ports_timer(struct ctx *c, const struct timespec *now);
 
 bool nat_inbound(const struct ctx *c, const union inany_addr *addr,
 		 union inany_addr *translated);
diff --git a/passt.c b/passt.c
index b877659e..28ce5711 100644
--- a/passt.c
+++ b/passt.c
@@ -56,7 +56,7 @@
 
 #define EPOLL_EVENTS		8
 
-#define TIMER_INTERVAL_		MIN(TCP_TIMER_INTERVAL, UDP_TIMER_INTERVAL)
+#define TIMER_INTERVAL_		MIN(TCP_TIMER_INTERVAL, FWD_PORT_SCAN_INTERVAL)
 #define TIMER_INTERVAL		MIN(TIMER_INTERVAL_, FLOW_TIMER_INTERVAL)
 
 char pkt_buf[PKT_BUF_BYTES]	__attribute__ ((aligned(PAGE_SIZE)));
@@ -117,11 +117,10 @@ static void post_handler(struct ctx *c, const struct timespec *now)
 
 	/* NOLINTNEXTLINE(bugprone-branch-clone): intervals can be the same */
 	CALL_PROTO_HANDLER(tcp, TCP);
-	/* NOLINTNEXTLINE(bugprone-branch-clone): intervals can be the same */
-	CALL_PROTO_HANDLER(udp, UDP);
+#undef CALL_PROTO_HANDLER
 
 	flow_defer_handler(c, now);
-#undef CALL_PROTO_HANDLER
+	fwd_scan_ports_timer(c, now);
 
 	if (!c->no_ndp)
 		ndp_timer(c, now);
diff --git a/tcp.c b/tcp.c
index 0f9e9b3f..dbbb00c4 100644
--- a/tcp.c
+++ b/tcp.c
@@ -2869,25 +2869,32 @@ static int tcp_port_rebind_outbound(void *arg)
 }
 
 /**
- * tcp_timer() - Periodic tasks: port detection, closed connections, pool refill
+ * tcp_scan_ports() - Update forwarding maps based on scan of listening ports
  * @c:		Execution context
- * @now:	Current timestamp
  */
-void tcp_timer(struct ctx *c, const struct timespec *now)
+void tcp_scan_ports(struct ctx *c)
 {
-	(void)now;
+	ASSERT(c->mode == MODE_PASTA && !c->no_tcp);
 
-	if (c->mode == MODE_PASTA) {
-		if (c->tcp.fwd_out.mode == FWD_AUTO) {
-			fwd_scan_ports_tcp(&c->tcp.fwd_out, &c->tcp.fwd_in);
-			NS_CALL(tcp_port_rebind_outbound, c);
-		}
+	if (c->tcp.fwd_out.mode == FWD_AUTO) {
+		fwd_scan_ports_tcp(&c->tcp.fwd_out, &c->tcp.fwd_in);
+		NS_CALL(tcp_port_rebind_outbound, c);
+	}
 
-		if (c->tcp.fwd_in.mode == FWD_AUTO) {
-			fwd_scan_ports_tcp(&c->tcp.fwd_in, &c->tcp.fwd_out);
-			tcp_port_rebind(c, false);
-		}
+	if (c->tcp.fwd_in.mode == FWD_AUTO) {
+		fwd_scan_ports_tcp(&c->tcp.fwd_in, &c->tcp.fwd_out);
+		tcp_port_rebind(c, false);
 	}
+}
+
+/**
+ * tcp_timer() - Periodic tasks: port detection, closed connections, pool refill
+ * @c:		Execution context
+ * @now:	Current timestamp
+ */
+void tcp_timer(const struct ctx *c, const struct timespec *now)
+{
+	(void)now;
 
 	tcp_sock_refill_init(c);
 	if (c->mode == MODE_PASTA)
diff --git a/tcp.h b/tcp.h
index 234a8033..43ab0655 100644
--- a/tcp.h
+++ b/tcp.h
@@ -21,7 +21,8 @@ int tcp_tap_handler(const struct ctx *c, uint8_t pif, sa_family_t af,
 int tcp_sock_init(const struct ctx *c, const union inany_addr *addr,
 		  const char *ifname, in_port_t port);
 int tcp_init(struct ctx *c);
-void tcp_timer(struct ctx *c, const struct timespec *now);
+void tcp_scan_ports(struct ctx *c);
+void tcp_timer(const struct ctx *c, const struct timespec *now);
 void tcp_defer_handler(struct ctx *c);
 
 void tcp_update_l2_buf(const unsigned char *eth_d, const unsigned char *eth_s);
diff --git a/udp.c b/udp.c
index 86585b7e..d15f03dc 100644
--- a/udp.c
+++ b/udp.c
@@ -1239,28 +1239,23 @@ static int udp_port_rebind_outbound(void *arg)
 }
 
 /**
- * udp_timer() - Scan activity bitmaps for ports with associated timed events
+ * udp_scan_ports() - Update forwarding maps based on scan of listening ports
  * @c:		Execution context
- * @now:	Current timestamp
  */
-void udp_timer(struct ctx *c, const struct timespec *now)
+void udp_scan_ports(struct ctx *c)
 {
-	(void)now;
-
-	ASSERT(!c->no_udp);
+	ASSERT(c->mode == MODE_PASTA && !c->no_udp);
 
-	if (c->mode == MODE_PASTA) {
-		if (c->udp.fwd_out.mode == FWD_AUTO) {
-			fwd_scan_ports_udp(&c->udp.fwd_out, &c->udp.fwd_in,
-					   &c->tcp.fwd_out, &c->tcp.fwd_in);
-			NS_CALL(udp_port_rebind_outbound, c);
-		}
+	if (c->udp.fwd_out.mode == FWD_AUTO) {
+		fwd_scan_ports_udp(&c->udp.fwd_out, &c->udp.fwd_in,
+				   &c->tcp.fwd_out, &c->tcp.fwd_in);
+		NS_CALL(udp_port_rebind_outbound, c);
+	}
 
-		if (c->udp.fwd_in.mode == FWD_AUTO) {
-			fwd_scan_ports_udp(&c->udp.fwd_in, &c->udp.fwd_out,
-					   &c->tcp.fwd_in, &c->tcp.fwd_out);
-			udp_port_rebind(c, false);
-		}
+	if (c->udp.fwd_in.mode == FWD_AUTO) {
+		fwd_scan_ports_udp(&c->udp.fwd_in, &c->udp.fwd_out,
+				   &c->tcp.fwd_in, &c->tcp.fwd_out);
+		udp_port_rebind(c, false);
 	}
 }
 
diff --git a/udp.h b/udp.h
index 8f8531ad..a6de1f1c 100644
--- a/udp.h
+++ b/udp.h
@@ -6,8 +6,6 @@
 #ifndef UDP_H
 #define UDP_H
 
-#define UDP_TIMER_INTERVAL		1000 /* ms */
-
 void udp_portmap_clear(void);
 void udp_listen_sock_handler(const struct ctx *c, union epoll_ref ref,
 			     uint32_t events, const struct timespec *now);
@@ -20,7 +18,7 @@ int udp_tap_handler(const struct ctx *c, uint8_t pif,
 int udp_sock_init(const struct ctx *c, int ns, const union inany_addr *addr,
 		  const char *ifname, in_port_t port);
 int udp_init(struct ctx *c);
-void udp_timer(struct ctx *c, const struct timespec *now);
+void udp_scan_ports(struct ctx *c);
 void udp_update_l2_buf(const unsigned char *eth_d, const unsigned char *eth_s);
 
 /**
-- 
2.51.0


  parent reply	other threads:[~2025-10-11  4:49 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-10-11  4:48 [PATCH 0/8] RFC: Cleanups to auto port scanning David Gibson
2025-10-11  4:48 ` [PATCH 1/8] icmp: Remove vestiges of ICMP timer David Gibson
2025-10-11  4:48 ` David Gibson [this message]
2025-10-11  4:48 ` [PATCH 3/8] fwd: Consolidate scans (not rebinds) in fwd.c David Gibson
2025-10-11  4:48 ` [PATCH 4/8] fwd: Move port exclusion handling from procfs_scan_listen() to callers David Gibson
2025-10-11  4:48 ` [PATCH 5/8] fwd: Share port scanning logic between init and timer cases David Gibson
2025-10-11  4:48 ` [PATCH 6/8] fwd: Check forwarding mode in fwd_scan_ports_*() rather than caller David Gibson
2025-10-11  4:48 ` [PATCH 7/8] fwd: Update all port maps before applying exclusions David Gibson
2025-10-11  4:48 ` [PATCH 8/8] tcp, udp: Don't exclude ports in {tcp,udp}_port_rebind() 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=20251011044827.862757-3-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).