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
next prev 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).