From 3d6c0dfa8782065252aef2397e313ac1979bb7b0 Mon Sep 17 00:00:00 2001 From: Philippe Guibert Date: Mon, 5 Sep 2016 10:53:51 +0200 Subject: [PATCH] bgpd: basic support for EVPN To handle BGP NLRI EVPN messages, bgp is modified to handle AFI_L2VPN and SAFI_EVPN values. Signed-off-by: Philippe Guibert --- bgpd/bgp_open.c | 15 +++++- bgpd/bgp_packet.c | 4 +- bgpd/bgp_route.c | 111 +++++++++++++++++++++++++----------------- bgpd/bgp_updgrp_adv.c | 4 +- bgpd/bgp_vty.c | 4 ++ bgpd/bgpd.c | 11 ++++- 6 files changed, 99 insertions(+), 50 deletions(-) diff --git a/bgpd/bgp_open.c b/bgpd/bgp_open.c index 7dbb439be1..51079f31e0 100644 --- a/bgpd/bgp_open.c +++ b/bgpd/bgp_open.c @@ -93,6 +93,9 @@ bgp_capability_vty_out (struct vty *vty, struct peer *peer, u_char use_json, jso case AFI_IP6: json_object_string_add(json_cap, "capabilityErrorMultiProtocolAfi", "IPv6"); break; + case AFI_L2VPN: + json_object_string_add(json_cap, "capabilityErrorMultiProtocolAfi", "L2VPN"); + break; default: json_object_int_add(json_cap, "capabilityErrorMultiProtocolAfiUnknown", ntohs (mpc.afi)); break; @@ -111,6 +114,9 @@ bgp_capability_vty_out (struct vty *vty, struct peer *peer, u_char use_json, jso case SAFI_ENCAP: json_object_string_add(json_cap, "capabilityErrorMultiProtocolSafi", "encap"); break; + case SAFI_EVPN: + json_object_string_add(json_cap, "capabilityErrorMultiProtocolSafi", "EVPN"); + break; default: json_object_int_add(json_cap, "capabilityErrorMultiProtocolSafiUnknown", mpc.safi); break; @@ -127,6 +133,9 @@ bgp_capability_vty_out (struct vty *vty, struct peer *peer, u_char use_json, jso case AFI_IP6: vty_out (vty, "AFI IPv6, "); break; + case AFI_L2VPN: + vty_out (vty, "AFI L2VPN, "); + break; default: vty_out (vty, "AFI Unknown %d, ", ntohs (mpc.afi)); break; @@ -145,6 +154,9 @@ bgp_capability_vty_out (struct vty *vty, struct peer *peer, u_char use_json, jso case SAFI_ENCAP: vty_out (vty, "SAFI ENCAP"); break; + case SAFI_EVPN: + vty_out (vty, "SAFI EVPN"); + break; default: vty_out (vty, "SAFI Unknown %d ", mpc.safi); break; @@ -1136,7 +1148,8 @@ bgp_open_option_parse (struct peer *peer, u_char length, int *mp_capability) && ! peer->afc_nego[AFI_IP6][SAFI_UNICAST] && ! peer->afc_nego[AFI_IP6][SAFI_MULTICAST] && ! peer->afc_nego[AFI_IP6][SAFI_MPLS_VPN] - && ! peer->afc_nego[AFI_IP6][SAFI_ENCAP]) + && ! peer->afc_nego[AFI_IP6][SAFI_ENCAP] + && ! peer->afc_nego[AFI_L2VPN][SAFI_EVPN]) { zlog_err ("%s [Error] Configured AFI/SAFIs do not " "overlap with received MP capabilities", diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c index 2df22ab568..c7453509fa 100644 --- a/bgpd/bgp_packet.c +++ b/bgpd/bgp_packet.c @@ -246,13 +246,13 @@ bgp_write_packet (struct peer *peer) if (!(PAF_SUBGRP(paf))->t_coalesce && peer->afc_nego[afi][safi] && peer->synctime && ! CHECK_FLAG (peer->af_sflags[afi][safi], - PEER_STATUS_EOR_SEND)) + PEER_STATUS_EOR_SEND) + && safi != SAFI_EVPN) { SET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_EOR_SEND); return bgp_update_packet_eor (peer, afi, safi); } - } continue; } diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 0123ed17ea..84c0ee1021 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -84,7 +84,8 @@ bgp_afi_node_get (struct bgp_table *table, afi_t afi, safi_t safi, struct prefix if (!table) return NULL; - if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) + if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP) || + (safi == SAFI_EVPN)) { prn = bgp_node_get (table, (struct prefix *) prd); @@ -97,7 +98,8 @@ bgp_afi_node_get (struct bgp_table *table, afi_t afi, safi_t safi, struct prefix rn = bgp_node_get (table, p); - if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) + if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP) || + (safi == SAFI_EVPN)) rn->prn = prn; return rn; @@ -3067,7 +3069,7 @@ bgp_soft_reconfig_in (struct peer *peer, afi_t afi, safi_t safi) if (peer->status != Established) return; - if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP)) + if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP) && (safi != SAFI_EVPN)) bgp_soft_reconfig_table (peer, afi, safi, NULL, NULL); else for (rn = bgp_table_top (peer->bgp->rib[afi][safi]); rn; @@ -3288,7 +3290,7 @@ bgp_clear_route (struct peer *peer, afi_t afi, safi_t safi) if (!peer->clear_node_queue->thread) peer_lock (peer); - if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP) + if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP && safi != SAFI_EVPN) bgp_clear_route_table (peer, afi, safi, NULL); else for (rn = bgp_table_top (peer->bgp->rib[afi][safi]); rn; @@ -3421,40 +3423,56 @@ void bgp_cleanup_routes (struct bgp *bgp) { afi_t afi; + struct bgp_node *rn; for (afi = AFI_IP; afi < AFI_MAX; ++afi) { - struct bgp_node *rn; - + if (afi == AFI_L2VPN) + continue; bgp_cleanup_table(bgp->rib[afi][SAFI_UNICAST], SAFI_UNICAST); - /* - * VPN and ENCAP tables are two-level (RD is top level) + * VPN and ENCAP and EVPN tables are two-level (RD is top level) */ - for (rn = bgp_table_top(bgp->rib[afi][SAFI_MPLS_VPN]); rn; - rn = bgp_route_next (rn)) - { - if (rn->info) - { - bgp_cleanup_table((struct bgp_table *)(rn->info), SAFI_MPLS_VPN); - bgp_table_finish ((struct bgp_table **)&(rn->info)); - rn->info = NULL; - bgp_unlock_node(rn); - } - } - - for (rn = bgp_table_top(bgp->rib[afi][SAFI_ENCAP]); rn; - rn = bgp_route_next (rn)) - { - if (rn->info) - { - bgp_cleanup_table((struct bgp_table *)(rn->info), SAFI_ENCAP); - bgp_table_finish ((struct bgp_table **)&(rn->info)); - rn->info = NULL; - bgp_unlock_node(rn); - } + if (afi != AFI_L2VPN) + { + safi_t safi; + safi = SAFI_MPLS_VPN; + for (rn = bgp_table_top(bgp->rib[afi][safi]); rn; + rn = bgp_route_next (rn)) + { + if (rn->info) + { + bgp_cleanup_table((struct bgp_table *)(rn->info), safi); + bgp_table_finish ((struct bgp_table **)&(rn->info)); + rn->info = NULL; + bgp_unlock_node(rn); + } + } + safi = SAFI_ENCAP; + for (rn = bgp_table_top(bgp->rib[afi][safi]); rn; + rn = bgp_route_next (rn)) + { + if (rn->info) + { + bgp_cleanup_table((struct bgp_table *)(rn->info), safi); + bgp_table_finish ((struct bgp_table **)&(rn->info)); + rn->info = NULL; + bgp_unlock_node(rn); + } + } } } + for (rn = bgp_table_top(bgp->rib[AFI_L2VPN][SAFI_EVPN]); rn; + rn = bgp_route_next (rn)) + { + if (rn->info) + { + bgp_cleanup_table((struct bgp_table *)(rn->info), SAFI_EVPN); + bgp_table_finish ((struct bgp_table **)&(rn->info)); + rn->info = NULL; + bgp_unlock_node(rn); + } + } } void @@ -4209,7 +4227,7 @@ bgp_static_add (struct bgp *bgp) for (rn = bgp_table_top (bgp->route[afi][safi]); rn; rn = bgp_route_next (rn)) if (rn->info != NULL) { - if (safi == SAFI_MPLS_VPN) + if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP) || (safi == SAFI_EVPN)) { table = rn->info; @@ -4243,7 +4261,7 @@ bgp_static_delete (struct bgp *bgp) for (rn = bgp_table_top (bgp->route[afi][safi]); rn; rn = bgp_route_next (rn)) if (rn->info != NULL) { - if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) + if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP) || (safi == SAFI_EVPN)) { table = rn->info; @@ -5099,7 +5117,7 @@ bgp_aggregate_increment (struct bgp *bgp, struct prefix *p, struct bgp_table *table; /* MPLS-VPN aggregation is not yet supported. */ - if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) + if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP) || (safi = SAFI_EVPN)) return; table = bgp->aggregate[afi][safi]; @@ -5136,7 +5154,7 @@ bgp_aggregate_decrement (struct bgp *bgp, struct prefix *p, struct bgp_table *table; /* MPLS-VPN aggregation is not yet supported. */ - if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) + if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP) || (safi = SAFI_EVPN)) return; table = bgp->aggregate[afi][safi]; @@ -5924,7 +5942,7 @@ route_vty_out (struct vty *vty, struct prefix *p, * neccessarily the same as the prefix address family. * Both SAFI_MPLS_VPN and SAFI_ENCAP use the MP nexthop field */ - if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN)) + if ((safi == SAFI_ENCAP) || (safi == SAFI_MPLS_VPN) || (safi = SAFI_EVPN)) { if (attr->extra) { @@ -5956,7 +5974,7 @@ route_vty_out (struct vty *vty, struct prefix *p, { json_nexthop_global = json_object_new_object(); - if (safi == SAFI_MPLS_VPN) + if ((safi == SAFI_MPLS_VPN) || (safi = SAFI_EVPN)) json_object_string_add(json_nexthop_global, "ip", inet_ntoa (attr->extra->mp_nexthop_global_in)); else json_object_string_add(json_nexthop_global, "ip", inet_ntoa (attr->nexthop)); @@ -5966,7 +5984,7 @@ route_vty_out (struct vty *vty, struct prefix *p, } else { - if (safi == SAFI_MPLS_VPN) + if ((safi == SAFI_MPLS_VPN) || (safi = SAFI_EVPN)) vty_out (vty, "%-16s", inet_ntoa (attr->extra->mp_nexthop_global_in)); else @@ -6180,9 +6198,10 @@ route_vty_out_tmp (struct vty *vty, struct prefix *p, struct attr *attr, safi_t if (p->family == AF_INET && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || + safi == SAFI_EVPN || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) { - if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) + if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) json_object_string_add(json_net, "nextHop", inet_ntoa (attr->extra->mp_nexthop_global_in)); else json_object_string_add(json_net, "nextHop", inet_ntoa (attr->nexthop)); @@ -6218,9 +6237,10 @@ route_vty_out_tmp (struct vty *vty, struct prefix *p, struct attr *attr, safi_t if (p->family == AF_INET && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || + safi == SAFI_EVPN || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) { - if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) + if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) vty_out (vty, "%-16s", inet_ntoa (attr->extra->mp_nexthop_global_in)); else @@ -6307,7 +6327,7 @@ route_vty_out_tag (struct vty *vty, struct prefix *p, if (p->family == AF_INET && (safi == SAFI_MPLS_VPN || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) { - if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) + if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) { if (json) json_object_string_add(json_out, "mpNexthopGlobalIn", inet_ntoa (attr->extra->mp_nexthop_global_in)); @@ -6717,9 +6737,10 @@ route_vty_out_detail (struct vty *vty, struct bgp *bgp, struct prefix *p, if (p->family == AF_INET && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || + safi == SAFI_EVPN || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) { - if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) + if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) { if (json_paths) json_object_string_add(json_nexthop_global, "ip", inet_ntoa (attr->extra->mp_nexthop_global_in)); @@ -7657,9 +7678,9 @@ route_vty_out_detail_header (struct vty *vty, struct bgp *bgp, else { vty_out (vty, "BGP routing table entry for %s%s%s/%d%s", - ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) ? + ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) ? prefix_rd2str (prd, buf1, RD_ADDRSTRLEN) : ""), - safi == SAFI_MPLS_VPN ? ":" : "", + ((safi == SAFI_MPLS_VPN) || (safi == SAFI_EVPN)) ? ":" : "", inet_ntop (p->family, &p->u.prefix, buf2, INET6_ADDRSTRLEN), p->prefixlen, VTY_NEWLINE); } @@ -7779,7 +7800,7 @@ bgp_show_route_in_table (struct vty *vty, struct bgp *bgp, json_paths = json_object_new_array(); } - if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) + if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) { for (rn = bgp_table_top (rib); rn; rn = bgp_route_next (rn)) { @@ -10054,7 +10075,7 @@ bgp_clear_damp_route (struct vty *vty, const char *view_name, match.family = afi2family (afi); - if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) + if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP) || (safi == SAFI_EVPN)) { for (rn = bgp_table_top (bgp->rib[AFI_IP][safi]); rn; rn = bgp_route_next (rn)) { diff --git a/bgpd/bgp_updgrp_adv.c b/bgpd/bgp_updgrp_adv.c index 48f56a29b2..efb2046e12 100644 --- a/bgpd/bgp_updgrp_adv.c +++ b/bgpd/bgp_updgrp_adv.c @@ -605,6 +605,7 @@ subgroup_announce_table (struct update_subgroup *subgrp, if (safi != SAFI_MPLS_VPN && safi != SAFI_ENCAP + && safi != SAFI_EVPN && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)) subgroup_default_originate (subgrp, 0); @@ -668,7 +669,8 @@ subgroup_announce_route (struct update_subgroup *subgrp) return; if (SUBGRP_SAFI (subgrp) != SAFI_MPLS_VPN && - SUBGRP_SAFI (subgrp) != SAFI_ENCAP) + SUBGRP_SAFI (subgrp) != SAFI_ENCAP && + SUBGRP_SAFI (subgrp) != SAFI_EVPN) subgroup_announce_table (subgrp, NULL); else for (rn = bgp_table_top (update_subgroup_rib (subgrp)); rn; diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index cca34d0a85..881173d382 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -6834,6 +6834,8 @@ afi_safi_print (afi_t afi, safi_t safi) return "IPv6 VPN"; else if (afi == AFI_IP6 && safi == SAFI_ENCAP) return "IPv6 Encap"; + else if (afi == AFI_L2VPN && safi == SAFI_EVPN) + return "L2VPN EVPN"; else return "Unknown"; } @@ -6857,6 +6859,8 @@ afi_safi_json (afi_t afi, safi_t safi) return "IPv6VPN"; else if (afi == AFI_IP6 && safi == SAFI_ENCAP) return "IPv6Encap"; + else if (afi == AFI_L2VPN && safi == SAFI_EVPN) + return "L2VPN EVPN"; else return "Unknown"; } diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index fc6968e9d9..1cad7c5a15 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -1643,6 +1643,8 @@ peer_as_change (struct peer *peer, as_t as, int as_specified) PEER_FLAG_REFLECTOR_CLIENT); UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_ENCAP], PEER_FLAG_REFLECTOR_CLIENT); + UNSET_FLAG (peer->af_flags[AFI_L2VPN][SAFI_EVPN], + PEER_FLAG_REFLECTOR_CLIENT); } /* local-as reset */ @@ -7217,7 +7219,11 @@ bgp_config_write_family_header (struct vty *vty, afi_t afi, safi_t safi, else if (safi == SAFI_ENCAP) vty_out (vty, "ipv6 encap"); } - + else if (afi == AFI_L2VPN) + { + if (safi == SAFI_EVPN) + vty_out (vty, "evpn"); + } vty_out (vty, "%s", VTY_NEWLINE); *write = 1; @@ -7518,6 +7524,9 @@ bgp_config_write (struct vty *vty) /* ENCAPv6 configuration. */ write += bgp_config_write_family (vty, bgp, AFI_IP6, SAFI_ENCAP); + /* EVPN configuration. */ + write += bgp_config_write_family (vty, bgp, AFI_L2VPN, SAFI_EVPN); + #if ENABLE_BGP_VNC write += bgp_rfapi_cfg_write(vty, bgp); #endif -- 2.39.5