]> git.puffer.fish Git - mirror/frr.git/commitdiff
zebra: lookup link by ifindex
authorMitesh Kanjariya <mitesh@marvel-07.cumulusnetworks.com>
Sun, 20 Aug 2017 00:28:58 +0000 (17:28 -0700)
committerMitesh Kanjariya <mitesh@marvel-07.cumulusnetworks.com>
Sun, 20 Aug 2017 13:10:38 +0000 (06:10 -0700)
Frr has an assumption that when interface A links to B,
we already know about B. But that might be true always.
It is probably purely depends on the configuration
and how the interfaces are hashed in Kernel.
FRR seems to sometimes get "A is linked to B" before it knows about B,
in that case, the linkage between the data structure for A & B won't be proper.

Ticket: CM-17679
Review: ccr-6628
Testing: Manual

Signed-off-by: Mitesh Kanjariya <mitesh@cumulusnetworks.com>
zebra/interface.c
zebra/rt_netlink.c
zebra/zebra_vxlan.c

index c4d0363994f51c5169f06bd45fe789259edd3c67..8456984330aab075e3b2a12c16cb30f1a64944bd 100644 (file)
@@ -874,7 +874,8 @@ void if_up(struct interface *ifp)
                link_if = ifp;
                zebra_vxlan_svi_up(ifp, link_if);
        } else if (IS_ZEBRA_IF_VLAN(ifp)) {
-               link_if = zif->link;
+               link_if = if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT),
+                                                   zif->link_ifindex);
                if (link_if)
                        zebra_vxlan_svi_up(ifp, link_if);
        }
@@ -902,7 +903,8 @@ void if_down(struct interface *ifp)
                link_if = ifp;
                zebra_vxlan_svi_down(ifp, link_if);
        } else if (IS_ZEBRA_IF_VLAN(ifp)) {
-               link_if = zif->link;
+               link_if = if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT),
+                                                   zif->link_ifindex);
                if (link_if)
                        zebra_vxlan_svi_down(ifp, link_if);
        }
index e28fe5630aeeb53360bc073599f099e2259c498b..6763a9a82e1021f97c56fa59698b69918052374d 100644 (file)
@@ -2005,7 +2005,8 @@ static int netlink_ipneigh_change(struct sockaddr_nl *snl, struct nlmsghdr *h,
         * itself
         */
        if (IS_ZEBRA_IF_VLAN(ifp)) {
-               link_if = zif->link;
+               link_if = if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT),
+                                                   zif->link_ifindex);
                if (!link_if)
                        return 0;
        } else if (IS_ZEBRA_IF_BRIDGE(ifp))
index 86c3ce1d00b7643f21d5f3d67bb94cc62febb5af..32c0e20a917b53e092cca0bc0f5ba7742a81943b 100644 (file)
@@ -1777,6 +1777,9 @@ static zebra_vni_t *zvni_map_svi(struct interface *ifp, struct interface *br_if)
        vlanid_t vid = 0;
        zebra_vni_t *zvni;
 
+       if (!br_if)
+               return NULL;
+
        /* Make sure the linked interface is a bridge. */
        if (!IS_ZEBRA_IF_BRIDGE(br_if))
                return NULL;
@@ -3886,7 +3889,11 @@ int zebra_vxlan_add_del_gw_macip(struct interface *ifp, struct prefix *p,
                if (!ifp_zif)
                        return -1;
 
-               svi_if = ifp_zif->link;
+               /*
+                * for a MACVLAN interface the link represents the svi_if
+                */
+               svi_if = if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT),
+                                                  ifp_zif->link_ifindex);
                if (!svi_if) {
                        zlog_err("%u:MACVLAN %s(%u) without link information",
                                 ifp->vrf_id, ifp->name, ifp->ifindex);
@@ -3894,19 +3901,39 @@ int zebra_vxlan_add_del_gw_macip(struct interface *ifp, struct prefix *p,
                }
 
                if (IS_ZEBRA_IF_VLAN(svi_if)) {
+                       /*
+                        * If it is a vlan aware bridge then the link gives the
+                        * bridge information
+                        */
+                       struct interface *svi_if_link = NULL;
+
                        svi_if_zif = svi_if->info;
-                       if (svi_if_zif)
-                               zvni = zvni_map_svi(svi_if, svi_if_zif->link);
+                       if (svi_if_zif) {
+                               svi_if_link = if_lookup_by_index_per_ns(
+                                                       zebra_ns_lookup(
+                                                               NS_DEFAULT),
+                                                       svi_if_zif->link_ifindex);
+                               zvni = zvni_map_svi(svi_if, svi_if_link);
+                       }
                } else if (IS_ZEBRA_IF_BRIDGE(svi_if)) {
+                       /*
+                        * If it is a vlan unaware bridge then svi is the bridge
+                        * itself
+                        */
                        zvni = zvni_map_svi(svi_if, svi_if);
                }
        } else if (IS_ZEBRA_IF_VLAN(ifp)) {
                struct zebra_if *svi_if_zif =
-                       NULL; /* Zebra daemon specific info for SVI*/
+                       NULL; /* Zebra daemon specific info for SVI */
+               struct interface *svi_if_link =
+                       NULL; /* link info for the SVI = bridge info */
 
                svi_if_zif = ifp->info;
-               if (svi_if_zif)
-                       zvni = zvni_map_svi(ifp, svi_if_zif->link);
+               svi_if_link =
+                       if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT),
+                                                 svi_if_zif->link_ifindex);
+               if (svi_if_zif && svi_if_link)
+                       zvni = zvni_map_svi(ifp, svi_if_link);
        } else if (IS_ZEBRA_IF_BRIDGE(ifp)) {
                zvni = zvni_map_svi(ifp, ifp);
        }