From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: passt.top; dmarc=none (p=none dis=none) header.from=gibson.dropbear.id.au Authentication-Results: passt.top; dkim=pass (2048-bit key; secure) header.d=gibson.dropbear.id.au header.i=@gibson.dropbear.id.au header.a=rsa-sha256 header.s=202602 header.b=GFvbRorg; dkim-atps=neutral Received: from mail.ozlabs.org (gandalf.ozlabs.org [150.107.74.76]) by passt.top (Postfix) with ESMTPS id 2329B5A061A for ; Fri, 27 Mar 2026 05:34:44 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gibson.dropbear.id.au; s=202602; t=1774586072; bh=uX9/fuAsSZh+tAOufFpyYnGcyAEIKQxyozKfLq1JWD4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=GFvbRorg7iC38prnOsDXQcPFdVKknQY2TmLKBAXfwguGab78EdbPtDnNl7OGXrqfJ jf2j9jWFTHcO9G4T8/58VBJcLhdOPbUGzZYl4V24efsSgE3QsiqiPDf5rTYpdOkro5 RKI0yZvYhF5Vxm7y2LGGc5f6qiezwajKezJDqhDVRqCLMyCLeCJ8/K1TDdP5JilH2l yHsV8REdAuXXXE9V4Eub/S6KdawsWcy0V6y/a8SorTpPrqBUITErUeEKHAGdU+pzhx 9tjF6mILUdgqQ2z9Wuw7wM7olSUgMsZiqsrOKAtwoPIZ+OmVwDswxO+esAanbGKtku VsNBPDwCKEQIQ== Received: by gandalf.ozlabs.org (Postfix, from userid 1007) id 4fhnqD6NjXz4wTH; Fri, 27 Mar 2026 15:34:32 +1100 (AEDT) From: David Gibson To: passt-dev@passt.top, Stefano Brivio Subject: [PATCH 18/18] fwd: Split forwading rule specification from its implementation state Date: Fri, 27 Mar 2026 15:34:30 +1100 Message-ID: <20260327043430.1785787-19-david@gibson.dropbear.id.au> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260327043430.1785787-1-david@gibson.dropbear.id.au> References: <20260327043430.1785787-1-david@gibson.dropbear.id.au> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Message-ID-Hash: GHDCK2ESDCSJFVAUQWWZEC2UHJBNME2H X-Message-ID-Hash: GHDCK2ESDCSJFVAUQWWZEC2UHJBNME2H X-MailFrom: dgibson@gandalf.ozlabs.org X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: David Gibson X-Mailman-Version: 3.3.8 Precedence: list List-Id: Development discussion and patches for passt Archived-At: Archived-At: List-Archive: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: Most of the fields in struct fwd_rule give the parameters of the forwarding rule itself. The @socks field gives the list of listening sockets we use to implement it. In order to share code with the configuraiton update tool pesto, we want to split these. Move the rule specification itself into fwd_rule.h, which can be shared with pesto. Signed-off-by: David Gibson --- Makefile | 12 +++++----- fwd.c | 66 ++++++++++++++++++++++++++++-------------------------- fwd.h | 31 +++++-------------------- fwd_rule.h | 44 ++++++++++++++++++++++++++++++++++++ 4 files changed, 90 insertions(+), 63 deletions(-) create mode 100644 fwd_rule.h diff --git a/Makefile b/Makefile index d6ced328..dd647b10 100644 --- a/Makefile +++ b/Makefile @@ -50,12 +50,12 @@ SRCS = $(PASST_SRCS) $(QRAP_SRCS) $(PASST_REPAIR_SRCS) MANPAGES = passt.1 pasta.1 qrap.1 passt-repair.1 PASST_HEADERS = arch.h arp.h bitmap.h checksum.h conf.h dhcp.h dhcpv6.h \ - epoll_ctl.h flow.h fwd.h flow_table.h icmp.h icmp_flow.h inany.h iov.h \ - ip.h isolation.h lineread.h log.h migrate.h ndp.h netlink.h packet.h \ - passt.h pasta.h pcap.h pif.h repair.h serialise.h siphash.h tap.h tcp.h \ - tcp_buf.h tcp_conn.h tcp_internal.h tcp_splice.h tcp_vu.h udp.h \ - udp_flow.h udp_internal.h udp_vu.h util.h vhost_user.h virtio.h \ - vu_common.h + epoll_ctl.h flow.h fwd.h fwd_rule.h flow_table.h icmp.h icmp_flow.h \ + inany.h iov.h ip.h isolation.h lineread.h log.h migrate.h ndp.h \ + netlink.h packet.h passt.h pasta.h pcap.h pif.h repair.h serialise.h \ + siphash.h tap.h tcp.h tcp_buf.h tcp_conn.h tcp_internal.h tcp_splice.h \ + tcp_vu.h udp.h udp_flow.h udp_internal.h udp_vu.h util.h vhost_user.h \ + virtio.h vu_common.h HEADERS = $(PASST_HEADERS) seccomp.h C := \#include \nint main(){int a=getrandom(0, 0, 0);} diff --git a/fwd.c b/fwd.c index 62d344c3..e09b42fe 100644 --- a/fwd.c +++ b/fwd.c @@ -363,7 +363,7 @@ void fwd_rule_add(struct fwd_table *fwd, uint8_t proto, uint8_t flags, /* Flags which can be set from the caller */ const uint8_t allowed_flags = FWD_WEAK | FWD_SCAN | FWD_DUAL_STACK_ANY; unsigned num = (unsigned)last - first + 1; - struct fwd_rule *new; + struct fwd_rule_state *new; unsigned i, port; assert(!(flags & ~allowed_flags)); @@ -379,7 +379,7 @@ void fwd_rule_add(struct fwd_table *fwd, uint8_t proto, uint8_t flags, /* Check for any conflicting entries */ for (i = 0; i < fwd->count; i++) { char newstr[INANY_ADDRSTRLEN], rulestr[INANY_ADDRSTRLEN]; - const struct fwd_rule *rule = &fwd->rules[i]; + const struct fwd_rule *rule = &fwd->rules[i].rule; if (proto != rule->proto) /* Non-conflicting protocols */ @@ -400,36 +400,37 @@ void fwd_rule_add(struct fwd_table *fwd, uint8_t proto, uint8_t flags, } new = &fwd->rules[fwd->count++]; - new->proto = proto; - new->flags = flags; + new->rule.proto = proto; + new->rule.flags = flags; if (addr) { - new->addr = *addr; + new->rule.addr = *addr; } else { - new->addr = inany_any6; - new->flags |= FWD_DUAL_STACK_ANY; + new->rule.addr = inany_any6; + new->rule.flags |= FWD_DUAL_STACK_ANY; } - memset(new->ifname, 0, sizeof(new->ifname)); + memset(new->rule.ifname, 0, sizeof(new->rule.ifname)); if (ifname) { int ret; - ret = snprintf(new->ifname, sizeof(new->ifname), "%s", ifname); - if (ret <= 0 || (size_t)ret >= sizeof(new->ifname)) + ret = snprintf(new->rule.ifname, sizeof(new->rule.ifname), + "%s", ifname); + if (ret <= 0 || (size_t)ret >= sizeof(new->rule.ifname)) die("Invalid interface name: %s", ifname); } assert(first <= last); - new->first = first; - new->last = last; + new->rule.first = first; + new->rule.last = last; - new->to = to; + new->rule.to = to; new->socks = &fwd->socks[fwd->sock_count]; fwd->sock_count += num; - for (port = new->first; port <= new->last; port++) - new->socks[port - new->first] = -1; + for (port = new->rule.first; port <= new->rule.last; port++) + new->socks[port - new->rule.first] = -1; } /** @@ -465,7 +466,7 @@ const struct fwd_rule *fwd_rule_search(const struct fwd_table *fwd, if (hint >= 0) { char ostr[INANY_ADDRSTRLEN], rstr[INANY_ADDRSTRLEN]; - const struct fwd_rule *rule = &fwd->rules[hint]; + const struct fwd_rule *rule = &fwd->rules[hint].rule; assert((unsigned)hint < fwd->count); if (fwd_rule_match(rule, ini, proto)) @@ -479,8 +480,8 @@ const struct fwd_rule *fwd_rule_search(const struct fwd_table *fwd, } for (i = 0; i < fwd->count; i++) { - if (fwd_rule_match(&fwd->rules[i], ini, proto)) - return &fwd->rules[i]; + if (fwd_rule_match(&fwd->rules[i].rule, ini, proto)) + return &fwd->rules[i].rule; } return NULL; @@ -495,7 +496,7 @@ void fwd_rules_print(const struct fwd_table *fwd) unsigned i; for (i = 0; i < fwd->count; i++) { - const struct fwd_rule *rule = &fwd->rules[i]; + const struct fwd_rule *rule = &fwd->rules[i].rule; const char *percent = *rule->ifname ? "%" : ""; const char *weak = "", *scan = ""; char addr[INANY_ADDRSTRLEN]; @@ -532,7 +533,8 @@ void fwd_rules_print(const struct fwd_table *fwd) static int fwd_sync_one(const struct ctx *c, uint8_t pif, unsigned idx, const uint8_t *tcp, const uint8_t *udp) { - const struct fwd_rule *rule = &c->fwd[pif]->rules[idx]; + const struct fwd_rule_state *rs = &c->fwd[pif]->rules[idx]; + const struct fwd_rule *rule = &rs->rule; const union inany_addr *addr = fwd_rule_addr(rule); const char *ifname = rule->ifname; const uint8_t *map = NULL; @@ -553,7 +555,7 @@ static int fwd_sync_one(const struct ctx *c, uint8_t pif, unsigned idx, } for (port = rule->first; port <= rule->last; port++) { - int fd = rule->socks[port - rule->first]; + int fd = rs->socks[port - rule->first]; if (map && !bitmap_isset(map, port)) { /* We don't want to listen on this port */ @@ -561,7 +563,7 @@ static int fwd_sync_one(const struct ctx *c, uint8_t pif, unsigned idx, /* We already are, so stop */ epoll_del(c->epollfd, fd); close(fd); - rule->socks[port - rule->first] = -1; + rs->socks[port - rule->first] = -1; } continue; } @@ -593,7 +595,7 @@ static int fwd_sync_one(const struct ctx *c, uint8_t pif, unsigned idx, continue; } - rule->socks[port - rule->first] = fd; + rs->socks[port - rule->first] = fd; bound_one = true; } @@ -683,11 +685,11 @@ void fwd_listen_close(const struct fwd_table *fwd) unsigned i; for (i = 0; i < fwd->count; i++) { - const struct fwd_rule *rule = &fwd->rules[i]; + const struct fwd_rule_state *rs = &fwd->rules[i]; unsigned port; - for (port = rule->first; port <= rule->last; port++) { - int *fdp = &rule->socks[port - rule->first]; + for (port = rs->rule.first; port <= rs->rule.last; port++) { + int *fdp = &rs->socks[port - rs->rule.first]; if (*fdp >= 0) { close(*fdp); *fdp = -1; @@ -767,8 +769,8 @@ static bool has_scan_rules(const struct fwd_table *fwd, uint8_t proto) unsigned i; for (i = 0; i < fwd->count; i++) { - if (fwd->rules[i].proto == proto && - fwd->rules[i].flags & FWD_SCAN) + if (fwd->rules[i].rule.proto == proto && + fwd->rules[i].rule.flags & FWD_SCAN) return true; } return false; @@ -836,14 +838,14 @@ static void current_listen_map(uint8_t *map, const struct fwd_table *fwd, memset(map, 0, PORT_BITMAP_SIZE); for (i = 0; i < fwd->count; i++) { - const struct fwd_rule *rule = &fwd->rules[i]; + const struct fwd_rule_state *rs = &fwd->rules[i]; unsigned port; - if (rule->proto != proto) + if (rs->rule.proto != proto) continue; - for (port = rule->first; port <= rule->last; port++) { - if (rule->socks[port - rule->first] >= 0) + for (port = rs->rule.first; port <= rs->rule.last; port++) { + if (rs->socks[port - rs->rule.first] >= 0) bitmap_set(map, port); } } diff --git a/fwd.h b/fwd.h index beba0bf5..33600cbf 100644 --- a/fwd.h +++ b/fwd.h @@ -16,6 +16,7 @@ #include "bitmap.h" #include "inany.h" +#include "fwd_rule.h" struct flowside; @@ -26,32 +27,12 @@ void fwd_probe_ephemeral(void); void fwd_port_map_ephemeral(uint8_t *map); /** - * struct fwd_rule - Forwarding rule governing a range of ports - * @addr: Address to forward from - * @ifname: Interface to forward from - * @first: First port number to forward - * @last: Last port number to forward - * @to: Target port for @first, port n goes to @to + (n - @first) - * @proto: Protocol to forward - * @flags: Flag mask - * FWD_DUAL_STACK_ANY - match any IPv4 or IPv6 address (@addr should be ::) - * FWD_WEAK - Don't give an error if binds fail for some forwards - * FWD_SCAN - Only forward if the matching port in the target is listening + * struct fwd_rule_state - Forwarding rule and associated state + * @rule: Rule specification * @socks: Array of listening sockets for this entry - * - * FIXME: @addr and @ifname currently ignored for outbound tables */ -struct fwd_rule { - union inany_addr addr; - char ifname[IFNAMSIZ]; - in_port_t first; - in_port_t last; - in_port_t to; - uint8_t proto; -#define FWD_DUAL_STACK_ANY BIT(0) -#define FWD_WEAK BIT(1) -#define FWD_SCAN BIT(2) - uint8_t flags; +struct fwd_rule_state { + struct fwd_rule rule; int *socks; }; @@ -88,7 +69,7 @@ struct fwd_listen_ref { */ struct fwd_table { unsigned count; - struct fwd_rule rules[MAX_FWD_RULES]; + struct fwd_rule_state rules[MAX_FWD_RULES]; unsigned sock_count; int socks[MAX_LISTEN_SOCKS]; }; diff --git a/fwd_rule.h b/fwd_rule.h new file mode 100644 index 00000000..ae0e1d61 --- /dev/null +++ b/fwd_rule.h @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later + * Copyright Red Hat + * Author: Stefano Brivio + * Author: David Gibson + * + * Forwarding rule definitions shared between passt/pasta and pesto + */ + +#ifndef FWD_RULE_H +#define FWD_RULE_H + +#include +#include +#include + +#include "inany.h" + +/** + * struct fwd_rule - Forwarding rule governing a range of ports + * @addr: Address to forward from + * @ifname: Interface to forward from + * @first: First port number to forward + * @last: Last port number to forward + * @to: Target port for @first, port n goes to @to + (n - @first) + * @proto: Protocol to forward + * @flags: Flag mask + * FWD_DUAL_STACK_ANY - match any IPv4 or IPv6 address (@addr should be ::) + * FWD_WEAK - Don't give an error if binds fail for some forwards + * FWD_SCAN - Only forward if the matching port in the target is listening + */ +struct fwd_rule { + union inany_addr addr; + char ifname[IFNAMSIZ]; + in_port_t first; + in_port_t last; + in_port_t to; + uint8_t proto; +#define FWD_DUAL_STACK_ANY BIT(0) +#define FWD_WEAK BIT(1) +#define FWD_SCAN BIT(2) + uint8_t flags; +}; + +#endif /* FWD_RULE_H */ -- 2.53.0