[libvirt] [PATCH] qemu: allow to control host side link status of network device

Vasiliy Tolstov v.tolstov at selfip.ru
Mon May 15 22:15:59 UTC 2017


Signed-off-by: Vasiliy Tolstov <v.tolstov at selfip.ru>
---
 docs/formatdomain.html.in     | 21 +++++++++++++++++++++
 docs/schemas/domaincommon.rng | 11 +++++++++++
 src/conf/domain_conf.c        | 28 ++++++++++++++++++++++++++++
 src/conf/domain_conf.h        |  1 +
 src/qemu/qemu_hotplug.c       | 17 +++++++++++++++++
 src/qemu/qemu_interface.c     |  8 ++++----
 6 files changed, 82 insertions(+), 4 deletions(-)

diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 8c884f4af9cb..dd8e6a4afa99 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -5421,6 +5421,27 @@ qemu-kvm -net nic,model=? /dev/null
       <span class="since">Since 0.9.5</span>
     </p>
 
+    <h5><a name="elementHostLink">Modifying phisical link state</a></h5>
+<pre>
+...
+<devices>
+  <interface type='ethernet'>
+    <source>
+    <b><link state='down'/></b>
+    <target dev='vnet0'/>
+  </interface>
+</devices>
+...</pre>
+
+    <p>
+      This element provides means of setting state of the phisical network interface.
+      Possible values for attribute <code>state</code> are <code>up</code> and
+      <code>down</code>. If <code>down</code> is specified as the value, the interface
+      put in down state. Default behavior if this element is unspecified is to have the
+      link state <code>up</code>.
+      <span class="since">Since 3.3.2</span>
+    </p>
+
     <h5><a name="mtu">MTU configuration</a></h5>
 <pre>
 ...
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 281309ec09da..89213d63b6e9 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -2798,6 +2798,17 @@
       All ip-related info for either the host or guest side of an interface
   -->
   <define name="interface-ip-info">
+    <optional>
+      <element name="link">
+        <attribute name="state">
+          <choice>
+            <value>up</value>
+            <value>down</value>
+          </choice>
+        </attribute>
+        <empty/>
+      </element>
+    </optional>
     <zeroOrMore>
       <element name="ip">
         <attribute name="address">
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 0ff216e3a373..b7398276af57 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -9606,6 +9606,7 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
     char *devaddr = NULL;
     char *mode = NULL;
     char *linkstate = NULL;
+    char *hostlinkstate = NULL;
     char *addrtype = NULL;
     char *domain_name = NULL;
     char *vhostuser_mode = NULL;
@@ -9654,6 +9655,10 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
                 if (virDomainNetIPInfoParseXML(_("interface host IP"),
                                                ctxt, &def->hostIP) < 0)
                     goto error;
+
+                if (!hostlinkstate)
+                       hostlinkstate = virXPathString("string(./link/@state)", ctxt);
+
                 ctxt->node = tmpnode;
             }
             if (!macaddr && xmlStrEqual(cur->name, BAD_CAST "mac")) {
@@ -10303,6 +10308,16 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
         }
     }
 
