Re: [PATCH 5/6] qemu: setup infrastructure to handle NIC_RX_FILTER_CHANGED event

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 09/24/2014 05:50 AM, Laine Stump wrote:
NIC_RX_FILTER_CHANGED is sent by qemu any time a NIC driver in the
guest modified the NIC's RX Filter (for example, if the MAC address of
the NIC is changed by the guest).

This patch doesn't do anything useful with that event; it just sets up
all the plumbing to get news of the event into a worker thread with
all proper locking/reference counting, and provide an easy place to
add in desired functionality.

For easy reference the next time a handler for a qemu event is
written, here is the sequence:
I assume you mean qemu_monitor_json.c
The handler in qemu_json_monitor.c calls

    qemu_json_monitor.c:qemuMonitorJSONHandleNicRxFilterChanged()

which calls

    qemu_monitor.c:qemuMonitorEmitNicRxFilterChanged()

which uses QEMU_MONITOR_CALLBACK() to call
mon->cb->domainNicRxFilterChanged(), ie:

    qemuProcessHandleNicRxFilterChanged()

which will queue an event QEMU_PROCESS_EVENT_NIC_RX_FILTER_CHANGED for
a worker thread to handle.

When the worker thread gets the event, it calls

    qemuProcessEventHandler()

which calls

    processNicRxFilterChangedEvent()

and *that* is where the actual work will be done (and any
event-specific memory allocated during qemuProcessHandleXXX() will be
freed) - it is the middle of this function where functionality behind
the event will be added in the next patch; for now there is just a
VIR_DEBUG() to log the event.
---
  src/qemu/qemu_domain.h       |  1 +
  src/qemu/qemu_driver.c       | 55 ++++++++++++++++++++++++++++++++++++++++++++
  src/qemu/qemu_monitor.c      | 13 +++++++++++
  src/qemu/qemu_monitor.h      |  7 ++++++
  src/qemu/qemu_monitor_json.c | 17 ++++++++++++++
  src/qemu/qemu_process.c      | 42 +++++++++++++++++++++++++++++++++
  6 files changed, 135 insertions(+)

diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
index 845d3c7..ad45a66 100644
--- a/src/qemu/qemu_domain.h
+++ b/src/qemu/qemu_domain.h
@@ -195,6 +195,7 @@ typedef enum {
      QEMU_PROCESS_EVENT_WATCHDOG = 0,
      QEMU_PROCESS_EVENT_GUESTPANIC,
      QEMU_PROCESS_EVENT_DEVICE_DELETED,
+    QEMU_PROCESS_EVENT_NIC_RX_FILTER_CHANGED,

      QEMU_PROCESS_EVENT_LAST
  } qemuProcessEventType;
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 543de79..64f1d45 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -4140,6 +4140,58 @@ processDeviceDeletedEvent(virQEMUDriverPtr driver,
  }


