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 v2 07/12] fwd: Make space to store listening sockets in forward table
Date: Sat, 20 Dec 2025 01:18:59 +1100 [thread overview]
Message-ID: <20251219141904.1758072-8-david@gibson.dropbear.id.au> (raw)
In-Reply-To: <20251219141904.1758072-1-david@gibson.dropbear.id.au>
At present, we don't keep track of the fds for listening sockets (except
for "auto" ones). Since the fd is stored in the epoll reference, we didn't
need an alternative source of it for the various handlers.
However, we're intending to allow dynamic changes to forwarding
configuration in future. That means we need a way to enumerate sockets so
we can close them on removal of a forward.
Extend our forwarding table data structure to make space for all the
listening sockets. To avoid allocation, this imposes another limit: we
could run out of space for socket fds before we run out of forwarding
entries.
We don't actually do anything with the allocate space yet. Plus, for
"auto" forwards the new space is redundant with existing arrays. We'll fix
both of those in later patches.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
fwd.c | 8 ++++++++
fwd.h | 11 +++++++++++
2 files changed, 19 insertions(+)
diff --git a/fwd.c b/fwd.c
index 5e5dc58c..5215cee9 100644
--- a/fwd.c
+++ b/fwd.c
@@ -332,12 +332,15 @@ void fwd_table_add(struct fwd_ports *fwd, uint8_t flags,
{
/* Flags which can be set from the caller */
const uint8_t allowed_flags = FWD_WEAK | FWD_SCAN;
+ unsigned num = (unsigned)last - first + 1, i;
struct fwd_entry *new;
ASSERT(!(flags & ~allowed_flags));
if (fwd->count >= ARRAY_SIZE(fwd->tab))
die("Too many port forwarding ranges");
+ if ((fwd->listen_sock_count + num) > ARRAY_SIZE(fwd->listen_socks))
+ die("Too many listening sockets");
new = &fwd->tab[fwd->count++];
new->flags = flags;
@@ -358,6 +361,11 @@ void fwd_table_add(struct fwd_ports *fwd, uint8_t flags,
new->last = last;
new->to = to;
+
+ new->socks = &fwd->listen_socks[fwd->listen_sock_count];
+ fwd->listen_sock_count += num;
+ for (i = 0; i < num; i++)
+ new->socks[i] = -1;
}
/**
diff --git a/fwd.h b/fwd.h
index eef507c6..84c463e2 100644
--- a/fwd.h
+++ b/fwd.h
@@ -23,6 +23,7 @@ bool fwd_port_is_ephemeral(in_port_t port);
* @first: First port number to forward
* @last: Last port number to forward
* @to: Port number to forward port @first to.
+ * @socks: Array of listening sockets for this entry
* @flags: Flag mask
* FWD_DUAL_STACK - forward both IPv4 and IPv6 (requires @addr be ::)
* FWD_WEAK - Don't give an error if binds fail for some forwards
@@ -34,6 +35,7 @@ struct fwd_entry {
union inany_addr addr;
char ifname[IFNAMSIZ];
in_port_t first, last, to;
+ int *socks;
#define FWD_DUAL_STACK BIT(0)
#define FWD_WEAK BIT(1)
#define FWD_SCAN BIT(2)
@@ -52,6 +54,13 @@ enum fwd_ports_mode {
#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
+ * for -T auto without SO_BINDTODEVICE), plus a comfortable number of extras.
+ */
+#define MAX_LISTEN_SOCKS (NUM_PORTS * 3)
+
/**
* fwd_ports() - Describes port forwarding for one protocol and direction
* @mode: Overall forwarding mode (all, none, auto, specific ports)
@@ -68,6 +77,8 @@ struct fwd_ports {
struct fwd_entry tab[MAX_FWDS];
uint8_t map[PORT_BITMAP_SIZE];
in_port_t delta[NUM_PORTS];
+ unsigned listen_sock_count;
+ int listen_socks[MAX_LISTEN_SOCKS];
};
#define FWD_PORT_SCAN_INTERVAL 1000 /* ms */
--
2.52.0
next prev parent reply other threads:[~2025-12-19 14:19 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-12-19 14:18 [PATCH v2 00/12] RFC: Improve forwarding data structure David Gibson
2025-12-19 14:18 ` [PATCH v2 01/12] tcp: Combine tcp_sock_init_one() and tcp_sock_init() into tcp_listen() David Gibson
2025-12-19 14:18 ` [PATCH v2 02/12] udp: Rename udp_sock_init() to udp_listen() with small cleanups David Gibson
2025-12-19 14:18 ` [PATCH v2 03/12] conf, fwd: Keep a table of our port forwarding configuration David Gibson
2025-12-19 14:18 ` [PATCH v2 04/12] conf: Accurately record ifname and address for outbound forwards David Gibson
2025-12-19 14:18 ` [PATCH v2 05/12] conf, fwd: Record "auto" port forwards in forwarding table David Gibson
2025-12-19 14:18 ` [PATCH v2 06/12] tcp, udp: Make {tcp,udp}_listen() return socket fds David Gibson
2025-12-19 14:18 ` David Gibson [this message]
2025-12-19 14:19 ` [PATCH v2 08/12] ip: Add ipproto_name() function David Gibson
2025-12-19 14:19 ` [PATCH v2 09/12] fwd, tcp, udp: Set up listening sockets based on forward table David Gibson
2025-12-19 14:19 ` [PATCH v2 10/12] tcp, udp: Remove old auto-forwarding socket arrays David Gibson
2025-12-19 14:19 ` [PATCH v2 11/12] fwd: Generate auto-forward exclusions from socket fd tables David Gibson
2025-12-19 14:19 ` [PATCH v2 12/12] tcp: Remove unused tcp_epoll_ref 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=20251219141904.1758072-8-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).