From nobody Thu Jun 4 20:00:33 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.libvirt.org designates 38.145.34.151 as permitted sender) client-ip=38.145.34.151; envelope-from=devel-bounces@lists.libvirt.org; helo=lists.libvirt.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of lists.libvirt.org designates 38.145.34.151 as permitted sender) smtp.mailfrom=devel-bounces@lists.libvirt.org; dmarc=pass(p=reject dis=none) header.from=lists.libvirt.org ARC-Seal: i=1; a=rsa-sha256; t=1780379305; cv=none; d=zohomail.com; s=zohoarc; b=NR6SE36dJ+O1W9ot7Na098W4/OYVLiEAxfIZ/efnXMZ6+upJ8AbDBf/fcIJlzkL/s8917dzMoFGVPrrWUZxJh58Ejp5j1NoHNbrt2VodyQHm3+TD8sfBVkN1IIrJ1uKOwHjeIDWoqMbOi8hvkqf9xyl07YaP/MOsxs9q4B8UAPg= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1780379305; h=Content-Type:Content-Transfer-Encoding:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Owner:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:Reply-To:References:Subject:Subject:To:To:Message-Id:Cc; bh=+VSrPFfIK36MKpoazsVlYHur4lia5eNJVfVy8gJ/rck=; b=hfCROhq8aSXx8xgOpPjBDlSGfSKvBV+5DYfLQs8ylMevSrF+lCUXTOA4XaL7cokdkT0gmoneZdae6nXMDgeg+QbrjiDbTVfPW5mpod72cY/ZnPRKOjqUH66YkAVwcUUTRSAS/scSZVVreYQE5BAUe3fEAKu4EC77A153P6+TR5A= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of lists.libvirt.org designates 38.145.34.151 as permitted sender) smtp.mailfrom=devel-bounces@lists.libvirt.org; dmarc=pass header.from= (p=reject dis=none) Return-Path: Received: from lists.libvirt.org (lists.libvirt.org [38.145.34.151]) by mx.zohomail.com with SMTPS id 1780379305057422.9198846151862; Mon, 1 Jun 2026 22:48:25 -0700 (PDT) Received: by lists.libvirt.org (Postfix, from userid 993) id 310DD41B2F; Tue, 2 Jun 2026 01:48:23 -0400 (EDT) Received: from [172.19.199.4] (unknown [10.16.107.18]) by lists.libvirt.org (Postfix) with ESMTP id 1C772418FA; Tue, 2 Jun 2026 01:47:04 -0400 (EDT) Received: by lists.libvirt.org (Postfix, from userid 993) id CBCAA4196C; Tue, 2 Jun 2026 01:46:53 -0400 (EDT) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (3072 bits) server-digest SHA256) (No client certificate requested) by lists.libvirt.org (Postfix) with ESMTPS id 32D7D3F93A for ; Tue, 2 Jun 2026 01:46:52 -0400 (EDT) Received: from mx-prod-mc-05.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-586-I_GyID0eOEOvMCmBL0VaQA-1; Tue, 02 Jun 2026 01:46:50 -0400 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (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-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 9FE10195608B for ; Tue, 2 Jun 2026 05:46:49 +0000 (UTC) Received: from vhost3.router.laine.org (unknown [10.22.80.68]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 3811A1800576 for ; Tue, 2 Jun 2026 05:46:49 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-26) on lists.libvirt.org X-Spam-Level: X-Spam-Status: No, score=0.6 required=5.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,MAILING_LIST_MULTI,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H5, RCVD_IN_MSPIKE_WL,RCVD_IN_SBL_CSS,SPF_HELO_PASS autolearn=no autolearn_force=no version=4.0.1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1780379211; 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=+VSrPFfIK36MKpoazsVlYHur4lia5eNJVfVy8gJ/rck=; b=NwU/Ebv0qoWV5UwxJlgYxwLFf67wHyogE8dJ0YGbLz+RN8sO3mRSvqwyY4nM87SankSCLP qwwafprwRf0DTyCzWyNvGO6Zr3syn4tiUVFCtqIIMfZxvq/2f3H0UFybRwbs/NUT9l6R+0 plRNAmKflM1lk8rS+yeW7kwIhktXGJo= X-MC-Unique: I_GyID0eOEOvMCmBL0VaQA-1 X-Mimecast-MFC-AGG-ID: I_GyID0eOEOvMCmBL0VaQA_1780379209 To: devel@lists.libvirt.org Subject: [PATCH 1/4] qemu: new monitor function qemuMonitorAnnounceSelf() Date: Tue, 2 Jun 2026 01:46:44 -0400 Message-ID: <20260602054647.4165045-2-laine@redhat.com> In-Reply-To: <20260602054647.4165045-1-laine@redhat.com> References: <20260602054647.4165045-1-laine@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: fN8FXgrC67Nxxqy07JRanIcF7P2AF1DP1Q26mVvmEmY_1780379209 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable Message-ID-Hash: MSQBHI6ETERTBWDUKWEBOFZGZ5YKS6JD X-Message-ID-Hash: MSQBHI6ETERTBWDUKWEBOFZGZ5YKS6JD X-MailFrom: laine@redhat.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; header-match-devel.lists.libvirt.org-0; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header X-Mailman-Version: 3.3.10 Precedence: list List-Id: Development discussions about the libvirt library & tools Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: From: Laine Stump via Devel Reply-To: Laine Stump X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZM-MESSAGEID: 1780379308782154100 Content-Type: text/plain; charset="utf-8"; x-default="true" From: Laine Stump This new function sends the command "self-announce" to QEMU, causing it to inject a series of gratuitous ARP packets (GARP) into the output stream of one or all guest interfaces, which will force any switches the same collision domain to update their forwarding db for that interface. There are several parameters that control which interfaces the GARP packets are sent on, as well as their number and interval, but all of these parameters have sane defaults (even though QEMU's own self-announce requires they all be specified in the QMP command). All parameters except the device are just unsigned integers; the QEMU command accepts a list of interface devices, but it seems much more likely that someone will either want to announce a single interface, or all of them, so our function just accepts a single device name that can be present or not, and puts that single name into a list (in the rare case that someone wants to announce multiple interfaces but not all of them, they can call our API multiple times). Signed-off-by: Laine Stump Reviewed-by: Martin Kletzander --- src/qemu/qemu_monitor.c | 13 +++++++++ src/qemu/qemu_monitor.h | 8 ++++++ src/qemu/qemu_monitor_json.c | 55 ++++++++++++++++++++++++++++++++++++ src/qemu/qemu_monitor_json.h | 8 ++++++ 4 files changed, 84 insertions(+) diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index ef83e7b69a..baa78dd6fe 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -4592,3 +4592,16 @@ qemuMonitorBlockLatencyHistogramSet(qemuMonitor *mon, boundaries_zone, boundaries_flush); } + +int +qemuMonitorAnnounceSelf(qemuMonitor *mon, + const char *device, + unsigned int initial, + unsigned int max, + unsigned int rounds, + unsigned int step) +{ + QEMU_CHECK_MONITOR(mon); + + return qemuMonitorJSONAnnounceSelf(mon, device, initial, max, rounds, = step); +} diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index f93d193d75..c2afb580e4 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -1995,3 +1995,11 @@ qemuMonitorBlockLatencyHistogramSet(qemuMonitor *mon, unsigned int *boundaries_write, unsigned int *boundaries_zone, unsigned int *boundaries_flush); + +int +qemuMonitorAnnounceSelf(qemuMonitor *mon, + const char *device, + unsigned int initial, + unsigned int max, + unsigned int rounds, + unsigned int step); diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index 7efd3f443a..074eeb856c 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -9237,3 +9237,58 @@ qemuMonitorJSONBlockLatencyHistogramSet(qemuMonitor = *mon, =20 return qemuMonitorJSONCheckError(cmd, reply); } + + +int +qemuMonitorJSONAnnounceSelf(qemuMonitor *mon, + const char *device, + unsigned int initial, + unsigned int max, + unsigned int rounds, + unsigned int step) +{ + g_autoptr(virJSONValue) cmd =3D NULL; + g_autoptr(virJSONValue) reply =3D NULL; + g_autoptr(virJSONValue) devlist =3D NULL; + + /* announce-self optionally accepts a list of device names, but we + * only support a single device name (or none), so we make a + * NULL-terminated list with a single item + */ + if (device) { + devlist =3D virJSONValueNewArray(); + if (virJSONValueArrayAppendString(devlist, device) < 0) + return -1; + } + + /* all the other parameters are mandatory for QEMU, but we make + * them optional to simplify using the API. Since the value 0 + * would be nonsensical for any of these, we make that the "use a + * default value" sentinal. The values we use as default are the + * values QEMU will use internally when it does an announce-self + * at the end of a migration. + */ + if (!initial) + initial =3D 50; + if (!max) + max =3D 550; + if (!rounds) + rounds =3D 5; + if (!step) + step =3D 50; + + if (!(cmd =3D qemuMonitorJSONMakeCommand("announce-self", + "A:interfaces", &devlist, + "u:initial", initial, + "u:max", max, + "u:rounds", rounds, + "u:step", step, + NULL))) { + return -1; + } + + if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0) + return -1; + + return qemuMonitorJSONCheckError(cmd, reply); +} diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h index 5034c8d23d..f4c093d717 100644 --- a/src/qemu/qemu_monitor_json.h +++ b/src/qemu/qemu_monitor_json.h @@ -828,3 +828,11 @@ qemuMonitorJSONBlockLatencyHistogramSet(qemuMonitor *m= on, unsigned int *boundaries_write, unsigned int *boundaries_zone, unsigned int *boundaries_flush); + +int +qemuMonitorJSONAnnounceSelf(qemuMonitor *mon, + const char *device, + unsigned int initial, + unsigned int max, + unsigned int rounds, + unsigned int step); --=20 2.54.0 From nobody Thu Jun 4 20:00:33 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.libvirt.org designates 38.145.34.151 as permitted sender) client-ip=38.145.34.151; envelope-from=devel-bounces@lists.libvirt.org; helo=lists.libvirt.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of lists.libvirt.org designates 38.145.34.151 as permitted sender) smtp.mailfrom=devel-bounces@lists.libvirt.org; dmarc=pass(p=reject dis=none) header.from=lists.libvirt.org ARC-Seal: i=1; a=rsa-sha256; t=1780379528; cv=none; d=zohomail.com; s=zohoarc; b=bHjvKzOS2NcXtmhj6PRTsiqN30EqzMDXFZzmnjt9bnEIDNM54brB0yFNZ9wI4qtkndheQYz36fFKUzZczkUnoyTNpKNfc3O5/UaSDdaaMyeZ25S3jDm2skvvjppLhgsKHBd3lXdty06a6M0iVnUmfqY5wwQ0A+oJrkk9SFxdapg= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1780379528; h=Content-Type:Content-Transfer-Encoding:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Owner:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:Reply-To:References:Subject:Subject:To:To:Message-Id:Cc; bh=14c7BvLjI9DPC8a6xzkaguppuERXtM4E2MJMvWg5tUY=; b=UHbOfUcXgN9owyFywQAl2SssCLzQJJD3jxBVJsZ87KqfTMkh5+62pzdhGWBw4efF1amyqD5QmYm83ZVvgZam66+pPP43cWNXyg45Qu4mGr48Hp+/+xjW3M7PtUPzFNzpiuruEQChVYyjGJJo9ukLgcZs3HVYFtlVLqWrG7212Cc= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of lists.libvirt.org designates 38.145.34.151 as permitted sender) smtp.mailfrom=devel-bounces@lists.libvirt.org; dmarc=pass header.from= (p=reject dis=none) Return-Path: Received: from lists.libvirt.org (lists.libvirt.org [38.145.34.151]) by mx.zohomail.com with SMTPS id 1780379528784829.1704161680083; Mon, 1 Jun 2026 22:52:08 -0700 (PDT) Received: by lists.libvirt.org (Postfix, from userid 993) id 18078419FE; Tue, 2 Jun 2026 01:52:08 -0400 (EDT) Received: from [172.19.199.4] (unknown [10.16.107.18]) by lists.libvirt.org (Postfix) with ESMTP id 2E0F941D64; Tue, 2 Jun 2026 01:47:18 -0400 (EDT) Received: by lists.libvirt.org (Postfix, from userid 993) id AE065418F6; Tue, 2 Jun 2026 01:46:54 -0400 (EDT) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (3072 bits)) (No client certificate requested) by lists.libvirt.org (Postfix) with ESMTPS id A2D1241908 for ; Tue, 2 Jun 2026 01:46:52 -0400 (EDT) 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-586-eN1OzD8WOpioM7lJ1z5yNA-1; Tue, 02 Jun 2026 01:46:51 -0400 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (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 5BBD5195608B for ; Tue, 2 Jun 2026 05:46:50 +0000 (UTC) Received: from vhost3.router.laine.org (unknown [10.22.80.68]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id E7B7F180034E for ; Tue, 2 Jun 2026 05:46:49 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-26) on lists.libvirt.org X-Spam-Level: X-Spam-Status: No, score=0.6 required=5.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,MAILING_LIST_MULTI,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H5, RCVD_IN_MSPIKE_WL,RCVD_IN_SBL_CSS,SPF_HELO_PASS autolearn=no autolearn_force=no version=4.0.1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1780379212; 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=14c7BvLjI9DPC8a6xzkaguppuERXtM4E2MJMvWg5tUY=; b=XTmYALU+IKI0TH591hM6IT8o47EuMxvBJjbHm74Dy1hA5S3fdQQUXxdMVA7blOj94g4OLd Yakt8cHOtvZWfsJge53EVUm/xt109mstVnWwJ/BS810DTnu90vWrD2uAi/ZGxo3pOSQU6y SP/FannOsjgjEPNz/LS6ASbs23736qE= X-MC-Unique: eN1OzD8WOpioM7lJ1z5yNA-1 X-Mimecast-MFC-AGG-ID: eN1OzD8WOpioM7lJ1z5yNA_1780379210 To: devel@lists.libvirt.org Subject: [PATCH 2/4] API: Introduce virDomainAnnounceInterface Date: Tue, 2 Jun 2026 01:46:45 -0400 Message-ID: <20260602054647.4165045-3-laine@redhat.com> In-Reply-To: <20260602054647.4165045-1-laine@redhat.com> References: <20260602054647.4165045-1-laine@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: Hm7Iq_HYtOjQ4Ko1SFiLCbTI3GxqffRWZv9IQCRN2q4_1780379210 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable Message-ID-Hash: EW2IVJOEMJFDV22ATWBXYJDQK4VE7OJJ X-Message-ID-Hash: EW2IVJOEMJFDV22ATWBXYJDQK4VE7OJJ X-MailFrom: laine@redhat.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; header-match-devel.lists.libvirt.org-0; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header X-Mailman-Version: 3.3.10 Precedence: list List-Id: Development discussions about the libvirt library & tools Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: From: Laine Stump via Devel Reply-To: Laine Stump X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZM-MESSAGEID: 1780379533180154100 Content-Type: text/plain; charset="utf-8"; x-default="true" From: Laine Stump This API provides a way for a libvirt client to force a guest to inject a "Gratuuitous ARP" packet into the outgoing stream of one, or all, network devices of the guest; this will be used to update the forwarding tables of any network switches in the local broadcast domain so that they will begin forarding traffic correctly in a more timely manner after network topology changes. Signed-off-by: Laine Stump Reviewed-by: Martin Kletzander --- include/libvirt/libvirt-domain.h | 46 ++++++++++++++++++++++ src/driver-hypervisor.h | 8 ++++ src/libvirt-domain.c | 65 ++++++++++++++++++++++++++++++++ src/libvirt_public.syms | 5 +++ src/remote/remote_driver.c | 1 + src/remote/remote_protocol.x | 19 +++++++++- src/remote_protocol-structs | 10 +++++ 7 files changed, 153 insertions(+), 1 deletion(-) diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-dom= ain.h index 8f07ef2156..ccc74ad6a4 100644 --- a/include/libvirt/libvirt-domain.h +++ b/include/libvirt/libvirt-domain.h @@ -9049,5 +9049,51 @@ virDomainDelThrottleGroup(virDomainPtr dom, const char *group, unsigned int flags); =20 +/** + * VIR_DOMAIN_ANNOUNCE_INTERFACE_INITIAL: + * + * Initial delay in milliseonds before the first announce packet is + * sent. If unspecified or 0, a default value of 50 will be used. + * + * Since: 12.5.0 + */ +# define VIR_DOMAIN_ANNOUNCE_INTERFACE_INITIAL "initial" + +/** + * VIR_DOMAIN_ANNOUNCE_INTERFACE_MAX: + * + * Maximum delay in milliseonds between packets. If unspecified or 0, + * a default value of 550 will be used. + * + * Since: 12.5.0 + */ +# define VIR_DOMAIN_ANNOUNCE_INTERFACE_MAX "max" + +/** + * VIR_DOMAIN_ANNOUNCE_INTERFACE_ROUNDS: + * + * The number of packets to send. If unspecified or 0, a default value + * of 5 will be used. + * + * Since: 12.5.0 + */ +# define VIR_DOMAIN_ANNOUNCE_INTERFACE_ROUNDS "rounds" + +/** + * VIR_DOMAIN_ANNOUNCE_INTERFACE_STEP: + * + * Increment added to the delay (in milliseconds) after each packet is + * sent. If unspecified or 0, a default value of 50 will be used. + * + * Since: 12.5.0 + */ +# define VIR_DOMAIN_ANNOUNCE_INTERFACE_STEP "step" + +int +virDomainAnnounceInterface(virDomainPtr dom, + const char *device, + virTypedParameterPtr params, + int nparams, + unsigned int flags); =20 #endif /* LIBVIRT_DOMAIN_H */ diff --git a/src/driver-hypervisor.h b/src/driver-hypervisor.h index 6a43688b0c..0add95de96 100644 --- a/src/driver-hypervisor.h +++ b/src/driver-hypervisor.h @@ -1473,6 +1473,13 @@ typedef int const char *groupname, unsigned int flags); =20 +typedef int +(*virDrvDomainAnnounceInterface)(virDomainPtr dom, + const char *device, + virTypedParameterPtr params, + int nparams, + unsigned int flags); + typedef struct _virHypervisorDriver virHypervisorDriver; =20 /** @@ -1750,4 +1757,5 @@ struct _virHypervisorDriver { virDrvDomainGraphicsReload domainGraphicsReload; virDrvDomainSetThrottleGroup domainSetThrottleGroup; virDrvDomainDelThrottleGroup domainDelThrottleGroup; + virDrvDomainAnnounceInterface domainAnnounceInterface; }; diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c index a4cbeb8ad4..f9ee416fe7 100644 --- a/src/libvirt-domain.c +++ b/src/libvirt-domain.c @@ -14308,3 +14308,68 @@ virDomainDelThrottleGroup(virDomainPtr dom, virDispatchError(dom->conn); return -1; } + + +/** + * virDomainAnnounceInterface: + * @dom: pointer to domain object + * @device: the interface name or mac address, or NULL to announce all int= erfaces + * @params: pointer to typed parameters object + * @nparams: number of parameters in @params + * @flags: currently unused, pass 0 + * + * Cause this domain to "announce" its network interfaces by injecting + * a series of "gratuitous ARP" packets into the outgoing data stream + * for the interface matching @device (or all interfaces). This should + * cause local switches to direct traffic for that MAC address + * correctly after a topology change. + * + * See VIR_DOMAIN_ANNOUNCE_INTERFACE_* for detailed descriptions of + * accepted parameters. + * + * Returns: 0 on success, + * -1 otherwise. + * + * Since: 12.5.0 + */ +int +virDomainAnnounceInterface(virDomainPtr dom, + const char *device, + virTypedParameterPtr params, + int nparams, + unsigned int flags) +{ + virConnectPtr conn; + + VIR_DEBUG("dom=3D%p, device=3D'%s' params=3D%p nparams=3D%d flags=3D0x= %x", + dom, NULLSTR(device), params, nparams, flags); + VIR_TYPED_PARAMS_DEBUG(params, nparams); + + virResetLastError(); + + virCheckDomainReturn(dom, -1); + + conn =3D dom->conn; + + virCheckReadOnlyGoto(conn->flags, error); + if (nparams !=3D 0) + virCheckNonNullArgGoto(params, error); + else + virCheckNullArgGoto(params, error); + + if (virTypedParameterValidateSet(conn, params, nparams) < 0) + goto error; + + if (conn->driver->domainAnnounceInterface) { + int ret =3D conn->driver->domainAnnounceInterface(dom, device, par= ams, nparams, flags); + if (ret < 0) + goto error; + return ret; + } + + virReportUnsupportedError(); + + error: + virDispatchError(conn); + return -1; +} diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms index c506acd2ed..64ed641b7f 100644 --- a/src/libvirt_public.syms +++ b/src/libvirt_public.syms @@ -956,4 +956,9 @@ LIBVIRT_11.2.0 { virDomainDelThrottleGroup; } LIBVIRT_10.2.0; =20 +LIBVIRT_12.5.0 { + global: + virDomainAnnounceInterface; +} LIBVIRT_11.2.0; + # .... define new API here using predicted next version number .... diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index 873e3d173c..16e82031e9 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -8004,6 +8004,7 @@ static virHypervisorDriver hypervisor_driver =3D { .domainGraphicsReload =3D remoteDomainGraphicsReload, /* 10.2.0 */ .domainSetThrottleGroup =3D remoteDomainSetThrottleGroup, /* 11.2.0 */ .domainDelThrottleGroup =3D remoteDomainDelThrottleGroup, /* 11.2.0 */ + .domainAnnounceInterface =3D remoteDomainAnnounceInterface, /* 12.5.0 = */ }; =20 static virNetworkDriver network_driver =3D { diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index 4adba82f6d..32185fde2f 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -293,6 +293,10 @@ const REMOTE_DOMAIN_AUTHORIZED_SSH_KEYS_MAX =3D 2048; /* Upper limit on number of messages */ const REMOTE_DOMAIN_MESSAGES_MAX =3D 2048; =20 +/* + * Upper limit on number of domain announce interface parameters + */ +const REMOTE_DOMAIN_ANNOUNCE_INTERFACE_PARAMS_MAX =3D 16; =20 /* UUID. VIR_UUID_BUFLEN definition comes from libvirt.h */ typedef opaque remote_uuid[VIR_UUID_BUFLEN]; @@ -4023,6 +4027,13 @@ struct remote_domain_event_callback_channel_lifecycl= e_msg { int reason; }; =20 +struct remote_domain_announce_interface_args { + remote_nonnull_domain dom; + remote_string device; + remote_typed_param params; + unsigned int flags; +}; + /*----- Protocol. -----*/ =20 /* Define the program number, protocol version and procedure numbers here.= */ @@ -7146,5 +7157,11 @@ enum remote_procedure { * @generate: both * @acl: none */ - REMOTE_PROC_DOMAIN_EVENT_CALLBACK_CHANNEL_LIFECYCLE =3D 455 + REMOTE_PROC_DOMAIN_EVENT_CALLBACK_CHANNEL_LIFECYCLE =3D 455, + + /** + * @generate: both + * @acl: domain:write + */ + REMOTE_PROC_DOMAIN_ANNOUNCE_INTERFACE =3D 456 }; diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs index dd297bffff..6093a85c98 100644 --- a/src/remote_protocol-structs +++ b/src/remote_protocol-structs @@ -3349,6 +3349,15 @@ struct remote_domain_event_callback_channel_lifecycl= e_msg { int state; int reason; }; +struct remote_domain_announce_interface_args { + remote_nonnull_domain dom; + remote_string device; + struct { + u_int params_len; + remote_typed_param * params_val; + } params; + u_int flags; +}; enum remote_procedure { REMOTE_PROC_CONNECT_OPEN =3D 1, REMOTE_PROC_CONNECT_CLOSE =3D 2, @@ -3805,4 +3814,5 @@ enum remote_procedure { REMOTE_PROC_DOMAIN_EVENT_NIC_MAC_CHANGE =3D 453, REMOTE_PROC_DOMAIN_EVENT_VCPU_REMOVED =3D 454, REMOTE_PROC_DOMAIN_EVENT_CALLBACK_CHANNEL_LIFECYCLE =3D 455, + REMOTE_PROC_DOMAIN_ANNOUNCE_INTERFACE =3D 456, }; --=20 2.54.0 From nobody Thu Jun 4 20:00:33 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.libvirt.org designates 38.145.34.151 as permitted sender) client-ip=38.145.34.151; envelope-from=devel-bounces@lists.libvirt.org; helo=lists.libvirt.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of lists.libvirt.org designates 38.145.34.151 as permitted sender) smtp.mailfrom=devel-bounces@lists.libvirt.org; dmarc=pass(p=reject dis=none) header.from=lists.libvirt.org ARC-Seal: i=1; a=rsa-sha256; t=1780379441; cv=none; d=zohomail.com; s=zohoarc; b=nQKTBEaYVvu0DxEHp2IovITsIymWtWfHM3OMzVN0+BeyeUuySTrSzvUEFonjWjrvNu+Gx3/MxGwdwFXzBV0cuMr43exWY3Zr5CmqPjyDoNgqrfbx4+j6nrsfcZSQIOkpI0pJExSm71xw7t+Zg/2WL/PVRwZmylSGhNdrm0RPNHk= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1780379441; h=Content-Type:Content-Transfer-Encoding:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Owner:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:Reply-To:References:Subject:Subject:To:To:Message-Id:Cc; bh=s037dWrjIs7yMISTtVa6ExeBxT9HrTBZujFluwkTS5E=; b=mSYvMCEsxJrwFReq2TS4NScsTurypD3MOboKSNA6ykNaqnUrArsVVQgTShrFELywJ+0pqrOh+BUKJJBqZojRVH7500vXBhcaxXJ/E2DmYYvZqgjJt7A4p/VHzNwt0NAZkdeEcuwE5ziRIHqO1KxddL7SBld6VDgsyl2WG3CBDQA= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of lists.libvirt.org designates 38.145.34.151 as permitted sender) smtp.mailfrom=devel-bounces@lists.libvirt.org; dmarc=pass header.from= (p=reject dis=none) Return-Path: Received: from lists.libvirt.org (lists.libvirt.org [38.145.34.151]) by mx.zohomail.com with SMTPS id 1780379441446442.7643050584055; Mon, 1 Jun 2026 22:50:41 -0700 (PDT) Received: by lists.libvirt.org (Postfix, from userid 993) id CF4C741AFC; Tue, 2 Jun 2026 01:50:39 -0400 (EDT) Received: from [172.19.199.4] (unknown [10.16.107.18]) by lists.libvirt.org (Postfix) with ESMTP id 33B3F41D0F; Tue, 2 Jun 2026 01:47:13 -0400 (EDT) Received: by lists.libvirt.org (Postfix, from userid 993) id 5848A3F93A; Tue, 2 Jun 2026 01:46:54 -0400 (EDT) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (3072 bits) server-digest SHA256) (No client certificate requested) by lists.libvirt.org (Postfix) with ESMTPS id 9AF78418F1 for ; Tue, 2 Jun 2026 01:46:53 -0400 (EDT) Received: from mx-prod-mc-03.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-581-jnBgMSKKMpKr6fNDue842w-1; Tue, 02 Jun 2026 01:46:51 -0400 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (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-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 0C7201956058 for ; Tue, 2 Jun 2026 05:46:51 +0000 (UTC) Received: from vhost3.router.laine.org (unknown [10.22.80.68]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 992A4180034E for ; Tue, 2 Jun 2026 05:46:50 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-26) on lists.libvirt.org X-Spam-Level: X-Spam-Status: No, score=0.6 required=5.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,MAILING_LIST_MULTI,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL,RCVD_IN_SBL_CSS,SPF_HELO_PASS autolearn=no autolearn_force=no version=4.0.1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1780379213; 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=s037dWrjIs7yMISTtVa6ExeBxT9HrTBZujFluwkTS5E=; b=a5thmYPHefvoaZwjvu9phn6UFJ0z0HjqoHh4pMDFDp9uOaj9tCUxjeiFhyiT0utSKnD8oG Hkn+XlRMfJzpCyLUtZpGR9KcscGuFAuGem4KyRwbyjOLe+9zN8juG149Aqelo/XE/fqiMw rIJ3HgEexG0O765jDLnl0fF/X3ePYyg= X-MC-Unique: jnBgMSKKMpKr6fNDue842w-1 X-Mimecast-MFC-AGG-ID: jnBgMSKKMpKr6fNDue842w_1780379211 To: devel@lists.libvirt.org Subject: [PATCH 3/4] qemu: implement virDomainAnnounceInterface() API Date: Tue, 2 Jun 2026 01:46:46 -0400 Message-ID: <20260602054647.4165045-4-laine@redhat.com> In-Reply-To: <20260602054647.4165045-1-laine@redhat.com> References: <20260602054647.4165045-1-laine@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: EK-J8Rf--ambu2J9PixmK8SXyjtBJNIIb8QiyXEecoI_1780379211 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable Message-ID-Hash: NS2A5ZYGWINIYKGSQ7J46JARWUEXOBWU X-Message-ID-Hash: NS2A5ZYGWINIYKGSQ7J46JARWUEXOBWU X-MailFrom: laine@redhat.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; header-match-devel.lists.libvirt.org-0; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header X-Mailman-Version: 3.3.10 Precedence: list List-Id: Development discussions about the libvirt library & tools Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: From: Laine Stump via Devel Reply-To: Laine Stump X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZM-MESSAGEID: 1780379442717158500 Content-Type: text/plain; charset="utf-8"; x-default="true" From: Laine Stump using qemuMonitorAnnounceSelf(). Note that the other public domain interface APIs expect interface to be specified by either its "target" name (i.e. the name of the tap/macvtap device on the host) or by the MAC address, but qemuMonitorAnnounceSelf() expects the QEMU "device id" (which is known in libvirt as the "alias"), so we have to convert. Resolves: https://redhat.atlassian.net/browse/RHEL-7047 Signed-off-by: Laine Stump Reviewed-by: Martin Kletzander --- src/qemu/qemu_driver.c | 81 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 80 insertions(+), 1 deletion(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 58b68a6e2b..872cf0e8ee 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -20865,7 +20865,85 @@ qemuDomainDelThrottleGroup(virDomainPtr dom, } =20 =20 -static virHypervisorDriver qemuHypervisorDriver =3D { + + +static int +qemuDomainAnnounceInterface(virDomainPtr dom, + const char *device, + virTypedParameterPtr params, + int nparams, + unsigned int flags) +{ + virDomainObj *vm =3D NULL; + int ret =3D -1; + qemuDomainObjPrivate *priv; + const char *alias =3D NULL; + unsigned int initial =3D 0; + unsigned int max =3D 0; + unsigned int rounds =3D 0; + unsigned int step =3D 0; + + /* no flags supported */ + virCheckFlags(0, -1); + + if (virTypedParamsValidate(params, nparams, + VIR_DOMAIN_ANNOUNCE_INTERFACE_INITIAL, VIR_= TYPED_PARAM_UINT, + VIR_DOMAIN_ANNOUNCE_INTERFACE_MAX, VIR_TYPE= D_PARAM_UINT, + VIR_DOMAIN_ANNOUNCE_INTERFACE_ROUNDS, VIR_T= YPED_PARAM_UINT, + VIR_DOMAIN_ANNOUNCE_INTERFACE_STEP, VIR_TYP= ED_PARAM_UINT, + NULL) < 0) + return -1; + + if (params && nparams) { + virTypedParamsGetUInt(params, nparams, VIR_DOMAIN_ANNOUNCE_INTERFA= CE_INITIAL, &initial); + virTypedParamsGetUInt(params, nparams, VIR_DOMAIN_ANNOUNCE_INTERFA= CE_MAX, &max); + virTypedParamsGetUInt(params, nparams, VIR_DOMAIN_ANNOUNCE_INTERFA= CE_ROUNDS, &rounds); + virTypedParamsGetUInt(params, nparams, VIR_DOMAIN_ANNOUNCE_INTERFA= CE_STEP, &step); + } + + if (!(vm =3D qemuDomainObjFromDomain(dom))) + return -1; + priv =3D vm->privateData; + + if (virDomainAnnounceInterfaceEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + + if (virDomainObjBeginJob(vm, VIR_JOB_MODIFY) < 0) + goto cleanup; + + if (virDomainObjCheckActive(vm) < 0) + goto endjob; + + /* the user is sending either the interface MAC address or the + * name of the tap device (because that's how other APIs are + * implemented), but qemu's announce-self command expects the + * device id (known in libvirt as the "alias id"), so we need to + * find the and grab the alias from there + */ + + if (device) { + virDomainNetDef *net =3D NULL; + + if (!(net =3D virDomainNetFind(vm->def, device))) + goto endjob; + + alias =3D net->info.alias; + } + + qemuDomainObjEnterMonitor(vm); + ret =3D qemuMonitorAnnounceSelf(priv->mon, alias, initial, max, rounds= , step); + qemuDomainObjExitMonitor(vm); + + endjob: + virDomainObjEndJob(vm); + + cleanup: + virDomainObjEndAPI(&vm); + return ret; +} + + + static virHypervisorDriver qemuHypervisorDriver =3D { .name =3D QEMU_DRIVER_NAME, .connectURIProbe =3D qemuConnectURIProbe, .connectOpen =3D qemuConnectOpen, /* 0.2.0 */ @@ -21119,6 +21197,7 @@ static virHypervisorDriver qemuHypervisorDriver =3D= { .domainSetAutostartOnce =3D qemuDomainSetAutostartOnce, /* 11.2.0 */ .domainSetThrottleGroup =3D qemuDomainSetThrottleGroup, /* 11.2.0 */ .domainDelThrottleGroup =3D qemuDomainDelThrottleGroup, /* 11.2.0 */ + .domainAnnounceInterface =3D qemuDomainAnnounceInterface /* 12.4.0 */ }; =20 =20 --=20 2.54.0 From nobody Thu Jun 4 20:00:33 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.libvirt.org designates 38.145.34.151 as permitted sender) client-ip=38.145.34.151; envelope-from=devel-bounces@lists.libvirt.org; helo=lists.libvirt.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of lists.libvirt.org designates 38.145.34.151 as permitted sender) smtp.mailfrom=devel-bounces@lists.libvirt.org; dmarc=pass(p=reject dis=none) header.from=lists.libvirt.org ARC-Seal: i=1; a=rsa-sha256; t=1780379629; cv=none; d=zohomail.com; s=zohoarc; b=bGdXOYzXS+PIsZXDBWhDV2LjH36kfK/g0Plj7ldxXB4ZnBROdb+Nf6NxJXf5X8IB9/abqPZWx2FOUyHaMbg4pmAm4rX3QfWszfefkQmtzxODpQ05xLLsMzPuL1mDlzRkfbr9I8SbUGqa8izANKypckpTIwfV0Jj4vQjlTLL9amU= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1780379629; h=Content-Type:Content-Transfer-Encoding:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Owner:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:Reply-To:References:Subject:Subject:To:To:Message-Id:Cc; bh=fiMIyEPqpgf0p0wkm8hmbTL8tQcitdKLoWXsuLWEOfk=; b=h/9FGiRjYx0gDAyo8KeX55x+k7E7qLiZPyljyzzL1a33lzKbcxtWln2/i97nUyla2aQsiIBVMMj3cXxorOpUUHNlCzmdYfCphLapBE9QKR0MUPVIix//xYKCCCHipLW05KRVEpDchB/f8xtSPj5Hwv4FYK2RDRpmD7oL0vbu0Ys= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of lists.libvirt.org designates 38.145.34.151 as permitted sender) smtp.mailfrom=devel-bounces@lists.libvirt.org; dmarc=pass header.from= (p=reject dis=none) Return-Path: Received: from lists.libvirt.org (lists.libvirt.org [38.145.34.151]) by mx.zohomail.com with SMTPS id 1780379629264762.2909703765691; Mon, 1 Jun 2026 22:53:49 -0700 (PDT) Received: by lists.libvirt.org (Postfix, from userid 993) id 7E1CB4196C; Tue, 2 Jun 2026 01:53:48 -0400 (EDT) Received: from [172.19.199.4] (unknown [10.16.107.18]) by lists.libvirt.org (Postfix) with ESMTP id 6CA8D41AE6; Tue, 2 Jun 2026 01:47:22 -0400 (EDT) Received: by lists.libvirt.org (Postfix, from userid 993) id 6A81B3F93A; Tue, 2 Jun 2026 01:46:55 -0400 (EDT) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (3072 bits) server-digest SHA256) (No client certificate requested) by lists.libvirt.org (Postfix) with ESMTPS id A3F81418F1 for ; Tue, 2 Jun 2026 01:46:54 -0400 (EDT) Received: from mx-prod-mc-05.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-493-map-ylu-NcazvgbZqsKP5g-1; Tue, 02 Jun 2026 01:46:52 -0400 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (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-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id B1713195609D for ; Tue, 2 Jun 2026 05:46:51 +0000 (UTC) Received: from vhost3.router.laine.org (unknown [10.22.80.68]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 49BC7180034E for ; Tue, 2 Jun 2026 05:46:51 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-26) on lists.libvirt.org X-Spam-Level: X-Spam-Status: No, score=0.6 required=5.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,MAILING_LIST_MULTI,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL,RCVD_IN_SBL_CSS,SPF_HELO_PASS autolearn=no autolearn_force=no version=4.0.1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1780379214; 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=fiMIyEPqpgf0p0wkm8hmbTL8tQcitdKLoWXsuLWEOfk=; b=Xz8oLTui/WK70JKjhgdlDpLjOd6xielNZf7sWjFany4yPl0Fk7G0ANk9ZNppYqdZ+5SjLp +SMtDOsEovUDQ2SMwpeI8FVXgh9NoaiHfMGur6qO/Yt9WAH8Pq4sO7x0EJymIu2du/w42O dZPEclyXPkGdx518Wn0oOCeT+qjMzgI= X-MC-Unique: map-ylu-NcazvgbZqsKP5g-1 X-Mimecast-MFC-AGG-ID: map-ylu-NcazvgbZqsKP5g_1780379211 To: devel@lists.libvirt.org Subject: [PATCH 4/4] virsh: new command "domifannounce" Date: Tue, 2 Jun 2026 01:46:47 -0400 Message-ID: <20260602054647.4165045-5-laine@redhat.com> In-Reply-To: <20260602054647.4165045-1-laine@redhat.com> References: <20260602054647.4165045-1-laine@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: Itu2Yy9UnbvZZ88Suh0rHrhdvvOTmaGYF4dvPU9AnGo_1780379211 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable Message-ID-Hash: 4YOKOQTRVQPITRRCH5GK33PGHEIPZG6Z X-Message-ID-Hash: 4YOKOQTRVQPITRRCH5GK33PGHEIPZG6Z X-MailFrom: laine@redhat.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; header-match-devel.lists.libvirt.org-0; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header X-Mailman-Version: 3.3.10 Precedence: list List-Id: Development discussions about the libvirt library & tools Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: From: Laine Stump via Devel Reply-To: Laine Stump X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZM-MESSAGEID: 1780379632587154100 Content-Type: text/plain; charset="utf-8"; x-default="true" From: Laine Stump virsh domifannounce is a thin wrapper around the new API virDomainAnnounceInterface(). Syntax: virsh domifannounce guestname [interfacename] [parameters] where the optional interfacename can be either the MAC address of the interface to announce, or the name of the tap device used to connect the domain's interface to the real network (if the connection is with a tap device), and [parameters] is one or more of the following options: --initial [unsigned integer] --max [unsigned integer] --rounds [unsigned integer] --step [unsigned integer] For example: virsh domifannounce myguest 52:54:00:BE:EF:E1 --initial 100 virsh domifannounce other vnet2 virsh domifaanounce Signed-off-by: Laine Stump Reviewed-by: Martin Kletzander --- docs/manpages/virsh.rst | 41 +++++++++++++++++++ tools/virsh-domain.c | 88 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 129 insertions(+) diff --git a/docs/manpages/virsh.rst b/docs/manpages/virsh.rst index d1901c82c2..83ef7dd7dc 100644 --- a/docs/manpages/virsh.rst +++ b/docs/manpages/virsh.rst @@ -2321,6 +2321,47 @@ exclusive. If no flag is specified, behavior is diff= erent depending on hypervisor. =20 =20 +domifannounce +------------- + +**Syntax** + +:: + + domifannounce domain [interface-device] [parameters] + + +Request that a domain inject "gratuitous" ARP responses into the +outbound data stream of a specific network interface of the domain (or +if no interface-device is given, inject ARP responses on the outbound +data stream of all interfaces of the domain). This can be helpful to +re-sync network switches in the broadcast domain of said interfaces +when the network topology has changed. This is usually done +automatically when a domain is started, or after it has migrated (for +example, that is the behavior of QEMU), but a more complicated setup +where the topology changes around an already active domain (or +possibly all the plumbing isn't yet connected and passing traffic at +the time the automatic announcement takes place) might benefit from a +manually triggered announce. + +The optional parameters are: + +- *--initial n* + + initial delay before first announcement (milliseconds) default: 50 + +- *--max n* + + maximum delay between announcements (milliseconds) default: 550 + +- *--rounds n* + + total number of announcements default: 5 + +- *--step n* + + increment added to delay (milliseconds) after each announcement default = 50 + dominfo ------- =20 diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c index 76369e8694..d9bc3f5a4d 100644 --- a/tools/virsh-domain.c +++ b/tools/virsh-domain.c @@ -3815,6 +3815,88 @@ cmdDomIftune(vshControl *ctl, const vshCmd *cmd) goto cleanup; } =20 + +/* "domifannounce" command + */ +static const vshCmdInfo info_domifannounce =3D { + .help =3D N_("trigger domain to announce virtual interface to network"= ), + .desc =3D N_("trigger a live domain to announce one or more virtual in= terfaces to their attached networks"), + +}; + +static const vshCmdOptDef opts_domifannounce[] =3D { + VIRSH_COMMON_OPT_DOMAIN_FULL(0), + {.name =3D "interface", + .type =3D VSH_OT_STRING, + .positional =3D true, + .completer =3D virshDomainInterfaceCompleter, + .help =3D N_("interface device (MAC Address)") + }, + {.name =3D VIR_DOMAIN_ANNOUNCE_INTERFACE_INITIAL, + .type =3D VSH_OT_INT, + .help =3D N_("initial delay before first announcement (milliseconds)"= )}, + {.name =3D VIR_DOMAIN_ANNOUNCE_INTERFACE_MAX, + .type =3D VSH_OT_INT, + .help =3D N_("maximum delay between announcements (milliseconds)")}, + {.name =3D VIR_DOMAIN_ANNOUNCE_INTERFACE_ROUNDS, + .type =3D VSH_OT_INT, + .help =3D N_("total number of announcements")}, + {.name =3D VIR_DOMAIN_ANNOUNCE_INTERFACE_STEP, + .type =3D VSH_OT_INT, + .help =3D N_("increment added to delay (milliseconds) after each anno= uncement")}, + {.name =3D NULL} +}; + +static bool +cmdDomIfAnnounce(vshControl *ctl, const vshCmd *cmd) +{ + g_autoptr(virshDomain) dom =3D NULL; + const char *name =3D NULL; + const char *device =3D NULL; + virTypedParameterPtr params =3D NULL; + int nparams =3D 0; + int maxparams =3D 0; + unsigned int val; + bool ret =3D false; + int rv; + + if (!(dom =3D virshCommandOptDomain(ctl, cmd, &name))) + return false; + + if (vshCommandOptString(ctl, cmd, "interface", &device) < 0) + return false; + + if ((rv =3D vshCommandOptUInt(ctl, cmd, VIR_DOMAIN_ANNOUNCE_INTERFACE_= INITIAL, &val)) < 0) + goto cleanup; + else if (rv > 0 && virTypedParamsAddUInt(¶ms, &nparams, &maxparams= , VIR_DOMAIN_ANNOUNCE_INTERFACE_INITIAL, val) < 0) + goto cleanup; + + if ((rv =3D vshCommandOptUInt(ctl, cmd, VIR_DOMAIN_ANNOUNCE_INTERFACE_= MAX, &val)) < 0) + goto cleanup; + else if (rv > 0 && virTypedParamsAddUInt(¶ms, &nparams, &maxparams= , VIR_DOMAIN_ANNOUNCE_INTERFACE_MAX, val) < 0) + goto cleanup; + + if ((rv =3D vshCommandOptUInt(ctl, cmd, VIR_DOMAIN_ANNOUNCE_INTERFACE_= ROUNDS, &val)) < 0) + goto cleanup; + else if (rv > 0 && virTypedParamsAddUInt(¶ms, &nparams, &maxparams= , VIR_DOMAIN_ANNOUNCE_INTERFACE_ROUNDS, val) < 0) + goto cleanup; + + if ((rv =3D vshCommandOptUInt(ctl, cmd, VIR_DOMAIN_ANNOUNCE_INTERFACE_= STEP, &val)) < 0) + goto cleanup; + else if (rv > 0 && virTypedParamsAddUInt(¶ms, &nparams, &maxparams= , VIR_DOMAIN_ANNOUNCE_INTERFACE_STEP, val) < 0) + goto cleanup; + + if (virDomainAnnounceInterface(dom, device, params, nparams, 0) < 0) + goto cleanup; + + vshPrintExtra(ctl, _("Interface announcement sent for domain '%1$s'"),= name); + ret =3D true; + cleanup: + virTypedParamsFree(params, nparams); + return ret; +} + + /* * "suspend" command */ @@ -14170,6 +14252,12 @@ const vshCmdDef domManagementCmds[] =3D { .info =3D &info_domid, .flags =3D 0 }, + {.name =3D "domifannounce", + .handler =3D cmdDomIfAnnounce, + .opts =3D opts_domifannounce, + .info =3D &info_domifannounce, + .flags =3D 0 + }, {.name =3D "domif-setlink", .handler =3D cmdDomIfSetLink, .opts =3D opts_domif_setlink, --=20 2.54.0