On Tue, Aug 19, 2025 at 11:09:59PM -0400, Jon Maloy wrote: > When communicating with remote hosts on the local network, some guest > applications want to see the real MAC address of that host instead > of PASST/PASTA's own tap address. The flow_common structure is a > convenient location for storing that address, so we do that in this > commit. > > Note that we donīt add actual usage of this address here, that will > be done in later commits. > > Signed-off-by: Jon Maloy > --- > flow.c | 19 ++++++++++++++++++- > flow.h | 2 ++ > 2 files changed, 20 insertions(+), 1 deletion(-) > > diff --git a/flow.c b/flow.c > index feefda3..d7b3fd1 100644 > --- a/flow.c > +++ b/flow.c > @@ -20,6 +20,7 @@ > #include "flow.h" > #include "flow_table.h" > #include "repair.h" > +#include "netlink.h" > > const char *flow_state_str[] = { > [FLOW_STATE_FREE] = "FREE", > @@ -438,18 +439,27 @@ struct flowside *flow_target(const struct ctx *c, union flow *flow, > { > char estr[INANY_ADDRSTRLEN], fstr[INANY_ADDRSTRLEN]; > struct flow_common *f = &flow->f; > - const struct flowside *ini = &f->side[INISIDE]; > + struct flowside *ini = &f->side[INISIDE]; I don't see anywhere you're modifying *ini. Leftover from an older draft? > struct flowside *tgt = &f->side[TGTSIDE]; > uint8_t tgtpif = PIF_NONE; > + int ifi; > > ASSERT(flow_new_entry == flow && f->state == FLOW_STATE_INI); > ASSERT(f->type == FLOW_TYPE_NONE); > ASSERT(f->pif[INISIDE] != PIF_NONE && f->pif[TGTSIDE] == PIF_NONE); > ASSERT(flow->f.state == FLOW_STATE_INI); > + memcpy(f->tap_omac, c->our_tap_mac, ETH_ALEN); > > switch (f->pif[INISIDE]) { > case PIF_TAP: > tgtpif = fwd_nat_from_tap(c, proto, ini, tgt); Attempting to preserve MAC probably only makes sense if tgtpif == PIF_HOST (which I think is always true for now, but maybe not forever). > + > + /* If there is no NAT, the remote host might be on the template As before, I'm not sure if conditioning this no no NAT makes sense. > + * interface's local network segment. If so, insert its MAC address > + */ > + ifi = inany_v4(&ini->oaddr) ? c->ifi4 : c->ifi6; > + if (!fwd_inany_nat(c, &ini->oaddr)) > + nl_neigh_mac_get(nl_sock, &ini->oaddr, ifi, f->tap_omac); It should be tgt->eaddr, rather than ini->oaddr. They'll usually be equal, but logically we want to look up based on the host side address. As noted in general comments on earlier versions, this lookup will fail (give our_tap_mac) if the host hasn't contacted this peer before (so it's not in the neigh table). Can we defer this lookup until we get a reply, to avoid that problem? > break; > > case PIF_SPLICE: > @@ -458,6 +468,13 @@ struct flowside *flow_target(const struct ctx *c, union flow *flow, > > case PIF_HOST: > tgtpif = fwd_nat_from_host(c, proto, ini, tgt); > + > + /* If there is no NAT, the remote host might be on the template > + * interface's local network segment. If so, insert its MAC address > + */ > + ifi = inany_v4(&ini->eaddr) ? c->ifi4 : c->ifi6; > + if (!fwd_inany_nat(c, &ini->eaddr)) > + nl_neigh_mac_get(nl_sock, &ini->eaddr, ifi, f->tap_omac); > break; > > default: > diff --git a/flow.h b/flow.h > index cac618a..29c8bc6 100644 > --- a/flow.h > +++ b/flow.h > @@ -177,6 +177,7 @@ int flowside_connect(const struct ctx *c, int s, > * @type: Type of packet flow > * @pif[]: Interface for each side of the flow > * @side[]: Information for each side of the flow > + * @tap_omac: MAC address of remote endpoint as seen from the guest > */ > struct flow_common { > #ifdef __GNUC__ > @@ -192,6 +193,7 @@ struct flow_common { > #endif > uint8_t pif[SIDES]; > struct flowside side[SIDES]; > + unsigned char tap_omac[6]; > }; > > #define FLOW_INDEX_BITS 17 /* 128k - 1 */ -- David Gibson (he or they) | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you, not the other way | around. http://www.ozlabs.org/~dgibson