+static void
+processNicRxFilterChangedEvent(virQEMUDriverPtr driver,
+                               virDomainObjPtr vm,
+                               char *devAlias)
+{
+    virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
+    virDomainDeviceDef dev;
+    virDomainNetDefPtr def;
+
+    VIR_DEBUG("Received NIC_RX_FILTER_CHANGED event for device %s "
+              "from domain %p %s",
+              devAlias, vm, vm->def->name);
+
+    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
+        goto cleanup;
+
+    if (!virDomainObjIsActive(vm)) {
+        VIR_DEBUG("Domain is not running");
+        goto endjob;
+    }
+
+    if (virDomainDefFindDevice(vm->def, devAlias, &dev, true) < 0) {
+        VIR_WARN("NIC_RX_FILTER_CHANGED event received for "
+                 "non-existent device %s in domain %s",
+                 devAlias, vm->def->name);
+        goto endjob;
+    }
+    if (dev.type != VIR_DOMAIN_DEVICE_NET) {
+        VIR_WARN("NIC_RX_FILTER_CHANGED event received for "
+                 "non-network device %s in domain %s",
+                 devAlias, vm->def->name);
+        goto endjob;
+    }
I understand the need to check the device type, but is it necessary to log a warning message? I wonder if it may not cause unnecessary concern for someone viewing the logs. Is it possible to receive a NIC_RX_FILTER_CHANGED event for something other than a network device?
+    def = dev.data.net;
+
+    /* handle the event - send query-rx-filter and respond to it. */
+
+    VIR_DEBUG("process NIC_RX_FILTER_CHANGED event for network "
+              "device %s in domain %s", def->info.alias, vm->def->name);
+
+ endjob:
+    /* We had an extra reference to vm before starting a new job so ending the
+     * job is guaranteed not to remove the last reference.
+     */
+    ignore_value(qemuDomainObjEndJob(driver, vm));
+
+ cleanup:
+    VIR_FREE(devAlias);
+    virObjectUnref(cfg);
+}
+
+
  static void qemuProcessEventHandler(void *data, void *opaque)
  {
      struct qemuProcessEvent *processEvent = data;
@@ -4160,6 +4212,9 @@ static void qemuProcessEventHandler(void *data, void *opaque)
      case QEMU_PROCESS_EVENT_DEVICE_DELETED:
          processDeviceDeletedEvent(driver, vm, processEvent->data);
          break;
+    case QEMU_PROCESS_EVENT_NIC_RX_FILTER_CHANGED:
+        processNicRxFilterChangedEvent(driver, vm, processEvent->data);
+        break;
      case QEMU_PROCESS_EVENT_LAST:
          break;
      }
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index 48cbe3e..a4661f8 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -1387,6 +1387,19 @@ qemuMonitorEmitDeviceDeleted(qemuMonitorPtr mon,
  }


