]> git.proxmox.com Git - mirror_frr.git/commitdiff
zebra: advertise stale neighs if EVPN-MH is not enabled
authorAnuradha Karuppiah <anuradhak@cumulusnetworks.com>
Tue, 7 Jul 2020 01:01:41 +0000 (18:01 -0700)
committerAnuradha Karuppiah <anuradhak@nvidia.com>
Mon, 21 Dec 2020 16:41:15 +0000 (08:41 -0800)
With EVPN-MH, Type-2 routes are also used for MAC-IP syncing between
ES peers so a change was done to only treat REACHABLE local neigh
entries as local-active and advertise them as Type-2 routes i.e. STALE
neigh entries are no longer advertised as Type-2s.

This however exposed some unexpected problems with MLAG where a
secondary reboot followed by a primary reboot left a lot of neighs
in STALE state (on the primary) resulting in them not being
advertised. And remote routed traffic to those hosts being
blackholed in a sym-IRB setup.

This commit is a workaround to fix the regression (it doesn't fix
the underlying problems with entries not becoming REACHABLE; which
maybe a day-1 problem). The workaround is to continue advertising
STALE neighbors if EVPN-MH is not enabled.

Ticket: CM-30303

Signed-off-by: Anuradha Karuppiah <anuradhak@cumulusnetworks.com>
zebra/rt_netlink.c
zebra/zebra_evpn_mh.c
zebra/zebra_evpn_mh.h

index f59fbae3afebb6af2c5b4c4976bd5572c463c0f2..1be67dac6042d27a58672ef9308b6f331b3cf8eb 100644 (file)
@@ -3410,7 +3410,15 @@ static int netlink_ipneigh_change(struct nlmsghdr *h, int len, ns_id_t ns_id)
                 * in re-adding the neighbor if it is a valid "remote" neighbor.
                 */
                if (ndm->ndm_state & NUD_VALID) {
-                       local_inactive = !(ndm->ndm_state & NUD_LOCAL_ACTIVE);
+                       if (zebra_evpn_mh_do_adv_reachable_neigh_only())
+                               local_inactive =
+                                       !(ndm->ndm_state & NUD_LOCAL_ACTIVE);
+                       else
+                               /* If EVPN-MH is not enabled we treat STALE
+                                * neighbors as locally-active and advertise
+                                * them
+                                */
+                               local_inactive = false;
 
                        /* XXX - populate dp-static based on the sync flags
                         * in the kernel
index e3018d5af256687181b02ba3a2adfb74c5acba48..79868e7fc9cad735cf68751eb8870b160253b9df 100644 (file)
@@ -1941,6 +1941,23 @@ static void zebra_evpn_mh_dup_addr_detect_off(void)
        }
 }
 
+/* On config of first local-ES turn off advertisement of STALE/DELAY/PROBE
+ * neighbors
+ */
+static void zebra_evpn_mh_advertise_reach_neigh_only(void)
+{
+       if (zmh_info->flags & ZEBRA_EVPN_MH_ADV_REACHABLE_NEIGH_ONLY)
+               return;
+
+       zmh_info->flags |= ZEBRA_EVPN_MH_ADV_REACHABLE_NEIGH_ONLY;
+       if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
+               zlog_debug("evpn-mh: only REACHABLE neigh advertised");
+
+       /* XXX - if STALE/DELAY/PROBE neighs were previously advertised we
+        * need to withdraw them
+        */
+}
+
 static int zebra_evpn_es_df_delay_exp_cb(struct thread *t)
 {
        struct zebra_evpn_es *es;
@@ -1966,6 +1983,7 @@ static void zebra_evpn_es_local_info_set(struct zebra_evpn_es *es,
                           es->nhg_id, zif->ifp->name);
 
        zebra_evpn_mh_dup_addr_detect_off();
+       zebra_evpn_mh_advertise_reach_neigh_only();
 
        es->flags |= ZEBRA_EVPNES_LOCAL;
        listnode_init(&es->local_es_listnode, es);
index 14b29875740a83acd6aca31d862a77d630921247..81ae740d49d5bffb6dd52c872186c3c6c640aa09 100644 (file)
@@ -195,6 +195,11 @@ struct zebra_evpn_mh_info {
  * first local ES, DAD is turned off
  */
 #define ZEBRA_EVPN_MH_DUP_ADDR_DETECT_OFF (1 << 1)
+/* If EVPN MH is enabled we only advertise REACHABLE neigh entries as Type-2
+ * routes. As there is no global config knob for enabling EVPN MH we turn
+ * this flag when the first local ES is detected.
+ */
+#define ZEBRA_EVPN_MH_ADV_REACHABLE_NEIGH_ONLY (1 << 2)
 
        /* RB tree of Ethernet segments (used for EVPN-MH)  */
        struct zebra_es_rb_head es_rb_tree;
@@ -275,6 +280,12 @@ static inline bool zebra_evpn_mh_do_dup_addr_detect(void)
        return !(zmh_info->flags & ZEBRA_EVPN_MH_DUP_ADDR_DETECT_OFF);
 }
 
+static inline bool zebra_evpn_mh_do_adv_reachable_neigh_only(void)
+{
+       return !!(zmh_info->flags & ZEBRA_EVPN_MH_ADV_REACHABLE_NEIGH_ONLY);
+}
+
+
 /*****************************************************************************/
 extern esi_t *zero_esi;
 extern void zebra_evpn_mh_init(void);