diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index 845d3c7c3ad0dc74d26dc15e833a5880883709e7..ad45a663f2ed7a4167a2f29f00d95b6b5561a8f5 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 925d2b1f2a2a97285283354ebf6016e23efa891f..ecce957f5a3adeb5cf17ccd667a05db8d1b510f1 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -4146,6 +4146,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; + } + 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; @@ -4166,6 +4218,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 307d024dfb76e70075366331f925f2fb6b0ce32a..5dff9ffcf0cb9fead495382d6742294aca910251 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 596468b9861fcb70701c2862d75b2f58774847cd..fd145a77d6919a59ab3029c0fc47cbf2a2a2d858 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 f3d5d7a875cbfa271e4cac7d8225012d61b70e66..7f23aae6a0aaec647b1b4f523bb9c52dcf2aebd8 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, }, @@ -1037,6 +1039,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; + } + + 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 712a25e0222c7b854a83136b279d4ffab65e2586..95548aa24256fbeeee80fa13bcdb9808bf4763d4 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