[libvirt] [PATCH 02/16] Rename and split the macvtap.c file

Daniel P. Berrange berrange at redhat.com
Tue Nov 15 11:14:15 UTC 2011


From: "Daniel P. Berrange" <berrange at redhat.com>

Rename the macvtap.c file to virnetdevmacvlan.c to reflect its
functionality. Move the port profile association code out into
virnetdevvportprofile.c. Make the APIs available unconditionally
to callers

* src/util/macvtap.h: rename to src/util/virnetdevmacvlan.h,
* src/util/macvtap.c: rename to src/util/virnetdevmacvlan.c
* src/util/virnetdevvportprofile.c, src/util/virnetdevvportprofile.h:
  Pull in vport association code
* src/Makefile.am, src/conf/domain_conf.h, src/qemu/qemu_conf.c,
  src/qemu/qemu_conf.h, src/qemu/qemu_driver.c: Update include
  paths & remove conditional compilation
---
 po/POTFILES.in                             |    3 +-
 src/Makefile.am                            |    2 +-
 src/conf/domain_conf.h                     |    2 +-
 src/qemu/qemu_command.c                    |   11 -
 src/qemu/qemu_conf.c                       |    1 -
 src/qemu/qemu_conf.h                       |    1 -
 src/qemu/qemu_driver.c                     |    1 -
 src/qemu/qemu_hotplug.c                    |    2 -
 src/qemu/qemu_migration.c                  |    5 -
 src/qemu/qemu_process.c                    |    2 -
 src/util/macvtap.c                         | 1209 ----------------------------
 src/util/virnetdevmacvlan.c                |  423 ++++++++++
 src/util/{macvtap.h => virnetdevmacvlan.h} |   38 +-
 src/util/virnetdevvportprofile.c           |  823 +++++++++++++++++++
 src/util/virnetdevvportprofile.h           |   33 +-
 15 files changed, 1283 insertions(+), 1273 deletions(-)
 delete mode 100644 src/util/macvtap.c
 create mode 100644 src/util/virnetdevmacvlan.c
 rename src/util/{macvtap.h => virnetdevmacvlan.h} (63%)

diff --git a/po/POTFILES.in b/po/POTFILES.in
index 810cf68..6797298 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -115,7 +115,6 @@ src/util/iohelper.c
 src/util/interface.c
 src/util/iptables.c
 src/util/json.c
-src/util/macvtap.c
 src/util/netlink.c
 src/util/pci.c
 src/util/processinfo.c
@@ -128,7 +127,9 @@ src/util/viraudit.c
 src/util/virfile.c
 src/util/virnetdev.c
 src/util/virnetdevbridge.c
+src/util/virnetdevmacvlan.c
 src/util/virnetdevtap.c
+src/util/virnetdevvportprofile.c
 src/util/virpidfile.c
 src/util/virsocketaddr.c
 src/util/virterror.c
diff --git a/src/Makefile.am b/src/Makefile.am
index fbe4c4d..e44c53a 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -67,7 +67,6 @@ UTIL_SOURCES =							\
 		util/dnsmasq.c util/dnsmasq.h                   \
 		util/json.c util/json.h				\
 		util/logging.c util/logging.h			\
-		util/macvtap.c util/macvtap.h			\
 		util/memory.c util/memory.h			\
 		util/netlink.c util/netlink.h			\
 		util/pci.c util/pci.h				\
@@ -95,6 +94,7 @@ UTIL_SOURCES =							\
 		util/virnetdev.h util/virnetdev.c		\
 		util/virnetdevbandwidth.h util/virnetdevbandwidth.c \
 		util/virnetdevbridge.h util/virnetdevbridge.c	\
+		util/virnetdevmacvlan.c util/virnetdevmacvlan.h	\
 		util/virnetdevtap.h util/virnetdevtap.c		\
 		util/virnetdevveth.h util/virnetdevveth.c \
 		util/virnetdevvportprofile.h util/virnetdevvportprofile.c \
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index c360674..9528199 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -38,7 +38,7 @@
 # include "virsocketaddr.h"
 # include "nwfilter_params.h"
 # include "nwfilter_conf.h"
-# include "macvtap.h"
+# include "virnetdevmacvlan.h"
 # include "sysinfo.h"
 # include "virnetdevvportprofile.h"
 # include "virnetdevbandwidth.h"
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index db65035..4514713 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -141,7 +141,6 @@ qemuPhysIfaceConnect(virDomainDefPtr def,
                      enum virNetDevVPortProfileOp vmop)
 {
     int rc;
-#if WITH_MACVTAP
     char *res_ifname = NULL;
     int vnet_hdr = 0;
 
@@ -163,16 +162,6 @@ qemuPhysIfaceConnect(virDomainDefPtr def,
         net->ifname = res_ifname;
     }
 
-#else
-    (void)def;
-    (void)net;
-    (void)qemuCaps;
-    (void)driver;
-    (void)vmop;
-    qemuReportError(VIR_ERR_INTERNAL_ERROR,
-                    "%s", _("No support for macvtap device"));
-    rc = -1;
-#endif
     return rc;
 }
 
diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
index d7e9d7d..9d93371 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -49,7 +49,6 @@
 #include "xml.h"
 #include "nodeinfo.h"
 #include "logging.h"
-#include "macvtap.h"
 #include "cpu/cpu.h"
 #include "domain_nwfilter.h"
 #include "virfile.h"
diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h
index bbe7e74..e13cd08 100644
--- a/src/qemu/qemu_conf.h
+++ b/src/qemu/qemu_conf.h
@@ -39,7 +39,6 @@
 # include "cpu_conf.h"
 # include "driver.h"
 # include "bitmap.h"
-# include "macvtap.h"
 # include "command.h"
 # include "threadpool.h"
 # include "locking/lock_manager.h"
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 3e5cbf6..fe2ab85 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -77,7 +77,6 @@
 #include "libvirt_internal.h"
 #include "xml.h"
 #include "cpu/cpu.h"
