]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
Introduce NIC_MAC_CHANGE event
authorMichal Privoznik <mprivozn@redhat.com>
Tue, 27 Jun 2023 08:13:51 +0000 (10:13 +0200)
committerMichal Privoznik <mprivozn@redhat.com>
Tue, 25 Mar 2025 10:49:30 +0000 (11:49 +0100)
The aim off this event is to notify management application that
guest changed MAC address on one of its vNICs so the app can
update its internal records, e.g. for finding match between
guest/host view of vNICs.

Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Martin Kletzander <mkletzan@redhat.com>
examples/c/misc/event-test.c
include/libvirt/libvirt-domain.h
src/conf/domain_event.c
src/conf/domain_event.h
src/libvirt_private.syms
src/remote/remote_daemon_dispatch.c
src/remote/remote_driver.c
src/remote/remote_protocol.x
src/remote_protocol-structs
tools/virsh-domain-event.c

index 88d99dff56417d54d37ace04906706f3ca4cc3a4..a61dbf4529d1283bfce3c2193c41b22787e65d98 100644 (file)
@@ -1102,6 +1102,19 @@ myNetworkEventMetadataChangeCallback(virConnectPtr conn G_GNUC_UNUSED,
 }
 
 
+static int
+myDomainEventNICMACChangeCallback(virConnectPtr conn G_GNUC_UNUSED,
+                                  virDomainPtr dom,
+                                  const char *alias,
+                                  const char *oldMAC,
+                                  const char *newMAC,
+                                  void *opaque G_GNUC_UNUSED)
+{
+    printf("%s EVENT: Domain %s(%d) NIC MAC changed: alias: '%s' oldMAC: '%s' newMAC: '%s'\n",
+           __func__, virDomainGetName(dom), virDomainGetID(dom), alias, oldMAC, newMAC);
+    return 0;
+}
+
 
 static void
 myFreeFunc(void *opaque)
@@ -1160,6 +1173,7 @@ struct domainEventData domainEvents[] = {
     DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_BLOCK_THRESHOLD, myDomainEventBlockThresholdCallback),
     DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_MEMORY_FAILURE, myDomainEventMemoryFailureCallback),
     DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_MEMORY_DEVICE_SIZE_CHANGE, myDomainEventMemoryDeviceSizeChangeCallback),