+int
+qemuMonitorEmitNicRxFilterChanged(qemuMonitorPtr mon,
+                                  const char *devAlias)
+{
+    int ret = -1;
+    VIR_DEBUG("mon=%p", mon);
+
+    QEMU_MONITOR_CALLBACK(mon, ret, domainNicRxFilterChanged, mon->vm, devAlias);
+
+    return ret;
+}
+
+
  int qemuMonitorSetCapabilities(qemuMonitorPtr mon)
  {
      int ret;
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index c37e36f..e841505 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -171,6 +171,10 @@ typedef int (*qemuMonitorDomainDeviceDeletedCallback)(qemuMonitorPtr mon,
                                                        virDomainObjPtr vm,
                                                        const char *devAlias,
                                                        void *opaque);
+typedef int (*qemuMonitorDomainNicRxFilterChangedCallback)(qemuMonitorPtr mon,
+                                                           virDomainObjPtr vm,
+                                                           const char *devAlias,
+                                                           void *opaque);

  typedef struct _qemuMonitorCallbacks qemuMonitorCallbacks;
  typedef qemuMonitorCallbacks *qemuMonitorCallbacksPtr;
@@ -197,6 +201,7 @@ struct _qemuMonitorCallbacks {
      qemuMonitorDomainPMSuspendDiskCallback domainPMSuspendDisk;
      qemuMonitorDomainGuestPanicCallback domainGuestPanic;
      qemuMonitorDomainDeviceDeletedCallback domainDeviceDeleted;
+    qemuMonitorDomainNicRxFilterChangedCallback domainNicRxFilterChanged;
  };

  char *qemuMonitorEscapeArg(const char *in);
@@ -285,6 +290,8 @@ int qemuMonitorEmitPMSuspendDisk(qemuMonitorPtr mon);
  int qemuMonitorEmitGuestPanic(qemuMonitorPtr mon);
  int qemuMonitorEmitDeviceDeleted(qemuMonitorPtr mon,
                                   const char *devAlias);
+int qemuMonitorEmitNicRxFilterChanged(qemuMonitorPtr mon,
+                                      const char *devAlias);

  int qemuMonitorStartCPUs(qemuMonitorPtr mon,
                           virConnectPtr conn);
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index 58007e6..640d96e 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -81,6 +81,7 @@ static void qemuMonitorJSONHandleBalloonChange(qemuMonitorPtr mon, virJSONValueP
  static void qemuMonitorJSONHandlePMSuspendDisk(qemuMonitorPtr mon, virJSONValuePtr data);
  static void qemuMonitorJSONHandleGuestPanic(qemuMonitorPtr mon, virJSONValuePtr data);
  static void qemuMonitorJSONHandleDeviceDeleted(qemuMonitorPtr mon, virJSONValuePtr data);
+static void qemuMonitorJSONHandleNicRxFilterChanged(qemuMonitorPtr mon, virJSONValuePtr data);

  typedef struct {
      const char *type;
@@ -96,6 +97,7 @@ static qemuEventHandler eventHandlers[] = {
      { "DEVICE_DELETED", qemuMonitorJSONHandleDeviceDeleted, },
      { "DEVICE_TRAY_MOVED", qemuMonitorJSONHandleTrayChange, },
      { "GUEST_PANICKED", qemuMonitorJSONHandleGuestPanic, },
+    { "NIC_RX_FILTER_CHANGED", qemuMonitorJSONHandleNicRxFilterChanged, },
      { "POWERDOWN", qemuMonitorJSONHandlePowerdown, },
      { "RESET", qemuMonitorJSONHandleReset, },
      { "RESUME", qemuMonitorJSONHandleResume, },
@@ -1041,6 +1043,21 @@ qemuMonitorJSONHandleDeviceDeleted(qemuMonitorPtr mon, virJSONValuePtr data)
      qemuMonitorEmitDeviceDeleted(mon, device);
  }

+
+static void
+qemuMonitorJSONHandleNicRxFilterChanged(qemuMonitorPtr mon, virJSONValuePtr data)
+{
+    const char *name;
+
+    if (!(name = virJSONValueObjectGetString(data, "name"))) {
+        VIR_WARN("missing device in NIC_RX_FILTER_CHANGED event");
+        return;
+    }
The device path is also sent with the event. It may be that data element is useless with regard to subsequent NIC_RX_FILTER_CHANGED event handling but, for my edification, I am curious as to why you ignored it.
+
+    qemuMonitorEmitNicRxFilterChanged(mon, name);
+}
+
+
  int
  qemuMonitorJSONHumanCommandWithFd(qemuMonitorPtr mon,
                                    const char *cmd_str,
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index dddca35..07f1f38 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -1489,6 +1489,47 @@ qemuProcessHandleDeviceDeleted(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
  }


+static int
+qemuProcessHandleNicRxFilterChanged(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
+                                    virDomainObjPtr vm,
+                                    const char *devAlias,
+                                    void *opaque)
+{
+    virQEMUDriverPtr driver = opaque;
+    struct qemuProcessEvent *processEvent = NULL;
+    char *data;
+
+    virObjectLock(vm);
+
+    VIR_DEBUG("Device %s RX Filter changed in domain %p %s",
+              devAlias, vm, vm->def->name);
+
+    if (VIR_ALLOC(processEvent) < 0)
+        goto error;
+
+    processEvent->eventType = QEMU_PROCESS_EVENT_NIC_RX_FILTER_CHANGED;
+    if (VIR_STRDUP(data, devAlias) < 0)
+        goto error;
+    processEvent->data = data;
+    processEvent->vm = vm;
+
+    virObjectRef(vm);
+    if (virThreadPoolSendJob(driver->workerPool, 0, processEvent) < 0) {
+        ignore_value(virObjectUnref(vm));
+        goto error;
+    }
+
+ cleanup:
+    virObjectUnlock(vm);
+    return 0;
+ error:
+    if (processEvent)
+        VIR_FREE(processEvent->data);
+    VIR_FREE(processEvent);
+    goto cleanup;
+}
+
+
  static qemuMonitorCallbacks monitorCallbacks = {
      .eofNotify = qemuProcessHandleMonitorEOF,
      .errorNotify = qemuProcessHandleMonitorError,
@@ -1510,6 +1551,7 @@ static qemuMonitorCallbacks monitorCallbacks = {
      .domainPMSuspendDisk = qemuProcessHandlePMSuspendDisk,
      .domainGuestPanic = qemuProcessHandleGuestPanic,
      .domainDeviceDeleted = qemuProcessHandleDeviceDeleted,
+    .domainNicRxFilterChanged = qemuProcessHandleNicRxFilterChanged,
  };

  static int

--
libvir-list mailing list
libvir-list@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/libvir-list




[Index of Archives]     [Virt Tools]     [Libvirt Users]     [Lib OS Info]     [Fedora Users]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [KDE Users]     [Fedora Tools]