From: Laine Stump <[email protected]>

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 <[email protected]>
---
 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-domain.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);
 
+/**
+ * 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);
 
 #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);
 
+typedef int
+(*virDrvDomainAnnounceInterface)(virDomainPtr dom,
+                                 const char *device,
+                                 virTypedParameterPtr params,
+                                 int nparams,
+                                 unsigned int flags);
+
 typedef struct _virHypervisorDriver virHypervisorDriver;
 
 /**
@@ -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 
interfaces
+ * @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=%p, device='%s' params=%p nparams=%d flags=0x%x",
+              dom, NULLSTR(device), params, nparams, flags);
+    VIR_TYPED_PARAMS_DEBUG(params, nparams);
+
+    virResetLastError();
+
+    virCheckDomainReturn(dom, -1);
+
+    conn = dom->conn;
+
+    virCheckReadOnlyGoto(conn->flags, error);
+    if (nparams != 0)
+        virCheckNonNullArgGoto(params, error);
+    else
+        virCheckNullArgGoto(params, error);
+
+    if (virTypedParameterValidateSet(conn, params, nparams) < 0)
+        goto error;
+
+    if (conn->driver->domainAnnounceInterface) {
+        int ret = conn->driver->domainAnnounceInterface(dom, device, params, 
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;
 
+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 = {
     .domainGraphicsReload = remoteDomainGraphicsReload, /* 10.2.0 */
     .domainSetThrottleGroup = remoteDomainSetThrottleGroup, /* 11.2.0 */
     .domainDelThrottleGroup = remoteDomainDelThrottleGroup, /* 11.2.0 */
+    .domainAnnounceInterface = remoteDomainAnnounceInterface, /* 12.5.0 */
 };
 
 static virNetworkDriver network_driver = {
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 = 2048;
 /* Upper limit on number of messages */
 const REMOTE_DOMAIN_MESSAGES_MAX = 2048;
 
+/*
+ * Upper limit on number of domain announce interface parameters
+ */
+const REMOTE_DOMAIN_ANNOUNCE_INTERFACE_PARAMS_MAX = 16;
 
 /* 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_lifecycle_msg {
     int reason;
 };
 
+struct remote_domain_announce_interface_args {
+    remote_nonnull_domain dom;
+    remote_string device;
+    remote_typed_param params<REMOTE_DOMAIN_ANNOUNCE_INTERFACE_PARAMS_MAX>;
+    unsigned int flags;
+};
+
 /*----- Protocol. -----*/
 
 /* 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 = 455
+    REMOTE_PROC_DOMAIN_EVENT_CALLBACK_CHANNEL_LIFECYCLE = 455,
+
+    /**
+     * @generate: both
+     * @acl: domain:write
+     */
+    REMOTE_PROC_DOMAIN_ANNOUNCE_INTERFACE = 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_lifecycle_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 = 1,
         REMOTE_PROC_CONNECT_CLOSE = 2,
@@ -3805,4 +3814,5 @@ enum remote_procedure {
         REMOTE_PROC_DOMAIN_EVENT_NIC_MAC_CHANGE = 453,
         REMOTE_PROC_DOMAIN_EVENT_VCPU_REMOVED = 454,
         REMOTE_PROC_DOMAIN_EVENT_CALLBACK_CHANNEL_LIFECYCLE = 455,
+        REMOTE_PROC_DOMAIN_ANNOUNCE_INTERFACE = 456,
 };
-- 
2.54.0

Reply via email to