]> git.proxmox.com Git - mirror_frr.git/commitdiff
lib/zebra: zapi for installing EVPN nexthops from bgp
authorAnuradha Karuppiah <anuradhak@cumulusnetworks.com>
Mon, 14 Sep 2020 13:35:45 +0000 (06:35 -0700)
committerAnuradha Karuppiah <anuradhak@nvidia.com>
Fri, 26 Mar 2021 00:09:53 +0000 (17:09 -0700)
EVPN nexthops are installed as remote neighs by zebra. This was earlier
done only via VRF IPvX uni routes imported from EVPN routes.

With EVPN-MH these VRF routes now reference a L3NHG which is setup based
on the EAD and doesn't include the RMAC. To workaround that BGP now
consolidates and maintains EVPN nexthops which are then sent to zebra.

zebra sets up these nexthops as L3-VNI nh entries using a dummy type-1
route as reference.

Ticket: CM-31398

Signed-off-by: Anuradha Karuppiah <anuradhak@cumulusnetworks.com>
lib/log.c
lib/zclient.h
zebra/zapi_msg.c
zebra/zebra_evpn_mh.c
zebra/zebra_evpn_mh.h
zebra/zebra_vxlan.c

index b86d3022b49243c49de852b101508cf5fe0e8b5f..e078d8e2a7a35c67ee987b9ebd4a6ed371dc4afb 100644 (file)
--- a/lib/log.c
+++ b/lib/log.c
@@ -462,7 +462,9 @@ static const struct zebra_desc_table command_types[] = {
        DESC_ENTRY(ZEBRA_NHG_DEL),
        DESC_ENTRY(ZEBRA_NHG_NOTIFY_OWNER),
        DESC_ENTRY(ZEBRA_ROUTE_NOTIFY_REQUEST),
-       DESC_ENTRY(ZEBRA_CLIENT_CLOSE_NOTIFY)};
+       DESC_ENTRY(ZEBRA_CLIENT_CLOSE_NOTIFY),
+       DESC_ENTRY(ZEBRA_EVPN_REMOTE_NH_ADD),
+       DESC_ENTRY(ZEBRA_EVPN_REMOTE_NH_DEL)};
 #undef DESC_ENTRY
 
 static const struct zebra_desc_table unknown = {0, "unknown", '?'};
index 43197534a8f6c91a5bc2e8e908bee2e164185a3a..5b2298c42d941ca31af2f22a97dd78b2a84f6420 100644 (file)
@@ -213,6 +213,8 @@ typedef enum {
        ZEBRA_NHG_ADD,
        ZEBRA_NHG_DEL,
        ZEBRA_NHG_NOTIFY_OWNER,
+       ZEBRA_EVPN_REMOTE_NH_ADD,
+       ZEBRA_EVPN_REMOTE_NH_DEL,
        ZEBRA_ERROR,
        ZEBRA_CLIENT_CAPABILITIES,
        ZEBRA_OPAQUE_MESSAGE,
index 63ba6cd8d906cff713b0c86305cc6e06600bbb92..b482914418f9b1c5b6d053a129f1149cc39556ea 100644 (file)
@@ -3350,6 +3350,8 @@ void (*const zserv_handlers[])(ZAPI_HANDLER_ARGS) = {
        [ZEBRA_NHG_ADD] = zread_nhg_add,
        [ZEBRA_NHG_DEL] = zread_nhg_del,
        [ZEBRA_ROUTE_NOTIFY_REQUEST] = zread_route_notify_request,
+       [ZEBRA_EVPN_REMOTE_NH_ADD] = zebra_evpn_proc_remote_nh,
+       [ZEBRA_EVPN_REMOTE_NH_DEL] = zebra_evpn_proc_remote_nh,
 };
 
 /*
index 1c258a04f76ed5e1f61d3663fa8fa8e22b8a60b4..cabba707a0ce00ee8f1266084fdcc01bbd56fa25 100644 (file)
@@ -3867,6 +3867,47 @@ static void zebra_evpn_mh_startup_delay_timer_start(const char *rc)
        }
 }
 
+/*****************************************************************************
+ * Nexthop management: nexthops associated with Type-2 routes that have
+ * an ES as destination are consolidated by BGP into a per-VRF nh->rmac
+ * mapping which is the installed as a remote neigh/fdb entry with a
+ * dummy (type-1) prefix referencing it.
+ * This handling is needed because Type-2 routes with ES as dest use NHG
+ * that are setup using EAD routes (i.e. such NHGs do not include the
+ * RMAC info).
+ ****************************************************************************/
+void zebra_evpn_proc_remote_nh(ZAPI_HANDLER_ARGS)
+{
+       struct stream *s;
+       vrf_id_t vrf_id;
+       struct ipaddr nh;
+       struct ethaddr rmac;
+       struct prefix_evpn dummy_prefix;
+
+       s = msg;
+       vrf_id = stream_getl(s);
+       stream_get(&nh, s, sizeof(nh));
+
+       memset(&dummy_prefix, 0, sizeof(dummy_prefix));
+       dummy_prefix.family = AF_EVPN;
+       dummy_prefix.prefixlen = (sizeof(struct evpn_addr) * 8);
+       dummy_prefix.prefix.route_type = 1; /* XXX - fixup to type-1 def */
+
+       if (hdr->command == ZEBRA_EVPN_REMOTE_NH_ADD) {
+               stream_get(&rmac, s, sizeof(rmac));
+               if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
+                       zlog_debug("evpn remote nh %d %pIA rmac %pEA add",
+                                  vrf_id, &nh, &rmac);
+               zebra_vxlan_evpn_vrf_route_add(vrf_id, &rmac, &nh,
+                                              (struct prefix *)&dummy_prefix);
+       } else {
+               if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
+                       zlog_debug("evpn remote nh %d %pIA del", vrf_id, &nh);
+               zebra_vxlan_evpn_vrf_route_del(vrf_id, &nh,
+                                              (struct prefix *)&dummy_prefix);
+       }
+}
+
 /*****************************************************************************/
 void zebra_evpn_mh_config_write(struct vty *vty)
 {
index 2361a70bff99e59b6c33105bf898b7db0c603870..8861e80cee4542e692f2e8bfce8800cf38e5c780 100644 (file)
@@ -382,5 +382,6 @@ extern void zebra_evpn_acc_bd_svi_set(struct zebra_if *vlan_zif,
 extern void zebra_evpn_acc_bd_svi_mac_add(struct interface *vlan_if);
 extern void zebra_evpn_es_bypass_update(struct zebra_evpn_es *es,
                                        struct interface *ifp, bool bypass);
+extern void zebra_evpn_proc_remote_nh(ZAPI_HANDLER_ARGS);
 
 #endif /* _ZEBRA_EVPN_MH_H */
index bc2eac7a0bf53f46383155c7265cdb56dc66ff90..4cd3b60a0ffc696914945266990dfff9cabdd143 100644 (file)
@@ -149,6 +149,11 @@ static int host_rb_entry_compare(const struct host_rb_entry *hle1,
        } else if (hle1->p.family == AF_INET6) {
                return memcmp(&hle1->p.u.prefix6, &hle2->p.u.prefix6,
                              IPV6_MAX_BYTELEN);
+       } else if (hle1->p.family == AF_EVPN) {
+               /* a single dummy prefix of route_type BGP_EVPN_AD_ROUTE is
+                * used for all nexthops associated with a non-zero ESI
+                */
+               return 0;
        } else {
                zlog_debug("%s: Unexpected family type: %d", __func__,
                           hle1->p.family);