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=hpDSy3OP; dkim-atps=neutral Received: from mail.ozlabs.org (mail.ozlabs.org [IPv6:2404:9400:2221:ea00::3]) by passt.top (Postfix) with ESMTPS id C73BF5A0271 for ; Mon, 08 Sep 2025 06:00:36 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gibson.dropbear.id.au; s=202508; t=1757304034; bh=jpHtswkk9AOipouLTpA5WNvJ7n9imMlct46NCwWS8HE=; h=Date:From:To:Cc:Subject:References:In-Reply-To:From; b=hpDSy3OPh9ty6VZ9yA6s1G0121kVIrarxGimVvBGDs6gEDUz+H7b0Y+aWfy3rKhvW 3Ov2Io7ChNKMMvXe2+Lb/FcPPUoXTbVvWKBFtToM3B7Xwoz9xefgBKINaeBzNuVi3l Ne2DppHyzyh2mqehG4QhsCbh09lHOociQmn678aHa65BWIO79NPL2dRzZ2cEdECoCB QzpJwZL2MoXgVlBanGT/q2tmfPEMmfla7/sAms98HPwz/4jxLBBJjU7nq3yxMyZYc6 86GoYPWh4wkq0cxIne6OQXqmP23chgFYHTo+TVK2zlCi97os376FLUUkT8bDbJQHt2 cIRj7xszJr5aw== Received: by gandalf.ozlabs.org (Postfix, from userid 1007) id 4cKtXL0w9Lz4w9y; Mon, 8 Sep 2025 14:00:34 +1000 (AEST) Date: Mon, 8 Sep 2025 14:00:29 +1000 From: David Gibson To: Volker Diels-Grabsch Subject: Re: [PATCH] Send an initial ARP request to resolve the guest IP address Message-ID: References: <20250907110108.18730-1-v@njh.eu> MIME-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha512; protocol="application/pgp-signature"; boundary="QVXBDDpUyKZny5z4" Content-Disposition: inline In-Reply-To: <20250907110108.18730-1-v@njh.eu> Message-ID-Hash: QYSL5S26JJ4WX6N7NQMUVWHEOK3DQ5W2 X-Message-ID-Hash: QYSL5S26JJ4WX6N7NQMUVWHEOK3DQ5W2 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: 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: --QVXBDDpUyKZny5z4 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable On Sun, Sep 07, 2025 at 01:01:08PM +0200, Volker Diels-Grabsch wrote: > When restarting passt while QEMU keeps running with a configured > "reconnect-ms" setting, the port forwardings will stop working until > the guest sends some outgoing network traffic. >=20 > Reason: Although QEMU reconnects successfully to the unix domain > socket of the new passt process, that one no longer knows the guest's > MAC address and uses instead a broadcast MAC address. However, this > is ignored by the guest, at least if the guest runs Linux. Huh... I thought Linux would respond to that. I wonder if there's some sysctl config or version difference going on here. > Only after > the guest sends some network package on its own initiative, passt will [Aside: Although "packet" and "package" usually mean the same thing in English, it's always "network packets" not "network packages" and always "software packages" not "software packets"] > know the MAC address and will be able to establish forwarded > connections. >=20 > This change fixes this issue by sending an ARP request to resolve the > guest's MAC address via its IP address, which we do know, right after > the unix domain socket (re)connection. Right. The guest doesn't necessarily use the IP we give it, but it usually will, so this will work most of the time. > The only case where the IP is "wrong" would be if the configuration > changed, and/or on the very first start right after qemu started. But > in those cases, we just wouldn't get an ARP response, and can't do > anything until we receive the guest's DHCP request - just as before. > In other words, in the worst case an ARP request would be harmless. Right. This seems like a good idea to me. It won't help in all cases, but it will help in some, and I can't see any harm it could do. Some comments on the implementation details below. > Signed-off-by: Volker Diels-Grabsch > --- > arp.c | 34 ++++++++++++++++++++++++++++++++++ > arp.h | 1 + > tap.c | 15 +++++++++++++-- > 3 files changed, 48 insertions(+), 2 deletions(-) >=20 > diff --git a/arp.c b/arp.c > index 44677ad..561581a 100644 > --- a/arp.c > +++ b/arp.c > @@ -112,3 +112,37 @@ int arp(const struct ctx *c, struct iov_tail *data) > =20 > return 1; > } > + > +/** > + * send_initial_arp_req() - Send initial ARP request to retrieve guest M= AC address Wrap to 80 columns, please. Also, since this is exposed from this module the name should start with 'arp_'. > + * @c: Execution context > + */ > +void send_initial_arp_req(const struct ctx *c) > +{ > + struct { > + struct ethhdr eh; > + struct arphdr ah; > + struct arpmsg am; > + } __attribute__((__packed__)) req; > + > + /* Ethernet header */ > + req.eh.h_proto =3D htons(ETH_P_ARP); > + memcpy(req.eh.h_dest, c->guest_mac, sizeof(req.eh.h_dest)); At this point we expect guest_mac to be the broadcast address, but it seems like explicitly using broadcast would be a little more robust if that changes at some point. > + memcpy(req.eh.h_source, c->our_tap_mac, sizeof(req.eh.h_source)); > + > + /* ARP header */ > + req.ah.ar_op =3D htons(ARPOP_REQUEST); > + req.ah.ar_hrd =3D htons(ARPHRD_ETHER); > + req.ah.ar_pro =3D htons(ETH_P_IP); > + req.ah.ar_hln =3D ETH_ALEN; > + req.ah.ar_pln =3D 4; > + > + /* ARP message */ > + memcpy(req.am.sha, c->our_tap_mac, sizeof(req.am.sha)); > + memcpy(req.am.sip, &c->ip4.our_tap_addr, sizeof(req.am.sip)); > + memcpy(req.am.tha, c->guest_mac, sizeof(req.am.tha)); > + memcpy(req.am.tip, &c->ip4.addr, sizeof(req.am.tip)); > + > + info("sending initial ARP request to retrieve guest MAC address after r= econnect"); > + tap_send_single(c, &req, sizeof(req)); > +} > diff --git a/arp.h b/arp.h > index 86bcbf8..5490144 100644 > --- a/arp.h > +++ b/arp.h > @@ -21,5 +21,6 @@ struct arpmsg { > } __attribute__((__packed__)); > =20 > int arp(const struct ctx *c, struct iov_tail *data); > +void send_initial_arp_req(const struct ctx *c); > =20 > #endif /* ARP_H */ > diff --git a/tap.c b/tap.c > index 7ba6399..47dedd5 100644 > --- a/tap.c > +++ b/tap.c > @@ -1355,6 +1355,16 @@ static void tap_start_connection(const struct ctx = *c) > ev.events =3D EPOLLIN | EPOLLRDHUP; > ev.data.u64 =3D ref.u64; > epoll_ctl(c->epollfd, EPOLL_CTL_ADD, c->fd_tap, &ev); > + > + switch (c->mode) { > + case MODE_PASST: > + send_initial_arp_req(c); > + break; > + case MODE_PASTA: > + break; > + case MODE_VU: > + break; > + } I don't think we want to make this conditional on MODE_PASST. I think MODE_VU could suffer from the same problem. So could MODE_PASTA, although it would take a more unusual setup to trigger it. In any case, sending it unconditionally should be at worst harmless and is simpler. > } > =20 > /** > @@ -1504,8 +1514,9 @@ void tap_backend_init(struct ctx *c) > tap_sock_unix_init(c); > =20 > /* In passt mode, we don't know the guest's MAC address until it > - * sends us packets. Use the broadcast address so that our > - * first packets will reach it. > + * sends us packets (e.g. responds to our initial ARP request). > + * Until then, use the broadcast address so that our first > + * packets will reach it. > */ > memset(&c->guest_mac, 0xff, sizeof(c->guest_mac)); > break; > --=20 > 2.47.2 >=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 --QVXBDDpUyKZny5z4 Content-Type: application/pgp-signature; name=signature.asc -----BEGIN PGP SIGNATURE----- iQIzBAEBCgAdFiEEO+dNsU4E3yXUXRK2zQJF27ox2GcFAmi+VNwACgkQzQJF27ox 2Gd9NxAAm4VhQKICqYxqCjBysDzK9ECN48gAmFnr0NbuDdxXoleDZ6Vd2gAaZ+vt jDdYbmSwQ+9qW4oqsh96kAbl+XLGZlL8n19RyZnrU7LJ7k7i/QxgF9hAg8nyBiPK 211I1LEZY9oi5b9JumP2tFfOU85HbCobOzo5ob9gIKjHcm+cM/avA5AqgauplJrA bOU9kP2SUzT9J1NqB9jD6diz82ASNW4TUCmrPQsd+YMnCiidq03KD2s0FxyLOR+6 0nxLt2pU2/pg2jAK1jalhb9kMs0lJ4C1LSfvFwX7kwerK1YqUZj+ISahLj8aTWHP Gzrq1ZcGV2ubtv5Bzm7epqNusHH5sLxE19a8impOPC1DhJcqTj+65jCBiXQKHF/G 46nyrmJxEFWvLYD18fz1MR9U9JHPj1uSREiXgRSJBMbQYkZj+QVSf5dBZFe2oy89 iMQUbkjkR1x0OvwwPnjY3knYleuFmuDty6vTvIdCU+5g2Fjfywk1Bmww+2VCMrES WsiTaBQu99KSu6eXii5uzZ8RQq80hNYFTXYbTcT+DzxmStanGucml4yNOhhQ2lcM X1OaUu3RjHZ/hllvjKMGKpWmWHfwgaDeMUBnY1yiqMlh96UW2ZYSq1iQtI9ozjio 1yI1ce6HJajR0p873P19ybugvjXiETvnQoVGNtfvvlswg92HAko= =lwpu -----END PGP SIGNATURE----- --QVXBDDpUyKZny5z4--