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