From 684a7227bd8811b3e222e7d533924e5bc21727e6 Mon Sep 17 00:00:00 2001 From: Philippe Guibert Date: Mon, 5 Sep 2016 14:07:01 +0200 Subject: [PATCH] bgpd: route type 5 internal structures plus processing The commit introduces the changes to be done to carry route type 5 EVPN information in bgp extra attribute information. The commit also handles the update processing for route type 5 information, including ESI, gatewayIP and label information. Signed-off-by: Philippe Guibert --- bgpd/bgp_attr.c | 15 +++++++- bgpd/bgp_attr.h | 11 ++++++ bgpd/bgp_route.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++-- bgpd/bgp_route.h | 4 +++ 4 files changed, 116 insertions(+), 4 deletions(-) diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c index 7dc42e719f..a0e8d5499b 100644 --- a/bgpd/bgp_attr.c +++ b/bgpd/bgp_attr.c @@ -419,6 +419,18 @@ encap_finish (void) #endif } +static bool +overlay_index_same(const struct attr_extra *ae1, const struct attr_extra *ae2) +{ + if(!ae1 && ae2) + return false; + if(!ae2 && ae1) + return false; + if(!ae1 && !ae2) + return false; + return !memcmp(&(ae1->evpn_overlay), &(ae2->evpn_overlay), sizeof(struct overlay_index)); +} + /* Unknown transit attribute. */ static struct hash *transit_hash; @@ -730,7 +742,8 @@ attrhash_cmp (const void *p1, const void *p2) #if ENABLE_BGP_VNC && encap_same(ae1->vnc_subtlvs, ae2->vnc_subtlvs) #endif - && IPV4_ADDR_SAME (&ae1->originator_id, &ae2->originator_id)) + && IPV4_ADDR_SAME (&ae1->originator_id, &ae2->originator_id) + && overlay_index_same(ae1, ae2)) return 1; else if (ae1 || ae2) return 0; diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h index c5799ccd0d..3ccf65029c 100644 --- a/bgpd/bgp_attr.h +++ b/bgpd/bgp_attr.h @@ -21,6 +21,8 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #ifndef _QUAGGA_BGP_ATTR_H #define _QUAGGA_BGP_ATTR_H +#include "bgp_attr_evpn.h" + /* Simple bit mapping. */ #define BITMAP_NBBY 8 @@ -80,6 +82,13 @@ struct bgp_tea_options { #endif +/* Overlay Index Info */ +struct overlay_index +{ + struct eth_segment_id eth_s_id; + union gw_addr gw_ip; +}; + /* Additional/uncommon BGP attributes. * lazily allocated as and when a struct attr * requires it. @@ -131,6 +140,8 @@ struct attr_extra #if ENABLE_BGP_VNC struct bgp_attr_encap_subtlv *vnc_subtlvs; /* VNC-specific */ #endif + /* EVPN */ + struct overlay_index evpn_overlay; }; /* BGP core attribute structure. */ diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index df2c3d8e73..f80c24dcba 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -68,6 +68,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "bgpd/rfapi/vnc_import_bgp.h" #include "bgpd/rfapi/vnc_export_bgp.h" #endif +#include "bgpd/bgp_evpn.h" /* Extern from bgp_dump.c */ extern const char *bgp_origin_str[]; @@ -2270,6 +2271,68 @@ info_make (int type, int sub_type, u_short instance, struct peer *peer, struct a return new; } +static void +overlay_index_update(struct attr *attr, struct eth_segment_id *eth_s_id, union gw_addr *gw_ip) +{ + struct attr_extra *extra; + + if(!attr) + return; + extra = bgp_attr_extra_get(attr); + + if(eth_s_id == NULL) + { + memset(&(extra->evpn_overlay.eth_s_id),0, sizeof(struct eth_segment_id)); + } + else + { + memcpy(&(extra->evpn_overlay.eth_s_id), eth_s_id, sizeof(struct eth_segment_id)); + } + if(gw_ip == NULL) + { + memset(&(extra->evpn_overlay.gw_ip), 0, sizeof(union gw_addr)); + } + else + { + memcpy(&(extra->evpn_overlay.gw_ip),gw_ip, sizeof(union gw_addr)); + } +} + +static bool +overlay_index_equal(afi_t afi, struct bgp_info *info, struct eth_segment_id *eth_s_id, union gw_addr *gw_ip) +{ + struct eth_segment_id *info_eth_s_id, *info_eth_s_id_remote; + union gw_addr *info_gw_ip, *info_gw_ip_remote; + char temp[16]; + + if(afi != AFI_L2VPN) + return true; + if (!info->attr || !info->attr->extra) + { + memset(&temp, 0, 16); + info_eth_s_id = (struct eth_segment_id *)&temp; + info_gw_ip = (union gw_addr *)&temp; + if(eth_s_id == NULL && gw_ip == NULL) + return true; + } + else + { + info_eth_s_id = &(info->attr->extra->evpn_overlay.eth_s_id); + info_gw_ip = &(info->attr->extra->evpn_overlay.gw_ip); + } + if(gw_ip == NULL) + info_gw_ip_remote = (union gw_addr *)&temp; + else + info_gw_ip_remote = gw_ip; + if(eth_s_id == NULL) + info_eth_s_id_remote = (struct eth_segment_id *)&temp; + else + info_eth_s_id_remote = eth_s_id; + if(!memcmp(info_gw_ip, info_gw_ip_remote, sizeof(union gw_addr))) + return false; + return !memcmp(info_eth_s_id, info_eth_s_id_remote, sizeof(struct eth_segment_id)); +} + /* Check if received nexthop is valid or not. */ static int bgp_update_martian_nexthop (struct bgp *bgp, afi_t afi, safi_t safi, struct attr *attr) @@ -2448,7 +2511,9 @@ bgp_update (struct peer *peer, struct prefix *p, u_int32_t addpath_id, /* Same attribute comes in. */ if (!CHECK_FLAG (ri->flags, BGP_INFO_REMOVED) - && attrhash_cmp (ri->attr, attr_new)) + && attrhash_cmp (ri->attr, attr_new) + && (overlay_index_equal(afi, ri, evpn==NULL?NULL:&evpn->eth_s_id, + evpn==NULL?NULL:&evpn->gw_ip))) { if (CHECK_FLAG (bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING) && peer->sort == BGP_PEER_EBGP @@ -2568,7 +2633,7 @@ bgp_update (struct peer *peer, struct prefix *p, u_int32_t addpath_id, ri->attr = attr_new; /* Update MPLS tag. */ - if (safi == SAFI_MPLS_VPN) + if (safi == SAFI_MPLS_VPN || safi == SAFI_EVPN) memcpy ((bgp_info_extra_get (ri))->tag, tag, 3); #if ENABLE_BGP_VNC @@ -2589,6 +2654,12 @@ bgp_update (struct peer *peer, struct prefix *p, u_int32_t addpath_id, } } #endif + /* Update Overlay Index */ + if(afi == AFI_L2VPN) + { + overlay_index_update(ri->attr, evpn==NULL?NULL:&evpn->eth_s_id, + evpn==NULL?NULL:&evpn->gw_ip); + } /* Update bgp route dampening information. */ if (CHECK_FLAG (bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING) @@ -2693,9 +2764,15 @@ bgp_update (struct peer *peer, struct prefix *p, u_int32_t addpath_id, new = info_make(type, sub_type, 0, peer, attr_new, rn); /* Update MPLS tag. */ - if (safi == SAFI_MPLS_VPN) + if (safi == SAFI_MPLS_VPN || safi == SAFI_EVPN) memcpy ((bgp_info_extra_get (new))->tag, tag, 3); + /* Update Overlay Index */ + if(afi == AFI_L2VPN) + { + overlay_index_update(new->attr, evpn==NULL?NULL:&evpn->eth_s_id, + evpn==NULL?NULL:&evpn->gw_ip); + } /* Nexthop reachability check. */ if ((afi == AFI_IP || afi == AFI_IP6) && safi == SAFI_UNICAST) { @@ -3616,6 +3693,8 @@ bgp_static_free (struct bgp_static *bgp_static) { if (bgp_static->rmap.name) XFREE(MTYPE_ROUTE_MAP_NAME, bgp_static->rmap.name); + if(bgp_static->eth_s_id) + XFREE(MTYPE_ATTR, bgp_static->eth_s_id); XFREE (MTYPE_BGP_STATIC, bgp_static); } @@ -3922,6 +4001,8 @@ bgp_static_update_safi (struct bgp *bgp, struct prefix *p, attr.med = bgp_static->igpmetric; attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC); + if(afi == AFI_L2VPN) + overlay_index_update(&attr, bgp_static->eth_s_id, NULL); /* Apply route-map. */ if (bgp_static->rmap.name) { @@ -3965,7 +4046,10 @@ bgp_static_update_safi (struct bgp *bgp, struct prefix *p, if (ri) { + union gw_addr add; + memset(&add, 0, sizeof(union gw_addr)); if (attrhash_cmp (ri->attr, attr_new) && + overlay_index_equal(afi, ri, bgp_static->eth_s_id, &add) && !CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)) { bgp_unlock_node (rn); diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h index 4a24b0f376..243c5afb00 100644 --- a/bgpd/bgp_route.h +++ b/bgpd/bgp_route.h @@ -203,6 +203,10 @@ struct bgp_static /* MPLS label. */ u_char tag[3]; + + /* EVPN */ + struct eth_segment_id *eth_s_id; + char *router_mac; }; #define BGP_NEXTHOP_AFI_FROM_NHLEN(nhlen) \ -- 2.39.5