|
|
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 |
|