From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: passt.top; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: passt.top; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=EViUSIzj; dkim-atps=neutral Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by passt.top (Postfix) with ESMTPS id DFD5A5A061D for ; Mon, 13 Apr 2026 02:53:32 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1776041611; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=idbJZKWNzaWO5J5iEU2gSnYOPbVxEp7THRuWkRwcaso=; b=EViUSIzjkDEH6LY7nwMuAgj6thuM4uzw9RqpK4sSbrbSnvNljv6qJbc0IozAgJ6c6VsPZo Z7QTzRDr4850/4hFkbpAnL12cunGoiRHXfc9K0Rs0lbPe1lAE8q5f10OeANzz3B3vy8TTU knkFWBSqO+LUgB1LzHZuLDLdXh1JqiA= Received: from mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-448-eBgeSem0NUOXqI129GamHA-1; Sun, 12 Apr 2026 20:53:28 -0400 X-MC-Unique: eBgeSem0NUOXqI129GamHA-1 X-Mimecast-MFC-AGG-ID: eBgeSem0NUOXqI129GamHA_1776041607 Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 633E0195609D; Mon, 13 Apr 2026 00:53:27 +0000 (UTC) Received: from jmaloy-thinkpadp16vgen1.rmtcaqc.csb (unknown [10.22.64.70]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 446F83000C16; Mon, 13 Apr 2026 00:53:26 +0000 (UTC) From: Jon Maloy To: sbrivio@redhat.com, david@gibson.dropbear.id.au, jmaloy@redhat.com, passt-dev@passt.top Subject: [PATCH v7 05/13] conf: Allow multiple -a/--address options per address family Date: Sun, 12 Apr 2026 20:53:11 -0400 Message-ID: <20260413005319.3295910-6-jmaloy@redhat.com> In-Reply-To: <20260413005319.3295910-1-jmaloy@redhat.com> References: <20260413005319.3295910-1-jmaloy@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: iWAH5dOrCnTEdHExXDor7PfVfeO3kpDDqk-nTJV0yIM_1776041607 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: 8bit content-type: text/plain; charset="US-ASCII"; x-default=true Message-ID-Hash: JPBVF7DLBPYEKIPTKTSQAJ3WKCDOWPCJ X-Message-ID-Hash: JPBVF7DLBPYEKIPTKTSQAJ3WKCDOWPCJ X-MailFrom: jmaloy@redhat.com 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 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: Allow specifying multiple addresses per family with -a/--address. The first address of each family is used for DHCP/DHCPv6 assignment. Signed-off-by: Jon Maloy --- v2: - Adapted to previous code changes v3: - Adapted to single-array strategy - Changes according to feedback from S. Brivio and D. Gibson. v4: - Stripped down and adapted after feedback from David G. v6: - Adapted to previous changes in series - Removed the "one address" limitation for -n option v7: - Updated man page. --- conf.c | 7 ++++--- fwd.c | 4 +--- passt.1 | 7 +++---- pasta.c | 14 ++++++++------ 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/conf.c b/conf.c index 591f561..8b4a7a0 100644 --- a/conf.c +++ b/conf.c @@ -939,9 +939,11 @@ static void usage(const char *name, FILE *f, int status) " 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 up to a maximum of %d times\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", + MAX_GUEST_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" @@ -1898,7 +1900,6 @@ void conf(struct ctx *c, int argc, char **argv) IN6_IS_ADDR_V4COMPAT(&addr.a6)) die("Invalid address: %s", optarg); - /* Legacy behaviour: replace existing address if any */ fwd_set_addr(c, &addr, CONF_ADDR_USER, prefix_len); if (inany_v4(&addr)) c->ip4.no_copy_addrs = true; diff --git a/fwd.c b/fwd.c index e676c18..d3f576a 100644 --- a/fwd.c +++ b/fwd.c @@ -250,14 +250,12 @@ void fwd_neigh_table_init(const struct ctx *c) } /** - * fwd_set_addr() - Add or update an address in the unified address array + * fwd_set_addr() - Update address entry, adding one if needed * @c: Execution context * @addr: Address to add (IPv4-mapped or IPv6) * @flags: CONF_ADDR_* flags for this address * @prefix_len: Prefix length in IPv6 or IPv4 format * - * Find the first existing entry of the same address family and - * overwrite it, or create a new one if none exists */ void fwd_set_addr(struct ctx *c, const union inany_addr *addr, uint8_t flags, int prefix_len) diff --git a/passt.1 b/passt.1 index 13e8df9..12ec857 100644 --- a/passt.1 +++ b/passt.1 @@ -164,16 +164,13 @@ An optional /\fIprefix_len\fR (0-32 for IPv4, 0-128 for IPv6) can be appended in CIDR notation (e.g. 192.0.2.1/24). This is an alternative to using the \fB-n\fR, \fB--netmask\fR option. Mixing CIDR notation with \fB-n\fR results in an error. -If a prefix length is assigned to an IPv6 address using this method, it will -in the current code version be overridden by the default value of 64. -This option can be specified zero (for defaults) to two times (once for IPv4, -once for IPv6). By default, assigned IPv4 and IPv6 addresses are taken from the host interfaces with the first default route, if any, for the corresponding IP version. If no default routes are available and there is any interface with any route for a given IP version, the first of these interfaces will be chosen instead. If no such interface exists for a given IP version, the link-local address 169.254.2.1 is assigned for IPv4, and no additional address will be assigned for IPv6. +This option can be given multiple times, indicating multiple different addresses. .TP .BR \-n ", " \-\-netmask " " \fImask @@ -181,6 +178,8 @@ Assign IPv4 netmask \fImask\fR, expressed as dot-decimal or number of bits, via DHCP (option 1). Alternatively, the prefix length can be specified using CIDR notation with the \fB-a\fR, \fB--address\fR option (e.g. \fB-a\fR 192.0.2.1/24). Mixing \fB-n\fR with CIDR notation results in an error. +When indicated, this option sets the prefix length of the first configured +IPv4 address only. If no address is indicated, the netmask associated with the adopted host address, if any, is used. If an address is indicated, but without a prefix length, the netmask is determined based on the corresponding network class. In all other diff --git a/pasta.c b/pasta.c index c51e4cd..b3936f5 100644 --- a/pasta.c +++ b/pasta.c @@ -343,14 +343,15 @@ void pasta_ns_conf(struct ctx *c) if (c->ifi4) { if (c->ip4.no_copy_addrs) { - a = fwd_get_addr(c, AF_INET, 0, 0); - if (a) { + for_each_addr(a, c->addrs, c->addr_count, AF_INET) { plen = inany_prefix_len(&a->addr, a->prefix_len); rc = nl_addr_set(nl_sock_ns, c->pasta_ifi, AF_INET, inany_v4(&a->addr), plen); + if (rc < 0) + break; } } else { rc = nl_addr_dup(nl_sock, c->ifi4, @@ -404,13 +405,14 @@ ipv4_done: 0, IFF_NOARP); if (c->ip6.no_copy_addrs) { - a = fwd_get_addr(c, AF_INET6, 0, 0); - if (a) + for_each_addr(a, c->addrs, c->addr_count, AF_INET6) { rc = nl_addr_set(nl_sock_ns, c->pasta_ifi, - AF_INET6, - &a->addr.a6, + AF_INET6, &a->addr.a6, a->prefix_len); + if (rc < 0) + break; + } } else { rc = nl_addr_dup(nl_sock, c->ifi6, nl_sock_ns, c->pasta_ifi, -- 2.52.0