API: Introduce virDomainAnnounceInterface()

This API provides a way for a libvirt client to force a guest to
inject a "Gratuitous 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 forwarding traffic correctly in a more
timely manner after network topology changes.

Signed-off-by: Laine Stump <laine@redhat.com>
Reviewed-by: Martin Kletzander <mkletzan@redhat.com>
This commit is contained in:
Laine Stump committed 2026-06-08 02:31:42 -04:00
1 parent 6b2c18913f
commit 6924b73d30
7 files changed
+153 -1

No files matched your search

+46
View File
@@ -9052,5 +9052,51 @@ virDomainDelThrottleGroup(virDomainPtr dom,
const char *group,
unsigned int flags);
/**
* VIR_DOMAIN_ANNOUNCE_INTERFACE_INITIAL:
*
* Initial delay in milliseconds 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 milliseconds 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 */
+8
View File
@@ -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;
};
+65
View File
@@ -14316,3 +14316,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;
}
+5
View File
@@ -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 ....
+1
View File
@@ -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 = {
+18 -1
View File
@@ -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
};
+10
View File
@@ -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,
};