+    DOMAIN_EVENT(VIR_DOMAIN_EVENT_ID_NIC_MAC_CHANGE, myDomainEventNICMACChangeCallback),
 };
 
 struct storagePoolEventData {
index 6e11baa3d3d04902129e3a28a84ba0e5a15a74c5..9496631bccc9734a3eb6d4c9bf50eb7c6254f522 100644 (file)
@@ -6993,6 +6993,33 @@ typedef void (*virConnectDomainEventMemoryDeviceSizeChangeCallback)(virConnectPt
                                                                     void *opaque);
 
 
+/**
+ * virConnectDomainEventNICMACChangeCallback:
+ * @conn: connection object
+ * @dom: domain on which the event occurred
+ * @alias: network interface device alias
+ * @oldMAC: the old value of network interface MAC address
+ * @newMAC: the new value of network interface MAC address
+ * @opaque: application specified data
+ *
+ * The callback occurs when the guest changes MAC address on one of
+ * its virtual network interfaces, for QEMU domains this is emitted
+ * only for vNICs of model virtio. The event is not emitted for
+ * other types (e.g. PCI device passthrough).
+ *
+ * The callback signature to use when registering for an event of
+ * type VIR_DOMAIN_EVENT_ID_NIC_MAC_CHANGE with
+ * virConnectDomainEventRegisterAny().
+ *
+ * Since: 11.2.0
+ */
+typedef void (*virConnectDomainEventNICMACChangeCallback)(virConnectPtr conn,
+                                                          virDomainPtr dom,
+                                                          const char *alias,
+                                                          const char *oldMAC,
+                                                          const char *newMAC,
+                                                          void *opaque);
+
 /**
  * VIR_DOMAIN_EVENT_CALLBACK:
  *
@@ -7041,6 +7068,7 @@ typedef enum {
     VIR_DOMAIN_EVENT_ID_BLOCK_THRESHOLD = 24, /* virConnectDomainEventBlockThresholdCallback (Since: 3.2.0) */
     VIR_DOMAIN_EVENT_ID_MEMORY_FAILURE = 25,  /* virConnectDomainEventMemoryFailureCallback (Since: 6.9.0) */
     VIR_DOMAIN_EVENT_ID_MEMORY_DEVICE_SIZE_CHANGE = 26, /* virConnectDomainEventMemoryDeviceSizeChangeCallback (Since: 7.9.0) */
+    VIR_DOMAIN_EVENT_ID_NIC_MAC_CHANGE = 27, /* virConnectDomainEventNICMACChangeCallback (Since: 11.2.0) */
 
 # ifdef VIR_ENUM_SENTINELS
     VIR_DOMAIN_EVENT_ID_LAST
index 09f3368064a31753d597f99965d2ad6533e60983..88087bad4f21da1151c6631ccde675367ecd90ad 100644 (file)
@@ -57,6 +57,7 @@ static virClass *virDomainEventMetadataChangeClass;
 static virClass *virDomainEventBlockThresholdClass;
 static virClass *virDomainEventMemoryFailureClass;
 static virClass *virDomainEventMemoryDeviceSizeChangeClass;
+static virClass *virDomainEventNICMACChangeClass;
 
 static void virDomainEventDispose(void *obj);
 static void virDomainEventLifecycleDispose(void *obj);
@@ -81,6 +82,7 @@ static void virDomainEventMetadataChangeDispose(void *obj);
 static void virDomainEventBlockThresholdDispose(void *obj);
 static void virDomainEventMemoryFailureDispose(void *obj);
 static void virDomainEventMemoryDeviceSizeChangeDispose(void *obj);
+static void virDomainEventNICMACChangeDispose(void *obj);
 
 static void
 virDomainEventDispatchDefaultFunc(virConnectPtr conn,
@@ -285,6 +287,15 @@ struct _virDomainEventMemoryDeviceSizeChange {
 };
 typedef struct _virDomainEventMemoryDeviceSizeChange virDomainEventMemoryDeviceSizeChange;
 
+struct _virDomainEventNICMACChange {
+    virDomainEvent parent;
+
+    char *alias;
+    char *oldMAC;
+    char *newMAC;
+};
+typedef struct _virDomainEventNICMACChange virDomainEventNICMACChange;
+
 static int
 virDomainEventsOnceInit(void)
 {
@@ -334,6 +345,8 @@ virDomainEventsOnceInit(void)
         return -1;
     if (!VIR_CLASS_NEW(virDomainEventMemoryDeviceSizeChange, virDomainEventClass))
         return -1;
+    if (!VIR_CLASS_NEW(virDomainEventNICMACChange, virDomainEventClass))
+        return -1;
     return 0;
 }
 
@@ -559,6 +572,16 @@ virDomainEventMemoryDeviceSizeChangeDispose(void *obj)
     g_free(event->alias);
 }
 
+static void
+virDomainEventNICMACChangeDispose(void *obj)
+{
+    virDomainEventNICMACChange *event = obj;
+
+    g_free(event->alias);
+    g_free(event->oldMAC);
+    g_free(event->newMAC);
+}
+
 static void *
 virDomainEventNew(virClass *klass,
                   int eventID,
@@ -1733,6 +1756,62 @@ virDomainEventMemoryDeviceSizeChangeNewFromDom(virDomainPtr dom,
 }
 
 
+static virObjectEvent *
+virDomainEventNICMACChangeNew(int id,
+                              const char *name,
+                              unsigned char *uuid,
+                              const char *alias,
+                              const char *oldMAC,
+                              const char *newMAC)
+
+{
+    virDomainEventNICMACChange *ev;
+
+    if (virDomainEventsInitialize() < 0)
+        return NULL;
+
+    if (!(ev = virDomainEventNew(virDomainEventNICMACChangeClass,
+                                 VIR_DOMAIN_EVENT_ID_NIC_MAC_CHANGE,
+                                 id, name, uuid)))
+        return NULL;
+
+    ev->alias = g_strdup(alias);
+    ev->oldMAC = g_strdup(oldMAC);
+    ev->newMAC = g_strdup(newMAC);
+
+    return (virObjectEvent *)ev;
+}
+
+
+virObjectEvent *
+virDomainEventNICMACChangeNewFromObj(virDomainObj *obj,
+                                     const char *alias,
+                                     const char *oldMAC,
+                                     const char *newMAC)
+{
+    return virDomainEventNICMACChangeNew(obj->def->id,
+                                         obj->def->name,
+                                         obj->def->uuid,
+                                         alias,
+                                         oldMAC,
+                                         newMAC);
+}
+
+virObjectEvent *
+virDomainEventNICMACChangeNewFromDom(virDomainPtr dom,
+                                     const char *alias,
+                                     const char *oldMAC,
+                                     const char *newMAC)
+{
+    return virDomainEventNICMACChangeNew(dom->id,
+                                         dom->name,
+                                         dom->uuid,
+                                         alias,
+                                         oldMAC,
+                                         newMAC);
+
+}
+
 static void
 virDomainEventDispatchDefaultFunc(virConnectPtr conn,
                                   virObjectEvent *event,
@@ -2041,6 +2120,20 @@ virDomainEventDispatchDefaultFunc(virConnectPtr conn,
             goto cleanup;
         }
 
+    case VIR_DOMAIN_EVENT_ID_NIC_MAC_CHANGE:
+        {
+            virDomainEventNICMACChange *nicMacChangeEvent;
+
+            nicMacChangeEvent = (virDomainEventNICMACChange *)event;
+            ((virConnectDomainEventNICMACChangeCallback)cb)(conn, dom,
+                                                            nicMacChangeEvent->alias,
+                                                            nicMacChangeEvent->oldMAC,
+                                                            nicMacChangeEvent->newMAC,
+                                                            cbopaque);
+
+            goto cleanup;
+        }
+
     case VIR_DOMAIN_EVENT_ID_LAST:
         break;
     }
index f4016dc1e9e9bcb9490ee4bb53fb327e7260144a..f31cfb9e42ad1eebe068973a60c09eaadb04aab4 100644 (file)
@@ -277,6 +277,18 @@ virDomainEventMemoryDeviceSizeChangeNewFromDom(virDomainPtr dom,
                                                const char *alias,
                                                unsigned long long size);
 
+virObjectEvent *
+virDomainEventNICMACChangeNewFromObj(virDomainObj *obj,
+                                     const char *alias,
+                                     const char *oldMAC,
+                                     const char *newMAC);
+
+virObjectEvent *
+virDomainEventNICMACChangeNewFromDom(virDomainPtr dom,
+                                     const char *alias,
+                                     const char *oldMAC,
+                                     const char *newMAC);
+
 int
 virDomainEventStateRegister(virConnectPtr conn,
                             virObjectEventState *state,
index f20ef34bca577d798cbcae9ae77a5571884d83c3..812fa4e43519f71b8a8cd75ff41723ee0b5da82d 100644 (file)
@@ -779,6 +779,8 @@ virDomainEventMetadataChangeNewFromDom;
 virDomainEventMetadataChangeNewFromObj;
 virDomainEventMigrationIterationNewFromDom;
 virDomainEventMigrationIterationNewFromObj;
+virDomainEventNICMACChangeNewFromDom;
+virDomainEventNICMACChangeNewFromObj;
 virDomainEventPMSuspendDiskNewFromDom;
 virDomainEventPMSuspendDiskNewFromObj;
 virDomainEventPMSuspendNewFromDom;
index e812f5c3e94d4cbb87c11472e7e5a5de889a45c5..5dfed7ceefe6daf4079d66a610ebb308dc7ce505 100644 (file)
@@ -1323,6 +1323,37 @@ remoteRelayDomainEventMemoryDeviceSizeChange(virConnectPtr conn,
 }
 
 
+static int
+remoteRelayDomainEventNICMACChange(virConnectPtr conn,
+                                   virDomainPtr dom,
+                                   const char *alias,
+                                   const char *oldMAC,
+                                   const char *newMAC,
+                                   void *opaque)
+{
+    daemonClientEventCallback *callback = opaque;
+    remote_domain_event_nic_mac_change_msg data;
+
+    if (callback->callbackID < 0 ||
+        !remoteRelayDomainEventCheckACL(callback->client, conn, dom))
+        return -1;
+
+    /* build return data */
+    memset(&data, 0, sizeof(data));
+    data.callbackID = callback->callbackID;
+    data.alias = g_strdup(alias);
+    data.oldMAC = g_strdup(oldMAC);
+    data.newMAC = g_strdup(newMAC);
+    make_nonnull_domain(&data.dom, dom);
+
+    remoteDispatchObjectEventSend(callback->client, remoteProgram,
+                                  REMOTE_PROC_DOMAIN_EVENT_NIC_MAC_CHANGE,
+                                  (xdrproc_t)xdr_remote_domain_event_nic_mac_change_msg,
+                                  &data);
+    return 0;
+}
+
+
 static virConnectDomainEventGenericCallback domainEventCallbacks[] = {
     VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventLifecycle),
     VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventReboot),
@@ -1351,6 +1382,7 @@ static virConnectDomainEventGenericCallback domainEventCallbacks[] = {
     VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventBlockThreshold),
     VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventMemoryFailure),
     VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventMemoryDeviceSizeChange),
