Blame SOURCES/libvirt-util-Functions-to-update-host-network-device-s-multicast-filter.patch

9119d9
From 8a337b676f90040f96ef195a70262c26aec36019 Mon Sep 17 00:00:00 2001
9119d9
Message-Id: <8a337b676f90040f96ef195a70262c26aec36019@dist-git>
9119d9
From: Tony Krowiak <akrowiak@linux.vnet.ibm.com>
9119d9
Date: Mon, 3 Nov 2014 10:00:22 -0500
9119d9
Subject: [PATCH] util: Functions to update host network device's multicast
9119d9
 filter
9119d9
9119d9
https://bugzilla.redhat.com/show_bug.cgi?id=848199
9119d9
9119d9
This patch provides the utility functions to needed to synchronize the
9119d9
changes made to a guest domain network device's multicast filter
9119d9
with the corresponding macvtap device's filter on the host:
9119d9
9119d9
* Get/add/remove multicast MAC addresses
9119d9
* Get the macvtap device's RX filter list
9119d9
9119d9
Signed-off-by: Tony Krowiak <akrowiak@linux.vnet.ibm.com>
9119d9
Signed-off-by: Laine Stump <laine@laine.org>
9119d9
(cherry picked from commit cc0e8c244d080f56392278e836cc378ba848e7aa)
9119d9
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
9119d9
---
9119d9
 src/libvirt_private.syms |   4 +
9119d9
 src/util/virmacaddr.c    |  25 ++++
9119d9
 src/util/virmacaddr.h    |   4 +
9119d9
 src/util/virnetdev.c     | 329 +++++++++++++++++++++++++++++++++++++++++++++++
9119d9
 src/util/virnetdev.h     |  10 ++
9119d9
 5 files changed, 372 insertions(+)
9119d9
9119d9
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
9119d9
index e2aae21..e7eba7e 100644
9119d9
--- a/src/libvirt_private.syms
9119d9
+++ b/src/libvirt_private.syms
9119d9
@@ -1568,13 +1568,16 @@ virMacAddrIsBroadcastRaw;
9119d9
 virMacAddrIsMulticast;
9119d9
 virMacAddrIsUnicast;
9119d9
 virMacAddrParse;
9119d9
+virMacAddrParseHex;
9119d9
 virMacAddrSet;
9119d9
 virMacAddrSetRaw;
9119d9
 
9119d9
 
9119d9
 # util/virnetdev.h
9119d9
+virNetDevAddMulti;
9119d9
 virNetDevAddRoute;
9119d9
 virNetDevClearIPv4Address;
9119d9
+virNetDevDelMulti;
9119d9
 virNetDevExists;
9119d9
 virNetDevGetIndex;
9119d9
 virNetDevGetIPv4Address;
9119d9
@@ -1582,6 +1585,7 @@ virNetDevGetLinkInfo;
9119d9
 virNetDevGetMAC;
9119d9
 virNetDevGetMTU;
9119d9
 virNetDevGetPhysicalFunction;
9119d9
+virNetDevGetRxFilter;
9119d9
 virNetDevGetVirtualFunctionIndex;
9119d9
 virNetDevGetVirtualFunctionInfo;
9119d9
 virNetDevGetVirtualFunctions;
9119d9
diff --git a/src/util/virmacaddr.c b/src/util/virmacaddr.c
9119d9
index ebd1182..612a409 100644
9119d9
--- a/src/util/virmacaddr.c
9119d9
+++ b/src/util/virmacaddr.c
9119d9
@@ -29,6 +29,7 @@
9119d9
 #include "c-ctype.h"
9119d9
 #include "virmacaddr.h"
9119d9
 #include "virrandom.h"
9119d9
+#include "virutil.h"
9119d9
 
9119d9
 static const unsigned char virMacAddrBroadcastAddrRaw[VIR_MAC_BUFLEN] =
