public inbox for passt-dev@passt.top
 help / color / mirror / code / Atom feed
From: David Gibson <david@gibson.dropbear.id.au>
To: Stefano Brivio <sbrivio@redhat.com>, passt-dev@passt.top
Cc: David Gibson <david@gibson.dropbear.id.au>
Subject: [PATCH 5/6] fwd: Split forwarding table from port scanning state
Date: Tue, 10 Mar 2026 15:16:04 +1100	[thread overview]
Message-ID: <20260310041605.1322552-6-david@gibson.dropbear.id.au> (raw)
In-Reply-To: <20260310041605.1322552-1-david@gibson.dropbear.id.au>

For hsitorical reasons, struct fwd_ports contained both the new forwarding
table and some older state related to port / scanning auto-forwarding
detection.  They are related, but keeping them together prevents some
future reworks we want to do.

Separate them into struct fwd_table (for the table) and struct fwd_scan
for the scanning state.  Adjusting all the users makes for a logically
straightforward, but fairly extensive patch.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 conf.c |  12 +++---
 flow.c |   5 ++-
 fwd.c  | 114 +++++++++++++++++++++++++++++++--------------------------
 fwd.h  |  38 +++++++++++--------
 tcp.c  |   5 ++-
 tcp.h  |  12 ++++--
 udp.c  |   5 ++-
 udp.h  |  12 ++++--
 8 files changed, 116 insertions(+), 87 deletions(-)

