Network should be notified if we plug in or unplug an interface, so it can perform some action, e.g. set/unset network part of QoS. --- src/conf/domain_conf.h | 1 + src/conf/network_conf.c | 1 + src/conf/network_conf.h | 2 + src/libvirt_network.syms | 2 + src/network/bridge_driver.c | 72 +++++++++++++++++++++++++++++++++++++++++++ src/network/bridge_driver.h | 7 ++++ src/qemu/qemu_command.c | 17 +++++++--- src/qemu/qemu_process.c | 12 +++++++ 8 files changed, 109 insertions(+), 5 deletions(-) diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 3d5d4f8..09f7cea 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -620,6 +620,7 @@ struct _virDomainNetDef { virNWFilterHashTablePtr filterparams; virNetDevBandwidthPtr bandwidth; int linkstate; + unsigned int class_id; /* ID for bandwidth internal classes */ }; /* Used for prefix of ifname of any network name generated dynamically diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c index 5d900eb..019cdc7 100644 --- a/src/conf/network_conf.c +++ b/src/conf/network_conf.c @@ -244,6 +244,7 @@ virNetworkObjPtr virNetworkAssignDef(virNetworkObjListPtr nets, } virNetworkObjLock(network); network->def = def; + network->class_id = 3; if (VIR_REALLOC_N(nets->objs, nets->count + 1) < 0) { virReportOOMError(); diff --git a/src/conf/network_conf.h b/src/conf/network_conf.h index 5cb396c..dcbf84d 100644 --- a/src/conf/network_conf.h +++ b/src/conf/network_conf.h @@ -189,6 +189,8 @@ struct _virNetworkObj { unsigned int active : 1; unsigned int autostart : 1; unsigned int persistent : 1; + unsigned int class_id; /* IDs for QoS, not to be confused with + IDs domains have */ virNetworkDefPtr def; /* The current definition */ virNetworkDefPtr newDef; /* New definition to activate at shutdown */ diff --git a/src/libvirt_network.syms b/src/libvirt_network.syms index 1fe8902..4c1cb8b 100644 --- a/src/libvirt_network.syms +++ b/src/libvirt_network.syms @@ -7,4 +7,6 @@ networkAllocateActualDevice; networkBuildDhcpDaemonCommandLine; networkGetNetworkAddress; networkNotifyActualDevice; +networkNotifyPlug; +networkNotifyUnplug; networkReleaseActualDevice; diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c index 057c955..4cea7c2 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -3263,3 +3263,75 @@ cleanup: virNetworkObjUnlock(network); return ret; } + +int +networkNotifyPlug(virNetworkPtr net, + virDomainNetDefPtr iface) +{ + struct network_driver *driver = net->conn->networkPrivateData; + virNetworkObjPtr network; + int ret = -1; + int plug_ret; + + networkDriverLock(driver); + network = virNetworkFindByUUID(&driver->networks, net->uuid); + networkDriverUnlock(driver); + + if (!network) { + networkReportError(VIR_ERR_NO_NETWORK, + "%s", _("no network with matching uuid")); + goto cleanup; + } + + plug_ret = virNetDevBandwidthPlug(network->def->bridge, + network->def->bandwidth, + iface->ifname, + iface->mac, + iface->bandwidth, + network->class_id); + if (plug_ret < 0) { + ignore_value(virNetDevBandwidthUnplug(network->def->bridge, + network->class_id)); + goto cleanup; + } else if (plug_ret == 0) { + /* QoS was set, generate next ID */ + iface->class_id = network->class_id; + network->class_id++; + } + + ret = 0; + +cleanup: + if (network) + virNetworkObjUnlock(network); + return ret; +} + +int networkNotifyUnplug(virDomainNetDefPtr iface) +{ + struct network_driver *driver = driverState; + virNetworkObjPtr network; + int ret = -1; + + if (!iface->class_id) { + /* nothing to unplug */ + return 0; + } + + networkDriverLock(driver); + network = virNetworkFindByName(&driver->networks, iface->data.network.name); + networkDriverUnlock(driver); + + if (!network) { + networkReportError(VIR_ERR_NO_NETWORK, + "%s", _("no network with matching uuid")); + goto cleanup; + } + + ret = virNetDevBandwidthUnplug(network->def->bridge, iface->class_id); + +cleanup: + if (network) + virNetworkObjUnlock(network); + return ret; +} diff --git a/src/network/bridge_driver.h b/src/network/bridge_driver.h index 4913126..f1e5abe 100644 --- a/src/network/bridge_driver.h +++ b/src/network/bridge_driver.h @@ -64,4 +64,11 @@ typedef char *(*networkDnsmasqLeaseFileNameFunc)(const char *netname); /* this allows the testsuite to replace the lease filename resolver function */ extern networkDnsmasqLeaseFileNameFunc networkDnsmasqLeaseFileName; +int +networkNotifyPlug(virNetworkPtr net, + virDomainNetDefPtr iface) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); + +int networkNotifyUnplug(virDomainNetDefPtr iface) + ATTRIBUTE_NONNULL(1); #endif /* __VIR_NETWORK__DRIVER_H */ diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 22cebe6..542a246 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -182,12 +182,12 @@ qemuNetworkIfaceConnect(virDomainDefPtr def, bool template_ifname = false; unsigned char tapmac[VIR_MAC_BUFLEN]; int actualType = virDomainNetGetActualType(net); + virNetworkPtr network = NULL; if (actualType == VIR_DOMAIN_NET_TYPE_NETWORK) { int active, fail = 0; virErrorPtr errobj; - virNetworkPtr network = virNetworkLookupByName(conn, - net->data.network.name); + network = virNetworkLookupByName(conn, net->data.network.name); if (!network) return -1; @@ -209,12 +209,13 @@ qemuNetworkIfaceConnect(virDomainDefPtr def, /* Make sure any above failure is preserved */ errobj = virSaveLastError(); - virNetworkFree(network); virSetError(errobj); virFreeError(errobj); - if (fail) + if (fail) { + virNetworkFree(network); return -1; + } } else if (actualType == VIR_DOMAIN_NET_TYPE_BRIDGE) { if (!(brname = strdup(virDomainNetGetActualBridgeName(net)))) { @@ -274,6 +275,12 @@ qemuNetworkIfaceConnect(virDomainDefPtr def, goto cleanup; } + if (tapfd >= 0 && network && + networkNotifyPlug(network, net) < 0) { + VIR_FORCE_CLOSE(tapfd); + goto cleanup; + } + if (tapfd >= 0) { if ((net->filter) && (net->ifname)) { if (virDomainConfNWFilterInstantiate(conn, def->uuid, net) < 0) @@ -283,7 +290,7 @@ qemuNetworkIfaceConnect(virDomainDefPtr def, cleanup: VIR_FREE(brname); - + virNetworkFree(network); return tapfd; } diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index e16ca07..a04b4de 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -3460,6 +3460,18 @@ void qemuProcessStop(struct qemud_driver *driver, } } + for ( i = 0; i < vm->def->nnets; i++) { + virDomainNetDefPtr net = vm->def->nets[i]; + + if (virDomainNetGetActualType(net) != VIR_DOMAIN_NET_TYPE_NETWORK) + continue; + + if (networkNotifyUnplug(net) < 0) { + VIR_WARN("Unable to remove QoS settings for interface '%s'", + net->ifname); + } + } + if (priv->mon) qemuMonitorClose(priv->mon); -- 1.7.3.4 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list