summaryrefslogtreecommitdiff
path: root/bgpd/bgp_zebra.c
diff options
context:
space:
mode:
authorAnuradha Karuppiah <anuradhak@cumulusnetworks.com>2020-03-27 14:43:50 -0700
committerAnuradha Karuppiah <anuradhak@cumulusnetworks.com>2020-08-05 06:46:12 -0700
commitc44ab6f1f3016fe1d595067dfa95b917e25519e9 (patch)
tree34b3bf60f88ea74b761c0ff8b201d4f89dca6de2 /bgpd/bgp_zebra.c
parent0a50c248132f3eec45c3e46ad1cf0dac1cb72e91 (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.c90
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;