9119d9
     { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
9119d9
@@ -198,6 +199,30 @@ virMacAddrFormat(const virMacAddr *addr,
9119d9
     return str;
9119d9
 }
9119d9
 
9119d9
+/**
9119d9
+ * virMacAddrParseHex:
9119d9
+ * @str: string hexadecimal representation of MAC address, e.g., "F801EFCE3aCB"
9119d9
+ * @addr: 6-byte MAC address
9119d9
+ *
9119d9
+ * Parse the hexadecimal representation of a MAC address
9119d9
+ *
9119d9
+ * Return 0 upon success, or -1 in case of error.
9119d9
+ */
9119d9
+int
9119d9
+virMacAddrParseHex(const char *str, virMacAddrPtr addr)
9119d9
+{
9119d9
+    size_t i;
9119d9
+
9119d9
+    if (strspn(str, "0123456789abcdefABCDEF") != VIR_MAC_HEXLEN ||
9119d9
+        str[VIR_MAC_HEXLEN])
9119d9
+        return -1;
9119d9
+
9119d9
+    for (i = 0; i < VIR_MAC_BUFLEN; i++)
9119d9
+        addr->addr[i] = (virHexToBin(str[2 * i]) << 4 |
9119d9
+                         virHexToBin(str[2 * i + 1]));
9119d9
+    return 0;
9119d9
+}
9119d9
+
9119d9
 void virMacAddrGenerate(const unsigned char prefix[VIR_MAC_PREFIX_BUFLEN],
9119d9
                         virMacAddrPtr addr)
9119d9
 {
9119d9
diff --git a/src/util/virmacaddr.h b/src/util/virmacaddr.h
9119d9
index 49efc36..ae26867 100644
9119d9
--- a/src/util/virmacaddr.h
9119d9
+++ b/src/util/virmacaddr.h
9119d9
@@ -27,6 +27,7 @@
9119d9
 # include "internal.h"
9119d9
 
9119d9
 # define VIR_MAC_BUFLEN 6
9119d9
+# define VIR_MAC_HEXLEN (VIR_MAC_BUFLEN * 2)
9119d9
 # define VIR_MAC_PREFIX_BUFLEN 3
9119d9
 # define VIR_MAC_STRING_BUFLEN (VIR_MAC_BUFLEN * 3)
9119d9
 
9119d9
@@ -50,6 +51,9 @@ void virMacAddrGenerate(const unsigned char prefix[VIR_MAC_PREFIX_BUFLEN],
9119d9
                         virMacAddrPtr addr);
9119d9
 int virMacAddrParse(const char* str,
9119d9
                     virMacAddrPtr addr) ATTRIBUTE_RETURN_CHECK;
9119d9
+int virMacAddrParseHex(const char* str,
9119d9
+                       virMacAddrPtr addr)
9119d9
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK;
9119d9
 bool virMacAddrIsUnicast(const virMacAddr *addr);
9119d9
 bool virMacAddrIsMulticast(const virMacAddr *addr);
9119d9
 bool virMacAddrIsBroadcastRaw(const unsigned char s[VIR_MAC_BUFLEN]);
9119d9
diff --git a/src/util/virnetdev.c b/src/util/virnetdev.c
9119d9
index 36b5a49..381031a 100644
9119d9
--- a/src/util/virnetdev.c
9119d9
+++ b/src/util/virnetdev.c
9119d9
@@ -56,6 +56,35 @@
9119d9
 
9119d9
 VIR_LOG_INIT("util.netdev");
9119d9
 
9119d9
+#define PROC_NET_DEV_MCAST "/proc/net/dev_mcast"
9119d9
+#define MAX_MCAST_SIZE 50*14336
9119d9
+#define VIR_MCAST_NAME_LEN (IFNAMSIZ + 1)
9119d9
+#define VIR_MCAST_INDEX_TOKEN_IDX 0
9119d9
+#define VIR_MCAST_NAME_TOKEN_IDX 1
9119d9
+#define VIR_MCAST_USERS_TOKEN_IDX 2
9119d9
+#define VIR_MCAST_GLOBAL_TOKEN_IDX 3
9119d9
+#define VIR_MCAST_ADDR_TOKEN_IDX 4
9119d9
+#define VIR_MCAST_NUM_TOKENS 5
9119d9
+#define VIR_MCAST_TOKEN_DELIMS " \n"
9119d9
+#define VIR_MCAST_ADDR_LEN (VIR_MAC_HEXLEN + 1)
9119d9
+
9119d9
+typedef struct _virNetDevMcastEntry virNetDevMcastEntry;
9119d9
+typedef virNetDevMcastEntry *virNetDevMcastEntryPtr;
9119d9
+struct _virNetDevMcastEntry  {
9119d9
+        int index;
9119d9
+        char name[VIR_MCAST_NAME_LEN];
9119d9
+        int users;
9119d9
+        bool global;
9119d9
+        virMacAddr macaddr;
9119d9
+};
9119d9
+
9119d9
+typedef struct _virNetDevMcastList virNetDevMcastList;
9119d9
+typedef virNetDevMcastList *virNetDevMcastListPtr;
9119d9
+struct _virNetDevMcastList {
9119d9
+    size_t nentries;
9119d9
+    virNetDevMcastEntryPtr *entries;
9119d9
+};
9119d9
+
9119d9
 #if defined(HAVE_STRUCT_IFREQ)
9119d9
 static int virNetDevSetupControlFull(const char *ifname,
9119d9
                                      struct ifreq *ifr,
9119d9
@@ -1935,6 +1964,238 @@ virNetDevGetLinkInfo(const char *ifname,
9119d9
 #endif /* defined(__linux__) */
9119d9
 
9119d9
 
9119d9
+#if defined(SIOCADDMULTI) && defined(HAVE_STRUCT_IFREQ)
9119d9
+/**
9119d9
+ * virNetDevAddMulti:
9119d9
+ * @ifname: interface name to which to add multicast MAC address
9119d9
+ * @macaddr: MAC address
9119d9
+ *
9119d9
+ * This function adds the @macaddr to the multicast list for a given interface
9119d9
+ * @ifname.
9119d9
+ *
9119d9
+ * Returns 0 in case of success or -1 on failure
9119d9
+ */
9119d9
+int virNetDevAddMulti(const char *ifname,
9119d9
+                      virMacAddrPtr macaddr)
9119d9
+{
9119d9
+    int fd = -1;
9119d9
+    int ret = -1;
9119d9
+    struct ifreq ifr;
9119d9
+
9119d9
+    if ((fd = virNetDevSetupControl(ifname, &ifr)) < 0)
9119d9
+        return -1;
9119d9
+
9119d9
+    ifr.ifr_hwaddr.sa_family = AF_UNSPEC;
9119d9
+    virMacAddrGetRaw(macaddr, (unsigned char *)ifr.ifr_hwaddr.sa_data);
9119d9
+
9119d9
+    if (ioctl(fd, SIOCADDMULTI, &ifr) < 0) {
9119d9
+        char macstr[VIR_MAC_STRING_BUFLEN];
9119d9
+        virReportSystemError(errno,
9119d9
+                             _("Cannot add multicast MAC %s on '%s' interface"),
9119d9
+                             virMacAddrFormat(macaddr, macstr), ifname);
9119d9
+        goto cleanup;
9119d9
+    }
9119d9
+
9119d9
+    ret = 0;
9119d9
+ cleanup:
9119d9
+    VIR_FORCE_CLOSE(fd);
9119d9
+    return ret;
9119d9
+}
9119d9
+#else
9119d9
+int virNetDevAddMulti(const char *ifname ATTRIBUTE_UNUSED,
9119d9
+                      virMacAddrPtr macaddr ATTRIBUTE_UNUSED)
9119d9
+{
9119d9
+    virReportSystemError(ENOSYS, "%s",
9119d9
+                         _("Unable to add address to interface "
9119d9
+                           "multicast list on this platform"));
9119d9
+    return -1;
9119d9
+}
9119d9
+#endif
9119d9
+
9119d9
+#if defined(SIOCDELMULTI) && defined(HAVE_STRUCT_IFREQ)
9119d9
+/**
9119d9
+ * virNetDevDelMulti:
9119d9
+ * @ifname: interface name from which to delete the multicast MAC address
9119d9
+ * @macaddr: MAC address
9119d9
+ *
9119d9
+ * This function deletes the @macaddr from the multicast list for a given
9119d9
+ * interface @ifname.
9119d9
+ *
9119d9
+ * Returns 0 in case of success or -1 on failure
9119d9
+ */
9119d9
+int virNetDevDelMulti(const char *ifname,
9119d9
+                      virMacAddrPtr macaddr)
9119d9
+{
9119d9
+    int fd = -1;
9119d9
+    int ret = -1;
9119d9
+    struct ifreq ifr;
9119d9
+
9119d9
+    if ((fd = virNetDevSetupControl(ifname, &ifr)) < 0)
9119d9
+        return -1;
9119d9
+
9119d9
+    ifr.ifr_hwaddr.sa_family = AF_UNSPEC;
9119d9
+    virMacAddrGetRaw(macaddr, (unsigned char *)ifr.ifr_hwaddr.sa_data);
9119d9
+
9119d9
+    if (ioctl(fd, SIOCDELMULTI, &ifr) < 0) {
9119d9
+        char macstr[VIR_MAC_STRING_BUFLEN];
9119d9
+        virReportSystemError(errno,
9119d9
+                             _("Cannot add multicast MAC %s on '%s' interface"),
9119d9
+                             virMacAddrFormat(macaddr, macstr), ifname);
9119d9
+        goto cleanup;
9119d9
+    }
9119d9
+
9119d9
+    ret = 0;
9119d9
+ cleanup:
9119d9
+    VIR_FORCE_CLOSE(fd);
9119d9
+    return ret;
9119d9
+}
9119d9
+#else
9119d9
+int virNetDevDelMulti(const char *ifname ATTRIBUTE_UNUSED,
9119d9
+                      virMacAddrPtr macaddr ATTRIBUTE_UNUSED)
9119d9
+{
9119d9
+    virReportSystemError(ENOSYS, "%s",
9119d9
+                         _("Unable to delete address from interface "
9119d9
+                           "multicast list on this platform"));
9119d9
+    return -1;
9119d9
+}
9119d9
+#endif
9119d9
+
9119d9
+static int virNetDevParseMcast(char *buf, virNetDevMcastEntryPtr mcast)
9119d9
+{
9119d9
+    int ifindex;
9119d9
+    int num;
9119d9
+    char *next;
9119d9
+    char *token;
9119d9
+    char *saveptr;
9119d9
+    char *endptr;
9119d9
+
9119d9
+    for (ifindex = 0, next = buf; ifindex < VIR_MCAST_NUM_TOKENS; ifindex++,
9119d9
+         next = NULL) {
9119d9
+        token = strtok_r(next, VIR_MCAST_TOKEN_DELIMS, &saveptr);
9119d9
+
9119d9
+        if (token == NULL) {
9119d9
+            virReportSystemError(EINVAL,
9119d9
+                                 _("failed to parse multicast address from '%s'"),
9119d9
+                                 buf);
9119d9
+            return -1;
9119d9
+        }
9119d9
+
9119d9
+        switch (ifindex) {
9119d9
+            case VIR_MCAST_INDEX_TOKEN_IDX:
9119d9
+                if (virStrToLong_i(token, &endptr, 10, &num) < 0) {
9119d9
+                    virReportSystemError(EINVAL,
9119d9
+                                         _("Failed to parse interface index from '%s'"),
9119d9
+                                         buf);
9119d9
+                    return -1;
9119d9
+
9119d9
+                }
9119d9
+                mcast->index = num;
9119d9
+                break;
9119d9
+            case VIR_MCAST_NAME_TOKEN_IDX:
9119d9
+                if (virStrncpy(mcast->name, token, strlen(token),
9119d9
+                    VIR_MCAST_NAME_LEN) == NULL) {
9119d9
+                    virReportSystemError(EINVAL,
9119d9
+                                         _("Failed to parse network device name from '%s'"),
9119d9
+                                         buf);
9119d9
+                    return -1;
9119d9
+                }
9119d9
+                break;
9119d9
+            case VIR_MCAST_USERS_TOKEN_IDX:
9119d9
+                if (virStrToLong_i(token, &endptr, 10, &num) < 0) {
9119d9
+                    virReportSystemError(EINVAL,
9119d9
+                                         _("Failed to parse users from '%s'"),
9119d9
+                                         buf);
9119d9
+                    return -1;
9119d9
+
9119d9
+                }
9119d9
+                mcast->users = num;
9119d9
+                break;
9119d9
+            case VIR_MCAST_GLOBAL_TOKEN_IDX:
9119d9
+                if (virStrToLong_i(token, &endptr, 10, &num) < 0) {
9119d9
+                    virReportSystemError(EINVAL,
9119d9
+                                         _("Failed to parse users from '%s'"),
9119d9
+                                         buf);
9119d9
+                    return -1;
9119d9
+
9119d9
+                }
9119d9
+                mcast->global = num;
9119d9
+                break;
9119d9
+            case VIR_MCAST_ADDR_TOKEN_IDX:
9119d9
+                if (virMacAddrParseHex((const char*)token,
9119d9
+                    &mcast->macaddr) < 0) {
9119d9
+                    virReportSystemError(EINVAL,
9119d9
+                                         _("Failed to parse MAC address from '%s'"),
9119d9
+                                         buf);
9119d9
+                }
9119d9
+                break;
9119d9
+            default:
9119d9
+                break;
9119d9
+        }
9119d9
+    }
9119d9
+    return 0;
9119d9
+}
9119d9
+
9119d9
+
9119d9
+static void virNetDevMcastListClear(virNetDevMcastListPtr mcast)
9119d9
+{
9119d9
+    size_t i;
9119d9
+
9119d9
+    for (i = 0; i < mcast->nentries; i++)
9119d9
+       VIR_FREE(mcast->entries[i]);
9119d9
+    VIR_FREE(mcast->entries);
9119d9
+    mcast->nentries = 0;
9119d9
+}
9119d9
+
9119d9
+
9119d9
+static int virNetDevGetMcastList(const char *ifname,
9119d9
+                                 virNetDevMcastListPtr mcast)
9119d9
+{
9119d9
+    char *cur = NULL;
9119d9
+    char *buf = NULL;
9119d9
+    char *next = NULL;
9119d9
+    int ret = -1, len;
9119d9
+    virNetDevMcastEntryPtr entry = NULL;
9119d9
+
9119d9
+    mcast->entries = NULL;
9119d9
+    mcast->nentries = 0;
9119d9
+
9119d9
+    /* Read entire multicast table into memory */
9119d9
+    if ((len = virFileReadAll(PROC_NET_DEV_MCAST, MAX_MCAST_SIZE, &buf)) <= 0)
9119d9
+        goto cleanup;
9119d9
+
9119d9
+    cur = buf;
9119d9
+    while (cur) {
9119d9
+        if (!entry && VIR_ALLOC(entry) < 0)
9119d9
+                goto cleanup;
9119d9
+
9119d9
+        next = strchr(cur, '\n');
9119d9
+        if (next)
9119d9
+            next++;
9119d9
+        if (virNetDevParseMcast(cur, entry))
9119d9
+            goto cleanup;
9119d9
+
9119d9
+        /* Only return global multicast MAC addresses for
9119d9
+         * specified interface */
9119d9
+        if (entry->global && STREQ(ifname, entry->name)) {
9119d9
+            if (VIR_APPEND_ELEMENT(mcast->entries, mcast->nentries, entry))
9119d9
+                 goto cleanup;
9119d9
+        } else {
9119d9
+            memset(entry, 0, sizeof(virNetDevMcastEntry));
9119d9
+        }
9119d9
+        cur = next && ((next - buf) < len) ? next : NULL;
9119d9
+    }
9119d9
+
9119d9
+    ret = 0;
9119d9
+ cleanup:
9119d9
+    if (ret < 0)
9119d9
+        virNetDevMcastListClear(mcast);
9119d9
+
9119d9
+    VIR_FREE(entry);
9119d9
+
9119d9
+    return ret;
9119d9
+}
9119d9
+
9119d9
+
9119d9
 VIR_ENUM_IMPL(virNetDevRxFilterMode,
9119d9
               VIR_NETDEV_RX_FILTER_MODE_LAST,
9119d9
               "none",
9119d9
@@ -1942,6 +2203,38 @@ VIR_ENUM_IMPL(virNetDevRxFilterMode,
9119d9
               "all");
9119d9
 
9119d9
 
9119d9
+static int virNetDevGetMulticastTable(const char *ifname,
9119d9
+                                      virNetDevRxFilterPtr filter)
9119d9
+{
9119d9
+    size_t i;
9119d9
+    int ret = -1;
9119d9
+    virNetDevMcastList mcast;
9119d9
+    filter->multicast.nTable = 0;
9119d9
+    filter->multicast.table = NULL;
9119d9
+
9119d9
+    if (virNetDevGetMcastList(ifname, &mcast) < 0)
9119d9
+        goto cleanup;
9119d9
+
9119d9
+    if (mcast.nentries > 0) {
9119d9
+        if (VIR_ALLOC_N(filter->multicast.table, mcast.nentries) < 0)
9119d9
+            goto cleanup;
9119d9
+
9119d9
+        for (i = 0; i < mcast.nentries; i++) {
9119d9
+            virMacAddrSet(&filter->multicast.table[i],
9119d9
+                          &mcast.entries[i]->macaddr);
9119d9
+        }
9119d9
+
9119d9
+        filter->multicast.nTable = mcast.nentries;
9119d9
+    }
9119d9
+
9119d9
+    ret = 0;
9119d9
+ cleanup:
9119d9
+    virNetDevMcastListClear(&mcast);
9119d9
+
9119d9
+    return ret;
9119d9
+}
9119d9
+
9119d9
+
9119d9
 virNetDevRxFilterPtr
9119d9
 virNetDevRxFilterNew(void)
9119d9
 {
9119d9
@@ -1964,3 +2257,39 @@ virNetDevRxFilterFree(virNetDevRxFilterPtr filter)
9119d9
         VIR_FREE(filter);
9119d9
     }
9119d9
 }
9119d9
+
9119d9
+
9119d9
+/**
9119d9
+ * virNetDevGetRxFilter:
9119d9
+ * This function supplies the RX filter list for a given device interface
9119d9
+ *
9119d9
+ * @ifname: Name of the interface
9119d9
+ * @filter: The RX filter list
9119d9
+ *
9119d9
+ * Returns 0 or -1 on failure.
9119d9
+ */
9119d9
+int virNetDevGetRxFilter(const char *ifname,
9119d9
+                         virNetDevRxFilterPtr *filter)
9119d9
+{
9119d9
+    int ret = -1;
9119d9
+    virNetDevRxFilterPtr fil = virNetDevRxFilterNew();
9119d9
+
9119d9
+    if (!fil)
9119d9
+        goto cleanup;
9119d9
+
9119d9
+    if (virNetDevGetMAC(ifname, &fil->mac))
9119d9
+        goto cleanup;
9119d9
+
9119d9
+    if (virNetDevGetMulticastTable(ifname, fil))
9119d9
+        goto cleanup;
9119d9
+
9119d9
+    ret = 0;
9119d9
+ cleanup:
9119d9
+    if (ret < 0) {
9119d9
+        virNetDevRxFilterFree(fil);
9119d9
+        fil = NULL;
9119d9
+    }
9119d9
+
9119d9
+    *filter = fil;
9119d9
+    return ret;
9119d9
+}
9119d9
diff --git a/src/util/virnetdev.h b/src/util/virnetdev.h
9119d9
index 2a6e67d..ac4beff 100644
9119d9
--- a/src/util/virnetdev.h
9119d9
+++ b/src/util/virnetdev.h
9119d9
@@ -189,5 +189,15 @@ int virNetDevGetLinkInfo(const char *ifname,
9119d9
 virNetDevRxFilterPtr virNetDevRxFilterNew(void)
9119d9
    ATTRIBUTE_RETURN_CHECK;
9119d9
 void virNetDevRxFilterFree(virNetDevRxFilterPtr filter);
9119d9
+int virNetDevGetRxFilter(const char *ifname,
9119d9
+                         virNetDevRxFilterPtr *filter)
9119d9
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK;
9119d9
+
9119d9
+int virNetDevAddMulti(const char *ifname,
9119d9
+                      virMacAddrPtr macaddr)
9119d9
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK;
9119d9
+int virNetDevDelMulti(const char *ifname,
9119d9
+                      virMacAddrPtr macaddr)
9119d9
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK;
9119d9
 
9119d9
 #endif /* __VIR_NETDEV_H__ */
9119d9
-- 
9119d9
2.1.3
9119d9