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=202512 header.b=S1g9Jta5; dkim-atps=neutral Received: from mail.ozlabs.org (gandalf.ozlabs.org [150.107.74.76]) by passt.top (Postfix) with ESMTPS id A9ED35A0627 for ; Thu, 08 Jan 2026 03:29:56 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gibson.dropbear.id.au; s=202512; t=1767839390; bh=uNtVl5YyDNwKa8pCGBv3sp0bVBGBEYX81iEpfFIvlzw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=S1g9Jta5+v+UrLAgnjuTnXp9qzeVkHwC114U4tbSqvD+AWMnJdSIVmLqvJKRRMxoH GFiJEXT4s9UQAeRHABBjuxHl+zyXHZmIXfBYYgq9FKUo9UdqQQw+Fso7+llg7lkLTU 2vskhMuj3jF7BqPuUmK2QQRq1VVA2eLyCpwa+JDW+yeKQRKhDH514vvbRZTnyoNgJA Kyyh2gR3k1+iDXxzXeYOPby7T+Ou4IwCunWoX/uFWsB8T+glgyy6U15ksme1Lno/Vy 0jW2oszvE7RO4dC/g6+n23jfiihqyT8zk9B1dtFuQpLXISm4vmQInfCWFzdHlhLaF/ qKEfB27nPWhyQ== Received: by gandalf.ozlabs.org (Postfix, from userid 1007) id 4dmplL4XKWz4wRP; Thu, 08 Jan 2026 13:29:50 +1100 (AEDT) From: David Gibson To: Stefano Brivio , passt-dev@passt.top Subject: [PATCH v3 12/14] fwd: Remap ports based directly on forwarding rule Date: Thu, 8 Jan 2026 13:29:46 +1100 Message-ID: <20260108022948.2657573-13-david@gibson.dropbear.id.au> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260108022948.2657573-1-david@gibson.dropbear.id.au> References: <20260108022948.2657573-1-david@gibson.dropbear.id.au> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Message-ID-Hash: NY6PM2F735TRZNOZVTAI3LB6QOT4PYO4 X-Message-ID-Hash: NY6PM2F735TRZNOZVTAI3LB6QOT4PYO4 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: Currently we remap port numbers based on the legacy delta[] array, which is indexed only by original port number, not the listening address. Now that we look up a forwarding rule entry in flow_target(), we can use this entry to directly determine the correct remapped port. Implement this, and remove the old delta[] array. Link: https://bugs.passt.top/show_bug.cgi?id=187 Signed-off-by: David Gibson --- flow.c | 7 ++++--- fwd.c | 21 +++++++-------------- fwd.h | 7 +++---- 3 files changed, 14 insertions(+), 21 deletions(-) diff --git a/flow.c b/flow.c index 045e9712..38f88732 100644 --- a/flow.c +++ b/flow.c @@ -493,6 +493,7 @@ struct flowside *flow_target(const struct ctx *c, union flow *flow, struct flow_common *f = &flow->f; const struct flowside *ini = &f->side[INISIDE]; struct flowside *tgt = &f->side[TGTSIDE]; + const struct fwd_rule *rule = NULL; uint8_t tgtpif = PIF_NONE; ASSERT(flow_new_entry == flow && f->state == FLOW_STATE_INI); @@ -514,7 +515,7 @@ struct flowside *flow_target(const struct ctx *c, union flow *flow, else goto nofwd; - if (!fwd_rule_search(fwd, ini)) { + if (!(rule = fwd_rule_search(fwd, ini))) { /* This shouldn't happen, because if there's no rule for * it we should have no listening socket that would let * us get here @@ -531,11 +532,11 @@ struct flowside *flow_target(const struct ctx *c, union flow *flow, break; case PIF_SPLICE: - tgtpif = fwd_nat_from_splice(c, proto, ini, tgt); + tgtpif = fwd_nat_from_splice(rule, proto, ini, tgt); break; case PIF_HOST: - tgtpif = fwd_nat_from_host(c, proto, ini, tgt); + tgtpif = fwd_nat_from_host(c, rule, proto, ini, tgt); fwd_neigh_mac_get(c, &tgt->oaddr, f->tap_omac); break; default: diff --git a/fwd.c b/fwd.c index 633ba5db..7c4575ff 100644 --- a/fwd.c +++ b/fwd.c @@ -405,7 +405,6 @@ void fwd_rule_add(struct fwd_ports *fwd, uint8_t flags, /* Fill in the legacy forwarding data structures to match the table */ if (!(new->flags & FWD_SCAN)) bitmap_set(fwd->map, port); - fwd->delta[port] = new->to - new->first; } } @@ -978,7 +977,7 @@ uint8_t fwd_nat_from_tap(const struct ctx *c, uint8_t proto, /** * fwd_nat_from_splice() - Determine to forward a flow from the splice interface - * @c: Execution context + * @rule: Forwarding rule to apply * @proto: Protocol (IP L4 protocol number) * @ini: Flow address information of the initiating side * @tgt: Flow address information on the target side (updated) @@ -986,7 +985,7 @@ uint8_t fwd_nat_from_tap(const struct ctx *c, uint8_t proto, * Return: pif of the target interface to forward the flow to, PIF_NONE if the * flow cannot or should not be forwarded at all. */ -uint8_t fwd_nat_from_splice(const struct ctx *c, uint8_t proto, +uint8_t fwd_nat_from_splice(const struct fwd_rule *rule, uint8_t proto, const struct flowside *ini, struct flowside *tgt) { if (!inany_is_loopback(&ini->eaddr) || @@ -1010,11 +1009,7 @@ uint8_t fwd_nat_from_splice(const struct ctx *c, uint8_t proto, /* But for UDP preserve the source port */ tgt->oport = ini->eport; - tgt->eport = ini->oport; - if (proto == IPPROTO_TCP) - tgt->eport += c->tcp.fwd_out.delta[tgt->eport]; - else if (proto == IPPROTO_UDP) - tgt->eport += c->udp.fwd_out.delta[tgt->eport]; + tgt->eport = ini->oport - rule->first + rule->to; return PIF_HOST; } @@ -1058,6 +1053,7 @@ bool nat_inbound(const struct ctx *c, const union inany_addr *addr, /** * fwd_nat_from_host() - Determine to forward a flow from the host interface * @c: Execution context + * @rule: Forwarding rule to apply * @proto: Protocol (IP L4 protocol number) * @ini: Flow address information of the initiating side * @tgt: Flow address information on the target side (updated) @@ -1065,15 +1061,12 @@ bool nat_inbound(const struct ctx *c, const union inany_addr *addr, * Return: pif of the target interface to forward the flow to, PIF_NONE if the * flow cannot or should not be forwarded at all. */ -uint8_t fwd_nat_from_host(const struct ctx *c, uint8_t proto, +uint8_t fwd_nat_from_host(const struct ctx *c, + const struct fwd_rule *rule, uint8_t proto, const struct flowside *ini, struct flowside *tgt) { /* Common for spliced and non-spliced cases */ - tgt->eport = ini->oport; - if (proto == IPPROTO_TCP) - tgt->eport += c->tcp.fwd_in.delta[tgt->eport]; - else if (proto == IPPROTO_UDP) - tgt->eport += c->udp.fwd_in.delta[tgt->eport]; + tgt->eport = ini->oport - rule->first + rule->to; if (!c->no_splice && inany_is_loopback(&ini->eaddr) && (proto == IPPROTO_TCP || proto == IPPROTO_UDP)) { diff --git a/fwd.h b/fwd.h index a10bdbb4..cfe9ed46 100644 --- a/fwd.h +++ b/fwd.h @@ -82,7 +82,6 @@ enum fwd_ports_mode { * @count: Number of forwarding rules * @rules: Array of forwarding rules * @map: Bitmap describing which ports are forwarded - * @delta: Offset between the original destination and mapped port number * @listen_sock_count: Number of entries used in @listen_socks * @listen_socks: Listening sockets for forwarding */ @@ -93,7 +92,6 @@ struct fwd_ports { unsigned count; struct fwd_rule rules[MAX_FWD_RULES]; uint8_t map[PORT_BITMAP_SIZE]; - in_port_t delta[NUM_PORTS]; unsigned listen_sock_count; int listen_socks[MAX_LISTEN_SOCKS]; }; @@ -117,9 +115,10 @@ bool nat_inbound(const struct ctx *c, const union inany_addr *addr, union inany_addr *translated); uint8_t fwd_nat_from_tap(const struct ctx *c, uint8_t proto, const struct flowside *ini, struct flowside *tgt); -uint8_t fwd_nat_from_splice(const struct ctx *c, uint8_t proto, +uint8_t fwd_nat_from_splice(const struct fwd_rule *rule, uint8_t proto, const struct flowside *ini, struct flowside *tgt); -uint8_t fwd_nat_from_host(const struct ctx *c, uint8_t proto, +uint8_t fwd_nat_from_host(const struct ctx *c, + const struct fwd_rule *rule, uint8_t proto, const struct flowside *ini, struct flowside *tgt); void fwd_neigh_table_update(const struct ctx *c, const union inany_addr *addr, const uint8_t *mac, bool permanent); -- 2.52.0