[libvirt] lxc_controller: don't ignore failed "accept"
by Jim Meyering
Initially I proposed a similar patch here:
http://thread.gmane.org/gmane.comp.emulators.libvirt/20607
That thread languished, and Eric proposed a nearly identical patch:
http://thread.gmane.org/gmane.comp.emulators.libvirt/21630
Here's a patch that should address the initial objection.
Now, my only question is about which errno values to ignore.
Obviously, EMFILE, EFAULT, etc. must not be ignored.
I doubt EINTR and EBADF should be ignored, but haven't
tried to prove the case.
>From 6dcd15b0aa594f3d89e810e0a92aa75dab22903e Mon Sep 17 00:00:00 2001
From: Jim Meyering <meyering(a)redhat.com>
Date: Thu, 20 May 2010 14:30:36 +0200
Subject: [PATCH] lxc_controller.c: don't ignore failed "accept"
* src/lxc/lxc_controller.c (ignorable_epoll_accept_errno): New function.
(lxcControllerMain): Handle a failed accept carefully:
most errno values indicate legitimate failure and must be fatal.
However, ignore a special case: that in which an incoming client quits
between the poll() indicating its presence, and our accept() which
is trying to process it.
---
src/lxc/lxc_controller.c | 23 +++++++++++++++++++++++
1 files changed, 23 insertions(+), 0 deletions(-)
diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c
index 6b64372..75a45e9 100644
--- a/src/lxc/lxc_controller.c
+++ b/src/lxc/lxc_controller.c
@@ -269,6 +269,17 @@ typedef struct _lxcTtyForwardFd_t {
int active;
} lxcTtyForwardFd_t;
+/* Return true if it is ok to ignore an accept-after-epoll syscall
+ that fails with the specified errno value. Else false. */
+static bool
+ignorable_epoll_accept_errno(int erratum)
+{
+ return (errnum == EINVAL
+ || errnum == ECONNABORTED
+ || errnum == EAGAIN
+ || errnum == EWOULDBLOCK);
+}
+
/**
* lxcControllerMain
* @monitor: server socket fd to accept client requests
@@ -350,6 +361,18 @@ static int lxcControllerMain(int monitor,
if (numEvents > 0) {
if (epollEvent.data.fd == monitor) {
int fd = accept(monitor, NULL, 0);
+ if (fd < 0) {
+ /* First reflex may be simply to declare accept failure
+ to be a fatal error. However, accept may fail when
+ a client quits between the above epoll_wait and here.
+ That case is not fatal, but rather to be expected,
+ if not common, so ignore it. */
+ if (ignorable_epoll_accept_errno(errno))
+ continue;
+ virReportSystemError(errno, "%s",
+ _("accept(monitor,...) failed"));
+ goto cleanup;
+ }
if (client != -1) { /* Already connected, so kick new one out */
close(fd);
continue;
--
1.7.1.262.g5ef3d
14 years, 7 months
[libvirt] libvirt and Ruby
by Jaromír Červenka
Hello everyone,
is there any possibility that the Ruby bindings for libvirt will be
updated? I am currently createing a web interface for libivirt. This
web app is written in Ruby on Rails. Now I am in phase when I have to
create a deamon (which will do a "background jobs" and will comunicate
with libvirt) and I would like to write this deamon in Ruby also, but
interface for libvirt is old and not actual. The other possibility is
write this deamon in C# (mono), 'cause from C# is very easy to call
external functions from your library.
Thank you for answer,
--
Greetings,
Jaromír Červenka
Official openSUSE community member
Web: http://www.cervajz.com/
Jabber: cervajz(a)cervajz.com
MSN: jara.cervenka(a)seznam.cz
Tel.: +420 607 592 687
Alt. e-mails:
jaromir.cervenka(a)opensuse.org,
jaromir.cervenka(a)speel.cz
14 years, 7 months
[libvirt] [PATCH] libvirtd: don't ignore virInitialize failure
by Jim Meyering
I almost missed this; it was so similar to what I though
was the sole ignore-virInitialize-failure bug (in python set-up)
that I thought I'd already fixed it.
>From f48e364b6f2182f7fa88862b2e1a789e2d83a027 Mon Sep 17 00:00:00 2001
From: Jim Meyering <meyering(a)redhat.com>
Date: Thu, 20 May 2010 09:52:20 +0200
Subject: [PATCH] libvirtd: don't ignore virInitialize failure
* daemon/libvirtd.c (main): Diagnose virInitialize failure
and exit nonzero.
---
daemon/libvirtd.c | 5 ++++-
1 files changed, 4 insertions(+), 1 deletions(-)
diff --git a/daemon/libvirtd.c b/daemon/libvirtd.c
index afa10fb..aac2d08 100644
--- a/daemon/libvirtd.c
+++ b/daemon/libvirtd.c
@@ -3028,7 +3028,10 @@ int main(int argc, char **argv) {
{0, 0, 0, 0}
};
- virInitialize();
+ if (virInitialize() < 0) {
+ fprintf (stderr, _("libvirtd: initialization failed\n"));
+ exit (EXIT_FAILURE);
+ }
while (1) {
int optidx = 0;
--
1.7.1.259.g3aef8
14 years, 7 months
[libvirt] Different VLAN IDs
by Csom Gyula
Hi there,
We experienced network problems (namely net packet storm), when using multiple NICs and
the same VLAN ID-s for different KVM guests. It turned out that we could workaround the
problem by simply assigning different VLAN ID-s to the different NICs. (Btw our case
looked similar to the one that was posted and discussed on the KVM mailing list. Also the
solution was picked from that discussion. See: http://www.mail-archive.com/kvm@vger.kernel.org/msg24203.html, for details)
We could resolve the problem at the KVM layer, however we have to do it at the libvirt
layer, too. Running thru qemu_conf.c, and executing some unit tests with different type
of interfaces (eg. ethernet, bridge, network), it turned out, that libvirt reassigns
the same vlan ids to the guests starting from 0...
So far the only solution we could figure out is to use a wrapper script around the KVM
binary that replaces VLAN ID-s with unique ones. This one was picked up from a recent
discussion on the upcoming debug API (http://www.mail-archive.com/libvir-list@redhat.com/msg23140.html).
However the method was marked fragile in the list, due the evolving nature of the libvirt
API.
My questions:
- Did anyone experience similar problems, and come up with a clean solution? Specially
is there any better way to provide unique VLAN ID-s thru libvirt then the above
one?
As far as I see the upcoming -netdev option (introduced in QEMU 0.12) will solve the
question. However this was removed from libvirt, since the corresponding qemu monitor command
is not yet developed:
- Do you have a target release for the -netdev option, or is it unknown (eg. dependent
on the yet unknown KVM/QEMU development schedule)?
Cheers,
Gyula
Ps.: our env: Debian GNU/Linux, libvirt, kvm, ebtables
14 years, 7 months
[libvirt] [PATCH] esx: Make esxVI_*_CastFromAnyType dynamically dispatched
by Matthias Bolte
This will be used in the ESX storage driver in order to handle
the DatastoreInfo type and inheriting types properly.
---
src/esx/esx_vi_generator.py | 13 ++++++++++++-
src/esx/esx_vi_types.c | 28 +++++++++++++++++++++-------
2 files changed, 33 insertions(+), 8 deletions(-)
diff --git a/src/esx/esx_vi_generator.py b/src/esx/esx_vi_generator.py
index d249e2d..6ae13c0 100755
--- a/src/esx/esx_vi_generator.py
+++ b/src/esx/esx_vi_generator.py
@@ -765,7 +765,18 @@ class Object:
# cast from any type
if self.features & Object.FEATURE__ANY_TYPE:
source += "/* esxVI_%s_CastFromAnyType */\n" % self.name
- source += "ESX_VI__TEMPLATE__CAST_FROM_ANY_TYPE(%s)\n" % self.name
+ source += "ESX_VI__TEMPLATE__CAST_FROM_ANY_TYPE(%s,\n" % self.name
+
+ if self.extended_by is None:
+ source += "{\n"
+ source += "})\n\n"
+ else:
+ source += "{\n"
+
+ for extended_by in self.extended_by:
+ source += " ESX_VI__TEMPLATE__DISPATCH__CAST_FROM_ANY_TYPE(%s)\n" % extended_by
+
+ source += "})\n\n"
if self.features & Object.FEATURE__LIST:
source += "/* esxVI_%s_CastListFromAnyType */\n" % self.name
diff --git a/src/esx/esx_vi_types.c b/src/esx/esx_vi_types.c
index de2839f..8334efd 100644
--- a/src/esx/esx_vi_types.c
+++ b/src/esx/esx_vi_types.c
@@ -183,7 +183,7 @@
-#define ESX_VI__TEMPLATE__CAST_FROM_ANY_TYPE(_type) \
+#define ESX_VI__TEMPLATE__CAST_FROM_ANY_TYPE(_type, _dispatch) \
int \
esxVI_##_type##_CastFromAnyType(esxVI_AnyType *anyType, \
esxVI_##_type **ptrptr) \
@@ -194,11 +194,16 @@
return -1; \
} \
\
- if (anyType->type != esxVI_Type_##_type) { \
+ switch (anyType->type) { \
+ _dispatch \
+ \
+ case esxVI_Type_##_type: \
+ break; \
+ \
+ default: \
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, \
- "Expecting type '%s' but found '%s'", \
- esxVI_Type_ToString(esxVI_Type_##_type), \
- anyType->other); \
+ _("Call to %s for unexpected type '%s'"), \
+ __FUNCTION__, anyType->other); \
return -1; \
} \
\
@@ -505,7 +510,7 @@
\
default: \
ESX_VI_ERROR(VIR_ERR_INTERNAL_ERROR, \
- "Call to %s for unexpected type '%s'", __FUNCTION__, \
+ _("Call to %s for unexpected type '%s'"), __FUNCTION__, \
esxVI_Type_ToString(item->_type)); \
return _error_return; \
}
@@ -526,6 +531,13 @@
+#define ESX_VI__TEMPLATE__DISPATCH__CAST_FROM_ANY_TYPE(_type) \
+ case esxVI_Type_##_type: \
+ return esxVI_##_type##_Deserialize(anyType->node, \
+ (esxVI_##_type **)ptrptr);
+
+
+
#define ESX_VI__TEMPLATE__DISPATCH__SERIALIZE(_type) \
case esxVI_Type_##_type: \
return esxVI_##_type##_Serialize((esxVI_##_type *)item, element, \
@@ -1359,7 +1371,9 @@ ESX_VI__TEMPLATE__DEEP_COPY(ManagedObjectReference,
ESX_VI__TEMPLATE__LIST__APPEND(ManagedObjectReference)
/* esxVI_ManagedObjectReference_CastFromAnyType */
-ESX_VI__TEMPLATE__CAST_FROM_ANY_TYPE(ManagedObjectReference)
+ESX_VI__TEMPLATE__CAST_FROM_ANY_TYPE(ManagedObjectReference,
+{
+})
/* esxVI_ManagedObjectReference_CastListFromAnyType */
ESX_VI__TEMPLATE__LIST__CAST_FROM_ANY_TYPE(ManagedObjectReference)
--
1.7.0.4
14 years, 7 months
[libvirt] [PATCH] esx: Allow esxVI_X_DynamicCast to be called successfully on X objects
by Matthias Bolte
This semantic will be used in the ESX storage driver.
---
src/esx/esx_vi_types.c | 16 +++++++++-------
1 files changed, 9 insertions(+), 7 deletions(-)
diff --git a/src/esx/esx_vi_types.c b/src/esx/esx_vi_types.c
index 7d2c02c..de2839f 100644
--- a/src/esx/esx_vi_types.c
+++ b/src/esx/esx_vi_types.c
@@ -540,6 +540,13 @@
+#define ESX_VI__TEMPLATE__DYNAMIC_CAST__ACCEPT(__type) \
+ if (((esxVI_Object *)item)->_type == esxVI_Type_##__type) { \
+ return item; \
+ }
+
+
+
#define ESX_VI__TEMPLATE__DYNAMIC_CAST(__type, _accept) \
esxVI_##__type * \
esxVI_##__type##_DynamicCast(void *item) \
@@ -550,6 +557,8 @@
return NULL; \
} \
\
+ ESX_VI__TEMPLATE__DYNAMIC_CAST__ACCEPT(__type) \
+ \
_accept \
\
return NULL; \
@@ -557,13 +566,6 @@
-#define ESX_VI__TEMPLATE__DYNAMIC_CAST__ACCEPT(__type) \
- if (((esxVI_Object *)item)->_type == esxVI_Type_##__type) { \
- return item; \
- }
-
-
-
#define ESX_VI__TEMPLATE__DYNAMIC_SERIALIZE(__type, _dispatch, _serialize) \
ESX_VI__TEMPLATE__SERIALIZE_EXTRA(__type, \
ESX_VI__TEMPLATE__DISPATCH(__type, _dispatch, -1), \
--
1.7.0.4
14 years, 7 months
[libvirt] [PATCH v4] vepa: parsing for 802.1Qb{g|h} XML
by Stefan Berger
Below is David Alan's original patch with lots of changes.
In particular, it now parses the following two XML descriptions, one
for 802.1Qbg and 802.1Qbh and stored the data internally. The actual
triggering of the switch setup protocol has not been implemented
here but the relevant code to do that should go into the functions
associatePortProfileId() and disassociatePortProfileId().
<interface type='direct'>
<source dev='static' mode='vepa'/>
<model type='virtio'/>
<vsi type='802.1Qbg'>
<parameters managerid='12' typeid='0x123456' typeidversion='1'
instanceid='fa9b7fff-b0a0-4893-8e0e-beef4ff18f8f'/>
</vsi>
<filterref filter='clean-traffic'/>
</interface>
<interface type='direct'>
<source dev='static' mode='vepa'/>
<model type='virtio'/>
<vsi type='802.1Qbh'>
<parameters profileid='my_profile'/>
</vsi>
</interface>
I'd suggest to use this patch as a base for triggering the setup
protocol with the 802.1Qb{g|h} switch.
Changes from V3 to V4:
- moving the associate and disassociate functions to the end of the
file for subsequent patches to easier make them generally available
for export
- passing the macvtap interface name rather than the link device since
this otherwise gives funny side effects when using netlink messages
where IFLA_IFNAME and IFLA_ADDRESS are specified and the link dev
all of a sudden gets the MAC address of the macvtap interface.
- Removing rc = -1 error indications in the case of 802.1Qbg|h setup in case
we wanted to use hook scripts for the setup and so the setup doesn't fail
here.
Changes from V2 to V3:
- if instance ID UUID is not supplied it will automatically be generated
- adapted schema to make instance ID UUID optional
- added test case
Some of the changes from V1 to V2:
- parser and XML generator have been separated into their own
functions so they can be re-used elsewhere (passthrough case
for example)
- Adapted XML parser and generator support the above shown type
(802.1Qbg, 802.1Qbh).
- Adapted schema to above XML
- Adapted test XML to above XML
- Passing through the VM's UUID which seems to be necessary for
802.1Qbh -- sorry no host UUID
- adding virtual function ID to association function, in case it's
necessary to use (for SR-IOV)
Signed-off-by: Stefan Berger <stefanb(a)us.ibm.com>
>From a945107f047c7cd71f9c1b74fd74c47d8cdc3670 Mon Sep 17 00:00:00 2001
From: David Allan <dallan(a)redhat.com>
Date: Fri, 12 Mar 2010 13:25:04 -0500
Subject: [PATCH 1/1] POC of port profile id support
* Modified schema per DanPB's feedback
* Added test for modified schema
---
docs/schemas/domain.rng | 69 +++++++++++++
src/conf/domain_conf.c | 155
+++++++++++++++++++++++++++++++
src/conf/domain_conf.h | 35 +++++++
src/qemu/qemu_conf.c | 18 +--
src/qemu/qemu_conf.h | 5 -
src/qemu/qemu_driver.c | 17 +--
src/util/macvtap.c | 165
+++++++++++++++++++++++++++++----
src/util/macvtap.h | 10 +-
tests/domainschemadata/portprofile.xml | 36 +++++++
9 files changed, 460 insertions(+), 50 deletions(-)
create mode 100644 tests/domainschemadata/portprofile.xml
Index: libvirt-acl/docs/schemas/domain.rng
===================================================================
--- libvirt-acl.orig/docs/schemas/domain.rng
+++ libvirt-acl/docs/schemas/domain.rng
@@ -817,6 +817,9 @@
</optional>
<empty/>
</element>
+ <optional>
+ <ref name="vsiProfile"/>
+ </optional>
<ref name="interface-options"/>
</interleave>
</group>
@@ -902,6 +905,45 @@
</optional>
</interleave>
</define>
+ <define name="vsiProfile">
+ <choice>
+ <group>
+ <element name="vsi">
+ <attribute name="type">
+ <value>802.1Qbg</value>
+ </attribute>
+ <element name="parameters">
+ <attribute name="managerid">
+ <ref name="uint8range"/>
+ </attribute>
+ <attribute name="typeid">
+ <ref name="uint24range"/>
+ </attribute>
+ <attribute name="typeidversion">
+ <ref name="uint8range"/>
+ </attribute>
+ <optional>
+ <attribute name="instanceid">
+ <ref name="UUID"/>
+ </attribute>
+ </optional>
+ </element>
+ </element>
+ </group>
+ <group>
+ <element name="vsi">
+ <attribute name="type">
+ <value>802.1Qbh</value>
+ </attribute>
+ <element name="parameters">
+ <attribute name="profileid">
+ <ref name="vsiProfileID"/>
+ </attribute>
+ </element>
+ </element>
+ </group>
+ </choice>
+ </define>
<!--
An emulator description is just a path to the binary used for the
task
-->
@@ -1769,4 +1811,31 @@
<param name="pattern">[a-zA-Z0-9_\.:]+</param>
</data>
</define>
+ <define name="uint8range">
+ <choice>
+ <data type="string">
+ <param name="pattern">0x[0-9a-fA-F]{1,2}</param>
+ </data>
+ <data type="int">
+ <param name="minInclusive">0</param>
+ <param name="maxInclusive">255</param>
+ </data>
+ </choice>
+ </define>
+ <define name="uint24range">
+ <choice>
+ <data type="string">
+ <param name="pattern">0x[0-9a-fA-F]{1,6}</param>
+ </data>
+ <data type="int">
+ <param name="minInclusive">0</param>
+ <param name="maxInclusive">16777215</param>
+ </data>
+ </choice>
+ </define>
+ <define name="vsiProfileID">
+ <data type="string">
+ <param name="maxLength">39</param>
+ </data>
+ </define>
</grammar>
Index: libvirt-acl/src/conf/domain_conf.c
===================================================================
--- libvirt-acl.orig/src/conf/domain_conf.c
+++ libvirt-acl/src/conf/domain_conf.c
@@ -242,6 +242,11 @@ VIR_ENUM_IMPL(virDomainNetdevMacvtap, VI
"private",
"bridge")
+VIR_ENUM_IMPL(virVSI, VIR_VSI_TYPE_LAST,
+ "none",
+ "802.1Qbg",
+ "802.1Qbh")
+
VIR_ENUM_IMPL(virDomainClockOffset, VIR_DOMAIN_CLOCK_OFFSET_LAST,
"utc",
"localtime",
@@ -1807,6 +1812,145 @@ isValidIfname(const char *ifname) {
}
+static void
+virVSIProfileDefParseXML(xmlNodePtr node,
+ virVSIProfileDefPtr vsi)
+{
+ char *vsiType;
+ char *vsiManagerID = NULL;
+ char *vsiTypeID = NULL;
+ char *vsiTypeIDVersion = NULL;
+ char *vsiInstanceID = NULL;
+ char *vsiProfileID = NULL;
+ xmlNodePtr cur = node->children;
+
+ vsiType = virXMLPropString(node, "type");
+ if (!vsiType)
+ return;
+
+ while (cur != NULL) {
+ if (xmlStrEqual(cur->name, BAD_CAST "parameters")) {
+
+ vsiManagerID = virXMLPropString(cur, "managerid");
+ vsiTypeID = virXMLPropString(cur, "typeid");
+ vsiTypeIDVersion = virXMLPropString(cur, "typeidversion");
+ vsiInstanceID = virXMLPropString(cur, "instanceid");
+ vsiProfileID = virXMLPropString(cur, "profileid");
+
+ break;
+ }
+
+ cur = cur->next;
+ }
+
+ vsi->vsiType = VIR_VSI_NONE;
+
+ switch (virVSITypeFromString(vsiType)) {
+
+ case VIR_VSI_8021QBG:
+ if (vsiManagerID != NULL && vsiTypeID != NULL &&
+ vsiTypeIDVersion != NULL) {
+ unsigned int val;
+
+ if ((virStrToLong_ui(vsiManagerID, NULL, 10, &val) &&
+ virStrToLong_ui(vsiManagerID, NULL, 16, &val) ) ||
+ val > 0xff)
+ break;
+
+ vsi->u.vsi8021Qbg.managerID = (uint8_t)val;
+
+ if ((virStrToLong_ui(vsiTypeID, NULL, 10, &val) &&
+ virStrToLong_ui(vsiTypeID, NULL, 16, &val) ) ||
+ val > 0xffffff)
+ break;
+
+ vsi->u.vsi8021Qbg.typeID = (uint32_t)val;
+
+ if ((virStrToLong_ui(vsiTypeIDVersion, NULL, 10, &val) &&
+ virStrToLong_ui(vsiTypeIDVersion, NULL, 16, &val) )
||
+ val > 0xff)
+ break;
+
+ vsi->u.vsi8021Qbg.typeIDVersion = (uint8_t)val;
+
+ if (vsiInstanceID != NULL) {
+ if (virUUIDParse(vsiInstanceID,
vsi->u.vsi8021Qbg.instanceID))
+ break;
+ } else {
+ if (virUUIDGenerate(vsi->u.vsi8021Qbg.instanceID))
+ break;
+ }
+
+ vsi->vsiType = VIR_VSI_8021QBG;
+ }
+ break;
+
+ case VIR_VSI_8021QBH:
+ if (vsiProfileID != NULL) {
+ if (virStrcpyStatic(vsi->u.vsi8021Qbh.profileID,
+ vsiProfileID) != NULL)
+ vsi->vsiType = VIR_VSI_8021QBH;
+ }
+ break;
+
+
+ default:
+ case VIR_VSI_NONE:
+ case VIR_VSI_TYPE_LAST:
+ break;
+ }
+
+ VIR_FREE(vsiManagerID);
+ VIR_FREE(vsiTypeID);
+ VIR_FREE(vsiTypeIDVersion);
+ VIR_FREE(vsiInstanceID);
+ VIR_FREE(vsiProfileID);
+ VIR_FREE(vsiType);
+}
+
+
+static void
+virVSIProfileFormat(virBufferPtr buf, virVSIProfileDefPtr vsi,
+ const char *indent)
+{
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+
+ if (vsi->vsiType == VIR_VSI_NONE)
+ return;
+
+ virBufferVSprintf(buf, "%s<vsi type='%s'>\n",
+ indent, virVSITypeToString(vsi->vsiType));
+
+ switch (vsi->vsiType) {
+ case VIR_VSI_NONE:
+ case VIR_VSI_TYPE_LAST:
+ break;
+
+ case VIR_VSI_8021QBG:
+ virUUIDFormat(vsi->u.vsi8021Qbg.instanceID,
+ uuidstr);
+ virBufferVSprintf(buf,
+ "%s <parameters managerid='%d' typeid='%d' "
+ "typeidversion='%d' instanceid='%s'/>\n",
+ indent,
+ vsi->u.vsi8021Qbg.managerID,
+ vsi->u.vsi8021Qbg.typeID,
+ vsi->u.vsi8021Qbg.typeIDVersion,
+ uuidstr);
+ break;
+
+ case VIR_VSI_8021QBH:
+ virBufferVSprintf(buf,
+ "%s <parameters profileid='%s'/>\n",
+ indent,
+ vsi->u.vsi8021Qbh.profileID);
+ break;
+ }
+
+ virBufferVSprintf(buf, "%s</vsi>\n", indent);
+}
+
+
/* Parse the XML definition for a network interface
* @param node XML nodeset to parse for net definition
* @return 0 on success, -1 on failure
@@ -1832,6 +1976,8 @@ virDomainNetDefParseXML(virCapsPtr caps,
char *devaddr = NULL;
char *mode = NULL;
virNWFilterHashTablePtr filterparams = NULL;
+ virVSIProfileDef vsi;
+ bool vsiParsed = false;
if (VIR_ALLOC(def) < 0) {
virReportOOMError();
@@ -1873,6 +2019,11 @@ virDomainNetDefParseXML(virCapsPtr caps,
xmlStrEqual(cur->name, BAD_CAST "source")) {
dev = virXMLPropString(cur, "dev");
mode = virXMLPropString(cur, "mode");
+ } else if ((vsiParsed == false) &&
+ (def->type == VIR_DOMAIN_NET_TYPE_DIRECT) &&
+ xmlStrEqual(cur->name, BAD_CAST "vsi")) {
+ virVSIProfileDefParseXML(cur, &vsi);
+ vsiParsed = true;
} else if ((network == NULL) &&
((def->type == VIR_DOMAIN_NET_TYPE_SERVER) ||
(def->type == VIR_DOMAIN_NET_TYPE_CLIENT) ||
@@ -2050,6 +2201,8 @@ virDomainNetDefParseXML(virCapsPtr caps,
} else
def->data.direct.mode =
VIR_DOMAIN_NETDEV_MACVTAP_MODE_VEPA;
+ def->data.direct.vsiProfile = vsi;
+
def->data.direct.linkdev = dev;
dev = NULL;
@@ -5142,6 +5295,8 @@ virDomainNetDefFormat(virBufferPtr buf,
virBufferVSprintf(buf, " mode='%s'",
virDomainNetdevMacvtapTypeToString(def->data.direct.mode));
virBufferAddLit(buf, "/>\n");
+ virVSIProfileFormat(buf, &def->data.direct.vsiProfile,
+ " ");
break;
case VIR_DOMAIN_NET_TYPE_USER:
Index: libvirt-acl/src/conf/domain_conf.h
===================================================================
--- libvirt-acl.orig/src/conf/domain_conf.h
+++ libvirt-acl/src/conf/domain_conf.h
@@ -259,6 +259,39 @@ enum virDomainNetdevMacvtapType {
};
+enum virVSIType {
+ VIR_VSI_NONE,
+ VIR_VSI_8021QBG,
+ VIR_VSI_8021QBH,
+
+ VIR_VSI_TYPE_LAST,
+};
+
+# ifdef IFLA_VF_PORT_PROFILE_MAX
+# define LIBVIRT_IFLA_VF_PORT_PROFILE_MAX IFLA_VF_PORT_PROFILE_MAX
+# else
+# define LIBVIRT_IFLA_VF_PORT_PROFILE_MAX 40
+# endif
+
+/* profile data for macvtap (VEPA) */
+typedef struct _virVSIProfileDef virVSIProfileDef;
+typedef virVSIProfileDef *virVSIProfileDefPtr;
+struct _virVSIProfileDef {
+ enum virVSIType vsiType;
+ union {
+ struct {
+ uint8_t managerID;
+ uint32_t typeID; // 24 bit valid
+ uint8_t typeIDVersion;
+ unsigned char instanceID[VIR_UUID_BUFLEN];
+ } vsi8021Qbg;
+ struct {
+ char profileID[LIBVIRT_IFLA_VF_PORT_PROFILE_MAX];
+ } vsi8021Qbh;
+ } u;
+};
+
+
/* Stores the virtual network interface configuration */
typedef struct _virDomainNetDef virDomainNetDef;
typedef virDomainNetDef *virDomainNetDefPtr;
@@ -290,6 +323,7 @@ struct _virDomainNetDef {
struct {
char *linkdev;
int mode;
+ virVSIProfileDef vsiProfile;
} direct;
} data;
char *ifname;
@@ -1089,6 +1123,7 @@ VIR_ENUM_DECL(virDomainSeclabel)
VIR_ENUM_DECL(virDomainClockOffset)
VIR_ENUM_DECL(virDomainNetdevMacvtap)
+VIR_ENUM_DECL(virVSI)
VIR_ENUM_DECL(virDomainTimerName)
VIR_ENUM_DECL(virDomainTimerTrack)
Index: libvirt-acl/src/util/macvtap.c
===================================================================
--- libvirt-acl.orig/src/util/macvtap.c
+++ libvirt-acl/src/util/macvtap.c
@@ -43,6 +43,7 @@
# include "util.h"
# include "memory.h"
+# include "logging.h"
# include "macvtap.h"
# include "interface.h"
# include "conf/domain_conf.h"
@@ -57,6 +58,19 @@
# define MACVTAP_NAME_PREFIX "macvtap"
# define MACVTAP_NAME_PATTERN "macvtap%d"
+
+static int associatePortProfileId(const char *linkdev,
+ const unsigned char *mac,
+ int mode,
+ const virVSIProfileDefPtr vsi,
+ int vf,
+ const unsigned char *vmuuid);
+
+static int disassociatePortProfileId(const char *linkdev,
+ const unsigned char *mac,
+ const virVSIProfileDefPtr vsi);
+
+
static int nlOpen(void)
{
int fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
@@ -567,39 +581,38 @@ configMacvtapTap(int tapfd, int vnet_hdr
return 0;
}
-
-
/**
* openMacvtapTap:
* Create an instance of a macvtap device and open its tap character
* device.
* @tgifname: Interface name that the macvtap is supposed to have. May
* be NULL if this function is supposed to choose a name
- * @macaddress: The MAC address for the macvtap device
- * @linkdev: The interface name of the NIC to connect to the external
bridge
- * @mode_str: String describing the mode. Valid are 'bridge', 'vepa'
and
- * 'private'.
+ * @net: pointer to the virDomainNetDef object describing the direct
+ * type if an interface
* @res_ifname: Pointer to a string pointer where the actual name of
the
* interface will be stored into if everything succeeded. It is up
* to the caller to free the string.
+ * @vnet_hdr: Whether to enable IFF_VNET_HDR on the interface
+ * @vmuuid: The (raw) UUID of the VM
*
* Returns file descriptor of the tap device in case of success,
* negative value otherwise with error reported.
*
+ * Open a macvtap device and trigger the switch setup protocol
+ * if valid port profile parameters were provided.
*/
int
openMacvtapTap(const char *tgifname,
- const unsigned char *macaddress,
- const char *linkdev,
- int mode,
+ virDomainNetDefPtr net,
char **res_ifname,
- int vnet_hdr)
+ int vnet_hdr,
+ const unsigned char *vmuuid)
{
const char *type = "macvtap";
int c, rc;
char ifname[IFNAMSIZ];
int retries, do_retry = 0;
- uint32_t macvtapMode = macvtapModeFromInt(mode);
+ uint32_t macvtapMode = macvtapModeFromInt(net->data.direct.mode);
const char *cr_ifname;
int ifindex;
@@ -616,7 +629,7 @@ openMacvtapTap(const char *tgifname,
return -1;
}
cr_ifname = tgifname;
- rc = link_add(type, macaddress, 6, tgifname, linkdev,
+ rc = link_add(type, net->mac, 6, tgifname,
net->data.direct.linkdev,
macvtapMode, &do_retry);
if (rc)
return -1;
@@ -626,7 +639,8 @@ create_name:
for (c = 0; c < 8192; c++) {
snprintf(ifname, sizeof(ifname), MACVTAP_NAME_PATTERN, c);
if (ifaceGetIndex(false, ifname, &ifindex) == ENODEV) {
- rc = link_add(type, macaddress, 6, ifname, linkdev,
+ rc = link_add(type, net->mac, 6, ifname,
+ net->data.direct.linkdev,
macvtapMode, &do_retry);
if (rc == 0)
break;
@@ -639,6 +653,15 @@ create_name:
cr_ifname = ifname;
}
+ rc = associatePortProfileId(cr_ifname,
+ net->mac,
+ net->data.direct.mode,
+ &net->data.direct.vsiProfile,
+ -1,
+ vmuuid);
+ if (rc != 0)
+ goto link_del_exit;
+
rc = ifaceUp(cr_ifname);
if (rc != 0) {
virReportSystemError(errno,
@@ -647,7 +670,7 @@ create_name:
"MAC address"),
cr_ifname);
rc = -1;
- goto link_del_exit;
+ goto disassociate_exit;
}
rc = openTap(cr_ifname, 10);
@@ -656,14 +679,19 @@ create_name:
if (configMacvtapTap(rc, vnet_hdr) < 0) {
close(rc);
rc = -1;
- goto link_del_exit;
+ goto disassociate_exit;
}
*res_ifname = strdup(cr_ifname);
} else
- goto link_del_exit;
+ goto disassociate_exit;
return rc;
+disassociate_exit:
+ disassociatePortProfileId(cr_ifname,
+ net->mac,
+ &net->data.direct.vsiProfile);
+
link_del_exit:
link_del(cr_ifname);
@@ -673,14 +701,111 @@ link_del_exit:
/**
* delMacvtap:
- * @ifname : The name of the macvtap interface
+ * @net: pointer to virDomainNetDef object
*
- * Delete an interface given its name.
+ * Delete an interface given its name. Disassociate
+ * it with the switch if port profile parameters
+ * were provided.
*/
void
-delMacvtap(const char *ifname)
+delMacvtap(virDomainNetDefPtr net)
{
- link_del(ifname);
+ if (net->ifname) {
+ disassociatePortProfileId(net->ifname,
+ net->mac,
+ &net->data.direct.vsiProfile);
+ link_del(net->ifname);
+ }
}
#endif
+
+
+/**
+ * associatePortProfile
+ *
+ * @macvtap_ifname: The name of the macvtap device
+ * @mac: the MAC address of the interface
+ * @mode: The vepa mode (private, bridge or vepa)
+ * @vsi: pointer to the object holding port profile parameters
+ * @vf: virtual function number, -1 if to be ignored
+ * @vmuuid : the UUID of the virtual machine
+ *
+ * Associate a port on a swtich with a profile. This function
+ * may notify a kernel driver or an external daemon to run
+ * the setup protocol. If profile parameters were not supplied
+ * by the user, then this function returns without doing
+ * anything.
+ *
+ * Returns 0 in case of success, != 0 otherwise with error
+ * having been reported.
+ */
+static int
+associatePortProfileId(const char *macvtap_ifname,
+ const unsigned char *mac,
+ int mode,
+ const virVSIProfileDefPtr vsi,
+ int vf,
+ const unsigned char *vmuuid)
+{
+ int rc = 0;
+ VIR_DEBUG("Associating port profile '%p' on link device '%s' mode %
d ",
+ vsi, macvtap_ifname, mode);
+ (void)mac;
+ (void)vf;
+ (void)vmuuid;
+
+ switch (vsi->vsiType) {
+ case VIR_VSI_NONE:
+ case VIR_VSI_TYPE_LAST:
+ break;
+
+ case VIR_VSI_8021QBG:
+
+ break;
+
+ case VIR_VSI_8021QBH:
+
+ break;
+ }
+
+ return rc;
+}
+
+
+/**
+ * disassociatePortProfile
+ *
+ * @macvtap_ifname: The name of the macvtap device
+ * @mac: The MAC address of the interface
+ * @vsi: point to object holding port profile parameters
+ *
+ * Returns 0 in case of success, != 0 otherwise with error
+ * having been reported.
+ */
+static int
+disassociatePortProfileId(const char *macvtap_ifname,
+ const unsigned char *mac,
+ const virVSIProfileDefPtr vsi)
+{
+ int rc = 0;
+ VIR_DEBUG("Disassociating port profile id '%p' on link device '%s'
",
+ vsi, macvtap_ifname);
+ (void)mac;
+
+ switch (vsi->vsiType) {
+ case VIR_VSI_NONE:
+ case VIR_VSI_TYPE_LAST:
+ break;
+
+ case VIR_VSI_8021QBG:
+
+ break;
+
+ case VIR_VSI_8021QBH:
+
+ break;
+ }
+
+ return rc;
+}
Index: libvirt-acl/src/util/macvtap.h
===================================================================
--- libvirt-acl.orig/src/util/macvtap.h
+++ libvirt-acl/src/util/macvtap.h
@@ -27,15 +27,15 @@
# if defined(WITH_MACVTAP)
# include "internal.h"
+# include "conf/domain_conf.h"
int openMacvtapTap(const char *ifname,
- const unsigned char *macaddress,
- const char *linkdev,
- int mode,
+ virDomainNetDefPtr net,
char **res_ifname,
- int vnet_hdr);
+ int vnet_hdr,
+ const unsigned char *vmuuid);
-void delMacvtap(const char *ifname);
+void delMacvtap(virDomainNetDefPtr net);
# endif /* WITH_MACVTAP */
Index: libvirt-acl/tests/domainschemadata/portprofile.xml
===================================================================
--- /dev/null
+++ libvirt-acl/tests/domainschemadata/portprofile.xml
@@ -0,0 +1,36 @@
+<domain type='lxc'>
+ <name>portprofile</name>
+ <uuid>00000000-0000-0000-0000-000000000000</uuid>
+ <memory>1048576</memory>
+ <os>
+ <type>exe</type>
+ <init>/sh</init>
+ </os>
+ <devices>
+ <interface type='direct'>
+ <source dev='eth0' mode='vepa'/>
+ <vsi type='802.1Qbg'>
+ <parameters managerid='12' typeid='1193046' typeidversion='1'
+ instanceid='fa9b7fff-b0a0-4893-8e0e-beef4ff18f8f'/>
+ </vsi>
+ </interface>
+ <interface type='direct'>
+ <source dev='eth0' mode='vepa'/>
+ <vsi type='802.1Qbg'>
+ <parameters managerid='12' typeid='1193046' typeidversion='1'/>
+ </vsi>
+ </interface>
+ <interface type='direct'>
+ <source dev='eth0' mode='vepa'/>
+ <vsi type='802.1Qbh'>
+ <parameters profileid='my_profile'/>
+ </vsi>
+ </interface>
+ <interface type='direct'>
+ <source dev='eth0' mode='vepa'/>
+ </interface>
+ <interface type='direct'>
+ <source dev='eth0' mode='vepa'/>
+ </interface>
+ </devices>
+</domain>
Index: libvirt-acl/src/qemu/qemu_conf.h
===================================================================
--- libvirt-acl.orig/src/qemu/qemu_conf.h
+++ libvirt-acl/src/qemu/qemu_conf.h
@@ -271,9 +271,8 @@ qemudOpenVhostNet(virDomainNetDefPtr net
int qemudPhysIfaceConnect(virConnectPtr conn,
struct qemud_driver *driver,
virDomainNetDefPtr net,
- char *linkdev,
- int brmode,
- unsigned long long qemuCmdFlags);
+ unsigned long long qemuCmdFlags,
+ const unsigned char *vmuuid);
int qemudProbeMachineTypes (const char *binary,
virCapsGuestMachinePtr
**machines,
Index: libvirt-acl/src/qemu/qemu_driver.c
===================================================================
--- libvirt-acl.orig/src/qemu/qemu_driver.c
+++ libvirt-acl/src/qemu/qemu_driver.c
@@ -3694,10 +3694,8 @@ static void qemudShutdownVMDaemon(struct
def = vm->def;
for (i = 0; i < def->nnets; i++) {
virDomainNetDefPtr net = def->nets[i];
- if (net->type == VIR_DOMAIN_NET_TYPE_DIRECT) {
- if (net->ifname)
- delMacvtap(net->ifname);
- }
+ if (net->type == VIR_DOMAIN_NET_TYPE_DIRECT)
+ delMacvtap(net);
}
#endif
@@ -7341,9 +7339,8 @@ static int qemudDomainAttachNetDevice(vi
}
if ((tapfd = qemudPhysIfaceConnect(conn, driver, net,
- net->data.direct.linkdev,
- net->data.direct.mode,
- qemuCmdFlags)) < 0)
+ qemuCmdFlags,
+ vm->def->uuid)) < 0)
return -1;
}
@@ -8386,10 +8383,8 @@ qemudDomainDetachNetDevice(struct qemud_
virNWFilterTearNWFilter(detach);
#if WITH_MACVTAP
- if (detach->type == VIR_DOMAIN_NET_TYPE_DIRECT) {
- if (detach->ifname)
- delMacvtap(detach->ifname);
- }
+ if (detach->type == VIR_DOMAIN_NET_TYPE_DIRECT)
+ delMacvtap(detach);
#endif
if ((driver->macFilter) && (detach->ifname != NULL)) {
Index: libvirt-acl/src/qemu/qemu_conf.c
===================================================================
--- libvirt-acl.orig/src/qemu/qemu_conf.c
+++ libvirt-acl/src/qemu/qemu_conf.c
@@ -1465,9 +1465,8 @@ int
qemudPhysIfaceConnect(virConnectPtr conn,
struct qemud_driver *driver,
virDomainNetDefPtr net,
- char *linkdev,
- int brmode,
- unsigned long long qemuCmdFlags)
+ unsigned long long qemuCmdFlags,
+ const unsigned char *vmuuid)
{
int rc;
#if WITH_MACVTAP
@@ -1479,8 +1478,7 @@ qemudPhysIfaceConnect(virConnectPtr conn
net->model && STREQ(net->model, "virtio"))
vnet_hdr = 1;
- rc = openMacvtapTap(net->ifname, net->mac, linkdev, brmode,
- &res_ifname, vnet_hdr);
+ rc = openMacvtapTap(net->ifname, net, &res_ifname, vnet_hdr,
vmuuid);
if (rc >= 0) {
VIR_FREE(net->ifname);
net->ifname = res_ifname;
@@ -1500,17 +1498,16 @@ qemudPhysIfaceConnect(virConnectPtr conn
if (err) {
close(rc);
rc = -1;
- delMacvtap(net->ifname);
+ delMacvtap(net);
}
}
}
#else
(void)conn;
(void)net;
- (void)linkdev;
- (void)brmode;
(void)qemuCmdFlags;
(void)driver;
+ (void)vmuuid;
qemuReportError(VIR_ERR_INTERNAL_ERROR,
"%s", _("No support for macvtap device"));
rc = -1;
@@ -4130,9 +4127,8 @@ int qemudBuildCommandLine(virConnectPtr
goto no_memory;
} else if (net->type == VIR_DOMAIN_NET_TYPE_DIRECT) {
int tapfd = qemudPhysIfaceConnect(conn, driver, net,
-
net->data.direct.linkdev,
-
net->data.direct.mode,
- qemuCmdFlags);
+ qemuCmdFlags,
+ def->uuid);
if (tapfd < 0)
goto error;
14 years, 7 months
[libvirt] [PATCH] qemudDomainMigrateFinish2: handle a case of virDomainSaveStatus failure
by Jim Meyering
This is very similar to ones I fixed yesterday.
The difference is that I'm adding ATTRIBUTE_RETURN_CHECK, now.
Here, it's easy, since the function is private.
>From cfce459e9aebae840356e62473f550f358834f30 Mon Sep 17 00:00:00 2001
From: Jim Meyering <meyering(a)redhat.com>
Date: Wed, 19 May 2010 17:48:03 +0200
Subject: [PATCH] qemudDomainMigrateFinish2: handle a case of virDomainSaveStatus failure
* src/qemu/qemu_driver.c (qemudDomainMigrateFinish2): Don't ignore
virDomainSaveStatus failure.
* src/conf/domain_conf.h (virDomainSaveStatus): Use
ATTRIBUTE_RETURN_CHECK, so this doesn't happen again.
---
src/conf/domain_conf.h | 2 +-
src/qemu/qemu_driver.c | 5 ++++-
2 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index fadc8bd..a7206d3 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -1011,7 +1011,7 @@ int virDomainSaveConfig(const char *configDir,
virDomainDefPtr def);
int virDomainSaveStatus(virCapsPtr caps,
const char *statusDir,
- virDomainObjPtr obj);
+ virDomainObjPtr obj) ATTRIBUTE_RETURN_CHECK;
typedef void (*virDomainLoadConfigNotify)(virDomainObjPtr dom,
int newDomain,
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 65ca117..a519c02 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -10816,7 +10816,10 @@ qemudDomainMigrateFinish2 (virConnectPtr dconn,
VIR_DOMAIN_EVENT_SUSPENDED,
VIR_DOMAIN_EVENT_SUSPENDED_PAUSED);
}
- virDomainSaveStatus(driver->caps, driver->stateDir, vm);
+ if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0) {
+ VIR_WARN("Failed to save status on vm %s", vm->def->name);
+ goto endjob;
+ }
} else {
qemudShutdownVMDaemon(driver, vm, 0);
event = virDomainEventNewFromObj(vm,
--
1.7.1.259.g3aef8
14 years, 7 months
[libvirt] Problems with pdwtags on Ubuntu 10.04
by Matthias Bolte
The "help avoid accidental remote_protocol.x changes" commit 180d4b2b
added a make check rule that tried using pdwtags from the dwarves
package to protect against accidental remote_protocol.x changes.
I installed dwarves package on Ubuntu 10.04 and make check fails for me now.
The temporary file remote_protocol-structs-t is empty for me. It seems
that pdwtags doesn't output the expected format for the embedded perl
script. pdwtags output doesn't contain /* DD */ comments between the
structs. A snippet from the pdwtags output looks like this:
struct remote_nonnull_network {
remote_nonnull_string name; /* 0 8 */
remote_uuid uuid; /* 8 16 */
/* size: 24, cachelines: 1 */
/* last cacheline: 24 bytes */
};
typedef struct remote_nonnull_network remote_nonnull_network;
struct remote_nonnull_nwfilter {
remote_nonnull_string name; /* 0 8 */
remote_uuid uuid; /* 8 16 */
/* size: 24, cachelines: 1 */
/* last cacheline: 24 bytes */
};
typedef struct remote_nonnull_nwfilter remote_nonnull_nwfilter;
If i run pdwtags with the --verbose flag then the output looks like this:
/* <44e> remote/remote_protocol.h:71 */
typedef struct remote_nonnull_domain remote_nonnull_domain;
/* <459> remote/remote_protocol.h:73 */
struct remote_nonnull_network {
remote_nonnull_string name; /* 0 8 */
remote_uuid uuid; /* 8 16 */
/* size: 24, cachelines: 1 */
/* last cacheline: 24 bytes */
};
/* <482> remote/remote_protocol.h:77 */
typedef struct remote_nonnull_network remote_nonnull_network;
/* <48d> remote/remote_protocol.h:79 */
struct remote_nonnull_nwfilter {
remote_nonnull_string name; /* 0 8 */
remote_uuid uuid; /* 8 16 */
/* size: 24, cachelines: 1 */
/* last cacheline: 24 bytes */
};
/* <4b6> remote/remote_protocol.h:83 */
typedef struct remote_nonnull_nwfilter remote_nonnull_nwfilter;
Now there are "markers" that can be used for splitting, but they still
differ from the expected format.
The attached patch fixes this issue for me on Ubuntu, but I doubt that
this can be the general solution.
Matthias
14 years, 7 months