]> git.ipfire.org Git - thirdparty/lldpd.git/commitdiff
netlink: handle veth loops correctly
authorVincent Bernat <vincent@bernat.im>
Fri, 1 Jan 2016 20:11:02 +0000 (21:11 +0100)
committerVincent Bernat <vincent@bernat.im>
Fri, 1 Jan 2016 20:11:02 +0000 (21:11 +0100)
Since Linux 4.1, a pair of veth are referenced as IFLINK for each
other. We previously detected this loop easily and did break the loop by
removing this bogus information. However, when one of the interface is
updated, only the modified interface has IFLINK pointing to the other
interface. Therefore, no more loop but the information is incorrect. To
avoid that, don't reset indexes, just pointers. We only use indexes to
build correctly those pointers.

src/daemon/netlink.c

index 720af3838d970a76faa164dfa157cf3ce60daea1..e0c2b888240cbc2785089bccb29391e35dd3b371 100644 (file)
@@ -498,19 +498,29 @@ end:
                                                break;
                                        }
                                }
+                               if (iface2 == NULL)
+                                       iface1->upper = NULL;
                        } else {
                                iface1->upper = NULL;
                        }
                        if (iface1->lower_idx != -1 && iface1->lower_idx != iface1->index) {
                                TAILQ_FOREACH(iface2, ifs, next) {
                                        if (iface1->lower_idx == iface2->index) {
+                                               /* Workaround a bug introduced
+                                                * in Linux 4.1: a pair of veth
+                                                * will be lower interface of
+                                                * each other. Do not modify
+                                                * index as if one of them is
+                                                * updated, we will loose the
+                                                * information about the
+                                                * loop. */
                                                if (iface2->lower_idx == iface1->index) {
-                                                       /* Workaround a bug introduced in Linux 4.1 */
-                                                       iface2->lower_idx = iface2->index;
-                                                       iface1->lower_idx = iface1->index;
+                                                       iface1->lower = NULL;
                                                } else iface1->lower = iface2;
                                                break;
                                        }
+                                       if (iface2 == NULL)
+                                               iface1->lower = NULL;
                                }
                        } else {
                                iface1->lower = NULL;