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.
Signed-off-by: Philippe Guibert <philippe.guib...@6wind.com> --- bgpd/bgp_attr.c | 16 ++++- bgpd/bgp_attr.h | 14 +++++ bgpd/bgp_route.c | 173 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- bgpd/bgp_route.h | 5 ++ 4 files changed, 205 insertions(+), 3 deletions(-) diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c index 8741c4af3441..c7564ae49fb8 100644 --- a/bgpd/bgp_attr.c +++ b/bgpd/bgp_attr.c @@ -311,6 +311,18 @@ encap_same(struct bgp_attr_encap_subtlv *h1, struct bgp_attr_encap_subtlv *h2) return 1; } +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; @@ -551,7 +563,9 @@ attrhash_cmp (const void *p1, const void *p2) && ae1->transit == ae2->transit && (ae1->encap_tunneltype == ae2->encap_tunneltype) && encap_same(ae1->encap_subtlvs, ae2->encap_subtlvs) - && IPV4_ADDR_SAME (&ae1->originator_id, &ae2->originator_id)) + && IPV4_ADDR_SAME (&ae1->originator_id, &ae2->originator_id) + && ae1->eth_t_id == ae2->eth_t_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 3bd7aface174..64a7464177df 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 @@ -54,6 +56,13 @@ struct bgp_attr_encap_subtlv { uint8_t value[1]; /* will be extended */ }; +/* 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. @@ -95,6 +104,11 @@ struct attr_extra /* route tag */ route_tag_t tag; + + /* EVPN */ + uint32_t eth_t_id; + struct overlay_index evpn_overlay; + short use_gw; }; /* BGP core attribute structure. */ diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 32577c299f6a..3c8ebcab8676 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -57,6 +57,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA #include "bgpd/bgp_vty.h" #include "bgpd/bgp_mpath.h" #include "bgpd/bgp_nht.h" +#include "bgpd/bgp_evpn.h" /* Extern from bgp_dump.c */ extern const char *bgp_origin_str[]; @@ -2526,6 +2527,86 @@ info_make (int type, int sub_type, struct peer *peer, struct attr *attr, 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 +eth_tag_id_equal(afi_t afi, struct bgp_info *info, uint32_t *eth_t_id) +{ + uint32_t local_eth_t_id; + + if(afi != AFI_INTERNAL_L2VPN) + return true; + if (!info->attr || !info->attr->extra) { + local_eth_t_id = 0; + if(eth_t_id == NULL) + return true; + } else { + local_eth_t_id = info->attr->extra->eth_t_id; + } + if(eth_t_id && (local_eth_t_id == *eth_t_id)) + return true; + if (local_eth_t_id == 0) + return true; + return false; +} + +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_INTERNAL_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)); +} + static bool labels_equal(struct bgp_info *info, uint32_t *labels, size_t nlabels) { @@ -2640,7 +2721,11 @@ bgp_update_rsclient (struct peer *rsclient, afi_t afi, safi_t safi, /* Same attribute comes in. */ if (!CHECK_FLAG(ri->flags, BGP_INFO_REMOVED) && attrhash_cmp (ri->attr, attr_new) - && labels_equal (ri, labels, nlabels)) + && labels_equal (ri, labels, nlabels) + && eth_tag_id_equal(afi, ri, evpn==NULL?NULL:&evpn->eth_t_id) + && (overlay_index_equal(afi, ri, + evpn==NULL?NULL:&evpn->eth_s_id, + evpn==NULL?NULL:&evpn->gw_ip))) { @@ -2684,6 +2769,19 @@ bgp_update_rsclient (struct peer *rsclient, afi_t afi, safi_t safi, else if (ri->extra) ri->extra->nlabels = 0; + /* Update Overlay Index */ + if(afi == AFI_INTERNAL_L2VPN) + { + overlay_index_update(ri->attr, evpn==NULL?NULL:&evpn->eth_s_id, + evpn==NULL?NULL:&evpn->gw_ip); + if(ri->attr && ri->attr->extra) + { + if(evpn && evpn->eth_t_id) + ri->attr->extra->eth_t_id = evpn->eth_t_id; + else + ri->attr->extra->eth_t_id = 0; + } + } bgp_info_set_flag (rn, ri, BGP_INFO_VALID); /* Process change. */ @@ -2713,6 +2811,19 @@ bgp_update_rsclient (struct peer *rsclient, afi_t afi, safi_t safi, memcpy (ri->extra->labels, labels, sizeof(*labels) * nlabels); } + /* Update Overlay Index */ + if(afi == AFI_INTERNAL_L2VPN) + { + overlay_index_update(new->attr, evpn==NULL?NULL:&evpn->eth_s_id, + evpn==NULL?NULL:&evpn->gw_ip); + if(new->attr && new->attr->extra) + { + if(evpn && evpn->eth_t_id) + new->attr->extra->eth_t_id = evpn->eth_t_id; + else + new->attr->extra->eth_t_id = 0; + } + } bgp_info_set_flag (rn, new, BGP_INFO_VALID); /* Register new BGP information. */ @@ -2897,7 +3008,10 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr, /* Same attribute comes in. */ if (!CHECK_FLAG (ri->flags, BGP_INFO_REMOVED) && attrhash_cmp (ri->attr, attr_new) - && labels_equal (ri, labels, nlabels)) + && labels_equal (ri, labels, nlabels) + && eth_tag_id_equal(afi, ri, evpn==NULL?0:&evpn->eth_t_id) + && (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 @@ -2992,6 +3106,19 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr, else if (ri->extra) ri->extra->nlabels = 0; + /* Update Overlay Index */ + if(afi == AFI_INTERNAL_L2VPN) + { + overlay_index_update(ri->attr, evpn==NULL?NULL:&evpn->eth_s_id, + evpn==NULL?NULL:&evpn->gw_ip); + if(ri->attr && ri->attr->extra) + { + if(evpn && evpn->eth_t_id) + ri->attr->extra->eth_t_id = evpn->eth_t_id; + else + ri->attr->extra->eth_t_id = 0; + } + } bgp_attr_flush (&new_attr); /* Update bgp route dampening information. */ @@ -3065,6 +3192,19 @@ bgp_update_main (struct peer *peer, struct prefix *p, struct attr *attr, memcpy (new->extra->labels, labels, sizeof(*labels) * nlabels); } + /* Update Overlay Index */ + if(afi == AFI_INTERNAL_L2VPN) + { + overlay_index_update(new->attr, evpn==NULL?NULL:&evpn->eth_s_id, + evpn==NULL?NULL:&evpn->gw_ip); + if(new->attr && new->attr->extra) + { + if(evpn && evpn->eth_t_id) + new->attr->extra->eth_t_id = evpn->eth_t_id; + else + new->attr->extra->eth_t_id = 0; + } + } /* Nexthop reachability check. */ if ((afi == AFI_IP || afi == AFI_IP6) && safi == SAFI_UNICAST) { @@ -4085,6 +4225,8 @@ bgp_static_free (struct bgp_static *bgp_static) { if (bgp_static->rmap.name) free (bgp_static->rmap.name); + if(bgp_static->eth_s_id) + XFREE(MTYPE_ATTR, bgp_static->eth_s_id); XFREE (MTYPE_BGP_STATIC, bgp_static); } @@ -4581,6 +4723,28 @@ bgp_static_update_safi (struct bgp *bgp, struct prefix *p, bgp_attr_extra_get (&attr)->ecommunity = ecommunity_dup (bgp_static->ecomm); attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES); } + if(afi == AFI_INTERNAL_L2VPN) + { + if (bgp_static->igpnexthop.s_addr) + { + union gw_addr add; + + memset(&add, 0, sizeof(union gw_addr)); + add.ipv4.s_addr = bgp_static->igpnexthop.s_addr; + overlay_index_update(&attr, bgp_static->eth_s_id, &add); + } + else + { + overlay_index_update(&attr, bgp_static->eth_s_id, NULL); + } + if((&attr)->extra) + (&attr)->extra->eth_t_id = bgp_static->eth_t_id; + } + if (bgp_static->igpnexthop.s_addr) + { + bgp_attr_extra_get (&attr)->mp_nexthop_global_in = bgp_static->igpnexthop; + bgp_attr_extra_get (&attr)->mp_nexthop_len = IPV4_MAX_BYTELEN; + } /* Apply route-map. */ if (bgp_static->rmap.name) { @@ -4624,7 +4788,12 @@ bgp_static_update_safi (struct bgp *bgp, struct prefix *p, if (ri) { + union gw_addr add; + memset(&add, 0, sizeof(union gw_addr)); + add.ipv4.s_addr = bgp_static->igpnexthop.s_addr; if (attrhash_cmp (ri->attr, attr_new) && + eth_tag_id_equal(afi, ri, &bgp_static->eth_t_id) && + 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 5047b5c48b18..4301088fed3d 100644 --- a/bgpd/bgp_route.h +++ b/bgpd/bgp_route.h @@ -149,6 +149,11 @@ struct bgp_static /* MPLS label. */ uint32_t labels[BGP_MAX_LABELS]; size_t nlabels; + + /* EVPN */ + uint32_t eth_t_id; + struct eth_segment_id *eth_s_id; + char *router_mac; }; #define BGP_INFO_COUNTABLE(BI) \ -- 2.1.4 _______________________________________________ Quagga-dev mailing list Quagga-dev@lists.quagga.net https://lists.quagga.net/mailman/listinfo/quagga-dev