Blob Blame History Raw
From 8d86aac0104f3a7a1f5c26ab04ac480b05b3921f Mon Sep 17 00:00:00 2001
Message-Id: <8d86aac0104f3a7a1f5c26ab04ac480b05b3921f@dist-git>
From: Laine Stump <laine@laine.org>
Date: Mon, 15 Dec 2014 10:51:25 -0500
Subject: [PATCH] util: new functions for setting bridge and bridge port
 attributes

This is part of the fix for:

  https://bugzilla.redhat.com/show_bug.cgi?id=1099210

These functions all set/get items in the sysfs for a bridge device.

(cherry picked from commit 100b7a72a4cf209f2146610f1860b87331f1d9ad)

Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
---
 src/libvirt_private.syms   |   6 ++
 src/util/virnetdevbridge.c | 235 ++++++++++++++++++++++++++++++++++++++++++++-
 src/util/virnetdevbridge.h |  28 +++++-
 3 files changed, 266 insertions(+), 3 deletions(-)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 6353d9c..2b7526a 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1632,9 +1632,15 @@ virNetDevBridgeCreate;
 virNetDevBridgeDelete;
 virNetDevBridgeGetSTP;
 virNetDevBridgeGetSTPDelay;
+virNetDevBridgeGetVlanFiltering;
+virNetDevBridgePortGetLearning;
+virNetDevBridgePortGetUnicastFlood;
+virNetDevBridgePortSetLearning;
+virNetDevBridgePortSetUnicastFlood;
 virNetDevBridgeRemovePort;
 virNetDevBridgeSetSTP;
 virNetDevBridgeSetSTPDelay;
+virNetDevBridgeSetVlanFiltering;
 
 
 # util/virnetdevmacvlan.h
diff --git a/src/util/virnetdevbridge.c b/src/util/virnetdevbridge.c
index d388358..1f3f221 100644
--- a/src/util/virnetdevbridge.c
+++ b/src/util/virnetdevbridge.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2013 Red Hat, Inc.
+ * Copyright (C) 2007-2014 Red Hat, Inc.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -219,6 +219,170 @@ static int virNetDevBridgeGet(const char *brname,
 }
 #endif /* __linux__ */
 
