From: "Daniel P. Berrange" <berrange(a)redhat.com>
Move the ifaceMacvtapLinkDump and ifaceGetNthParent functions
into virnetdevvportprofile.c since they are specific to that
code. This avoids polluting the headers with the Linux specific
netlink data types
* src/util/interface.c, src/util/interface.h: Move
ifaceMacvtapLinkDump and ifaceGetNthParent functions and delete
remaining file
* src/util/virnetdevvportprofile.c: Add ifaceMacvtapLinkDump
and ifaceGetNthParent functions
* src/network/bridge_driver.c, src/nwfilter/nwfilter_gentech_driver.c,
src/nwfilter/nwfilter_learnipaddr.c, src/util/virnetdevmacvlan.c:
Remove include of interface.h
---
po/POTFILES.in | 1 -
src/Makefile.am | 1 -
src/libvirt_private.syms | 2 -
src/network/bridge_driver.c | 1 -
src/nwfilter/nwfilter_gentech_driver.c | 2 +-
src/nwfilter/nwfilter_learnipaddr.c | 1 -
src/util/interface.c | 296 --------------------------------
src/util/interface.h | 41 -----
src/util/virnetdevmacvlan.c | 1 -
src/util/virnetdevvportprofile.c | 199 +++++++++++++++++++++-
10 files changed, 195 insertions(+), 350 deletions(-)
delete mode 100644 src/util/interface.c
delete mode 100644 src/util/interface.h
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 6797298..403d94b 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -112,7 +112,6 @@ src/util/hash.c
src/util/hooks.c
src/util/hostusb.c
src/util/iohelper.c
-src/util/interface.c
src/util/iptables.c
src/util/json.c
src/util/netlink.c
diff --git a/src/Makefile.am b/src/Makefile.am
index e44c53a..f82be78 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -72,7 +72,6 @@ UTIL_SOURCES = \
util/pci.c util/pci.h \
util/processinfo.c util/processinfo.h \
util/hostusb.c util/hostusb.h \
- util/interface.c util/interface.h \
util/qparams.c util/qparams.h \
util/sexpr.c util/sexpr.h \
util/stats_linux.c util/stats_linux.h \
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 0189875..131d856 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -578,14 +578,12 @@ virHookPresent;
virNetDevValidateConfig;
virNetDevGetIndex;
virNetDevGetIPv4Address;
-ifaceGetNthParent;
virNetDevGetPhysicalFunction;
virNetDevGetVirtualFunctionIndex;
virNetDevGetVLanID;
virNetDevIsVirtualFunction;
virNetDevMacVLanCreate;
virNetDevMacVLanDelete;
-ifaceMacvtapLinkDump;
virNetDevReplaceMacAddress;
virNetDevRestoreMacAddress;
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index f19bf51..7bea465 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -55,7 +55,6 @@
#include "memory.h"
#include "uuid.h"
#include "iptables.h"
-#include "interface.h"
#include "logging.h"
#include "dnsmasq.h"
#include "configmake.h"
diff --git a/src/nwfilter/nwfilter_gentech_driver.c
b/src/nwfilter/nwfilter_gentech_driver.c
index 9dffdc5..c9c1415 100644
--- a/src/nwfilter/nwfilter_gentech_driver.c
+++ b/src/nwfilter/nwfilter_gentech_driver.c
@@ -28,13 +28,13 @@
#include "memory.h"
#include "logging.h"
-#include "interface.h"
#include "domain_conf.h"
#include "virterror_internal.h"
#include "nwfilter_gentech_driver.h"
#include "nwfilter_ebiptables_driver.h"
#include "nwfilter_learnipaddr.h"
#include "virnetdev.h"
+#include "datatypes.h"
#define VIR_FROM_THIS VIR_FROM_NWFILTER
diff --git a/src/nwfilter/nwfilter_learnipaddr.c b/src/nwfilter/nwfilter_learnipaddr.c
index 03716ea..1843c98 100644
--- a/src/nwfilter/nwfilter_learnipaddr.c
+++ b/src/nwfilter/nwfilter_learnipaddr.c
@@ -45,7 +45,6 @@
#include "memory.h"
#include "logging.h"
#include "datatypes.h"
-#include "interface.h"
#include "virnetdev.h"
#include "virterror_internal.h"
#include "threads.h"
diff --git a/src/util/interface.c b/src/util/interface.c
deleted file mode 100644
index 00a873e..0000000
--- a/src/util/interface.c
+++ /dev/null
@@ -1,296 +0,0 @@
-/*
- * interface.c: interface support functions
- *
- * Copyright (C) 2011 Red Hat, Inc.
- * Copyright (C) 2010 IBM Corp.
- * Copyright (C) 2010 Stefan Berger
- *
- * 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
- *
- * chgIfaceFlags originated from bridge.c
- *
- * Author: Stefan Berger <stefanb(a)us.ibm.com>
- */
-
-#include <config.h>
-
-#include <sys/socket.h>
-#include <sys/ioctl.h>
-#include <fcntl.h>
-#include <netinet/in.h>
-
-#ifdef __linux__
-# include <linux/if.h>
-# include <linux/sockios.h>
-# include <linux/if_vlan.h>
-#endif
-
-#include "internal.h"
-
-#include "util.h"
-#include "interface.h"
-#include "virterror_internal.h"
-#include "virfile.h"
-#include "memory.h"
-#include "netlink.h"
-#include "logging.h"
-#include "virnetdev.h"
-
-#define VIR_FROM_THIS VIR_FROM_NET
-
-#define ifaceError(code, ...) \
- virReportErrorHelper(VIR_FROM_NET, code, __FILE__, \
- __FUNCTION__, __LINE__, __VA_ARGS__)
-
-
-#if defined(__linux__) && defined(IFLA_PORT_MAX)
-
-static struct nla_policy ifla_policy[IFLA_MAX + 1] =
-{
- [IFLA_VF_PORTS] = { .type = NLA_NESTED },
-};
-
-/**
- * ifaceMacvtapLinkDump
- *
- * @nltarget_kernel: whether to send the message to the kernel or another
- * process
- * @ifname: The name of the interface; only use if ifindex < 0
- * @ifindex: The interface index; may be < 0 if ifname is given
- * @nlattr: pointer to a pointer of netlink attributes that will contain
- * the results
- * @recvbuf: Pointer to the buffer holding the returned netlink response
- * message; free it, once not needed anymore
- * @getPidFunc: Pointer to a function that will be invoked if the kernel
- * is not the target of the netlink message but it is to be
- * sent to another process.
- *
- * Get information about an interface given its name or index.
- *
- * Returns 0 on success, -1 on fatal error.
- */
-int
-ifaceMacvtapLinkDump(bool nltarget_kernel, const char *ifname, int ifindex,
- struct nlattr **tb, unsigned char **recvbuf,
- uint32_t (*getPidFunc)(void))
-{
- int rc = 0;
- struct nlmsghdr *resp;
- struct nlmsgerr *err;
- struct ifinfomsg ifinfo = {
- .ifi_family = AF_UNSPEC,
- .ifi_index = ifindex
- };
- unsigned int recvbuflen;
- uint32_t pid = 0;
- struct nl_msg *nl_msg;
-
- *recvbuf = NULL;
-
- nl_msg = nlmsg_alloc_simple(RTM_GETLINK, NLM_F_REQUEST);
- if (!nl_msg) {
- virReportOOMError();
- return -1;
- }
-
- if (nlmsg_append(nl_msg, &ifinfo, sizeof(ifinfo), NLMSG_ALIGNTO) < 0)
- goto buffer_too_small;
-
- if (ifindex < 0 && ifname) {
- if (nla_put(nl_msg, IFLA_IFNAME, strlen(ifname)+1, ifname) < 0)
- goto buffer_too_small;
- }
-
- if (!nltarget_kernel) {
- pid = getPidFunc();
- if (pid == 0) {
- rc = -1;
- goto cleanup;
- }
- }
-
- if (nlComm(nl_msg, recvbuf, &recvbuflen, pid) < 0) {
- rc = -1;
- goto cleanup;
- }
-
- if (recvbuflen < NLMSG_LENGTH(0) || *recvbuf == NULL)
- goto malformed_resp;
-
- resp = (struct nlmsghdr *)*recvbuf;
-
- switch (resp->nlmsg_type) {
- case NLMSG_ERROR:
- err = (struct nlmsgerr *)NLMSG_DATA(resp);
- if (resp->nlmsg_len < NLMSG_LENGTH(sizeof(*err)))
- goto malformed_resp;
-
- if (err->error) {
- virReportSystemError(-err->error,
- _("error dumping %s (%d) interface"),
- ifname, ifindex);
- rc = -1;
- }
- break;
-
- case GENL_ID_CTRL:
- case NLMSG_DONE:
- if (nlmsg_parse(resp, sizeof(struct ifinfomsg),
- tb, IFLA_MAX, ifla_policy)) {
- goto malformed_resp;
- }
- break;
-
- default:
- goto malformed_resp;
- }
-
- if (rc != 0)
- VIR_FREE(*recvbuf);
-
-cleanup:
- nlmsg_free(nl_msg);
-
- return rc;
-
-malformed_resp:
- nlmsg_free(nl_msg);
-
- ifaceError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("malformed netlink response message"));
- VIR_FREE(*recvbuf);
- return -1;
-
-buffer_too_small:
- nlmsg_free(nl_msg);
-
- ifaceError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("allocated netlink buffer is too small"));
- return -1;
-}
-
-#else
-
-int
-ifaceMacvtapLinkDump(bool nltarget_kernel ATTRIBUTE_UNUSED,
- const char *ifname ATTRIBUTE_UNUSED,
- int ifindex ATTRIBUTE_UNUSED,
- struct nlattr **tb ATTRIBUTE_UNUSED,
- unsigned char **recvbuf ATTRIBUTE_UNUSED,
- uint32_t (*getPidFunc)(void) ATTRIBUTE_UNUSED)
-{
- ifaceError(VIR_ERR_INTERNAL_ERROR, "%s",
-# if defined(__linux__) && !defined(IFLA_PORT_MAX)
- _("ifaceMacvtapLinkDump is not supported since the include "
- "files were too old"));
-# else
- _("ifaceMacvtapLinkDump is not supported on non-linux "
- "platforms"));
-# endif
-
- return -1;
-}
-
-#endif
-
-
-/**
- * ifaceGetNthParent
- *
- * @ifindex : the index of the interface or -1 if ifname is given
- * @ifname : the name of the interface; ignored if ifindex is valid
- * @nthParent : the nth parent interface to get
- * @parent_ifindex : pointer to int
- * @parent_ifname : pointer to buffer of size IFNAMSIZ
- * @nth : the nth parent that is actually returned; if for example eth0.100
- * was given and the 100th parent is to be returned, then eth0 will
- * most likely be returned with nth set to 1 since the chain does
- * not have more interfaces
- *
- * Get the nth parent interface of the given interface. 0 is the interface
- * itself.
- *
- * Return 0 on success, < 0 otherwise
- */
-#if defined(__linux__) && WITH_MACVTAP
-int
-ifaceGetNthParent(int ifindex, const char *ifname, unsigned int nthParent,
- int *parent_ifindex, char *parent_ifname,
- unsigned int *nth)
-{
- int rc;
- struct nlattr *tb[IFLA_MAX + 1] = { NULL, };
- unsigned char *recvbuf = NULL;
- bool end = false;
- unsigned int i = 0;
-
- *nth = 0;
-
- if (ifindex <= 0 && virNetDevGetIndex(ifname, &ifindex) < 0)
- return -1;
-
- while (!end && i <= nthParent) {
- rc = ifaceMacvtapLinkDump(true, ifname, ifindex, tb, &recvbuf, NULL);
- if (rc < 0)
- break;
-
- if (tb[IFLA_IFNAME]) {
- if (!virStrcpy(parent_ifname, (char*)RTA_DATA(tb[IFLA_IFNAME]),
- IFNAMSIZ)) {
- ifaceError(VIR_ERR_INTERNAL_ERROR, "%s",
- _("buffer for root interface name is too small"));
- VIR_FREE(recvbuf);
- return -1;
- }
- *parent_ifindex = ifindex;
- }
-
- if (tb[IFLA_LINK]) {
- ifindex = *(int *)RTA_DATA(tb[IFLA_LINK]);
- ifname = NULL;
- } else
- end = true;
-
- VIR_FREE(recvbuf);
-
- i++;
- }
-
- *nth = i - 1;
-
- return rc;
-}
-
-#else
-
-int
-ifaceGetNthParent(int ifindex ATTRIBUTE_UNUSED,
- const char *ifname ATTRIBUTE_UNUSED,
- unsigned int nthParent ATTRIBUTE_UNUSED,
- int *parent_ifindex ATTRIBUTE_UNUSED,
- char *parent_ifname ATTRIBUTE_UNUSED,
- unsigned int *nth ATTRIBUTE_UNUSED)
-{
- ifaceError(VIR_ERR_INTERNAL_ERROR, "%s",
-# if defined(__linux__) && !WITH_MACVTAP
- _("ifaceGetNthParent is not supported since the include files "
- "were too old"));
-# else
- _("ifaceGetNthParent is not supported on non-linux
platforms"));
-# endif
- return -1;
-}
-
-#endif
diff --git a/src/util/interface.h b/src/util/interface.h
deleted file mode 100644
index 141d19c..0000000
--- a/src/util/interface.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * interface.h: interface helper APIs for libvirt
- *
- * Copyright (C) 2011 Red Hat, Inc.
- * Copyright (C) 2010 IBM Corporation, Inc.
- *
- * See COPYING.LIB for the License of this software
- *
- * Stefan Berger <stefanb(a)us.ibm.com>
- */
-#ifndef __VIR_INTERFACE_H__
-# define __VIR_INTERFACE_H__
-
-# include <stdint.h>
-
-# if __linux__
-
-# include <sys/socket.h>
-# include <linux/netlink.h>
-
-# else
-
-struct nlattr;
-
-# endif
-
-# include "datatypes.h"
-# include "virsocketaddr.h"
-
-
-int ifaceMacvtapLinkDump(bool nltarget_kernel, const char *ifname, int ifindex,
- struct nlattr **tb, unsigned char **recvbuf,
- uint32_t (*getPidFunc)(void));
-
-int ifaceGetNthParent(int ifindex, const char *ifname, unsigned int nthParent,
- int *parent_ifindex, char *parent_ifname,
- unsigned int *nth)
- ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(4) ATTRIBUTE_NONNULL(5)
- ATTRIBUTE_NONNULL(6);
-
-#endif /* __VIR_INTERFACE_H__ */
diff --git a/src/util/virnetdevmacvlan.c b/src/util/virnetdevmacvlan.c
index e3f90dd..fe2f383 100644
--- a/src/util/virnetdevmacvlan.c
+++ b/src/util/virnetdevmacvlan.c
@@ -64,7 +64,6 @@ VIR_ENUM_IMPL(virNetDevMacVLanMode, VIR_NETDEV_MACVLAN_MODE_LAST,
# include "memory.h"
# include "logging.h"
-# include "interface.h"
# include "uuid.h"
# include "virfile.h"
# include "netlink.h"
diff --git a/src/util/virnetdevvportprofile.c b/src/util/virnetdevvportprofile.c
index 9315281..8f7e5b9 100644
--- a/src/util/virnetdevvportprofile.c
+++ b/src/util/virnetdevvportprofile.c
@@ -58,7 +58,6 @@ VIR_ENUM_IMPL(virNetDevVPortProfileOp,
VIR_NETDEV_VPORT_PROFILE_OP_LAST,
# include "netlink.h"
# include "virfile.h"
# include "memory.h"
-# include "interface.h"
# include "logging.h"
# include "virnetdev.h"
@@ -127,6 +126,10 @@ static struct nla_policy ifla_port_policy[IFLA_PORT_MAX + 1] =
{
[IFLA_PORT_RESPONSE] = { .type = NLA_U16 },
};
+static struct nla_policy ifla_policy[IFLA_MAX + 1] =
+{
+ [IFLA_VF_PORTS] = { .type = NLA_NESTED },
+};
static uint32_t
@@ -163,6 +166,125 @@ virNetDevVPortProfileGetLldpadPid(void) {
/**
+ * virNetDevVPortProfileLinkDump:
+ *
+ * @ifname: The name of the interface; only use if ifindex < 0
+ * @ifindex: The interface index; may be < 0 if ifname is given
+ * @nltarget_kernel: whether to send the message to the kernel or another
+ * process
+ * @nlattr: pointer to a pointer of netlink attributes that will contain
+ * the results
+ * @recvbuf: Pointer to the buffer holding the returned netlink response
+ * message; free it, once not needed anymore
+ * @getPidFunc: Pointer to a function that will be invoked if the kernel
+ * is not the target of the netlink message but it is to be
+ * sent to another process.
+ *
+ * Get information about an interface given its name or index.
+ *
+ * Returns 0 on success, -1 on fatal error.
+ */
+static int
+virNetDevVPortProfileLinkDump(const char *ifname, int ifindex, bool nltarget_kernel,
+ struct nlattr **tb, unsigned char **recvbuf,
+ uint32_t (*getPidFunc)(void))
+{
+ int rc = 0;
+ struct nlmsghdr *resp;
+ struct nlmsgerr *err;
+ struct ifinfomsg ifinfo = {
+ .ifi_family = AF_UNSPEC,
+ .ifi_index = ifindex
+ };
+ unsigned int recvbuflen;
+ uint32_t pid = 0;
+ struct nl_msg *nl_msg;
+
+ *recvbuf = NULL;
+
+ nl_msg = nlmsg_alloc_simple(RTM_GETLINK, NLM_F_REQUEST);
+ if (!nl_msg) {
+ virReportOOMError();
+ return -1;
+ }
+
+ if (nlmsg_append(nl_msg, &ifinfo, sizeof(ifinfo), NLMSG_ALIGNTO) < 0)
+ goto buffer_too_small;
+
+ if (ifindex < 0 && ifname) {
+ if (nla_put(nl_msg, IFLA_IFNAME, strlen(ifname)+1, ifname) < 0)
+ goto buffer_too_small;
+ }
+
+ if (!nltarget_kernel) {
+ pid = getPidFunc();
+ if (pid == 0) {
+ rc = -1;
+ goto cleanup;
+ }
+ }
+
+ if (nlComm(nl_msg, recvbuf, &recvbuflen, pid) < 0) {
+ rc = -1;
+ goto cleanup;
+ }
+
+ if (recvbuflen < NLMSG_LENGTH(0) || *recvbuf == NULL)
+ goto malformed_resp;
+
+ resp = (struct nlmsghdr *)*recvbuf;
+
+ switch (resp->nlmsg_type) {
+ case NLMSG_ERROR:
+ err = (struct nlmsgerr *)NLMSG_DATA(resp);
+ if (resp->nlmsg_len < NLMSG_LENGTH(sizeof(*err)))
+ goto malformed_resp;
+
+ if (err->error) {
+ virReportSystemError(-err->error,
+ _("error dumping %s (%d) interface"),
+ ifname, ifindex);
+ rc = -1;
+ }
+ break;
+
+ case GENL_ID_CTRL:
+ case NLMSG_DONE:
+ if (nlmsg_parse(resp, sizeof(struct ifinfomsg),
+ tb, IFLA_MAX, ifla_policy)) {
+ goto malformed_resp;
+ }
+ break;
+
+ default:
+ goto malformed_resp;
+ }
+
+ if (rc != 0)
+ VIR_FREE(*recvbuf);
+
+cleanup:
+ nlmsg_free(nl_msg);
+
+ return rc;
+
+malformed_resp:
+ nlmsg_free(nl_msg);
+
+ virNetDevError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("malformed netlink response message"));
+ VIR_FREE(*recvbuf);
+ return -1;
+
+buffer_too_small:
+ nlmsg_free(nl_msg);
+
+ virNetDevError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("allocated netlink buffer is too small"));
+ return -1;
+}
+
+/**
* virNetDevVPortProfileGetStatus:
*
* tb: top level netlink response attributes + values
@@ -450,6 +572,73 @@ buffer_too_small:
}
+/**
+ * virNetDevVPortProfileGetNthParent
+ *
+ * @ifname : the name of the interface; ignored if ifindex is valid
+ * @ifindex : the index of the interface or -1 if ifname is given
+ * @nthParent : the nth parent interface to get
+ * @parent_ifindex : pointer to int
+ * @parent_ifname : pointer to buffer of size IFNAMSIZ
+ * @nth : the nth parent that is actually returned; if for example eth0.100
+ * was given and the 100th parent is to be returned, then eth0 will
+ * most likely be returned with nth set to 1 since the chain does
+ * not have more interfaces
+ *
+ * Get the nth parent interface of the given interface. 0 is the interface
+ * itself.
+ *
+ * Return 0 on success, < 0 otherwise
+ */
+static int
+virNetDevVPortProfileGetNthParent(const char *ifname, int ifindex, unsigned int
nthParent,
+ int *parent_ifindex, char *parent_ifname,
+ unsigned int *nth)
+{
+ int rc;
+ struct nlattr *tb[IFLA_MAX + 1] = { NULL, };
+ unsigned char *recvbuf = NULL;
+ bool end = false;
+ unsigned int i = 0;
+
+ *nth = 0;
+
+ if (ifindex <= 0 && virNetDevGetIndex(ifname, &ifindex) < 0)
+ return -1;
+
+ while (!end && i <= nthParent) {
+ rc = virNetDevVPortProfileLinkDump(ifname, ifindex, true, tb, &recvbuf,
NULL);
+ if (rc < 0)
+ break;
+
+ if (tb[IFLA_IFNAME]) {
+ if (!virStrcpy(parent_ifname, (char*)RTA_DATA(tb[IFLA_IFNAME]),
+ IFNAMSIZ)) {
+ virNetDevError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("buffer for root interface name is too
small"));
+ VIR_FREE(recvbuf);
+ return -1;
+ }
+ *parent_ifindex = ifindex;
+ }
+
+ if (tb[IFLA_LINK]) {
+ ifindex = *(int *)RTA_DATA(tb[IFLA_LINK]);
+ ifname = NULL;
+ } else
+ end = true;
+
+ VIR_FREE(recvbuf);
+
+ i++;
+ }
+
+ *nth = i - 1;
+
+ return rc;
+}
+
+
/* Returns 0 on success, -1 on general failure, and -2 on timeout */
static int
virNetDevVPortProfileOpCommon(const char *ifname, int ifindex,
@@ -487,8 +676,8 @@ virNetDevVPortProfileOpCommon(const char *ifname, int ifindex,
}
while (--repeats >= 0) {
- rc = ifaceMacvtapLinkDump(nltarget_kernel, NULL, ifindex, tb,
- &recvbuf, virNetDevVPortProfileGetLldpadPid);
+ rc = virNetDevVPortProfileLinkDump(NULL, ifindex, nltarget_kernel, tb,
+ &recvbuf,
virNetDevVPortProfileGetLldpadPid);
if (rc < 0)
goto err_exit;
@@ -538,8 +727,8 @@ virNetDevVPortProfileGetPhysdevAndVlan(const char *ifname, int
*root_ifindex, ch
*vlanid = -1;
while (1) {
- if ((ret = ifaceGetNthParent(ifindex, ifname, 1,
- root_ifindex, root_ifname, &nth)) < 0)
+ if ((ret = virNetDevVPortProfileGetNthParent(ifname, ifindex, 1,
+ root_ifindex, root_ifname,
&nth)) < 0)
return ret;
if (nth == 0)
break;
--
1.7.6.4