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 | 57 +++++++++++++++++++++++++++++++--------------------------
fwd.c | 21 +++++++--------------
fwd.h | 7 +++----
3 files changed, 41 insertions(+), 44 deletions(-)
diff --git a/flow.c b/flow.c
index 0d97f161..99e4f7f6 100644
--- a/flow.c
+++ b/flow.c
@@ -530,6 +530,8 @@ 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;
+ const struct fwd_ports *fwd;
uint8_t tgtpif = PIF_NONE;
ASSERT(flow_new_entry == flow && f->state == FLOW_STATE_INI);
@@ -537,30 +539,6 @@ struct flowside *flow_target(const struct ctx *c, union flow *flow,
ASSERT(f->pif[INISIDE] != PIF_NONE && f->pif[TGTSIDE] == PIF_NONE);
ASSERT(flow->f.state == FLOW_STATE_INI);
- if (pif_is_socket(f->pif[INISIDE])) {
- const struct fwd_ports *fwd;
-
- if (f->pif[INISIDE] == PIF_HOST && proto == IPPROTO_TCP)
- fwd = &c->tcp.fwd_in;
- else if (f->pif[INISIDE] == PIF_HOST && proto == IPPROTO_UDP)
- fwd = &c->udp.fwd_in;
- else if (f->pif[INISIDE] == PIF_SPLICE && proto == IPPROTO_TCP)
- fwd = &c->tcp.fwd_out;
- else if (f->pif[INISIDE] == PIF_SPLICE && proto == IPPROTO_UDP)
- fwd = &c->udp.fwd_out;
- else
- goto nofwd;
-
- if (!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
- */
- flow_dbg(flow, "Unexpected missing forward rule");
- goto nofwd;
- }
- }
-
switch (f->pif[INISIDE]) {
case PIF_TAP:
memcpy(f->tap_omac, MAC_UNDEF, ETH_ALEN);
@@ -568,11 +546,31 @@ struct flowside *flow_target(const struct ctx *c, union flow *flow,
break;
case PIF_SPLICE:
- tgtpif = fwd_nat_from_splice(c, proto, ini, tgt);
+ if (proto == IPPROTO_TCP)
+ fwd = &c->tcp.fwd_out;
+ else if (proto == IPPROTO_UDP)
+ fwd = &c->udp.fwd_out;
+ else
+ goto nofwd;
+
+ if (!(rule = fwd_rule_search(fwd, ini)))
+ goto norule;
+
+ tgtpif = fwd_nat_from_splice(rule, proto, ini, tgt);
break;
case PIF_HOST:
- tgtpif = fwd_nat_from_host(c, proto, ini, tgt);
+ if (proto == IPPROTO_TCP)
+ fwd = &c->tcp.fwd_in;
+ else if (proto == IPPROTO_UDP)
+ fwd = &c->udp.fwd_in;
+ else
+ goto nofwd;
+
+ if (!(rule = fwd_rule_search(fwd, ini)))
+ goto norule;
+
+ tgtpif = fwd_nat_from_host(c, rule, proto, ini, tgt);
fwd_neigh_mac_get(c, &tgt->oaddr, f->tap_omac);
break;
default:
@@ -586,6 +584,13 @@ struct flowside *flow_target(const struct ctx *c, union flow *flow,
flow_set_state(f, FLOW_STATE_TGT);
return tgt;
+norule:
+ /* This shouldn't happen, because if there's no rule for it we should
+ * have no listening socket that would let us get here
+ */
+ flow_dbg(flow, "Missing forward rule");
+ flow_log_details_(f, LOG_DEBUG, f->state);
+
nofwd:
flow_err(flow, "No rules to forward %s %s [%s]:%hu -> [%s]:%hu",
pif_name(f->pif[INISIDE]), ipproto_name(proto),
diff --git a/fwd.c b/fwd.c
index 99f4193e..97d8758a 100644
--- a/fwd.c
+++ b/fwd.c
@@ -409,7 +409,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;
}
}
@@ -982,7 +981,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)
@@ -990,7 +989,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) ||
@@ -1014,11 +1013,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 = rule->to + (ini->oport - rule->first);
return PIF_HOST;
}
@@ -1062,6 +1057,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)
@@ -1069,15 +1065,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 = rule->to + (ini->oport - rule->first);
if (!c->no_splice && inany_is_loopback(&ini->eaddr) &&
(proto == IPPROTO_TCP || proto == IPPROTO_UDP)) {
diff --git a/fwd.h b/fwd.h
index 954db021..184c1767 100644
--- a/fwd.h
+++ b/fwd.h
@@ -85,7 +85,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 mapped port number
* @sock_count: Number of entries used in @socks
* @socks: Listening sockets for forwarding
*/
@@ -96,7 +95,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 sock_count;
int socks[MAX_LISTEN_SOCKS];
};
@@ -120,9 +118,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