diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 05a1ed4509..33cec1e6dd 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -5879,8 +5879,13 @@
After creating/opening the tap device, an optional shell script
(given in the path
attribute of
- the <script>
element) will be run; this can
- be used to do whatever extra host network integration is
+ the <script>
element) will be run.
+ Since 0.2.1
+ Also, after detaching/closing the tap device, an optional shell
+ script (given in the path
attribute of
+ the <downscript>
element) will be run.
+ Since 5.1.0
+ These can be used to do whatever extra host network integration is
required.
@@ -5889,6 +5894,7 @@
<devices>
<interface type='ethernet'>
<script path='/etc/qemu-ifup-mynet'/>
+ <downscript path='/etc/qemu-ifdown-mynet'/>
</interface>
...
<interface type='ethernet'>
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 9d60b090f3..6727cd743b 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -3191,6 +3191,14 @@
+
+
+
+
+
+
+
+
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index c201fc901d..1406cf079e 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -2520,6 +2520,7 @@ virDomainNetDefClear(virDomainNetDefPtr def)
VIR_FREE(def->teaming.persistent);
VIR_FREE(def->virtPortProfile);
VIR_FREE(def->script);
+ VIR_FREE(def->downscript);
VIR_FREE(def->domain_name);
VIR_FREE(def->ifname);
VIR_FREE(def->ifname_guest);
@@ -11977,6 +11978,7 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
g_autofree char *ifname_guest = NULL;
g_autofree char *ifname_guest_actual = NULL;
g_autofree char *script = NULL;
+ g_autofree char *downscript = NULL;
g_autofree char *address = NULL;
g_autofree char *port = NULL;
g_autofree char *localaddr = NULL;
@@ -12149,6 +12151,9 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
} else if (!script &&
virXMLNodeNameEqual(cur, "script")) {
script = virXMLPropString(cur, "path");
+ } else if (!downscript &&
+ virXMLNodeNameEqual(cur, "downscript")) {
+ downscript = virXMLPropString(cur, "path");
} else if (!domain_name &&
virXMLNodeNameEqual(cur, "backenddomain")) {
domain_name = virXMLPropString(cur, "name");
@@ -12482,6 +12487,8 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
if (script != NULL)
def->script = g_steal_pointer(&script);
+ if (downscript != NULL)
+ def->downscript = g_steal_pointer(&downscript);
if (domain_name != NULL)
def->domain_name = g_steal_pointer(&domain_name);
if (ifname != NULL)
@@ -26567,6 +26574,8 @@ virDomainNetDefFormat(virBufferPtr buf,
virBufferEscapeString(buf, "\n",
def->script);
+ virBufferEscapeString(buf, "\n",
+ def->downscript);
virBufferEscapeString(buf, "\n", def->domain_name);
if (def->ifname &&
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index ddc75d8de2..e152c599ca 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -1055,6 +1055,7 @@ struct _virDomainNetDef {
unsigned long sndbuf;
} tune;
char *script;
+ char *downscript;
char *domain_name; /* backend domain name */
char *ifname; /* interface name on the host () */
int managed_tap; /* enum virTristateBool - ABSENT == YES */