case QEMU_PROCESS_EVENT_GUESTPANIC:
qemuMonitorEventPanicInfoFree(event->data);
break;
+ case QEMU_PROCESS_EVENT_RDMA_GID_STATUS_CHANGED:
+ qemuMonitorEventRdmaGidStatusFree(event->data);
+ break;
case QEMU_PROCESS_EVENT_WATCHDOG:
case QEMU_PROCESS_EVENT_DEVICE_DELETED:
case QEMU_PROCESS_EVENT_NIC_RX_FILTER_CHANGED:
QEMU_PROCESS_EVENT_BLOCK_JOB,
QEMU_PROCESS_EVENT_MONITOR_EOF,
QEMU_PROCESS_EVENT_PR_DISCONNECT,
+ QEMU_PROCESS_EVENT_RDMA_GID_STATUS_CHANGED,
QEMU_PROCESS_EVENT_LAST
} qemuProcessEventType;
}
+static void
+processRdmaGidStatusChangedEvent(virDomainObjPtr vm,
+ qemuMonitorRdmaGidStatusPtr info)
+{
+ unsigned int prefix_len;
+ virSocketAddr addr;
+ VIR_AUTOFREE(char *) addrStr = NULL;
+ int rc;
+
+ if (!virDomainObjIsActive(vm))
+ return;
+
+ VIR_DEBUG("netdev=%s, gid_status=%d, subnet_prefix=0x%llx, interface_id=0x%llx",
+ info->netdev, info->gid_status, info->subnet_prefix,
+ info->interface_id);
+
+ if (info->subnet_prefix) {
+ uint32_t ipv6[4] = {0};
+
+ prefix_len = 64;
+ memcpy(&ipv6[0], &info->subnet_prefix, sizeof(info->subnet_prefix));
+ memcpy(&ipv6[2], &info->interface_id, sizeof(info->interface_id));
+ virSocketAddrSetIPv6AddrNetOrder(&addr, ipv6);
+ } else {
+ prefix_len = 24;
+ virSocketAddrSetIPv4AddrNetOrder(&addr, info->interface_id >> 32);
+ }
+
+ if (!(addrStr = virSocketAddrFormat(&addr)))
+ return;
+
+ if (info->gid_status) {
+ VIR_DEBUG("Adding %s to %s", addrStr, info->netdev);
+ rc = virNetDevIPAddrAdd(info->netdev, &addr, NULL, prefix_len);
+ } else {
+ VIR_DEBUG("Removing %s from %s", addrStr, info->netdev);
+ rc = virNetDevIPAddrDel(info->netdev, &addr, prefix_len);
+ }
+
+ if (rc < 0)
+ VIR_WARN("Fail to update address %s to %s", addrStr, info->netdev);
+}
+
+
static void qemuProcessEventHandler(void *data, void *opaque)
{
struct qemuProcessEvent *processEvent = data;
case QEMU_PROCESS_EVENT_PR_DISCONNECT:
processPRDisconnectEvent(vm);
break;
+ case QEMU_PROCESS_EVENT_RDMA_GID_STATUS_CHANGED:
+ processRdmaGidStatusChangedEvent(vm, processEvent->data);
+ break;
case QEMU_PROCESS_EVENT_LAST:
break;
}
}
+int
+qemuMonitorEmitRdmaGidStatusChanged(qemuMonitorPtr mon,
+ const char *netdev,
+ bool gid_status,
+ uint64_t subnet_prefix,
+ uint64_t interface_id)
+{
+ int ret = -1;
+ VIR_DEBUG("netdev=%s, gid_status=%d, subnet_prefix=0x%lx, interface_id=0x%lx",
+ netdev, gid_status, subnet_prefix, interface_id);
+
+ QEMU_MONITOR_CALLBACK(mon, ret, domainRdmaGidStatusChanged, mon->vm,
+ netdev, gid_status, subnet_prefix, interface_id);
+
+ return ret;
+}
+
+
int
qemuMonitorSetCapabilities(qemuMonitorPtr mon)
{
}
+void
+qemuMonitorEventRdmaGidStatusFree(qemuMonitorRdmaGidStatusPtr info)
+{
+ if (!info)
+ return;
+
+ VIR_FREE(info->netdev);
+ VIR_FREE(info);
+}
+
+
int
qemuMonitorSetWatchdogAction(qemuMonitorPtr mon,
const char *action)
} data;
};
+
+typedef struct _qemuMonitorRdmaGidStatus qemuMonitorRdmaGidStatus;
+typedef qemuMonitorRdmaGidStatus *qemuMonitorRdmaGidStatusPtr;
+struct _qemuMonitorRdmaGidStatus {
+ char *netdev;
+ bool gid_status;
+ unsigned long long subnet_prefix;
+ unsigned long long interface_id;
+};
+
+
char *qemuMonitorGuestPanicEventInfoFormatMsg(qemuMonitorEventPanicInfoPtr info);
void qemuMonitorEventPanicInfoFree(qemuMonitorEventPanicInfoPtr info);
+void qemuMonitorEventRdmaGidStatusFree(qemuMonitorRdmaGidStatusPtr info);
typedef void (*qemuMonitorDestroyCallback)(qemuMonitorPtr mon,
virDomainObjPtr vm,
bool connected,
void *opaque);
+typedef int (*qemuMonitorDomainRdmaGidStatusChangedCallback)(qemuMonitorPtr mon,
+ virDomainObjPtr vm,
+ const char *netdev,
+ bool gid_status,
+ uint64_t subnet_prefix,
+ uint64_t interface_id,
+ void *opaque);
+
typedef struct _qemuMonitorCallbacks qemuMonitorCallbacks;
typedef qemuMonitorCallbacks *qemuMonitorCallbacksPtr;
struct _qemuMonitorCallbacks {
qemuMonitorDomainBlockThresholdCallback domainBlockThreshold;
qemuMonitorDomainDumpCompletedCallback domainDumpCompleted;
qemuMonitorDomainPRManagerStatusChangedCallback domainPRManagerStatusChanged;
+ qemuMonitorDomainRdmaGidStatusChangedCallback domainRdmaGidStatusChanged;
};
char *qemuMonitorEscapeArg(const char *in);
const char *prManager,
bool connected);
+int qemuMonitorEmitRdmaGidStatusChanged(qemuMonitorPtr mon, const char *netdev,
+ bool gid_status, uint64_t subnet_prefix,
+ uint64_t interface_id);
+
int qemuMonitorStartCPUs(qemuMonitorPtr mon);
int qemuMonitorStopCPUs(qemuMonitorPtr mon);
static void qemuMonitorJSONHandleBlockThreshold(qemuMonitorPtr mon, virJSONValuePtr data);
static void qemuMonitorJSONHandleDumpCompleted(qemuMonitorPtr mon, virJSONValuePtr data);
static void qemuMonitorJSONHandlePRManagerStatusChanged(qemuMonitorPtr mon, virJSONValuePtr data);
+static void qemuMonitorJSONHandleRdmaGidStatusChanged(qemuMonitorPtr mon, virJSONValuePtr data);
typedef struct {
const char *type;
{ "NIC_RX_FILTER_CHANGED", qemuMonitorJSONHandleNicRxFilterChanged, },
{ "POWERDOWN", qemuMonitorJSONHandlePowerdown, },
{ "PR_MANAGER_STATUS_CHANGED", qemuMonitorJSONHandlePRManagerStatusChanged, },
+ { "RDMA_GID_STATUS_CHANGED", qemuMonitorJSONHandleRdmaGidStatusChanged, },
{ "RESET", qemuMonitorJSONHandleReset, },
{ "RESUME", qemuMonitorJSONHandleResume, },
{ "RTC_CHANGE", qemuMonitorJSONHandleRTCChange, },
}
+static void qemuMonitorJSONHandleRdmaGidStatusChanged(qemuMonitorPtr mon,
+ virJSONValuePtr data)
+{
+ const char *netdev;
+ bool gid_status;
+ unsigned long long subnet_prefix, interface_id;
+
+ if (!(netdev = virJSONValueObjectGetString(data, "netdev"))) {
+ VIR_WARN("missing netdev in GID_STATUS_CHANGED event");
+ return;
+ }
+
+ if (virJSONValueObjectGetBoolean(data, "gid-status", &gid_status)) {
+ VIR_WARN("missing gid-status in GID_STATUS_CHANGED event");
+ return;
+ }
+
+ if (virJSONValueObjectGetNumberUlong(data, "subnet-prefix",
+ &subnet_prefix)) {
+ VIR_WARN("missing subnet-prefix in GID_STATUS_CHANGED event");
+ return;
+ }
+
+ if (virJSONValueObjectGetNumberUlong(data, "interface-id",
+ &interface_id)) {
+ VIR_WARN("missing interface-id in GID_STATUS_CHANGED event");
+ return;
+ }
+
+ qemuMonitorEmitRdmaGidStatusChanged(mon, netdev, gid_status, subnet_prefix,
+ interface_id);
+}
+
+
int
qemuMonitorJSONHumanCommandWithFd(qemuMonitorPtr mon,
const char *cmd_str,
}
+static int
+qemuProcessHandleRdmaGidStatusChanged(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
+ virDomainObjPtr vm,
+ const char *netdev,
+ bool gid_status,
+ uint64_t subnet_prefix,
+ uint64_t interface_id,
+ void *opaque)
+{
+ virQEMUDriverPtr driver = opaque;
+ struct qemuProcessEvent *processEvent = NULL;
+ qemuMonitorRdmaGidStatusPtr info = NULL;
+ int ret = -1;
+
+ virObjectLock(vm);
+
+ VIR_DEBUG("netdev=%s,gid_status=%d,subnet_prefix=0x%lx,interface_id=0x%lx",
+ netdev, gid_status, subnet_prefix, interface_id);
+
+ if (VIR_ALLOC(info) < 0 ||
+ VIR_STRDUP(info->netdev, netdev) < 0)
+ goto cleanup;
+
+ info->gid_status = gid_status;
+ info->subnet_prefix = subnet_prefix;
+ info->interface_id = interface_id;
+
+ if (VIR_ALLOC(processEvent) < 0)
+ goto cleanup;
+
+ processEvent->eventType = QEMU_PROCESS_EVENT_RDMA_GID_STATUS_CHANGED;
+ processEvent->vm = virObjectRef(vm);
+ VIR_STEAL_PTR(processEvent->data, info);
+
+ if (virThreadPoolSendJob(driver->workerPool, 0, processEvent) < 0) {
+ qemuProcessEventFree(processEvent);
+ virObjectUnref(vm);
+ goto cleanup;
+ }
+
+ ret = 0;
+ cleanup:
+ qemuMonitorEventRdmaGidStatusFree(info);
+ virObjectUnlock(vm);
+ return ret;
+}
+
+
static qemuMonitorCallbacks monitorCallbacks = {
.eofNotify = qemuProcessHandleMonitorEOF,
.errorNotify = qemuProcessHandleMonitorError,
.domainBlockThreshold = qemuProcessHandleBlockThreshold,
.domainDumpCompleted = qemuProcessHandleDumpCompleted,
.domainPRManagerStatusChanged = qemuProcessHandlePRManagerStatusChanged,
+ .domainRdmaGidStatusChanged = qemuProcessHandleRdmaGidStatusChanged,
};
static void