public inbox for passt-dev@passt.top
 help / color / mirror / code / Atom feed
* [PATCH 0/3] pasta: Implement runtime auto-forwarding for UDP
@ 2023-11-15  5:25 David Gibson
  2023-11-15  5:25 ` [PATCH 1/3] tcp: Use common helper for rebinding inbound and outbound ports David Gibson
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: David Gibson @ 2023-11-15  5:25 UTC (permalink / raw)
  To: Stefano Brivio, passt-dev; +Cc: David Gibson

In "auto" mode port forwarding, we scan for listening TCP ports at
start up, and then every second thereafter.  For UDP, however, we scan
only at start up.

That's documented, but surprising, and there's no real reason for it
to be that way.  Implement periodic scanning for UDP auto forwarding
too.

Link: https://bugs.passt.top/show_bug.cgi?id=45

*** BLURB HERE ***

David Gibson (3):
  tcp: Use common helper for rebinding inbound and outbound ports
  tcp: Simplify away tcp_port_rebind()
  udp,pasta: Periodically scan for ports to automatically forward

 passt.1 |   3 +-
 tcp.c   | 109 +++++++++++++++++++++++---------------------------------
 udp.c   |  74 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 120 insertions(+), 66 deletions(-)

-- 
2.41.0


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH 1/3] tcp: Use common helper for rebinding inbound and outbound ports
  2023-11-15  5:25 [PATCH 0/3] pasta: Implement runtime auto-forwarding for UDP David Gibson
@ 2023-11-15  5:25 ` David Gibson
  2023-11-15  5:25 ` [PATCH 2/3] tcp: Simplify away tcp_port_rebind() David Gibson
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: David Gibson @ 2023-11-15  5:25 UTC (permalink / raw)
  To: Stefano Brivio, passt-dev; +Cc: David Gibson

tcp_port_rebind() has two cases with almost but not quite identical code.
Simplify things a bit by factoring this out into a single parameterised
helper, tcp_port_do_rebind().

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 tcp.c | 92 +++++++++++++++++++++++++++++------------------------------
 1 file changed, 45 insertions(+), 47 deletions(-)

diff --git a/tcp.c b/tcp.c
index f51d27a..6bc040c 100644
--- a/tcp.c
+++ b/tcp.c
@@ -3155,6 +3155,49 @@ int tcp_init(struct ctx *c)
 	return 0;
 }
 
+/**
+ * tcp_port_do_rebind() - Rebind ports to match forward maps
+ * @c:		Execution context
+ * @outbound:	True to remap outbound forwards, otherwise inbound
+ *
+ * Must be called in namespace context if @outbound is true.
+ */
+static void tcp_port_do_rebind(struct ctx *c, bool outbound)
+{
+	const uint8_t *fmap = outbound ? c->tcp.fwd_out.map : c->tcp.fwd_in.map;
+	const uint8_t *rmap = outbound ? c->tcp.fwd_in.map : c->tcp.fwd_out.map;
+	int (*socks)[IP_VERSIONS] = outbound ? tcp_sock_ns : tcp_sock_init_ext;
+	unsigned port;
+
+	for (port = 0; port < NUM_PORTS; port++) {
+		if (!bitmap_isset(fmap, port)) {
+			if (socks[port][V4] >= 0) {
+				close(socks[port][V4]);
+				socks[port][V4] = -1;
+			}
+
+			if (socks[port][V6] >= 0) {
+				close(socks[port][V6]);
+				socks[port][V6] = -1;
+			}
+
+			continue;
+		}
+
+		/* Don't loop back our own ports */
+		if (bitmap_isset(rmap, port))
+			continue;
+
+		if ((c->ifi4 && socks[port][V4] == -1) ||
+		    (c->ifi6 && socks[port][V6] == -1)) {
+			if (outbound)
+				tcp_ns_sock_init(c, port);
+			else
+				tcp_sock_init(c, AF_UNSPEC, NULL, NULL, port);
+		}
+	}
+}
+
 /**
  * struct tcp_port_rebind_arg - Arguments for tcp_port_rebind()
  * @c:			Execution context
@@ -3174,58 +3217,13 @@ struct tcp_port_rebind_arg {
 static int tcp_port_rebind(void *arg)
 {
 	struct tcp_port_rebind_arg *a = (struct tcp_port_rebind_arg *)arg;
-	unsigned port;
 
 	if (a->bind_in_ns) {
 		ns_enter(a->c);
 
-		for (port = 0; port < NUM_PORTS; port++) {
-			if (!bitmap_isset(a->c->tcp.fwd_out.map, port)) {
-				if (tcp_sock_ns[port][V4] >= 0) {
-					close(tcp_sock_ns[port][V4]);
-					tcp_sock_ns[port][V4] = -1;
-				}
-
-				if (tcp_sock_ns[port][V6] >= 0) {
-					close(tcp_sock_ns[port][V6]);
-					tcp_sock_ns[port][V6] = -1;
-				}
-
-				continue;
-			}
-
-			/* Don't loop back our own ports */
-			if (bitmap_isset(a->c->tcp.fwd_in.map, port))
-				continue;
-
-			if ((a->c->ifi4 && tcp_sock_ns[port][V4] == -1) ||
-			    (a->c->ifi6 && tcp_sock_ns[port][V6] == -1))
-				tcp_ns_sock_init(a->c, port);
-		}
+		tcp_port_do_rebind(a->c, true);
 	} else {
-		for (port = 0; port < NUM_PORTS; port++) {
-			if (!bitmap_isset(a->c->tcp.fwd_in.map, port)) {
-				if (tcp_sock_init_ext[port][V4] >= 0) {
-					close(tcp_sock_init_ext[port][V4]);
-					tcp_sock_init_ext[port][V4] = -1;
-				}
-
-				if (tcp_sock_init_ext[port][V6] >= 0) {
-					close(tcp_sock_init_ext[port][V6]);
-					tcp_sock_init_ext[port][V6] = -1;
-				}
-				continue;
-			}
-
-			/* Don't loop back our own ports */
-			if (bitmap_isset(a->c->tcp.fwd_out.map, port))
-				continue;
-
-			if ((a->c->ifi4 && tcp_sock_init_ext[port][V4] == -1) ||
-			    (a->c->ifi6 && tcp_sock_init_ext[port][V6] == -1))
-				tcp_sock_init(a->c, AF_UNSPEC, NULL, NULL,
-					      port);
-		}
+		tcp_port_do_rebind(a->c, false);
 	}
 
 	return 0;
-- 
@@ -3155,6 +3155,49 @@ int tcp_init(struct ctx *c)
 	return 0;
 }
 
+/**
+ * tcp_port_do_rebind() - Rebind ports to match forward maps
+ * @c:		Execution context
+ * @outbound:	True to remap outbound forwards, otherwise inbound
+ *
+ * Must be called in namespace context if @outbound is true.
+ */
+static void tcp_port_do_rebind(struct ctx *c, bool outbound)
+{
+	const uint8_t *fmap = outbound ? c->tcp.fwd_out.map : c->tcp.fwd_in.map;
+	const uint8_t *rmap = outbound ? c->tcp.fwd_in.map : c->tcp.fwd_out.map;
+	int (*socks)[IP_VERSIONS] = outbound ? tcp_sock_ns : tcp_sock_init_ext;
+	unsigned port;
+
+	for (port = 0; port < NUM_PORTS; port++) {
+		if (!bitmap_isset(fmap, port)) {
+			if (socks[port][V4] >= 0) {
+				close(socks[port][V4]);
+				socks[port][V4] = -1;
+			}
+
+			if (socks[port][V6] >= 0) {
+				close(socks[port][V6]);
+				socks[port][V6] = -1;
+			}
+
+			continue;
+		}
+
+		/* Don't loop back our own ports */
+		if (bitmap_isset(rmap, port))
+			continue;
+
+		if ((c->ifi4 && socks[port][V4] == -1) ||
+		    (c->ifi6 && socks[port][V6] == -1)) {
+			if (outbound)
+				tcp_ns_sock_init(c, port);
+			else
+				tcp_sock_init(c, AF_UNSPEC, NULL, NULL, port);
+		}
+	}
+}
+
 /**
  * struct tcp_port_rebind_arg - Arguments for tcp_port_rebind()
  * @c:			Execution context
@@ -3174,58 +3217,13 @@ struct tcp_port_rebind_arg {
 static int tcp_port_rebind(void *arg)
 {
 	struct tcp_port_rebind_arg *a = (struct tcp_port_rebind_arg *)arg;
-	unsigned port;
 
 	if (a->bind_in_ns) {
 		ns_enter(a->c);
 
-		for (port = 0; port < NUM_PORTS; port++) {
-			if (!bitmap_isset(a->c->tcp.fwd_out.map, port)) {
-				if (tcp_sock_ns[port][V4] >= 0) {
-					close(tcp_sock_ns[port][V4]);
-					tcp_sock_ns[port][V4] = -1;
-				}
-
-				if (tcp_sock_ns[port][V6] >= 0) {
-					close(tcp_sock_ns[port][V6]);
-					tcp_sock_ns[port][V6] = -1;
-				}
-
-				continue;
-			}
-
-			/* Don't loop back our own ports */
-			if (bitmap_isset(a->c->tcp.fwd_in.map, port))
-				continue;
-
-			if ((a->c->ifi4 && tcp_sock_ns[port][V4] == -1) ||
-			    (a->c->ifi6 && tcp_sock_ns[port][V6] == -1))
-				tcp_ns_sock_init(a->c, port);
-		}
+		tcp_port_do_rebind(a->c, true);
 	} else {
-		for (port = 0; port < NUM_PORTS; port++) {
-			if (!bitmap_isset(a->c->tcp.fwd_in.map, port)) {
-				if (tcp_sock_init_ext[port][V4] >= 0) {
-					close(tcp_sock_init_ext[port][V4]);
-					tcp_sock_init_ext[port][V4] = -1;
-				}
-
-				if (tcp_sock_init_ext[port][V6] >= 0) {
-					close(tcp_sock_init_ext[port][V6]);
-					tcp_sock_init_ext[port][V6] = -1;
-				}
-				continue;
-			}
-
-			/* Don't loop back our own ports */
-			if (bitmap_isset(a->c->tcp.fwd_out.map, port))
-				continue;
-
-			if ((a->c->ifi4 && tcp_sock_init_ext[port][V4] == -1) ||
-			    (a->c->ifi6 && tcp_sock_init_ext[port][V6] == -1))
-				tcp_sock_init(a->c, AF_UNSPEC, NULL, NULL,
-					      port);
-		}
+		tcp_port_do_rebind(a->c, false);
 	}
 
 	return 0;
-- 
2.41.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 2/3] tcp: Simplify away tcp_port_rebind()
  2023-11-15  5:25 [PATCH 0/3] pasta: Implement runtime auto-forwarding for UDP David Gibson
  2023-11-15  5:25 ` [PATCH 1/3] tcp: Use common helper for rebinding inbound and outbound ports David Gibson