+#if defined(__linux__)
+static int
+virNetDevBridgePortSet(const char *brname,
+                       const char *ifname,
+                       const char *paramname,
+                       unsigned long value)
+{
+    char *path = NULL;
+    char valuestr[INT_BUFSIZE_BOUND(value)];
+    int ret = -1;
+
+    snprintf(valuestr, sizeof(valuestr), "%lu", value);
+
+    if (virAsprintf(&path, "%s/%s/brif/%s/%s",
+                    SYSFS_NET_DIR, brname, ifname, paramname) < 0)
+        return -1;
+
+    if (!virFileExists(path))
+        errno = EINVAL;
+    else
+        ret = virFileWriteStr(path, valuestr, 0);
+
+    if (ret < 0) {
+        virReportSystemError(errno,
+                             _("Unable to set bridge %s port %s %s to %s"),
+                             brname, ifname, paramname, valuestr);
+    }
+
+    VIR_FREE(path);
+    return ret;
+}
+
+
+static int
+virNetDevBridgePortGet(const char *brname,
+                       const char *ifname,
+                       const char *paramname,
+                       unsigned long *value)
+{
+    char *path = NULL;
+    char *valuestr = NULL;
+    int ret = -1;
+
+    if (virAsprintf(&path, "%s/%s/brif/%s/%s",
+                    SYSFS_NET_DIR, brname, ifname, paramname) < 0)
+        return -1;
+
+    if (virFileReadAll(path, INT_BUFSIZE_BOUND(unsigned long), &valuestr) < 0)
+        goto cleanup;
+
+    if (virStrToLong_ul(valuestr, NULL, 10, value) < 0) {
+        virReportSystemError(EINVAL,
+                             _("Unable to get bridge %s port %s %s"),
+                             brname, ifname, paramname);
+        goto cleanup;
+    }
+
+    ret = 0;
+ cleanup:
+    VIR_FREE(path);
+    VIR_FREE(valuestr);
+    return ret;
+}
+
+
+int
+virNetDevBridgePortGetLearning(const char *brname,
+                               const char *ifname,
+                               bool *enable)
+{
+    int ret = -1;
+    unsigned long value;
+
+    if (virNetDevBridgePortGet(brname, ifname, "learning", &value) < 0)
+       goto cleanup;
+
+    *enable = !!value;
+    ret = 0;
+ cleanup:
+    return ret;
+}
+
+
+int
+virNetDevBridgePortSetLearning(const char *brname,
+                               const char *ifname,
+                               bool enable)
+{
+    return virNetDevBridgePortSet(brname, ifname, "learning", enable ? 1 : 0);
+}
+
+
+int
+virNetDevBridgePortGetUnicastFlood(const char *brname,
+                                   const char *ifname,
+                                   bool *enable)
+{
+    int ret = -1;
+    unsigned long value;
+
+    if (virNetDevBridgePortGet(brname, ifname, "unicast_flood", &value) < 0)
+       goto cleanup;
+
+    *enable = !!value;
+    ret = 0;
+ cleanup:
+    return ret;
+}
+
+
+int
+virNetDevBridgePortSetUnicastFlood(const char *brname,
+                                   const char *ifname,
+                                   bool enable)
+{
+    return virNetDevBridgePortSet(brname, ifname, "unicast_flood", enable ? 1 : 0);
+}
+
+
+#else
+int
+virNetDevBridgePortGetLearning(const char *brname ATTRIBUTE_UNUSED,
+                               const char *ifname ATTRIBUTE_UNUSED,
+                               bool *enable ATTRIBUTE_UNUSED)
+{
+    virReportSystemError(ENOSYS, "%s",
+                         _("Unable to get bridge port learning on this platform"));
+    return -1;
+}
+
+
+int
+virNetDevBridgePortSetLearning(const char *brname ATTRIBUTE_UNUSED,
+                               const char *ifname ATTRIBUTE_UNUSED,
+                               bool enable)
+{
+    virReportSystemError(ENOSYS, "%s",
+                         _("Unable to set bridge port learning on this platform"));
+    return -1;
+}
+
+
+int
+virNetDevBridgePortGetUnicastFlood(const char *brname ATTRIBUTE_UNUSED,
+                                   const char *ifname ATTRIBUTE_UNUSED,
+                                   bool *enable ATTRIBUTE_UNUSED)
+{
+    virReportSystemError(ENOSYS, "%s",
+                         _("Unable to get bridge port unicast_flood on this platform"));
+    return -1;
+}
+
+
+int
+virNetDevBridgePortSetUnicastFlood(const char *brname ATTRIBUTE_UNUSED,
+                                   const char *ifname ATTRIBUTE_UNUSED,
+                                   bool enable ATTRIBUTE_UNUSED)
+{
+    virReportSystemError(ENOSYS, "%s",
+                         _("Unable to set bridge port unicast_flood on this platform"));
+    return -1;
+}
+#endif
+
 
 /**
  * virNetDevBridgeCreate:
@@ -518,7 +682,7 @@ int virNetDevBridgeSetSTPDelay(const char *brname,
  * @brname: the bridge device name
  * @delayms: the forward delay in milliseconds
  *
- * Retrives the forward delay for the bridge device @brname
+ * Retrieves the forward delay for the bridge device @brname
  * storing it in @delayms. The forward delay is only meaningful
  * if STP is enabled
  *
@@ -683,3 +847,70 @@ int virNetDevBridgeGetSTP(const char *brname,
     return -1;
 }
 #endif
+
+#if defined(HAVE_STRUCT_IFREQ) && defined(__linux__)
+/**
+ * virNetDevBridgeGetVlanFiltering:
+ * @brname: the bridge device name
+ * @enable: true or false
+ *
+ * Retrieves the vlan_filtering setting for the bridge device @brname
+ * storing it in @enable.
+ *
+ * Returns 0 on success, -1 on error
+ */
+int
+virNetDevBridgeGetVlanFiltering(const char *brname,
+                                bool *enable)
+{
+    int ret = -1;
+    unsigned long value;
+
+    if (virNetDevBridgeGet(brname, "vlan_filtering", &value, -1, NULL) < 0)
+        goto cleanup;
+
+    *enable = !!value;
+    ret = 0;
+ cleanup:
+    return ret;
+}
+
+
+/**
+ * virNetDevBridgeSetVlanFiltering:
+ * @brname: the bridge name
+ * @enable: true or false
+ *
+ * Set the bridge vlan_filtering mode
+ *
+ * Returns 0 in case of success or -1 on failure
+ */
+
+int
+virNetDevBridgeSetVlanFiltering(const char *brname,
+                                bool enable)
+{
+    return virNetDevBridgeSet(brname, "vlan_filtering", enable ? 1 : 0, -1, NULL);
+}
+
+
+#else
+int
+virNetDevBridgeGetVlanFiltering(const char *brname ATTRIBUTE_UNUSED,
+                                bool *enable ATTRIBUTE_UNUSED)
+{
+    virReportSystemError(ENOSYS, "%s",
+                         _("Unable to get bridge vlan_filtering on this platform"));
+    return -1;
+}
+
+
+int
+virNetDevBridgeSetVlanFiltering(const char *brname ATTRIBUTE_UNUSED,
+                                bool enable ATTRIBUTE_UNUSED)
+{
+    virReportSystemError(ENOSYS, "%s",
+                         _("Unable to set bridge vlan_filtering on this platform"));
+    return -1;
+}
+#endif
diff --git a/src/util/virnetdevbridge.h b/src/util/virnetdevbridge.h
index 13776d2..8188a2f 100644
--- a/src/util/virnetdevbridge.h
+++ b/src/util/virnetdevbridge.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2011 Red Hat, Inc.
+ * Copyright (C) 2007-2012, 2014 Red Hat, Inc.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -51,4 +51,30 @@ int virNetDevBridgeGetSTP(const char *brname,
                           bool *enable)
     ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK;
 
+int virNetDevBridgeSetVlanFiltering(const char *brname,
+                                    bool enable)
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK;
+int virNetDevBridgeGetVlanFiltering(const char *brname,
+                                    bool *enable)
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK;
+
+int virNetDevBridgePortGetLearning(const char *brname,
+                                   const char *ifname,
+                                   bool *enable)
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3)
+    ATTRIBUTE_RETURN_CHECK;
+int virNetDevBridgePortSetLearning(const char *brname,
+                                   const char *ifname,
+                                   bool enable)
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK;
+int virNetDevBridgePortGetUnicastFlood(const char *brname,
+                                       const char *ifname,
+                                       bool *enable)
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3)
+    ATTRIBUTE_RETURN_CHECK;
+int virNetDevBridgePortSetUnicastFlood(const char *brname,
+                                       const char *ifname,
+                                       bool enable)
+    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK;
+
 #endif /* __VIR_NETDEV_BRIDGE_H__ */
-- 
2.2.0