diff options
| author | Anuradha Karuppiah <anuradhak@cumulusnetworks.com> | 2020-03-27 14:43:50 -0700 |
|---|---|---|
| committer | Anuradha Karuppiah <anuradhak@cumulusnetworks.com> | 2020-08-05 06:46:12 -0700 |
| commit | c44ab6f1f3016fe1d595067dfa95b917e25519e9 (patch) | |
| tree | 34b3bf60f88ea74b761c0ff8b201d4f89dca6de2 /bgpd/bgp_zebra.c | |
| parent | 0a50c248132f3eec45c3e46ad1cf0dac1cb72e91 (diff) | |
bgpd: support for Ethernet Segments and Type-1/EAD routes
This is the base patch that brings in support for Type-1 routes.
It includes support for -
- Ethernet Segment (ES) management
- EAD route handling
- MAC-IP (Type-2) routes with a non-zero ESI i.e. Aliasing for
active-active multihoming
- Initial infra for consistency checking. Consistency checking
is a fundamental feature for active-active solutions like MLAG.
We will try to levarage the info in the EAD-ES/EAD-EVI routes to
detect inconsitencies in access config across VTEPs attached to
the same Ethernet Segment.
Functionality Overview -
========================
1. Ethernet segments are created in zebra and associated with
access VLANs. zebra sends that info as ES and ES-EVI objects to BGP.
2. BGP advertises EAD-ES and EAD-EVI routes for the locally attached
ethernet segments.
3. Similarly BGP processes EAD-ES and EAD-EVI routes from peers
and translates them into ES-VTEP objects which are then sent to zebra
as remote ESs.
4. Each ES in zebra is associated with a list of active VTEPs which
is then translated into a L2-NHG (nexthop group). This is the ES
"Alias" entry
5. MAC-IP routes with a non-zero ESI use the alias entry created in
(4.) to forward traffic i.e. a MAC-ECMP is done to these remote-ES
destinations.
EAD route management (route table and key) -
============================================
1. Local EAD-ES routes
a. route-table: per-ES route-table
key: {RD=ES-RD, ESI, ET=0xffffffff, VTEP-IP)
b. route-table: per-VNI route-table
Not added
c. route-table: global route-table
key: {RD=ES-RD, ESI, ET=0xffffffff)
2. Remote EAD-ES routes
a. route-table: per-ES route-table
Not added
b. route-table: per-VNI route-table
key: {RD=ES-RD, ESI, ET=0xffffffff, VTEP-IP)
c. route-table: global route-table
key: {RD=ES-RD, ESI, ET=0xffffffff)
3. Local EAD-EVI routes
a. route-table: per-ES route-table
Not added
b. route-table: per-VNI route-table
key: {RD=0, ESI, ET=0, VTEP-IP)
c. route-table: global route-table
key: {RD=L2-VNI-RD, ESI, ET=0)
4. Remote EAD-EVI routes
a. route-table: per-ES route-table
Not added
b. route-table: per-VNI route-table
key: {RD=0, ESI, ET=0, VTEP-IP)
c. route-table: global route-table
key: {RD=L2-VNI-RD, ESI, ET=0)
Please refer to bgp_evpn_mh.h for info on how the data-structures are
organized.
Signed-off-by: Anuradha Karuppiah <anuradhak@cumulusnetworks.com>
Diffstat (limited to 'bgpd/bgp_zebra.c')
| -rw-r--r-- | bgpd/bgp_zebra.c | 90 |
1 files changed, 72 insertions, 18 deletions
diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 80645b0310..87936f1dd6 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -56,11 +56,11 @@ #include "bgpd/rfapi/vnc_export_bgp.h" #endif #include "bgpd/bgp_evpn.h" -#include "bgpd/bgp_evpn_mh.h" #include "bgpd/bgp_mplsvpn.h" #include "bgpd/bgp_labelpool.h" #include "bgpd/bgp_pbr.h" #include "bgpd/bgp_evpn_private.h" +#include "bgpd/bgp_evpn_mh.h" #include "bgpd/bgp_mac.h" /* All information about zebra. */ @@ -2499,17 +2499,66 @@ static void bgp_zebra_connected(struct zclient *zclient) BGP_GR_ROUTER_DETECT_AND_SEND_CAPABILITY_TO_ZEBRA(bgp, bgp->peer); } -static int bgp_zebra_process_local_es(ZAPI_CALLBACK_ARGS) +static int bgp_zebra_process_local_es_add(ZAPI_CALLBACK_ARGS) +{ + esi_t esi; + struct bgp *bgp = NULL; + struct stream *s = NULL; + char buf[ESI_STR_LEN]; + struct in_addr originator_ip; + uint8_t active; + + bgp = bgp_lookup_by_vrf_id(vrf_id); + if (!bgp) + return 0; + + s = zclient->ibuf; + stream_get(&esi, s, sizeof(esi_t)); + originator_ip.s_addr = stream_get_ipv4(s); + active = stream_getc(s); + + if (BGP_DEBUG(zebra, ZEBRA)) + zlog_debug("Rx add ESI %s originator-ip %s active %u", + esi_to_str(&esi, buf, sizeof(buf)), + inet_ntoa(originator_ip), + active); + + bgp_evpn_local_es_add(bgp, &esi, originator_ip, active); + + return 0; +} + +static int bgp_zebra_process_local_es_del(ZAPI_CALLBACK_ARGS) { esi_t esi; struct bgp *bgp = NULL; struct stream *s = NULL; char buf[ESI_STR_LEN]; - char buf1[INET6_ADDRSTRLEN]; - struct ipaddr originator_ip; memset(&esi, 0, sizeof(esi_t)); - memset(&originator_ip, 0, sizeof(struct ipaddr)); + bgp = bgp_lookup_by_vrf_id(vrf_id); + if (!bgp) + return 0; + + s = zclient->ibuf; + stream_get(&esi, s, sizeof(esi_t)); + + if (BGP_DEBUG(zebra, ZEBRA)) + zlog_debug("Rx del ESI %s", + esi_to_str(&esi, buf, sizeof(buf))); + + bgp_evpn_local_es_del(bgp, &esi); + + return 0; +} + +static int bgp_zebra_process_local_es_evi(ZAPI_CALLBACK_ARGS) +{ + esi_t esi; + vni_t vni; + struct bgp *bgp; + struct stream *s; + char buf[ESI_STR_LEN]; bgp = bgp_lookup_by_vrf_id(vrf_id); if (!bgp) @@ -2517,18 +2566,18 @@ static int bgp_zebra_process_local_es(ZAPI_CALLBACK_ARGS) s = zclient->ibuf; stream_get(&esi, s, sizeof(esi_t)); - stream_get(&originator_ip, s, sizeof(struct ipaddr)); + vni = stream_getl(s); if (BGP_DEBUG(zebra, ZEBRA)) - zlog_debug("Rx %s ESI %s originator-ip %s", - (cmd == ZEBRA_LOCAL_ES_ADD) ? "add" : "del", - esi_to_str(&esi, buf, sizeof(buf)), - ipaddr2str(&originator_ip, buf1, sizeof(buf1))); + zlog_debug("Rx %s ESI %s VNI %u", + ZEBRA_VNI_ADD ? "add" : "del", + esi_to_str(&esi, buf, sizeof(buf)), vni); - if (cmd == ZEBRA_LOCAL_ES_ADD) - bgp_evpn_local_es_add(bgp, &esi, &originator_ip); + if (cmd == ZEBRA_LOCAL_ES_EVI_ADD) + bgp_evpn_local_es_evi_add(bgp, &esi, vni); else - bgp_evpn_local_es_del(bgp, &esi, &originator_ip); + bgp_evpn_local_es_evi_del(bgp, &esi, vni); + return 0; } @@ -2628,6 +2677,8 @@ static int bgp_zebra_process_local_macip(ZAPI_CALLBACK_ARGS) uint8_t flags = 0; uint32_t seqnum = 0; int state = 0; + char buf2[ESI_STR_LEN]; + esi_t esi; memset(&ip, 0, sizeof(ip)); s = zclient->ibuf; @@ -2651,6 +2702,7 @@ static int bgp_zebra_process_local_macip(ZAPI_CALLBACK_ARGS) if (cmd == ZEBRA_MACIP_ADD) { flags = stream_getc(s); seqnum = stream_getl(s); + stream_get(&esi, s, sizeof(esi_t)); } else { state = stream_getl(s); } @@ -2660,15 +2712,15 @@ static int bgp_zebra_process_local_macip(ZAPI_CALLBACK_ARGS) return 0; if (BGP_DEBUG(zebra, ZEBRA)) - zlog_debug("%u:Recv MACIP %s flags 0x%x MAC %s IP %s VNI %u seq %u state %d", + zlog_debug("%u:Recv MACIP %s f 0x%x MAC %s IP %s VNI %u seq %u state %d ESI %s", vrf_id, (cmd == ZEBRA_MACIP_ADD) ? "Add" : "Del", flags, prefix_mac2str(&mac, buf, sizeof(buf)), ipaddr2str(&ip, buf1, sizeof(buf1)), vni, seqnum, - state); + state, esi_to_str(&esi, buf2, sizeof(buf2))); if (cmd == ZEBRA_MACIP_ADD) return bgp_evpn_local_macip_add(bgp, vni, &mac, &ip, - flags, seqnum); + flags, seqnum, &esi); else return bgp_evpn_local_macip_del(bgp, vni, &mac, &ip, state); } @@ -2801,9 +2853,11 @@ void bgp_zebra_init(struct thread_master *master, unsigned short instance) zclient->nexthop_update = bgp_read_nexthop_update; zclient->import_check_update = bgp_read_import_check_update; zclient->fec_update = bgp_read_fec_update; - zclient->local_es_add = bgp_zebra_process_local_es; - zclient->local_es_del = bgp_zebra_process_local_es; + zclient->local_es_add = bgp_zebra_process_local_es_add; + zclient->local_es_del = bgp_zebra_process_local_es_del; zclient->local_vni_add = bgp_zebra_process_local_vni; + zclient->local_es_evi_add = bgp_zebra_process_local_es_evi; + zclient->local_es_evi_del = bgp_zebra_process_local_es_evi; zclient->local_vni_del = bgp_zebra_process_local_vni; zclient->local_macip_add = bgp_zebra_process_local_macip; zclient->local_macip_del = bgp_zebra_process_local_macip; |