@ 2023-11-15  5:25 ` David Gibson
  2023-11-15  5:25 ` [PATCH 3/3] udp,pasta: Periodically scan for ports to automatically forward David Gibson
  2023-11-19 20:10 ` [PATCH 0/3] pasta: Implement runtime auto-forwarding for UDP Stefano Brivio
  3 siblings, 0 replies; 5+ messages in thread
From: David Gibson @ 2023-11-15  5:25 UTC (permalink / raw)
  To: Stefano Brivio, passt-dev; +Cc: David Gibson

tcp_port_rebind() is desgined to be called from NS_CALL() and has two
disjoint cases: one where it enters the namespace (outbound forwards) and
one where it doesn't (inbound forwards).

We only actually need the NS_CALL() framing for the outbound case, for
inbound we can just call tcp_port_do_rebind() directly.  So simplify
tcp_port_rebind() to tcp_port_rebind_outbound(), allowing us to eliminate
an awkward parameters structure.

With that done we can safely rename tcp_port_do_rebind() to
tcp_port_rebind() for brevity.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 tcp.c | 41 ++++++++++++-----------------------------
 1 file changed, 12 insertions(+), 29 deletions(-)

diff --git a/tcp.c b/tcp.c
index 6bc040c..b933042 100644
--- a/tcp.c
+++ b/tcp.c
@@ -3156,13 +3156,13 @@ int tcp_init(struct ctx *c)
 }
 
 /**
- * tcp_port_do_rebind() - Rebind ports to match forward maps
+ * tcp_port_rebind() - Rebind ports to match forward maps
  * @c:		Execution context
  * @outbound:	True to remap outbound forwards, otherwise inbound
  *
  * Must be called in namespace context if @outbound is true.
  */
-static void tcp_port_do_rebind(struct ctx *c, bool outbound)
+static void tcp_port_rebind(struct ctx *c, bool outbound)
 {
 	const uint8_t *fmap = outbound ? c->tcp.fwd_out.map : c->tcp.fwd_in.map;
 	const uint8_t *rmap = outbound ? c->tcp.fwd_in.map : c->tcp.fwd_out.map;
@@ -3199,32 +3199,19 @@ static void tcp_port_do_rebind(struct ctx *c, bool outbound)
 }
 
 /**
- * struct tcp_port_rebind_arg - Arguments for tcp_port_rebind()
- * @c:			Execution context
- * @bind_in_ns:		Rebind ports in namespace, not in init
- */
-struct tcp_port_rebind_arg {
-	struct ctx *c;
-	int bind_in_ns;
-};
-
-/**
- * tcp_port_rebind() - Rebind ports in namespace or init
- * @arg:		See struct tcp_port_rebind_arg
+ * tcp_port_rebind_outbound() - Rebind ports in namespace
+ * @arg:	Execution context
+ *
+ * Called with NS_CALL()
  *
  * Return: 0
  */
-static int tcp_port_rebind(void *arg)
+static int tcp_port_rebind_outbound(void *arg)
 {
-	struct tcp_port_rebind_arg *a = (struct tcp_port_rebind_arg *)arg;
-
-	if (a->bind_in_ns) {
-		ns_enter(a->c);
+	struct ctx *c = (struct ctx *)arg;
 
-		tcp_port_do_rebind(a->c, true);
-	} else {
-		tcp_port_do_rebind(a->c, false);
-	}
+	ns_enter(c);
+	tcp_port_rebind(c, true);
 
 	return 0;
 }
@@ -3241,18 +3228,14 @@ void tcp_timer(struct ctx *c, const struct timespec *ts)
 	(void)ts;
 
 	if (c->mode == MODE_PASTA) {
-		struct tcp_port_rebind_arg rebind_arg = { c, 0 };
-
 		if (c->tcp.fwd_out.mode == FWD_AUTO) {
 			port_fwd_scan_tcp(&c->tcp.fwd_out, &c->tcp.fwd_in);
-			rebind_arg.bind_in_ns = 1;
-			NS_CALL(tcp_port_rebind, &rebind_arg);
+			NS_CALL(tcp_port_rebind_outbound, c);
 		}
 
 		if (c->tcp.fwd_in.mode == FWD_AUTO) {
 			port_fwd_scan_tcp(&c->tcp.fwd_in, &c->tcp.fwd_out);
-			rebind_arg.bind_in_ns = 0;
-			tcp_port_rebind(&rebind_arg);
+			tcp_port_rebind(c, false);
 		}
 	}
 
-- 
@@ -3156,13 +3156,13 @@ int tcp_init(struct ctx *c)
 }
 
 /**
- * tcp_port_do_rebind() - Rebind ports to match forward maps
+ * tcp_port_rebind() - Rebind ports to match forward maps
  * @c:		Execution context
  * @outbound:	True to remap outbound forwards, otherwise inbound
  *
  * Must be called in namespace context if @outbound is true.
  */
-static void tcp_port_do_rebind(struct ctx *c, bool outbound)
+static void tcp_port_rebind(struct ctx *c, bool outbound)
 {
 	const uint8_t *fmap = outbound ? c->tcp.fwd_out.map : c->tcp.fwd_in.map;
 	const uint8_t *rmap = outbound ? c->tcp.fwd_in.map : c->tcp.fwd_out.map;
@@ -3199,32 +3199,19 @@ static void tcp_port_do_rebind(struct ctx *c, bool outbound)
 }
 
 /**
- * struct tcp_port_rebind_arg - Arguments for tcp_port_rebind()
- * @c:			Execution context
- * @bind_in_ns:		Rebind ports in namespace, not in init
- */
-struct tcp_port_rebind_arg {
-	struct ctx *c;
-	int bind_in_ns;
-};
-
-/**
- * tcp_port_rebind() - Rebind ports in namespace or init
- * @arg:		See struct tcp_port_rebind_arg
+ * tcp_port_rebind_outbound() - Rebind ports in namespace
+ * @arg:	Execution context
+ *
+ * Called with NS_CALL()
  *
  * Return: 0
  */
-static int tcp_port_rebind(void *arg)
+static int tcp_port_rebind_outbound(void *arg)
 {
-	struct tcp_port_rebind_arg *a = (struct tcp_port_rebind_arg *)arg;
-
-	if (a->bind_in_ns) {
-		ns_enter(a->c);
+	struct ctx *c = (struct ctx *)arg;
 
-		tcp_port_do_rebind(a->c, true);
-	} else {
-		tcp_port_do_rebind(a->c, false);
-	}
+	ns_enter(c);
+	tcp_port_rebind(c, true);
 
 	return 0;
 }
@@ -3241,18 +3228,14 @@ void tcp_timer(struct ctx *c, const struct timespec *ts)
 	(void)ts;
 
 	if (c->mode == MODE_PASTA) {
-		struct tcp_port_rebind_arg rebind_arg = { c, 0 };
-
 		if (c->tcp.fwd_out.mode == FWD_AUTO) {
 			port_fwd_scan_tcp(&c->tcp.fwd_out, &c->tcp.fwd_in);
-			rebind_arg.bind_in_ns = 1;
-			NS_CALL(tcp_port_rebind, &rebind_arg);
+			NS_CALL(tcp_port_rebind_outbound, c);
 		}
 
 		if (c->tcp.fwd_in.mode == FWD_AUTO) {
 			port_fwd_scan_tcp(&c->tcp.fwd_in, &c->tcp.fwd_out);
-			rebind_arg.bind_in_ns = 0;
-			tcp_port_rebind(&rebind_arg);
+			tcp_port_rebind(c, false);
 		}
 	}
 
-- 
2.41.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 3/3] udp,pasta: Periodically scan for ports to automatically forward
  2023-11-15  5:25 [PATCH 0/3] pasta: Implement runtime auto-forwarding for UDP David Gibson
  2023-11-15  5:25 ` [PATCH 1/3] tcp: Use common helper for rebinding inbound and outbound ports David Gibson
  2023-11-15  5:25 ` [PATCH 2/3] tcp: Simplify away tcp_port_rebind() David Gibson
@ 2023-11-15  5:25 ` David Gibson
  2023-11-19 20:10 ` [PATCH 0/3] pasta: Implement runtime auto-forwarding for UDP Stefano Brivio
  3 siblings, 0 replies; 5+ messages in thread
From: David Gibson @ 2023-11-15  5:25 UTC (permalink / raw)
  To: Stefano Brivio, passt-dev; +Cc: David Gibson

pasta supports automatic port forwarding, where we look for listening
sockets in /proc/net (in both namespace and outside) and establish port
forwarding to match.

For TCP we do this scan both at initial startup, then periodically
thereafter.  For UDP however, we currently only scan at start.  So unlike
TCP we won't update forwarding to handle services that start after pasta
has begun.

There's no particular reason for that, other than that we didn't implement
it.  So, remove that difference, by scanning for new UDP forwards
periodically too.  The logic is basically identical to that for TCP, but it
needs some changes to handle the mildly different data structures in the
UDP case.

Link: https://bugs.passt.top/show_bug.cgi?id=45

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 passt.1 |  3 +--
 udp.c   | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 75 insertions(+), 2 deletions(-)

diff --git a/passt.1 b/passt.1
index 1ad4276..efd6bb7 100644
--- a/passt.1
+++ b/passt.1
@@ -496,8 +496,7 @@ Default is \fBauto\fR.
 .BR \-u ", " \-\-udp-ports " " \fIspec
 Configure UDP port forwarding to namespace. \fIspec\fR is as described for TCP
 above, and the list of ports is derived from listening sockets reported by
-\fI/proc/net/udp\fR and \fI/proc/net/udp6\fR, see \fBproc\fR(5),
-when \fBpasta\fR starts (not periodically).
+\fI/proc/net/udp\fR and \fI/proc/net/udp6\fR, see \fBproc\fR(5).
 
 Note: unless overridden, UDP ports with numbers corresponding to forwarded TCP
 port numbers are forwarded too, without, however, any port translation. 
diff --git a/udp.c b/udp.c
index a13efd2..cc1ea9c 100644
--- a/udp.c
+++ b/udp.c
@@ -1186,6 +1186,66 @@ static void udp_timer_one(struct ctx *c, int v6, enum udp_act_type type,
 	}
 }
 
+/**
+ * udp_port_rebind() - Rebind ports to match forward maps
+ * @c:		Execution context
+ * @outbound:	True to remap outbound forwards, otherwise inbound
+ *
+ * Must be called in namespace context if @outbound is true.
+ */
+static void udp_port_rebind(struct ctx *c, bool outbound)
+{
+	const uint8_t *fmap
+		= outbound ? c->udp.fwd_out.f.map : c->udp.fwd_in.f.map;
+	const uint8_t *rmap
+		= outbound ? c->udp.fwd_in.f.map : c->udp.fwd_out.f.map;
+	struct udp_splice_port (*socks)[NUM_PORTS]
+		= outbound ? udp_splice_ns : udp_splice_init;
+	unsigned port;
+
+	for (port = 0; port < NUM_PORTS; port++) {
+		if (!bitmap_isset(fmap, port)) {
+			if (socks[V4][port].sock >= 0) {
+				close(socks[V4][port].sock);
+				socks[V4][port].sock = -1;
+			}
+
+			if (socks[V6][port].sock >= 0) {
+				close(socks[V6][port].sock);
+				socks[V6][port].sock = -1;
+			}
+
+			continue;
+		}
+
+		/* Don't loop back our own ports */
+		if (bitmap_isset(rmap, port))
+			continue;
+
+		if ((c->ifi4 && socks[V4][port].sock == -1) ||
+		    (c->ifi6 && socks[V6][port].sock == -1))
+			udp_sock_init(c, outbound, AF_UNSPEC, NULL, NULL, port);
+	}
+}
+
+/**
+ * udp_port_rebind_outbound() - Rebind ports in namespace
+ * @arg:	Execution context
+ *
+ * Called with NS_CALL()
+ *
+ * Return: 0
+ */
+static int udp_port_rebind_outbound(void *arg)
+{
+	struct ctx *c = (struct ctx *)arg;
+
+	ns_enter(c);
+	udp_port_rebind(c, true);
+
+	return 0;
+}
+
 /**
  * udp_timer() - Scan activity bitmaps for ports with associated timed events
  * @c:		Execution context
@@ -1197,6 +1257,20 @@ void udp_timer(struct ctx *c, const struct timespec *ts)
 	unsigned int i;
 	long *word, tmp;
 
+	if (c->mode == MODE_PASTA) {
+		if (c->udp.fwd_out.f.mode == FWD_AUTO) {
+			port_fwd_scan_udp(&c->udp.fwd_out.f, &c->udp.fwd_in.f,
+					  &c->tcp.fwd_out);
+			NS_CALL(udp_port_rebind_outbound, c);
+		}
+
+		if (c->udp.fwd_in.f.mode == FWD_AUTO) {
+			port_fwd_scan_udp(&c->udp.fwd_in.f, &c->udp.fwd_out.f,
+					  &c->tcp.fwd_in);
+			udp_port_rebind(c, false);
+		}
+	}
+
 	if (!c->ifi4)
 		v6 = 1;
 v6:
-- 
@@ -1186,6 +1186,66 @@ static void udp_timer_one(struct ctx *c, int v6, enum udp_act_type type,
 	}
 }
 
+/**
+ * udp_port_rebind() - Rebind ports to match forward maps
+ * @c:		Execution context
+ * @outbound:	True to remap outbound forwards, otherwise inbound
+ *
+ * Must be called in namespace context if @outbound is true.
+ */
+static void udp_port_rebind(struct ctx *c, bool outbound)
+{
+	const uint8_t *fmap
+		= outbound ? c->udp.fwd_out.f.map : c->udp.fwd_in.f.map;
+	const uint8_t *rmap
+		= outbound ? c->udp.fwd_in.f.map : c->udp.fwd_out.f.map;
+	struct udp_splice_port (*socks)[NUM_PORTS]
+		= outbound ? udp_splice_ns : udp_splice_init;
+	unsigned port;
+
+	for (port = 0; port < NUM_PORTS; port++) {
+		if (!bitmap_isset(fmap, port)) {
+			if (socks[V4][port].sock >= 0) {
+				close(socks[V4][port].sock);
+				socks[V4][port].sock = -1;
+			}
+
+			if (socks[V6][port].sock >= 0) {
+				close(socks[V6][port].sock);
+				socks[V6][port].sock = -1;
+			}
+
+			continue;
+		}
+
+		/* Don't loop back our own ports */
+		if (bitmap_isset(rmap, port))
+			continue;
+
+		if ((c->ifi4 && socks[V4][port].sock == -1) ||
+		    (c->ifi6 && socks[V6][port].sock == -1))
+			udp_sock_init(c, outbound, AF_UNSPEC, NULL, NULL, port);
+	}
+}
+
+/**
+ * udp_port_rebind_outbound() - Rebind ports in namespace
+ * @arg:	Execution context
+ *
+ * Called with NS_CALL()
+ *
+ * Return: 0
+ */
+static int udp_port_rebind_outbound(void *arg)
+{
+	struct ctx *c = (struct ctx *)arg;
+
+	ns_enter(c);
+	udp_port_rebind(c, true);
+
+	return 0;
+}
+
 /**
  * udp_timer() - Scan activity bitmaps for ports with associated timed events
  * @c:		Execution context
@@ -1197,6 +1257,20 @@ void udp_timer(struct ctx *c, const struct timespec *ts)
 	unsigned int i;
 	long *word, tmp;
 
+	if (c->mode == MODE_PASTA) {
+		if (c->udp.fwd_out.f.mode == FWD_AUTO) {
+			port_fwd_scan_udp(&c->udp.fwd_out.f, &c->udp.fwd_in.f,
+					  &c->tcp.fwd_out);
+			NS_CALL(udp_port_rebind_outbound, c);
+		}
+
+		if (c->udp.fwd_in.f.mode == FWD_AUTO) {
+			port_fwd_scan_udp(&c->udp.fwd_in.f, &c->udp.fwd_out.f,
+					  &c->tcp.fwd_in);
+			udp_port_rebind(c, false);
+		}
+	}
+
 	if (!c->ifi4)
 		v6 = 1;
 v6:
-- 
2.41.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH 0/3] pasta: Implement runtime auto-forwarding for UDP
  2023-11-15  5:25 [PATCH 0/3] pasta: Implement runtime auto-forwarding for UDP David Gibson
                   ` (2 preceding siblings ...)
  2023-11-15  5:25 ` [PATCH 3/3] udp,pasta: Periodically scan for ports to automatically forward David Gibson
@ 2023-11-19 20:10 ` Stefano Brivio
  3 siblings, 0 replies; 5+ messages in thread
