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=DVUpE81A; dkim-atps=neutral Received: from mail.ozlabs.org (mail.ozlabs.org [IPv6:2404:9400:2221:ea00::3]) by passt.top (Postfix) with ESMTPS id 4956B5A0626 for ; Mon, 19 Jan 2026 09:41:43 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gibson.dropbear.id.au; s=202512; t=1768812101; bh=/OdKvxK83s0T4b1dVUJwTr4jqMJ5/DyGUG2UEL4N48g=; h=Date:From:To:Cc:Subject:References:In-Reply-To:From; b=DVUpE81AHTkXtFYLUxe3AnyevWYUxfbCXYGsNcy27+MnU/l4kfNmtwsGXTQ0hhWWB L4+Wmgi7sHzSv8m3PDr7eK2Lj962CsgkCBLbODJ8zv2N4SRZuANdCxgPqyGY2If0IC hcs8T+Rmk4WxSIt29Ct32iYNRM4+a4XQGp0kJChEy5k5cwmeAiP+VxN+Y+xd072uCP pBaVrmMYfXBIYM1HdRIdNhKk3bJl1qdIo+1FAGcTtbjOLiDoHnScpWUMdT/F7/1fCT 6b48zmCK8KgaVeO3rkAv8xNLL2UQNs3YE74lsh6raUXijmneZOaAmOSCzKCvC/UWlY x/7RkY1kxL8tg== Received: by gandalf.ozlabs.org (Postfix, from userid 1007) id 4dvkTK0glhz4wGs; Mon, 19 Jan 2026 19:41:41 +1100 (AEDT) Date: Mon, 19 Jan 2026 19:41:31 +1100 From: David Gibson To: Jon Maloy Subject: Re: [PATCH v2 6/9] conf: Allow multiple -a/--address options per address family Message-ID: References: <20260118221612.2115386-1-jmaloy@redhat.com> <20260118221612.2115386-7-jmaloy@redhat.com> MIME-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha512; protocol="application/pgp-signature"; boundary="uNA+I9z5Ekjnlq7t" Content-Disposition: inline In-Reply-To: <20260118221612.2115386-7-jmaloy@redhat.com> Message-ID-Hash: 2VXT5VLTGPXEETKAMZ6VTNT4BX2W7A72 X-Message-ID-Hash: 2VXT5VLTGPXEETKAMZ6VTNT4BX2W7A72 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: --uNA+I9z5Ekjnlq7t Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable On Sun, Jan 18, 2026 at 05:16:09PM -0500, Jon Maloy wrote: > We enable configuration of multiple IPv4 and IPv6 addresses by allowing > repeated use of the -a/--address option. >=20 > - We update option parsing to append addresses to the addrs[] array. > - Each address specified via -a does initially get a class-based default > prefix. > - If no -a option is given, address and prefix are inherited from > the template interface. > - If a prefix length is to be added, it has to be done in CIDR format, > except for the very first address. > - We configure all indicated addresses in the namespace interface. >=20 > Signed-off-by: Jon Maloy >=20 > --- > v2: Adapted to previous code changes > --- > conf.c | 42 +++++++++++++++++++++++++++++------------- > pasta.c | 24 ++++++++++++++++++------ > 2 files changed, 47 insertions(+), 19 deletions(-) >=20 > diff --git a/conf.c b/conf.c > index 3ecd1a0..32a754d 100644 > --- a/conf.c > +++ b/conf.c > @@ -789,7 +789,7 @@ static unsigned int conf_ip4(unsigned int ifi, struct= ip4_ctx *ip4) > =20 > ip4->our_tap_addr =3D ip4->guest_gw; > =20 > - if (inany_is_unspecified(&ip4->addrs[0].addr)) > + if (!ip4->addr_count) > return 0; > =20 > return ifi; > @@ -858,8 +858,7 @@ static unsigned int conf_ip6(unsigned int ifi, struct= ip6_ctx *ip6) > if (IN6_IS_ADDR_LINKLOCAL(&ip6->guest_gw)) > ip6->our_tap_ll =3D ip6->guest_gw; > =20 > - if (IN6_IS_ADDR_UNSPECIFIED(&ip6->addrs[0].addr.a6) || > - IN6_IS_ADDR_UNSPECIFIED(&ip6->our_tap_ll)) > + if (!ip6->addr_count || IN6_IS_ADDR_UNSPECIFIED(&ip6->our_tap_ll)) > return 0; > =20 > return ifi; > @@ -951,9 +950,11 @@ static void usage(const char *name, FILE *f, int sta= tus) > " default: 65520: maximum 802.3 MTU minus 802.3 header\n" > " length, rounded to 32 bits (IPv4 words)\n" > " -a, --address ADDR Assign IPv4 or IPv6 address ADDR[/PREFIXLEN]\n" > - " can be specified zero to two times (for IPv4 and IPv6)\n" > + " can be specified multiple times (limit: %d IPv4, %d IPv6)\n" > " default: use addresses from interface with default route\n" > - " -n, --netmask MASK Assign IPv4 MASK, dot-decimal or bits\n" > + " -n, --netmask MASK Assign IPv4 MASK, dot-decimal or bits\n", > + IP4_MAX_ADDRS, IP6_MAX_ADDRS); > + FPRINTF(f, > " default: netmask from matching address on the host\n" > " -M, --mac-addr ADDR Use source MAC address ADDR\n" > " default: 9a:55:9a:55:9a:55 (locally administered)\n" > @@ -1882,6 +1883,7 @@ void conf(struct ctx *c, int argc, char **argv) > union inany_addr addr; > const struct in_addr *a4; > int prefix_len =3D 0; > + unsigned int i; > int af; > =20 > af =3D conf_addr_prefix_len(optarg, &addr, &prefix_len); > @@ -1893,9 +1895,15 @@ void conf(struct ctx *c, int argc, char **argv) > die("Invalid address: %s", optarg); > =20 > if (af =3D=3D AF_INET6) { > - c->ip6.addrs[0].addr.a6 =3D addr.a6; > - c->ip6.addrs[0].flags |=3D INANY_ADDR_CONFIGURED; > - c->ip6.addr_count =3D 1; > + i =3D c->ip6.addr_count; > + > + if (i >=3D IP6_MAX_ADDRS) > + die("Too many IPv6 addresses"); > + > + c->ip6.addrs[i].addr.a6 =3D addr.a6; > + c->ip6.addrs[i].prefix_len =3D prefix_len; > + c->ip6.addrs[i].flags =3D INANY_ADDR_CONFIGURED; > + c->ip6.addr_count++; This is getting moderately deeply nested. Maybe worth creating an "add_address" helper? That could also be helpful if we later integrate the addr_seen stuff into the same table. > if (c->mode =3D=3D MODE_PASTA) > c->ip6.no_copy_addrs =3D true; > break; > @@ -1904,10 +1912,15 @@ void conf(struct ctx *c, int argc, char **argv) > a4 =3D inany_v4(&addr); > =20 > if (af =3D=3D AF_INET && a4) { > - c->ip4.addrs[0].addr =3D inany_from_v4(*a4); > - c->ip4.addrs[0].flags |=3D INANY_ADDR_CONFIGURED; > - c->ip4.addr_count =3D 1; > - if (prefix_len) { > + i =3D c->ip4.addr_count; > + > + if (i >=3D IP4_MAX_ADDRS) > + die("Too many IPv4 addresses"); > + > + c->ip4.addrs[i].addr =3D inany_from_v4(*a4); > + c->ip4.addrs[i].prefix_len =3D prefix_len; > + c->ip4.addrs[i].flags =3D INANY_ADDR_CONFIGURED; > + if (i =3D=3D 0 && prefix_len) { > if (prefix_from_opt) > die("Can't mix CIDR with -n"); > prefix_from_cidr =3D true; > @@ -1915,6 +1928,9 @@ void conf(struct ctx *c, int argc, char **argv) > prefix_len =3D ip4_default_prefix_len(a4); > } > c->ip4.addrs[0].prefix_len =3D prefix_len; > + c->ip4.addr_count++; > + if (c->mode =3D=3D MODE_PASTA) > + c->ip4.no_copy_addrs =3D true; > break; > } > =20 > @@ -2217,7 +2233,7 @@ void conf(struct ctx *c, int argc, char **argv) > if (!c->ifi6) { > c->no_ndp =3D 1; > c->no_dhcpv6 =3D 1; > - } else if (IN6_IS_ADDR_UNSPECIFIED(&c->ip6.addrs[0].addr.a6)) { > + } else if (!c->ip6.addr_count) { > c->no_dhcpv6 =3D 1; Kind of pre-existing, but AFAICT we entirely disable IPv6 (ifi6 =3D=3D 0) if we have no addresses - that would seem to superseded disabling just DHCPv6. > } > =20 > diff --git a/pasta.c b/pasta.c > index 1bb3dd0..27ce6a7 100644 > --- a/pasta.c > +++ b/pasta.c > @@ -338,10 +338,16 @@ void pasta_ns_conf(struct ctx *c) > =20 > if (c->ifi4) { > if (c->ip4.no_copy_addrs) { > - rc =3D nl_addr_set(nl_sock_ns, c->pasta_ifi, > - AF_INET, > - inany_v4(&c->ip4.addrs[0].addr), > - c->ip4.addrs[0].prefix_len); > + int i; > + > + for (i =3D 0; i < c->ip4.addr_count; i++) { > + rc =3D nl_addr_set(nl_sock_ns, > + c->pasta_ifi, AF_INET, > + inany_v4(&c->ip4.addrs[i].addr), > + c->ip4.addrs[i].prefix_len); > + if (rc < 0) > + break; > + } > } else { > rc =3D nl_addr_dup(nl_sock, c->ifi4, > nl_sock_ns, c->pasta_ifi, > @@ -387,12 +393,18 @@ void pasta_ns_conf(struct ctx *c) > 0, IFF_NOARP); > =20 > if (c->ip6.no_copy_addrs) { > - struct in6_addr *a =3D &c->ip6.addrs[0].addr.a6; > + struct in6_addr *a; > + int i; > =20 > - if (!IN6_IS_ADDR_UNSPECIFIED(a)) { > + for (i =3D 0; i < c->ip6.addr_count; i++) { > + a =3D &c->ip6.addrs[i].addr.a6; > + if (IN6_IS_ADDR_UNSPECIFIED(a)) > + continue; > rc =3D nl_addr_set(nl_sock_ns, > c->pasta_ifi, > AF_INET6, a, 64); > + if (rc < 0) > + break; > } > } else { > rc =3D nl_addr_dup(nl_sock, c->ifi6, > --=20 > 2.52.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 --uNA+I9z5Ekjnlq7t Content-Type: application/pgp-signature; name=signature.asc -----BEGIN PGP SIGNATURE----- iQIzBAEBCgAdFiEEO+dNsU4E3yXUXRK2zQJF27ox2GcFAmlt7joACgkQzQJF27ox 2Gf+7BAAkjO58s6IR3Bd2nGoJlVWtNTWyQcZ5QPWkEbH3wKKS5GabVMtgOx7dFE7 f3B/odj+uymqB3no4gw69aVfrqpWQIIRcdxWJvEncQutq3Er//sZLUXNVwxju1mN RMiIivLIx5iPL/p41944QnAL/8ZjW+Kz2aHmnvEA7UsKQtDNSjcTnTo407360rRl NfF5xN1YmPKABRQ4Zf8Q54JwTOIkrT6XBMm40dlYUwcHvMPadF2DMQQFajgAmfOi PqeSiAAmf68tUecBT6k5GBMTn5XPDlV/WAEp9g4jmAy7S7n0CE/O1ek1a6L0znZn HuSVEdmCOj0Z/qdUj5V1HcGOLzq0V2MpsgRvH0UAJVtGNMdNgGdeHqXom5AJGRiE +wHYVCe6rasP1HsHmlL8ZFDHjR1Qr0EYmVna+fkkYse65YBLGSyW+3RBH2JspU/v 7MmxkYM3cQK5N1yzM2jSqQ8dTCaaWMKPav+4BZezNEpXfCLMWvvogceaQfy3nGbs LBN/eTbocROkYDz3YebzOouV4lebw+xz1g7/b8iQYDn/HlFmEkT7TzQLCkY43+Km cN3Bs1JO/+JpxkMG8JJKS58kvzcqsal1bgbOZoAE7WJ/7B7gnepGTzDixoITfNQ9 VncmnWWHBwEQUEZ/Q5O1ebSTgAEElK0HR2pDUi1jaLPBR5arDjA= =0wcc -----END PGP SIGNATURE----- --uNA+I9z5Ekjnlq7t--