Merge pull request #2873 from vivek-cumulus/evpn-extended-mobility

EVPN extended mobility support
This commit is contained in:
Russ White 2018-09-05 18:09:31 -04:00 committed by GitHub
commit 7f0f6e7b75
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 921 additions and 752 deletions

View File

@ -543,7 +543,7 @@ static void evpn_convert_nexthop_to_ipv6(struct attr *attr)
static int bgp_zebra_send_remote_macip(struct bgp *bgp, struct bgpevpn *vpn, static int bgp_zebra_send_remote_macip(struct bgp *bgp, struct bgpevpn *vpn,
struct prefix_evpn *p, struct prefix_evpn *p,
struct in_addr remote_vtep_ip, int add, struct in_addr remote_vtep_ip, int add,
uint8_t flags) uint8_t flags, uint32_t seq)
{ {
struct stream *s; struct stream *s;
int ipa_len; int ipa_len;
@ -579,19 +579,22 @@ static int bgp_zebra_send_remote_macip(struct bgp *bgp, struct bgpevpn *vpn,
stream_put_in_addr(s, &remote_vtep_ip); stream_put_in_addr(s, &remote_vtep_ip);
/* TX flags - MAC sticky status and/or gateway mac */ /* TX flags - MAC sticky status and/or gateway mac */
if (add) /* Also TX the sequence number of the best route. */
if (add) {
stream_putc(s, flags); stream_putc(s, flags);
stream_putl(s, seq);
}
stream_putw_at(s, 0, stream_get_endp(s)); stream_putw_at(s, 0, stream_get_endp(s));
if (bgp_debug_zebra(NULL)) if (bgp_debug_zebra(NULL))
zlog_debug( zlog_debug(
"Tx %s MACIP, VNI %u MAC %s IP %s (flags: 0x%x) remote VTEP %s", "Tx %s MACIP, VNI %u MAC %s IP %s flags 0x%x seq %u remote VTEP %s",
add ? "ADD" : "DEL", vpn->vni, add ? "ADD" : "DEL", vpn->vni,
prefix_mac2str(&p->prefix.macip_addr.mac, prefix_mac2str(&p->prefix.macip_addr.mac,
buf1, sizeof(buf1)), buf1, sizeof(buf1)),
ipaddr2str(&p->prefix.macip_addr.ip, ipaddr2str(&p->prefix.macip_addr.ip,
buf3, sizeof(buf3)), flags, buf3, sizeof(buf3)), flags, seq,
inet_ntop(AF_INET, &remote_vtep_ip, buf2, inet_ntop(AF_INET, &remote_vtep_ip, buf2,
sizeof(buf2))); sizeof(buf2)));
@ -875,13 +878,14 @@ static void add_mac_mobility_to_attr(uint32_t seq_num, struct attr *attr)
/* Install EVPN route into zebra. */ /* Install EVPN route into zebra. */
static int evpn_zebra_install(struct bgp *bgp, struct bgpevpn *vpn, static int evpn_zebra_install(struct bgp *bgp, struct bgpevpn *vpn,
struct prefix_evpn *p, struct prefix_evpn *p,
struct in_addr remote_vtep_ip, uint8_t flags) struct in_addr remote_vtep_ip, uint8_t flags,
uint32_t seq)
{ {
int ret; int ret;
if (p->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE) if (p->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE)
ret = bgp_zebra_send_remote_macip(bgp, vpn, p, remote_vtep_ip, ret = bgp_zebra_send_remote_macip(bgp, vpn, p, remote_vtep_ip,
1, flags); 1, flags, seq);
else else
ret = bgp_zebra_send_remote_vtep(bgp, vpn, p, 1); ret = bgp_zebra_send_remote_vtep(bgp, vpn, p, 1);
@ -897,7 +901,7 @@ static int evpn_zebra_uninstall(struct bgp *bgp, struct bgpevpn *vpn,
if (p->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE) if (p->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE)
ret = bgp_zebra_send_remote_macip(bgp, vpn, p, remote_vtep_ip, ret = bgp_zebra_send_remote_macip(bgp, vpn, p, remote_vtep_ip,
0, 0); 0, 0, 0);
else else
ret = bgp_zebra_send_remote_vtep(bgp, vpn, p, 0); ret = bgp_zebra_send_remote_vtep(bgp, vpn, p, 0);
@ -1141,7 +1145,8 @@ static int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn,
ret = evpn_zebra_install( ret = evpn_zebra_install(
bgp, vpn, (struct prefix_evpn *)&rn->p, bgp, vpn, (struct prefix_evpn *)&rn->p,
old_select->attr->nexthop, flags); old_select->attr->nexthop, flags,
mac_mobility_seqnum(old_select->attr));
} }
UNSET_FLAG(old_select->flags, BGP_INFO_MULTIPATH_CHG); UNSET_FLAG(old_select->flags, BGP_INFO_MULTIPATH_CHG);
bgp_zebra_clear_route_change_flags(rn); bgp_zebra_clear_route_change_flags(rn);
@ -1177,7 +1182,8 @@ static int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn,
SET_FLAG(flags, ZEBRA_MACIP_TYPE_ROUTER_FLAG); SET_FLAG(flags, ZEBRA_MACIP_TYPE_ROUTER_FLAG);
ret = evpn_zebra_install(bgp, vpn, (struct prefix_evpn *)&rn->p, ret = evpn_zebra_install(bgp, vpn, (struct prefix_evpn *)&rn->p,
new_select->attr->nexthop, flags); new_select->attr->nexthop, flags,
mac_mobility_seqnum(new_select->attr));
/* If an old best existed and it was a "local" route, the only /* If an old best existed and it was a "local" route, the only
* reason * reason
* it would be supplanted is due to MAC mobility procedures. So, * it would be supplanted is due to MAC mobility procedures. So,
@ -1557,11 +1563,12 @@ static int update_evpn_type5_route(struct bgp *bgp_vrf, struct prefix_evpn *evp,
*/ */
static int update_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn, static int update_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn,
afi_t afi, safi_t safi, struct bgp_node *rn, afi_t afi, safi_t safi, struct bgp_node *rn,
struct attr *attr, int add, int vni_table, struct attr *attr, int add,
struct bgp_info **ri, uint8_t flags) struct bgp_info **ri, uint8_t flags,
uint32_t seq)
{ {
struct bgp_info *tmp_ri; struct bgp_info *tmp_ri;
struct bgp_info *local_ri, *remote_ri; struct bgp_info *local_ri;
struct attr *attr_new; struct attr *attr_new;
mpls_label_t label[BGP_MAX_LABELS]; mpls_label_t label[BGP_MAX_LABELS];
uint32_t num_labels = 1; uint32_t num_labels = 1;
@ -1573,28 +1580,13 @@ static int update_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn,
evp = (struct prefix_evpn *)&rn->p; evp = (struct prefix_evpn *)&rn->p;
memset(&label, 0, sizeof(label)); memset(&label, 0, sizeof(label));
/* See if this is an update of an existing route, or a new add. Also, /* See if this is an update of an existing route, or a new add. */
* identify if already known from remote, and if so, the one with the local_ri = NULL;
* highest sequence number; this is only when adding to the VNI routing
* table.
*/
local_ri = remote_ri = NULL;
for (tmp_ri = rn->info; tmp_ri; tmp_ri = tmp_ri->next) { for (tmp_ri = rn->info; tmp_ri; tmp_ri = tmp_ri->next) {
if (tmp_ri->peer == bgp->peer_self if (tmp_ri->peer == bgp->peer_self
&& tmp_ri->type == ZEBRA_ROUTE_BGP && tmp_ri->type == ZEBRA_ROUTE_BGP
&& tmp_ri->sub_type == BGP_ROUTE_STATIC) && tmp_ri->sub_type == BGP_ROUTE_STATIC)
local_ri = tmp_ri; local_ri = tmp_ri;
if (vni_table) {
if (tmp_ri->type == ZEBRA_ROUTE_BGP
&& tmp_ri->sub_type == BGP_ROUTE_IMPORTED
&& CHECK_FLAG(tmp_ri->flags, BGP_INFO_VALID)) {
if (!remote_ri)
remote_ri = tmp_ri;
else if (mac_mobility_seqnum(tmp_ri->attr)
> mac_mobility_seqnum(remote_ri->attr))
remote_ri = tmp_ri;
}
}
} }
/* If route doesn't exist already, create a new one, if told to. /* If route doesn't exist already, create a new one, if told to.
@ -1604,22 +1596,11 @@ static int update_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn,
if (!local_ri && !add) if (!local_ri && !add)
return 0; return 0;
/* For non-GW MACs, update MAC mobility seq number, if needed. */
if (seq && !CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_GW))
add_mac_mobility_to_attr(seq, attr);
if (!local_ri) { if (!local_ri) {
/* When learnt locally for the first time but already known from
* remote, we have to initiate appropriate MAC mobility steps.
* This is applicable when updating the VNI routing table.
* We need to skip mobility steps for g/w macs (local mac on g/w
* SVI) advertised in EVPN.
* This will ensure that local routes are preferred for g/w macs
*/
if (remote_ri && !CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_GW)) {
uint32_t cur_seqnum;
/* Add MM extended community to route. */
cur_seqnum = mac_mobility_seqnum(remote_ri->attr);
add_mac_mobility_to_attr(cur_seqnum + 1, attr);
}
/* Add (or update) attribute to hash. */ /* Add (or update) attribute to hash. */
attr_new = bgp_attr_intern(attr); attr_new = bgp_attr_intern(attr);
@ -1685,6 +1666,11 @@ static int update_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn,
attr_new = bgp_attr_intern(attr); attr_new = bgp_attr_intern(attr);
bgp_info_set_flag(rn, tmp_ri, BGP_INFO_ATTR_CHANGED); bgp_info_set_flag(rn, tmp_ri, BGP_INFO_ATTR_CHANGED);
/* Extract MAC mobility sequence number, if any. */
attr_new->mm_seqnum =
bgp_attr_mac_mobility_seqnum(attr_new, &sticky);
attr_new->sticky = sticky;
/* Restore route, if needed. */ /* Restore route, if needed. */
if (CHECK_FLAG(tmp_ri->flags, BGP_INFO_REMOVED)) if (CHECK_FLAG(tmp_ri->flags, BGP_INFO_REMOVED))
bgp_info_restore(rn, tmp_ri); bgp_info_restore(rn, tmp_ri);
@ -1706,7 +1692,8 @@ static int update_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn,
* and schedule for processing. * and schedule for processing.
*/ */
static int update_evpn_route(struct bgp *bgp, struct bgpevpn *vpn, static int update_evpn_route(struct bgp *bgp, struct bgpevpn *vpn,
struct prefix_evpn *p, uint8_t flags) struct prefix_evpn *p, uint8_t flags,
uint32_t seq)
{ {
struct bgp_node *rn; struct bgp_node *rn;
struct attr attr; struct attr attr;
@ -1758,7 +1745,7 @@ static int update_evpn_route(struct bgp *bgp, struct bgpevpn *vpn,
/* Create or update route entry. */ /* Create or update route entry. */
route_change = update_evpn_route_entry(bgp, vpn, afi, safi, rn, &attr, route_change = update_evpn_route_entry(bgp, vpn, afi, safi, rn, &attr,
1, 1, &ri, flags); 1, &ri, flags, seq);
assert(ri); assert(ri);
attr_new = ri->attr; attr_new = ri->attr;
@ -1778,8 +1765,8 @@ static int update_evpn_route(struct bgp *bgp, struct bgpevpn *vpn,
rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi,
(struct prefix *)p, &vpn->prd); (struct prefix *)p, &vpn->prd);
update_evpn_route_entry(bgp, vpn, afi, safi, rn, attr_new, 1, 0, update_evpn_route_entry(bgp, vpn, afi, safi, rn, attr_new, 1,
&global_ri, flags); &global_ri, flags, seq);
/* Schedule for processing and unlock node. */ /* Schedule for processing and unlock node. */
bgp_process(bgp, rn, afi, safi); bgp_process(bgp, rn, afi, safi);
@ -1954,58 +1941,14 @@ static int update_all_type2_routes(struct bgp *bgp, struct bgpevpn *vpn)
afi_t afi; afi_t afi;
safi_t safi; safi_t safi;
struct bgp_node *rn; struct bgp_node *rn;
struct bgp_info *ri; struct bgp_info *ri, *tmp_ri;
struct attr attr; struct attr attr;
struct attr attr_sticky;
struct attr attr_def_gw;
struct attr attr_ip6_ll;
struct attr *attr_new; struct attr *attr_new;
uint32_t seq;
int add_l3_ecomm = 0; int add_l3_ecomm = 0;
afi = AFI_L2VPN; afi = AFI_L2VPN;
safi = SAFI_EVPN; safi = SAFI_EVPN;
memset(&attr, 0, sizeof(struct attr));
memset(&attr_sticky, 0, sizeof(struct attr));
memset(&attr_def_gw, 0, sizeof(struct attr));
memset(&attr_ip6_ll, 0, sizeof(struct attr));
/* Build path-attribute - multiple type-2 routes for this VNI will share
* the same path attribute, but we need separate structures for sticky
* MACs, default gateway and IPv6 link-local addresses (no L3 RT/RMAC).
*/
bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
bgp_attr_default_set(&attr_sticky, BGP_ORIGIN_IGP);
bgp_attr_default_set(&attr_def_gw, BGP_ORIGIN_IGP);
attr.nexthop = vpn->originator_ip;
attr.mp_nexthop_global_in = vpn->originator_ip;
attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
bgpevpn_get_rmac(vpn, &attr.rmac);
attr_sticky.nexthop = vpn->originator_ip;
attr_sticky.mp_nexthop_global_in = vpn->originator_ip;
attr_sticky.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
attr_sticky.sticky = 1;
bgpevpn_get_rmac(vpn, &attr_sticky.rmac);
attr_def_gw.nexthop = vpn->originator_ip;
attr_def_gw.mp_nexthop_global_in = vpn->originator_ip;
attr_def_gw.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
attr_def_gw.default_gw = 1;
bgpevpn_get_rmac(vpn, &attr_def_gw.rmac);
bgp_attr_default_set(&attr_ip6_ll, BGP_ORIGIN_IGP);
attr_ip6_ll.nexthop = vpn->originator_ip;
attr_ip6_ll.mp_nexthop_global_in = vpn->originator_ip;
attr_ip6_ll.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
/* Add L3 VNI RTs and RMAC for non IPv6 link-local attributes if
* using L3 VNI for type-2 routes also.
*/
if (CHECK_FLAG(vpn->flags, VNI_FLAG_USE_TWO_LABELS) &&
bgpevpn_get_l3vni(vpn))
add_l3_ecomm = 1;
build_evpn_route_extcomm(vpn, &attr, add_l3_ecomm);
build_evpn_route_extcomm(vpn, &attr_sticky, add_l3_ecomm);
build_evpn_route_extcomm(vpn, &attr_def_gw, add_l3_ecomm);
build_evpn_route_extcomm(vpn, &attr_ip6_ll, 0);
/* Walk this VNI's route table and update local type-2 routes. For any /* Walk this VNI's route table and update local type-2 routes. For any
* routes updated, update corresponding entry in the global table too. * routes updated, update corresponding entry in the global table too.
@ -2019,35 +1962,57 @@ static int update_all_type2_routes(struct bgp *bgp, struct bgpevpn *vpn)
if (evp->prefix.route_type != BGP_EVPN_MAC_IP_ROUTE) if (evp->prefix.route_type != BGP_EVPN_MAC_IP_ROUTE)
continue; continue;
if (is_evpn_prefix_ipaddr_v6(evp) && /* Identify local route. */
IN6_IS_ADDR_LINKLOCAL(&evp->prefix.macip_addr.ip.ipaddr_v6)) for (tmp_ri = rn->info; tmp_ri; tmp_ri = tmp_ri->next) {
update_evpn_route_entry(bgp, vpn, afi, safi, rn, if (tmp_ri->peer == bgp->peer_self
&attr_ip6_ll, 0, 1, &ri, 0); && tmp_ri->type == ZEBRA_ROUTE_BGP
else { && tmp_ri->sub_type == BGP_ROUTE_STATIC)
if (evpn_route_is_sticky(bgp, rn)) break;
update_evpn_route_entry(bgp, vpn, afi, safi, rn,
&attr_sticky, 0, 1, &ri,
0);
else if (evpn_route_is_def_gw(bgp, rn)) {
if (is_evpn_prefix_ipaddr_v6(evp))
attr_def_gw.router_flag = 1;
update_evpn_route_entry(bgp, vpn, afi, safi, rn,
&attr_def_gw, 0, 1, &ri,
0);
} else
update_evpn_route_entry(bgp, vpn, afi, safi, rn,
&attr, 0, 1, &ri, 0);
} }
/* If a local route exists for this prefix, we need to update if (!tmp_ri)
* the global routing table too.
*/
if (!ri)
continue; continue;
/*
* Build attribute per local route as the MAC mobility and
* some other values could differ for different routes. The
* attributes will be shared in the hash table.
*/
bgp_attr_default_set(&attr, BGP_ORIGIN_IGP);
attr.nexthop = vpn->originator_ip;
attr.mp_nexthop_global_in = vpn->originator_ip;
attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
bgpevpn_get_rmac(vpn, &attr.rmac);
if (evpn_route_is_sticky(bgp, rn))
attr.sticky = 1;
else if (evpn_route_is_def_gw(bgp, rn)) {
attr.default_gw = 1;
if (is_evpn_prefix_ipaddr_v6(evp))
attr.router_flag = 1;
}
/* Add L3 VNI RTs and RMAC for non IPv6 link-local if
* using L3 VNI for type-2 routes also.
*/
if ((is_evpn_prefix_ipaddr_v4(evp) ||
!IN6_IS_ADDR_LINKLOCAL(
&evp->prefix.macip_addr.ip.ipaddr_v6)) &&
CHECK_FLAG(vpn->flags, VNI_FLAG_USE_TWO_LABELS) &&
bgpevpn_get_l3vni(vpn))
add_l3_ecomm = 1;
/* Set up extended community. */
build_evpn_route_extcomm(vpn, &attr, add_l3_ecomm);
seq = mac_mobility_seqnum(tmp_ri->attr);
/* Update the route entry. */
update_evpn_route_entry(bgp, vpn, afi, safi, rn,
&attr, 0, &ri, 0, seq);
/* Perform route selection; this is just to set the flags /* Perform route selection; this is just to set the flags
* correctly * correctly as local route in the VNI always wins.
* as local route in the VNI always wins.
*/ */
evpn_route_select_install(bgp, vpn, rn); evpn_route_select_install(bgp, vpn, rn);
@ -2058,18 +2023,17 @@ static int update_all_type2_routes(struct bgp *bgp, struct bgpevpn *vpn)
(struct prefix *)evp, &vpn->prd); (struct prefix *)evp, &vpn->prd);
assert(rd_rn); assert(rd_rn);
update_evpn_route_entry(bgp, vpn, afi, safi, rd_rn, attr_new, 0, update_evpn_route_entry(bgp, vpn, afi, safi, rd_rn, attr_new, 0,
0, &global_ri, 0); &global_ri, 0,
mac_mobility_seqnum(attr_new));
/* Schedule for processing and unlock node. */ /* Schedule for processing and unlock node. */
bgp_process(bgp, rd_rn, afi, safi); bgp_process(bgp, rd_rn, afi, safi);
bgp_unlock_node(rd_rn); bgp_unlock_node(rd_rn);
}
/* Unintern temporary. */ /* Unintern temporary. */
aspath_unintern(&attr.aspath); aspath_unintern(&attr.aspath);
aspath_unintern(&attr_sticky.aspath);
aspath_unintern(&attr_def_gw.aspath); }
aspath_unintern(&attr_ip6_ll.aspath);
return 0; return 0;
} }
@ -2206,7 +2170,7 @@ static int update_routes_for_vni(struct bgp *bgp, struct bgpevpn *vpn)
* locally learnt type-2 routes (MACIP) - for this VNI. * locally learnt type-2 routes (MACIP) - for this VNI.
*/ */
build_evpn_type3_prefix(&p, vpn->originator_ip); build_evpn_type3_prefix(&p, vpn->originator_ip);
ret = update_evpn_route(bgp, vpn, &p, 0); ret = update_evpn_route(bgp, vpn, &p, 0, 0);
if (ret) if (ret)
return ret; return ret;
@ -3451,8 +3415,8 @@ static int update_advertise_vni_routes(struct bgp *bgp, struct bgpevpn *vpn)
global_rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, global_rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi,
(struct prefix *)&p, &vpn->prd); (struct prefix *)&p, &vpn->prd);
update_evpn_route_entry(bgp, vpn, afi, safi, global_rn, attr, 1, 0, &ri, update_evpn_route_entry(bgp, vpn, afi, safi, global_rn, attr, 1, &ri,
0); 0, mac_mobility_seqnum(attr));
/* Schedule for processing and unlock node. */ /* Schedule for processing and unlock node. */
bgp_process(bgp, global_rn, afi, safi); bgp_process(bgp, global_rn, afi, safi);
@ -3485,7 +3449,8 @@ static int update_advertise_vni_routes(struct bgp *bgp, struct bgpevpn *vpn)
(struct prefix *)evp, &vpn->prd); (struct prefix *)evp, &vpn->prd);
assert(global_rn); assert(global_rn);
update_evpn_route_entry(bgp, vpn, afi, safi, global_rn, attr, 1, update_evpn_route_entry(bgp, vpn, afi, safi, global_rn, attr, 1,
0, &global_ri, 0); &global_ri, 0,
mac_mobility_seqnum(attr));
/* Schedule for processing and unlock node. */ /* Schedule for processing and unlock node. */
bgp_process(bgp, global_rn, afi, safi); bgp_process(bgp, global_rn, afi, safi);
@ -5213,7 +5178,7 @@ int bgp_evpn_local_macip_del(struct bgp *bgp, vni_t vni, struct ethaddr *mac,
* Handle add of a local MACIP. * Handle add of a local MACIP.
*/ */
int bgp_evpn_local_macip_add(struct bgp *bgp, vni_t vni, struct ethaddr *mac, int bgp_evpn_local_macip_add(struct bgp *bgp, vni_t vni, struct ethaddr *mac,
struct ipaddr *ip, uint8_t flags) struct ipaddr *ip, uint8_t flags, uint32_t seq)
{ {
struct bgpevpn *vpn; struct bgpevpn *vpn;
struct prefix_evpn p; struct prefix_evpn p;
@ -5228,7 +5193,7 @@ int bgp_evpn_local_macip_add(struct bgp *bgp, vni_t vni, struct ethaddr *mac,
/* Create EVPN type-2 route and schedule for processing. */ /* Create EVPN type-2 route and schedule for processing. */
build_evpn_type2_prefix(&p, mac, ip); build_evpn_type2_prefix(&p, mac, ip);
if (update_evpn_route(bgp, vpn, &p, flags)) { if (update_evpn_route(bgp, vpn, &p, flags, seq)) {
char buf[ETHER_ADDR_STRLEN]; char buf[ETHER_ADDR_STRLEN];
char buf2[INET6_ADDRSTRLEN]; char buf2[INET6_ADDRSTRLEN];
@ -5525,7 +5490,7 @@ int bgp_evpn_local_vni_add(struct bgp *bgp, vni_t vni,
/* Create EVPN type-3 route and schedule for processing. */ /* Create EVPN type-3 route and schedule for processing. */
build_evpn_type3_prefix(&p, vpn->originator_ip); build_evpn_type3_prefix(&p, vpn->originator_ip);
if (update_evpn_route(bgp, vpn, &p, 0)) { if (update_evpn_route(bgp, vpn, &p, 0, 0)) {
flog_err(BGP_ERR_EVPN_ROUTE_CREATE, flog_err(BGP_ERR_EVPN_ROUTE_CREATE,
"%u: Type3 route creation failure for VNI %u", "%u: Type3 route creation failure for VNI %u",
bgp->vrf_id, vni); bgp->vrf_id, vni);

View File

@ -132,7 +132,7 @@ extern int bgp_evpn_local_macip_del(struct bgp *bgp, vni_t vni,
struct ethaddr *mac, struct ipaddr *ip); struct ethaddr *mac, struct ipaddr *ip);
extern int bgp_evpn_local_macip_add(struct bgp *bgp, vni_t vni, extern int bgp_evpn_local_macip_add(struct bgp *bgp, vni_t vni,
struct ethaddr *mac, struct ipaddr *ip, struct ethaddr *mac, struct ipaddr *ip,
uint8_t flags); uint8_t flags, uint32_t seq);
extern int bgp_evpn_local_l3vni_add(vni_t vni, vrf_id_t vrf_id, extern int bgp_evpn_local_l3vni_add(vni_t vni, vrf_id_t vrf_id,
struct ethaddr *rmac, struct ethaddr *rmac,
struct in_addr originator_ip, int filter); struct in_addr originator_ip, int filter);

View File

@ -2380,7 +2380,8 @@ static int bgp_zebra_process_local_macip(int command, struct zclient *zclient,
int ipa_len; int ipa_len;
char buf[ETHER_ADDR_STRLEN]; char buf[ETHER_ADDR_STRLEN];
char buf1[INET6_ADDRSTRLEN]; char buf1[INET6_ADDRSTRLEN];
uint8_t flags; uint8_t flags = 0;
uint32_t seqnum = 0;
memset(&ip, 0, sizeof(ip)); memset(&ip, 0, sizeof(ip));
s = zclient->ibuf; s = zclient->ibuf;
@ -2401,20 +2402,24 @@ static int bgp_zebra_process_local_macip(int command, struct zclient *zclient,
(ipa_len == IPV4_MAX_BYTELEN) ? IPADDR_V4 : IPADDR_V6; (ipa_len == IPV4_MAX_BYTELEN) ? IPADDR_V4 : IPADDR_V6;
stream_get(&ip.ip.addr, s, ipa_len); stream_get(&ip.ip.addr, s, ipa_len);
} }
flags = stream_getc(s); if (command == ZEBRA_MACIP_ADD) {
flags = stream_getc(s);
seqnum = stream_getl(s);
}
bgp = bgp_lookup_by_vrf_id(vrf_id); bgp = bgp_lookup_by_vrf_id(vrf_id);
if (!bgp) if (!bgp)
return 0; return 0;
if (BGP_DEBUG(zebra, ZEBRA)) if (BGP_DEBUG(zebra, ZEBRA))
zlog_debug("%u:Recv MACIP %s flags 0x%x MAC %s IP %s VNI %u", zlog_debug("%u:Recv MACIP %s flags 0x%x MAC %s IP %s VNI %u seq %u",
vrf_id, (command == ZEBRA_MACIP_ADD) ? "Add" : "Del", vrf_id, (command == ZEBRA_MACIP_ADD) ? "Add" : "Del",
flags, prefix_mac2str(&mac, buf, sizeof(buf)), flags, prefix_mac2str(&mac, buf, sizeof(buf)),
ipaddr2str(&ip, buf1, sizeof(buf1)), vni); ipaddr2str(&ip, buf1, sizeof(buf1)), vni, seqnum);
if (command == ZEBRA_MACIP_ADD) if (command == ZEBRA_MACIP_ADD)
return bgp_evpn_local_macip_add(bgp, vni, &mac, &ip, flags); return bgp_evpn_local_macip_add(bgp, vni, &mac, &ip,
flags, seqnum);
else else
return bgp_evpn_local_macip_del(bgp, vni, &mac, &ip); return bgp_evpn_local_macip_del(bgp, vni, &mac, &ip);
} }

File diff suppressed because it is too large Load Diff

View File

@ -260,6 +260,10 @@ struct zebra_mac_t_ {
struct in_addr r_vtep_ip; struct in_addr r_vtep_ip;
} fwd_info; } fwd_info;
/* Mobility sequence numbers associated with this entry. */
uint32_t rem_seq;
uint32_t loc_seq;
/* List of neigh associated with this mac */ /* List of neigh associated with this mac */
struct list *neigh_list; struct list *neigh_list;
@ -338,6 +342,16 @@ struct zebra_neigh_t_ {
/* Remote VTEP IP - applicable only for remote neighbors. */ /* Remote VTEP IP - applicable only for remote neighbors. */
struct in_addr r_vtep_ip; struct in_addr r_vtep_ip;
/*
* Mobility sequence numbers associated with this entry. The rem_seq
* represents the sequence number from the client (BGP) for the most
* recent add or update of this entry while the loc_seq represents
* the sequence number informed (or to be informed) by zebra to BGP
* for this entry.
*/
uint32_t rem_seq;
uint32_t loc_seq;
/* list of hosts pointing to this remote NH entry */ /* list of hosts pointing to this remote NH entry */
struct host_rb_tree_entry host_rb; struct host_rb_tree_entry host_rb;
}; };