To handle BGP NLRI EVPN messages, bgp is modified to handle AFI_L2VPN and SAFI_EVPN values.
Signed-off-by: Philippe Guibert <philippe.guib...@6wind.com> --- bgpd/bgp_attr.c | 25 ++++++++++++++++++----- bgpd/bgp_open.c | 29 ++++++++++++++++++++++++++- bgpd/bgp_packet.c | 28 ++++++++++++++++++++------ bgpd/bgp_route.c | 60 ++++++++++++++++++++++++++++++++++++++----------------- bgpd/bgp_vty.c | 2 ++ bgpd/bgpd.c | 20 +++++++++++++++---- 6 files changed, 130 insertions(+), 34 deletions(-) diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c index b46e7a30e3f7..8741c4af3441 100644 --- a/bgpd/bgp_attr.c +++ b/bgpd/bgp_attr.c @@ -2396,9 +2396,16 @@ bgp_packet_mpattr_start (struct stream *s, afi_t afi, safi_t safi, sizep = stream_get_endp (s); stream_putw (s, 0); /* Marker: Attribute length. */ - stream_putw (s, afi); - stream_putc (s, (safi == SAFI_MPLS_VPN) ? SAFI_MPLS_LABELED_VPN : safi); - + if(afi == AFI_INTERNAL_L2VPN) + stream_putw (s, AFI_L2VPN); + else + stream_putw (s, afi); + if(safi == SAFI_MPLS_VPN) + stream_putc (s, SAFI_MPLS_LABELED_VPN); + else if(safi == SAFI_INTERNAL_EVPN) + stream_putc (s, SAFI_EVPN); + else + stream_putc (s, safi); /* Nexthop */ switch (afi) { @@ -2987,8 +2994,16 @@ bgp_packet_mpunreach_start (struct stream *s, afi_t afi, safi_t safi) attrlen_pnt = stream_get_endp (s); stream_putw (s, 0); /* Length of this attribute. */ - stream_putw (s, afi); - stream_putc (s, (safi == SAFI_MPLS_VPN) ? SAFI_MPLS_LABELED_VPN : safi); + if(afi == AFI_INTERNAL_L2VPN) + stream_putw (s, AFI_L2VPN); + else + stream_putw (s, afi); + if(safi == SAFI_MPLS_VPN) + stream_putc (s, SAFI_MPLS_LABELED_VPN); + else if(safi == SAFI_INTERNAL_EVPN) + stream_putc (s, SAFI_EVPN); + else + stream_putc (s, safi); return attrlen_pnt; } diff --git a/bgpd/bgp_open.c b/bgpd/bgp_open.c index 7b8b6577e078..5ce838b899dc 100644 --- a/bgpd/bgp_open.c +++ b/bgpd/bgp_open.c @@ -82,6 +82,9 @@ bgp_capability_vty_out (struct vty *vty, struct peer *peer) 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; @@ -100,6 +103,9 @@ bgp_capability_vty_out (struct vty *vty, struct peer *peer) 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; @@ -143,6 +149,12 @@ bgp_afi_safi_valid_indices (afi_t afi, safi_t *safi) case SAFI_ENCAP: return 1; } + case AFI_INTERNAL_L2VPN: + switch (*safi) + { + case SAFI_INTERNAL_EVPN: + return 1; + } break; } @@ -849,7 +861,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_INTERNAL_L2VPN][SAFI_INTERNAL_EVPN]) { plog_err (peer->log, "%s [Error] Configured AFI/SAFIs do not " "overlap with received MP capabilities", @@ -884,6 +897,8 @@ bgp_open_capability_orf (struct stream *s, struct peer *peer, if (safi == SAFI_MPLS_VPN) safi = SAFI_MPLS_LABELED_VPN; + else if (safi == SAFI_INTERNAL_EVPN) + safi = SAFI_EVPN; stream_putc (s, BGP_OPEN_OPT_CAP); capp = stream_get_endp (s); /* Set Capability Len Pointer */ @@ -1054,6 +1069,18 @@ bgp_open_capability (struct stream *s, struct peer *peer) stream_putc (s, 0); stream_putc (s, SAFI_ENCAP); } + /* IPv6 ENCAP. */ + if (peer->afc[AFI_INTERNAL_L2VPN][SAFI_INTERNAL_EVPN]) + { + peer->afc_adv[AFI_INTERNAL_L2VPN][SAFI_INTERNAL_EVPN] = 1; + stream_putc (s, BGP_OPEN_OPT_CAP); + stream_putc (s, CAPABILITY_CODE_MP_LEN + 2); + stream_putc (s, CAPABILITY_CODE_MP); + stream_putc (s, CAPABILITY_CODE_MP_LEN); + stream_putw (s, AFI_L2VPN); + stream_putc (s, 0); + stream_putc (s, SAFI_EVPN); + } /* Route refresh. */ SET_FLAG (peer->cap, PEER_CAP_REFRESH_ADV); diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c index 8e315d1dbc80..db569b876424 100644 --- a/bgpd/bgp_packet.c +++ b/bgpd/bgp_packet.c @@ -650,7 +650,8 @@ bgp_write_packet (struct peer *peer) CHECK_FLAG (adv->binfo->peer->cap, PEER_CAP_RESTART_BIT_ADV)) && ! CHECK_FLAG (adv->binfo->flags, BGP_INFO_STALE) - && safi != SAFI_MPLS_VPN) + && safi != SAFI_MPLS_VPN + && safi != SAFI_INTERNAL_EVPN) { if (CHECK_FLAG (adv->binfo->peer->af_sflags[afi][safi], PEER_STATUS_EOR_RECEIVED)) @@ -668,7 +669,8 @@ bgp_write_packet (struct peer *peer) { if (peer->afc_nego[afi][safi] && peer->synctime && ! CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_EOR_SEND) - && safi != SAFI_MPLS_VPN) + && safi != SAFI_MPLS_VPN + && safi != SAFI_INTERNAL_EVPN) { SET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_EOR_SEND); return bgp_update_packet_eor (peer, afi, safi); @@ -1077,7 +1079,11 @@ bgp_route_refresh_send (struct peer *peer, afi_t afi, safi_t safi, /* Adjust safi code. */ if (safi == SAFI_MPLS_VPN) safi = SAFI_MPLS_LABELED_VPN; - + else if (safi == SAFI_INTERNAL_EVPN) + safi = SAFI_EVPN; + if (afi == AFI_INTERNAL_L2VPN) + afi = AFI_L2VPN; + s = stream_new (BGP_MAX_PACKET_SIZE); /* Make BGP update packet. */ @@ -1159,9 +1165,15 @@ bgp_capability_send (struct peer *peer, afi_t afi, safi_t safi, struct stream *s; int length; + /* Adjust afi code. */ + if (afi == AFI_INTERNAL_L2VPN) + afi = AFI_L2VPN; + /* Adjust safi code. */ if (safi == SAFI_MPLS_VPN) safi = SAFI_MPLS_LABELED_VPN; + if (safi == SAFI_INTERNAL_EVPN) + safi = SAFI_EVPN; s = stream_new (BGP_MAX_PACKET_SIZE); @@ -2079,9 +2091,9 @@ bgp_route_refresh_receive (struct peer *peer, bgp_size_t size) peer->host, afi, safi); /* Check AFI and SAFI. */ - if ((afi != AFI_IP && afi != AFI_IP6) + if ((afi != AFI_IP && afi != AFI_IP6 && afi != AFI_L2VPN) || (safi != SAFI_UNICAST && safi != SAFI_MULTICAST - && safi != SAFI_MPLS_LABELED_VPN)) + && safi != SAFI_MPLS_LABELED_VPN && safi != SAFI_EVPN)) { if (BGP_DEBUG (normal, NORMAL)) { @@ -2094,7 +2106,11 @@ bgp_route_refresh_receive (struct peer *peer, bgp_size_t size) /* Adjust safi code. */ if (safi == SAFI_MPLS_LABELED_VPN) safi = SAFI_MPLS_VPN; - + else if (safi == SAFI_EVPN) + safi = SAFI_INTERNAL_EVPN; + if (afi == AFI_L2VPN) + afi = AFI_INTERNAL_L2VPN; + if (size != BGP_MSG_ROUTE_REFRESH_MIN_SIZE - BGP_HEADER_SIZE) { u_char *end; diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index e83f292162ba..a958a2e42fba 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -91,7 +91,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_INTERNAL_EVPN)) { prn = bgp_node_get (table, (struct prefix *) prd); @@ -108,7 +109,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_INTERNAL_EVPN)) rn->prn = prn; return rn; @@ -1562,8 +1564,12 @@ void bgp_vrf_clean_tables (struct bgp_vrf *vrf) if (rn->info) { struct bgp_static *bs = rn->info; - bgp_static_withdraw_safi (vrf->bgp, &rn->p, afi, SAFI_MPLS_VPN, - &vrf->outbound_rd, NULL, 0); + if(afi == AFI_INTERNAL_L2VPN) + bgp_static_withdraw_safi (vrf->bgp, &rn->p, afi, SAFI_INTERNAL_EVPN, + &vrf->outbound_rd, NULL, 0); + else + bgp_static_withdraw_safi (vrf->bgp, &rn->p, afi, SAFI_MPLS_VPN, + &vrf->outbound_rd, NULL, 0); bgp_static_free (bs); rn->info = NULL; bgp_unlock_node (rn); @@ -2408,8 +2414,15 @@ bgp_maximum_prefix_overflow (struct peer *peer, afi_t afi, u_int8_t ndata[7]; if (safi == SAFI_MPLS_VPN) - safi = SAFI_MPLS_LABELED_VPN; - + ndata[2] = SAFI_MPLS_LABELED_VPN; + else if (safi == SAFI_INTERNAL_EVPN) + ndata[2] = SAFI_EVPN; + else + ndata[2] = safi; + if (afi == AFI_INTERNAL_L2VPN) + ndata[1] = AFI_L2VPN; + else + ndata[1] = afi; ndata[0] = (afi >> 8); ndata[1] = afi; ndata[2] = safi; @@ -3324,11 +3337,10 @@ bgp_announce_table (struct peer *peer, afi_t afi, safi_t safi, struct attr_extra extra; memset(&extra, 0, sizeof(extra)); - if (! table) table = (rsclient) ? peer->rib[afi][safi] : peer->bgp->rib[afi][safi]; - if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP) + if (((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP) && (safi != SAFI_INTERNAL_EVPN)) && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_DEFAULT_ORIGINATE)) bgp_default_originate (peer, afi, safi, 0); @@ -3366,7 +3378,7 @@ bgp_announce_route (struct peer *peer, afi_t afi, safi_t safi) if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_WAIT_REFRESH)) return; - if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP)) + if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP) && ( safi != SAFI_INTERNAL_EVPN)) bgp_announce_table (peer, afi, safi, NULL, 0); else for (rn = bgp_table_top (peer->bgp->rib[afi][safi]); rn; @@ -3417,7 +3429,7 @@ bgp_soft_reconfig_rsclient (struct peer *rsclient, afi_t afi, safi_t safi) struct bgp_table *table; struct bgp_node *rn; - if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP)) + if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP) && (safi != SAFI_INTERNAL_EVPN)) bgp_soft_reconfig_table_rsclient (rsclient, afi, safi, NULL, NULL); else @@ -3477,7 +3489,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_INTERNAL_EVPN)) bgp_soft_reconfig_table (peer, afi, safi, NULL, NULL); else for (rn = bgp_table_top (peer->bgp->rib[afi][safi]); rn; @@ -3694,7 +3706,8 @@ bgp_clear_route (struct peer *peer, afi_t afi, safi_t safi, switch (purpose) { case BGP_CLEAR_ROUTE_NORMAL: - if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP)) + if ((safi != SAFI_MPLS_VPN) && (safi != SAFI_ENCAP) && + (safi != SAFI_INTERNAL_EVPN)) bgp_clear_route_table (peer, afi, safi, NULL, NULL, purpose); else for (rn = bgp_table_top (peer->bgp->rib[afi][safi]); rn; @@ -3859,10 +3872,11 @@ bgp_cleanup_routes (void) for (ALL_LIST_ELEMENTS (bm->bgp, node, nnode, bgp)) { + struct bgp_node *rn; for (afi = AFI_IP; afi < AFI_MAX; ++afi) { - struct bgp_node *rn; - + if(afi == AFI_INTERNAL_L2VPN) + continue; bgp_cleanup_table(bgp->rib[afi][SAFI_UNICAST], SAFI_UNICAST); /* @@ -3892,6 +3906,17 @@ bgp_cleanup_routes (void) } } } + for (rn = bgp_table_top(bgp->rib[AFI_INTERNAL_L2VPN][SAFI_INTERNAL_EVPN]); rn; + rn = bgp_route_next (rn)) + { + if (rn->info) + { + bgp_cleanup_table((struct bgp_table *)(rn->info), SAFI_INTERNAL_EVPN); + bgp_table_finish ((struct bgp_table **)&(rn->info)); + rn->info = NULL; + bgp_unlock_node(rn); + } + } } } @@ -4539,7 +4564,6 @@ bgp_static_update_safi (struct bgp *bgp, struct prefix *p, assert (bgp_static); rn = bgp_afi_node_get (bgp->rib[afi][safi], afi, safi, p, &bgp_static->prd); - bgp_attr_default_set (&attr, BGP_ORIGIN_IGP); attr.nexthop = bgp_static->igpnexthop; @@ -4810,7 +4834,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_INTERNAL_EVPN)) { table = rn->info; @@ -5673,7 +5697,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_INTERNAL_EVPN)) return; table = bgp->aggregate[afi][safi]; @@ -5710,7 +5734,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_INTERNAL_EVPN)) return; table = bgp->aggregate[afi][safi]; diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 5fbec0f1a85b..1720fafe9d0a 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -8103,6 +8103,8 @@ afi_safi_print (afi_t afi, safi_t safi) return "VPN-IPv6 Unicast"; else if (afi == AFI_IP6 && safi == SAFI_ENCAP) return "ENCAP-IPv6 Unicast"; + else if (afi == AFI_INTERNAL_L2VPN && safi == SAFI_INTERNAL_EVPN) + return "EVPN"; else return "Unknown"; } diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 9e091dd2e04b..bd8ee96c1ce1 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -1021,6 +1021,8 @@ peer_as_change (struct peer *peer, as_t as) PEER_FLAG_REFLECTOR_CLIENT); UNSET_FLAG (peer->af_flags[AFI_IP6][SAFI_ENCAP], PEER_FLAG_REFLECTOR_CLIENT); + UNSET_FLAG (peer->af_flags[AFI_INTERNAL_L2VPN][SAFI_INTERNAL_EVPN], + PEER_FLAG_REFLECTOR_CLIENT); } /* local-as reset */ @@ -1455,7 +1457,8 @@ peer_group_active (struct peer *peer) || peer->af_group[AFI_IP6][SAFI_UNICAST] || peer->af_group[AFI_IP6][SAFI_MULTICAST] || peer->af_group[AFI_IP6][SAFI_MPLS_VPN] - || peer->af_group[AFI_IP6][SAFI_ENCAP]) + || peer->af_group[AFI_IP6][SAFI_ENCAP] + || peer->af_group[AFI_INTERNAL_L2VPN][SAFI_INTERNAL_EVPN]) return 1; return 0; } @@ -2606,7 +2609,8 @@ peer_active (struct peer *peer) || peer->afc[AFI_IP6][SAFI_UNICAST] || peer->afc[AFI_IP6][SAFI_MULTICAST] || peer->afc[AFI_IP6][SAFI_MPLS_VPN] - || peer->afc[AFI_IP6][SAFI_ENCAP]) + || peer->afc[AFI_IP6][SAFI_ENCAP] + || peer->afc[AFI_INTERNAL_L2VPN][SAFI_INTERNAL_EVPN]) return 1; return 0; } @@ -2622,7 +2626,8 @@ peer_active_nego (struct peer *peer) || 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_INTERNAL_L2VPN][SAFI_INTERNAL_EVPN]) return 1; return 0; } @@ -5577,7 +5582,11 @@ bgp_config_write_family_header (struct vty *vty, afi_t afi, safi_t safi, vty_out (vty, " multicast"); } } - + else if (afi == AFI_INTERNAL_L2VPN) + { + if (safi == SAFI_INTERNAL_EVPN) + vty_out (vty, "evpn"); + } vty_out (vty, "%s", VTY_NEWLINE); *write = 1; @@ -5864,6 +5873,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_INTERNAL_L2VPN, SAFI_INTERNAL_EVPN); + vty_out (vty, " exit%s", VTY_NEWLINE); write++; -- 2.1.4 _______________________________________________ Quagga-dev mailing list Quagga-dev@lists.quagga.net https://lists.quagga.net/mailman/listinfo/quagga-dev