Blame SOURCES/libvirt-qemu-setup-infrastructure-to-handle-NIC_RX_FILTER_CHANGED-event.patch

9119d9
From 5fe7a27d876a94c77d23b5e846f8af58756125c3 Mon Sep 17 00:00:00 2001
9119d9
Message-Id: <5fe7a27d876a94c77d23b5e846f8af58756125c3@dist-git>
9119d9
From: Laine Stump <laine@laine.org>
9119d9
Date: Mon, 3 Nov 2014 10:00:20 -0500
9119d9
Subject: [PATCH] qemu: setup infrastructure to handle NIC_RX_FILTER_CHANGED
9119d9
 event
9119d9
9119d9
https://bugzilla.redhat.com/show_bug.cgi?id=848199
9119d9
9119d9
NIC_RX_FILTER_CHANGED is sent by qemu any time a NIC driver in the
9119d9
guest modified the NIC's RX Filter (for example, if the MAC address of
9119d9
the NIC is changed by the guest).
9119d9
9119d9
This patch doesn't do anything useful with that event; it just sets up
9119d9
all the plumbing to get news of the event into a worker thread with
9119d9
all proper locking/reference counting, and provide an easy place to
9119d9
add in desired functionality.
9119d9
9119d9
See src/qemu/EVENTHANDLERS.txt for information/instructions on adding
9119d9
a libvirt-internal handler for a qemu event (using
9119d9
NIC_RX_FILTER_CHANGED as an example).
9119d9
9119d9
(cherry picked from commit b6bdda458ab08353dc2b664d026de6322c7db680)
9119d9
9119d9
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
9119d9
---
9119d9
 src/qemu/qemu_domain.h       |  1 +
9119d9
 src/qemu/qemu_driver.c       | 55 ++++++++++++++++++++++++++++++++++++++++++++
9119d9
 src/qemu/qemu_monitor.c      | 13 +++++++++++
9119d9
 src/qemu/qemu_monitor.h      |  7 ++++++
9119d9
 src/qemu/qemu_monitor_json.c | 17 ++++++++++++++
9119d9
 src/qemu/qemu_process.c      | 42 +++++++++++++++++++++++++++++++++
9119d9
 6 files changed, 135 insertions(+)
9119d9
9119d9
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
9119d9
index 845d3c7..ad45a66 100644
9119d9
--- a/src/qemu/qemu_domain.h
9119d9
+++ b/src/qemu/qemu_domain.h
9119d9
@@ -195,6 +195,7 @@ typedef enum {
9119d9
     QEMU_PROCESS_EVENT_WATCHDOG = 0,
9119d9
     QEMU_PROCESS_EVENT_GUESTPANIC,
9119d9
     QEMU_PROCESS_EVENT_DEVICE_DELETED,
9119d9
+    QEMU_PROCESS_EVENT_NIC_RX_FILTER_CHANGED,
9119d9
 
9119d9
     QEMU_PROCESS_EVENT_LAST
9119d9
 } qemuProcessEventType;
9119d9
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
9119d9
index c158f64..29deb76 100644
9119d9
--- a/src/qemu/qemu_driver.c
9119d9
+++ b/src/qemu/qemu_driver.c
9119d9
@@ -4147,6 +4147,58 @@ processDeviceDeletedEvent(virQEMUDriverPtr driver,
9119d9
 }
9119d9
 
9119d9
 