-#include "macvtap.h"
 #include "sysinfo.h"
 #include "domain_nwfilter.h"
 #include "hooks.h"
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index 47ece57..bbcf9ca 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -1909,7 +1909,6 @@ int qemuDomainDetachNetDevice(struct qemud_driver *driver,
 
     virDomainConfNWFilterTeardown(detach);
 
-#if WITH_MACVTAP
     if (virDomainNetGetActualType(detach) == VIR_DOMAIN_NET_TYPE_DIRECT) {
         ignore_value(virNetDevMacVLanDelete(detach->ifname, detach->mac,
                                             virDomainNetGetActualDirectDev(detach),
@@ -1918,7 +1917,6 @@ int qemuDomainDetachNetDevice(struct qemud_driver *driver,
                                             driver->stateDir));
         VIR_FREE(detach->ifname);
     }
-#endif
 
     if ((driver->macFilter) && (detach->ifname != NULL)) {
         if ((errno = networkDisallowMacOnPort(driver,
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index 2525210..3b50fc6 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -2512,7 +2512,6 @@ qemuMigrationPerform(struct qemud_driver *driver,
     }
 }
 
-#if WITH_MACVTAP
 static void
 qemuMigrationVPAssociatePortProfiles(virDomainDefPtr def) {
     int i;
@@ -2547,10 +2546,6 @@ err_exit:
         }
     }
 }
-#else /* !WITH_MACVTAP */
-static void
-qemuMigrationVPAssociatePortProfiles(virDomainDefPtr def ATTRIBUTE_UNUSED) { }
-#endif /* WITH_MACVTAP */
 
 
 virDomainPtr
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 4dc9357..f4096f8 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -3410,7 +3410,6 @@ void qemuProcessStop(struct qemud_driver *driver,
     def = vm->def;
     for (i = 0; i < def->nnets; i++) {
         virDomainNetDefPtr net = def->nets[i];
-#if WITH_MACVTAP
         if (virDomainNetGetActualType(net) == VIR_DOMAIN_NET_TYPE_DIRECT) {
             ignore_value(virNetDevMacVLanDelete(net->ifname, net->mac,
                                                 virDomainNetGetActualDirectDev(net),
@@ -3419,7 +3418,6 @@ void qemuProcessStop(struct qemud_driver *driver,
                                                 driver->stateDir));
             VIR_FREE(net->ifname);
         }
-#endif
         /* release the physical device (or any other resources used by
          * this interface in the network driver
          */
diff --git a/src/util/macvtap.c b/src/util/macvtap.c
deleted file mode 100644
index c793493..0000000
--- a/src/util/macvtap.c
+++ /dev/null
@@ -1,1209 +0,0 @@
-/*
- * Copyright (C) 2010-2011 Red Hat, Inc.
- * Copyright (C) 2010 IBM Corporation
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
- *
- * Authors:
- *     Stefan Berger <stefanb at us.ibm.com>
- *
- * Notes:
- * netlink: http://lovezutto.googlepages.com/netlink.pdf
- *          iproute2 package
- *
- */
-
-#include <config.h>
-
-#include <stdint.h>
-
-#if WITH_MACVTAP || WITH_VIRTUALPORT
-
-# include <stdio.h>
-# include <errno.h>
-# include <fcntl.h>
-# include <c-ctype.h>
-# include <sys/socket.h>
-# include <sys/ioctl.h>
-
-# include <linux/if.h>
-# include <linux/if_tun.h>
-
-/* Older kernels lacked this enum value.  */
-# if !HAVE_DECL_MACVLAN_MODE_PASSTHRU
-#  define MACVLAN_MODE_PASSTHRU 8
-# endif
-
-#endif /* WITH_MACVTAP || WITH_VIRTUALPORT */
-
-#include "util.h"
-#include "macvtap.h"
-#include "virnetdev.h"
-
-VIR_ENUM_IMPL(virNetDevMacVLanMode, VIR_NETDEV_MACVLAN_MODE_LAST,
-              "vepa",
-              "private",
-              "bridge",
-              "passthrough")
-
-#if WITH_MACVTAP || WITH_VIRTUALPORT
-
-# include "memory.h"
-# include "logging.h"
-# include "interface.h"
-# include "virterror_internal.h"
-# include "uuid.h"
-# include "virfile.h"
-# include "netlink.h"
-
-# define VIR_FROM_THIS VIR_FROM_NET
-
-# define macvtapError(code, ...)                                           \
-        virReportErrorHelper(VIR_FROM_NET, code, __FILE__,                 \
-                             __FUNCTION__, __LINE__, __VA_ARGS__)
-
-# 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 STATUS_POLL_TIMEOUT_USEC (10 * MICROSEC_PER_SEC)
-# define STATUS_POLL_INTERVL_USEC (MICROSEC_PER_SEC / 8)
-
-
-# define LLDPAD_PID_FILE  "/var/run/lldpad.pid"
-
-
-enum virNetDevVPortProfileLinkOp {
-    VIR_NETDEV_VPORT_PROFILE_LINK_OP_ASSOCIATE = 0x1,
-    VIR_NETDEV_VPORT_PROFILE_LINK_OP_DISASSOCIATE = 0x2,
-    VIR_NETDEV_VPORT_PROFILE_LINK_OP_PREASSOCIATE = 0x3,
-    VIR_NETDEV_VPORT_PROFILE_LINK_OP_PREASSOCIATE_RR = 0x4,
-};
-
-
-
-
-# if WITH_MACVTAP
-
-/**
- * virNetDevMacVLanTapOpen:
- * Open the macvtap's tap device.
- * @ifname: Name of the macvtap interface
- * @retries : Number of retries in case udev for example may need to be
- *            waited for to create the tap chardev
- * Returns negative value in case of error, the file descriptor otherwise.
- */
-static
-int virNetDevMacVLanTapOpen(const char *ifname,
-                            int retries)
-{
-    FILE *file;
-    char path[64];
-    int ifindex;
-    char tapname[50];
-    int tapfd;
-
-    if (snprintf(path, sizeof(path),
-                 "/sys/class/net/%s/ifindex", ifname) >= sizeof(path)) {
-        virReportSystemError(errno,
-                             "%s",
-                             _("buffer for ifindex path is too small"));
-        return -1;
-    }
-
-    file = fopen(path, "r");
-
-    if (!file) {
-        virReportSystemError(errno,
-                             _("cannot open macvtap file %s to determine "
-                               "interface index"), path);
-        return -1;
-    }
-
-    if (fscanf(file, "%d", &ifindex) != 1) {
-        virReportSystemError(errno,
-                             "%s",_("cannot determine macvtap's tap device "
-                             "interface index"));
-        VIR_FORCE_FCLOSE(file);
-        return -1;
-    }
-
-    VIR_FORCE_FCLOSE(file);
-
-    if (snprintf(tapname, sizeof(tapname),
-                 "/dev/tap%d", ifindex) >= sizeof(tapname)) {
-        virReportSystemError(errno,
-                             "%s",
-                             _("internal buffer for tap device is too small"));
-        return -1;
-    }
-
-    while (1) {
-        /* may need to wait for udev to be done */
-        tapfd = open(tapname, O_RDWR);
-        if (tapfd < 0 && retries > 0) {
-            retries--;
-            usleep(20000);
-            continue;
-        }
-        break;
-    }
-
-    if (tapfd < 0)
-        virReportSystemError(errno,
-                             _("cannot open macvtap tap device %s"),
-                             tapname);
-
-    return tapfd;
-}
-
-
-/**
- * virNetDevMacVLanTapSetup:
- * @tapfd: file descriptor of the macvtap tap
- * @vnet_hdr: 1 to enable IFF_VNET_HDR, 0 to disable it
- *
- * Returns 0 on success, -1 in case of fatal error, error code otherwise.
- *
- * Turn the IFF_VNET_HDR flag, if requested and available, make sure
- * it's off in the other cases.
- * A fatal error is defined as the VNET_HDR flag being set but it cannot
- * be turned off for some reason. This is reported with -1. Other fatal
- * error is not being able to read the interface flags. In that case the
- * macvtap device should not be used.
- */
-static int
-virNetDevMacVLanTapSetup(int tapfd, int vnet_hdr)
-{
-    unsigned int features;
-    struct ifreq ifreq;
-    short new_flags = 0;
-    int rc_on_fail = 0;
-    const char *errmsg = NULL;
-
-    memset(&ifreq, 0, sizeof(ifreq));
-
-    if (ioctl(tapfd, TUNGETIFF, &ifreq) < 0) {
-        virReportSystemError(errno, "%s",
-                             _("cannot get interface flags on macvtap tap"));
-        return -1;
-    }
-
-    new_flags = ifreq.ifr_flags;
-
-    if ((ifreq.ifr_flags & IFF_VNET_HDR) && !vnet_hdr) {
-        new_flags = ifreq.ifr_flags & ~IFF_VNET_HDR;
-        rc_on_fail = -1;
-        errmsg = _("cannot clean IFF_VNET_HDR flag on macvtap tap");
-    } else if ((ifreq.ifr_flags & IFF_VNET_HDR) == 0 && vnet_hdr) {
-        if (ioctl(tapfd, TUNGETFEATURES, &features) < 0) {
-            virReportSystemError(errno, "%s",
-                   _("cannot get feature flags on macvtap tap"));
-            return -1;
-        }
-        if ((features & IFF_VNET_HDR)) {
-            new_flags = ifreq.ifr_flags | IFF_VNET_HDR;
-            errmsg = _("cannot set IFF_VNET_HDR flag on macvtap tap");
-        }
-    }
-
-    if (new_flags != ifreq.ifr_flags) {
-        ifreq.ifr_flags = new_flags;
-        if (ioctl(tapfd, TUNSETIFF, &ifreq) < 0) {
-            virReportSystemError(errno, "%s", errmsg);
-            return rc_on_fail;
-        }
-    }
-
-    return 0;
-}
-
-
-static const uint32_t modeMap[VIR_NETDEV_MACVLAN_MODE_LAST] = {
-    [VIR_NETDEV_MACVLAN_MODE_VEPA] = MACVLAN_MODE_VEPA,
-    [VIR_NETDEV_MACVLAN_MODE_PRIVATE] = MACVLAN_MODE_PRIVATE,
-    [VIR_NETDEV_MACVLAN_MODE_BRIDGE] = MACVLAN_MODE_BRIDGE,
-    [VIR_NETDEV_MACVLAN_MODE_PASSTHRU] = MACVLAN_MODE_PASSTHRU,
-};
-
-/**
- * virNetDevMacVLanCreate:
- * 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: int describing the mode for 'bridge', 'vepa', 'private' or 'passthru'.
- * @vnet_hdr: 1 to enable IFF_VNET_HDR, 0 to disable it
- * @vmuuid: The UUID of the VM the macvtap belongs to
- * @virtPortProfile: pointer to object holding the virtual port profile data
- * @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.
- *
- * Returns file descriptor of the tap device in case of success,
- * negative value otherwise with error reported.
- *
- */
-int virNetDevMacVLanCreate(const char *tgifname,
-                           const unsigned char *macaddress,
-                           const char *linkdev,
-                           enum virNetDevMacVLanMode mode,
-                           int vnet_hdr,
-                           const unsigned char *vmuuid,
-                           virNetDevVPortProfilePtr virtPortProfile,
-                           char **res_ifname,
-                           enum virNetDevVPortProfileOp vmOp,
-                           char *stateDir,
-                           virNetDevBandwidthPtr bandwidth)
-{
-    const char *type = "macvtap";
-    int c, rc;
-    char ifname[IFNAMSIZ];
-    int retries, do_retry = 0;
-    uint32_t macvtapMode;
-    const char *cr_ifname;
-    int ifindex;
-
-    macvtapMode = modeMap[mode];
-
-    *res_ifname = NULL;
-
-    VIR_DEBUG("%s: VM OPERATION: %s", __FUNCTION__, virNetDevVPortProfileOpTypeToString(vmOp));
-
-    /** Note: When using PASSTHROUGH mode with MACVTAP devices the link
-     * device's MAC address must be set to the VMs MAC address. In
-     * order to not confuse the first switch or bridge in line this MAC
-     * address must be reset when the VM is shut down.
-     * This is especially important when using SRIOV capable cards that
-     * emulate their switch in firmware.
-     */
-    if (mode == VIR_NETDEV_MACVLAN_MODE_PASSTHRU) {
-        if (ifaceReplaceMacAddress(macaddress, linkdev, stateDir) < 0) {
-            return -1;
-        }
-    }
-
-    if (tgifname) {
-        if(ifaceGetIndex(false, tgifname, &ifindex) == 0) {
-            if (STRPREFIX(tgifname,
-                          MACVTAP_NAME_PREFIX)) {
-                goto create_name;
-            }
-            virReportSystemError(errno,
-                                 _("Interface %s already exists"), tgifname);
-            return -1;
-        }
-        cr_ifname = tgifname;
-        rc = ifaceMacvtapLinkAdd(type, macaddress, 6, tgifname, linkdev,
-                                 macvtapMode, &do_retry);
-        if (rc < 0)
-            return -1;
-    } else {
-create_name:
-        retries = 5;
-        for (c = 0; c < 8192; c++) {
-            snprintf(ifname, sizeof(ifname), MACVTAP_NAME_PATTERN, c);
-            if (ifaceGetIndex(false, ifname, &ifindex) == -ENODEV) {
-                rc = ifaceMacvtapLinkAdd(type, macaddress, 6, ifname, linkdev,
-                                         macvtapMode, &do_retry);
-                if (rc == 0)
-                    break;
-
-                if (do_retry && --retries)
-                    continue;
-                return -1;
-            }
-        }
-        cr_ifname = ifname;
-    }
-
-    if (virNetDevVPortProfileAssociate(cr_ifname,
-                                       virtPortProfile,
-                                       macaddress,
-                                       linkdev,
-                                       vmuuid, vmOp) < 0) {
-        rc = -1;
-        goto link_del_exit;
-    }
-
-    if (virNetDevSetOnline(cr_ifname, true) < 0) {
-        rc = -1;
-        goto disassociate_exit;
-    }
-
-    rc = virNetDevMacVLanTapOpen(cr_ifname, 10);
-    if (rc >= 0) {
-        if (virNetDevMacVLanTapSetup(rc, vnet_hdr) < 0) {
-            VIR_FORCE_CLOSE(rc); /* sets rc to -1 */
-            goto disassociate_exit;
-        }
-        *res_ifname = strdup(cr_ifname);
-    } else
-        goto disassociate_exit;
-
-    if (virNetDevBandwidthSet(cr_ifname, bandwidth) < 0) {
-        macvtapError(VIR_ERR_INTERNAL_ERROR,
-                     _("cannot set bandwidth limits on %s"),
-                     cr_ifname);
-        rc = -1;
-        goto disassociate_exit;
-    }
-
-
-    return rc;
-
-disassociate_exit:
-    ignore_value(virNetDevVPortProfileDisassociate(cr_ifname,
-                                                   virtPortProfile,
-                                                   macaddress,
-                                                   linkdev,
-                                                   vmOp));
-
-link_del_exit:
-    ifaceLinkDel(cr_ifname);
-
-    return rc;
-}
-
-
-/**
- * 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
- * it with the switch if port profile parameters
- * were provided.
- */
-int virNetDevMacVLanDelete(const char *ifname,
-                           const unsigned char *macaddr,
-                           const char *linkdev,
-                           int mode,
-                           virNetDevVPortProfilePtr virtPortProfile,
-                           char *stateDir)
-{
-    int ret = 0;
-    if (mode == VIR_NETDEV_MACVLAN_MODE_PASSTHRU) {
-        ifaceRestoreMacAddress(linkdev, stateDir);
-    }
-
-    if (ifname) {
-        if (virNetDevVPortProfileDisassociate(ifname,
-                                              virtPortProfile,
-                                              macaddr,
-                                              linkdev,
-                                              VIR_NETDEV_VPORT_PROFILE_OP_DESTROY) < 0)
-            ret = -1;
-        if (ifaceLinkDel(ifname) < 0)
-            ret = -1;
-    }
-    return ret;
-}
-
-# endif /* WITH_MACVTAP */
-
-# ifdef IFLA_PORT_MAX
-
-static struct nla_policy ifla_port_policy[IFLA_PORT_MAX + 1] =
-{
-  [IFLA_PORT_RESPONSE]      = { .type = NLA_U16 },
-};
-
-
-static uint32_t
-virNetDevVPortProfileGetLldpadPid(void) {
-    int fd;
-    uint32_t pid = 0;
-
-    fd = open(LLDPAD_PID_FILE, O_RDONLY);
-    if (fd >= 0) {
-        char buffer[10];
-
-        if (saferead(fd, buffer, sizeof(buffer)) <= sizeof(buffer)) {
-            unsigned int res;
-            char *endptr;
-
-            if (virStrToLong_ui(buffer, &endptr, 10, &res) == 0
-                && (*endptr == '\0' || 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);
-    }
-
-    VIR_FORCE_CLOSE(fd);
-
-    return pid;
-}
-
-
-/**
- * virNetDevVPortProfileGetStatus:
- *
- * 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
-virNetDevVPortProfileGetStatus(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;
-            rc = 0;
-        } 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
-virNetDevVPortProfileOpSetLink(const char *ifname, int ifindex,
-                               bool nltarget_kernel,
-                               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 = -1;
-    struct nlmsghdr *resp;
-    struct nlmsgerr *err;
-    struct ifinfomsg ifinfo = {
-        .ifi_family = AF_UNSPEC,
-        .ifi_index  = ifindex,
-    };
-    unsigned char *recvbuf = NULL;
-    unsigned int recvbuflen = 0;
-    uint32_t pid = 0;
-    struct nl_msg *nl_msg;
-    struct nlattr *vfports = NULL, *vfport;
-
-    nl_msg = nlmsg_alloc_simple(RTM_SETLINK, NLM_F_REQUEST);
-    if (!nl_msg) {
-        virReportOOMError();
-        return rc;
-    }
-
-    if (nlmsg_append(nl_msg,  &ifinfo, sizeof(ifinfo), NLMSG_ALIGNTO) < 0)
-        goto buffer_too_small;
-
-    if (ifname &&
-        nla_put(nl_msg, IFLA_IFNAME, strlen(ifname)+1, ifname) < 0)
-        goto buffer_too_small;
-
-    if (macaddr || vlanid >= 0) {
-        struct nlattr *vfinfolist, *vfinfo;
-
-        if (!(vfinfolist = nla_nest_start(nl_msg, IFLA_VFINFO_LIST)))
-            goto buffer_too_small;
-
-        if (!(vfinfo = nla_nest_start(nl_msg, IFLA_VF_INFO)))
-            goto buffer_too_small;
-
-        if (macaddr) {
-            struct ifla_vf_mac ifla_vf_mac = {
-                .vf = vf,
-                .mac = { 0, },
-            };
-
-            memcpy(ifla_vf_mac.mac, macaddr, 6);
-
-            if (nla_put(nl_msg, IFLA_VF_MAC, sizeof(ifla_vf_mac),
-                        &ifla_vf_mac) < 0)
-                goto buffer_too_small;
-        }
-
-        if (vlanid >= 0) {
-            struct ifla_vf_vlan ifla_vf_vlan = {
-                .vf = vf,
-                .vlan = vlanid,
-                .qos = 0,
-            };
-
-            if (nla_put(nl_msg, IFLA_VF_VLAN, sizeof(ifla_vf_vlan),
-                        &ifla_vf_vlan) < 0)
-                goto buffer_too_small;
-        }
-
-        nla_nest_end(nl_msg, vfinfo);
-        nla_nest_end(nl_msg, vfinfolist);
-    }
-
-    if (vf == PORT_SELF_VF && nltarget_kernel) {
-        if (!(vfport = nla_nest_start(nl_msg, IFLA_PORT_SELF)))
-            goto buffer_too_small;
-    } else {
-        if (!(vfports = nla_nest_start(nl_msg, IFLA_VF_PORTS)))
-            goto buffer_too_small;
-
-        /* begin nesting vfports */
-        if (!(vfport = nla_nest_start(nl_msg, IFLA_VF_PORT)))
-            goto buffer_too_small;
-    }
-
-    if (profileId) {
-        if (nla_put(nl_msg, IFLA_PORT_PROFILE, strlen(profileId) + 1,
-                    profileId) < 0)
-            goto buffer_too_small;
-    }
-
-    if (portVsi) {
-        if (nla_put(nl_msg, IFLA_PORT_VSI_TYPE, sizeof(*portVsi),
-                    portVsi) < 0)
-            goto buffer_too_small;
-    }
-
-    if (instanceId) {
-        if (nla_put(nl_msg, IFLA_PORT_INSTANCE_UUID, VIR_UUID_BUFLEN,
-                    instanceId) < 0)
-            goto buffer_too_small;
-    }
-
-    if (hostUUID) {
-        if (nla_put(nl_msg, IFLA_PORT_HOST_UUID, VIR_UUID_BUFLEN,
-                    hostUUID) < 0)
-            goto buffer_too_small;
-    }
-
-    if (vf != PORT_SELF_VF) {
-        if (nla_put(nl_msg, IFLA_PORT_VF, sizeof(vf), &vf) < 0)
-            goto buffer_too_small;
-    }
-
-    if (nla_put(nl_msg, IFLA_PORT_REQUEST, sizeof(op), &op) < 0)
-        goto buffer_too_small;
-
-    /* end nesting of vport */
-    nla_nest_end(nl_msg, vfport);
-
-    if (vfports) {
-        /* end nesting of vfports */
-        nla_nest_end(nl_msg, vfports);
-    }
-
-    if (!nltarget_kernel) {
-        pid = virNetDevVPortProfileGetLldpadPid();
-        if (pid == 0)
-            goto err_exit;
-    }
-
-    if (nlComm(nl_msg, &recvbuf, &recvbuflen, pid) < 0)
-        goto err_exit;
-
-    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);
-            goto err_exit;
-        }
-        break;
-
-    case NLMSG_DONE:
-        break;
-
-    default:
-        goto malformed_resp;
-    }
-
-    rc = 0;
-
-err_exit:
-    nlmsg_free(nl_msg);
-
-    VIR_FREE(recvbuf);
-
-    return rc;
-
-malformed_resp:
-    nlmsg_free(nl_msg);
-
-    macvtapError(VIR_ERR_INTERNAL_ERROR, "%s",
-                 _("malformed netlink response message"));
-    VIR_FREE(recvbuf);
-    return rc;
-
-buffer_too_small:
-    nlmsg_free(nl_msg);
-
-    macvtapError(VIR_ERR_INTERNAL_ERROR, "%s",
-                 _("allocated netlink buffer is too small"));
-    return rc;
-}
-
-
-/* Returns 0 on success, -1 on general failure, and -2 on timeout */
-static int
-virNetDevVPortProfileOpCommon(const char *ifname, int ifindex,
-                              bool nltarget_kernel,
-                              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;
-    unsigned 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 = virNetDevVPortProfileOpSetLink(ifname, ifindex,
-                                        nltarget_kernel,
-                                        macaddr,
-                                        vlanid,
-                                        profileId,
-                                        portVsi,
-                                        instanceId,
-                                        hostUUID,
-                                        vf,
-                                        op);
-    if (rc < 0) {
-        macvtapError(VIR_ERR_INTERNAL_ERROR, "%s",
-                     _("sending of PortProfileRequest failed."));
-        return rc;
-    }
-
-    while (--repeats >= 0) {
-        rc = ifaceMacvtapLinkDump(nltarget_kernel, NULL, ifindex, tb,
-                                  &recvbuf, virNetDevVPortProfileGetLldpadPid);
-        if (rc < 0)
-            goto err_exit;
-
-        rc = virNetDevVPortProfileGetStatus(tb, vf, instanceId, nltarget_kernel,
-                                            is8021Qbg, &status);
-        if (rc < 0)
-            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 = -2;
-    }
-
-err_exit:
-    VIR_FREE(recvbuf);
-
-    return rc;
-}
-
-# endif /* IFLA_PORT_MAX */
-
-
-# ifdef IFLA_VF_PORT_MAX
-
-static int
-virNetDevVPortProfileGetPhysdevAndVlan(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)) < 0)
-            return ret;
-        if (nth == 0)
-            break;
-        if (*vlanid == -1) {
-            if (ifaceGetVlanID(root_ifname, vlanid) < 0)
-                *vlanid = -1;
-        }
-
-        ifindex = *root_ifindex;
-        ifname = NULL;
-    }
-
-    return 0;
-}
-
-# endif
-
-/* Returns 0 on success, -1 on general failure, and -2 on timeout */
-static int
-virNetDevVPortProfileOp8021Qbg(const char *ifname,
-                               const unsigned char *macaddr,
-                               const virNetDevVPortProfilePtr virtPort,
-                               enum virNetDevVPortProfileLinkOp virtPortOp)
-{
-    int rc = 0;
-
-# 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 (virNetDevVPortProfileGetPhysdevAndVlan(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 VIR_NETDEV_VPORT_PROFILE_LINK_OP_PREASSOCIATE:
-        op = PORT_REQUEST_PREASSOCIATE;
-        break;
-    case VIR_NETDEV_VPORT_PROFILE_LINK_OP_ASSOCIATE:
-        op = PORT_REQUEST_ASSOCIATE;
-        break;
-    case VIR_NETDEV_VPORT_PROFILE_LINK_OP_DISASSOCIATE:
-        op = PORT_REQUEST_DISASSOCIATE;
-        break;
-    default:
-        macvtapError(VIR_ERR_INTERNAL_ERROR,
-                     _("operation type %d not supported"), virtPortOp);
-        rc = -1;
-        goto err_exit;
-    }
-
-    rc = virNetDevVPortProfileOpCommon(physdev_ifname, physdev_ifindex,
-                                       nltarget_kernel,
-                                       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
-virNetDevVPortProfileGetPhysfnDev(const char *linkdev,
-                                  int32_t *vf,
-                                  char **physfndev)
-{
-    int rc = -1;
-
-    if (ifaceIsVirtualFunction(linkdev) == 1) {
-        /* if linkdev is SR-IOV VF, then set vf = VF index */
-        /* and set linkdev = PF device */
-
-        rc = ifaceGetPhysicalFunction(linkdev, physfndev);
-        if (!rc)
-            rc = ifaceGetVirtualFunctionIndex(*physfndev, linkdev, vf);
-    } else {
-
-        /* Not SR-IOV VF: physfndev is linkdev and VF index
-         * refers to linkdev self
-         */
-
-        *vf = PORT_SELF_VF;
-        *physfndev = strdup(linkdev);
-        if (!*physfndev) {
-            virReportOOMError();
-            goto err_exit;
-        }
-        rc = 0;
-    }
-
-err_exit:
-
-    return rc;
-}
-# endif /* IFLA_VF_PORT_MAX */
-
-/* Returns 0 on success, -1 on general failure, and -2 on timeout */
-static int
-virNetDevVPortProfileOp8021Qbh(const char *ifname,
-                               const unsigned char *macaddr,
-                               const virNetDevVPortProfilePtr virtPort,
-                               const unsigned char *vm_uuid,
-                               enum virNetDevVPortProfileLinkOp virtPortOp)
-{
-    int rc = 0;
-
-# ifndef IFLA_VF_PORT_MAX
-
-    (void)ifname;
-    (void)macaddr;
-    (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 = NULL;
-    unsigned char hostuuid[VIR_UUID_BUFLEN];
-    int32_t vf;
-    bool nltarget_kernel = true;
-    int ifindex;
-    int vlanid = -1;
-
-    rc = virNetDevVPortProfileGetPhysfnDev(ifname, &vf, &physfndev);
-    if (rc < 0)
-        goto err_exit;
-
-    rc = ifaceGetIndex(true, physfndev, &ifindex);
-    if (rc < 0)
-        goto err_exit;
-
-    switch (virtPortOp) {
-    case VIR_NETDEV_VPORT_PROFILE_LINK_OP_PREASSOCIATE_RR:
-    case VIR_NETDEV_VPORT_PROFILE_LINK_OP_ASSOCIATE:
-        errno = virGetHostUUID(hostuuid);
-        if (errno) {
-            rc = -1;
-            goto err_exit;
-        }
-
-        rc = virNetDevVPortProfileOpCommon(NULL, ifindex,
-                                           nltarget_kernel,
-                                           macaddr,
-                                           vlanid,
-                                           virtPort->u.virtPort8021Qbh.profileID,
-                                           NULL,
-                                           vm_uuid,
-                                           hostuuid,
-                                           vf,
-                                           (virtPortOp == VIR_NETDEV_VPORT_PROFILE_LINK_OP_PREASSOCIATE_RR) ?
-                                           PORT_REQUEST_PREASSOCIATE_RR
-                                           : PORT_REQUEST_ASSOCIATE);
-        if (rc == -2)
-            /* Association timed out, disassociate */
-            virNetDevVPortProfileOpCommon(NULL, ifindex,
-                                          nltarget_kernel,
-                                          NULL,
-                                          vlanid,
-                                          NULL,
-                                          NULL,
-                                          NULL,
-                                          NULL,
-                                          vf,
-                                          PORT_REQUEST_DISASSOCIATE);
-        break;
-
-    case VIR_NETDEV_VPORT_PROFILE_LINK_OP_DISASSOCIATE:
-        rc = virNetDevVPortProfileOpCommon(NULL, ifindex,
-                                           nltarget_kernel,
-                                           NULL,
-                                           vlanid,
-                                           NULL,
-                                           NULL,
-                                           NULL,
-                                           NULL,
-                                           vf,
-                                           PORT_REQUEST_DISASSOCIATE);
-        break;
-
-    default:
-        macvtapError(VIR_ERR_INTERNAL_ERROR,
-                     _("operation type %d not supported"), virtPortOp);
-        rc = -1;
-    }
-
-err_exit:
-    VIR_FREE(physfndev);
-
-# endif /* IFLA_VF_PORT_MAX */
-
-    return rc;
-}
-
-/**
- * virNetDevVPortProfileAssociate:
- *
- * @macvtap_ifname: The name of the macvtap device
- * @virtPort: pointer to the object holding port profile parameters
- * @vmuuid : the UUID of the virtual machine
- * @vmOp : The VM operation (i.e., create, no-op)
- *
- * 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.
- */
-int
-virNetDevVPortProfileAssociate(const char *macvtap_ifname,
-                               const virNetDevVPortProfilePtr virtPort,
-                               const unsigned char *macvtap_macaddr,
-                               const char *linkdev,
-                               const unsigned char *vmuuid,
-                               enum virNetDevVPortProfileOp vmOp)
-{
-    int rc = 0;
-
-    VIR_DEBUG("Associating port profile '%p' on link device '%s'",
-              virtPort, macvtap_ifname);
-
-    VIR_DEBUG("%s: VM OPERATION: %s", __FUNCTION__, virNetDevVPortProfileOpTypeToString(vmOp));
-
-    if (!virtPort || vmOp == VIR_NETDEV_VPORT_PROFILE_OP_NO_OP)
-        return 0;
-
-    switch (virtPort->virtPortType) {
-    case VIR_NETDEV_VPORT_PROFILE_NONE:
-    case VIR_NETDEV_VPORT_PROFILE_LAST:
-        break;
-
-    case VIR_NETDEV_VPORT_PROFILE_8021QBG:
-        rc = virNetDevVPortProfileOp8021Qbg(macvtap_ifname, macvtap_macaddr,
-                                            virtPort,
-                                            (vmOp == VIR_NETDEV_VPORT_PROFILE_OP_MIGRATE_IN_START)
-                                            ? VIR_NETDEV_VPORT_PROFILE_LINK_OP_PREASSOCIATE
-                                            : VIR_NETDEV_VPORT_PROFILE_LINK_OP_ASSOCIATE);
-        break;
-
-    case VIR_NETDEV_VPORT_PROFILE_8021QBH:
-        rc = virNetDevVPortProfileOp8021Qbh(linkdev, macvtap_macaddr,
-                                            virtPort, vmuuid,
-                                            (vmOp == VIR_NETDEV_VPORT_PROFILE_OP_MIGRATE_IN_START)
-                                            ? VIR_NETDEV_VPORT_PROFILE_LINK_OP_PREASSOCIATE_RR
-                                            : VIR_NETDEV_VPORT_PROFILE_LINK_OP_ASSOCIATE);
-        if (vmOp != VIR_NETDEV_VPORT_PROFILE_OP_MIGRATE_IN_START && !rc) {
-            /* XXX bogus error handling */
-            ignore_value(virNetDevSetOnline(linkdev, true));
-        }
-
-        break;
-    }
-
-    return rc;
-}
-
-
-/**
- * virNetDevVPortProfileDisassociate:
- *
- * @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.
- */
-int
-virNetDevVPortProfileDisassociate(const char *macvtap_ifname,
-                                  const virNetDevVPortProfilePtr virtPort,
-                                  const unsigned char *macvtap_macaddr,
-                                  const char *linkdev,
-                                  enum virNetDevVPortProfileOp vmOp)
-{
-    int rc = 0;
-
-    VIR_DEBUG("Disassociating port profile id '%p' on link device '%s' ",
-              virtPort, macvtap_ifname);
-
-    VIR_DEBUG("%s: VM OPERATION: %s", __FUNCTION__, virNetDevVPortProfileOpTypeToString(vmOp));
-
-    if (!virtPort)
-       return 0;
-
-    switch (virtPort->virtPortType) {
-    case VIR_NETDEV_VPORT_PROFILE_NONE:
-    case VIR_NETDEV_VPORT_PROFILE_LAST:
-        break;
-
-    case VIR_NETDEV_VPORT_PROFILE_8021QBG:
-        rc = virNetDevVPortProfileOp8021Qbg(macvtap_ifname, macvtap_macaddr,
-                                            virtPort, VIR_NETDEV_VPORT_PROFILE_LINK_OP_DISASSOCIATE);
-        break;
-
-    case VIR_NETDEV_VPORT_PROFILE_8021QBH:
-        /* avoid disassociating twice */
-        if (vmOp == VIR_NETDEV_VPORT_PROFILE_OP_MIGRATE_IN_FINISH)
-            break;
-        ignore_value(virNetDevSetOnline(linkdev, false));
-        rc = virNetDevVPortProfileOp8021Qbh(linkdev, macvtap_macaddr,
-                                            virtPort, NULL,
-                                            VIR_NETDEV_VPORT_PROFILE_LINK_OP_DISASSOCIATE);
-        break;
-    }
-
-    return rc;
-}
-
-#endif /* WITH_MACVTAP || WITH_VIRTUALPORT */
-
-VIR_ENUM_IMPL(virNetDevVPortProfileOp, VIR_NETDEV_VPORT_PROFILE_OP_LAST,
-              "create",
-              "save",
-              "restore",
-              "destroy",
-              "migrate out",
-              "migrate in start",
-              "migrate in finish",
-              "no-op")
diff --git a/src/util/virnetdevmacvlan.c b/src/util/virnetdevmacvlan.c
new file mode 100644
index 0000000..ab111f0
--- /dev/null
+++ b/src/util/virnetdevmacvlan.c
@@ -0,0 +1,423 @@
+/*
+ * Copyright (C) 2010-2011 Red Hat, Inc.
+ * Copyright (C) 2010 IBM Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+ *
+ * Authors:
+ *     Stefan Berger <stefanb at us.ibm.com>
+ *
+ * Notes:
+ * netlink: http://lovezutto.googlepages.com/netlink.pdf
+ *          iproute2 package
+ *
+ */
+
+#include <config.h>
+
+
+#include "virnetdevmacvlan.h"
+#include "util.h"
+#include "virterror_internal.h"
+
+#define VIR_FROM_THIS VIR_FROM_NET
+
+#define macvtapError(code, ...)                                         \
+    virReportErrorHelper(VIR_FROM_NET, code, __FILE__,                  \
+                         __FUNCTION__, __LINE__, __VA_ARGS__)
+
+
+VIR_ENUM_IMPL(virNetDevMacVLanMode, VIR_NETDEV_MACVLAN_MODE_LAST,
+              "vepa",
+              "private",
+              "bridge",
+              "passthrough")
+
+#if WITH_MACVTAP
+
+# include <stdint.h>
+# include <stdio.h>
+# include <errno.h>
+# include <fcntl.h>
+# include <sys/socket.h>
+# include <sys/ioctl.h>
+
+# include <linux/if.h>
+# include <linux/if_tun.h>
+
+/* Older kernels lacked this enum value.  */
+# if !HAVE_DECL_MACVLAN_MODE_PASSTHRU
+#  define MACVLAN_MODE_PASSTHRU 8
+# endif
+
+# include "memory.h"
+# include "logging.h"
+# include "interface.h"
+# include "uuid.h"
+# include "virfile.h"
+# include "netlink.h"
+# include "virnetdev.h"
+
+# define MACVTAP_NAME_PREFIX	"macvtap"
+# define MACVTAP_NAME_PATTERN	"macvtap%d"
+
+/**
+ * virNetDevMacVLanTapOpen:
+ * Open the macvtap's tap device.
+ * @ifname: Name of the macvtap interface
+ * @retries : Number of retries in case udev for example may need to be
+ *            waited for to create the tap chardev
+ * Returns negative value in case of error, the file descriptor otherwise.
+ */
+static
+int virNetDevMacVLanTapOpen(const char *ifname,
+                            int retries)
+{
+    FILE *file;
+    char path[64];
+    int ifindex;
+    char tapname[50];
+    int tapfd;
+
+    if (snprintf(path, sizeof(path),
+                 "/sys/class/net/%s/ifindex", ifname) >= sizeof(path)) {
+        virReportSystemError(errno,
+                             "%s",
+                             _("buffer for ifindex path is too small"));
+        return -1;
+    }
+
+    file = fopen(path, "r");
+
+    if (!file) {
+        virReportSystemError(errno,
+                             _("cannot open macvtap file %s to determine "
+                               "interface index"), path);
+        return -1;
+    }
+
+    if (fscanf(file, "%d", &ifindex) != 1) {
+        virReportSystemError(errno,
+                             "%s",_("cannot determine macvtap's tap device "
+                             "interface index"));
+        VIR_FORCE_FCLOSE(file);
+        return -1;
+    }
+
+    VIR_FORCE_FCLOSE(file);
+
+    if (snprintf(tapname, sizeof(tapname),
+                 "/dev/tap%d", ifindex) >= sizeof(tapname)) {
+        virReportSystemError(errno,
+                             "%s",
+                             _("internal buffer for tap device is too small"));
+        return -1;
+    }
+
+    while (1) {
+        /* may need to wait for udev to be done */
+        tapfd = open(tapname, O_RDWR);
+        if (tapfd < 0 && retries > 0) {
+            retries--;
+            usleep(20000);
+            continue;
+        }
+        break;
+    }
+
+    if (tapfd < 0)
+        virReportSystemError(errno,
+                             _("cannot open macvtap tap device %s"),
+                             tapname);
+
+    return tapfd;
+}
+
+
+/**
+ * virNetDevMacVLanTapSetup:
+ * @tapfd: file descriptor of the macvtap tap
+ * @vnet_hdr: 1 to enable IFF_VNET_HDR, 0 to disable it
+ *
+ * Returns 0 on success, -1 in case of fatal error, error code otherwise.
+ *
+ * Turn the IFF_VNET_HDR flag, if requested and available, make sure
+ * it's off in the other cases.
+ * A fatal error is defined as the VNET_HDR flag being set but it cannot
+ * be turned off for some reason. This is reported with -1. Other fatal
+ * error is not being able to read the interface flags. In that case the
+ * macvtap device should not be used.
+ */
+static int
+virNetDevMacVLanTapSetup(int tapfd, int vnet_hdr)
+{
+    unsigned int features;
+    struct ifreq ifreq;
+    short new_flags = 0;
+    int rc_on_fail = 0;
+    const char *errmsg = NULL;
+
+    memset(&ifreq, 0, sizeof(ifreq));
+
+    if (ioctl(tapfd, TUNGETIFF, &ifreq) < 0) {
+        virReportSystemError(errno, "%s",
+                             _("cannot get interface flags on macvtap tap"));
+        return -1;
+    }
+
+    new_flags = ifreq.ifr_flags;
+
+    if ((ifreq.ifr_flags & IFF_VNET_HDR) && !vnet_hdr) {
+        new_flags = ifreq.ifr_flags & ~IFF_VNET_HDR;
+        rc_on_fail = -1;
+        errmsg = _("cannot clean IFF_VNET_HDR flag on macvtap tap");
+    } else if ((ifreq.ifr_flags & IFF_VNET_HDR) == 0 && vnet_hdr) {
+        if (ioctl(tapfd, TUNGETFEATURES, &features) < 0) {
+            virReportSystemError(errno, "%s",
+                   _("cannot get feature flags on macvtap tap"));
+            return -1;
+        }
+        if ((features & IFF_VNET_HDR)) {
+            new_flags = ifreq.ifr_flags | IFF_VNET_HDR;
+            errmsg = _("cannot set IFF_VNET_HDR flag on macvtap tap");
+        }
+    }
+
+    if (new_flags != ifreq.ifr_flags) {
+        ifreq.ifr_flags = new_flags;
+        if (ioctl(tapfd, TUNSETIFF, &ifreq) < 0) {
+            virReportSystemError(errno, "%s", errmsg);
+            return rc_on_fail;
+        }
+    }
+
+    return 0;
+}
+
+
+static const uint32_t modeMap[VIR_NETDEV_MACVLAN_MODE_LAST] = {
+    [VIR_NETDEV_MACVLAN_MODE_VEPA] = MACVLAN_MODE_VEPA,
+    [VIR_NETDEV_MACVLAN_MODE_PRIVATE] = MACVLAN_MODE_PRIVATE,
+    [VIR_NETDEV_MACVLAN_MODE_BRIDGE] = MACVLAN_MODE_BRIDGE,
+    [VIR_NETDEV_MACVLAN_MODE_PASSTHRU] = MACVLAN_MODE_PASSTHRU,
+};
+
+/**
+ * virNetDevMacVLanCreate:
+ * 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: int describing the mode for 'bridge', 'vepa', 'private' or 'passthru'.
+ * @vnet_hdr: 1 to enable IFF_VNET_HDR, 0 to disable it
+ * @vmuuid: The UUID of the VM the macvtap belongs to
+ * @virtPortProfile: pointer to object holding the virtual port profile data
+ * @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.
+ *
+ * Returns file descriptor of the tap device in case of success,
+ * negative value otherwise with error reported.
+ *
+ */
+int virNetDevMacVLanCreate(const char *tgifname,
+                           const unsigned char *macaddress,
+                           const char *linkdev,
+                           enum virNetDevMacVLanMode mode,
+                           int vnet_hdr,
+                           const unsigned char *vmuuid,
+                           virNetDevVPortProfilePtr virtPortProfile,
+                           char **res_ifname,
+                           enum virNetDevVPortProfileOp vmOp,
+                           char *stateDir,
+                           virNetDevBandwidthPtr bandwidth)
+{
+    const char *type = "macvtap";
+    int c, rc;
+    char ifname[IFNAMSIZ];
+    int retries, do_retry = 0;
+    uint32_t macvtapMode;
+    const char *cr_ifname;
+    int ifindex;
+
+    macvtapMode = modeMap[mode];
+
+    *res_ifname = NULL;
+
+    VIR_DEBUG("%s: VM OPERATION: %s", __FUNCTION__, virNetDevVPortProfileOpTypeToString(vmOp));
+
+    /** Note: When using PASSTHROUGH mode with MACVTAP devices the link
+     * device's MAC address must be set to the VMs MAC address. In
+     * order to not confuse the first switch or bridge in line this MAC
+     * address must be reset when the VM is shut down.
+     * This is especially important when using SRIOV capable cards that
+     * emulate their switch in firmware.
+     */
+    if (mode == VIR_NETDEV_MACVLAN_MODE_PASSTHRU) {
+        if (ifaceReplaceMacAddress(macaddress, linkdev, stateDir) < 0) {
+            return -1;
+        }
+    }
+
+    if (tgifname) {
+        if(ifaceGetIndex(false, tgifname, &ifindex) == 0) {
+            if (STRPREFIX(tgifname,
+                          MACVTAP_NAME_PREFIX)) {
+                goto create_name;
+            }
+            virReportSystemError(errno,
+                                 _("Interface %s already exists"), tgifname);
+            return -1;
+        }
+        cr_ifname = tgifname;
+        rc = ifaceMacvtapLinkAdd(type, macaddress, 6, tgifname, linkdev,
+                                 macvtapMode, &do_retry);
+        if (rc < 0)
+            return -1;
+    } else {
+create_name:
+        retries = 5;
+        for (c = 0; c < 8192; c++) {
+            snprintf(ifname, sizeof(ifname), MACVTAP_NAME_PATTERN, c);
+            if (ifaceGetIndex(false, ifname, &ifindex) == -ENODEV) {
+                rc = ifaceMacvtapLinkAdd(type, macaddress, 6, ifname, linkdev,
+                                         macvtapMode, &do_retry);
+                if (rc == 0)
+                    break;
+
+                if (do_retry && --retries)
+                    continue;
+                return -1;
+            }
+        }
+        cr_ifname = ifname;
+    }
+
+    if (virNetDevVPortProfileAssociate(cr_ifname,
+                                       virtPortProfile,
+                                       macaddress,
+                                       linkdev,
+                                       vmuuid, vmOp) < 0) {
+        rc = -1;
+        goto link_del_exit;
+    }
+
+    if (virNetDevSetOnline(cr_ifname, true) < 0) {
+        rc = -1;
+        goto disassociate_exit;
+    }
+
+    rc = virNetDevMacVLanTapOpen(cr_ifname, 10);
+    if (rc >= 0) {
+        if (virNetDevMacVLanTapSetup(rc, vnet_hdr) < 0) {
+            VIR_FORCE_CLOSE(rc); /* sets rc to -1 */
+            goto disassociate_exit;
+        }
+        *res_ifname = strdup(cr_ifname);
+    } else
+        goto disassociate_exit;
+
+    if (virNetDevBandwidthSet(cr_ifname, bandwidth) < 0) {
+        macvtapError(VIR_ERR_INTERNAL_ERROR,
+                     _("cannot set bandwidth limits on %s"),
+                     cr_ifname);
+        rc = -1;
+        goto disassociate_exit;
+    }
+
+
+    return rc;
+
+disassociate_exit:
+    ignore_value(virNetDevVPortProfileDisassociate(cr_ifname,
+                                                   virtPortProfile,
+                                                   macaddress,
+                                                   linkdev,
+                                                   vmOp));
+
+link_del_exit:
+    ifaceLinkDel(cr_ifname);
+
+    return rc;
+}
+
+
+/**
+ * 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
+ * it with the switch if port profile parameters
+ * were provided.
+ */
+int virNetDevMacVLanDelete(const char *ifname,
+                           const unsigned char *macaddr,
+                           const char *linkdev,
+                           int mode,
+                           virNetDevVPortProfilePtr virtPortProfile,
+                           char *stateDir)
+{
+    int ret = 0;
+    if (mode == VIR_NETDEV_MACVLAN_MODE_PASSTHRU) {
+        ifaceRestoreMacAddress(linkdev, stateDir);
+    }
+
+    if (ifname) {
+        if (virNetDevVPortProfileDisassociate(ifname,
+                                              virtPortProfile,
+                                              macaddr,
+                                              linkdev,
+                                              VIR_NETDEV_VPORT_PROFILE_OP_DESTROY) < 0)
+            ret = -1;
+        if (ifaceLinkDel(ifname) < 0)
+            ret = -1;
+    }
+    return ret;
+}
+
+#else /* ! WITH_MACVTAP */
+int virNetDevMacVLanCreate(const char *ifname ATTRIBUTE_UNUSED,
+                           const unsigned char *macaddress ATTRIBUTE_UNUSED,
+                           const char *linkdev ATTRIBUTE_UNUSED,
+                           enum virNetDevMacVLanMode mode ATTRIBUTE_UNUSED,
+                           int vnet_hdr ATTRIBUTE_UNUSED,
+                           const unsigned char *vmuuid ATTRIBUTE_UNUSED,
+                           virNetDevVPortProfilePtr virtPortProfile ATTRIBUTE_UNUSED,
+                           char **res_ifname ATTRIBUTE_UNUSED,
+                           enum virNetDevVPortProfileOp vmop ATTRIBUTE_UNUSED,
+                           char *stateDir ATTRIBUTE_UNUSED,
+                           virNetDevBandwidthPtr bandwidth ATTRIBUTE_UNUSED)
+{
+    virReportSystemError(ENOSYS, "%s",
+                         _("Cannot create macvlan devices on this platform"));
+    return -1;
+}
+
+int virNetDevMacVLanDelete(const char *ifname ATTRIBUTE_UNUSED,
+                           const unsigned char *macaddress ATTRIBUTE_UNUSED,
+                           const char *linkdev ATTRIBUTE_UNUSED,
+                           int mode ATTRIBUTE_UNUSED,
+                           virNetDevVPortProfilePtr virtPortProfile ATTRIBUTE_UNUSED,
+                           char *stateDir ATTRIBUTE_UNUSED)
+{
+    virReportSystemError(ENOSYS, "%s",
+                         _("Cannot create macvlan devices on this platform"));
+    return -1;
+}
+#endif /* ! WITH_MACVTAP */
diff --git a/src/util/macvtap.h b/src/util/virnetdevmacvlan.h
similarity index 63%
rename from src/util/macvtap.h
rename to src/util/virnetdevmacvlan.h
index 5c5d84a..f3277f9 100644
--- a/src/util/macvtap.h
+++ b/src/util/virnetdevmacvlan.h
@@ -37,21 +37,7 @@ enum virNetDevMacVLanMode {
 
     VIR_NETDEV_MACVLAN_MODE_LAST,
 };
-
-enum virNetDevVPortProfileOp {
-    VIR_NETDEV_VPORT_PROFILE_OP_CREATE,
-    VIR_NETDEV_VPORT_PROFILE_OP_SAVE,
-    VIR_NETDEV_VPORT_PROFILE_OP_RESTORE,
-    VIR_NETDEV_VPORT_PROFILE_OP_DESTROY,
-    VIR_NETDEV_VPORT_PROFILE_OP_MIGRATE_OUT,
-    VIR_NETDEV_VPORT_PROFILE_OP_MIGRATE_IN_START,
-    VIR_NETDEV_VPORT_PROFILE_OP_MIGRATE_IN_FINISH,
-    VIR_NETDEV_VPORT_PROFILE_OP_NO_OP,
-
-    VIR_NETDEV_VPORT_PROFILE_OP_LAST
-};
-
-# if WITH_MACVTAP
+VIR_ENUM_DECL(virNetDevMacVLanMode)
 
 int virNetDevMacVLanCreate(const char *ifname,
                            const unsigned char *macaddress,
@@ -76,26 +62,4 @@ int virNetDevMacVLanDelete(const char *ifname,
     ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3)
     ATTRIBUTE_NONNULL(6) ATTRIBUTE_RETURN_CHECK;
 
-int virNetDevVPortProfileAssociate(const char *ifname,
-                                   const virNetDevVPortProfilePtr virtPort,
-                                   const unsigned char *macaddr,
-                                   const char *linkdev,
-                                   const unsigned char *vmuuid,
-                                   enum virNetDevVPortProfileOp vmOp)
-    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4)
-    ATTRIBUTE_NONNULL(5) ATTRIBUTE_RETURN_CHECK;
-
-int virNetDevVPortProfileDisassociate(const char *ifname,
-                                      const virNetDevVPortProfilePtr virtPort,
-                                      const unsigned char *macaddr,
-                                      const char *linkdev,
-                                      enum virNetDevVPortProfileOp vmOp)
-    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4)
-    ATTRIBUTE_RETURN_CHECK;
-
-# endif /* WITH_MACVTAP */
-
-VIR_ENUM_DECL(virNetDevVPortProfileOp)
-VIR_ENUM_DECL(virNetDevMacVLanMode)
-
 #endif /* __UTIL_MACVTAP_H__ */
diff --git a/src/util/virnetdevvportprofile.c b/src/util/virnetdevvportprofile.c
index 6aecd52..ec86e2c 100644
--- a/src/util/virnetdevvportprofile.c
+++ b/src/util/virnetdevvportprofile.c
@@ -23,6 +23,65 @@
 #include <config.h>
 
 #include "virnetdevvportprofile.h"
+#include "virterror_internal.h"
+
+#define VIR_FROM_THIS VIR_FROM_NET
+
+#define virNetDevError(code, ...)                                       \
+    virReportErrorHelper(VIR_FROM_NET, code, __FILE__,                  \
+                         __FUNCTION__, __LINE__, __VA_ARGS__)
+
+
+VIR_ENUM_IMPL(virNetDevVPortProfileOp, VIR_NETDEV_VPORT_PROFILE_OP_LAST,
+              "create",
+              "save",
+              "restore",
+              "destroy",
+              "migrate out",
+              "migrate in start",
+              "migrate in finish",
+              "no-op")
+
+#if WITH_VIRTUALPORT
+
+# include <stdint.h>
+# include <stdio.h>
+# include <errno.h>
+# include <fcntl.h>
+# include <c-ctype.h>
+# include <sys/socket.h>
+# include <sys/ioctl.h>
+
+# include <linux/if.h>
+# include <linux/if_tun.h>
+
+# include "netlink.h"
+# include "virfile.h"
+# include "memory.h"
+# include "interface.h"
+# include "logging.h"
+# include "virnetdev.h"
+
+# define MICROSEC_PER_SEC       (1000 * 1000)
+
+# define NLMSGBUF_SIZE  256
+# define RATTBUF_SIZE   64
+
+
+# define STATUS_POLL_TIMEOUT_USEC (10 * MICROSEC_PER_SEC)
+# define STATUS_POLL_INTERVL_USEC (MICROSEC_PER_SEC / 8)
+
+# define LLDPAD_PID_FILE  "/var/run/lldpad.pid"
+
+
+enum virNetDevVPortProfileLinkOp {
+    VIR_NETDEV_VPORT_PROFILE_LINK_OP_ASSOCIATE = 0x1,
+    VIR_NETDEV_VPORT_PROFILE_LINK_OP_DISASSOCIATE = 0x2,
+    VIR_NETDEV_VPORT_PROFILE_LINK_OP_PREASSOCIATE = 0x3,
+    VIR_NETDEV_VPORT_PROFILE_LINK_OP_PREASSOCIATE_RR = 0x4,
+};
+
+#endif
 
 bool
 virNetDevVPortProfileEqual(virNetDevVPortProfilePtr a, virNetDevVPortProfilePtr b)
@@ -60,3 +119,767 @@ virNetDevVPortProfileEqual(virNetDevVPortProfilePtr a, virNetDevVPortProfilePtr
 
     return true;
 }
+
+
+#ifdef WITH_VIRTUALPORT
+
+static struct nla_policy ifla_port_policy[IFLA_PORT_MAX + 1] =
+{
+  [IFLA_PORT_RESPONSE]      = { .type = NLA_U16 },
+};
+
+
+static uint32_t
+virNetDevVPortProfileGetLldpadPid(void) {
+    int fd;
+    uint32_t pid = 0;
+
+    fd = open(LLDPAD_PID_FILE, O_RDONLY);
+    if (fd >= 0) {
+        char buffer[10];
+
+        if (saferead(fd, buffer, sizeof(buffer)) <= sizeof(buffer)) {
+            unsigned int res;
+            char *endptr;
+
+            if (virStrToLong_ui(buffer, &endptr, 10, &res) == 0
+                && (*endptr == '\0' || c_isspace(*endptr))
+                && res != 0) {
+                pid = res;
+            } else {
+                virNetDevError(VIR_ERR_INTERNAL_ERROR, "%s",
+                               _("error parsing pid of lldpad"));
+            }
+        }
+    } else {
+        virReportSystemError(errno,
+                             _("Error opening file %s"), LLDPAD_PID_FILE);
+    }
+
+    VIR_FORCE_CLOSE(fd);
+
+    return pid;
+}
+
+
+/**
+ * virNetDevVPortProfileGetStatus:
+ *
+ * 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
+virNetDevVPortProfileGetStatus(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;
+            rc = 0;
+        } else {
+            msg = _("no IFLA_PORT_RESPONSE found in netlink message");
+            goto err_exit;
+        }
+    }
+
+err_exit:
+    if (msg)
+        virNetDevError(VIR_ERR_INTERNAL_ERROR, "%s", msg);
+
+    return rc;
+}
+
+
+static int
+virNetDevVPortProfileOpSetLink(const char *ifname, int ifindex,
+                               bool nltarget_kernel,
+                               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 = -1;
+    struct nlmsghdr *resp;
+    struct nlmsgerr *err;
+    struct ifinfomsg ifinfo = {
+        .ifi_family = AF_UNSPEC,
+        .ifi_index  = ifindex,
+    };
+    unsigned char *recvbuf = NULL;
+    unsigned int recvbuflen = 0;
+    uint32_t pid = 0;
+    struct nl_msg *nl_msg;
+    struct nlattr *vfports = NULL, *vfport;
+
+    nl_msg = nlmsg_alloc_simple(RTM_SETLINK, NLM_F_REQUEST);
+    if (!nl_msg) {
+        virReportOOMError();
+        return rc;
+    }
+
+    if (nlmsg_append(nl_msg,  &ifinfo, sizeof(ifinfo), NLMSG_ALIGNTO) < 0)
+        goto buffer_too_small;
+
+    if (ifname &&
+        nla_put(nl_msg, IFLA_IFNAME, strlen(ifname)+1, ifname) < 0)
+        goto buffer_too_small;
+
+    if (macaddr || vlanid >= 0) {
+        struct nlattr *vfinfolist, *vfinfo;
+
+        if (!(vfinfolist = nla_nest_start(nl_msg, IFLA_VFINFO_LIST)))
+            goto buffer_too_small;
+
+        if (!(vfinfo = nla_nest_start(nl_msg, IFLA_VF_INFO)))
+            goto buffer_too_small;
+
+        if (macaddr) {
+            struct ifla_vf_mac ifla_vf_mac = {
+                .vf = vf,
+                .mac = { 0, },
+            };
+
+            memcpy(ifla_vf_mac.mac, macaddr, 6);
+
+            if (nla_put(nl_msg, IFLA_VF_MAC, sizeof(ifla_vf_mac),
+                        &ifla_vf_mac) < 0)
+                goto buffer_too_small;
+        }
+
+        if (vlanid >= 0) {
+            struct ifla_vf_vlan ifla_vf_vlan = {
+                .vf = vf,
+                .vlan = vlanid,
+                .qos = 0,
+            };
+
+            if (nla_put(nl_msg, IFLA_VF_VLAN, sizeof(ifla_vf_vlan),
+                        &ifla_vf_vlan) < 0)
+                goto buffer_too_small;
+        }
+
+        nla_nest_end(nl_msg, vfinfo);
+        nla_nest_end(nl_msg, vfinfolist);
+    }
+
+    if (vf == PORT_SELF_VF && nltarget_kernel) {
+        if (!(vfport = nla_nest_start(nl_msg, IFLA_PORT_SELF)))
+            goto buffer_too_small;
+    } else {
+        if (!(vfports = nla_nest_start(nl_msg, IFLA_VF_PORTS)))
+            goto buffer_too_small;
+
+        /* begin nesting vfports */
+        if (!(vfport = nla_nest_start(nl_msg, IFLA_VF_PORT)))
+            goto buffer_too_small;
+    }
+
+    if (profileId) {
+        if (nla_put(nl_msg, IFLA_PORT_PROFILE, strlen(profileId) + 1,
+                    profileId) < 0)
+            goto buffer_too_small;
+    }
+
+    if (portVsi) {
+        if (nla_put(nl_msg, IFLA_PORT_VSI_TYPE, sizeof(*portVsi),
+                    portVsi) < 0)
+            goto buffer_too_small;
+    }
+
+    if (instanceId) {
+        if (nla_put(nl_msg, IFLA_PORT_INSTANCE_UUID, VIR_UUID_BUFLEN,
+                    instanceId) < 0)
+            goto buffer_too_small;
+    }
+
+    if (hostUUID) {
+        if (nla_put(nl_msg, IFLA_PORT_HOST_UUID, VIR_UUID_BUFLEN,
+                    hostUUID) < 0)
+            goto buffer_too_small;
+    }
+
+    if (vf != PORT_SELF_VF) {
+        if (nla_put(nl_msg, IFLA_PORT_VF, sizeof(vf), &vf) < 0)
+            goto buffer_too_small;
+    }
+
+    if (nla_put(nl_msg, IFLA_PORT_REQUEST, sizeof(op), &op) < 0)
+        goto buffer_too_small;
+
+    /* end nesting of vport */
+    nla_nest_end(nl_msg, vfport);
+
+    if (vfports) {
+        /* end nesting of vfports */
+        nla_nest_end(nl_msg, vfports);
+    }
+
+    if (!nltarget_kernel) {
+        pid = virNetDevVPortProfileGetLldpadPid();
+        if (pid == 0)
+            goto err_exit;
+    }
+
+    if (nlComm(nl_msg, &recvbuf, &recvbuflen, pid) < 0)
+        goto err_exit;
+
+    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);
+            goto err_exit;
+        }
+        break;
+
+    case NLMSG_DONE:
+        break;
+
+    default:
+        goto malformed_resp;
+    }
+
+    rc = 0;
+
+err_exit:
+    nlmsg_free(nl_msg);
+
+    VIR_FREE(recvbuf);
+
+    return rc;
+
+malformed_resp:
+    nlmsg_free(nl_msg);
+
+    virNetDevError(VIR_ERR_INTERNAL_ERROR, "%s",
+                   _("malformed netlink response message"));
+    VIR_FREE(recvbuf);
+    return rc;
+
+buffer_too_small:
+    nlmsg_free(nl_msg);
+
+    virNetDevError(VIR_ERR_INTERNAL_ERROR, "%s",
+                   _("allocated netlink buffer is too small"));
+    return rc;
+}
+
+
+/* Returns 0 on success, -1 on general failure, and -2 on timeout */
+static int
+virNetDevVPortProfileOpCommon(const char *ifname, int ifindex,
+                              bool nltarget_kernel,
+                              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;
+    unsigned 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 = virNetDevVPortProfileOpSetLink(ifname, ifindex,
+                                        nltarget_kernel,
+                                        macaddr,
+                                        vlanid,
+                                        profileId,
+                                        portVsi,
+                                        instanceId,
+                                        hostUUID,
+                                        vf,
+                                        op);
+    if (rc < 0) {
+        virNetDevError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("sending of PortProfileRequest failed."));
+        return rc;
+    }
+
+    while (--repeats >= 0) {
+        rc = ifaceMacvtapLinkDump(nltarget_kernel, NULL, ifindex, tb,
+                                  &recvbuf, virNetDevVPortProfileGetLldpadPid);
+        if (rc < 0)
+            goto err_exit;
+
+        rc = virNetDevVPortProfileGetStatus(tb, vf, instanceId, nltarget_kernel,
+                                            is8021Qbg, &status);
+        if (rc < 0)
+            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) {
+        virNetDevError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("port-profile setlink timed out"));
+        rc = -2;
+    }
+
+err_exit:
+    VIR_FREE(recvbuf);
+
+    return rc;
+}
+
+
+static int
+virNetDevVPortProfileGetPhysdevAndVlan(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)) < 0)
+            return ret;
+        if (nth == 0)
+            break;
+        if (*vlanid == -1) {
+            if (ifaceGetVlanID(root_ifname, vlanid) < 0)
+                *vlanid = -1;
+        }
+
+        ifindex = *root_ifindex;
+        ifname = NULL;
+    }
+
+    return 0;
+}
+
+/* Returns 0 on success, -1 on general failure, and -2 on timeout */
+static int
+virNetDevVPortProfileOp8021Qbg(const char *ifname,
+                               const unsigned char *macaddr,
+                               const virNetDevVPortProfilePtr virtPort,
+                               enum virNetDevVPortProfileLinkOp virtPortOp)
+{
+    int rc = 0;
+    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 (virNetDevVPortProfileGetPhysdevAndVlan(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 VIR_NETDEV_VPORT_PROFILE_LINK_OP_PREASSOCIATE:
+        op = PORT_REQUEST_PREASSOCIATE;
+        break;
+    case VIR_NETDEV_VPORT_PROFILE_LINK_OP_ASSOCIATE:
+        op = PORT_REQUEST_ASSOCIATE;
+        break;
+    case VIR_NETDEV_VPORT_PROFILE_LINK_OP_DISASSOCIATE:
+        op = PORT_REQUEST_DISASSOCIATE;
+        break;
+    default:
+        virNetDevError(VIR_ERR_INTERNAL_ERROR,
+                       _("operation type %d not supported"), virtPortOp);
+        rc = -1;
+        goto err_exit;
+    }
+
+    rc = virNetDevVPortProfileOpCommon(physdev_ifname, physdev_ifindex,
+                                       nltarget_kernel,
+                                       macaddr,
+                                       vlanid,
+                                       NULL,
+                                       &portVsi,
+                                       virtPort->u.virtPort8021Qbg.instanceID,
+                                       NULL,
+                                       vf,
+                                       op);
+
+err_exit:
+
+    return rc;
+}
+
+
+static int
+virNetDevVPortProfileGetPhysfnDev(const char *linkdev,
+                                  int32_t *vf,
+                                  char **physfndev)
+{
+    int rc = -1;
+
+    if (ifaceIsVirtualFunction(linkdev) == 1) {
+        /* if linkdev is SR-IOV VF, then set vf = VF index */
+        /* and set linkdev = PF device */
+
+        rc = ifaceGetPhysicalFunction(linkdev, physfndev);
+        if (!rc)
+            rc = ifaceGetVirtualFunctionIndex(*physfndev, linkdev, vf);
+    } else {
+
+        /* Not SR-IOV VF: physfndev is linkdev and VF index
+         * refers to linkdev self
+         */
+
+        *vf = PORT_SELF_VF;
+        *physfndev = strdup(linkdev);
+        if (!*physfndev) {
+            virReportOOMError();
+            goto err_exit;
+        }
+        rc = 0;
+    }
+
+err_exit:
+
+    return rc;
+}
+
+
+/* Returns 0 on success, -1 on general failure, and -2 on timeout */
+static int
+virNetDevVPortProfileOp8021Qbh(const char *ifname,
+                               const unsigned char *macaddr,
+                               const virNetDevVPortProfilePtr virtPort,
+                               const unsigned char *vm_uuid,
+                               enum virNetDevVPortProfileLinkOp virtPortOp)
+{
+    int rc = 0;
+    char *physfndev = NULL;
+    unsigned char hostuuid[VIR_UUID_BUFLEN];
+    int32_t vf;
+    bool nltarget_kernel = true;
+    int ifindex;
+    int vlanid = -1;
+
+    rc = virNetDevVPortProfileGetPhysfnDev(ifname, &vf, &physfndev);
+    if (rc < 0)
+        goto err_exit;
+
+    rc = ifaceGetIndex(true, physfndev, &ifindex);
+    if (rc < 0)
+        goto err_exit;
+
+    switch (virtPortOp) {
+    case VIR_NETDEV_VPORT_PROFILE_LINK_OP_PREASSOCIATE_RR:
+    case VIR_NETDEV_VPORT_PROFILE_LINK_OP_ASSOCIATE:
+        errno = virGetHostUUID(hostuuid);
+        if (errno) {
+            rc = -1;
+            goto err_exit;
+        }
+
+        rc = virNetDevVPortProfileOpCommon(NULL, ifindex,
+                                           nltarget_kernel,
+                                           macaddr,
+                                           vlanid,
+                                           virtPort->u.virtPort8021Qbh.profileID,
+                                           NULL,
+                                           vm_uuid,
+                                           hostuuid,
+                                           vf,
+                                           (virtPortOp ==
+                                            VIR_NETDEV_VPORT_PROFILE_LINK_OP_PREASSOCIATE_RR) ?
+                                           PORT_REQUEST_PREASSOCIATE_RR
+                                           : PORT_REQUEST_ASSOCIATE);
+        if (rc == -2)
+            /* Association timed out, disassociate */
+            virNetDevVPortProfileOpCommon(NULL, ifindex,
+                                          nltarget_kernel,
+                                          NULL,
+                                          vlanid,
+                                          NULL,
+                                          NULL,
+                                          NULL,
+                                          NULL,
+                                          vf,
+                                          PORT_REQUEST_DISASSOCIATE);
+        break;
+
+    case VIR_NETDEV_VPORT_PROFILE_LINK_OP_DISASSOCIATE:
+        rc = virNetDevVPortProfileOpCommon(NULL, ifindex,
+                                           nltarget_kernel,
+                                           NULL,
+                                           vlanid,
+                                           NULL,
+                                           NULL,
+                                           NULL,
+                                           NULL,
+                                           vf,
+                                           PORT_REQUEST_DISASSOCIATE);
+        break;
+
+    default:
+        virNetDevError(VIR_ERR_INTERNAL_ERROR,
+                       _("operation type %d not supported"), virtPortOp);
+        rc = -1;
+    }
+
+err_exit:
+    VIR_FREE(physfndev);
+    return rc;
+}
+
+/**
+ * virNetDevVPortProfileAssociate:
+ *
+ * @macvtap_ifname: The name of the macvtap device
+ * @virtPort: pointer to the object holding port profile parameters
+ * @vmuuid : the UUID of the virtual machine
+ * @vmOp : The VM operation (i.e., create, no-op)
+ *
+ * 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.
+ */
+int
+virNetDevVPortProfileAssociate(const char *macvtap_ifname,
+                               const virNetDevVPortProfilePtr virtPort,
+                               const unsigned char *macvtap_macaddr,
+                               const char *linkdev,
+                               const unsigned char *vmuuid,
+                               enum virNetDevVPortProfileOp vmOp)
+{
+    int rc = 0;
+
+    VIR_DEBUG("Associating port profile '%p' on link device '%s'",
+              virtPort, macvtap_ifname);
+
+    VIR_DEBUG("%s: VM OPERATION: %s", __FUNCTION__, virNetDevVPortProfileOpTypeToString(vmOp));
+
+    if (!virtPort || vmOp == VIR_NETDEV_VPORT_PROFILE_OP_NO_OP)
+        return 0;
+
+    switch (virtPort->virtPortType) {
+    case VIR_NETDEV_VPORT_PROFILE_NONE:
+    case VIR_NETDEV_VPORT_PROFILE_LAST:
+        break;
+
+    case VIR_NETDEV_VPORT_PROFILE_8021QBG:
+        rc = virNetDevVPortProfileOp8021Qbg(macvtap_ifname, macvtap_macaddr,
+                                            virtPort,
+                                            (vmOp == VIR_NETDEV_VPORT_PROFILE_OP_MIGRATE_IN_START)
+                                            ? VIR_NETDEV_VPORT_PROFILE_LINK_OP_PREASSOCIATE
+                                            : VIR_NETDEV_VPORT_PROFILE_LINK_OP_ASSOCIATE);
+        break;
+
+    case VIR_NETDEV_VPORT_PROFILE_8021QBH:
+        rc = virNetDevVPortProfileOp8021Qbh(linkdev, macvtap_macaddr,
+                                            virtPort, vmuuid,
+                                            (vmOp == VIR_NETDEV_VPORT_PROFILE_OP_MIGRATE_IN_START)
+                                            ? VIR_NETDEV_VPORT_PROFILE_LINK_OP_PREASSOCIATE_RR
+                                            : VIR_NETDEV_VPORT_PROFILE_LINK_OP_ASSOCIATE);
+        if (vmOp != VIR_NETDEV_VPORT_PROFILE_OP_MIGRATE_IN_START && !rc) {
+            /* XXX bogus error handling */
+            ignore_value(virNetDevSetOnline(linkdev, true));
+        }
+
+        break;
+    }
+
+    return rc;
+}
+
+
+/**
+ * virNetDevVPortProfileDisassociate:
+ *
+ * @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.
+ */
+int
+virNetDevVPortProfileDisassociate(const char *macvtap_ifname,
+                                  const virNetDevVPortProfilePtr virtPort,
+                                  const unsigned char *macvtap_macaddr,
+                                  const char *linkdev,
+                                  enum virNetDevVPortProfileOp vmOp)
+{
+    int rc = 0;
+
+    VIR_DEBUG("Disassociating port profile id '%p' on link device '%s' ",
+              virtPort, macvtap_ifname);
+
+    VIR_DEBUG("%s: VM OPERATION: %s", __FUNCTION__, virNetDevVPortProfileOpTypeToString(vmOp));
+
+    if (!virtPort)
+       return 0;
+
+    switch (virtPort->virtPortType) {
+    case VIR_NETDEV_VPORT_PROFILE_NONE:
+    case VIR_NETDEV_VPORT_PROFILE_LAST:
+        break;
+
+    case VIR_NETDEV_VPORT_PROFILE_8021QBG:
+        rc = virNetDevVPortProfileOp8021Qbg(macvtap_ifname, macvtap_macaddr,
+                                            virtPort,
+                                            VIR_NETDEV_VPORT_PROFILE_LINK_OP_DISASSOCIATE);
+        break;
+
+    case VIR_NETDEV_VPORT_PROFILE_8021QBH:
+        /* avoid disassociating twice */
+        if (vmOp == VIR_NETDEV_VPORT_PROFILE_OP_MIGRATE_IN_FINISH)
+            break;
+        ignore_value(virNetDevSetOnline(linkdev, false));
+        rc = virNetDevVPortProfileOp8021Qbh(linkdev, macvtap_macaddr,
+                                            virtPort, NULL,
+                                            VIR_NETDEV_VPORT_PROFILE_LINK_OP_DISASSOCIATE);
+        break;
+    }
+
+    return rc;
+}
+
+#else /* ! WITH_VIRTUALPORT */
+int virNetDevVPortProfileAssociate(const char *macvtap_ifname ATTRIBUTE_UNUSED,
+                               const virNetDevVPortProfilePtr virtPort ATTRIBUTE_UNUSED,
+                               const unsigned char *macvtap_macaddr ATTRIBUTE_UNUSED,
+                               const char *linkdev ATTRIBUTE_UNUSED,
+                               const unsigned char *vmuuid ATTRIBUTE_UNUSED,
+                               enum virNetDevVPortProfileOp vmOp ATTRIBUTE_UNUSED)
+{
+    virReportSystemError(ENOSYS, "%s",
+                         _("Virtual port profile association not supported on this platform"));
+    return -1;
+}
+
+int virNetDevVPortProfileDisassociate(const char *macvtap_ifname ATTRIBUTE_UNUSED,
+                                      const virNetDevVPortProfilePtr virtPort ATTRIBUTE_UNUSED,
+                                      const unsigned char *macvtap_macaddr ATTRIBUTE_UNUSED,
+                                      const char *linkdev ATTRIBUTE_UNUSED,
+                                      enum virNetDevVPortProfileOp vmOp ATTRIBUTE_UNUSED)
+{
+    virReportSystemError(ENOSYS, "%s",
+                         _("Virtual port profile association not supported on this platform"));
+    return -1;
+}
+#endif /* ! WITH_VIRTUALPORT */
diff --git a/src/util/virnetdevvportprofile.h b/src/util/virnetdevvportprofile.h
index 36e8fd7..92df005 100644
--- a/src/util/virnetdevvportprofile.h
+++ b/src/util/virnetdevvportprofile.h
@@ -36,9 +36,22 @@ enum virNetDevVPortProfile {
 
     VIR_NETDEV_VPORT_PROFILE_LAST,
 };
-
 VIR_ENUM_DECL(virNetDevVPort)
 
+enum virNetDevVPortProfileOp {
+    VIR_NETDEV_VPORT_PROFILE_OP_CREATE,
+    VIR_NETDEV_VPORT_PROFILE_OP_SAVE,
+    VIR_NETDEV_VPORT_PROFILE_OP_RESTORE,
+    VIR_NETDEV_VPORT_PROFILE_OP_DESTROY,
+    VIR_NETDEV_VPORT_PROFILE_OP_MIGRATE_OUT,
+    VIR_NETDEV_VPORT_PROFILE_OP_MIGRATE_IN_START,
+    VIR_NETDEV_VPORT_PROFILE_OP_MIGRATE_IN_FINISH,
+    VIR_NETDEV_VPORT_PROFILE_OP_NO_OP,
+
+    VIR_NETDEV_VPORT_PROFILE_OP_LAST
+};
+VIR_ENUM_DECL(virNetDevVPortProfileOp)
+
 /* profile data for macvtap (VEPA) */
 typedef struct _virNetDevVPortProfile virNetDevVPortProfile;
 typedef virNetDevVPortProfile *virNetDevVPortProfilePtr;
@@ -61,4 +74,22 @@ struct _virNetDevVPortProfile {
 bool virNetDevVPortProfileEqual(virNetDevVPortProfilePtr a,
                                 virNetDevVPortProfilePtr b);
 
+int virNetDevVPortProfileAssociate(const char *ifname,
+                                   const virNetDevVPortProfilePtr virtPort,
+                                   const unsigned char *macaddr,
+                                   const char *linkdev,
+                                   const unsigned char *vmuuid,
+                                   enum virNetDevVPortProfileOp vmOp)
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4)
+    ATTRIBUTE_NONNULL(5) ATTRIBUTE_RETURN_CHECK;
+
+int virNetDevVPortProfileDisassociate(const char *ifname,
+                                      const virNetDevVPortProfilePtr virtPort,
+                                      const unsigned char *macaddr,
+                                      const char *linkdev,
+                                      enum virNetDevVPortProfileOp vmOp)
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4)
+    ATTRIBUTE_RETURN_CHECK;
+
+
 #endif /* __VIR_NETDEV_VPORT_PROFILE_H__ */
-- 
1.7.6.4




More information about the libvir-list mailing list