diff --git a/conf.c b/conf.c
index c436b88e..80d8106d 100644
--- a/conf.c
+++ b/conf.c
@@ -130,7 +130,7 @@ static int parse_port_range(const char *s, char **endptr,
  * @c:		Execution context
  * @optname:	Short option name, t, T, u, or U
  * @optarg:	Option argument (port specification)
- * @fwd:	Pointer to @fwd_ports to be updated
+ * @fwd:	Forwarding table to be updated
  * @addr:	Listening address
  * @ifname:	Listening interface
  * @first:	First port to forward
@@ -140,7 +140,7 @@ static int parse_port_range(const char *s, char **endptr,
  * @flags:	Flags for forwarding entries
  */
 static void conf_ports_range_except(const struct ctx *c, char optname,
-				    const char *optarg, struct fwd_ports *fwd,
+				    const char *optarg, struct fwd_table *fwd,
 				    const union inany_addr *addr,
 				    const char *ifname,
 				    uint16_t first, uint16_t last,
@@ -215,11 +215,11 @@ enum fwd_mode {
  * @c:		Execution context
  * @optname:	Short option name, t, T, u, or U
  * @optarg:	Option argument (port specification)
- * @fwd:	Pointer to @fwd_ports to be updated
+ * @fwd:	Forwarding table to be updated
  * @mode:	Overall port forwarding mode (updated)
  */
 static void conf_ports(const struct ctx *c, char optname, const char *optarg,
-		       struct fwd_ports *fwd, enum fwd_mode *mode)
+		       struct fwd_table *fwd, enum fwd_mode *mode)
 {
 	union inany_addr addr_buf = inany_any6, *addr = &addr_buf;
 	char buf[BUFSIZ], *spec, *ifname = NULL, *p;
@@ -1245,7 +1245,7 @@ dns6:
 		info("Outbound TCP forwarding:");
 		fwd_rules_print(&c->tcp.fwd_out);
 		info("Outbound UDP forwarding:");
-		fwd_rules_print(&c->udp.fwd_out);
+		fwd_rules_print(&c->tcp.fwd_out);
 	}
 }
 
@@ -2116,7 +2116,7 @@ void conf(struct ctx *c, int argc, char **argv)
 
 		if (name == 't') {
 			conf_ports(c, name, optarg,
-				   &c->tcp.fwd_in, &tcp_in_mode);
+				&c->tcp.fwd_in, &tcp_in_mode);
 		} else if (name == 'u') {
 			conf_ports(c, name, optarg,
 				   &c->udp.fwd_in, &udp_in_mode);
diff --git a/flow.c b/flow.c
index 5207143d..4b07697e 100644
--- a/flow.c
+++ b/flow.c
@@ -505,7 +505,7 @@ struct flowside *flow_target(const struct ctx *c, union flow *flow,
 	const struct flowside *ini = &f->side[INISIDE];
 	struct flowside *tgt = &f->side[TGTSIDE];
 	const struct fwd_rule *rule = NULL;
-	const struct fwd_ports *fwd;
+	const struct fwd_table *fwd;
 	uint8_t tgtpif = PIF_NONE;
 
 	ASSERT(flow_new_entry == flow && f->state == FLOW_STATE_INI);
@@ -1023,7 +1023,8 @@ static int flow_migrate_source_rollback(struct ctx *c, unsigned bound, int ret)
 
 	debug("...roll back migration");
 
-	if (fwd_listen_sync(c, &c->tcp.fwd_in, PIF_HOST, IPPROTO_TCP) < 0)
+	if (fwd_listen_sync(c, &c->tcp.fwd_in, &c->tcp.scan_in,
+			    PIF_HOST, IPPROTO_TCP) < 0)
 		die("Failed to re-establish listening sockets");
 
 	foreach_established_tcp_flow(flow) {
diff --git a/fwd.c b/fwd.c
index 9e455094..3e0e1063 100644
--- a/fwd.c
+++ b/fwd.c
@@ -341,7 +341,7 @@ bool fwd_port_is_ephemeral(in_port_t port)
  * @last:	Last port number to forward
  * @to:		First port of target port range to map to
  */
-void fwd_rule_add(struct fwd_ports *fwd, uint8_t flags,
+void fwd_rule_add(struct fwd_table *fwd, uint8_t flags,
 		  const union inany_addr *addr, const char *ifname,
 		  in_port_t first, in_port_t last, in_port_t to)
 {
@@ -431,7 +431,7 @@ static bool fwd_rule_match(const struct fwd_rule *rule,
  *
  * Returns: first matching rule, or NULL if there is none
  */
-const struct fwd_rule *fwd_rule_search(const struct fwd_ports *fwd,
+const struct fwd_rule *fwd_rule_search(const struct fwd_table *fwd,
 				       const struct flowside *ini,
 				       int hint)
 {
@@ -464,7 +464,7 @@ const struct fwd_rule *fwd_rule_search(const struct fwd_ports *fwd,
  * fwd_rules_print() - Print forwarding rules for debugging
  * @fwd:	Table to print
  */
-void fwd_rules_print(const struct fwd_ports *fwd)
+void fwd_rules_print(const struct fwd_table *fwd)
 {
 	unsigned i;
 
@@ -504,8 +504,8 @@ void fwd_rules_print(const struct fwd_ports *fwd)
  *
  * Return: 0 on success, -1 on failure
  */
-static int fwd_sync_one(const struct ctx *c,
-			const struct fwd_ports *fwd, const struct fwd_rule *rule,
+static int fwd_sync_one(const struct ctx *c, const struct fwd_table *fwd,
+			const struct fwd_rule *rule,
 			uint8_t pif, uint8_t proto, const uint8_t *scanmap)
 {
 	const union inany_addr *addr = fwd_rule_addr(rule);
@@ -582,7 +582,7 @@ static int fwd_sync_one(const struct ctx *c,
 
 /** struct fwd_listen_args - arguments for fwd_listen_init_()
  * @c:		Execution context
- * @fwd:	Forwarding information
+ * @fwd:	Forwarding table
  * @scanmap:	Bitmap of ports to auto-forward
  * @pif:	Interface to create listening sockets for
  * @proto:	Protocol
@@ -590,7 +590,7 @@ static int fwd_sync_one(const struct ctx *c,
  */
 struct fwd_listen_args {
 	const struct ctx *c;
-	const struct fwd_ports *fwd;
+	const struct fwd_table *fwd;
 	const uint8_t *scanmap;
 	uint8_t pif;
 	uint8_t proto;
@@ -612,7 +612,7 @@ static int fwd_listen_sync_(void *arg)
 
 	for (i = 0; i < a->fwd->count; i++) {
 		a->ret = fwd_sync_one(a->c, a->fwd, &a->fwd->rules[i],
-				      a->pif, a->proto, a->fwd->map);
+				      a->pif, a->proto, a->scanmap);
 		if (a->ret < 0)
 			break;
 	}
@@ -623,16 +623,18 @@ static int fwd_listen_sync_(void *arg)
 /** fwd_listen_sync() - Call fwd_listen_sync_() in correct namespace
  * @c:		Execution context
  * @fwd:	Forwarding information
+ * @scan:	Scanning state for direction and protocol
  * @pif:	Interface to create listening sockets for
  * @proto:	Protocol
  *
  * Return: 0 on success, -1 on failure
  */
-int fwd_listen_sync(const struct ctx *c, const struct fwd_ports *fwd,
-		    uint8_t pif, uint8_t proto)
+int fwd_listen_sync(const struct ctx *c, const struct fwd_table *fwd,
+		    const struct fwd_scan *scan, uint8_t pif, uint8_t proto)
 {
 	struct fwd_listen_args a = {
-		.c = c, .fwd = fwd, .pif = pif, .proto = proto,
+		.c = c, .fwd = fwd, .scanmap = scan->map,
+		.pif = pif, .proto = proto,
 	};
 
 	if (pif == PIF_SPLICE)
@@ -652,7 +654,7 @@ int fwd_listen_sync(const struct ctx *c, const struct fwd_ports *fwd,
 /** fwd_listen_close() - Close all listening sockets
  * @fwd:	Forwarding information
  */
-void fwd_listen_close(const struct fwd_ports *fwd)
+void fwd_listen_close(const struct fwd_table *fwd)
 {
 	unsigned i;
 
@@ -716,7 +718,7 @@ static void procfs_scan_listen(int fd, unsigned int lstate, uint8_t *map)
  * has_scan_rules() - Does the given table have any FWD_SCAN rules?
  * @fwd:	Forwarding table
  */
-static bool has_scan_rules(const struct fwd_ports *fwd)
+static bool has_scan_rules(const struct fwd_table *fwd)
 {
 	unsigned i;
 
@@ -729,46 +731,50 @@ static bool has_scan_rules(const struct fwd_ports *fwd)
 
 /**
  * fwd_scan_ports_tcp() - Scan /proc to update TCP forwarding map
- * @fwd:	Forwarding information to update
+ * @fwd:	Forwarding table
+ * @scan:	Scanning state to update
  * @exclude:	Ports to _not_ forward
  */
-static void fwd_scan_ports_tcp(struct fwd_ports *fwd, const uint8_t *exclude)
+static void fwd_scan_ports_tcp(const struct fwd_table *fwd,
+			       struct fwd_scan *scan, const uint8_t *exclude)
 {
 	if (!has_scan_rules(fwd))
 		return;
 
-	memset(fwd->map, 0, PORT_BITMAP_SIZE);
-	procfs_scan_listen(fwd->scan4, TCP_LISTEN, fwd->map);
-	procfs_scan_listen(fwd->scan6, TCP_LISTEN, fwd->map);
-	bitmap_and_not(fwd->map, PORT_BITMAP_SIZE, fwd->map, exclude);
+	memset(scan->map, 0, PORT_BITMAP_SIZE);
+	procfs_scan_listen(scan->scan4, TCP_LISTEN, scan->map);
+	procfs_scan_listen(scan->scan6, TCP_LISTEN, scan->map);
+	bitmap_and_not(scan->map, PORT_BITMAP_SIZE, scan->map, exclude);
 }
 
 /**
  * fwd_scan_ports_udp() - Scan /proc to update UDP forwarding map
- * @fwd:	Forwarding information to update
- * @tcp_fwd:	Corresponding TCP forwarding information
+ * @fwd:	Forwarding table
+ * @scan:	Scanning state to update
+ * @tcp_scan:	Corresponding TCP scanning state
  * @exclude:	Ports to _not_ forward
  */
-static void fwd_scan_ports_udp(struct fwd_ports *fwd,
-			       const struct fwd_ports *tcp_fwd,
+static void fwd_scan_ports_udp(const struct fwd_table *fwd,
+			       struct fwd_scan *scan,
+			       const struct fwd_scan *tcp_scan,
 			       const uint8_t *exclude)
 {
 	if (!has_scan_rules(fwd))
 		return;
 
-	memset(fwd->map, 0, PORT_BITMAP_SIZE);
-	procfs_scan_listen(fwd->scan4, UDP_LISTEN, fwd->map);
-	procfs_scan_listen(fwd->scan6, UDP_LISTEN, fwd->map);
+	memset(scan->map, 0, PORT_BITMAP_SIZE);
+	procfs_scan_listen(scan->scan4, UDP_LISTEN, scan->map);
+	procfs_scan_listen(scan->scan6, UDP_LISTEN, scan->map);
 
 	/* Also forward UDP ports with the same numbers as bound TCP ports.
 	 * This is useful for a handful of protocols (e.g. iperf3) where a TCP
 	 * control port is used to set up transfers on a corresponding UDP
 	 * port.
 	 */
-	procfs_scan_listen(tcp_fwd->scan4, TCP_LISTEN, fwd->map);
-	procfs_scan_listen(tcp_fwd->scan6, TCP_LISTEN, fwd->map);
+	procfs_scan_listen(tcp_scan->scan4, TCP_LISTEN, scan->map);
+	procfs_scan_listen(tcp_scan->scan6, TCP_LISTEN, scan->map);
 
-	bitmap_and_not(fwd->map, PORT_BITMAP_SIZE, fwd->map, exclude);
+	bitmap_and_not(scan->map, PORT_BITMAP_SIZE, scan->map, exclude);
 }
 
 /**
@@ -776,7 +782,7 @@ static void fwd_scan_ports_udp(struct fwd_ports *fwd,
  * @map:	Bitmap to populate
  * @fwd:	Forwarding table to consider
  */
-static void current_listen_map(uint8_t *map, const struct fwd_ports *fwd)
+static void current_listen_map(uint8_t *map, const struct fwd_table *fwd)
 {
 	unsigned i;
 
@@ -807,10 +813,12 @@ static void fwd_scan_ports(struct ctx *c)
 	current_listen_map(excl_udp_out, &c->udp.fwd_in);
 	current_listen_map(excl_udp_in, &c->udp.fwd_out);
 
-	fwd_scan_ports_tcp(&c->tcp.fwd_out, excl_tcp_out);
-	fwd_scan_ports_tcp(&c->tcp.fwd_in, excl_tcp_in);
-	fwd_scan_ports_udp(&c->udp.fwd_out, &c->tcp.fwd_out, excl_udp_out);
-	fwd_scan_ports_udp(&c->udp.fwd_in, &c->tcp.fwd_in, excl_udp_in);
+	fwd_scan_ports_tcp(&c->tcp.fwd_out, &c->tcp.scan_out, excl_tcp_out);
+	fwd_scan_ports_tcp(&c->tcp.fwd_in, &c->tcp.scan_in, excl_tcp_in);
+	fwd_scan_ports_udp(&c->udp.fwd_out, &c->udp.scan_out,
+			   &c->tcp.scan_out, excl_udp_out);
+	fwd_scan_ports_udp(&c->udp.fwd_in, &c->udp.scan_in,
+			   &c->tcp.scan_in, excl_udp_in);
 }
 
 /**
@@ -821,26 +829,26 @@ void fwd_scan_ports_init(struct ctx *c)
 {
 	const int flags = O_RDONLY | O_CLOEXEC;
 
-	c->tcp.fwd_in.scan4 = c->tcp.fwd_in.scan6 = -1;
-	c->tcp.fwd_out.scan4 = c->tcp.fwd_out.scan6 = -1;
-	c->udp.fwd_in.scan4 = c->udp.fwd_in.scan6 = -1;
-	c->udp.fwd_out.scan4 = c->udp.fwd_out.scan6 = -1;
+	c->tcp.scan_in.scan4 = c->tcp.scan_in.scan6 = -1;
+	c->tcp.scan_out.scan4 = c->tcp.scan_out.scan6 = -1;
+	c->udp.scan_in.scan4 = c->udp.scan_in.scan6 = -1;
+	c->udp.scan_out.scan4 = c->udp.scan_out.scan6 = -1;
 
 	if (has_scan_rules(&c->tcp.fwd_in)) {
-		c->tcp.fwd_in.scan4 = open_in_ns(c, "/proc/net/tcp", flags);
-		c->tcp.fwd_in.scan6 = open_in_ns(c, "/proc/net/tcp6", flags);
+		c->tcp.scan_in.scan4 = open_in_ns(c, "/proc/net/tcp", flags);
+		c->tcp.scan_in.scan6 = open_in_ns(c, "/proc/net/tcp6", flags);
 	}
 	if (has_scan_rules(&c->udp.fwd_in)) {
-		c->udp.fwd_in.scan4 = open_in_ns(c, "/proc/net/udp", flags);
-		c->udp.fwd_in.scan6 = open_in_ns(c, "/proc/net/udp6", flags);
+		c->udp.scan_in.scan4 = open_in_ns(c, "/proc/net/udp", flags);
+		c->udp.scan_in.scan6 = open_in_ns(c, "/proc/net/udp6", flags);
 	}
-	if (has_scan_rules(&c->tcp.fwd_out)) {
-		c->tcp.fwd_out.scan4 = open("/proc/net/tcp", flags);
-		c->tcp.fwd_out.scan6 = open("/proc/net/tcp6", flags);
+	if (has_scan_rules(&c->udp.fwd_out)) {
+		c->tcp.scan_out.scan4 = open("/proc/net/tcp", flags);
+		c->tcp.scan_out.scan6 = open("/proc/net/tcp6", flags);
 	}
 	if (has_scan_rules(&c->udp.fwd_out)) {
-		c->udp.fwd_out.scan4 = open("/proc/net/udp", flags);
-		c->udp.fwd_out.scan6 = open("/proc/net/udp6", flags);
+		c->udp.scan_out.scan4 = open("/proc/net/udp", flags);
+		c->udp.scan_out.scan6 = open("/proc/net/udp6", flags);
 	}
 	fwd_scan_ports(c);
 }
@@ -866,12 +874,16 @@ void fwd_scan_ports_timer(struct ctx *c, const struct timespec *now)
 	fwd_scan_ports(c);
 
 	if (!c->no_tcp) {
-		fwd_listen_sync(c, &c->tcp.fwd_in, PIF_HOST, IPPROTO_TCP);
-		fwd_listen_sync(c, &c->tcp.fwd_out, PIF_SPLICE, IPPROTO_TCP);
+		fwd_listen_sync(c, &c->tcp.fwd_in, &c->tcp.scan_in,
+				PIF_HOST, IPPROTO_TCP);
+		fwd_listen_sync(c, &c->tcp.fwd_out, &c->tcp.scan_out,
+				PIF_SPLICE, IPPROTO_TCP);
 	}
 	if (!c->no_udp) {
-		fwd_listen_sync(c, &c->udp.fwd_in, PIF_HOST, IPPROTO_UDP);
-		fwd_listen_sync(c, &c->udp.fwd_out, PIF_SPLICE, IPPROTO_UDP);
+		fwd_listen_sync(c, &c->udp.fwd_in, &c->udp.scan_in,
+				PIF_HOST, IPPROTO_UDP);
+		fwd_listen_sync(c, &c->udp.fwd_out, &c->udp.scan_out,
+				PIF_SPLICE, IPPROTO_UDP);
 	}
 }
 
diff --git a/fwd.h b/fwd.h
index 6d657ddc..1af13ad4 100644
--- a/fwd.h
+++ b/fwd.h
@@ -68,8 +68,6 @@ struct fwd_listen_ref {
 	unsigned	rule :FWD_RULE_BITS;
 };
 
-#define PORT_BITMAP_SIZE	DIV_ROUND_UP(NUM_PORTS, 8)
-
 /* Maximum number of listening sockets (per pif & protocol)
  *
  * Rationale: This lets us listen on every port for two addresses (which we need
@@ -78,41 +76,49 @@ struct fwd_listen_ref {
 #define MAX_LISTEN_SOCKS	(NUM_PORTS * 3)
 
 /**
- * fwd_ports() - Describes port forwarding for one protocol and direction
- * @scan4:	/proc/net fd to scan for IPv4 ports when in AUTO mode
- * @scan6:	/proc/net fd to scan for IPv6 ports when in AUTO mode
+ * struct fwd_table - Table of forwarding rules (per protocol and ini pif)
  * @count:	Number of forwarding rules
  * @rules:	Array of forwarding rules
- * @map:	Bitmap describing which ports are forwarded
  * @sock_count:	Number of entries used in @socks
  * @socks:	Listening sockets for forwarding
  */
-struct fwd_ports {
-	int scan4;
-	int scan6;
+struct fwd_table {
 	unsigned count;
 	struct fwd_rule rules[MAX_FWD_RULES];
-	uint8_t map[PORT_BITMAP_SIZE];
 	unsigned sock_count;
 	int socks[MAX_LISTEN_SOCKS];
 };
 
+#define PORT_BITMAP_SIZE	DIV_ROUND_UP(NUM_PORTS, 8)
+
+/**
+ * struct fwd_scan - Port scanning state for a protocol+direction
+ * @scan4:	/proc/net fd to scan for IPv4 ports when in AUTO mode
+ * @scan6:	/proc/net fd to scan for IPv6 ports when in AUTO mode
+ * @map:	Bitmap describing which ports are forwarded
+ */
+struct fwd_scan {
+	int scan4;
+	int scan6;
+	uint8_t map[PORT_BITMAP_SIZE];
+};
+
 #define FWD_PORT_SCAN_INTERVAL		1000	/* ms */
 
-void fwd_rule_add(struct fwd_ports *fwd, uint8_t flags,
+void fwd_rule_add(struct fwd_table *fwd, uint8_t flags,
 		  const union inany_addr *addr, const char *ifname,
 		  in_port_t first, in_port_t last, in_port_t to);
-const struct fwd_rule *fwd_rule_search(const struct fwd_ports *fwd,
+const struct fwd_rule *fwd_rule_search(const struct fwd_table *fwd,
 				       const struct flowside *ini,
 				       int hint);
-void fwd_rules_print(const struct fwd_ports *fwd);
+void fwd_rules_print(const struct fwd_table *fwd);
 
 void fwd_scan_ports_init(struct ctx *c);
 void fwd_scan_ports_timer(struct ctx * c, const struct timespec *now);
 
-int fwd_listen_sync(const struct ctx *c, const struct fwd_ports *fwd,
-		    uint8_t pif, uint8_t proto);
-void fwd_listen_close(const struct fwd_ports *fwd);
+int fwd_listen_sync(const struct ctx *c, const struct fwd_table *fwd,
+		    const struct fwd_scan *scan, uint8_t pif, uint8_t proto);
+void fwd_listen_close(const struct fwd_table *fwd);
 
 bool nat_inbound(const struct ctx *c, const union inany_addr *addr,
 		 union inany_addr *translated);
diff --git a/tcp.c b/tcp.c
index a0d7cd86..29355c0c 100644
--- a/tcp.c
+++ b/tcp.c
@@ -2863,11 +2863,12 @@ int tcp_init(struct ctx *c)
 
 	tcp_sock_refill_init(c);
 
-	if (fwd_listen_sync(c, &c->tcp.fwd_in, PIF_HOST, IPPROTO_TCP) < 0)
+	if (fwd_listen_sync(c, &c->tcp.fwd_in, &c->tcp.scan_in,
+			    PIF_HOST, IPPROTO_TCP) < 0)
 		return -1;
 	if (c->mode == MODE_PASTA) {
 		tcp_splice_init(c);
-		if (fwd_listen_sync(c, &c->tcp.fwd_out,
+		if (fwd_listen_sync(c, &c->tcp.fwd_out, &c->tcp.scan_out,
 				    PIF_SPLICE, IPPROTO_TCP) < 0)
 			return -1;
 	}
diff --git a/tcp.h b/tcp.h
index c9455e85..c4f200c1 100644
--- a/tcp.h
+++ b/tcp.h
@@ -38,8 +38,10 @@ extern bool peek_offset_cap;
 
 /**
  * struct tcp_ctx - Execution context for TCP routines
- * @fwd_in:		Port forwarding configuration for inbound packets
- * @fwd_out:		Port forwarding configuration for outbound packets
+ * @fwd_in:		Forwarding table for inbound flows
+ * @scan_in:		Port scanning state for inbound packets
+ * @fwd_out:		Forwarding table for outbound flows
+ * @scan_out:		Port scanning state for outbound packets
  * @timer_run:		Timestamp of most recent timer run
  * @pipe_size:		Size of pipes for spliced connections
  * @rto_max:		Maximum retry timeout (in s)
@@ -49,8 +51,10 @@ extern bool peek_offset_cap;
  * @inactivity_run:	Time we last scanned for inactive connections
  */
 struct tcp_ctx {
-	struct fwd_ports fwd_in;
-	struct fwd_ports fwd_out;
+	struct fwd_table fwd_in;
+	struct fwd_scan scan_in;
+	struct fwd_table fwd_out;
+	struct fwd_scan scan_out;
 	struct timespec timer_run;
 	size_t pipe_size;
 	int rto_max;
diff --git a/udp.c b/udp.c
index 464aa093..ed23ab7c 100644
--- a/udp.c
+++ b/udp.c
@@ -1215,12 +1215,13 @@ int udp_init(struct ctx *c)
 
 	udp_iov_init(c);
 
-	if (fwd_listen_sync(c, &c->udp.fwd_in, PIF_HOST, IPPROTO_UDP) < 0)
+	if (fwd_listen_sync(c, &c->udp.fwd_in, &c->udp.scan_in,
+			    PIF_HOST, IPPROTO_UDP) < 0)
 		return -1;
 
 	if (c->mode == MODE_PASTA) {
 		udp_splice_iov_init();
-		if (fwd_listen_sync(c, &c->udp.fwd_out,
+		if (fwd_listen_sync(c, &c->udp.fwd_out, &c->udp.scan_out,
 				    PIF_SPLICE, IPPROTO_UDP) < 0)
 			return -1;
 	}
diff --git a/udp.h b/udp.h
index 0eca1abe..785133ef 100644
--- a/udp.h
+++ b/udp.h
@@ -26,15 +26,19 @@ void udp_update_l2_buf(const unsigned char *eth_d);
 
 /**
  * struct udp_ctx - Execution context for UDP
- * @fwd_in:		Port forwarding configuration for inbound packets
- * @fwd_out:		Port forwarding configuration for outbound packets
+ * @fwd_in:		Forwarding table for inbound flows
+ * @scan_in:		Port scanning state for inbound packets
+ * @fwd_out:		Forwarding table for outbound flows
+ * @scan_out:		Port scanning state for outbound packets
  * @timer_run:		Timestamp of most recent timer run
  * @timeout:		Timeout for unidirectional flows (in s)
  * @stream_timeout:	Timeout for stream-like flows (in s)
  */
 struct udp_ctx {
-	struct fwd_ports fwd_in;
-	struct fwd_ports fwd_out;
+	struct fwd_table fwd_in;
+	struct fwd_scan scan_in;
+	struct fwd_table fwd_out;
+	struct fwd_scan scan_out;
 	struct timespec timer_run;
 	int timeout;
 	int stream_timeout;
-- 
2.53.0


  parent reply	other threads:[~2026-03-10  4:16 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-03-10  4:15 [PATCH 0/6] Unify TCP and UDP forwarding tables David Gibson
2026-03-10  4:16 ` [PATCH 1/6] conf, fwd: Make overall forwarding mode local to conf path David Gibson
2026-03-10 19:33   ` Stefano Brivio
2026-03-11  1:34     ` David Gibson
2026-03-10  4:16 ` [PATCH 2/6] tcp: Remove stale description of port_to_tap field David Gibson
2026-03-10  4:16 ` [PATCH 3/6] fwd: Don't initialise unused port bitmaps David Gibson
2026-03-10  4:16 ` [PATCH 4/6] Fix misnamed field in struct ctx comments David Gibson
2026-03-10  4:16 ` David Gibson [this message]
2026-03-10  4:16 ` [PATCH 6/6] fwd: Unify TCP and UDP forwarding tables David Gibson
2026-03-10 19:33   ` Stefano Brivio
2026-03-11  1:39     ` 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=20260310041605.1322552-6-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).