9119d9
+static void
9119d9
+processNicRxFilterChangedEvent(virQEMUDriverPtr driver,
9119d9
+                               virDomainObjPtr vm,
9119d9
+                               char *devAlias)
9119d9
+{
9119d9
+    virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
9119d9
+    virDomainDeviceDef dev;
9119d9
+    virDomainNetDefPtr def;
9119d9
+
9119d9
+    VIR_DEBUG("Received NIC_RX_FILTER_CHANGED event for device %s "
9119d9
+              "from domain %p %s",
9119d9
+              devAlias, vm, vm->def->name);
9119d9
+
9119d9
+    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
9119d9
+        goto cleanup;
9119d9
+
9119d9
+    if (!virDomainObjIsActive(vm)) {
9119d9
+        VIR_DEBUG("Domain is not running");
9119d9
+        goto endjob;
9119d9
+    }
9119d9
+
9119d9
+    if (virDomainDefFindDevice(vm->def, devAlias, &dev, true) < 0) {
9119d9
+        VIR_WARN("NIC_RX_FILTER_CHANGED event received for "
9119d9
+                 "non-existent device %s in domain %s",
9119d9
+                 devAlias, vm->def->name);
9119d9
+        goto endjob;
9119d9
+    }
9119d9
+    if (dev.type != VIR_DOMAIN_DEVICE_NET) {
9119d9
+        VIR_WARN("NIC_RX_FILTER_CHANGED event received for "
9119d9
+                 "non-network device %s in domain %s",
9119d9
+                 devAlias, vm->def->name);
9119d9
+        goto endjob;
9119d9
+    }
9119d9
+    def = dev.data.net;
9119d9
+
9119d9
+    /* handle the event - send query-rx-filter and respond to it. */
9119d9
+
9119d9
+    VIR_DEBUG("process NIC_RX_FILTER_CHANGED event for network "
9119d9
+              "device %s in domain %s", def->info.alias, vm->def->name);
9119d9
+
9119d9
+ endjob:
9119d9
+    /* We had an extra reference to vm before starting a new job so ending the
9119d9
+     * job is guaranteed not to remove the last reference.
9119d9
+     */
9119d9
+    ignore_value(qemuDomainObjEndJob(driver, vm));
9119d9
+
9119d9
+ cleanup:
9119d9
+    VIR_FREE(devAlias);
9119d9
+    virObjectUnref(cfg);
9119d9
+}
9119d9
+
9119d9
+
9119d9
 static void qemuProcessEventHandler(void *data, void *opaque)
9119d9
 {
9119d9
     struct qemuProcessEvent *processEvent = data;
9119d9
@@ -4167,6 +4219,9 @@ static void qemuProcessEventHandler(void *data, void *opaque)
9119d9
     case QEMU_PROCESS_EVENT_DEVICE_DELETED:
9119d9
         processDeviceDeletedEvent(driver, vm, processEvent->data);
9119d9
         break;
9119d9
+    case QEMU_PROCESS_EVENT_NIC_RX_FILTER_CHANGED:
9119d9
+        processNicRxFilterChangedEvent(driver, vm, processEvent->data);
9119d9
+        break;
9119d9
     case QEMU_PROCESS_EVENT_LAST:
9119d9
         break;
9119d9
     }
9119d9
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
9119d9
index be8d60b..b516880 100644
9119d9
--- a/src/qemu/qemu_monitor.c
9119d9
+++ b/src/qemu/qemu_monitor.c
9119d9
@@ -1391,6 +1391,19 @@ qemuMonitorEmitDeviceDeleted(qemuMonitorPtr mon,
9119d9
 }
9119d9
 
9119d9
 
9119d9
+int
9119d9
+qemuMonitorEmitNicRxFilterChanged(qemuMonitorPtr mon,
9119d9
+                                  const char *devAlias)
9119d9
+{
9119d9
+    int ret = -1;
9119d9
+    VIR_DEBUG("mon=%p", mon);
9119d9
+
9119d9
+    QEMU_MONITOR_CALLBACK(mon, ret, domainNicRxFilterChanged, mon->vm, devAlias);
9119d9
+
9119d9
+    return ret;
9119d9
+}
9119d9
+
9119d9
+
9119d9
 int qemuMonitorSetCapabilities(qemuMonitorPtr mon)
