]> git.ipfire.org Git - thirdparty/lldpd.git/commitdiff
interfaces: enable team interfaces like a bond interface
authorVincent Bernat <vincent@bernat.im>
Sat, 12 Aug 2017 18:09:22 +0000 (20:09 +0200)
committerVincent Bernat <vincent@bernat.im>
Sat, 12 Aug 2017 18:26:53 +0000 (20:26 +0200)
Unfortunately, we are not able to retrieve the real MAC address as the
kernel doesn't know it. Only the teamd daemon knows it. We could ask for
it through ethtool but it would be the permenant MAC address which may
be incorrect.

Fix #234

NEWS
src/daemon/interfaces-linux.c
src/daemon/netlink.c
tests/integration/fixtures/network.py
tests/integration/test_interfaces.py

diff --git a/NEWS b/NEWS
index 46423519d3e9378b3c28aa17fa7f37300286f9d8..61f917a65f576534d0cd87cccda8d5f7401048d6 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,9 @@
 lldpd (0.9.8)
   * Changes:
     + "Station" capability is only set if no other bit is set.
+  * Fixes:
+    + Handle team interfaces like a bond. Real MAC address cannot be
+      retrieved yet.
 
 lldpd (0.9.7)
   * Changes:
index 92aad6a56f77deb706890664567dbb9fcb1700b7..3150e6b888f59002f7826f20089e6fc5b14e665c 100644 (file)
@@ -293,6 +293,9 @@ iflinux_get_permanent_mac(struct lldpd *cfg,
 
        if ((master = iface->upper) == NULL || master->type != IFACE_BOND_T)
                return;
+       if (master->driver == NULL || strcmp(master->driver, "bonding"))
+               /* Not a bond interface, maybe a team */
+               return;
 
        /* We have a bond, we need to query it to get real MAC addresses */
        if (snprintf(path, SYSFS_PATH_MAX, "/proc/net/bonding/%s",
index 1a64a231938aa97844591bdc5df13eda4560acaa..6e80d2545ecae37780ec1395a6b418f1771976ec 100644 (file)
@@ -211,6 +211,10 @@ netlink_parse_linkinfo(struct interfaces_device *iff, struct rtattr *rta, int le
                                log_debug("netlink", "interface %s is a bond",
                                    iff->name);
                                iff->type |= IFACE_BOND_T;
+                       } else if (!strcmp(kind, "team")) {
+                               log_debug("netlink", "interface %s is a team",
+                                   iff->name);
+                               iff->type |= IFACE_BOND_T;
                        }
                }
        }
index 42ff48e1798a54f8cf9766dbfba043fc5d656c21..8aa8cf92dd4593b88ca19fa4acce1535d85592dd 100644 (file)
@@ -77,12 +77,12 @@ class LinksFactory(object):
         ipr.link('set', index=idx, state='up')
         return idx
 
-    def bond(self, name, *ifaces):
-        """Create a bond."""
+    def _bond_or_team(self, kind, name, *ifaces):
+        """Create a bond or a team."""
         ipr = pyroute2.IPRoute()
         # Create the bond
         ipr.link_create(ifname=name,
-                        kind='bond')
+                        kind=kind)
         idx = ipr.link_lookup(ifname=name)[0]
         # Attach interfaces
         for iface in ifaces:
@@ -93,6 +93,16 @@ class LinksFactory(object):
         ipr.link('set', index=idx, state='up')
         return idx
 
+    def team(self, name, *ifaces):
+        """Create a team."""
+        # Unfortunately, pyroute2 will try to run teamd too. This
+        # doesn't work.
+        return self._bond_or_team("team", name, *ifaces)
+
+    def bond(self, name, *ifaces):
+        """Create a bond."""
+        return self._bond_or_team("bond", name, *ifaces)
+
     def vlan(self, name, id, iface):
         """Create a VLAN."""
         ipr = pyroute2.IPRoute()
index c09fc8dbde67db8a693227f3a68406d36ce5ef55..292bf7fbd40419a40da04d43c4f6781ee64fa6ba 100644 (file)
@@ -64,6 +64,29 @@ def test_bond(lldpd1, lldpd, lldpcli, namespaces, links, when):
         assert out['lldp.eth0.port.mac'] == '00:00:00:00:00:02'
 
 
+@pytest.mark.skipif('Dot3' not in pytest.config.lldpd.features,
+                    reason="Dot3 not supported")
+@pytest.mark.skip(reason="Cannot create a simple team interface without teamd")
+@pytest.mark.parametrize('when', ['before', 'after'])
+def test_team(lldpd1, lldpd, lldpcli, namespaces, links, when):
+    links(namespaces(3), namespaces(2))  # Another link to setup a bond
+    with namespaces(2):
+        if when == 'after':
+            lldpd()
+        idx = links.team('team42', 'eth3', 'eth1')
+        if when == 'before':
+            lldpd()
+        else:
+            time.sleep(6)
+    with namespaces(1):
+        out = lldpcli("-f", "keyvalue", "show", "neighbors", "details")
+        assert out['lldp.eth0.port.descr'] == 'eth1'
+        assert out['lldp.eth0.port.aggregation'] == str(idx)
+        # Unfortunately, we cannot get the right MAC currently... So,
+        # this bit will fail.
+        assert out['lldp.eth0.port.mac'] == '00:00:00:00:00:02'
+
+
 @pytest.mark.skipif('Dot3' not in pytest.config.lldpd.features,
                     reason="Dot3 not supported")
 @pytest.mark.skipif('Dot1' not in pytest.config.lldpd.features,