[libvirt] Using -netdev with qemu/kvm rather than old style
by Pete Ashdown
I have 0.8.3 installed and my net devices are still being defined via -net
rather than -netdev. I have found that using the latter allows my ethernet to
properly offload and gives a 35% performance gain. Looking through the
libvirt code I find in qemu_conf.c:
/* Possible combinations
*
* 1. Old way: -net nic,model=e1000,vlan=1 -net tap,vlan=1
* 2. Semi-new: -device e1000,vlan=1 -net tap,vlan=1
* 3. Best way: -netdev type=tap,id=netdev1 -device e1000,id=netdev1
*
* NB, no support for -netdev without use of -device
*/
How do I convince virsh/libvirt to use #3, the "Best way"?
14 years, 1 month
[libvirt] [PATCH] [DOCS] nwfilter: Add 2nd example to the html docs
by Stefan Berger
This patch adds another example to the nwfilter html page and provides
2 solutions for how to write a filter meeting the given requirements
using newly added features.
Signed-off-by: Stefan Berger <stefanb(a)us.ibm.com>
---
docs/formatnwfilter.html.in | 180
+++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 179 insertions(+), 1 deletion(-)
Index: libvirt-acl/docs/formatnwfilter.html.in
===================================================================
--- libvirt-acl.orig/docs/formatnwfilter.html.in
+++ libvirt-acl/docs/formatnwfilter.html.in
@@ -1468,7 +1468,8 @@
<li>prevents a VM's interface from MAC, IP and ARP spoofing</li>
<li>opens only TCP ports 22 and 80 of a VM's interface</li>
<li>allows the VM to send ping traffic from an interface
- but no let the VM be pinged on the interface</li>
+ but not let the VM be pinged on the interface</li>
+ <li>allows the VM to do DNS lookups (UDP towards port 53)</li>
</ul>
<p>
The requirement to prevent spoofing is fulfilled by the existing
@@ -1510,6 +1511,11 @@
<icmp/>
</rule>
+ <!-- enable outgoing DNS lookups using UDP -->
+ <rule action='accept' direction='out'>
+ <udp dstportstart='53'/>
+ </rule>
+
<!-- drop all other traffic -->
<rule action='drop' direction='inout'>
<all/>
@@ -1556,6 +1562,178 @@
</rule>
</pre>
+ <h3><a name="nwfwriteexample2nd">Second example custom filter</a></h3>
+ <p>
+ In this example we now want to build a similar filter as in the
+ example above, but extend the list of requirements with an
+ ftp server located inside the VM. Further, we will be using features
+ that have been added in <span class="since">version 0.8.5</span>.
+ The requirements for this filter shall be:
+ </p>
+ <ul>
+ <li>prevents a VM's interface from MAC, IP and ARP spoofing</li>
+ <li>opens only TCP ports 22 and 80 of a VM's interface</li>
+ <li>allows the VM to send ping traffic from an interface
+ but not let the VM be pinged on the interface</li>
+ <li>allows the VM to do DNS lookups (UDP towards port 53)</li>
+ <li>enable an ftp server (in active mode) to be run inside the VM
+ </ul>
+ <p>
+ The additional requirement of allowing an ftp server to be run inside
+ the VM maps into the requirement of allowing port 21 to be reachable
+ for ftp control traffic as well as enabling the VM to establish an
+ outgoing tcp connection originating from the VM's TCP port 20 back to
+ the ftp client (ftp active mode). There are several ways of how this
+ filter can be written and we present 2 solutions.
+ <br><br>
+ The 1st solution makes use of the <code>state</code> attribute of
+ the TCP protocol that gives us a hook into the connection tracking
+ framework of the Linux host. For the VM-initiated ftp data connection
+ (ftp active mode) we use the <code>RELATED</code> state that allows
+ us to detect that the VM-initated ftp data connection is a
consequence of
+ ( or 'has a relationship with' ) an existing ftp control connection,
+ thus we want to allow it to let packets
+ pass the firewall. The <code>RELATED</code> state, however, is only
+ valid for the very first packet of the outgoing TCP connection for the
+ ftp data path. Afterwards, the state to compare against is
+ <code>ESTABLISHED</code>, which then applies equally
+ to the incoming and outgoing direction. All this is related to the ftp
+ data traffic origination from TCP port 20 of the VM. This then
leads to
+ the following solution
+ <span class="since">(since 0.8.5 (Qemu, KVM, UML))</span>:
+ </p>
+<pre>
+<filter name='test-eth0'>
+ <!-- reference the clean traffic filter to prevent
+ MAC, IP and ARP spoofing. By not providing
+ and IP address parameter, libvirt will detect the
+ IP address the VM is using. -->
+ <filterref filter='clean-traffic'/>
+
+ <!-- enable TCP port 21 (ftp-control) to be reachable -->
+ <rule action='accept' direction='in'>
+ <tcp dstportstart='21'/>
+ </rule>
+
+ <!-- enable TCP port 20 for VM-initiated ftp data connection
+ related to an existing ftp control connection -->
+ <rule action='accept' direction='out'>
+ <tcp srcportstart='20' state='RELATED,ESTABLISHED'/>
+ </rule>
+
+ <!-- accept all packets from client on the ftp data connection -->
+ <rule action='accept' direction='in'>
+ <tcp dstportstart='20' state='ESTABLISHED'/>
+ </rule>
+
+ <!-- enable TCP ports 22 (ssh) and 80 (http) to be reachable -->
+ <rule action='accept' direction='in'>
+ <tcp dstportstart='22'/>
+ </rule>
+
+ <rule action='accept' direction='in'>
+ <tcp dstportstart='80'/>
+ </rule>
+
+ <!-- enable general ICMP traffic to be initiated by the VM;
+ this includes ping traffic -->
+ <rule action='accept' direction='out'>
+ <icmp/>
+ </rule>
+
+ <!-- enable outgoing DNS lookups using UDP -->
+ <rule action='accept' direction='out'>
+ <udp dstportstart='53'/>
+ </rule>
+
+ <!-- drop all other traffic -->
+ <rule action='drop' direction='inout'>
+ <all/>
+ </rule>
+
+</filter>
+</pre>
+ <p>
+ Before trying out a filter using the <code>RELATED</code> state,
+ you have to make sure that the approriate connection tracking module
+ has been loaded into the host's kernel. Depending on the version
of the
+ kernel, you must run either one of the following two commands before
+ the ftp connection with the VM is established.
+ </p>
+<pre>
+ modprobe nf_conntrack_ftp # where available or
+
+ modprobe ip_conntrack_ftp # if above is not available
+</pre>
+ <p>
+ If other protocols than ftp are to be used in conjunction with the
+ <code>RELATED</code> state, their corresponding module must be loaded.
+ Modules exist at least for the protocols ftp, tftp, irc, sip,
+ sctp, and amanda.
+ </p>
+ <p>
+ The 2nd solution makes uses the state flags of connections more
+ than the previous solution did.
+ In this solution we take advantage of the fact that the
+ <code>NEW</code> state of a connection is valid when the very
+ first packet of a traffic flow is seen. Subsequently, if the very
first
+ packet of a flow is accepted, the flow becomes a connection and enters
+ the <code>ESTABLISHED</code> state. This allows us to write a general
+ rule for allowing packets of <code>ESTABLISHED</code> connections to
+ reach the VM or be sent by the VM.
+ We write specific rules for the very first packets identified by the
+ <code>NEW</code> state and for which ports they are acceptable. All
+ packets for ports that are not explicitly accepted will be dropped and
+ therefore the connection will not go into the <code>ESTABLISHED</code>
+ state and any subsequent packets be dropped.
+ </p>
+
+<pre>
+<filter name='test-eth0'>
+ <!-- reference the clean traffic filter to prevent
+ MAC, IP and ARP spoofing. By not providing
+ and IP address parameter, libvirt will detect the
+ IP address the VM is using. -->
+ <filterref filter='clean-traffic'/>
+
+ <!-- let the packets of all previously accepted connections reach
the VM -->
+ <rule action='accept' direction='in'>
+ <all state='ESTABLISHED'/>
+ </rule>
+
+ <!-- let the packets of all previously accepted and related
connections be sent from the VM -->
+ <rule action='accept' direction='out'>
+ <all state='ESTABLISHED,RELATED'/>
+ </rule>
+
+ <!-- enable traffic towards port 21 (ftp), 22 (ssh) and 80 (http)
-->
+ <rule action='accept' direction='in'>
+ <tcp dstportstart='21' dstportend='22' state='NEW'/>
+ </rule>
+
+ <rule action='accept' direction='in'>
+ <tcp dstportstart='80' state='NEW'/>
+ </rule>
+
+ <!-- enable general ICMP traffic to be initiated by the VM;
+ this includes ping traffic -->
+ <rule action='accept' direction='out'>
+ <icmp state='NEW'/>
+ </rule>
+
+ <!-- enable outgoing DNS lookups using UDP -->
+ <rule action='accept' direction='out'>
+ <udp dstportstart='53' state='NEW'/>
+ </rule>
+
+ <!-- drop all other traffic -->
+ <rule action='drop' direction='inout'>
+ <all/>
+ </rule>
+
+</filter>
+
+</pre>
<h2><a name="nwflimits">Limitations</a></h2>
<p>
14 years, 1 month
[libvirt] [patch 0/5] nwfilter: add a 'state' attribute to protocols
by Stefan Berger
The following patch series introduces an attribute 'state' for iptables-
supported protocols. This gives the user more control over the 'state match'
of the underlying ip(6)tables implementation and allows to create filtering
rules that are more efficient to evaluate. TCK test cases will be posted later.
Each rule containing a state attribute with either one of the values
NEW, ESTABLISHED, RELATED, INVALID or NONE, gets one iptables rule created
for the direction of the rule. The keyword 'NONE' does the same, but doesn't
generate a rule with the 'state match'. If no state attribute is used,
a symmetric rule in the incoming and outgoing direction is generated (as
was done previously).
The patches do the following:
- extend the parser and XML generator to parse and create XML with the
state attribute
- instantiate the state in case of ip(6)tables
- extend the nwfilter.rng schema with the state attribute's possible values
- add information about the new state attribute to the web docs
- add a test case for the XML parser/generator to be run during 'make check'
I valgrind'ed this patch and it looks all memory is freed appropriately.
Regards,
Stefan
14 years, 1 month
[libvirt] bug: network lock-out
by Zdenek Styblik
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Hello,
I'm sorry to report this, but network should start or stop regardless
iptables status.
virsh # net-start default
error: Failed to start network default
error: internal error '/usr/sbin/iptables --table filter --delete INPUT
- --in-interface virbr0 --protocol udp --destination-port 69 --jump
ACCEPT' exited with non-zero status 1 and signal 0: iptables: Bad rule
(does a matching rule exist in that chain?).
Ok, so I'm going to create this rule to make you happy.
virsh # net-start default
error: Failed to start network default
error: internal error '/usr/sbin/iptables --table mangle --delete
POSTROUTING --out-interface virbr0 --protocol udp --destination-port 68
- --jump CHECKSUM --checksum-fill' exited with non-zero status 2 and
signal 0: iptables v1.4.7: unknown option `--checksum-fill'
Try `iptables -h' or 'iptables --help' for more information.
And Oops, because I don't have CHECKSUM support. And to note, it's not
even in kernel. Rely on such features is unfriendly and bellow belt :)
Once again, I'm locked by hard-coded features :( That's why I "fight"
against these.
btw it's strange to me that libvirt is deleting rules that shouldn't be
present since I want to start network, not to stop it.
Let's dump all nwfilters and hope for miracle...and nothing. Same
errors, although nwfilter rules are gone. What the ...? :|
libvirt-0.8.4
Regards,
Zdenek
- --
Zdenek Styblik
Net/Linux admin
OS TurnovFree.net
email: stybla(a)turnovfree.net
jabber: stybla(a)jabber.turnovfree.net
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/
iEYEARECAAYFAkyrezwACgkQ8MreUbSH7ikbpQCdEDtbwG+PV6u0yvUZYzXlQas9
ohEAoIyy/HPZwtWlaOAgtx6jnOEFashR
=u7st
-----END PGP SIGNATURE-----
14 years, 1 month
[libvirt] libvirt and nested pagind
by Eduardo
Good afternoon!
Searching on the web, I joint some codes and produced those patches.
Now I have a server running perfectly with the following scenario:
AMD Phenom 8400 x3;
Slackware64 13.1 on a slim and custom 2.6.35.2 Linux;
qemu-kvm 0.12.5;
libvirt 0.8.4.
Patch of libvirt 0.8.3:
diff -Naur ../libvirt-0.8.3//docs/schemas/domain.rng
./docs/schemas/domain.rng
--- ../libvirt-0.8.3//docs/schemas/domain.rng 2010-07-29
06:48:30.000000000 -0300
+++ ./docs/schemas/domain.rng 2010-09-01 16:51:57.710851479 -0300
@@ -1595,6 +1595,11 @@
<empty/>
</element>
</optional>
+ <optional>
+ <element name="nesting">
+ <empty/>
+ </element>
+ </optional>
</interleave>
</element>
</optional>
diff -Naur ../libvirt-0.8.3//src/conf/domain_conf.c ./src/conf/domain_conf.c
--- ../libvirt-0.8.3//src/conf/domain_conf.c 2010-08-02
16:16:42.000000000 -0300
+++ ./src/conf/domain_conf.c 2010-09-01 16:51:57.710851479 -0300
@@ -75,7 +75,8 @@
VIR_ENUM_IMPL(virDomainFeature, VIR_DOMAIN_FEATURE_LAST,
"acpi",
"apic",
- "pae")
+ "pae",
+ "nesting")
VIR_ENUM_IMPL(virDomainLifecycle, VIR_DOMAIN_LIFECYCLE_LAST,
"destroy",
diff -Naur ../libvirt-0.8.3//src/conf/domain_conf.h ./src/conf/domain_conf.h
--- ../libvirt-0.8.3//src/conf/domain_conf.h 2010-07-29
06:48:30.000000000 -0300
+++ ./src/conf/domain_conf.h 2010-09-01 16:51:57.710851479 -0300
@@ -649,6 +649,7 @@
VIR_DOMAIN_FEATURE_ACPI,
VIR_DOMAIN_FEATURE_APIC,
VIR_DOMAIN_FEATURE_PAE,
+ VIR_DOMAIN_FEATURE_NESTING,
VIR_DOMAIN_FEATURE_LAST
};
diff -Naur ../libvirt-0.8.3//src/qemu/qemu_conf.c ./src/qemu/qemu_conf.c
--- ../libvirt-0.8.3//src/qemu/qemu_conf.c 2010-08-04
09:21:27.000000000 -0300
+++ ./src/qemu/qemu_conf.c 2010-09-01 16:57:47.485469640 -0300
@@ -1190,6 +1190,8 @@
flags |= QEMUD_CMD_FLAG_MEM_PATH;
if (strstr(help, "-chardev"))
flags |= QEMUD_CMD_FLAG_CHARDEV;
+ if (strstr(help, "-enable-nesting"))
+ flags |= QEMUD_CMD_FLAG_NESTING;
if (strstr(help, "-balloon"))
flags |= QEMUD_CMD_FLAG_BALLOON;
if (strstr(help, "-device"))
@@ -3907,6 +3909,9 @@
goto error;
}
}
+ if ((qemuCmdFlags & QEMUD_CMD_FLAG_NESTING) &&
+ (def->features & (1 << VIR_DOMAIN_FEATURE_NESTING)))
+ ADD_ARG_LIT("-enable-nesting");
/*
* NB, -nographic *MUST* come before any serial, or monitor
@@ -6265,6 +6270,8 @@
fullscreen = 1;
} else if (STREQ(arg, "-localtime")) {
def->clock.offset = VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME;
+ } else if (STREQ(arg, "-enable-nesting")) {
+ def->features |= (1 << VIR_DOMAIN_FEATURE_NESTING);
} else if (STREQ(arg, "-kernel")) {
WANT_VALUE();
if (!(def->os.kernel = strdup(val)))
diff -Naur ../libvirt-0.8.3//src/qemu/qemu_conf.h ./src/qemu/qemu_conf.h
--- ../libvirt-0.8.3//src/qemu/qemu_conf.h 2010-07-28
11:18:15.000000000 -0300
+++ ./src/qemu/qemu_conf.h 2010-09-01 16:58:29.900876561 -0300
@@ -92,6 +92,7 @@
QEMUD_CMD_FLAG_PCI_CONFIGFD = (1LL << 36), /* pci-assign.configfd */
QEMUD_CMD_FLAG_NODEFCONFIG = (1LL << 37), /* -nodefconfig */
QEMUD_CMD_FLAG_BOOT_MENU = (1LL << 38), /* -boot menu=on
support */
+ QEMUD_CMD_FLAG_NESTING = (1LL << 39), /* Is the
-enable-nesting flag available */
};
/* Main driver state */
Patch of libvirt 0.8.4:
diff -Naur libvirt-0.8.4/docs/schemas/domain.rng
libvirt-0.8.4.edu/docs/schemas/domain.rng
--- libvirt-0.8.4/docs/schemas/domain.rng 2010-08-31
10:44:13.000000000 -0300
+++ libvirt-0.8.4.edu/docs/schemas/domain.rng 2010-09-28
14:34:40.626234752 -0300
@@ -1619,6 +1619,11 @@
<empty/>
</element>
</optional>
+ <optional>
+ <element name="nesting">
+ <empty/>
+ </element>
+ </optional>
</interleave>
</element>
</optional>
diff -Naur libvirt-0.8.4/src/conf/domain_conf.c
libvirt-0.8.4.edu/src/conf/domain_conf.c
--- libvirt-0.8.4/src/conf/domain_conf.c 2010-08-31
10:44:13.000000000 -0300
+++ libvirt-0.8.4.edu/src/conf/domain_conf.c 2010-09-28
14:35:36.069149447 -0300
@@ -75,7 +75,8 @@
VIR_ENUM_IMPL(virDomainFeature, VIR_DOMAIN_FEATURE_LAST,
"acpi",
"apic",
- "pae")
+ "pae",
+ "nesting")
VIR_ENUM_IMPL(virDomainLifecycle, VIR_DOMAIN_LIFECYCLE_LAST,
"destroy",
diff -Naur libvirt-0.8.4/src/conf/domain_conf.h
libvirt-0.8.4.edu/src/conf/domain_conf.h
--- libvirt-0.8.4/src/conf/domain_conf.h 2010-08-31
10:44:13.000000000 -0300
+++ libvirt-0.8.4.edu/src/conf/domain_conf.h 2010-09-28
14:36:11.931054102 -0300
@@ -650,6 +650,7 @@
VIR_DOMAIN_FEATURE_ACPI,
VIR_DOMAIN_FEATURE_APIC,
VIR_DOMAIN_FEATURE_PAE,
+ VIR_DOMAIN_FEATURE_NESTING,
VIR_DOMAIN_FEATURE_LAST
};
diff -Naur libvirt-0.8.4/src/qemu/qemu_conf.c
libvirt-0.8.4.edu/src/qemu/qemu_conf.c
--- libvirt-0.8.4/src/qemu/qemu_conf.c 2010-09-10 09:38:13.000000000 -0300
+++ libvirt-0.8.4.edu/src/qemu/qemu_conf.c 2010-09-28
14:38:36.218612249 -0300
@@ -1192,6 +1192,8 @@
flags |= QEMUD_CMD_FLAG_MEM_PATH;
if (strstr(help, "-chardev"))
flags |= QEMUD_CMD_FLAG_CHARDEV;
+ if (strstr(help, "-enable-nesting"))
+ flags |= QEMUD_CMD_FLAG_NESTING;
if (strstr(help, "-balloon"))
flags |= QEMUD_CMD_FLAG_BALLOON;
if (strstr(help, "-device"))
@@ -3944,6 +3946,9 @@
goto error;
}
}
+ if ((qemuCmdFlags & QEMUD_CMD_FLAG_NESTING) &&
+ (def->features & (1 << VIR_DOMAIN_FEATURE_NESTING)))
+ ADD_ARG_LIT("-enable-nesting");
/*
* NB, -nographic *MUST* come before any serial, or monitor
@@ -6303,6 +6308,8 @@
fullscreen = 1;
} else if (STREQ(arg, "-localtime")) {
def->clock.offset = VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME;
+ } else if (STREQ(arg, "-enable-nesting")) {
+ def->features |= (1 << VIR_DOMAIN_FEATURE_NESTING);
} else if (STREQ(arg, "-kernel")) {
WANT_VALUE();
if (!(def->os.kernel = strdup(val)))
diff -Naur libvirt-0.8.4/src/qemu/qemu_conf.h
libvirt-0.8.4.edu/src/qemu/qemu_conf.h
--- libvirt-0.8.4/src/qemu/qemu_conf.h 2010-08-31 10:44:13.000000000 -0300
+++ libvirt-0.8.4.edu/src/qemu/qemu_conf.h 2010-09-28
14:38:58.739788135 -0300
@@ -93,6 +93,8 @@
QEMUD_CMD_FLAG_NODEFCONFIG = (1LL << 37), /* -nodefconfig */
QEMUD_CMD_FLAG_BOOT_MENU = (1LL << 38), /* -boot menu=on
support */
QEMUD_CMD_FLAG_ENABLE_KQEMU = (1LL << 39), /* -enable-kqemu flag */
+ QEMUD_CMD_FLAG_NESTING = (1LL << 39), /* Is the
-enable-nesting flag available */
+
};
/* Main driver state */
--
*Eduardo Ramos*
www.freedominterface.org
+55 12 91051687
exten=>eduardo,1,hangup()
14 years, 1 month
[libvirt] [PATCH] Added new attribute exportfs_type to filesystem element
by Harsh Prateek Bora
This patch introduces a new attribute export_fs to the filesystem
element which specifies the type of export. Currently only 'local'
type of exported filesystem is supported. More types like NFS, clusterFS, etc.
can be added later as required.
Note: This patch is based on the following two patches:
1) Daniel's patch to support 9pfs:
https://www.redhat.com/archives/libvir-list/2010-September/msg00358.html
2) Another related patch to support 'security_model' attribute:
https://www.redhat.com/archives/libvir-list/2010-September/msg00435.html
Signed-off-by: Harsh Prateek Bora <harsh(a)linux.vnet.ibm.com>
---
docs/schemas/domain.rng | 5 +++++
src/conf/domain_conf.c | 24 ++++++++++++++++++++++--
src/conf/domain_conf.h | 9 +++++++++
src/qemu/qemu_conf.c | 3 ++-
4 files changed, 38 insertions(+), 3 deletions(-)
diff --git a/docs/schemas/domain.rng b/docs/schemas/domain.rng
index 43a292d..5b7563a 100644
--- a/docs/schemas/domain.rng
+++ b/docs/schemas/domain.rng
@@ -768,6 +768,11 @@
<value>none</value>
</choice>
</attribute>
+ <attribute name="exportfs_type">
+ <choice>
+ <value>local</value>
+ </choice>
+ </attribute>
</optional>
</element>
</define>
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index a9881d1..6d728a7 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -166,6 +166,8 @@ VIR_ENUM_IMPL(virDomainFSSecurityModel, VIR_DOMAIN_FS_SECURITY_LAST,
"mapped",
"none")
+VIR_ENUM_IMPL(virDomainFSExportType, VIR_DOMAIN_FS_EXPORT_TYPE_LAST,
+ "local")
VIR_ENUM_IMPL(virDomainNet, VIR_DOMAIN_NET_TYPE_LAST,
"user",
@@ -1851,6 +1853,7 @@ virDomainFSDefParseXML(xmlNodePtr node,
virDomainFSDefPtr def;
xmlNodePtr cur;
char *type = NULL;
+ char *exportfs_type = NULL;
char *source = NULL;
char *target = NULL;
char *security_model;
@@ -1871,6 +1874,17 @@ virDomainFSDefParseXML(xmlNodePtr node,
def->type = VIR_DOMAIN_FS_TYPE_MOUNT;
}
+ exportfs_type = virXMLPropString(node, "exportfs_type");
+ if (exportfs_type) {
+ if ((def->exportfs_type = virDomainFSExportTypeTypeFromString(exportfs_type)) < 0) {
+ virDomainReportError(VIR_ERR_INTERNAL_ERROR,
+ _("unknown exportfs type '%s'"), exportfs_type);
+ goto error;
+ }
+ } else {
+ def->exportfs_type = VIR_DOMAIN_FS_EXPORT_TYPE_LOCAL;
+ }
+
security_model = virXMLPropString(node, "security_model");
if (security_model) {
if ((def->security_model = virDomainFSSecurityModelTypeFromString(security_model)) < 0) {
@@ -5621,6 +5635,7 @@ virDomainFSDefFormat(virBufferPtr buf,
{
const char *type = virDomainFSTypeToString(def->type);
const char *sec_model = virDomainFSSecurityModelTypeToString(def->security_model);
+ const char *expfs_type = virDomainFSExportTypeTypeToString(def->exportfs_type);
if (!type) {
virDomainReportError(VIR_ERR_INTERNAL_ERROR,
@@ -5628,6 +5643,11 @@ virDomainFSDefFormat(virBufferPtr buf,
return -1;
}
+ if (!expfs_type) {
+ virDomainReportError(VIR_ERR_INTERNAL_ERROR,
+ _("unexpected exportfs type %d"), def->type);
+ }
+
if (!sec_model) {
virDomainReportError(VIR_ERR_INTERNAL_ERROR,
_("unexpected security model %d"), def->security_model);
@@ -5636,8 +5656,8 @@ virDomainFSDefFormat(virBufferPtr buf,
virBufferVSprintf(buf,
- " <filesystem type='%s' security_model='%s'>\n",
- type, sec_model);
+ " <filesystem type='%s' exportfs_type='%s' security_model='%s'>\n",
+ type, expfs_type, sec_model);
if (def->src) {
switch (def->type) {
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 6adf027..956cac0 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -245,10 +245,18 @@ enum virDomainFSSecurityModel {
VIR_DOMAIN_FS_SECURITY_LAST
};
+/* Export Filesystem Type */
+enum virDomainFSExportType {
+ VIR_DOMAIN_FS_EXPORT_TYPE_LOCAL,
+
+ VIR_DOMAIN_FS_EXPORT_TYPE_LAST
+};
+
typedef struct _virDomainFSDef virDomainFSDef;
typedef virDomainFSDef *virDomainFSDefPtr;
struct _virDomainFSDef {
int type;
+ int exportfs_type;
int security_model;
char *src;
char *dst;
@@ -1177,6 +1185,7 @@ VIR_ENUM_DECL(virDomainDiskErrorPolicy)
VIR_ENUM_DECL(virDomainController)
VIR_ENUM_DECL(virDomainControllerModel)
VIR_ENUM_DECL(virDomainFS)
+VIR_ENUM_DECL(virDomainFSExportType)
VIR_ENUM_DECL(virDomainNet)
VIR_ENUM_DECL(virDomainChrDevice)
VIR_ENUM_DECL(virDomainChrChannelTarget)
diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
index 6b96d2f..458beab 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -2788,7 +2788,8 @@ char *qemuBuildFSStr(virDomainFSDefPtr fs,
goto error;
}
- virBufferAddLit(&opt, "local");
+ if (fs->exportfs_type == VIR_DOMAIN_FS_EXPORT_TYPE_LOCAL)
+ virBufferAddLit(&opt, "local");
if (fs->security_model == VIR_DOMAIN_FS_SECURITY_PASSTHROUGH)
virBufferAddLit(&opt, ",security_model=passthrough");
else if (fs->security_model == VIR_DOMAIN_FS_SECURITY_MAPPED)
--
1.7.1.1
14 years, 1 month
[libvirt] [PATCH] [RFC] nwfilter: resolve deadlock between VM operations and filter update
by Stefan Berger
This is from a bug report and conversation on IRC where Soren reported
that while a filter update is occurring on one or more VMs (due to a
rule having been edited for example), a deadlock can occur when a VM
referencing a filter is started.
The problem is caused by the two locking sequences of
qemu driver, qemu domain, filter # for the VM start operation
filter, qemu_driver, qemu_domain # for the filter update
operation
that obviously don't lock in the same order. The problem is the 2nd lock
sequence. Here the qemu_driver lock is being grabbed in
qemu_driver:qemudVMFilterRebuild()
The following solution is based on the idea of trying to re-arrange the
2nd sequence of locks as follows:
qemu_driver, filter, qemu_driver, qemu_domain
and making the qemu driver recursively lockable so that a second lock
can occur, this would then lead to the following net-locking sequence
qemu_driver, filter, qemu_domain
where the 2nd qemu_driver lock has been ( logically ) eliminated.
The 2nd part of the idea is that the sequence of locks (filter,
qemu_domain) and (qemu_domain, filter) becomes interchangeable if all
code paths where filter AND qemu_domain are locked have a preceding
qemu_domain lock that basically blocks their concurrent execution
So, the following code paths exist towards
qemu_driver:qemudVMFilterRebuild where we now want to put a qemu_driver
lock in front of the filter lock.
-> nwfilterUndefine() [ locks the filter ]
-> virNWFilterTestUnassignDef()
-> virNWFilterTriggerVMFilterRebuild()
-> qemudVMFilterRebuild()
-> nwfilterDefine()
-> virNWFilterPoolAssignDef() [ locks the filter ]
-> virNWFilterTriggerVMFilterRebuild()
-> qemudVMFilterRebuild()
-> nwfilterDriverReload()
-> virNWFilterPoolLoadAllConfigs()
->virNWFilterPoolObjLoad()
-> virNWFilterPoolAssignDef() [ locks the filter ]
-> virNWFilterTriggerVMFilterRebuild()
-> qemudVMFilterRebuild()
-> nwfilterDriverStartup()
-> virNWFilterPoolLoadAllConfigs()
->virNWFilterPoolObjLoad()
-> virNWFilterPoolAssignDef() [ locks the filter ]
-> virNWFilterTriggerVMFilterRebuild()
-> qemudVMFilterRebuild()
Qemu is not the only driver using the nwfilter driver, but also the UML
driver calls into it. Therefore qemuVMFilterRebuild() can be exchanged
with umlVMFilterRebuild() along with the driver lock of qemu_driver that
can now be a uml_driver. Further, since UML and Qemu domains can be
running on the same machine, the triggering of a rebuild of the filter
can touch both types of drivers and their domains.
In the patch below I am now extending each nwfilter callback driver with
functions for locking and unlocking the (VM) driver (UML, QEMU) and
introduce new functions for locking all registered callback drivers and
unlocking them. Then I am distributing the
lock-all-cbdrivers/unlock-all-cbdrivers call into the above call paths.
The last shown callpath starting with nwfilterDriverStart() is
problematic since it is initialize before the Qemu and UML drives are
and thus a lock in the path would result in a NULL pointer attempted to
be locked -- the call to virNWFilterTriggerVMFilterRebuild() is never
called, so we never lock either the qemu_driver or the uml_driver in
that path. Therefore, only the first 3 paths now receive calls to lock
and unlock all callback drivers. Now that the locks are distributed
where it matters I can remove the qemu_driver and uml_driver lock from
qemudVMFilterRebuild() and umlVMFilterRebuild() and not requiring the
recursive locks.
For now I want to put this out as an RFC patch. I have tested it by
'stretching' the critical section after the define/undefine functions
each lock the filter so I can (easily) concurrently execute another VM
operation (suspend,start). That code is in this patch and if you want
you can de-activate it. It seems to work ok and operations are being
blocked while the update is being done.
I still also want to verify the other assumption above that locking
filter and qemu_domain always has a preceding qemu_driver lock.
Signed-off-by: Stefan Berger <stefanb(a)us.ibm.com>
---
src/conf/nwfilter_conf.c | 18 ++++++++++++++++++
src/conf/nwfilter_conf.h | 6 ++++++
src/libvirt_private.syms | 2 ++
src/nwfilter/nwfilter_driver.c | 20 ++++++++++++++++++++
src/qemu/qemu_driver.c | 15 +++++++++++++++
src/uml/uml_driver.c | 14 ++++++++++++++
6 files changed, 75 insertions(+)
Index: libvirt-acl/src/conf/nwfilter_conf.h
===================================================================
--- libvirt-acl.orig/src/conf/nwfilter_conf.h
+++ libvirt-acl/src/conf/nwfilter_conf.h
@@ -639,6 +639,8 @@ void virNWFilterConfLayerShutdown(void);
typedef int (*virNWFilterRebuild)(virConnectPtr conn,
virHashIterator, void *data);
+typedef void (*virNWFilterVoidCall)(void);
+
typedef struct _virNWFilterCallbackDriver virNWFilterCallbackDriver;
typedef virNWFilterCallbackDriver *virNWFilterCallbackDriverPtr;
@@ -646,9 +648,13 @@ struct _virNWFilterCallbackDriver {
const char *name;
virNWFilterRebuild vmFilterRebuild;
+ virNWFilterVoidCall vmDriverLock;
+ virNWFilterVoidCall vmDriverUnlock;
};
void virNWFilterRegisterCallbackDriver(virNWFilterCallbackDriverPtr);
+void virNWFilterCallbackDriversLock(void);
+void virNWFilterCallbackDriversUnlock(void);
VIR_ENUM_DECL(virNWFilterRuleAction);
Index: libvirt-acl/src/qemu/qemu_driver.c
===================================================================
--- libvirt-acl.orig/src/qemu/qemu_driver.c
+++ libvirt-acl/src/qemu/qemu_driver.c
@@ -12757,9 +12757,24 @@ qemudVMFiltersInstantiate(virConnectPtr
return err;
}
+
+static void
+qemudVMDriverLock(void) {
+ qemuDriverLock(qemu_driver);
+};
+
+
+static void
+qemudVMDriverUnlock(void) {
+ qemuDriverUnlock(qemu_driver);
+};
+
+
static virNWFilterCallbackDriver qemuCallbackDriver = {
.name = "QEMU",
.vmFilterRebuild = qemudVMFilterRebuild,
+ .vmDriverLock = qemudVMDriverLock,
+ .vmDriverUnlock = qemudVMDriverUnlock,
};
int qemuRegister(void) {
Index: libvirt-acl/src/uml/uml_driver.c
===================================================================
--- libvirt-acl.orig/src/uml/uml_driver.c
+++ libvirt-acl/src/uml/uml_driver.c
@@ -2219,9 +2219,23 @@ static virStateDriver umlStateDriver = {
.active = umlActive,
};
+static void
+umlVMDriverLock(void)
+{
+ umlDriverLock(uml_driver);
+}
+
+static void
+umlVMDriverUnlock(void)
+{
+ umlDriverUnlock(uml_driver);
+}
+
static virNWFilterCallbackDriver umlCallbackDriver = {
.name = "UML",
.vmFilterRebuild = umlVMFilterRebuild,
+ .vmDriverLock = umlVMDriverLock,
+ .vmDriverUnlock = umlVMDriverUnlock,
};
int umlRegister(void) {
Index: libvirt-acl/src/conf/nwfilter_conf.c
===================================================================
--- libvirt-acl.orig/src/conf/nwfilter_conf.c
+++ libvirt-acl/src/conf/nwfilter_conf.c
@@ -2161,6 +2161,24 @@ virNWFilterRegisterCallbackDriver(virNWF
}
}
+void
+virNWFilterCallbackDriversLock(void)
+{
+ int i;
+
+ for (i = 0; i < nCallbackDriver; i++)
+ callbackDrvArray[i]->vmDriverLock();
+}
+
+void
+virNWFilterCallbackDriversUnlock(void)
+{
+ int i;
+
+ for (i = 0; i < nCallbackDriver; i++)
+ callbackDrvArray[i]->vmDriverUnlock();
+}
+
static virHashIterator virNWFilterDomainFWUpdateCB;
Index: libvirt-acl/src/libvirt_private.syms
===================================================================
--- libvirt-acl.orig/src/libvirt_private.syms
+++ libvirt-acl/src/libvirt_private.syms
@@ -534,6 +534,8 @@ virNWFilterConfLayerInit;
virNWFilterConfLayerShutdown;
virNWFilterLockFilterUpdates;
virNWFilterUnlockFilterUpdates;
+virNWFilterCallbackDriversLock;
+virNWFilterCallbackDriversUnlock;
# nwfilter_params.h
Index: libvirt-acl/src/nwfilter/nwfilter_driver.c
===================================================================
--- libvirt-acl.orig/src/nwfilter/nwfilter_driver.c
+++ libvirt-acl/src/nwfilter/nwfilter_driver.c
@@ -34,6 +34,7 @@
#include "memory.h"
#include "domain_conf.h"
#include "domain_nwfilter.h"
+#include "nwfilter_conf.h"
#include "nwfilter_driver.h"
#include "nwfilter_gentech_driver.h"
@@ -152,9 +153,13 @@ nwfilterDriverReload(void) {
virNWFilterLearnThreadsTerminate(true);
nwfilterDriverLock(driverState);
+ virNWFilterCallbackDriversLock();
+
virNWFilterPoolLoadAllConfigs(conn,
&driverState->pools,
driverState->configDir);
+
+ virNWFilterCallbackDriversUnlock();
nwfilterDriverUnlock(driverState);
virConnectClose(conn);
@@ -328,12 +333,21 @@ nwfilterDefine(virConnectPtr conn,
virNWFilterPtr ret = NULL;
nwfilterDriverLock(driver);
+ virNWFilterCallbackDriversLock();
+
if (!(def = virNWFilterDefParseString(conn, xml)))
goto cleanup;
if (!(pool = virNWFilterPoolObjAssignDef(conn, &driver->pools, def)))
goto cleanup;
+#define CRITICAL_SECTION_STRETCH 10
+if (true) {
+ fprintf(stderr,"sleep in %s\n", __FUNCTION__);
+ sleep(CRITICAL_SECTION_STRETCH);
+ fprintf(stderr,"continue in %s\n", __FUNCTION__);
+}
+
if (virNWFilterPoolObjSaveDef(driver, pool, def) < 0) {
virNWFilterPoolObjRemove(&driver->pools, pool);
def = NULL;
@@ -347,6 +361,8 @@ cleanup:
virNWFilterDefFree(def);
if (pool)
virNWFilterPoolObjUnlock(pool);
+
+ virNWFilterCallbackDriversUnlock();
nwfilterDriverUnlock(driver);
return ret;
}
@@ -359,6 +375,8 @@ nwfilterUndefine(virNWFilterPtr obj) {
int ret = -1;
nwfilterDriverLock(driver);
+ virNWFilterCallbackDriversLock();
+
pool = virNWFilterPoolObjFindByUUID(&driver->pools, obj->uuid);
if (!pool) {
virNWFilterReportError(VIR_ERR_INVALID_NWFILTER,
@@ -366,6 +384,12 @@ nwfilterUndefine(virNWFilterPtr obj) {
goto cleanup;
}
+if (true) {
+ fprintf(stderr,"sleep in %s\n", __FUNCTION__);
+ sleep(CRITICAL_SECTION_STRETCH);
+ fprintf(stderr,"continue in %s\n", __FUNCTION__);
+}
+
if (virNWFilterTestUnassignDef(obj->conn, pool)) {
virNWFilterReportError(VIR_ERR_INVALID_NWFILTER,
"%s",
@@ -385,6 +409,8 @@ nwfilterUndefine(virNWFilterPtr obj) {
cleanup:
if (pool)
virNWFilterPoolObjUnlock(pool);
+
+ virNWFilterCallbackDriversUnlock();
nwfilterDriverUnlock(driver);
return ret;
}
14 years, 1 month
[libvirt] [PATCH] xen: Fix bogus error when attaching a device
by Jiri Denemark
The xm internal xen driver only supports disk and network devices to be
added to a guest. On an attempt to attach any other device the xm driver
used VIR_ERR_XML_ERROR which resulted in a completely bogus error
message:
error: Failed to attach device from pci.xml
error: XML description for unknown device is not well formed or invalid
---
src/xen/xm_internal.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/xen/xm_internal.c b/src/xen/xm_internal.c
index fcc9378..00f0df8 100644
--- a/src/xen/xm_internal.c
+++ b/src/xen/xm_internal.c
@@ -2980,8 +2980,8 @@ xenXMDomainAttachDeviceFlags(virDomainPtr domain, const char *xml,
}
default:
- xenXMError(VIR_ERR_XML_ERROR,
- "%s", _("unknown device"));
+ xenXMError(VIR_ERR_OPERATION_INVALID, "%s",
+ _("Xm driver only supports adding disk or network devices"));
goto cleanup;
}
--
1.7.3.1
14 years, 1 month