]> git.ipfire.org Git - thirdparty/lldpd.git/commitdiff
linux: mangle MAC address for enslaved devices
authorVincent Bernat <bernat@luffy.cx>
Thu, 25 Jul 2013 08:24:30 +0000 (10:24 +0200)
committerVincent Bernat <bernat@luffy.cx>
Thu, 25 Jul 2013 08:24:30 +0000 (10:24 +0200)
With enslaved devices, we may end up with in a situation where we send
a packet with a source MAC address that may confuse switches. For
example:

 1. eth0, MAC X connected to switch A.
 2. eth1, MAC Y connected to switch B.
 3. Active/backup bond is created, MAC X.
 4. eth1 is active, eth0 is backup.

If we use the real MAC, eth0 will send LLDP packets with MAC X to
switch A that will learn this MAC and send packets on backup port eth0
and they will be discarded.

The solution until then was to use a zero MAC address in those
cases. However, it seems that some switches may be confused by such a
move. See #26.

Instead, we set the "local" bit to 1 if not already set. Otherwise, we
just use some arbitrary MAC address that I have on an unused 3Com
"Tornado" card. It is unlikely to be reused (100 MBps and it is in a
basement). If you happen to have an even older MAC address and are
willing to give it for lldpd, feel free to tell me. The later case
does not handle all problems but allievate the problem with switches
discarding or complaining about zero MAC address as a source.

NEWS
src/daemon/interfaces-linux.c

diff --git a/NEWS b/NEWS
index 80a74ea570694df9906b48e5aaf86f37a590c35f..3af638f248053b8135402d86e2c181df35f7891e 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,4 +1,7 @@
 lldpd (0.7.7)
+  * Features:
+    + Use a locally administered MAC address or an arbitrary one
+      instead of null MAC address for bond devices on Linux.
   * Fixes:
     + Various bugs related to fixed point number handling (for
       coordinates in LLDP-MED)
index 00124befda830068b61d06fee6cb6f9b7e95704b..ebd374eba9150762eda7b20e1fdb7e75faf36753 100644 (file)
@@ -465,14 +465,31 @@ iface_bond_init(struct lldpd *cfg, struct lldpd_hardware *hardware)
        return 0;
 }
 
+/**
+ * Mangle the MAC address to avoid duplicates.
+ *
+ * With bonds, we have duplicate MAC address on different physical
+ * interfaces. We need to alter the source MAC address when we send on
+ * an inactive slave. We try to set "local" bit to 1 first. If it is
+ * already set to 1, use an unused MAC address instead.
+ */
+static void
+iface_mangle_mac(char *buffer)
+{
+       if (buffer[0] & 2) {
+               /* Already a locally administered MAC address, use a fixed MAC
+                * address (an old 3c905 MAC address of a card that I own). */
+               char arbitrary[] = { 0x00, 0x60, 0x08, 0x69, 0x97, 0xef};
+               memcpy(buffer, arbitrary, sizeof(arbitrary));
+               return;
+       }
+       buffer[0] |= 2;
+}
+
 static int
 iface_bond_send(struct lldpd *cfg, struct lldpd_hardware *hardware,
     char *buffer, size_t size)
 {
-       /* With bonds, we have duplicate MAC address on different physical
-        * interfaces. We need to alter the source MAC address when we send on
-        * an inactive slave. To avoid any future problem, we always set the
-        * source MAC address to 0. */
        log_debug("interfaces", "send PDU to bonded device %s",
            hardware->h_ifname);
        if (size < 2 * ETHER_ADDR_LEN) {
@@ -481,7 +498,7 @@ iface_bond_send(struct lldpd *cfg, struct lldpd_hardware *hardware,
                    hardware->h_ifname);
                return 0;
        }
-       memset(buffer + ETHER_ADDR_LEN, 0, ETHER_ADDR_LEN);
+       iface_mangle_mac(buffer + ETHER_ADDR_LEN);
        return write(hardware->h_sendfd,
            buffer, size);
 }