int is_bgp_static_route);
static void unregister_zebra_rnh(struct bgp_nexthop_cache *bnc,
int is_bgp_static_route);
-static void evaluate_paths(struct bgp_nexthop_cache *bnc);
static int make_prefix(int afi, struct bgp_path_info *pi, struct prefix *p);
static int bgp_nht_ifp_initial(struct thread *thread);
*/
int bgp_find_or_add_nexthop(struct bgp *bgp_route, struct bgp *bgp_nexthop,
afi_t afi, safi_t safi, struct bgp_path_info *pi,
- struct peer *peer, int connected)
+ struct peer *peer, int connected,
+ const struct prefix *orig_prefix)
{
struct bgp_nexthop_cache_head *tree = NULL;
struct bgp_nexthop_cache *bnc;
if (make_prefix(afi, pi, &p) < 0)
return 1;
+ if (!is_bgp_static_route && orig_prefix
+ && prefix_same(&p, orig_prefix)) {
+ if (BGP_DEBUG(nht, NHT)) {
+ zlog_debug(
+ "%s(%pFX): prefix loops through itself",
+ __func__, &p);
+ }
+ return 0;
+ }
+
srte_color = pi->attr->srte_color;
} else if (peer) {
/*
}
}
+ if (pi && is_route_parent_evpn(pi))
+ bnc->is_evpn_gwip_nexthop = true;
+
if (is_bgp_static_route) {
SET_FLAG(bnc->flags, BGP_STATIC_ROUTE);
return 1;
else if (safi == SAFI_UNICAST && pi
&& pi->sub_type == BGP_ROUTE_IMPORTED && pi->extra
- && pi->extra->num_labels) {
+ && pi->extra->num_labels && !bnc->is_evpn_gwip_nexthop) {
return bgp_isvalid_labeled_nexthop(bnc);
} else
return (bgp_isvalid_nexthop(bnc));
struct nexthop *nhlist_head = NULL;
struct nexthop *nhlist_tail = NULL;
int i;
+ bool evpn_resolved = false;
bnc->last_update = bgp_clock();
bnc->change_flags = 0;
if (!bnc->nexthop_num)
UNSET_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED);
- bnc->flags |= BGP_NEXTHOP_VALID;
+ if (!bnc->is_evpn_gwip_nexthop)
+ bnc->flags |= BGP_NEXTHOP_VALID;
bnc->metric = nhr->metric;
bnc->nexthop_num = nhr->nexthop_num;
}
bnc_nexthop_free(bnc);
bnc->nexthop = nhlist_head;
+
+ /*
+ * Gateway IP nexthop is L3 reachable. Mark it as
+ * BGP_NEXTHOP_VALID only if it is recursively resolved with a
+ * remote EVPN RT-2.
+ * Else, mark it as BGP_NEXTHOP_EVPN_INCOMPLETE.
+ * When its mapping with EVPN RT-2 is established, unset
+ * BGP_NEXTHOP_EVPN_INCOMPLETE and set BGP_NEXTHOP_VALID.
+ */
+ if (bnc->is_evpn_gwip_nexthop) {
+ evpn_resolved = bgp_evpn_is_gateway_ip_resolved(bnc);
+
+ if (BGP_DEBUG(nht, NHT)) {
+ char buf2[PREFIX2STR_BUFFER];
+
+ prefix2str(&bnc->prefix, buf2, sizeof(buf2));
+ zlog_debug(
+ "EVPN gateway IP %s recursive MAC/IP lookup %s",
+ buf2,
+ (evpn_resolved ? "successful"
+ : "failed"));
+ }
+
+ if (evpn_resolved) {
+ bnc->flags |= BGP_NEXTHOP_VALID;
+ bnc->flags &= ~BGP_NEXTHOP_EVPN_INCOMPLETE;
+ bnc->change_flags |= BGP_NEXTHOP_MACIP_CHANGED;
+ } else {
+ bnc->flags |= BGP_NEXTHOP_EVPN_INCOMPLETE;
+ bnc->flags &= ~BGP_NEXTHOP_VALID;
+ }
+ }
} else {
+ bnc->flags &= ~BGP_NEXTHOP_EVPN_INCOMPLETE;
bnc->flags &= ~BGP_NEXTHOP_VALID;
bnc->flags &= ~BGP_NEXTHOP_LABELED_VALID;
bnc->nexthop_num = nhr->nexthop_num;
UNSET_FLAG(bnc->flags, BGP_NEXTHOP_VALID);
UNSET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED);
UNSET_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED);
+ UNSET_FLAG(bnc->flags, BGP_NEXTHOP_EVPN_INCOMPLETE);
}
}
}
|| IN6_IS_ADDR_LINKLOCAL(
&pi->attr->mp_nexthop_global)))
p->u.prefix6 = pi->attr->mp_nexthop_local;
- else
+ /* If we receive MR_REACH with (GA)::(LL)
+ * then check for route-map to choose GA or LL
+ */
+ else if (pi->attr->mp_nexthop_len
+ == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
+ if (pi->attr->mp_nexthop_prefer_global)
+ p->u.prefix6 =
+ pi->attr->mp_nexthop_global;
+ else
+ p->u.prefix6 =
+ pi->attr->mp_nexthop_local;
+ } else
p->u.prefix6 = pi->attr->mp_nexthop_global;
p->prefixlen = IPV6_MAX_BITLEN;
}
* RETURNS:
* void.
*/
-static void evaluate_paths(struct bgp_nexthop_cache *bnc)
+void evaluate_paths(struct bgp_nexthop_cache *bnc)
{
struct bgp_dest *dest;
struct bgp_path_info *path;
bool bnc_is_valid_nexthop = false;
bool path_valid = false;
- if (safi == SAFI_UNICAST &&
- path->sub_type == BGP_ROUTE_IMPORTED &&
- path->extra &&
- path->extra->num_labels &&
- path->attr->evpn_overlay.type !=
- OVERLAY_INDEX_GATEWAY_IP) {
+ if (safi == SAFI_UNICAST && path->sub_type == BGP_ROUTE_IMPORTED
+ && path->extra && path->extra->num_labels
+ && (path->attr->evpn_overlay.type
+ != OVERLAY_INDEX_GATEWAY_IP)) {
bnc_is_valid_nexthop =
bgp_isvalid_labeled_nexthop(bnc) ? true : false;
} else {
|| path->attr->srte_color != 0)
SET_FLAG(path->flags, BGP_PATH_IGP_CHANGED);
- path_valid = !!CHECK_FLAG(path->flags, BGP_PATH_VALID);
+ path_valid = CHECK_FLAG(path->flags, BGP_PATH_VALID);
if (path_valid != bnc_is_valid_nexthop) {
if (path_valid) {
/* No longer valid, clear flag; also for EVPN