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=lyntvzFt; dkim-atps=neutral Received: from mail.ozlabs.org (mail.ozlabs.org [IPv6:2404:9400:2221:ea00::3]) by passt.top (Postfix) with ESMTPS id 9CC205A0623 for ; Fri, 06 Feb 2026 09:47:12 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gibson.dropbear.id.au; s=202512; t=1770367630; bh=72wqiLynNQA8SxupG9qeEc29eEkz+5rgy+QFwx1pyME=; h=Date:From:To:Cc:Subject:References:In-Reply-To:From; b=lyntvzFtABaz4bksnQT81Tqnx0eKCaF+/NWOZppR3LTZRSeGzkDFYFO+VpBEdynws 1PqCy7mv3FMspT3PgXIH/Pkiuy9DQI+/cCItpNxkY0+0hIAB0bhPJC45caB5xROExm 4aholLwbVrXLMXaOAhiZvy5NHxev33XLbsbaz5/hO7Dmh4YVuFc6gR4j4yzmvBR1wd 2q1hOcdJ6+feg0B4daymar7HdIl7JxsRFmmsmy7PPUyEBNoUYqCvhCNTe+pncnXSfB DyqqQktBfIpaMvUwkvTzF3WlB44Ffiu+1GGQObqEkUV/PQkPIzowKLfG4f+gjqpsSj PMv7+JxTz4ROQ== Received: by gandalf.ozlabs.org (Postfix, from userid 1007) id 4f6nlL2rwKz4wB8; Fri, 06 Feb 2026 19:47:10 +1100 (AEDT) Date: Fri, 6 Feb 2026 19:47:03 +1100 From: David Gibson To: Jon Maloy Subject: Re: [PATCH v3 07/11] conf: Allow multiple -a/--address options per address family Message-ID: References: <20260130214447.2540791-1-jmaloy@redhat.com> <20260130214447.2540791-8-jmaloy@redhat.com> MIME-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha512; protocol="application/pgp-signature"; boundary="ukqVmFXIpxQDfSSE" Content-Disposition: inline In-Reply-To: <20260130214447.2540791-8-jmaloy@redhat.com> Message-ID-Hash: DLV24UL33C6CIHPLS7W72CA3BYT4TFGE X-Message-ID-Hash: DLV24UL33C6CIHPLS7W72CA3BYT4TFGE 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: --ukqVmFXIpxQDfSSE Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable On Fri, Jan 30, 2026 at 04:44:43PM -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 unified addrs[] > array, with limit checks for IP4_MAX_ADDRS and IP6_MAX_ADDRS. I don't see any point to separate v4 and v6 limits, now there's a unified array. > - Each address specified via -a, but with no prefix length indicated, > gets a class-based default prefix length. That's not new, is it? I think we want to be careful with this. We need to maintain compatibility with previously working options, but I think we want to strongly encourage prefix lengths to be explicitly specified. Address classes are very anachronistic now, so I don't think we want to add any more uses of them than we have to for compatibility. > - If no -a option is given, addresses/prefix lengths 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. I don't really follow what that means. > - We configure all indicated addresses in the namespace interface using > the for_each_addr() macro. >=20 > Signed-off-by: Jon Maloy >=20 > --- > v2: - Adapted to previous code changes > v3: - Adapted to single-array strategy > - Changes according to feedback from S. Brivio and G Gibson. > --- > conf.c | 23 ++++++++++++++++------- > pasta.c | 21 ++++++++++++++------- > 2 files changed, 30 insertions(+), 14 deletions(-) >=20 > diff --git a/conf.c b/conf.c > index bb6bcf8..d73a3dd 100644 > --- a/conf.c > +++ b/conf.c > @@ -803,13 +803,13 @@ static unsigned int conf_ip6(unsigned int ifi, stru= ct ctx *c) > } > =20 > e =3D first_v6(c); > - c->ip6.addr_seen =3D e->addr.a6; > + if (e) > + c->ip6.addr_seen =3D e->addr.a6; This seems like it belongs in an earlier patch. > =20 > if (IN6_IS_ADDR_LINKLOCAL(&c->ip6.guest_gw)) > c->ip6.our_tap_ll =3D c->ip6.guest_gw; > =20 > - if (IN6_IS_ADDR_UNSPECIFIED(&e->addr.a6) || > - IN6_IS_ADDR_UNSPECIFIED(&c->ip6.our_tap_ll)) Missed this in an earlier patch, but !!e and an unspecified address shouldn't be possible, no? > + if (!count_v6(c) || IN6_IS_ADDR_UNSPECIFIED(&c->ip6.our_tap_ll)) > return 0; > =20 > return ifi; > @@ -901,9 +901,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" > @@ -1836,6 +1838,9 @@ void conf(struct ctx *c, int argc, char **argv) > die("Can't mix CIDR with -n"); > =20 > if (af =3D=3D AF_INET) { > + if (count_v4(c) >=3D IP4_MAX_ADDRS) > + die("Too many IPv4 addresses"); > + > e =3D &c->addrs[c->addr_count]; > e->addr =3D addr; > e->prefix_len =3D prefix_len ? prefix_len : > @@ -1845,6 +1850,9 @@ void conf(struct ctx *c, int argc, char **argv) > if (c->mode =3D=3D MODE_PASTA) > c->ip4.no_copy_addrs =3D true; > } else if (af =3D=3D AF_INET6) { > + if (count_v6(c) >=3D IP6_MAX_ADDRS) > + die("Too many IPv6 addresses"); > + > e =3D &c->addrs[c->addr_count]; > e->addr =3D addr; > e->prefix_len =3D prefix_len ? prefix_len : 64; > @@ -1861,6 +1869,8 @@ void conf(struct ctx *c, int argc, char **argv) > struct inany_addr_entry *e; > int plen; > =20 > + if (count_v4(c) > 1) > + die("-n can only be used with first address"); > if (prefix_from_cidr) > die("Can't use both -n and CIDR prefix length"); > plen =3D conf_ip4_prefix(optarg); > @@ -2156,8 +2166,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 (!first_v6(c) || > - IN6_IS_ADDR_UNSPECIFIED(&first_v6(c)->addr.a6)) { > + } else if (!count_v6(c)) { > c->no_dhcpv6 =3D 1; > } > =20 > diff --git a/pasta.c b/pasta.c > index de0ba14..8cb5873 100644 > --- a/pasta.c > +++ b/pasta.c > @@ -312,10 +312,14 @@ static void pasta_ns_conf_ip4(struct ctx *c) > int rc =3D 0; > =20 > if (c->ip4.no_copy_addrs) { > - struct inany_addr_entry *e =3D first_v4(c); > + const struct inany_addr_entry *e; > =20 > - rc =3D nl_addr_set(nl_sock_ns, c->pasta_ifi, AF_INET, > - inany_v4(&e->addr), e->prefix_len - 96); > + for_each_addr(c, e, AF_INET) { > + rc =3D nl_addr_set(nl_sock_ns, c->pasta_ifi, AF_INET, > + inany_v4(&e->addr), e->prefix_len - 96); > + if (rc < 0) > + break; > + } As noted on the previous patch, I think a single pass through the array makes sense, only changing the inner part of the loop for v4 vs. v6 (we could potentially update nl_addr_set() to take an inany, which might make it cleaner). > } else { > rc =3D nl_addr_dup(nl_sock, c->ifi4, > nl_sock_ns, c->pasta_ifi, AF_INET); > @@ -346,7 +350,6 @@ static void pasta_ns_conf_ip4(struct ctx *c) > */ > static void pasta_ns_conf_ip6(struct ctx *c) > { > - struct inany_addr_entry *e; > int rc =3D 0; > =20 > rc =3D nl_addr_get_ll(nl_sock_ns, c->pasta_ifi, &c->ip6.addr_ll_seen); > @@ -365,11 +368,15 @@ static void pasta_ns_conf_ip6(struct ctx *c) > nl_link_set_flags(nl_sock_ns, c->pasta_ifi, 0, IFF_NOARP); > =20 > if (c->ip6.no_copy_addrs) { > - e =3D first_v6(c); > + const struct inany_addr_entry *e; > =20 > - if (e && !IN6_IS_ADDR_UNSPECIFIED(&e->addr.a6)) { > + for_each_addr(c, e, AF_INET6) { > + if (IN6_IS_ADDR_UNSPECIFIED(&e->addr.a6)) > + continue; > rc =3D nl_addr_set(nl_sock_ns, c->pasta_ifi, > - AF_INET6, &e->addr.a6, 64); > + AF_INET6, &e->addr.a6, e->prefix_len); > + 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 --ukqVmFXIpxQDfSSE Content-Type: application/pgp-signature; name=signature.asc -----BEGIN PGP SIGNATURE----- iQIzBAEBCgAdFiEEO+dNsU4E3yXUXRK2zQJF27ox2GcFAmmFqn0ACgkQzQJF27ox 2GdpLQ/+OvVDGIA12ofmm4/WMQuGfROE8OuwNf9QQhw+/JX7/QdIpjl2OSYNQfiJ or9z3WZjlv07YSfCRvpf/nbmW6YJBrluoHpQDTo4xx1+hcLUxjqk9Zz6KTamLhai //xxrf1abguTqyhEj3eog3fBUolFhrAUqBmuJ93+hhAgW84Gmc01QqergBrpN1f2 xtNEOgY8QoVoLLc9hU/nYAGnbW+GjNrJA+mIV9rht0+ipU4H2kmjD2m0hh1z2Uds YdY95m62LGeHkM0rqXJBpSQn1Dv/Y6jpx9Ldau7IMgzdq3Yxqm/Lnvpl5OMs2G64 vuekFFOOJnEKR0njoUtiD6oUAKxkQySlxfDuki2BRC5Gz5XYspKrcZS5g90D59+0 QUEQt6F9efO539NelrP7EdbQQSXaNPGvW/hpUwaeO4HVs4PgkvKug4CVcXKGGzs/ VHkypjxlqfk8OIDxZFAlDXegyQheNFmCE2CPdKBC0kOM52Ua1h+FIZWO6oetXKqR 6juf98qk7z5pI7p3UjU5ERabOnABrSqVmaf8RH4leN5NrOEVT36HJURueC3QrF3F rCTTkFLyYuLdv2AdaiIqhR7YwOU04StOcPHAy95xVHLOKrH5ePIcD1TJzeLf0dZJ xhtUtuooLJrMLid8PZdprUGAmK7S70cSIOwRsR4ypRrNMCaXCgg= =d3PU -----END PGP SIGNATURE----- --ukqVmFXIpxQDfSSE--