+    def->hostlinkstate = VIR_DOMAIN_NET_INTERFACE_LINK_STATE_DEFAULT;
+    if (hostlinkstate != NULL) {
+        if ((def->hostlinkstate = virDomainNetInterfaceLinkStateTypeFromString(hostlinkstate)) <= 0) {
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                           _("unknown interface link state '%s'"),
+                           hostlinkstate);
+            goto error;
+        }
+    }
+
     if (filter != NULL) {
         switch (def->type) {
         case VIR_DOMAIN_NET_TYPE_ETHERNET:
@@ -10371,6 +10386,7 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
     VIR_FREE(devaddr);
     VIR_FREE(mode);
     VIR_FREE(linkstate);
+    VIR_FREE(hostlinkstate);
     VIR_FREE(addrtype);
     VIR_FREE(domain_name);
     VIR_FREE(trustGuestRxFilters);
@@ -22113,6 +22129,18 @@ virDomainNetDefFormat(virBufferPtr buf,
             break;
         }
 
+        if (def->hostlinkstate) {
+            if (sourceLines == 0) {
+                virBufferAddLit(buf, "<source>\n");
+                sourceLines += 2;
+            }
+            virBufferAdjustIndent(buf, 2);
+            virBufferAsprintf(buf, "<link state='%s'/>\n",
+                    virDomainNetInterfaceLinkStateTypeToString(def->hostlinkstate));
+            virBufferAdjustIndent(buf, -2);
+            sourceLines += 2;
+        }
+
         /* if sourceLines == 0 - no <source> info at all so far
          *    sourceLines == 1 - first line written, no terminating ">"
          *    sourceLines > 1 - multiple lines, including subelements
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 09fb7aada4b2..71e12a30c2c1 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -1037,6 +1037,7 @@ struct _virDomainNetDef {
     virNetDevVlan vlan;
     int trustGuestRxFilters; /* enum virTristateBool */
     int linkstate;
+    int hostlinkstate;
     unsigned int mtu;
     virNetDevCoalescePtr coalesce;
 };
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index e8d29186eb32..7fc41b28d9f8 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -2978,6 +2978,7 @@ qemuDomainChangeNet(virQEMUDriverPtr driver,
     bool needBridgeChange = false;
     bool needFilterChange = false;
     bool needLinkStateChange = false;
+    bool needHostLinkStateChange = false;
     bool needReplaceDevDef = false;
     bool needBandwidthSet = false;
     int ret = -1;
@@ -3264,6 +3265,9 @@ qemuDomainChangeNet(virQEMUDriverPtr driver,
     if (olddev->linkstate != newdev->linkstate)
         needLinkStateChange = true;
 
+    if (olddev->hostlinkstate != newdev->hostlinkstate)
+        needHostLinkStateChange = true;
+
     if (!virNetDevBandwidthEqual(virDomainNetGetActualBandwidth(olddev),
                                  virDomainNetGetActualBandwidth(newdev)))
         needBandwidthSet = true;
@@ -3308,6 +3312,19 @@ qemuDomainChangeNet(virQEMUDriverPtr driver,
         goto cleanup;
     }
 
+    if (needHostLinkStateChange) {
+        if (newdev->hostlinkstate == VIR_DOMAIN_NET_INTERFACE_LINK_STATE_DOWN) {
+            if (virNetDevSetOnline(newdev->ifname, false) < 0)
+                goto cleanup;
+        } else {
+            if (virNetDevSetOnline(newdev->ifname, true) < 0)
+                goto cleanup;
+            if (virNetDevIPInfoAddToDev(newdev->ifname, &newdev->hostIP) < 0)
+                goto cleanup;
+        }
+        needReplaceDevDef = true;
+    }
+
     if (needReplaceDevDef) {
         /* the changes above warrant replacing olddev with newdev in
          * the domain's nets list.
diff --git a/src/qemu/qemu_interface.c b/src/qemu/qemu_interface.c
index d8a678b4ab13..f3afbdae4009 100644
--- a/src/qemu/qemu_interface.c
+++ b/src/qemu/qemu_interface.c
@@ -413,7 +413,7 @@ qemuInterfaceEthernetConnect(virDomainDefPtr def,
 {
     virMacAddr tapmac;
     int ret = -1;
-    unsigned int tap_create_flags = VIR_NETDEV_TAP_CREATE_IFUP;
+    unsigned int tap_create_flags = 0;
     bool template_ifname = false;
     virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
     const char *tunpath = "/dev/net/tun";
@@ -427,6 +427,9 @@ qemuInterfaceEthernetConnect(virDomainDefPtr def,
         }
     }
 
+    if (net->hostlinkstate != VIR_DOMAIN_NET_INTERFACE_LINK_STATE_DOWN)
+        tap_create_flags |= VIR_NETDEV_TAP_CREATE_IFUP;
+
     if (!net->ifname ||
         STRPREFIX(net->ifname, VIR_NET_GENERATED_TAP_PREFIX) ||
         strchr(net->ifname, '%')) {
@@ -453,9 +456,6 @@ qemuInterfaceEthernetConnect(virDomainDefPtr def,
     if (virNetDevSetMAC(net->ifname, &tapmac) < 0)
         goto cleanup;
 
-    if (virNetDevSetOnline(net->ifname, true) < 0)
-        goto cleanup;
-
     if (net->script &&
         virNetDevRunEthernetScript(net->ifname, net->script) < 0)
         goto cleanup;
-- 
2.9.3




More information about the libvir-list mailing list