9119d9
 {
9119d9
     int ret;
9119d9
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
9119d9
index cfcaf30..69f41bf 100644
9119d9
--- a/src/qemu/qemu_monitor.h
9119d9
+++ b/src/qemu/qemu_monitor.h
9119d9
@@ -171,6 +171,10 @@ typedef int (*qemuMonitorDomainDeviceDeletedCallback)(qemuMonitorPtr mon,
9119d9
                                                       virDomainObjPtr vm,
9119d9
                                                       const char *devAlias,
9119d9
                                                       void *opaque);
9119d9
+typedef int (*qemuMonitorDomainNicRxFilterChangedCallback)(qemuMonitorPtr mon,
9119d9
+                                                           virDomainObjPtr vm,
9119d9
+                                                           const char *devAlias,
9119d9
+                                                           void *opaque);
9119d9
 
9119d9
 typedef struct _qemuMonitorCallbacks qemuMonitorCallbacks;
9119d9
 typedef qemuMonitorCallbacks *qemuMonitorCallbacksPtr;
9119d9
@@ -197,6 +201,7 @@ struct _qemuMonitorCallbacks {
9119d9
     qemuMonitorDomainPMSuspendDiskCallback domainPMSuspendDisk;
9119d9
     qemuMonitorDomainGuestPanicCallback domainGuestPanic;
9119d9
     qemuMonitorDomainDeviceDeletedCallback domainDeviceDeleted;
9119d9
+    qemuMonitorDomainNicRxFilterChangedCallback domainNicRxFilterChanged;
9119d9
 };
9119d9
 
9119d9
 char *qemuMonitorEscapeArg(const char *in);
9119d9
@@ -285,6 +290,8 @@ int qemuMonitorEmitPMSuspendDisk(qemuMonitorPtr mon);
9119d9
 int qemuMonitorEmitGuestPanic(qemuMonitorPtr mon);
9119d9
 int qemuMonitorEmitDeviceDeleted(qemuMonitorPtr mon,
9119d9
                                  const char *devAlias);
9119d9
+int qemuMonitorEmitNicRxFilterChanged(qemuMonitorPtr mon,
9119d9
+                                      const char *devAlias);
9119d9
 
9119d9
 int qemuMonitorStartCPUs(qemuMonitorPtr mon,
9119d9
                          virConnectPtr conn);
9119d9
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
9119d9
index 7a6d1e1..4fb1d81 100644
9119d9
--- a/src/qemu/qemu_monitor_json.c
9119d9
+++ b/src/qemu/qemu_monitor_json.c
9119d9
@@ -81,6 +81,7 @@ static void qemuMonitorJSONHandleBalloonChange(qemuMonitorPtr mon, virJSONValueP
9119d9
 static void qemuMonitorJSONHandlePMSuspendDisk(qemuMonitorPtr mon, virJSONValuePtr data);
9119d9
 static void qemuMonitorJSONHandleGuestPanic(qemuMonitorPtr mon, virJSONValuePtr data);
9119d9
 static void qemuMonitorJSONHandleDeviceDeleted(qemuMonitorPtr mon, virJSONValuePtr data);
9119d9
+static void qemuMonitorJSONHandleNicRxFilterChanged(qemuMonitorPtr mon, virJSONValuePtr data);
9119d9
 
9119d9
 typedef struct {
9119d9
     const char *type;
9119d9
@@ -96,6 +97,7 @@ static qemuEventHandler eventHandlers[] = {
9119d9
     { "DEVICE_DELETED", qemuMonitorJSONHandleDeviceDeleted, },
9119d9
     { "DEVICE_TRAY_MOVED", qemuMonitorJSONHandleTrayChange, },
9119d9
     { "GUEST_PANICKED", qemuMonitorJSONHandleGuestPanic, },
9119d9
+    { "NIC_RX_FILTER_CHANGED", qemuMonitorJSONHandleNicRxFilterChanged, },
9119d9
     { "POWERDOWN", qemuMonitorJSONHandlePowerdown, },
9119d9
     { "RESET", qemuMonitorJSONHandleReset, },
9119d9
     { "RESUME", qemuMonitorJSONHandleResume, },
9119d9
@@ -1021,6 +1023,21 @@ qemuMonitorJSONHandleDeviceDeleted(qemuMonitorPtr mon, virJSONValuePtr data)
9119d9
     qemuMonitorEmitDeviceDeleted(mon, device);
9119d9
 }
9119d9
 
9119d9
+
9119d9
+static void
9119d9
+qemuMonitorJSONHandleNicRxFilterChanged(qemuMonitorPtr mon, virJSONValuePtr data)
9119d9
+{
9119d9
+    const char *name;
9119d9
+
9119d9
+    if (!(name = virJSONValueObjectGetString(data, "name"))) {
9119d9
+        VIR_WARN("missing device in NIC_RX_FILTER_CHANGED event");
9119d9
+        return;
9119d9
+    }
9119d9
+
9119d9
+    qemuMonitorEmitNicRxFilterChanged(mon, name);
9119d9
+}
9119d9
+
9119d9
+
9119d9
 int
9119d9
 qemuMonitorJSONHumanCommandWithFd(qemuMonitorPtr mon,
9119d9
                                   const char *cmd_str,
9119d9
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
9119d9
index e711b5f..7101311 100644
9119d9
--- a/src/qemu/qemu_process.c
9119d9
+++ b/src/qemu/qemu_process.c
9119d9
@@ -1488,6 +1488,47 @@ qemuProcessHandleDeviceDeleted(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
9119d9
 }
9119d9
 
9119d9
 
9119d9
+static int
9119d9
+qemuProcessHandleNicRxFilterChanged(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
9119d9
+                                    virDomainObjPtr vm,
9119d9
+                                    const char *devAlias,
9119d9
+                                    void *opaque)
9119d9
+{
9119d9
+    virQEMUDriverPtr driver = opaque;
9119d9
+    struct qemuProcessEvent *processEvent = NULL;
9119d9
+    char *data;
9119d9
+
9119d9
+    virObjectLock(vm);
9119d9
+
9119d9
+    VIR_DEBUG("Device %s RX Filter changed in domain %p %s",
9119d9
+              devAlias, vm, vm->def->name);
9119d9
+
9119d9
+    if (VIR_ALLOC(processEvent) < 0)
9119d9
+        goto error;
9119d9
+
9119d9
+    processEvent->eventType = QEMU_PROCESS_EVENT_NIC_RX_FILTER_CHANGED;
9119d9
+    if (VIR_STRDUP(data, devAlias) < 0)
9119d9
+        goto error;
9119d9
+    processEvent->data = data;
9119d9
+    processEvent->vm = vm;
9119d9
+
9119d9
+    virObjectRef(vm);
9119d9
+    if (virThreadPoolSendJob(driver->workerPool, 0, processEvent) < 0) {
9119d9
+        ignore_value(virObjectUnref(vm));
9119d9
+        goto error;
9119d9
+    }
9119d9
+
9119d9
+ cleanup:
9119d9
+    virObjectUnlock(vm);
9119d9
+    return 0;
9119d9
+ error:
9119d9
+    if (processEvent)
9119d9
+        VIR_FREE(processEvent->data);
9119d9
+    VIR_FREE(processEvent);
9119d9
+    goto cleanup;
9119d9
+}
9119d9
+
9119d9
+
9119d9
 static qemuMonitorCallbacks monitorCallbacks = {
9119d9
     .eofNotify = qemuProcessHandleMonitorEOF,
9119d9
     .errorNotify = qemuProcessHandleMonitorError,
9119d9
@@ -1509,6 +1550,7 @@ static qemuMonitorCallbacks monitorCallbacks = {
9119d9
     .domainPMSuspendDisk = qemuProcessHandlePMSuspendDisk,
9119d9
     .domainGuestPanic = qemuProcessHandleGuestPanic,
9119d9
     .domainDeviceDeleted = qemuProcessHandleDeviceDeleted,
9119d9
+    .domainNicRxFilterChanged = qemuProcessHandleNicRxFilterChanged,
9119d9
 };
9119d9
 
9119d9
 static int
9119d9
-- 
9119d9
2.1.3
9119d9