From: Stefano Brivio @ 2023-11-19 20:10 UTC (permalink / raw)
  To: David Gibson; +Cc: passt-dev

On Wed, 15 Nov 2023 16:25:31 +1100
David Gibson <david@gibson.dropbear.id.au> wrote:

> In "auto" mode port forwarding, we scan for listening TCP ports at
> start up, and then every second thereafter.  For UDP, however, we scan
> only at start up.
> 
> That's documented, but surprising, and there's no real reason for it
> to be that way.  Implement periodic scanning for UDP auto forwarding
> too.
> 
> Link: https://bugs.passt.top/show_bug.cgi?id=45
> 
> *** BLURB HERE ***
> 
> David Gibson (3):
>   tcp: Use common helper for rebinding inbound and outbound ports
>   tcp: Simplify away tcp_port_rebind()
>   udp,pasta: Periodically scan for ports to automatically forward

Applied.

-- 
Stefano


^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2023-11-19 20:10 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-11-15  5:25 [PATCH 0/3] pasta: Implement runtime auto-forwarding for UDP David Gibson
2023-11-15  5:25 ` [PATCH 1/3] tcp: Use common helper for rebinding inbound and outbound ports David Gibson
2023-11-15  5:25 ` [PATCH 2/3] tcp: Simplify away tcp_port_rebind() David Gibson
2023-11-15  5:25 ` [PATCH 3/3] udp,pasta: Periodically scan for ports to automatically forward David Gibson
2023-11-19 20:10 ` [PATCH 0/3] pasta: Implement runtime auto-forwarding for UDP Stefano Brivio

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