summaryrefslogtreecommitdiffstats
path: root/bgpd
diff options
context:
space:
mode:
authorSri Mohana Singamsetty <srimohans@gmail.com>2019-12-03 02:17:26 +0100
committerGitHub <noreply@github.com>2019-12-03 02:17:26 +0100
commitda579bf9ffc3ca0406d4d97f42446910a03f405e (patch)
tree3f6ff9bb793a77b844885d8dd6ee7edbaf65a718 /bgpd
parentMerge pull request #5450 from donaldsharp/rpki_node_issues (diff)
parentbgpd: Handle possible non-selection of local route (diff)
downloadfrr-da579bf9ffc3ca0406d4d97f42446910a03f405e.tar.xz
frr-da579bf9ffc3ca0406d4d97f42446910a03f405e.zip
Merge pull request #5432 from chiragshah6/evpn_dev2
bgpd: Handle possible non-selection of local route
Diffstat (limited to 'bgpd')
-rw-r--r--bgpd/bgp_evpn.c60
1 files changed, 41 insertions, 19 deletions
diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c
index d9d83335d..48b714c7d 100644
--- a/bgpd/bgp_evpn.c
+++ b/bgpd/bgp_evpn.c
@@ -1918,9 +1918,15 @@ static int update_evpn_route(struct bgp *bgp, struct bgpevpn *vpn,
/* lock ri to prevent freeing in evpn_route_select_install */
bgp_path_info_lock(pi);
- /* Perform route selection; this is just to set the flags correctly
- * as local route in the VNI always wins.
- */
+
+ /* Perform route selection. Normally, the local route in the
+ * VNI is expected to win and be the best route. However, if
+ * there is a race condition where a host moved from local to
+ * remote and the remote route was received in BGP just prior
+ * to the local MACIP notification from zebra, the remote
+ * route would win, and we should evict the defunct local route
+ * and (re)install the remote route into zebra.
+ */
evpn_route_select_install(bgp, vpn, rn);
/*
* If the new local route was not selected evict it and tell zebra
@@ -2207,24 +2213,40 @@ static int update_all_type2_routes(struct bgp *bgp, struct bgpevpn *vpn)
update_evpn_route_entry(bgp, vpn, afi, safi, rn, &attr, 0, &pi,
0, seq);
- /* Perform route selection; this is just to set the flags
- * correctly as local route in the VNI always wins.
+ /* lock ri to prevent freeing in evpn_route_select_install */
+ bgp_path_info_lock(pi);
+
+ /* Perform route selection. Normally, the local route in the
+ * VNI is expected to win and be the best route. However,
+ * under peculiar situations (e.g., tunnel (next hop) IP change
+ * that causes best selection to be based on next hop), a
+ * remote route could win. If the local route is the best,
+ * ensure it is updated in the global EVPN route table and
+ * advertised to peers; otherwise, ensure it is evicted and
+ * (re)install the remote route into zebra.
*/
evpn_route_select_install(bgp, vpn, rn);
-
- attr_new = pi->attr;
-
- /* Update route in global routing table. */
- rd_rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi,
- (struct prefix *)evp, &vpn->prd);
- assert(rd_rn);
- update_evpn_route_entry(bgp, vpn, afi, safi, rd_rn, attr_new, 0,
- &global_pi, 0,
- mac_mobility_seqnum(attr_new));
-
- /* Schedule for processing and unlock node. */
- bgp_process(bgp, rd_rn, afi, safi);
- bgp_unlock_node(rd_rn);
+ if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) {
+ evpn_cleanup_local_non_best_route(bgp, vpn, rn, pi);
+ /* unlock pi */
+ bgp_path_info_unlock(pi);
+ } else {
+ attr_new = pi->attr;
+ /* unlock pi */
+ bgp_path_info_unlock(pi);
+
+ /* Update route in global routing table. */
+ rd_rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi,
+ (struct prefix *)evp, &vpn->prd);
+ assert(rd_rn);
+ update_evpn_route_entry(bgp, vpn, afi, safi, rd_rn,
+ attr_new, 0, &global_pi, 0,
+ mac_mobility_seqnum(attr_new));
+
+ /* Schedule for processing and unlock node. */
+ bgp_process(bgp, rd_rn, afi, safi);
+ bgp_unlock_node(rd_rn);
+ }
/* Unintern temporary. */
aspath_unintern(&attr.aspath);