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=202602 header.b=J20wUsSS; dkim-atps=neutral Received: from mail.ozlabs.org (gandalf.ozlabs.org [150.107.74.76]) by passt.top (Postfix) with ESMTPS id 030EA5A0271 for ; Tue, 03 Mar 2026 06:28:30 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gibson.dropbear.id.au; s=202602; t=1772515706; bh=nc7V4s7HvMyGV2xR1GRyrn2GaaXULkt/tNtUMBrxnr4=; h=Date:From:To:Cc:Subject:References:In-Reply-To:From; b=J20wUsSSdAmFfeUwXc4kekF8DzkWkXwff4akI64psfI0enMNgzbGcrp2CdJkBVLzC G6Y+U48MkV2dXLv7YA2n+zw4dk+Q/QR6fKvxHDucKmcNdnK0UpkEnOxwt/OJhb3hjl dMsxNM3rHJaTQlWMfeK+3ULt7PYPcs5uHV+GZxRtyKNRaLe9ZNx9m6Mq+UNVSvDfSx PPkezIhIgDRH4J9449/ZERGKzVnjyjc+q4RreaJ1mAfA/kLsL8f3lNQKclPrFwT5j8 4tWsRKCeULHL6ZCvj55+O9yGeLWby8RrMwMqPvDTwyfTIw1spAdKtPx78npACJo0c7 0IjsFzavjdftQ== Received: by gandalf.ozlabs.org (Postfix, from userid 1007) id 4fQ48V20vxz4wCQ; Tue, 03 Mar 2026 16:28:26 +1100 (AEDT) Date: Tue, 3 Mar 2026 15:53:39 +1100 From: David Gibson To: Jon Maloy Subject: Re: [PATCH v5 10/13] migrate: Update protocol to v3 for multi-address support Message-ID: References: <20260222174445.743845-1-jmaloy@redhat.com> <20260222174445.743845-11-jmaloy@redhat.com> MIME-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha512; protocol="application/pgp-signature"; boundary="j+duCen53Gx72kCA" Content-Disposition: inline In-Reply-To: <20260222174445.743845-11-jmaloy@redhat.com> Message-ID-Hash: L6LLSFXKXRSWU6FDAOPS6RRKIW34ZF7R X-Message-ID-Hash: L6LLSFXKXRSWU6FDAOPS6RRKIW34ZF7R 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: --j+duCen53Gx72kCA Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable On Sun, Feb 22, 2026 at 12:44:42PM -0500, Jon Maloy wrote: > We update the migration protocol to version 3 to support distributing > multiple addresses from the unified address array. The new protocol > migrates all address entries in the array, along with their prefix > lengths and flags, and leaves it to the receiver to filter which > ones he wants to apply. >=20 > Signed-off-by: Jon Maloy >=20 > --- > v4: - Broke out as separate commit > - Made number of transferable addresses variable > --- > migrate.c | 123 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 123 insertions(+) >=20 > diff --git a/migrate.c b/migrate.c > index 1990067..c2c2403 100644 > --- a/migrate.c > +++ b/migrate.c > @@ -122,6 +122,108 @@ static int seen_addrs_target_v2(struct ctx *c, > return 0; > } > =20 > +/** > + * addrs_source_v3() - Send all addresses with flags from source > + * @c: Execution context > + * @stage: Migration stage, unused > + * @fd: File descriptor for state transfer > + * > + * Send all address entries with their flags. The receiver can filter > + * based on flags as needed. This provides forward compatibility if > + * future versions need different address types. > + * > + * Return: 0 on success, positive error code on failure > + */ > +/* cppcheck-suppress [constParameterCallback, unmatchedSuppression] */ > +static int addrs_source_v3(struct ctx *c, > + const struct migrate_stage *stage, int fd) > +{ > + uint8_t addr_count =3D c->addr_count; > + > + (void)stage; > + > + /* Send count, then all addresses with flags, then MAC */ > + if (write_all_buf(fd, &addr_count, sizeof(addr_count))) > + return errno; > + > + if (addr_count && write_all_buf(fd, c->addrs, > + addr_count * sizeof(c->addrs[0]))) Writing the raw internal structures is kind of risky - it means migration will be broken by any change in the addrs entry format - including any alterations to the flags bit assignments. Mind you, it's probably not the only place in the current migration format with that problem. > + return errno; > + > + if (write_all_buf(fd, c->guest_mac, ETH_ALEN)) > + return errno; > + > + return 0; > +} > + > +/** > + * migrate_merge_addr() - Merge migrated address into local array > + * @c: Execution context > + * @addr: Address entry from migration source > + * > + * If the address already exists locally, merge the flags (preserving > + * local flags and adding migrated ones). Otherwise add as new entry. > + */ > +static void migrate_merge_addr(struct ctx *c, > + const struct inany_addr_entry *addr) > +{ > + struct inany_addr_entry *e; > + > + if (inany_is_unspecified(&addr->addr)) > + return; That would be a bug on the migration origin side, wouldn't it? > + > + /* Check if address already exists, merge flags */ > + for_each_addr(e, c, 0) { > + if (inany_equals(&e->addr, &addr->addr)) { Related to comments earlier in the series, should we be checking the whole prefix for equality? > + e->flags |=3D addr->flags; > + return; > + } > + } > + > + /* Add new entry if there's room */ > + if (c->addr_count < INANY_MAX_ADDRS) > + c->addrs[c->addr_count++] =3D *addr; We probably shouldn't continue silently if there isn't room - it's quite likely the migrated guest won't work properly if that's the case. > +} > + > +/** > + * addrs_target_v3() - Receive addresses on target > + * @c: Execution context > + * @stage: Migration stage, unused > + * @fd: File descriptor for state transfer > + * > + * Receive all address entries and merge only observed addresses into lo= cal > + * array. Source sends all addresses for forward compatibility, but targ= et > + * only applies those marked as observed by guest traffic. > + * > + * Return: 0 on success, positive error code on failure > + */ > +static int addrs_target_v3(struct ctx *c, > + const struct migrate_stage *stage, int fd) > +{ > + struct inany_addr_entry addrs[INANY_MAX_ADDRS]; > + uint8_t addr_count, i; > + > + (void)stage; > + > + if (read_all_buf(fd, &addr_count, sizeof(addr_count))) > + return errno; > + > + if (addr_count > INANY_MAX_ADDRS) > + addr_count =3D INANY_MAX_ADDRS; > + > + if (addr_count && read_all_buf(fd, addrs, addr_count * sizeof(addrs[0])= )) > + return errno; Reading and processing the addresses from the stream one by one would be slightly more elegant, and importantly it decouples the max number of addresses at the origin from that at the target. > + > + if (read_all_buf(fd, c->guest_mac, ETH_ALEN)) > + return errno; > + > + for (i =3D 0; i < addr_count; i++) > + if (addrs[i].flags & CONF_ADDR_OBSERVED) > + migrate_merge_addr(c, &addrs[i]); Can you re-use your addr_set function from earlier in the series here? It seems like the logic is pretty similar. > + > + return 0; > +} > + > /* Stages for version 2 */ > static const struct migrate_stage stages_v2[] =3D { > { > @@ -142,8 +244,29 @@ static const struct migrate_stage stages_v2[] =3D { > { 0 }, > }; > =20 > +/* Stages for version 3 (multiple observed IPv4 addresses) */ > +static const struct migrate_stage stages_v3[] =3D { > + { > + .name =3D "addresses", > + .source =3D addrs_source_v3, > + .target =3D addrs_target_v3, > + }, > + { > + .name =3D "prepare flows", > + .source =3D flow_migrate_source_pre, > + .target =3D NULL, > + }, > + { > + .name =3D "transfer flows", > + .source =3D flow_migrate_source, > + .target =3D flow_migrate_target, > + }, > + { 0 }, > +}; > + > /* Supported encoding versions, from latest (most preferred) to oldest */ > static const struct migrate_version versions[] =3D { > + { 3, stages_v3, }, > { 2, stages_v2, }, > /* v1 was released, but not widely used. It had bad endianness for the > * MSS and omitted timestamps, which meant it usually wouldn't work. > --=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 --j+duCen53Gx72kCA Content-Type: application/pgp-signature; name=signature.asc -----BEGIN PGP SIGNATURE----- iQIzBAEBCgAdFiEEO+dNsU4E3yXUXRK2zQJF27ox2GcFAmmmaUQACgkQzQJF27ox 2GddfA/9EPVu80KON3uN5+qI1sLzFj4hizouviuAUpdP32P2zR01MqrYqaHnJ3Cw 5XgkDU3i9sDMn17al1SMEnPxcq4rTMSrdspNQ4z/0KRbbZtMj4XZMSdLm2Lovhk4 NiG3A1XJiBWs6qP3DHoVntDveG7zGjk8gl2eQCpsZ0RF+YSsL6aPnX3YLwJ/LtXa GI5dEm99wWa9tCZElXI4kOGT74eO6dmLsJ/OdMitO2KwWOhUqhnD6VGwzbYtQzFP AfID+LoPPfEM+qkFu6h3nWDGZR1n1gOf9teTdLYq/wQi2MJQQQ1BCZATK/aRnXzp GG+5NCIUIzpMscnbX6DmwR2X0C+kFolZ4POxTnQ31/YGf7ywjQ2kKJfLAvMqucJa eqPDiH94hBETRaKg9rrwHcwMa11xpvrl4MZThYObafbcaQGmmUjxEdubgOERtWQw Mlaq5YR93EkZ9wIExvBc96OE0ZtDgwdh+Q1bCQPsEagDlcjQk28KUE/K2TjO6p9z j30hiiMBESmX2vLYfZqMZWDWbOjABtSOgDI3bvGHOOSXYs1Oa7SaGFUBxI9o2uFv uEVEYmcNeiK6APiknqk8P7Nonk4XSRlk5xA4dDIlbiRXSRd6nL7ljh/mA99af99p gCEt19H/S3hFetaLejL/UPPlTfgFfBBXWMm/0iXt2LT7T5ieqBs= =9B3b -----END PGP SIGNATURE----- --j+duCen53Gx72kCA--