]> git.proxmox.com Git - mirror_frr.git/commitdiff
zebra: resolve link dependencies post nldump
authorAnuradha Karuppiah <anuradhak@cumulusnetworks.com>
Wed, 12 Sep 2018 18:33:51 +0000 (11:33 -0700)
committerDonald Sharp <sharpd@cumulusnetworks.com>
Tue, 18 Sep 2018 14:41:53 +0000 (10:41 -0400)
Netdevices are not sorted in any fashion by the kernel during the initial
interface nldump. So you can get an upper device (such as an SVI) before
its corresponding lower device (bridge).

To fix this problem we skip resolving link dependencies during handling of
nldump notifications. Resolving instead at the end (when all the devices
are present)

Signed-off-by: Anuradha Karuppiah <anuradhak@cumulusnetworks.com>
Ticket: CM-22388, CM-21796
Reviewed By: CCR-7845
Testing Done:
1. verified on a setup with missing linkages
2. automation - evpn-min

zebra/if_netlink.c
zebra/interface.c
zebra/interface.h

index 47a101e619b84055c193934d7570879b219de141..6c71fddbbf9af0fae0f80ca99e68c034af772b69 100644 (file)
@@ -585,6 +585,7 @@ static int netlink_interface(struct nlmsghdr *h, ns_id_t ns_id, int startup)
        zebra_slave_iftype_t zif_slave_type = ZEBRA_IF_SLAVE_NONE;
        ifindex_t bridge_ifindex = IFINDEX_INTERNAL;
        ifindex_t link_ifindex = IFINDEX_INTERNAL;
+       struct zebra_if *zif;
 
        zns = zebra_ns_lookup(ns_id);
        ifi = NLMSG_DATA(h);
@@ -679,8 +680,12 @@ static int netlink_interface(struct nlmsghdr *h, ns_id_t ns_id, int startup)
        if (IS_ZEBRA_IF_VRF(ifp))
                SET_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK);
 
-       /* Update link. */
-       zebra_if_update_link(ifp, link_ifindex, ns_id);
+       /* Just set the @link/lower-device ifindex. During nldump interfaces are
+        * not ordered in any fashion so we may end up getting upper devices
+        * before lower devices. We will setup the real linkage once the dump
+        * is complete. */
+       zif = (struct zebra_if *)ifp->info;
+       zif->link_ifindex = link_ifindex;
 
        /* Hardware type and address. */
        ifp->ll_type = netlink_to_zebra_link_type(ifi->ifi_type);
@@ -754,6 +759,9 @@ int interface_lookup_netlink(struct zebra_ns *zns)
        if (ret < 0)
                return ret;
 
+       /* fixup linkages */
+       zebra_if_update_all_links();
+
        /* Get IPv4 address of the interfaces. */
        ret = netlink_request_intf_addr(zns, AF_INET, RTM_GETADDR, 0);
        if (ret < 0)
index ca90c18cf2c89ef7fe21bfbc6931026de7c4cf89..9e43a5b53c4ceec55b1842c990476aa0ccfb6f7a 100644 (file)
@@ -999,6 +999,37 @@ void zebra_if_update_link(struct interface *ifp, ifindex_t link_ifindex,
                                              link_ifindex);
 }
 
+/* during initial link dump kernel does not order lower devices before
+ * upper devices so we need to fixup link dependencies at the end of dump */
+void zebra_if_update_all_links(void)
+{
+       struct route_node *rn;
+       struct interface *ifp;
+       struct zebra_if *zif;
+       struct zebra_ns *ns;
+
+       if (IS_ZEBRA_DEBUG_KERNEL)
+               zlog_info("fixup link dependencies");
+
+       ns = zebra_ns_lookup(NS_DEFAULT);
+       for (rn = route_top(ns->if_table); rn; rn = route_next(rn)) {
+               ifp = (struct interface *)rn->info;
+               if (!ifp)
+                       continue;
+               zif = ifp->info;
+               if ((zif->link_ifindex != IFINDEX_INTERNAL) && !zif->link) {
+                       zif->link = if_lookup_by_index_per_ns(ns,
+                                                        zif->link_ifindex);
+                       if (IS_ZEBRA_DEBUG_KERNEL)
+                               zlog_debug("interface %s/%d's lower fixup to %s/%d",
+                                               ifp->name, ifp->ifindex,
+                                               zif->link?zif->link->name:"unk",
+                                               zif->link_ifindex);
+               }
+       }
+}
+
+
 
 /* Output prefix string to vty. */
 static int prefix_vty_out(struct vty *vty, struct prefix *p)
index 02a05e6146399c5b53412baad44241dcf24d3b5c..c6d8b24b019a23f0259bceabee81191a8c4db22b 100644 (file)
@@ -348,6 +348,7 @@ extern int ipv6_address_configured(struct interface *ifp);
 extern void if_handle_vrf_change(struct interface *ifp, vrf_id_t vrf_id);
 extern void zebra_if_update_link(struct interface *ifp, ifindex_t link_ifindex,
                                 ns_id_t ns_id);
+extern void zebra_if_update_all_links(void);
 
 extern void vrf_add_update(struct vrf *vrfp);