summaryrefslogtreecommitdiff
path: root/bgpd/bgp_evpn_private.h
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_evpn_private.h
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_evpn_private.h')
-rw-r--r--bgpd/bgp_evpn_private.h125
1 files changed, 84 insertions, 41 deletions
diff --git a/bgpd/bgp_evpn_private.h b/bgpd/bgp_evpn_private.h
index 839785d3a0..4ac626e4cb 100644
--- a/bgpd/bgp_evpn_private.h
+++ b/bgpd/bgp_evpn_private.h
@@ -34,6 +34,20 @@
* in bits */
#define EVPN_ROUTE_PREFIXLEN (sizeof(struct evpn_addr) * 8)
+/* EVPN route RD buffer length */
+#define BGP_EVPN_PREFIX_RD_LEN 100
+
+/* packet sizes for EVPN routes */
+/* Type-1 route should be 25 bytes
+ * RD (8), ESI (10), eth-tag (4), vni (3)
+ */
+#define BGP_EVPN_TYPE1_PSIZE 25
+/* Type-4 route should be either 23 or 35 bytes
+ * RD (8), ESI (10), ip-len (1), ip (4 or 16)
+ */
+#define BGP_EVPN_TYPE4_V4_PSIZE 23
+#define BGP_EVPN_TYPE4_V6_PSIZE 34
+
/* EVPN route types. */
typedef enum {
BGP_EVPN_AD_ROUTE = 1, /* Ethernet Auto-Discovery (A-D) route */
@@ -43,6 +57,9 @@ typedef enum {
BGP_EVPN_IP_PREFIX_ROUTE, /* IP Prefix route */
} bgp_evpn_route_type;
+RB_HEAD(bgp_es_evi_rb_head, bgp_evpn_es_evi);
+RB_PROTOTYPE(bgp_es_evi_rb_head, bgp_evpn_es_evi, rb_node,
+ bgp_es_evi_rb_cmp);
/*
* Hash table of EVIs. Right now, the only type of EVI supported is with
* VxLAN encapsulation, hence each EVI corresponds to a L2 VNI.
@@ -98,46 +115,16 @@ struct bgpevpn {
* this VNI. */
struct bgp_table *route_table;
- QOBJ_FIELDS
-};
-
-DECLARE_QOBJ_TYPE(bgpevpn)
-
-struct evpnes {
-
- /* Ethernet Segment Identifier */
- esi_t esi;
-
- /* es flags */
- uint16_t flags;
-#define EVPNES_LOCAL 0x01
-#define EVPNES_REMOTE 0x02
-
- /*
- * Id for deriving the RD
- * automatically for this ESI
- */
- uint16_t rd_id;
-
- /* RD for this VNI. */
- struct prefix_rd prd;
+ /* RB tree of ES-EVIs */
+ struct bgp_es_evi_rb_head es_evi_rb_tree;
- /* originator ip address */
- struct ipaddr originator_ip;
-
- /* list of VTEPs in the same site */
- struct list *vtep_list;
-
- /*
- * Route table for EVPN routes for
- * this ESI. - type4 routes
- */
- struct bgp_table *route_table;
+ /* List of local ESs */
+ struct list *local_es_evi_list;
QOBJ_FIELDS
};
-DECLARE_QOBJ_TYPE(evpnes)
+DECLARE_QOBJ_TYPE(bgpevpn)
/* Mapping of Import RT to VNIs.
* The Import RTs of all VNIs are maintained in a hash table with each
@@ -330,6 +317,16 @@ static inline void encode_es_rt_extcomm(struct ecommunity_val *eval,
memcpy(&eval->val[2], mac, ETH_ALEN);
}
+static inline void encode_esi_label_extcomm(struct ecommunity_val *eval,
+ bool single_active)
+{
+ memset(eval, 0, sizeof(struct ecommunity_val));
+ eval->val[0] = ECOMMUNITY_ENCODE_EVPN;
+ eval->val[1] = ECOMMUNITY_EVPN_SUBTYPE_ESI_LABEL;
+ if (single_active)
+ eval->val[2] |= (1 << 0);
+}
+
static inline void encode_rmac_extcomm(struct ecommunity_val *eval,
struct ethaddr *rmac)
{
@@ -487,6 +484,47 @@ static inline void build_evpn_type4_prefix(struct prefix_evpn *p,
memcpy(&p->prefix.es_addr.esi, esi, sizeof(esi_t));
}
+static inline void build_evpn_type1_prefix(struct prefix_evpn *p,
+ uint32_t eth_tag,
+ esi_t *esi,
+ struct in_addr originator_ip)
+{
+ memset(p, 0, sizeof(struct prefix_evpn));
+ p->family = AF_EVPN;
+ p->prefixlen = EVPN_ROUTE_PREFIXLEN;
+ p->prefix.route_type = BGP_EVPN_AD_ROUTE;
+ p->prefix.ead_addr.eth_tag = eth_tag;
+ p->prefix.ead_addr.ip_prefix_length = IPV4_MAX_BITLEN;
+ p->prefix.ead_addr.ip.ipa_type = IPADDR_V4;
+ p->prefix.ead_addr.ip.ipaddr_v4 = originator_ip;
+ memcpy(&p->prefix.ead_addr.esi, esi, sizeof(esi_t));
+}
+
+static inline void evpn_type1_prefix_global_copy(struct prefix_evpn *global_p,
+ const struct prefix_evpn *vni_p)
+{
+ memcpy(global_p, vni_p, sizeof(*global_p));
+ global_p->prefix.ead_addr.ip_prefix_length = 0;
+ global_p->prefix.ead_addr.ip.ipa_type = 0;
+ global_p->prefix.ead_addr.ip.ipaddr_v4.s_addr = 0;
+}
+
+/* EAD prefix in the global table doesn't include the VTEP-IP so
+ * we need to create a different copy for the VNI
+ */
+static inline struct prefix_evpn *evpn_type1_prefix_vni_copy(
+ struct prefix_evpn *vni_p,
+ const struct prefix_evpn *global_p,
+ struct in_addr originator_ip)
+{
+ memcpy(vni_p, global_p, sizeof(*vni_p));
+ vni_p->prefix.ead_addr.ip_prefix_length = IPV4_MAX_BITLEN;
+ vni_p->prefix.ead_addr.ip.ipa_type = IPADDR_V4;
+ vni_p->prefix.ead_addr.ip.ipaddr_v4 = originator_ip;
+
+ return vni_p;
+}
+
static inline int evpn_default_originate_set(struct bgp *bgp, afi_t afi,
safi_t safi)
{
@@ -511,11 +549,6 @@ static inline void es_get_system_mac(esi_t *esi,
memcpy(mac, &esi->val[1], ETH_ALEN);
}
-static inline int is_es_local(struct evpnes *es)
-{
- return CHECK_FLAG(es->flags, EVPNES_LOCAL) ? 1 : 0;
-}
-
static inline bool bgp_evpn_is_svi_macip_enabled(struct bgpevpn *vpn)
{
struct bgp *bgp_evpn = NULL;
@@ -526,6 +559,8 @@ static inline bool bgp_evpn_is_svi_macip_enabled(struct bgpevpn *vpn)
vpn->advertise_svi_macip);
}
+extern struct zclient *zclient;
+
extern void bgp_evpn_install_uninstall_default_route(struct bgp *bgp_vrf,
afi_t afi, safi_t safi,
bool add);
@@ -563,10 +598,18 @@ extern struct bgpevpn *bgp_evpn_new(struct bgp *bgp, vni_t vni,
vrf_id_t tenant_vrf_id,
struct in_addr mcast_grp);
extern void bgp_evpn_free(struct bgp *bgp, struct bgpevpn *vpn);
-extern struct evpnes *bgp_evpn_lookup_es(struct bgp *bgp, esi_t *esi);
extern bool bgp_evpn_lookup_l3vni_l2vni_table(vni_t vni);
extern int update_routes_for_vni(struct bgp *bgp, struct bgpevpn *vpn);
extern void delete_evpn_route_entry(struct bgp *bgp, afi_t afi, safi_t safi,
struct bgp_dest *dest,
struct bgp_path_info **pi);
+int vni_list_cmp(void *p1, void *p2);
+extern int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn,
+ struct bgp_node *rn);
+extern struct bgp_node *bgp_global_evpn_node_get(
+ struct bgp_table *table, afi_t afi, safi_t safi,
+ const struct prefix_evpn *evp, struct prefix_rd *prd);
+extern struct bgp_node *bgp_global_evpn_node_lookup(
+ struct bgp_table *table, afi_t afi, safi_t safi,
+ const struct prefix_evpn *evp, struct prefix_rd *prd);
#endif /* _BGP_EVPN_PRIVATE_H */