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=202508 header.b=d9ZKCBdl; dkim-atps=neutral Received: from mail.ozlabs.org (gandalf.ozlabs.org [150.107.74.76]) by passt.top (Postfix) with ESMTPS id C91155A0619 for ; Fri, 03 Oct 2025 07:33:46 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gibson.dropbear.id.au; s=202508; t=1759469623; bh=SSETNITz6mMS5xNFdw+F2853VL7DOMymzeNYToY+FMk=; h=Date:From:To:Cc:Subject:References:In-Reply-To:From; b=d9ZKCBdl7LKHobNLlN+CXRHov0fmBrpXhdLqEdxL4ydyABbpg4IYETQb0qu2Ym7pj 0on7bO412MwW+OxlXB6NA7eJIl1KN62sku32BVqjY8Aqdc0unimRDcHVB7BvgpzbIb 7nK/fECRUBm6rjj9EEDARp6c453kcmXBf/RuymJ4Tqi57x6qgyqfmjJ9okJrcx8g6h gld9DzWz7BAsDlnbbloxX8QFDcJ79/Sd0xCcdbiE8gSLLjXK8Gqa5oEhUedwnvLzVW PjfKChsQoZ1Mu/eHLiR9n8cX8Gf8/GT9+Fa/ARucjFV1L0RRkApIhHXW/gv/1T4+0X 7LdEyBJTC7KMQ== Received: by gandalf.ozlabs.org (Postfix, from userid 1007) id 4cdHQH6CmHz4wBj; Fri, 3 Oct 2025 15:33:43 +1000 (AEST) Date: Fri, 3 Oct 2025 14:48:57 +1000 From: David Gibson To: Jon Maloy Subject: Re: [PATCH v12 4/9] arp/ndp: respond with true MAC address of LAN local remote hosts Message-ID: References: <20251003003412.588801-1-jmaloy@redhat.com> <20251003003412.588801-5-jmaloy@redhat.com> MIME-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha512; protocol="application/pgp-signature"; boundary="2+T2JGLE7rETD1ro" Content-Disposition: inline In-Reply-To: <20251003003412.588801-5-jmaloy@redhat.com> Message-ID-Hash: 6WXJQS7V6NEEIPCRMQ6N6LRGXHUGTHUP X-Message-ID-Hash: 6WXJQS7V6NEEIPCRMQ6N6LRGXHUGTHUP 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: sbrivio@redhat.com, dgibson@redhat.com, passt-dev@passt.top 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: --2+T2JGLE7rETD1ro Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable On Thu, Oct 02, 2025 at 08:34:07PM -0400, Jon Maloy wrote: > When we receive an ARP request or NDP neigbour solicitation over > the tap interface for a host on the local network segment attached > to the template interface, we respond with that host's real MAC > address, if available. >=20 > Signed-off-by: Jon Maloy > Reviewed-by: David Gibson >=20 > --- > v3: - Added helper function to find out if a remote ip address is subject > to NAT. This filters out local host addresses which should be > presented with the passt/pasta local MAC address 9a:55:9a:55:9a:55 = even > though it is on the local segment. > - Adapted to the change in nl_mac_get() function, so that we now cons= ider > only the template interface when checking the ARP/NDP table. > v4: - Moved NAT check into the function nat_outbound() to obtain more > precise criteria for when NAT is used. We may in theory > have NAT even if original and translated addresses are equal, and > we want to catch this case. > - I chose to keep the wrapper funtion inany_nat(), but moved it to > fwd.h/fwd.c and renamed it to fwd_inany_nat(). > v5: - Simplified criteria for when we do ARP/NDP lookup. Now, we > just try with the potentially translated address after an > attempted NAT check. > - Using the new ARP/NDP cache table instead of using netlink > directly. > v6: - Fixes after feedback from David: > - Renamed nat_outbound() to fwd_nat_outbound() > - Eliminated unnecessary temporary variable in arp.c::arp() > v12: - Some minor changes after feedback from Stefano > --- > arp.c | 9 +++++++-- > fwd.c | 8 ++++---- > fwd.h | 2 ++ > inany.c | 1 + > ndp.c | 8 ++++++++ > 5 files changed, 22 insertions(+), 6 deletions(-) >=20 > diff --git a/arp.c b/arp.c > index b08780f..a95c377 100644 > --- a/arp.c > +++ b/arp.c > @@ -69,6 +69,7 @@ static bool ignore_arp(const struct ctx *c, > */ > int arp(const struct ctx *c, struct iov_tail *data) > { > + union inany_addr tgt, tgt_nat; > struct { > struct ethhdr eh; > struct arphdr ah; > @@ -102,8 +103,12 @@ int arp(const struct ctx *c, struct iov_tail *data) > resp.ah.ar_hln =3D ah->ar_hln; > resp.ah.ar_pln =3D ah->ar_pln; > =20 > - /* ARP message */ > - memcpy(resp.am.sha, c->our_tap_mac, sizeof(resp.am.sha)); > + /* MAC address to return in ARP message */ > + inany_from_af(&tgt, AF_INET, am->tip); > + fwd_nat_outbound(c, &tgt, &tgt_nat); > + fwd_neigh_mac_get(c, &tgt_nat, resp.am.sha); > + /* Rest of ARP message */ > memcpy(resp.am.sip, am->tip, sizeof(resp.am.sip)); > memcpy(resp.am.tha, am->sha, sizeof(resp.am.tha)); > memcpy(resp.am.tip, am->sip, sizeof(resp.am.tip)); > diff --git a/fwd.c b/fwd.c > index ade97c8..a69d84d 100644 > --- a/fwd.c > +++ b/fwd.c > @@ -522,7 +522,7 @@ static bool fwd_guest_accessible(const struct ctx *c, > } > =20 > /** > - * nat_outbound() - Apply address translation for outbound (TAP to HOST) > + * fwd_nat_outbound() - Apply address translation for outbound (TAP to H= OST) > * @c: Execution context > * @addr: Input address (as seen on TAP interface) > * @translated: Output address (as seen on HOST interface) > @@ -530,8 +530,8 @@ static bool fwd_guest_accessible(const struct ctx *c, > * Only handles translations that depend *only* on the address. Anything > * related to specific ports or flows is handled elsewhere. > */ > -static void nat_outbound(const struct ctx *c, const union inany_addr *ad= dr, > - union inany_addr *translated) > +void fwd_nat_outbound(const struct ctx *c, const union inany_addr *addr, > + union inany_addr *translated) > { > if (inany_equals4(addr, &c->ip4.map_host_loopback)) > *translated =3D inany_loopback4; > @@ -565,7 +565,7 @@ uint8_t fwd_nat_from_tap(const struct ctx *c, uint8_t= proto, > inany_equals6(&ini->oaddr, &c->ip6.dns_match)) > tgt->eaddr.a6 =3D c->ip6.dns_host; > else > - nat_outbound(c, &ini->oaddr, &tgt->eaddr); > + fwd_nat_outbound(c, &ini->oaddr, &tgt->eaddr); > =20 > tgt->eport =3D ini->oport; > =20 > diff --git a/fwd.h b/fwd.h > index 6ca743c..f91fa55 100644 > --- a/fwd.h > +++ b/fwd.h > @@ -50,6 +50,8 @@ void fwd_scan_ports_init(struct ctx *c); > =20 > bool nat_inbound(const struct ctx *c, const union inany_addr *addr, > union inany_addr *translated); > +void fwd_nat_outbound(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, > diff --git a/inany.c b/inany.c > index 65a39f9..7680439 100644 > --- a/inany.c > +++ b/inany.c > @@ -16,6 +16,7 @@ > #include "ip.h" > #include "siphash.h" > #include "inany.h" > +#include "fwd.h" > =20 > const union inany_addr inany_loopback4 =3D INANY_INIT4(IN4ADDR_LOOPBACK_= INIT); > const union inany_addr inany_any4 =3D INANY_INIT4(IN4ADDR_ANY_INIT); > diff --git a/ndp.c b/ndp.c > index d7f64a3..6bba0a8 100644 > --- a/ndp.c > +++ b/ndp.c > @@ -196,6 +196,7 @@ static void ndp_send(const struct ctx *c, const struc= t in6_addr *dst, > static void ndp_na(const struct ctx *c, const struct in6_addr *dst, > const struct in6_addr *addr) > { > + union inany_addr tgt, tgt_nat; > struct ndp_na na =3D { > .ih =3D { > .icmp6_type =3D NA, > @@ -215,6 +216,13 @@ static void ndp_na(const struct ctx *c, const struct= in6_addr *dst, > =20 > memcpy(na.target_l2_addr.mac, c->our_tap_mac, ETH_ALEN); > =20 > + /* Respond with recorded MAC address if remote host's address > + * or NAT translated address can be found in NDP table. > + */ > + inany_from_af(&tgt, AF_INET6, addr); > + fwd_nat_outbound(c, &tgt, &tgt_nat); > + fwd_neigh_mac_get(c, &tgt_nat, na.target_l2_addr.mac); You do indeed need nat_outbound() here, and as noted on the previous patch you need nat_inbound() for unsolicited NAs triggered by host neighbour updates. But you want to avoid doing both an inbound and outbound NAT for the same operation, which might require some restructuring here. Or, I guess, you could convert the whole neighbour table to be in terms of guest side addresses, in which case you'd remove the NAT here, and instead need a nat_inbound() before you insert things into the table. > ndp_send(c, dst, &na, sizeof(na)); > } > =20 > --=20 > 2.50.1 >=20 --=20 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 --2+T2JGLE7rETD1ro Content-Type: application/pgp-signature; name=signature.asc -----BEGIN PGP SIGNATURE----- iQIzBAEBCgAdFiEEO+dNsU4E3yXUXRK2zQJF27ox2GcFAmjfVbgACgkQzQJF27ox 2Gck4Q/8DFyadqlI56cQnrIw9K5St9vJgOILU4lxRJqWAZa9yOfCTcnAH/09S1c2 GKfVasn3BCHxaIK85XbUDeIbReCpbsWJ/VrsQjmPWU9KXciEjqz980zE/pMHrPt/ MaXWdbiuNX/5pKIwzt7ECKiWW5BXcoTRa2CYS4A3Gc6wGjfNxxV1O+/hB9QUT+UH mrOt3VCT27Wn3G38//rXBsYep/lsnjiAahiofm83TSntbDqmb1KMMd6xkNDdGVxs I9k8DD3N01WpT70sCcQRYfJGe4iWwcwK68/F36VbB4w+W6ey/V9X7asEw4zWwf7t cW7/JA6d3AvYHu/NcxdUSzdhBjSO4RetIMf8gwTG+iF+bGABc7WxI7eaFam7KcVC 2B+QZxsfGQWx9J4JPF1hrv8GZNr6fhCqst4r4/KJ8EwUZ4Pc1BXmgizvhzh/Fu6z 8zJ0nnmJ9BLHvT6PcYSPVKXHJIB7RvMCOlPBKZThSMXQoF9ElWQs0ytQCW2n4WST 59Xi8D1BZFPyCKiEMHt+IHgzLFE2zUacrNCvo5PmsZLXoEhUIb+Z7SofFea64ZLU QkRL8EPYr2zvl4TlhCeVeeapEovPqbk9xFKZP6DZjpyvVWoEa847YjS3b9n404EO SboaWUWsMNU/0kPTNNf/sDrZJfOL5lSwmvAfZux8+ozWNofqtoQ= =wxkb -----END PGP SIGNATURE----- --2+T2JGLE7rETD1ro--