Signed-off-by: Vasiliy Tolstov <v.tolstov(a)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