[libvirt] [PATCH v2 4/6] bandwidth: Create network (un)plug functions

Michal Privoznik mprivozn at redhat.com
Thu Jan 12 14:44:44 UTC 2012


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




More information about the libvir-list mailing list