[libvirt] Live Migration with non-shared storage for kvm
by Kenneth Nagin
On Wed Apr 07 I sent an email with a patch titled Live Migration with
non-shared storage for kvm. What is the status on the patch?
Kenneth Nagin
Ph: +972-4-8296227
Cell: 054-6976227
Fx: +972-4- 8296113
"Do not look back in anger, or forward in fear, but around in awareness."
--James Thurber
14 years, 6 months
[libvirt] [PATCH 0/2][RESEND] Fix problems on using lxc with cgroup ns subsystem
by Ryota Ozaki
The patch set fixes two problems of lxc that happen when ns
subsystem is enabled with memory subsystem at the same time.
The fist problem is that cgroup subdirectories that are
automatically created by ns subsystem remain after domain
shutdown. The second problem is that memory usage is not
properly accounted.
Ryota Ozaki (2):
cgroup: Change virCgroupRemove to remove all child groups at first
cgroup: Enable memory.use_hierarchy of cgroup for domain
14 years, 6 months
[libvirt] Don't add iptables rules when creating networks
by Felix Schwarz
Hi,
I just found out that libvirt always add some iptables rules if it creates a
natted (or routed) network. There were a couple of mailing list posts about
this so I'm pretty sure this is not news to you.
I don't want to go into the debate if your approach is sensible or not (I
guess there are some use cases where I kind of like it). However on my server
machine I really need full control over my (rather complicated) firewall
settings.
Currently the newly added rules really create a lot of problems for me. For
example if I manage to have a good configuration after startup and then start
a libvirt network afterwards, it will inject its rules at the start of the
FORWARD queue (even though the same parameters are already present at the
end!). On every net start there will be more duplicated rules and they will
take preference over my existing rules.
Besides that specific issue I think this is only one tiny problem compared to
others (central configuration of firewall rules, auditing requirements, ...).
Therefore I would like to have some kind 'power user' flag that prevents
libvirt from adding any filter rules. I'm fine with activating it manually as
long as I don't have to patch libvirt.
fs
14 years, 6 months
[libvirt] [PATCH] Correct two memory leaks triggered by udev events
by Nigel Jones
Hi List,
Please find below a patch that should correct two memory leaks within
the udev device handling code.
The issue is triggered by 'add' udev calls and will slowly cause
libvirtd to consume the majority of system memory.
The first part of the patch deals with udevAddOneDevice() and frees
the memory allocated to 'def' if the function would return -1 (an
error condition) due to the inability to look up udev properties (for
example, if the udev device is already removed).
The second part of the patch deals with a remaining 8kB/cycle memory
leak, in which the udev device reference isn't released at the end of
running udevEventHandleCallback().
I'm happy to answer any questions about the patch, there is also a bit
more background at
https://bugs.launchpad.net/ubuntu/+source/libvirt/+bug/571093
---
>From 6c8183e83fbfeb031b16cf9ae2d41b16e3145378 Mon Sep 17 00:00:00 2001
From: Nigel Jones <dev(a)nigelj.com>
Date: Mon, 24 May 2010 15:05:53 +0000
Subject: [PATCH] Patch 2 memory leaks.
1. Ensure that memory is free'd from udevAddOneDevice() if the return
value will be non-zero
2. Release udev device reference in udevEventHandleCallback()
similar to the release of the reference in udevProcessDeviceListEntry()
---
src/node_device/node_device_udev.c | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)
diff --git a/src/node_device/node_device_udev.c
b/src/node_device/node_device_udev.c
index a1ced87..4d0effa 100644
--- a/src/node_device/node_device_udev.c
+++ b/src/node_device/node_device_udev.c
@@ -1296,6 +1296,9 @@ static int udevAddOneDevice(struct udev_device *device)
ret = 0;
out:
+ if (ret != 0) {
+ virNodeDeviceDefFree(def); /* Free assigned memory to prevent leaks */
+ }
return ret;
}
@@ -1426,6 +1429,7 @@ static void udevEventHandleCallback(int watch
ATTRIBUTE_UNUSED,
}
out:
+ udev_device_unref(device);
return;
}
--
1.7.0.4
14 years, 6 months
[libvirt] [PATCH] 0/10AppArmor driver updates
by Jamie Strandboge
This patch series addresses bug fixes in the AppArmor driver as well as
updating it to changes made in 0.7.6 and 0.7.7. All of these are
self-contained within the driver except 4_qemu_driver_stdin_path.patch.
This is required by 5_apparmor-fix-save-restore.patch (see below). These
all pass 'make syntax-check' and 'make check' (except 'daemon-conf',
which has never passed here and I didn't patch it).
1_apparmor-dont-clear-caps.patch: originally submitted on 2010/02/08
with no feedback. The calls to virExec() in security_apparmor.c when
invoking virt-aa-helper use VIR_EXEC_CLEAR_CAPS. When compiled without
libcap-ng, this is not a problem (it's effectively a no-op) but with
libcap-ng this causes MAC_ADMIN to be cleared. MAC_ADMIN is needed by
virt-aa-helper to manipulate apparmor profiles and without it VMs will
not start[1]. This patch calls virExec with the default VIR_EXEC_NONE
instead.
2_apparmor-remove-unloaded-profile-is-not-fatal.patch: Don't exit with
error if the user unloaded the profile outside of libvirt[2]
3_apparmor-fix-vah-xml-parse.patch: add VIR_DOMAIN_XML_INACTIVE flag to
virDomainDefParseString() so virDomainDefParseString() doesn't error out
when seeing <seclabel...>. This was needed due to changes since 0.7.5.
4_qemu_driver_stdin_path.patch: adjust args to qemudStartVMDaemon() to
also specify path to stdin_fd, so this can be passed to the AppArmor
driver via *SetSecurityAllLabel(). This updates all calls to
qemudStartVMDaemon() as well as setting up the non-AppArmor security
driver *SetSecurityAllLabel() declarations for the above. This is
required for 5_apparmor-fix-save-restore.patch since AppArmor resolves
the passed file descriptor to the pathname given to open().
5_apparmor-fix-save-restore.patch: refactoring to update AppArmor
security driver to adjust profile for save/restore[3]
6_apparmor-fix-backingstore.patch: adjust virt-aa-helper to handle
backing store[4]
7_apparmor-fix-hostdev.patch: adjust virt-aa-helper to handle pci
devices. Update valid_path() to have an override array to check against,
and add "/sys/devices/pci" to it. Then rename file_iterate_cb() to
file_iterate_hostdev_cb() and create file_iterate_pci_cb() based on it.
8_apparmor-fix-xauth.patch: adjust virt-aa-helper to handle SDL
graphics, specifically Xauthority[6]. Also remove a couple redundant
checks
9_apparmor-examples.patch: adjustments to the example profiles
10_apparmor-vah-test.patch: update pcidev test and add SDL xauth
[1] https://launchpad.net/bugs/517714
[2] https://launchpad.net/bugs/530400
[3] https://launchpad.net/bugs/457716
[4] https://launchpad.net/bugs/470636
[5] https://launchpad.net/bugs/545795
[6] https://launchpad.net/bugs/545426
--
Jamie Strandboge | http://www.canonical.com
14 years, 6 months
[libvirt] Draft of pre migration checks framework
by Paolo Smiraglia
Hi guys, I'm working on a pre migration checks implementation.
The patch files attached provide a framework to execute
pre-migration-checks before the domain migration.
================================================================
1 - FRAMEWORK OVERVIEW
================================================================
Pre-Migration-Checks are enabled by adding a "--pmc" option in
"virsh migrate" command
$ virsh migrate --pmc ...
In this way, before the execution of function virDomainMigrate(),
an array of "checks" are performed. Return value of every check
set if the migration will continue or not.
================================================================
2 - FRAMEWORK STRUCTURE
================================================================
Every check is defined in the file
libvirt/src/util/pmc.c
Check list is defined by object "chklist". This is a struct
defined as
static virPMCCheckList chklist = {
.count = 2,
.check = {&chk1,&chk2,NULL}
};
where "count" define the current array size, and "check" is an
array of pointer to virPMCCheck object.
virPMCCheck is a stuct defined as
struct _virPMCCheck
{
const char *name;
virPMCCheckRun run;
};
where "name" is the name of the check needed for debugging
messages, and "run" is a pointer to check function.
================================================================
3 - HOW TO ADD NEW CHECK
================================================================
Adding new check is very simple! You have to define a check
funcion as
static int
pmcCheckFooCheck(virDomainPtr domain,
virConnectPtr dconn)
{
/* do something */
return CHECK_SUCCESS
}
then you have to define a "check-hook" as
static virPMCCheck chk3 = {
.name = "this is fooCheck",
.run = pmcCheckFooCheck
};
and update the object "chklist"
static virPMCCheckList chklist = {
.count = 3, /* previous value was 2 */
.check = {&chk1,&chk2,&chk3,NULL} /* previous content not
* include a pointer to
* chk3 object
*/
};
================================================================
4 - POSSIBLE ENHANCHEMENT
================================================================
1. Adding infos in _virPMCCheck struct about check security level.
Example: if a check with level CRITICAL return CHECK_FAIL,
migration process is stopped,
2. Implementing framework not as util, but as driver. For example
this can permit to define new checks by xml file.
3. Define external checks loadable by shared library.
================================================================
5 - PATCH FILE DESCRIPTION
================================================================
file: datatypes.h.patch
desc: define new type virPMCCheckRun
define struct _virPMCCheck
define struct _virPMCCheckList
file: libvirt.c.patch
desc: impement public API virDomainMigratePMC()
file: libvirt.h.in.patch
desc: impement public API virDomainMigratePMC() prototype
define type virPMCCheck
define type virPMCCheckPtr
define type virPMCCheckList
define type virPMCCheckListPtr
define macro PMC_LIST_SIZE
file: libvirt_public.syms
desc: export public API virDomainMigratePMC()
file: pmc.c.patch, pmc.h.patch
desc: define and implements pre migration checks and some auxiliary
functions.
file: virsh.c.patch
desc: add option "pmc" to virsh migrate command
================================================================
6 - NOTES
================================================================
I start to implement this framework on git sources, but the
latest sources produce a regress on my code. For this reason
I applied my code on latest stable release of libvirt (0.8.1).
What do you think about that? Is this a good approach to implement pre
migration checks? Have you a suggestions? There is a possibility to
include this patch in future libvirt distributions?
Waiting for feedback...
Paolo Smiraglia
--
PAOLO SMIRAGLIA
http://portale.isf.polito.it/paolo-smiraglia
14 years, 6 months
[libvirt] [PATCH v13] [REPOST] add 802.1Qbh and 802.1Qbg handling
by Stefan Berger
Formatting errors in the previous posting (and another problem).
This is now hopefully the final version of this patch that adds support
for configuring 802.1Qbg and 802.1Qbh switches. The 802.1Qbh part has
been successfully tested with real hardware. The 802.1Qbg part has only
been tested with a (dummy) server that 'behaves' similarly to how we
expect lldpad to 'behave'.
V13:
- Merging Scott's v13-pre1 patch
- Fixing endptr related bug while using virStrToLong_ui() pointed out
by Jim Meyering
V12:
- Addressing Jim Meyering's comments to v11
- requiring mac address to the vpDisassociateProfileId() function to
pass it further to the 802.1Qbg disassociate part (802.1Qbh untouched)
V11:
- determining pid of lldpad daemon by reading it from /var/run/libvirt.pid
(hardcode as is hardcode alson in lldpad sources)
- merging netlink send code for kernel target and user space target
(lldpad) using one function nlComm() to send the messages
- adding a select() after the sending and before the reading of the
netlink response in case lldpad doesn't respond and so we don't hang
- when reading the port status, in case of 802.1Qbg, no status may be
received while things are 'in progress' and only at the end a status
will be there.
- when reading the port status, use the given instanceId and vf to pick
the right IFLA_VF_PORT among those nested under IFLA_VF_PORTS.
V10:
- never sending nor parsing IFLA_PORT_SELF type of messages in the
802.1Qbg case
- iterating over the elements in a IFLA_VF_PORTS to pick the right
IFLA_VF_PORT by either IFLA_PORT_PROFILE and given profileId
(802.1Qbh) or IFLA_PORT_INSTANCE_UUID and given instanceId (802.1Qbg)
and reading the current status in IFLA_PORT_RESPONSE.
V9:
- recycling a previous patch that adds functionality to interface.c to
- get the vlan identifier on an interface
- get the flags of an interface and some convenience function to
check whether an interface is 'up' or not (not currently used here)
- adding function to determine the root physical interface of an
interface. For example if a macvtap is linked to eth0.100, it will
find eth0. Also adding a function that finds the vlan on the 'way to
the root physical interface'
- conveying the root physical interface name and index in case of 802.1Qbg
- conveying mac address of macvlan device and vlan identifier in
IFLA_VFINFO_LIST[ IFLA_VF_INFO[ IFLA_VF_MAC(mac), IFLA_VF_VLAN(vlan) ] ]
to (future) lldpad via netlink
V8:
- To enable build with --without-macvtap rename the
[dis|]associatePortProfileId functions, prepend 'vp' before their
name and make them non-static functions.
- Renaming variable multicast to nltarget_kernel and inverting
the logic
V7:
- Addressing Jim Meyering's comments; this also touches existing
code for example for correcting indentation of break statements or
simplification of switch statements.
Changes from v5 to v6:
- Renamed occurrencvirVirtualPortProfileDef to virVirtualPortProfileParamses
- 802.1Qbg part prepared for sending a RTM_SETLINK and getting
processing status back plus a subsequent RTM_GETLINK to
get IFLA_PORT_RESPONSE.
Note: This interface for 802.1Qbg may still change
Changes from v4 to v5:
- [David Allan] move getPhysfn inside IFLA_VF_PORT_MAX to avoid
compiler
warning when latest if_link.h isn't available
Changes from v3 to v4:
- move from Stefan's 802.1Qb{g|h} XML v8 to v9
- move hostuuid and vf index calcs to inside doPortProfileOp8021Qbh
Changes from v2 to v3:
- remove debug fprintfs
- use virGetHostUUID (thanks Stefan!)
- fix compile issue when latest if_link.h isn't available
- change poll timeout to 10s, at 1/8 intervals
- if polling times out, log msg and return -ETIMEDOUT
Changes from v1 to v2:
- Add Stefan's code for getPortProfileStatus
- Poll for up to 2 secs for port-profile status, at 1/8 sec intervals:
- if status indicates error, abort openMacvtapTap
- if status indicates success, exit polling
- if status is "in-progress" after 2 secs of polling, exit
polling loop silently, without error
My patch finishes out the 802.1Qbh parts, which Stefan had mostly complete.
I've tested using the recent kernel updates for VF_PORT netlink msgs and
enic for Cisco's 10G Ethernet NIC. I tested many VMs, each with several
direct interfaces, each configured with a port-profile per the XML. VM-to-VM,
and VM-to-external work as expected. VM-to-VM on same host (using same NIC)
works same as VM-to-VM where VMs are on diff hosts. I'm able to change
settings on the port-profile while the VM is running to change the virtual
port behaviour. For example, adjusting a QoS setting like rate limit. All
VMs with interfaces using that port-profile immediatly see the effect of the
change to the port-profile.
I don't have a SR-IOV device to test so source dev is a non-SR-IOV device,
but most of the code paths include support for specifing the source dev and
VF index. We'll need to complete this by discovering the PF given the VF
linkdev. Once we have the PF, we'll also have the VF index. All this info-
mation is available from sysfs.
Signed-off-by: Scott Feldman <scofeldm(a)cisco.com>
Signed-off-by: Stefan Berger <stefanb(a)us.ibm.com>
---
configure.ac | 17
src/libvirt_private.syms | 3
src/qemu/qemu_conf.c | 2
src/qemu/qemu_driver.c | 4
src/util/interface.c | 141 ++++++
src/util/interface.h | 5
src/util/macvtap.c | 1025 ++++++++++++++++++++++++++++++++++++++++++-----
src/util/macvtap.h | 12
8 files changed, 1103 insertions(+), 106 deletions(-)
Index: libvirt-acl/configure.ac
===================================================================
--- libvirt-acl.orig/configure.ac
+++ libvirt-acl/configure.ac
@@ -2005,13 +2005,27 @@ if test "$with_macvtap" != "no" ; then
fi
AM_CONDITIONAL([WITH_MACVTAP], [test "$with_macvtap" = "yes"])
+AC_TRY_COMPILE([ #include <sys/socket.h>
+ #include <linux/rtnetlink.h> ],
+ [ int x = IFLA_PORT_MAX; ],
+ [ with_virtualport=yes ],
+ [ with_virtualport=no ])
+if test "$with_virtualport" = "yes"; then
+ val=1
+else
+ val=0
+fi
+AC_DEFINE_UNQUOTED([WITH_VIRTUALPORT], $val,
+ [whether vsi vepa support is enabled])
+AM_CONDITIONAL([WITH_VIRTUALPORT], [test "$with_virtualport" = "yes"])
+
dnl netlink library
LIBNL_CFLAGS=""
LIBNL_LIBS=""
-if test "$with_macvtap" = "yes"; then
+if test "$with_macvtap" = "yes" || test "$with_virtualport" = "yes"; then
PKG_CHECK_MODULES([LIBNL], [libnl-1 >= $LIBNL_REQUIRED], [
], [
AC_MSG_ERROR([libnl >= $LIBNL_REQUIRED is required for macvtap support])
@@ -2084,6 +2098,7 @@ AC_MSG_NOTICE([ Network: $with_network])
AC_MSG_NOTICE([Libvirtd: $with_libvirtd])
AC_MSG_NOTICE([ netcf: $with_netcf])
AC_MSG_NOTICE([ macvtap: $with_macvtap])
+AC_MSG_NOTICE([virtport: $with_virtualport])
AC_MSG_NOTICE([])
AC_MSG_NOTICE([Storage Drivers])
AC_MSG_NOTICE([])
Index: libvirt-acl/src/qemu/qemu_conf.c
===================================================================
--- libvirt-acl.orig/src/qemu/qemu_conf.c
+++ libvirt-acl/src/qemu/qemu_conf.c
@@ -1554,7 +1554,7 @@ qemudPhysIfaceConnect(virConnectPtr conn
if (err) {
close(rc);
rc = -1;
- delMacvtap(net->ifname,
+ delMacvtap(net->ifname, net->mac, net->data.direct.linkdev,
&net->data.direct.virtPortProfile);
VIR_FREE(net->ifname);
}
Index: libvirt-acl/src/qemu/qemu_driver.c
===================================================================
--- libvirt-acl.orig/src/qemu/qemu_driver.c
+++ libvirt-acl/src/qemu/qemu_driver.c
@@ -3709,7 +3709,7 @@ static void qemudShutdownVMDaemon(struct
for (i = 0; i < def->nnets; i++) {
virDomainNetDefPtr net = def->nets[i];
if (net->type == VIR_DOMAIN_NET_TYPE_DIRECT) {
- delMacvtap(net->ifname,
+ delMacvtap(net->ifname, net->mac, net->data.direct.linkdev,
&net->data.direct.virtPortProfile);
VIR_FREE(net->ifname);
}
@@ -8548,7 +8548,7 @@ qemudDomainDetachNetDevice(struct qemud_
#if WITH_MACVTAP
if (detach->type == VIR_DOMAIN_NET_TYPE_DIRECT) {
- delMacvtap(detach->ifname,
+ delMacvtap(detach->ifname, detach->mac, detach->data.direct.linkdev,
&detach->data.direct.virtPortProfile);
VIR_FREE(detach->ifname);
}
Index: libvirt-acl/src/util/macvtap.c
===================================================================
--- libvirt-acl.orig/src/util/macvtap.c
+++ libvirt-acl/src/util/macvtap.c
@@ -27,12 +27,13 @@
#include <config.h>
-#if WITH_MACVTAP
+#if WITH_MACVTAP || WITH_VIRTUALPORT
# include <stdio.h>
# include <errno.h>
# include <fcntl.h>
# include <stdint.h>
+# include <c-ctype.h>
# include <sys/socket.h>
# include <sys/ioctl.h>
@@ -41,6 +42,8 @@
# include <linux/rtnetlink.h>
# include <linux/if_tun.h>
+# include <netlink/msg.h>
+
# include "util.h"
# include "memory.h"
# include "logging.h"
@@ -48,6 +51,7 @@
# include "interface.h"
# include "conf/domain_conf.h"
# include "virterror_internal.h"
+# include "uuid.h"
# define VIR_FROM_THIS VIR_FROM_NET
@@ -58,14 +62,24 @@
# define MACVTAP_NAME_PREFIX "macvtap"
# define MACVTAP_NAME_PATTERN "macvtap%d"
+# define MICROSEC_PER_SEC (1000 * 1000)
+
+# define NLMSGBUF_SIZE 256
+# define RATTBUF_SIZE 64
+
+# define NETLINK_ACK_TIMEOUT_S 2
+
+# define STATUS_POLL_TIMEOUT_USEC (10 * MICROSEC_PER_SEC)
+# define STATUS_POLL_INTERVL_USEC (MICROSEC_PER_SEC / 8)
-static int associatePortProfileId(const char *macvtap_ifname,
- const virVirtualPortProfileParamsPtr virtPort,
- int vf,
- const unsigned char *vmuuid);
-static int disassociatePortProfileId(const char *macvtap_ifname,
- const virVirtualPortProfileParamsPtr virtPort);
+# define LLDPAD_PID_FILE "/var/run/lldpad.pid"
+
+
+enum virVirtualPortOp {
+ ASSOCIATE = 0x1,
+ DISASSOCIATE = 0x2,
+};
static int nlOpen(void)
@@ -90,6 +104,7 @@ static void nlClose(int fd)
* @respbuf: pointer to pointer where response buffer will be allocated
* @respbuflen: pointer to integer holding the size of the response buffer
* on return of the function.
+ * @nl_pid: the pid of the process to talk to, i.e., pid = 0 for kernel
*
* Send the given message to the netlink layer and receive response.
* Returns 0 on success, -1 on error. In case of error, no response
@@ -97,22 +112,29 @@ static void nlClose(int fd)
*/
static
int nlComm(struct nlmsghdr *nlmsg,
- char **respbuf, int *respbuflen)
+ char **respbuf, unsigned int *respbuflen,
+ int nl_pid)
{
int rc = 0;
struct sockaddr_nl nladdr = {
.nl_family = AF_NETLINK,
- .nl_pid = 0,
+ .nl_pid = nl_pid,
.nl_groups = 0,
};
int rcvChunkSize = 1024; // expecting less than that
int rcvoffset = 0;
ssize_t nbytes;
+ struct timeval tv = {
+ .tv_sec = NETLINK_ACK_TIMEOUT_S,
+ };
+ fd_set readfds;
int fd = nlOpen();
+ int n;
if (fd < 0)
return -1;
+ nlmsg->nlmsg_pid = getpid();
nlmsg->nlmsg_flags |= NLM_F_ACK;
nbytes = sendto(fd, (void *)nlmsg, nlmsg->nlmsg_len, 0,
@@ -124,6 +146,21 @@ int nlComm(struct nlmsghdr *nlmsg,
goto err_exit;
}
+ FD_ZERO(&readfds);
+ FD_SET(fd, &readfds);
+
+ n = select(fd + 1, &readfds, NULL, NULL, &tv);
+ if (n <= 0) {
+ if (n < 0)
+ virReportSystemError(errno, "%s",
+ _("error in select call"));
+ if (n == 0)
+ virReportSystemError(ETIMEDOUT, "%s",
+ _("no valid netlink response was received"));
+ rc = -1;
+ goto err_exit;
+ }
+
while (1) {
if (VIR_REALLOC_N(*respbuf, rcvoffset+rcvChunkSize) < 0) {
virReportOOMError();
@@ -204,6 +241,8 @@ nlAppend(struct nlmsghdr *nlm, int totle
}
+# if WITH_MACVTAP
+
static int
link_add(const char *type,
const unsigned char *macaddress, int macaddrsize,
@@ -213,15 +252,15 @@ link_add(const char *type,
int *retry)
{
int rc = 0;
- char nlmsgbuf[256];
+ char nlmsgbuf[NLMSGBUF_SIZE];
struct nlmsghdr *nlm = (struct nlmsghdr *)nlmsgbuf, *resp;
struct nlmsgerr *err;
- char rtattbuf[64];
+ char rtattbuf[RATTBUF_SIZE];
struct rtattr *rta, *rta1, *li;
- struct ifinfomsg i = { .ifi_family = AF_UNSPEC };
+ struct ifinfomsg ifinfo = { .ifi_family = AF_UNSPEC };
int ifindex;
char *recvbuf = NULL;
- int recvbuflen;
+ unsigned int recvbuflen;
if (ifaceGetIndex(true, srcdev, &ifindex) != 0)
return -1;
@@ -232,65 +271,46 @@ link_add(const char *type,
nlInit(nlm, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL, RTM_NEWLINK);
- if (!nlAppend(nlm, sizeof(nlmsgbuf), &i, sizeof(i)))
+ if (!nlAppend(nlm, sizeof(nlmsgbuf), &ifinfo, sizeof(ifinfo)))
goto buffer_too_small;
rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_LINK,
&ifindex, sizeof(ifindex));
- if (!rta)
- goto buffer_too_small;
-
- if (!nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len))
+ if (!rta || !nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len))
goto buffer_too_small;
rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_ADDRESS,
macaddress, macaddrsize);
- if (!rta)
- goto buffer_too_small;
-
- if (!nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len))
+ if (!rta || !nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len))
goto buffer_too_small;
if (ifname) {
rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_IFNAME,
ifname, strlen(ifname) + 1);
- if (!rta)
- goto buffer_too_small;
-
- if (!nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len))
+ if (!rta || !nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len))
goto buffer_too_small;
}
rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_LINKINFO, NULL, 0);
- if (!rta)
- goto buffer_too_small;
-
- if (!(li = nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len)))
+ if (!rta ||
+ !(li = nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len)))
goto buffer_too_small;
rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_INFO_KIND,
type, strlen(type));
- if (!rta)
- goto buffer_too_small;
-
- if (!nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len))
+ if (!rta || !nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len))
goto buffer_too_small;
if (macvlan_mode > 0) {
rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_INFO_DATA,
NULL, 0);
- if (!rta)
- goto buffer_too_small;
-
- if (!(rta1 = nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len)))
+ if (!rta ||
+ !(rta1 = nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len)))
goto buffer_too_small;
rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_MACVLAN_MODE,
&macvlan_mode, sizeof(macvlan_mode));
- if (!rta)
- goto buffer_too_small;
-
- if (!nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len))
+ if (!rta || !nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len))
goto buffer_too_small;
rta1->rta_len = (char *)nlm + nlm->nlmsg_len - (char *)rta1;
@@ -298,7 +318,7 @@ link_add(const char *type,
li->rta_len = (char *)nlm + nlm->nlmsg_len - (char *)li;
- if (nlComm(nlm, &recvbuf, &recvbuflen) < 0)
+ if (nlComm(nlm, &recvbuf, &recvbuflen, 0) < 0)
return -1;
if (recvbuflen < NLMSG_LENGTH(0) || recvbuf == NULL)
@@ -312,15 +332,15 @@ link_add(const char *type,
if (resp->nlmsg_len < NLMSG_LENGTH(sizeof(*err)))
goto malformed_resp;
- switch (-err->error) {
+ switch (err->error) {
case 0:
- break;
+ break;
- case EEXIST:
+ case -EEXIST:
*retry = 1;
rc = -1;
- break;
+ break;
default:
virReportSystemError(-err->error,
@@ -328,10 +348,10 @@ link_add(const char *type,
type);
rc = -1;
}
- break;
+ break;
case NLMSG_DONE:
- break;
+ break;
default:
goto malformed_resp;
@@ -358,14 +378,14 @@ static int
link_del(const char *name)
{
int rc = 0;
- char nlmsgbuf[256];
+ char nlmsgbuf[NLMSGBUF_SIZE];
struct nlmsghdr *nlm = (struct nlmsghdr *)nlmsgbuf, *resp;
struct nlmsgerr *err;
- char rtattbuf[64];
+ char rtattbuf[RATTBUF_SIZE];
struct rtattr *rta;
struct ifinfomsg ifinfo = { .ifi_family = AF_UNSPEC };
char *recvbuf = NULL;
- int recvbuflen;
+ unsigned int recvbuflen;
memset(&nlmsgbuf, 0, sizeof(nlmsgbuf));
@@ -376,13 +396,10 @@ link_del(const char *name)
rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_IFNAME,
name, strlen(name)+1);
- if (!rta)
- goto buffer_too_small;
-
- if (!nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len))
+ if (!rta || !nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len))
goto buffer_too_small;
- if (nlComm(nlm, &recvbuf, &recvbuflen) < 0)
+ if (nlComm(nlm, &recvbuf, &recvbuflen, 0) < 0)
return -1;
if (recvbuflen < NLMSG_LENGTH(0) || recvbuf == NULL)
@@ -396,20 +413,16 @@ link_del(const char *name)
if (resp->nlmsg_len < NLMSG_LENGTH(sizeof(*err)))
goto malformed_resp;
- switch (-err->error) {
- case 0:
- break;
-
- default:
+ if (err->error) {
virReportSystemError(-err->error,
_("error destroying %s interface"),
name);
rc = -1;
}
- break;
+ break;
case NLMSG_DONE:
- break;
+ break;
default:
goto malformed_resp;
@@ -509,11 +522,9 @@ macvtapModeFromInt(enum virDomainNetdevM
switch (mode) {
case VIR_DOMAIN_NETDEV_MACVTAP_MODE_PRIVATE:
return MACVLAN_MODE_PRIVATE;
- break;
case VIR_DOMAIN_NETDEV_MACVTAP_MODE_BRIDGE:
return MACVLAN_MODE_BRIDGE;
- break;
case VIR_DOMAIN_NETDEV_MACVTAP_MODE_VEPA:
default:
@@ -654,10 +665,11 @@ create_name:
cr_ifname = ifname;
}
- if (associatePortProfileId(cr_ifname,
- virtPortProfile,
- -1,
- vmuuid) != 0) {
+ if (vpAssociatePortProfileId(cr_ifname,
+ macaddress,
+ linkdev,
+ virtPortProfile,
+ vmuuid) != 0) {
rc = -1;
goto link_del_exit;
}
@@ -688,8 +700,10 @@ create_name:
return rc;
disassociate_exit:
- disassociatePortProfileId(cr_ifname,
- virtPortProfile);
+ vpDisassociatePortProfileId(cr_ifname,
+ macaddress,
+ linkdev,
+ virtPortProfile);
link_del_exit:
link_del(cr_ifname);
@@ -701,6 +715,7 @@ link_del_exit:
/**
* delMacvtap:
* @ifname : The name of the macvtap interface
+ * @linkdev: The interface name of the NIC to connect to the external bridge
* @virtPortProfile: pointer to object holding the virtual port profile data
*
* Delete an interface given its name. Disassociate
@@ -709,22 +724,837 @@ link_del_exit:
*/
void
delMacvtap(const char *ifname,
+ const unsigned char *macaddr,
+ const char *linkdev,
virVirtualPortProfileParamsPtr virtPortProfile)
{
if (ifname) {
- disassociatePortProfileId(ifname,
- virtPortProfile);
+ vpDisassociatePortProfileId(ifname, macaddr,
+ linkdev,
+ virtPortProfile);
link_del(ifname);
}
}
+# endif /* WITH_MACVTAP */
+
+# ifdef IFLA_PORT_MAX
+
+static struct nla_policy ifla_policy[IFLA_MAX + 1] =
+{
+ [IFLA_VF_PORTS] = { .type = NLA_NESTED },
+};
+
+static struct nla_policy ifla_port_policy[IFLA_PORT_MAX + 1] =
+{
+ [IFLA_PORT_RESPONSE] = { .type = NLA_U16 },
+};
+
+
+static uint32_t
+getLldpadPid(void) {
+ int fd;
+ uint32_t pid = 0;
+
+ fd = open(LLDPAD_PID_FILE, O_RDONLY);
+ if (fd >= 0) {
+ char buffer[10];
+ char *endptr;
+
+ if (saferead(fd, buffer, sizeof(buffer)) <= sizeof(buffer)) {
+ unsigned int res;
+
+ if (virStrToLong_ui(buffer, &endptr, 10, &res) == 0
+ && (endptr == NULL || c_isspace(*endptr))
+ && res != 0) {
+ pid = res;
+ } else {
+ macvtapError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("error parsing pid of lldpad"));
+ }
+ }
+ } else {
+ virReportSystemError(errno,
+ _("Error opening file %s"), LLDPAD_PID_FILE);
+ }
+
+ if (fd >= 0)
+ close(fd);
+
+ return pid;
+}
+
+
+static int
+link_dump(bool nltarget_kernel, const char *ifname, int ifindex,
+ struct nlattr **tb, char **recvbuf)
+{
+ int rc = 0;
+ char nlmsgbuf[NLMSGBUF_SIZE] = { 0, };
+ struct nlmsghdr *nlm = (struct nlmsghdr *)nlmsgbuf, *resp;
+ struct nlmsgerr *err;
+ char rtattbuf[RATTBUF_SIZE];
+ struct rtattr *rta;
+ struct ifinfomsg ifinfo = {
+ .ifi_family = AF_UNSPEC,
+ .ifi_index = ifindex
+ };
+ unsigned int recvbuflen;
+ uint32_t pid = 0;
+
+ *recvbuf = NULL;
+
+ nlInit(nlm, NLM_F_REQUEST, RTM_GETLINK);
+
+ if (!nlAppend(nlm, sizeof(nlmsgbuf), &ifinfo, sizeof(ifinfo)))
+ goto buffer_too_small;
+
+ if (ifindex < 0 && ifname) {
+ rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_IFNAME,
+ ifname, strlen(ifname) + 1);
+ if (!rta || !nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len))
+ goto buffer_too_small;
+ }
+
+ if (!nltarget_kernel) {
+ pid = getLldpadPid();
+ if (pid == 0)
+ return -1;
+ }
+
+ if (nlComm(nlm, recvbuf, &recvbuflen, pid) < 0)
+ return -1;
+
+ if (recvbuflen < NLMSG_LENGTH(0) || *recvbuf == NULL)
+ goto malformed_resp;
+
+ resp = (struct nlmsghdr *)*recvbuf;
+
+ switch (resp->nlmsg_type) {
+ case NLMSG_ERROR:
+ err = (struct nlmsgerr *)NLMSG_DATA(resp);
+ if (resp->nlmsg_len < NLMSG_LENGTH(sizeof(*err)))
+ goto malformed_resp;
+
+ if (err->error) {
+ virReportSystemError(-err->error,
+ _("error dumping %s (%d) interface"),
+ ifname, ifindex);
+ rc = -1;
+ }
+ break;
+
+ case GENL_ID_CTRL:
+ case NLMSG_DONE:
+ if (nlmsg_parse(resp, sizeof(struct ifinfomsg),
+ tb, IFLA_MAX, ifla_policy)) {
+ goto malformed_resp;
+ }
+ break;
+
+ default:
+ goto malformed_resp;
+ }
+
+ if (rc != 0)
+ VIR_FREE(*recvbuf);
+
+ return rc;
+
+malformed_resp:
+ macvtapError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("malformed netlink response message"));
+ VIR_FREE(*recvbuf);
+ return -1;
+
+buffer_too_small:
+ macvtapError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("internal buffer is too small"));
+ return -1;
+}
+
+
+/**
+ * ifaceGetNthParent
+ *
+ * @ifindex : the index of the interface or -1 if ifname is given
+ * @ifname : the name of the interface; ignored if ifindex is valid
+ * @nthParent : the nth parent interface to get
+ * @parent_ifindex : pointer to int
+ * @parent_ifname : pointer to buffer of size IFNAMSIZ
+ * @nth : the nth parent that is actually returned; if for example eth0.100
+ * was given and the 100th parent is to be returned, then eth0 will
+ * most likely be returned with nth set to 1 since the chain does
+ * not have more interfaces
+ *
+ * Get the nth parent interface of the given interface. 0 is the interface
+ * itself.
+ *
+ * Return 0 on success, != 0 otherwise
+ */
+static int
+ifaceGetNthParent(int ifindex, const char *ifname, unsigned int nthParent,
+ int *parent_ifindex, char *parent_ifname,
+ unsigned int *nth)
+{
+ int rc;
+ struct nlattr *tb[IFLA_MAX + 1] = { NULL, };
+ char *recvbuf = NULL;
+ bool end = false;
+ unsigned int i = 0;
+
+ *nth = 0;
+
+ while (!end && i <= nthParent) {
+ rc = link_dump(true, ifname, ifindex, tb, &recvbuf);
+ if (rc)
+ break;
+
+ if (tb[IFLA_IFNAME]) {
+ if (!virStrcpy(parent_ifname, (char*)RTA_DATA(tb[IFLA_IFNAME]),
+ IFNAMSIZ)) {
+ macvtapError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("buffer for root interface name is too small"));
+ VIR_FREE(recvbuf);
+ return 1;
+ }
+ *parent_ifindex = ifindex;
+ }
+
+ if (tb[IFLA_LINK]) {
+ ifindex = *(int *)RTA_DATA(tb[IFLA_LINK]);
+ ifname = NULL;
+ } else
+ end = true;
+
+ VIR_FREE(recvbuf);
+
+ i++;
+ }
+
+ if (nth)
+ *nth = i - 1;
+
+ return rc;
+}
/**
- * associatePortProfile
+ * getPortProfileStatus
+ *
+ * tb: top level netlink response attributes + values
+ * vf: The virtual function used in the request
+ * instanceId: instanceId of the interface (vm uuid in case of 802.1Qbh)
+ * is8021Qbg: whether this function is call for 8021Qbg
+ * status: pointer to a uint16 where the status will be written into
+ *
+ * Get the status from the IFLA_PORT_RESPONSE field; Returns 0 in
+ * case of success, != 0 otherwise with error having been reported
+ */
+static int
+getPortProfileStatus(struct nlattr **tb, int32_t vf,
+ const unsigned char *instanceId,
+ bool nltarget_kernel,
+ bool is8021Qbg,
+ uint16_t *status)
+{
+ int rc = 1;
+ const char *msg = NULL;
+ struct nlattr *tb_port[IFLA_PORT_MAX + 1] = { NULL, };
+
+ if (vf == PORT_SELF_VF && nltarget_kernel) {
+ if (tb[IFLA_PORT_SELF]) {
+ if (nla_parse_nested(tb_port, IFLA_PORT_MAX, tb[IFLA_PORT_SELF],
+ ifla_port_policy)) {
+ msg = _("error parsing IFLA_PORT_SELF part");
+ goto err_exit;
+ }
+ } else {
+ msg = _("IFLA_PORT_SELF is missing");
+ goto err_exit;
+ }
+ } else {
+ if (tb[IFLA_VF_PORTS]) {
+ int rem;
+ bool found = false;
+ struct nlattr *tb_vf_ports = { NULL, };
+
+ nla_for_each_nested(tb_vf_ports, tb[IFLA_VF_PORTS], rem) {
+
+ if (nla_type(tb_vf_ports) != IFLA_VF_PORT) {
+ msg = _("error while iterating over IFLA_VF_PORTS part");
+ goto err_exit;
+ }
+
+ if (nla_parse_nested(tb_port, IFLA_PORT_MAX, tb_vf_ports,
+ ifla_port_policy)) {
+ msg = _("error parsing IFLA_VF_PORT part");
+ goto err_exit;
+ }
+
+ if (instanceId &&
+ tb_port[IFLA_PORT_INSTANCE_UUID] &&
+ !memcmp(instanceId,
+ (unsigned char *)
+ RTA_DATA(tb_port[IFLA_PORT_INSTANCE_UUID]),
+ VIR_UUID_BUFLEN) &&
+ tb_port[IFLA_PORT_VF] &&
+ vf == *(uint32_t *)RTA_DATA(tb_port[IFLA_PORT_VF])) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ msg = _("Could not find netlink response with "
+ "expected parameters");
+ goto err_exit;
+ }
+ } else {
+ msg = _("IFLA_VF_PORTS is missing");
+ goto err_exit;
+ }
+ }
+
+ if (tb_port[IFLA_PORT_RESPONSE]) {
+ *status = *(uint16_t *)RTA_DATA(tb_port[IFLA_PORT_RESPONSE]);
+ rc = 0;
+ } else {
+ if (is8021Qbg) {
+ /* no in-progress here; may be missing */
+ *status = PORT_PROFILE_RESPONSE_INPROGRESS;
+ } else {
+ msg = _("no IFLA_PORT_RESPONSE found in netlink message");
+ goto err_exit;
+ }
+ }
+
+err_exit:
+ if (msg)
+ macvtapError(VIR_ERR_INTERNAL_ERROR, "%s", msg);
+
+ return rc;
+}
+
+
+static int
+doPortProfileOpSetLink(bool nltarget_kernel,
+ const char *ifname, int ifindex,
+ const unsigned char *macaddr,
+ int vlanid,
+ const char *profileId,
+ struct ifla_port_vsi *portVsi,
+ const unsigned char *instanceId,
+ const unsigned char *hostUUID,
+ int32_t vf,
+ uint8_t op)
+{
+ int rc = 0;
+ char nlmsgbuf[NLMSGBUF_SIZE];
+ struct nlmsghdr *nlm = (struct nlmsghdr *)nlmsgbuf, *resp;
+ struct nlmsgerr *err;
+ char rtattbuf[RATTBUF_SIZE];
+ struct rtattr *rta, *vfports = NULL, *vfport;
+ struct ifinfomsg ifinfo = {
+ .ifi_family = AF_UNSPEC,
+ .ifi_index = ifindex,
+ };
+ char *recvbuf = NULL;
+ unsigned int recvbuflen = 0;
+ uint32_t pid = 0;
+
+ memset(&nlmsgbuf, 0, sizeof(nlmsgbuf));
+
+ nlInit(nlm, NLM_F_REQUEST, RTM_SETLINK);
+
+ if (!nlAppend(nlm, sizeof(nlmsgbuf), &ifinfo, sizeof(ifinfo)))
+ goto buffer_too_small;
+
+ if (ifname) {
+ rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_IFNAME,
+ ifname, strlen(ifname) + 1);
+ if (!rta || !nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len))
+ goto buffer_too_small;
+ }
+
+ if (macaddr && vlanid >= 0) {
+ struct rtattr *vfinfolist, *vfinfo;
+ struct ifla_vf_mac ifla_vf_mac = {
+ .vf = vf,
+ .mac = { 0, },
+ };
+ struct ifla_vf_vlan ifla_vf_vlan = {
+ .vf = vf,
+ .vlan = vlanid,
+ .qos = 0,
+ };
+
+ memcpy(ifla_vf_mac.mac, macaddr, 6);
+
+ rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_VFINFO_LIST,
+ NULL, 0);
+ if (!rta ||
+ !(vfinfolist = nlAppend(nlm, sizeof(nlmsgbuf),
+ rtattbuf, rta->rta_len)))
+ goto buffer_too_small;
+
+ rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_VF_INFO,
+ NULL, 0);
+ if (!rta ||
+ !(vfinfo = nlAppend(nlm, sizeof(nlmsgbuf),
+ rtattbuf, rta->rta_len)))
+ goto buffer_too_small;
+
+ rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_VF_MAC,
+ &ifla_vf_mac, sizeof(ifla_vf_mac));
+ if (!rta || !nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len))
+ goto buffer_too_small;
+
+ rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_VF_VLAN,
+ &ifla_vf_vlan, sizeof(ifla_vf_vlan));
+
+ if (!rta || !nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len))
+ goto buffer_too_small;
+
+ vfinfo->rta_len = (char *)nlm + nlm->nlmsg_len - (char *)vfinfo;
+
+ vfinfolist->rta_len = (char *)nlm + nlm->nlmsg_len -
+ (char *)vfinfolist;
+ }
+
+ if (vf == PORT_SELF_VF && nltarget_kernel) {
+ rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_PORT_SELF, NULL, 0);
+ } else {
+ rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_VF_PORTS, NULL, 0);
+ if (!rta ||
+ !(vfports = nlAppend(nlm, sizeof(nlmsgbuf),
+ rtattbuf, rta->rta_len)))
+ goto buffer_too_small;
+
+ /* begin nesting vfports */
+ rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_VF_PORT, NULL, 0);
+ }
+
+ if (!rta ||
+ !(vfport = nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len)))
+ goto buffer_too_small;
+
+ if (profileId) {
+ rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_PORT_PROFILE,
+ profileId, strlen(profileId) + 1);
+ if (!rta || !nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len))
+ goto buffer_too_small;
+ }
+
+ if (portVsi) {
+ rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_PORT_VSI_TYPE,
+ portVsi, sizeof(*portVsi));
+ if (!rta || !nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len))
+ goto buffer_too_small;
+ }
+
+ if (instanceId) {
+ rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_PORT_INSTANCE_UUID,
+ instanceId, VIR_UUID_BUFLEN);
+ if (!rta || !nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len))
+ goto buffer_too_small;
+ }
+
+ if (hostUUID) {
+ rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_PORT_HOST_UUID,
+ hostUUID, VIR_UUID_BUFLEN);
+ if (!rta || !nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len))
+ goto buffer_too_small;
+ }
+
+ if (vf != PORT_SELF_VF) {
+ rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_PORT_VF,
+ &vf, sizeof(vf));
+ if (!rta || !nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len))
+ goto buffer_too_small;
+ }
+
+ rta = rtattrCreate(rtattbuf, sizeof(rtattbuf), IFLA_PORT_REQUEST,
+ &op, sizeof(op));
+ if (!rta || !nlAppend(nlm, sizeof(nlmsgbuf), rtattbuf, rta->rta_len))
+ goto buffer_too_small;
+
+ /* end nesting of vport */
+ vfport->rta_len = (char *)nlm + nlm->nlmsg_len - (char *)vfport;
+
+ if (vfports) {
+ /* end nesting of vfports */
+ vfports->rta_len = (char *)nlm + nlm->nlmsg_len - (char *)vfports;
+ }
+
+ if (!nltarget_kernel) {
+ pid = getLldpadPid();
+ if (pid == 0)
+ return -1;
+ }
+
+ if (nlComm(nlm, &recvbuf, &recvbuflen, pid) < 0)
+ return -1;
+
+ if (recvbuflen < NLMSG_LENGTH(0) || recvbuf == NULL)
+ goto malformed_resp;
+
+ resp = (struct nlmsghdr *)recvbuf;
+
+ switch (resp->nlmsg_type) {
+ case NLMSG_ERROR:
+ err = (struct nlmsgerr *)NLMSG_DATA(resp);
+ if (resp->nlmsg_len < NLMSG_LENGTH(sizeof(*err)))
+ goto malformed_resp;
+
+ if (err->error) {
+ virReportSystemError(-err->error,
+ _("error during virtual port configuration of ifindex %d"),
+ ifindex);
+ rc = -1;
+ }
+ break;
+
+ case NLMSG_DONE:
+ break;
+
+ default:
+ goto malformed_resp;
+ }
+
+ VIR_FREE(recvbuf);
+
+ return rc;
+
+malformed_resp:
+ macvtapError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("malformed netlink response message"));
+ VIR_FREE(recvbuf);
+ return -1;
+
+buffer_too_small:
+ macvtapError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("internal buffer is too small"));
+ return -1;
+}
+
+
+static int
+doPortProfileOpCommon(bool nltarget_kernel,
+ const char *ifname, int ifindex,
+ const unsigned char *macaddr,
+ int vlanid,
+ const char *profileId,
+ struct ifla_port_vsi *portVsi,
+ const unsigned char *instanceId,
+ const unsigned char *hostUUID,
+ int32_t vf,
+ uint8_t op)
+{
+ int rc;
+ char *recvbuf = NULL;
+ struct nlattr *tb[IFLA_MAX + 1] = { NULL , };
+ int repeats = STATUS_POLL_TIMEOUT_USEC / STATUS_POLL_INTERVL_USEC;
+ uint16_t status = 0;
+ bool is8021Qbg = (profileId == NULL);
+
+ rc = doPortProfileOpSetLink(nltarget_kernel,
+ ifname, ifindex,
+ macaddr,
+ vlanid,
+ profileId,
+ portVsi,
+ instanceId,
+ hostUUID,
+ vf,
+ op);
+
+ if (rc) {
+ macvtapError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("sending of PortProfileRequest failed."));
+ return rc;
+ }
+
+ while (--repeats >= 0) {
+ rc = link_dump(nltarget_kernel, NULL, ifindex, tb, &recvbuf);
+ if (rc)
+ goto err_exit;
+ rc = getPortProfileStatus(tb, vf, instanceId, nltarget_kernel,
+ is8021Qbg, &status);
+ if (rc)
+ goto err_exit;
+ if (status == PORT_PROFILE_RESPONSE_SUCCESS ||
+ status == PORT_VDP_RESPONSE_SUCCESS) {
+ break;
+ } else if (status == PORT_PROFILE_RESPONSE_INPROGRESS) {
+ // keep trying...
+ } else {
+ virReportSystemError(EINVAL,
+ _("error %d during port-profile setlink on "
+ "interface %s (%d)"),
+ status, ifname, ifindex);
+ rc = 1;
+ break;
+ }
+
+ usleep(STATUS_POLL_INTERVL_USEC);
+
+ VIR_FREE(recvbuf);
+ }
+
+ if (status == PORT_PROFILE_RESPONSE_INPROGRESS) {
+ macvtapError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("port-profile setlink timed out"));
+ rc = -ETIMEDOUT;
+ }
+
+err_exit:
+ VIR_FREE(recvbuf);
+
+ return rc;
+}
+
+# endif /* IFLA_PORT_MAX */
+
+
+# ifdef IFLA_VF_PORT_MAX
+
+static int
+getPhysdevAndVlan(const char *ifname, int *root_ifindex, char *root_ifname,
+ int *vlanid)
+{
+ int ret;
+ unsigned int nth;
+ int ifindex = -1;
+
+ *vlanid = -1;
+ while (1) {
+ if ((ret = ifaceGetNthParent(ifindex, ifname, 1,
+ root_ifindex, root_ifname, &nth)))
+ return ret;
+ if (nth == 0)
+ break;
+ if (*vlanid == -1) {
+ if (ifaceGetVlanID(root_ifname, vlanid))
+ *vlanid = -1;
+ }
+
+ ifindex = *root_ifindex;
+ ifname = NULL;
+ }
+
+ return 0;
+}
+
+# endif
+
+static int
+doPortProfileOp8021Qbg(const char *ifname,
+ const unsigned char *macaddr,
+ const virVirtualPortProfileParamsPtr virtPort,
+ enum virVirtualPortOp virtPortOp)
+{
+ int rc;
+
+# ifndef IFLA_VF_PORT_MAX
+
+ (void)ifname;
+ (void)macaddr;
+ (void)virtPort;
+ (void)virtPortOp;
+ macvtapError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Kernel VF Port support was missing at compile time."));
+ rc = 1;
+
+# else /* IFLA_VF_PORT_MAX */
+
+ int op = PORT_REQUEST_ASSOCIATE;
+ struct ifla_port_vsi portVsi = {
+ .vsi_mgr_id = virtPort->u.virtPort8021Qbg.managerID,
+ .vsi_type_version = virtPort->u.virtPort8021Qbg.typeIDVersion,
+ };
+ bool nltarget_kernel = false;
+ int vlanid;
+ int physdev_ifindex = 0;
+ char physdev_ifname[IFNAMSIZ] = { 0, };
+ int vf = PORT_SELF_VF;
+
+ if (getPhysdevAndVlan(ifname, &physdev_ifindex, physdev_ifname,
+ &vlanid) != 0) {
+ rc = 1;
+ goto err_exit;
+ }
+
+ if (vlanid < 0)
+ vlanid = 0;
+
+ portVsi.vsi_type_id[2] = virtPort->u.virtPort8021Qbg.typeID >> 16;
+ portVsi.vsi_type_id[1] = virtPort->u.virtPort8021Qbg.typeID >> 8;
+ portVsi.vsi_type_id[0] = virtPort->u.virtPort8021Qbg.typeID;
+
+ switch (virtPortOp) {
+ case ASSOCIATE:
+ op = PORT_REQUEST_ASSOCIATE;
+ break;
+ case DISASSOCIATE:
+ op = PORT_REQUEST_DISASSOCIATE;
+ break;
+ default:
+ macvtapError(VIR_ERR_INTERNAL_ERROR,
+ _("operation type %d not supported"), op);
+ rc = 1;
+ goto err_exit;
+ }
+
+ rc = doPortProfileOpCommon(nltarget_kernel,
+ physdev_ifname, physdev_ifindex,
+ macaddr,
+ vlanid,
+ NULL,
+ &portVsi,
+ virtPort->u.virtPort8021Qbg.instanceID,
+ NULL,
+ vf,
+ op);
+
+err_exit:
+
+# endif /* IFLA_VF_PORT_MAX */
+
+ return rc;
+}
+
+
+# ifdef IFLA_VF_PORT_MAX
+static int
+getPhysfn(const char *linkdev,
+ int32_t *vf,
+ char **physfndev)
+{
+ int rc = 0;
+ bool virtfn = false;
+
+ if (virtfn) {
+
+ // XXX: if linkdev is SR-IOV VF, then set vf = VF index
+ // XXX: and set linkdev = PF device
+ // XXX: need to use get_physical_function_linux() or
+ // XXX: something like that to get PF
+ // XXX: device and figure out VF index
+
+ rc = 1;
+
+ } else {
+
+ /* Not SR-IOV VF: physfndev is linkdev and VF index
+ * refers to linkdev self
+ */
+
+ *vf = PORT_SELF_VF;
+ *physfndev = (char *)linkdev;
+ }
+
+ return rc;
+}
+# endif /* IFLA_VF_PORT_MAX */
+
+static int
+doPortProfileOp8021Qbh(const char *ifname,
+ const virVirtualPortProfileParamsPtr virtPort,
+ const unsigned char *vm_uuid,
+ enum virVirtualPortOp virtPortOp)
+{
+ int rc;
+
+# ifndef IFLA_VF_PORT_MAX
+
+ (void)ifname;
+ (void)virtPort;
+ (void)vm_uuid;
+ (void)virtPortOp;
+ macvtapError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Kernel VF Port support was missing at compile time."));
+ rc = 1;
+
+# else /* IFLA_VF_PORT_MAX */
+
+ char *physfndev;
+ unsigned char hostuuid[VIR_UUID_BUFLEN];
+ int32_t vf;
+ bool nltarget_kernel = true;
+ int ifindex;
+ int vlanid = -1;
+ const unsigned char *macaddr = NULL;
+
+ rc = getPhysfn(ifname, &vf, &physfndev);
+ if (rc)
+ goto err_exit;
+
+ if (ifaceGetIndex(true, physfndev, &ifindex) != 0) {
+ rc = 1;
+ goto err_exit;
+ }
+
+ switch (virtPortOp) {
+ case ASSOCIATE:
+ rc = virGetHostUUID(hostuuid);
+ if (rc)
+ goto err_exit;
+
+ rc = doPortProfileOpCommon(nltarget_kernel, NULL, ifindex,
+ macaddr,
+ vlanid,
+ virtPort->u.virtPort8021Qbh.profileID,
+ NULL,
+ vm_uuid,
+ hostuuid,
+ vf,
+ PORT_REQUEST_ASSOCIATE);
+ if (rc == -ETIMEDOUT)
+ /* Association timed out, disassociate */
+ doPortProfileOpCommon(nltarget_kernel, NULL, ifindex,
+ NULL,
+ 0,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ vf,
+ PORT_REQUEST_DISASSOCIATE);
+ if (!rc)
+ ifaceUp(ifname);
+ break;
+
+ case DISASSOCIATE:
+ rc = doPortProfileOpCommon(nltarget_kernel, NULL, ifindex,
+ NULL,
+ 0,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ vf,
+ PORT_REQUEST_DISASSOCIATE);
+ ifaceDown(ifname);
+ break;
+
+ default:
+ macvtapError(VIR_ERR_INTERNAL_ERROR,
+ _("operation type %d not supported"), virtPortOp);
+ rc = 1;
+ }
+
+err_exit:
+
+# endif /* IFLA_VF_PORT_MAX */
+
+ return rc;
+}
+
+/**
+ * vpAssociatePortProfile
*
* @macvtap_ifname: The name of the macvtap device
* @virtPort: 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
@@ -736,17 +1566,17 @@ delMacvtap(const char *ifname,
* Returns 0 in case of success, != 0 otherwise with error
* having been reported.
*/
-static int
-associatePortProfileId(const char *macvtap_ifname,
- const virVirtualPortProfileParamsPtr virtPort,
- int vf,
- const unsigned char *vmuuid)
+int
+vpAssociatePortProfileId(const char *macvtap_ifname,
+ const unsigned char *macvtap_macaddr,
+ const char *linkdev,
+ const virVirtualPortProfileParamsPtr virtPort,
+ const unsigned char *vmuuid)
{
int rc = 0;
+
VIR_DEBUG("Associating port profile '%p' on link device '%s'",
virtPort, macvtap_ifname);
- (void)vf;
- (void)vmuuid;
switch (virtPort->virtPortType) {
case VIR_VIRTUALPORT_NONE:
@@ -754,11 +1584,14 @@ associatePortProfileId(const char *macvt
break;
case VIR_VIRTUALPORT_8021QBG:
-
+ rc = doPortProfileOp8021Qbg(macvtap_ifname, macvtap_macaddr,
+ virtPort, ASSOCIATE);
break;
case VIR_VIRTUALPORT_8021QBH:
-
+ rc = doPortProfileOp8021Qbh(linkdev, virtPort,
+ vmuuid,
+ ASSOCIATE);
break;
}
@@ -767,19 +1600,24 @@ associatePortProfileId(const char *macvt
/**
- * disassociatePortProfile
+ * vpDisassociatePortProfile
*
* @macvtap_ifname: The name of the macvtap device
+ * @macvtap_macaddr : The MAC address of the macvtap
+ * @linkdev: The link device in case of macvtap
* @virtPort: 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 virVirtualPortProfileParamsPtr virtPort)
+int
+vpDisassociatePortProfileId(const char *macvtap_ifname,
+ const unsigned char *macvtap_macaddr,
+ const char *linkdev,
+ const virVirtualPortProfileParamsPtr virtPort)
{
int rc = 0;
+
VIR_DEBUG("Disassociating port profile id '%p' on link device '%s' ",
virtPort, macvtap_ifname);
@@ -789,15 +1627,18 @@ disassociatePortProfileId(const char *ma
break;
case VIR_VIRTUALPORT_8021QBG:
-
+ rc = doPortProfileOp8021Qbg(macvtap_ifname, macvtap_macaddr,
+ virtPort, DISASSOCIATE);
break;
case VIR_VIRTUALPORT_8021QBH:
-
+ rc = doPortProfileOp8021Qbh(linkdev, virtPort,
+ NULL,
+ DISASSOCIATE);
break;
}
return rc;
}
-#endif /* WITH_MACVTAP */
+#endif /* WITH_MACVTAP || WITH_VIRTUALPORT */
Index: libvirt-acl/src/util/macvtap.h
===================================================================
--- libvirt-acl.orig/src/util/macvtap.h
+++ libvirt-acl/src/util/macvtap.h
@@ -72,6 +72,8 @@ int openMacvtapTap(const char *ifname,
char **res_ifname);
void delMacvtap(const char *ifname,
+ const unsigned char *macaddress,
+ const char *linkdev,
virVirtualPortProfileParamsPtr virtPortProfile);
# endif /* WITH_MACVTAP */
@@ -80,6 +82,16 @@ void delMacvtap(const char *ifname,
# define MACVTAP_MODE_VEPA_STR "vepa"
# define MACVTAP_MODE_BRIDGE_STR "bridge"
+int vpAssociatePortProfileId(const char *macvtap_ifname,
+ const unsigned char *macvtap_macaddr,
+ const char *linkdev,
+ const virVirtualPortProfileParamsPtr virtPort,
+ const unsigned char *vmuuid);
+
+int vpDisassociatePortProfileId(const char *macvtap_ifname,
+ const unsigned char *macvtap_macaddr,
+ const char *linkdev,
+ const virVirtualPortProfileParamsPtr virtPort);
VIR_ENUM_DECL(virVirtualPort)
Index: libvirt-acl/src/libvirt_private.syms
===================================================================
--- libvirt-acl.orig/src/libvirt_private.syms
+++ libvirt-acl/src/libvirt_private.syms
@@ -695,6 +695,9 @@ virArgvToString;
ifaceCtrl;
ifaceCheck;
ifaceGetIndex;
+ifaceGetFlags;
+ifaceIsUp;
+ifaceGetVlanID;
# usb.h
usbGetDevice;
Index: libvirt-acl/src/util/interface.c
===================================================================
--- libvirt-acl.orig/src/util/interface.c
+++ libvirt-acl/src/util/interface.c
@@ -30,6 +30,8 @@
#ifdef __linux__
# include <linux/if.h>
+# include <linux/sockios.h>
+# include <linux/if_vlan.h>
#endif
#include "internal.h"
@@ -42,6 +44,85 @@
virReportErrorHelper(NULL, VIR_FROM_NET, code, __FILE__, \
__FUNCTION__, __LINE__, __VA_ARGS__)
+#if __linux__
+static int
+getFlags(int fd, const char *ifname, struct ifreq *ifr) {
+
+ memset(ifr, 0, sizeof(*ifr));
+
+ if (virStrncpy(ifr->ifr_name,
+ ifname, strlen(ifname), sizeof(ifr->ifr_name)) == NULL)
+ return ENODEV;
+
+ if (ioctl(fd, SIOCGIFFLAGS, ifr) < 0)
+ return errno;
+
+ return 0;
+}
+
+
+/**
+ * ifaceGetFlags
+ *
+ * @ifname : name of the interface
+ * @flags : pointer to short holding the flags on success
+ *
+ * Get the flags of the interface. Returns 0 on success, error code on failure.
+ */
+int
+ifaceGetFlags(const char *ifname, short *flags) {
+ struct ifreq ifr;
+ int rc;
+ int fd = socket(PF_PACKET, SOCK_DGRAM, 0);
+
+ if (fd < 0)
+ return errno;
+
+ rc = getFlags(fd, ifname, &ifr);
+
+ *flags = ifr.ifr_flags;
+
+ close(fd);
+
+ return rc;
+}
+
+
+int
+ifaceIsUp(const char *ifname, bool *up) {
+ short flags;
+ int rc = ifaceGetFlags(ifname, &flags);
+
+ if (rc)
+ return rc;
+
+ *up = ((flags & IFF_UP) == IFF_UP);
+
+ return 0;
+}
+#else
+
+/* Note: Showstopper on cygwin is only missing PF_PACKET */
+
+int
+ifaceGetFlags(const char *ifname ATTRIBUTE_UNUSED,
+ short *flags ATTRIBUTE_UNUSED) {
+ ifaceError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("ifaceGetFlags is not supported on non-linux platforms"));
+ return ENOSYS;
+}
+
+int
+ifaceIsUp(const char *ifname ATTRIBUTE_UNUSED,
+ bool *up ATTRIBUTE_UNUSED) {
+
+ ifaceError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("ifaceIsUp is not supported on non-linux platforms"));
+ return ENOSYS;
+}
+
+#endif /* __linux__ */
+
/*
* chgIfaceFlags: Change flags on an interface
*
@@ -59,23 +140,16 @@
static int chgIfaceFlags(const char *ifname, short flagclear, short flagset) {
struct ifreq ifr;
int rc = 0;
- int flags;
+ short flags;
short flagmask = (~0 ^ flagclear);
int fd = socket(PF_PACKET, SOCK_DGRAM, 0);
if (fd < 0)
return errno;
- if (virStrncpy(ifr.ifr_name,
- ifname, strlen(ifname), sizeof(ifr.ifr_name)) == NULL) {
- rc = ENODEV;
+ rc = getFlags(fd, ifname, &ifr);
+ if (rc != 0)
goto err_exit;
- }
-
- if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) {
- rc = errno;
- goto err_exit;
- }
flags = (ifr.ifr_flags & flagmask) | flagset;
@@ -151,6 +225,8 @@ ifaceCheck(bool reportError, const char
if (fd < 0)
return errno;
+ memset(&ifr, 0, sizeof(ifr));
+
if (virStrncpy(ifr.ifr_name,
ifname, strlen(ifname), sizeof(ifr.ifr_name)) == NULL) {
if (reportError)
@@ -227,6 +303,8 @@ ifaceGetIndex(bool reportError, const ch
if (fd < 0)
return errno;
+ memset(&ifreq, 0, sizeof(ifreq));
+
if (virStrncpy(ifreq.ifr_name, ifname, strlen(ifname),
sizeof(ifreq.ifr_name)) == NULL) {
if (reportError)
@@ -269,3 +347,46 @@ ifaceGetIndex(bool reportError,
}
#endif /* __linux__ */
+
+#ifdef __linux__
+int
+ifaceGetVlanID(const char *vlanifname, int *vlanid) {
+ struct vlan_ioctl_args vlanargs = {
+ .cmd = GET_VLAN_VID_CMD,
+ };
+ int rc = 0;
+ int fd = socket(PF_PACKET, SOCK_DGRAM, 0);
+
+ if (fd < 0)
+ return errno;
+
+ if (virStrcpyStatic(vlanargs.device1, vlanifname) == NULL) {
+ rc = EINVAL;
+ goto err_exit;
+ }
+
+ if (ioctl(fd, SIOCGIFVLAN, &vlanargs) != 0) {
+ rc = errno;
+ goto err_exit;
+ }
+
+ *vlanid = vlanargs.u.VID;
+
+ err_exit:
+ close(fd);
+
+ return rc;
+}
+
+#else
+
+int
+ifaceGetVlanID(const char *vlanifname ATTRIBUTE_UNUSED,
+ int *vlanid ATTRIBUTE_UNUSED) {
+
+ ifaceError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("ifaceGetVlanID is not supported on non-linux platforms"));
+
+ return ENOSYS;
+}
+#endif /* __linux__ */
Index: libvirt-acl/src/util/interface.h
===================================================================
--- libvirt-acl.orig/src/util/interface.h
+++ libvirt-acl/src/util/interface.h
@@ -12,6 +12,9 @@
# include "datatypes.h"
+int ifaceGetFlags(const char *name, short *flags);
+int ifaceIsUp(const char *name, bool *up);
+
int ifaceCtrl(const char *name, bool up);
static inline int ifaceUp(const char *name) {
@@ -27,4 +30,6 @@ int ifaceCheck(bool reportError, const c
int ifaceGetIndex(bool reportError, const char *ifname, int *ifindex);
+int ifaceGetVlanID(const char *vlanifname, int *vlanid);
+
#endif /* __VIR_INTERFACE_H__ */
14 years, 7 months
[libvirt] Compile v0.8.0 under fedora 12 / mingw
by Dev.Atom
Hi there,
I'm trying to compile the libvirt from git (today).
I use these configure parameters :
./configure --prefix=/usr/i686-pc-mingw32/sys-root/mingw/ --host=i686-pc-mingw32 --without-xen --without-xen-inotify --without-umlt --without-openvz --without-phyp --without-xenapi --without-vbox --without-lxc --without-one --without-esx --without-libvirtd --without-sasl --without-yajl --without-polkit --without-avahi --without-selinux --without-secdriver-selinux --without-apparmor --without-capng --without-netcf --without-python --without-xen-proxy --without-hal --without-udev
And make crash in this way :
make[3]: Entering directory `/home/arnaud/Bureau/MingWinProjects/libvirt/git20102704/libvirt/src'
CC libvirt_util_la-authhelper.lo
CC libvirt_util_la-buf.lo
CC libvirt_util_la-conf.lo
CC libvirt_util_la-cgroup.lo
CC libvirt_util_la-event.lo
CC libvirt_util_la-hash.lo
CC libvirt_util_la-hooks.lo
In file included from ../src/util/threads-pthread.h:24,
from ../src/util/threads.h:65,
from ./conf/domain_conf.h:36,
from util/hooks.c:38:
/usr/i686-pc-mingw32/sys-root/mingw/include/pthread.h:307: error: redefinition of 'struct rpl_timespec'
make[3]: *** [libvirt_util_la-hooks.lo] Error 1
make[3]: Leaving directory `/home/arnaud/Bureau/MingWinProjects/libvirt/git20102704/libvirt/src'
make[2]: *** [all] Error 2
make[2]: Leaving directory `/home/arnaud/Bureau/MingWinProjects/libvirt/git20102704/libvirt/src'
make[1]: *** [all-recursive] Error 1
make[1]: Leaving directory `/home/arnaud/Bureau/MingWinProjects/libvirt/git20102704/libvirt'
make: *** [all] Error 2
Maybe I have made a mistake in the configure line ?
Any help ?
Thanks
Arnaud Champion
14 years, 7 months
[libvirt] [PATCH 0/2] Filesystem pool probing & filesystem building
by David Allan
The following patches add support for building a filesystem on the
source device when building a filesystem pool.
The first patch adds mkfs and libblkid to the build system.
The second patch adds two flags to virStorageBackendFileSystemBuild.
The first flag causes the build operation to probe for an existing
filesystem of the type specified in the pool XML. If an existing
filesystem of the specified type is present, mkfs is not executed and
the build call returns an error. Any other data present on the source
device will be overwritten. The second flag causes the build to
execute mkfs unconditionally overwriting whatever is currently on the
source device.
Calling virStorageBackendFileSystemBuild without any flags preserves
the current behavior, which is to make the directory on which the
filesystem will be mounted, but to leave the source device untouched.
David Allan (2):
Add mkfs and libblkid to build system
Add fs pool formatting
configure.ac | 25 ++++++++
include/libvirt/libvirt.h.in | 6 +-
include/libvirt/virterror.h | 2 +
libvirt.spec.in | 5 ++
po/POTFILES.in | 1 +
src/Makefile.am | 5 ++
src/libvirt_private.syms | 4 +
src/storage/storage_backend_fs.c | 88 +++++++++++++++++++++++++-
src/storage/storage_backend_fs.h | 19 ++++++
src/storage/storage_backend_fs_libblkid.c | 97 +++++++++++++++++++++++++++++
src/util/virterror.c | 12 ++++
tools/virsh.c | 15 ++++-
12 files changed, 273 insertions(+), 6 deletions(-)
create mode 100644 src/storage/storage_backend_fs_libblkid.c
14 years, 7 months