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=faa6u3Ob; dkim-atps=neutral Received: from mail.ozlabs.org (mail.ozlabs.org [IPv6:2404:9400:2221:ea00::3]) by passt.top (Postfix) with ESMTPS id 6538A5A068E for ; Mon, 05 Jan 2026 05:18:14 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gibson.dropbear.id.au; s=202512; t=1767586690; bh=pkO0VLGeBKKyRL4P1vbQYbhSe9eYMHKCLuv7xeIqDfU=; h=Date:From:To:Cc:Subject:References:In-Reply-To:From; b=faa6u3ObZXlch+ajTmsFMwW7la6HHlEIIDQgNHRhuaEAsR1mw03BCn7f+lhVXHEVB 982ewp504ceW/qs+Xmpf1ycwaHgGPduYYgbLNATxOY+spUnKZaSrb6LEHM1qjXO6b9 9GaPQlozJru+EXhzwxp3DSez18U2GBr9bue9CtA9pNNOv7USfJCR/svT9Nf7dtXOzt vu2SwxiY0VoftjH6yJWqkV0lbVPGOVQOlRm7yB8X8q0darfadTMDBGsw+ZDw9IarDG cxiR3winoG+L2+Oy5qRY3rb2WyeMdd4NAIA56e4gVbt9dDP3iEye5+3LY6H1DcQc1g 1ioFFIs5j7/DQ== Received: by gandalf.ozlabs.org (Postfix, from userid 1007) id 4dl1Hk0tHTz4wCZ; Mon, 05 Jan 2026 15:18:10 +1100 (AEDT) Date: Mon, 5 Jan 2026 15:18:05 +1100 From: David Gibson To: Yumei Huang Subject: Re: [PATCH] conf, pasta: Add --no-tap option Message-ID: References: <20251229095558.918055-1-yuhuang@redhat.com> MIME-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha512; protocol="application/pgp-signature"; boundary="UGN1WUueYxi8pHmo" Content-Disposition: inline In-Reply-To: <20251229095558.918055-1-yuhuang@redhat.com> Message-ID-Hash: CNVZWFRFMJQBY2VYQF27NQQ2K5YUM65F X-Message-ID-Hash: CNVZWFRFMJQBY2VYQF27NQQ2K5YUM65F 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, sbrivio@redhat.com 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: --UGN1WUueYxi8pHmo Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable On Mon, Dec 29, 2025 at 05:55:58PM +0800, Yumei Huang wrote: > This patch introduces a mode where we only forward loopback connections > and traffic between two namespaces (via the loopback interface, 'lo'), > without a tap device. >=20 > With this, podman can support forwarding ::1 in custom networks when using > rootlesskit for forwarding ports. >=20 > In --no-tap mode, --host-lo-to-ns-lo, --no-icmp and --no-ra is automatica= lly > enabled. Options requiring a tap device (--ns-ifname, --ns-mac-addr, > --config-net, --outbound-if4/6) are rejected. >=20 > Link: https://bugs.passt.top/show_bug.cgi?id=3D149 > Signed-off-by: Yumei Huang Nice work. There are some things that need polish, but overall this looks pretty good to me. Like Stefano, I'm pleasantly surprised at how simple it turned out to be. > --- > conf.c | 56 +++++++++++++++++++++++++++++++++++++++++--------------- > fwd.c | 3 +++ > passt.1 | 5 +++++ > passt.h | 2 ++ > pasta.c | 3 +++ > tap.c | 11 +++++++---- > 6 files changed, 61 insertions(+), 19 deletions(-) >=20 > diff --git a/conf.c b/conf.c > index 84ae12b..353d0a5 100644 > --- a/conf.c > +++ b/conf.c > @@ -1049,7 +1049,8 @@ pasta_opts: > " --no-copy-addrs DEPRECATED:\n" > " Don't copy all addresses to namespace\n" > " --ns-mac-addr ADDR Set MAC address on tap interface\n" > - " --no-splice Disable inbound socket splicing\n"); > + " --no-splice Disable inbound socket splicing\n" > + " --no-tap Don't create tap device\n"); I feel like this description can be improved, but I'm not exactly sure how, yet. > =20 > passt_exit(status); > } > @@ -1451,6 +1452,7 @@ void conf(struct ctx *c, int argc, char **argv) > {"no-ndp", no_argument, &c->no_ndp, 1 }, > {"no-ra", no_argument, &c->no_ra, 1 }, > {"no-splice", no_argument, &c->no_splice, 1 }, > + {"no-tap", no_argument, &c->no_tap, 1 }, > {"freebind", no_argument, &c->freebind, 1 }, > {"no-map-gw", no_argument, &no_map_gw, 1 }, > {"ipv4-only", no_argument, NULL, '4' }, > @@ -1947,8 +1949,11 @@ void conf(struct ctx *c, int argc, char **argv) > } > } while (name !=3D -1); > =20 > - if (c->mode !=3D MODE_PASTA) > + if (c->mode !=3D MODE_PASTA) { > c->no_splice =3D 1; > + if (c->no_tap) > + die("--no-tap is for pasta mode only"); > + } > =20 > if (c->mode =3D=3D MODE_PASTA && !c->pasta_conf_ns) { > if (copy_routes_opt) > @@ -1957,6 +1962,25 @@ void conf(struct ctx *c, int argc, char **argv) > die("--no-copy-addrs needs --config-net"); > } > =20 > + if (c->mode =3D=3D MODE_PASTA && c->no_tap) { > + if (c->no_splice) > + die("--no-tap is incompatible with --no-splice"); > + if (*c->ip4.ifname_out || *c->ip6.ifname_out) > + die("--no-tap is incompatible with --outbound-if4/6"); > + if (*c->pasta_ifn) > + die("--no-tap is incompatible with --ns-ifname"); > + if (*c->guest_mac) > + die("--no-tap is incompatible with --ns-mac-addr"); These all make sense. It might also make sense to exclude the -i option - setting a template interface also makes no sense in --no-tap mode. > + if (c->pasta_conf_ns) > + die("--no-tap is incompatible with --config-net"); I don't think this is right. We still can and should bring up 'lo' in the --no-tap case. > + c->host_lo_to_ns_lo =3D 1; > + c->no_icmp =3D 1; > + c->no_ra =3D 1; > + c->no_dns =3D 1; > + c->no_dns_search =3D 1; The reasoning for the last two items is a bit unclear to me. IIUC, no_dns and no_dns_search aren't so much about "support" for DNS itself but for advertising DNS settings via DHCP. Since DHCP will be unsupported, so are these as a consequence. Is that right? > + } > + > if (!ifi4 && *c->ip4.ifname_out) > ifi4 =3D if_nametoindex(c->ip4.ifname_out); > =20 > @@ -1980,9 +2004,9 @@ void conf(struct ctx *c, int argc, char **argv) > log_conf_parsed =3D true; /* Stop printing everything */ > =20 > nl_sock_init(c, false); > - if (!v6_only) > + if (!v6_only && !c->no_tap) > c->ifi4 =3D conf_ip4(ifi4, &c->ip4); > - if (!v4_only) > + if (!v4_only && !c->no_tap) > c->ifi6 =3D conf_ip6(ifi6, &c->ip6); > =20 > if (c->ifi4 && c->mtu < IPV4_MIN_MTU) { > @@ -1998,30 +2022,32 @@ void conf(struct ctx *c, int argc, char **argv) > (*c->ip6.ifname_out && !c->ifi6)) > die("External interface not usable"); > =20 > - if (!c->ifi4 && !c->ifi6 && !*c->pasta_ifn) { > + if (!c->ifi4 && !c->ifi6 && !*c->pasta_ifn && !c->no_tap) { > strncpy(c->pasta_ifn, pasta_default_ifn, > sizeof(c->pasta_ifn) - 1); > } > =20 > if (!c->ifi4 && !v6_only) { > - info("IPv4: no external interface as template, use local mode"); > - > - conf_ip4_local(&c->ip4); > + if (!c->no_tap) { > + info("IPv4: no external interface as template, use local mode"); > + conf_ip4_local(&c->ip4); > + } > c->ifi4 =3D -1; > } > =20 > if (!c->ifi6 && !v4_only) { > - info("IPv6: no external interface as template, use local mode"); > - > - conf_ip6_local(&c->ip6); > + if (!c->no_tap) { > + info("IPv6: no external interface as template, use local mode"); > + conf_ip6_local(&c->ip6); > + } > c->ifi6 =3D -1; > } > =20 > - if (c->ifi4 && !no_map_gw && > + if (c->ifi4 > 0 && !no_map_gw && This isn't quite right. ifi4 =3D=3D -1 now occurs in two cases: local mode, and --no-tap mode. Not setting map_host_loopback makes sense for --no-tap mode, but it's still needed for local mode. > IN4_IS_ADDR_UNSPECIFIED(&c->ip4.map_host_loopback)) > c->ip4.map_host_loopback =3D c->ip4.guest_gw; > =20 > - if (c->ifi6 && !no_map_gw && > + if (c->ifi6 > 0 && !no_map_gw && Same here. > IN6_IS_ADDR_UNSPECIFIED(&c->ip6.map_host_loopback)) > c->ip6.map_host_loopback =3D c->ip6.guest_gw; > =20 > @@ -2116,10 +2142,10 @@ void conf(struct ctx *c, int argc, char **argv) > conf_ports(c, name, optarg, &c->udp.fwd_out); > } while (name !=3D -1); > =20 > - if (!c->ifi4) > + if (c->ifi4 <=3D 0) > c->no_dhcp =3D 1; > =20 > - if (!c->ifi6) { > + if (c->ifi6 <=3D 0) { > c->no_ndp =3D 1; > c->no_dhcpv6 =3D 1; And here. Local mode can still use NDP and DHCP, even though --no-tap mode can't. It might be simpler to force no_ndp, no_dhcp etc. along with no_ra and the rest above. > } else if (IN6_IS_ADDR_UNSPECIFIED(&c->ip6.addr)) { > diff --git a/fwd.c b/fwd.c > index 44a0e10..2f4a89a 100644 > --- a/fwd.c > +++ b/fwd.c > @@ -780,6 +780,9 @@ uint8_t fwd_nat_from_host(const struct ctx *c, uint8_= t proto, > return PIF_SPLICE; > } > =20 > + if (c->no_tap) > + return PIF_NONE; > + > if (!nat_inbound(c, &ini->eaddr, &tgt->oaddr)) { > if (inany_v4(&ini->eaddr)) { > if (IN4_IS_ADDR_UNSPECIFIED(&c->ip4.our_tap_addr)) > diff --git a/passt.1 b/passt.1 > index db0d662..2d643f7 100644 > --- a/passt.1 > +++ b/passt.1 > @@ -755,6 +755,11 @@ Default is to let the tap driver build a pseudorando= m hardware address. > Disable the bypass path for inbound, local traffic. See the section \fBH= andling > of local traffic in pasta\fR in the \fBNOTES\fR for more details. > =20 > +.TP > +.BR \-\-no-tap > +Do not create a tap device in the namespace. In this mode, only local lo= opback > +traffic between namespaces is forwarded using splice. This probably wants some work, because I'm not sure "tap device" and "splice" are sufficiently clear in this context. > + > .SH EXAMPLES > =20 > .SS \fBpasta > diff --git a/passt.h b/passt.h > index 79d01dd..0c1ec4c 100644 > --- a/passt.h > +++ b/passt.h > @@ -200,6 +200,7 @@ struct ip6_ctx { > * @no_ndp: Disable NDP handler altogether > * @no_ra: Disable router advertisements > * @no_splice: Disable socket splicing for inbound traffic > + * @no_tap: Do not create tap device > * @host_lo_to_ns_lo: Map host loopback addresses to ns loopback address= es > * @freebind: Allow binding of non-local addresses for forwarding > * @low_wmem: Low probed net.core.wmem_max > @@ -277,6 +278,7 @@ struct ctx { > int no_ndp; > int no_ra; > int no_splice; > + int no_tap; > int host_lo_to_ns_lo; > int freebind; > =20 > diff --git a/pasta.c b/pasta.c > index 0ddd6b0..3510ec5 100644 > --- a/pasta.c > +++ b/pasta.c > @@ -316,6 +316,9 @@ void pasta_ns_conf(struct ctx *c) > die("Couldn't bring up loopback interface in namespace: %s", > strerror_(-rc)); > =20 > + if (c->no_tap) > + return; > + > /* Get or set MAC in target namespace */ > if (MAC_IS_ZERO(c->guest_mac)) > nl_link_get_mac(nl_sock_ns, c->pasta_ifi, c->guest_mac); > diff --git a/tap.c b/tap.c > index 9d1344b..9b4eedc 100644 > --- a/tap.c > +++ b/tap.c > @@ -1491,13 +1491,16 @@ static int tap_ns_tun(void *arg) > */ > static void tap_sock_tun_init(struct ctx *c) > { > - NS_CALL(tap_ns_tun, c); > - if (c->fd_tap =3D=3D -1) > - die("Failed to set up tap device in namespace"); > + if (!c->no_tap) { > + NS_CALL(tap_ns_tun, c); > + if (c->fd_tap =3D=3D -1) > + die("Failed to set up tap device in namespace"); > + } > =20 > pasta_ns_conf(c); > =20 > - tap_start_connection(c); > + if (!c->no_tap) > + tap_start_connection(c); > } > =20 > /** > --=20 > 2.49.0 >=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 --UGN1WUueYxi8pHmo Content-Type: application/pgp-signature; name=signature.asc -----BEGIN PGP SIGNATURE----- iQIzBAEBCgAdFiEEO+dNsU4E3yXUXRK2zQJF27ox2GcFAmlbO2oACgkQzQJF27ox 2Gf1Uw/+Kk2FtxW109ZeTG5OwXFy6YP0FM/9od1UGogyGq0ukER/tT0zQCEYFvr7 6pyAYzz2OrHcPf3A4WiLxR/JRtNIqGPaNTo6YGZotLXLycc7CyFO465QHrR1gStK ZTA4nxnXRYhUsjsy8GKmh+v/ExYhTLqmNOgLE6JlyqUlP9HWbyMBA0Z1YyGJ6xbC yIfDD4stXghbDG7tEO3jptqFiv92vpUBJFwzuGP8ClKO4pSR/Vbb0AxAiIyKGADI MeTFudQGmoicqdthqjX4V5V7bsg+noJbGR595ZmrEyIclb7UgoYZ8iHh5xY0MsqV DSMY/uRGacIphzvNMM0axbiIa+9JAH06jQaXqMny74NDMhAAQXLz2t+rmGGfIcDd r2MX9mNipjizbNHHm7SFjh8IY4Dx2hN+tAk0Q9x3ned5hOgTgxzZ9+66EeqNKnDR zUxMb59NC6BnL9gsVv2EUV6Qj3j3amJ+57Z3CSWH0+vtqTbcVaqCpVItrq3KFoiG Jnp5HPdrFVkPe3cqUYTv4dF5gSrgXyZVoavISXvhoGYa7uwLr/TtJWHBLE+UDQJ1 ziS9joG4sH5qYsjUsh4+OygB/QYaZFvaVKjuyeOKmGmEnO6thnuxLF4U8To8MNCS 0HvzO0sTAKmmbHYcoivmT75fD+Ukkol58Hr/DzM5p4q/6Q+ykq8= =fsL+ -----END PGP SIGNATURE----- --UGN1WUueYxi8pHmo--