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 v3 24/25] pesto, conf: Parse, send and receive new rules
Date: Mon, 23 Mar 2026 18:37:31 +1100 [thread overview]
Message-ID: <20260323073732.3158468-25-david@gibson.dropbear.id.au> (raw)
In-Reply-To: <20260323073732.3158468-1-david@gibson.dropbear.id.au>
From: Stefano Brivio <sbrivio@redhat.com>
This adds parsing of options using conf_ports() in pesto, builds rules, and
sends them one by one to passt, which now receives them and stores then in
a different table. We debug print the rules in the "pending" table but
don't yet attempt to activate them.
Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
Message-ID: <20260322141843.4095972-3-sbrivio@redhat.com>
[dwg: Rebased on changes to my earlier patches]
[dwg: Properly preserve the rule flags when they're read in]
[dwg: Removed the non-working logic to activate the new table]
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
Makefile | 2 +-
conf.c | 60 ++++++++++++++++++++++++++++++++++++--
fwd.c | 9 +++++-
passt.h | 2 ++
pesto.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--
pif.h | 2 ++
6 files changed, 157 insertions(+), 6 deletions(-)
diff --git a/Makefile b/Makefile
index b6b6a823..24235702 100644
--- a/Makefile
+++ b/Makefile
@@ -51,7 +51,7 @@ SRCS = $(PASST_SRCS) $(QRAP_SRCS) $(PASST_REPAIR_SRCS) $(PESTO_SRCS)
MANPAGES = passt.1 pasta.1 pesto.1 qrap.1 passt-repair.1
PESTO_HEADERS = common.h fwd_rule.h inany.h ip.h pesto.h serialise.h ports.h \
- lineread.h
+ lineread.h pif.h
PASST_HEADERS = arch.h arp.h checksum.h conf.h dhcp.h dhcpv6.h epoll_ctl.h \
flow.h fwd.h flow_table.h icmp.h icmp_flow.h iov.h isolation.h \
lineread.h log.h migrate.h ndp.h netlink.h packet.h passt.h pasta.h \
diff --git a/conf.c b/conf.c
index 7f624db6..b4c2074e 100644
--- a/conf.c
+++ b/conf.c
@@ -2046,6 +2046,50 @@ static int conf_send_rules(const struct ctx *c, int fd)
return 0;
}
+/**
+ * conf_send_rules() - Send current forwarding rules to dynamic update client (pesto)
+ * @c: Execution context
+ * @fd: Socket to the client
+ *
+ * Return: 0 on success, -1 on failure
+ */
+static int conf_recv_rules(const struct ctx *c, int fd)
+{
+ while (1) {
+ struct fwd_table *fwd;
+ struct fwd_rule r;
+ uint32_t count;
+ uint8_t pif;
+ unsigned i;
+
+ if (read_u8(fd, &pif))
+ return -1;
+
+ if (pif == PIF_NONE)
+ break;
+
+ fwd = c->fwd_pending[pif];
+ if (!fwd) {
+ err("Received rules for non-existent table");
+ return -1;
+ }
+
+ /* Clear pending table */
+ memset(fwd, 0, sizeof(*fwd));
+
+ if (read_u32(fd, &count))
+ return -1;
+
+ for (i = 0; i < count; i++) {
+ fwd_rule_read(fd, &r);
+ fwd_rule_add(fwd, r.proto, r.flags, &r.addr, NULL,
+ r.first, r.last, r.to);
+ }
+ }
+
+ return 0;
+}
+
/**
* conf_listen_handler() - Handle events on configuration listening socket
* @c: Execution context
@@ -2060,14 +2104,14 @@ void conf_listen_handler(struct ctx *c, uint32_t events)
union epoll_ref ref = { .type = EPOLL_TYPE_CONF };
struct ucred uc = { 0 };
socklen_t len = sizeof(uc);
- int fd, rc;
+ int fd, rc, i;
if (events != EPOLLIN) {
err("Unexpected event 0x%04x on configuration socket", events);
return;
}
- fd = accept4(c->fd_control_listen, NULL, NULL, SOCK_NONBLOCK);
+ fd = accept4(c->fd_control_listen, NULL, NULL, 0);
if (fd < 0) {
warn_perror("accept4() on configuration listening socket");
return;
@@ -2108,6 +2152,18 @@ void conf_listen_handler(struct ctx *c, uint32_t events)
if (conf_send_rules(c, fd) < 0)
goto fail;
+ if (conf_recv_rules(c, fd) < 0)
+ goto fail;
+
+ info("Received new forwarding table:");
+ for (i = 0; i < PIF_NUM_TYPES; i++) {
+ if (!c->fwd_pending[i])
+ continue;
+
+ info("Forwarding from %s:", pif_name(i));
+ fwd_rules_print(c->fwd_pending[i]);
+ }
+
return;
fail:
diff --git a/fwd.c b/fwd.c
index 4592af25..d54a1f15 100644
--- a/fwd.c
+++ b/fwd.c
@@ -247,6 +247,9 @@ void fwd_neigh_table_init(const struct ctx *c)
static struct fwd_table fwd_in;
static struct fwd_table fwd_out;
+static struct fwd_table fwd_in_pending;
+static struct fwd_table fwd_out_pending;
+
/**
* fwd_rule_init() - Initialise forwarding tables
* @c: Execution context
@@ -254,8 +257,12 @@ static struct fwd_table fwd_out;
void fwd_rule_init(struct ctx *c)
{
c->fwd[PIF_HOST] = &fwd_in;
- if (c->mode == MODE_PASTA)
+ c->fwd_pending[PIF_HOST] = &fwd_in_pending;
+
+ if (c->mode == MODE_PASTA) {
c->fwd[PIF_SPLICE] = &fwd_out;
+ c->fwd_pending[PIF_SPLICE] = &fwd_out_pending;
+ }
}
/**
diff --git a/passt.h b/passt.h
index b3f049de..1726965d 100644
--- a/passt.h
+++ b/passt.h
@@ -188,6 +188,7 @@ struct ip6_ctx {
* @pasta_ifi: Index of namespace interface for pasta
* @pasta_conf_ns: Configure namespace after creating it
* @fwd: Forwarding tables
+ * @fwd_pending: Pending forward tables
* @no_tcp: Disable TCP operation
* @tcp: Context for TCP protocol handler
* @no_udp: Disable UDP operation
@@ -270,6 +271,7 @@ struct ctx {
int pasta_conf_ns;
struct fwd_table *fwd[PIF_NUM_TYPES];
+ struct fwd_table *fwd_pending[PIF_NUM_TYPES];
int no_tcp;
struct tcp_ctx tcp;
diff --git a/pesto.c b/pesto.c
index aa1d584c..5ee0352e 100644
--- a/pesto.c
+++ b/pesto.c
@@ -38,6 +38,7 @@
#include "fwd_rule.h"
#include "pesto.h"
#include "log.h"
+#include "pif.h"
int verbosity = 1;
@@ -65,6 +66,36 @@ static void usage(const char *name, FILE *f, int status)
FPRINTF(f, "Usage: %s [OPTION]... PATH\n", name);
FPRINTF(f,
"\n"
+ " -t, --tcp-ports SPEC TCP inbound port forwarding\n"
+ " can be specified multiple times\n"
+ " SPEC can be:\n"
+ " 'none': don't forward any ports\n"
+ " 'auto': forward all ports currently bound in namespace\n"
+ " 'all': forward all unbound, non-ephemeral ports\n"
+ " a comma-separated list, optionally ranged with '-'\n"
+ " and optional target ports after ':', with optional\n"
+ " address specification suffixed by '/' and optional\n"
+ " interface prefixed by '%%'. Examples:\n"
+ " -t 22 Forward local port 22 to port 22 in netns\n"
+ " -t 22:23 Forward local port 22 to port 23\n"
+ " -t 22,25 Forward ports 22, 25 to ports 22, 25\n"
+ " -t 22-80 Forward ports 22 to 80\n"
+ " -t 22-80:32-90 Forward ports 22 to 80 to\n"
+ " corresponding port numbers plus 10\n"
+ " -t 192.0.2.1/5 Bind port 5 of 192.0.2.1\n"
+ " -t 5-25,~10-20 Forward ports 5 to 9, and 21 to 25\n"
+ " -t ~25 Forward all bound ports except for 25\n"
+ " IPv6 bound ports are also forwarded for IPv4\n"
+ " -u, --udp-ports SPEC UDP inbound port forwarding\n"
+ " SPEC is as described for TCP above\n"
+ " IPv6 bound ports are also forwarded for IPv4\n"
+ " unless specified, with '-t auto', UDP ports with numbers\n"
+ " corresponding to forwarded TCP port numbers are\n"
+ " forwarded too\n"
+ " -T, --tcp-ns SPEC TCP port forwarding to init namespace\n"
+ " SPEC is as described above\n"
+ " -U, --udp-ns SPEC UDP port forwarding to init namespace\n"
+ " SPEC is as described above\n"
" -v, --verbose Be more verbose\n"
" -q, --quiet Be less verbose\n"
" -h, --help Display this help message and exit\n"
@@ -221,7 +252,7 @@ static void show_state(const struct conf_state *state)
*
* Return: 0 on success, won't return on failure
*
- * #syscalls:pesto connect write close exit_group fstat brk getrandom
+ * #syscalls:pesto connect write close exit_group fstat brk getrandom openat
* #syscalls:pesto socket s390x:socketcall i686:socketcall
* #syscalls:pesto recvfrom recvmsg arm:recv ppc64le:recv
* #syscalls:pesto sendto sendmsg arm:send ppc64le:send
@@ -233,15 +264,22 @@ int main(int argc, char **argv)
{"verbose", no_argument, NULL, 'v' },
{"help", no_argument, NULL, 'h' },
{"version", no_argument, NULL, 1 },
+ {"tcp-ports", required_argument, NULL, 't' },
+ {"udp-ports", required_argument, NULL, 'u' },
+ {"tcp-ns", required_argument, NULL, 'T' },
+ {"udp-ns", required_argument, NULL, 'U' },
{ 0 },
};
+ struct fwd_table fwd_in = { .count = 0 }, fwd_out = { .count = 0 };
struct sockaddr_un a = { AF_UNIX, "" };
- const char *optstring = "vh";
+ const char *optstring = "vht:u:T:U:";
+ enum fwd_mode fwd_default;
struct pesto_hello hello;
struct conf_state *state;
struct sock_fprog prog;
int optname, ret, s;
uint32_t s_version;
+ unsigned i;
prog.len = (unsigned short)sizeof(filter_pesto) /
sizeof(filter_pesto[0]);
@@ -250,6 +288,8 @@ int main(int argc, char **argv)
prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog))
die("Failed to apply seccomp filter");
+ fwd_probe_ephemeral();
+
do {
optname = getopt_long(argc, argv, optstring, options, NULL);
@@ -266,6 +306,18 @@ int main(int argc, char **argv)
case 'v':
verbosity++;
break;
+ case 't':
+ case 'u':
+ fwd_default = FWD_MODE_UNSET;
+ conf_ports(optname, optarg, &fwd_in, &fwd_default,
+ true, true, true);
+ break;
+ case 'T':
+ case 'U':
+ fwd_default = FWD_MODE_UNSET;
+ conf_ports(optname, optarg, &fwd_out, &fwd_default,
+ true, true, true);
+ break;
case 1:
FPRINTF(stdout, "pesto ");
FPRINTF(stdout, VERSION_BLOB);
@@ -291,6 +343,22 @@ int main(int argc, char **argv)
a.sun_path, strerror(errno));
}
+ debug("Inbound rules from command line:");
+ for (i = 0; i < fwd_in.count; i++) {
+ const struct fwd_rule *rule = &fwd_in.rules[i].rule;
+ char rulestr[FWD_RULE_STRLEN];
+
+ debug(" %s", fwd_rule_ntop(rule, rulestr, sizeof(rulestr)));
+ }
+
+ debug("Outbound rules from command line:");
+ for (i = 0; i < fwd_out.count; i++) {
+ const struct fwd_rule *rule = &fwd_out.rules[i].rule;
+ char rulestr[FWD_RULE_STRLEN];
+
+ debug(" %s", fwd_rule_ntop(rule, rulestr, sizeof(rulestr)));
+ }
+
debug("Connected to passt/pasta control socket");
ret = read_all_buf(s, &hello, sizeof(hello));
@@ -324,5 +392,21 @@ int main(int argc, char **argv)
show_state(state);
+ if (fwd_in.count) {
+ write_u8(s, PIF_HOST);
+ write_u32(s, fwd_in.count);
+ for (i = 0; i < fwd_in.count; i++)
+ fwd_rule_write(s, &fwd_in.rules[i].rule);
+ }
+
+ if (fwd_out.count) {
+ write_u8(s, PIF_SPLICE);
+ write_u32(s, fwd_out.count);
+ for (i = 0; i < fwd_out.count; i++)
+ fwd_rule_write(s, &fwd_out.rules[i].rule);
+ }
+
+ write_u8(s, PIF_NONE);
+
exit(0);
}
diff --git a/pif.h b/pif.h
index 7bb58e5c..c96a0900 100644
--- a/pif.h
+++ b/pif.h
@@ -35,6 +35,7 @@ enum pif_type {
PIF_NUM_TYPES,
};
+#ifndef PESTO
extern const char *pif_type_str[];
static inline const char *pif_type(enum pif_type pt)
@@ -66,5 +67,6 @@ void pif_sockaddr(const struct ctx *c, union sockaddr_inany *sa,
int pif_listen(const struct ctx *c, enum epoll_type type, uint8_t pif,
const union inany_addr *addr, const char *ifname,
in_port_t port, unsigned rule);
+#endif /* !PESTO */
#endif /* PIF_H */
--
2.53.0
next prev parent reply other threads:[~2026-03-23 8:33 UTC|newest]
Thread overview: 49+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-03-23 7:37 [PATCH v3 00/25] RFC: Read-only dynamic update implementation David Gibson
2026-03-23 7:37 ` [PATCH v3 01/25] conf: runas can be const David Gibson
2026-03-23 7:37 ` [PATCH v3 02/25] vhost_user: Fix assorted minor cppcheck warnings David Gibson
2026-03-23 7:37 ` [PATCH v3 03/25] serialise: Split functions user for serialisation from util.c David Gibson
2026-03-25 0:54 ` Stefano Brivio
2026-03-25 1:50 ` David Gibson
2026-03-23 7:37 ` [PATCH v3 04/25] serialise: Add helpers for serialising unsigned integers David Gibson
2026-03-23 7:37 ` [PATCH v3 05/25] fwd: Move selecting correct scan bitmap into fwd_sync_one() David Gibson
2026-03-23 7:37 ` [PATCH v3 06/25] fwd: Look up rule index in fwd_sync_one() David Gibson
2026-03-23 7:37 ` [PATCH v3 07/25] fwd: Store forwarding tables indexed by (origin) pif David Gibson
2026-03-25 0:54 ` Stefano Brivio
2026-03-25 4:04 ` David Gibson
2026-03-23 7:37 ` [PATCH v3 08/25] fwd: Allow FWD_DUAL_STACK_ANY flag to be passed directly to fwd_rule_add() David Gibson
2026-03-25 0:54 ` Stefano Brivio
2026-03-25 4:07 ` David Gibson
2026-03-23 7:37 ` [PATCH v3 09/25] fwd, conf: Expose ephemeral ports as bitmap rather than function David Gibson
2026-03-23 7:37 ` [PATCH v3 10/25] conf: Don't bother complaining about overlapping excluded ranges David Gibson
2026-03-23 7:37 ` [PATCH v3 11/25] conf: Move check for mapping port 0 to caller David Gibson
2026-03-23 7:37 ` [PATCH v3 12/25] conf: Move check for disabled interfaces earlier David Gibson
2026-03-23 7:37 ` [PATCH v3 13/25] pesto: Introduce stub configuration interface and tool David Gibson
2026-03-25 0:54 ` Stefano Brivio
2026-03-23 7:37 ` [PATCH v3 14/25] pesto: Add command line option parsing and debug messages David Gibson
2026-03-25 0:55 ` Stefano Brivio
2026-03-25 4:27 ` David Gibson
2026-03-23 7:37 ` [PATCH v3 15/25] pesto: Expose list of pifs to pesto David Gibson
2026-03-25 0:56 ` Stefano Brivio
2026-03-25 4:34 ` David Gibson
2026-03-25 8:18 ` Stefano Brivio
2026-03-25 8:31 ` David Gibson
2026-03-23 7:37 ` [PATCH v3 16/25] ip: Prepare ip.[ch] for sharing with pesto tool David Gibson
2026-03-23 7:37 ` [PATCH v3 17/25] inany: Prepare inany.[ch] " David Gibson
2026-03-23 7:37 ` [PATCH v3 18/25] fwd: Split forwading rule specification from its implementation state David Gibson
2026-03-23 7:37 ` [PATCH v3 19/25] ip: Define a bound for the string returned by ipproto_name() David Gibson
2026-03-23 7:37 ` [PATCH v3 20/25] fwd_rule: Move forwarding rule text formatting to common code David Gibson
2026-03-25 0:56 ` Stefano Brivio
2026-03-25 4:42 ` David Gibson
2026-03-25 8:18 ` Stefano Brivio
2026-03-25 23:54 ` David Gibson
2026-03-23 7:37 ` [PATCH v3 21/25] pesto: Read current ruleset from passt/pasta and display it David Gibson
2026-03-25 0:56 ` Stefano Brivio
2026-03-25 4:43 ` David Gibson
2026-03-23 7:37 ` [PATCH v3 22/25] conf: Move port parsing functions to own file, ports.c David Gibson
2026-03-23 7:37 ` [PATCH v3 23/25] conf, fwd, ports, util: Move things around for pesto David Gibson
2026-03-23 7:37 ` David Gibson [this message]
2026-03-23 7:37 ` [PATCH v3 25/25] conf, fwd: Allow switching to new rules received from pesto David Gibson
2026-03-23 8:38 ` [PATCH v3 00/25] RFC: Read-only dynamic update implementation David Gibson
2026-03-25 0:56 ` Stefano Brivio
2026-03-25 1:00 ` Stefano Brivio
2026-03-25 4:44 ` 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=20260323073732.3158468-25-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).