+    VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventNICMACChange),
 };
 
 G_STATIC_ASSERT(G_N_ELEMENTS(domainEventCallbacks) == VIR_DOMAIN_EVENT_ID_LAST);
index 7d9f5421bf18516ccaeab2a8437b42ab22bab2d2..745cd34f83f7b8c41712dae8812bb8b5cdfa5938 100644 (file)
@@ -432,6 +432,11 @@ remoteConnectNotifyEventConnectionClosed(virNetClientProgram *prog G_GNUC_UNUSED
                                          virNetClient *client G_GNUC_UNUSED,
                                          void *evdata, void *opaque);
 
+static void
+remoteDomainBuildEventNICMACChange(virNetClientProgram *prog,
+                                   virNetClient *client,
+                                   void *evdata, void *opaque);
+
 static virNetClientProgramEvent remoteEvents[] = {
     { REMOTE_PROC_DOMAIN_EVENT_LIFECYCLE,
       remoteDomainBuildEventLifecycle,
@@ -650,6 +655,10 @@ static virNetClientProgramEvent remoteEvents[] = {
       remoteDomainBuildEventMemoryDeviceSizeChange,
       sizeof(remote_domain_event_memory_device_size_change_msg),
       (xdrproc_t)xdr_remote_domain_event_memory_device_size_change_msg },
+    { REMOTE_PROC_DOMAIN_EVENT_NIC_MAC_CHANGE,
+      remoteDomainBuildEventNICMACChange,
+      sizeof(remote_domain_event_nic_mac_change_msg),
+      (xdrproc_t)xdr_remote_domain_event_nic_mac_change_msg },
 };
 
 static void
@@ -5068,6 +5077,31 @@ remoteDomainBuildEventMemoryDeviceSizeChange(virNetClientProgram *prog G_GNUC_UN
 }
 
 
+static void
+remoteDomainBuildEventNICMACChange(virNetClientProgram *prog G_GNUC_UNUSED,
+                                   virNetClient *client G_GNUC_UNUSED,
+                                   void *evdata, void *opaque)
+{
+    virConnectPtr conn = opaque;
+    remote_domain_event_nic_mac_change_msg *msg = evdata;
+    struct private_data *priv = conn->privateData;
+    virDomainPtr dom;
+    virObjectEvent *event = NULL;
+
+    if (!(dom = get_nonnull_domain(conn, msg->dom)))
+        return;
+
+    event = virDomainEventNICMACChangeNewFromDom(dom,
+                                                 msg->alias,
+                                                 msg->oldMAC,
+                                                 msg->newMAC);
+
+    virObjectUnref(dom);
+
+    virObjectEventStateQueueRemote(priv->eventState, event, msg->callbackID);
+}
+
+
 static int
 remoteStreamSend(virStreamPtr st,
                  const char *data,
index d6bdc75d03cc4ab93490cf32c201c15a51ea79cb..57cd5796af5773bc5877c9cefc4dbe429ae4d339 100644 (file)
@@ -4000,6 +4000,14 @@ struct remote_domain_set_autostart_once_args {
     int autostart;
 };
 
+struct remote_domain_event_nic_mac_change_msg {
+    int callbackID;
+    remote_nonnull_domain dom;
+    remote_nonnull_string alias;
+    remote_nonnull_string oldMAC;
+    remote_nonnull_string newMAC;
+};
+
 /*----- Protocol. -----*/
 
 /* Define the program number, protocol version and procedure numbers here. */
@@ -7105,5 +7113,11 @@ enum remote_procedure {
      * @acl: domain:save:!VIR_DOMAIN_AFFECT_CONFIG|VIR_DOMAIN_AFFECT_LIVE
      * @acl: domain:save:VIR_DOMAIN_AFFECT_CONFIG
      */
-    REMOTE_PROC_DOMAIN_DEL_THROTTLE_GROUP = 452
+    REMOTE_PROC_DOMAIN_DEL_THROTTLE_GROUP = 452,
+
+    /**
+     * @generate: both
+     * @acl: none
+     */
+    REMOTE_PROC_DOMAIN_EVENT_NIC_MAC_CHANGE = 453
 };
index 8acc5475c206470acc24fbe1373dcdedc10e4911..dd612b4dc67fc36810b4e22c6e74d8380967aabf 100644 (file)
@@ -3330,6 +3330,13 @@ struct remote_domain_set_autostart_once_args {
         remote_nonnull_domain      dom;
         int                        autostart;
 };
+struct remote_domain_event_nic_mac_change_msg {
+        int                        callbackID;
+        remote_nonnull_domain      dom;
+        remote_nonnull_string      alias;
+        remote_nonnull_string      oldMAC;
+        remote_nonnull_string      newMAC;
+};
 enum remote_procedure {
         REMOTE_PROC_CONNECT_OPEN = 1,
         REMOTE_PROC_CONNECT_CLOSE = 2,
@@ -3783,4 +3790,5 @@ enum remote_procedure {
         REMOTE_PROC_DOMAIN_SET_AUTOSTART_ONCE = 450,
         REMOTE_PROC_DOMAIN_SET_THROTTLE_GROUP = 451,
         REMOTE_PROC_DOMAIN_DEL_THROTTLE_GROUP = 452,
+        REMOTE_PROC_DOMAIN_EVENT_NIC_MAC_CHANGE = 453,
 };
index cd33d4d93839a40b91b94dde4a69e9cd60078397..69a68d857d8bd775c48c4c8569e2c81f13f827de 100644 (file)
@@ -783,6 +783,24 @@ virshEventMemoryDeviceSizeChangePrint(virConnectPtr conn G_GNUC_UNUSED,
 }
 
 
+static void
+virshEventNICMACChangePrint(virConnectPtr conn G_GNUC_UNUSED,
+                            virDomainPtr dom,
+                            const char *alias,
+                            const char *oldMAC,
+                            const char *newMAC,
+                            void *opaque)
+{
+    g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
+
+    virBufferAsprintf(&buf,
+                      _("event 'nic-mac-change' for domain '%1$s':\nalias: %2$s\noldMAC: %3$s\nnewMAC: %4$s\n"),
+                      virDomainGetName(dom), alias, oldMAC, newMAC);
+
+    virshEventPrint(opaque, &buf);
+}
+
+
 virshDomainEventCallback virshDomainEventCallbacks[] = {
     { "lifecycle",
       VIR_DOMAIN_EVENT_CALLBACK(virshEventLifecyclePrint), },
@@ -836,6 +854,8 @@ virshDomainEventCallback virshDomainEventCallbacks[] = {
       VIR_DOMAIN_EVENT_CALLBACK(virshEventMemoryFailurePrint), },
     { "memory-device-size-change",
       VIR_DOMAIN_EVENT_CALLBACK(virshEventMemoryDeviceSizeChangePrint), },
+    { "nic-mac-change",
+      VIR_DOMAIN_EVENT_CALLBACK(virshEventNICMACChangePrint), },
 };
 G_STATIC_ASSERT(VIR_DOMAIN_EVENT_ID_LAST == G_N_ELEMENTS(virshDomainEventCallbacks));