diff options
Diffstat (limited to 'bgpd/bgp_route.c')
| -rw-r--r-- | bgpd/bgp_route.c | 147 |
1 files changed, 103 insertions, 44 deletions
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 551547b7c0..429d1c8ac7 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -1064,7 +1064,32 @@ int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new, } } - /* Tie-breaker - AIGP (Metric TLV) attribute */ + /* 3. Local route check. We prefer: + * - BGP_ROUTE_STATIC + * - BGP_ROUTE_AGGREGATE + * - BGP_ROUTE_REDISTRIBUTE + */ + new_origin = !(new->sub_type == BGP_ROUTE_NORMAL || new->sub_type == BGP_ROUTE_IMPORTED); + exist_origin = !(exist->sub_type == BGP_ROUTE_NORMAL || + exist->sub_type == BGP_ROUTE_IMPORTED); + + if (new_origin && !exist_origin) { + *reason = bgp_path_selection_local_route; + if (debug) + zlog_debug("%s: %s wins over %s due to preferred BGP_ROUTE type", pfx_buf, + new_buf, exist_buf); + return 1; + } + + if (!new_origin && exist_origin) { + *reason = bgp_path_selection_local_route; + if (debug) + zlog_debug("%s: %s loses to %s due to preferred BGP_ROUTE type", pfx_buf, + new_buf, exist_buf); + return 0; + } + + /* 3.5. Tie-breaker - AIGP (Metric TLV) attribute */ if (CHECK_FLAG(newattr->flag, ATTR_FLAG_BIT(BGP_ATTR_AIGP)) && CHECK_FLAG(existattr->flag, ATTR_FLAG_BIT(BGP_ATTR_AIGP)) && CHECK_FLAG(bgp->flags, BGP_FLAG_COMPARE_AIGP)) { @@ -1094,34 +1119,6 @@ int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new, } } - /* 3. Local route check. We prefer: - * - BGP_ROUTE_STATIC - * - BGP_ROUTE_AGGREGATE - * - BGP_ROUTE_REDISTRIBUTE - */ - new_origin = !(new->sub_type == BGP_ROUTE_NORMAL || - new->sub_type == BGP_ROUTE_IMPORTED); - exist_origin = !(exist->sub_type == BGP_ROUTE_NORMAL || - exist->sub_type == BGP_ROUTE_IMPORTED); - - if (new_origin && !exist_origin) { - *reason = bgp_path_selection_local_route; - if (debug) - zlog_debug( - "%s: %s wins over %s due to preferred BGP_ROUTE type", - pfx_buf, new_buf, exist_buf); - return 1; - } - - if (!new_origin && exist_origin) { - *reason = bgp_path_selection_local_route; - if (debug) - zlog_debug( - "%s: %s loses to %s due to preferred BGP_ROUTE type", - pfx_buf, new_buf, exist_buf); - return 0; - } - /* Here if these are imported routes then get ultimate pi for * path compare. */ @@ -1133,9 +1130,9 @@ int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new, /* 4. AS path length check. */ if (!CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_IGNORE)) { int exist_hops = aspath_count_hops(existattr->aspath); - int exist_confeds = aspath_count_confeds(existattr->aspath); if (CHECK_FLAG(bgp->flags, BGP_FLAG_ASPATH_CONFED)) { + int exist_confeds = aspath_count_confeds(existattr->aspath); int aspath_hops; aspath_hops = aspath_count_hops(newattr->aspath); @@ -1779,14 +1776,13 @@ static bool bgp_community_filter(struct peer *peer, struct attr *attr) return true; /* NO_EXPORT check. */ - if (peer->sort == BGP_PEER_EBGP && - community_include(bgp_attr_get_community(attr), - COMMUNITY_NO_EXPORT)) + if (peer->sort == BGP_PEER_EBGP && peer->sub_sort != BGP_PEER_EBGP_OAD && + community_include(bgp_attr_get_community(attr), COMMUNITY_NO_EXPORT)) return true; /* NO_EXPORT_SUBCONFED check. */ - if (peer->sort == BGP_PEER_EBGP - || peer->sort == BGP_PEER_CONFED) + if ((peer->sort == BGP_PEER_EBGP && peer->sub_sort != BGP_PEER_EBGP_OAD) || + peer->sort == BGP_PEER_CONFED) if (community_include(bgp_attr_get_community(attr), COMMUNITY_NO_EXPORT_SUBCONFED)) return true; @@ -2821,6 +2817,65 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi, false)); } + /* + * Adjust AIGP for propagation when the nexthop is set to ourselves, + * e.g., using "set ip nexthop peer-address" or when advertising to + * EBGP. Note in route reflection the nexthop is usually unmodified + * and the AIGP should not be adjusted in that case. + */ + if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_AIGP)) && AIGP_TRANSMIT_ALLOWED(peer)) { + if (nh_reset || + CHECK_FLAG(attr->rmap_change_flags, BATTR_RMAP_NEXTHOP_PEER_ADDRESS)) { + uint64_t aigp = bgp_aigp_metric_total(pi); + + bgp_attr_set_aigp_metric(attr, aigp); + } + } + + /* Extended communities can be transitive and non-transitive. + * If the extended community is non-transitive, strip it off, + * unless it's a locally originated route (static, aggregate, + * redistributed, etc.). + */ + if (from->sort == BGP_PEER_EBGP && peer->sort == BGP_PEER_EBGP && + pi->sub_type == BGP_ROUTE_NORMAL) { + struct ecommunity *new_ecomm; + struct ecommunity *old_ecomm; + + old_ecomm = bgp_attr_get_ecommunity(attr); + if (old_ecomm) { + new_ecomm = ecommunity_dup(old_ecomm); + if (ecommunity_strip_non_transitive(new_ecomm)) { + bgp_attr_set_ecommunity(attr, new_ecomm); + if (!old_ecomm->refcnt) + ecommunity_free(&old_ecomm); + if (bgp_debug_update(NULL, p, subgrp->update_group, 0)) + zlog_debug("%pBP: %pFX stripped non-transitive extended communities", + peer, p); + } else { + ecommunity_free(&new_ecomm); + } + } + + /* Extended link-bandwidth communities are encoded as IPv6 + * address-specific extended communities. + */ + old_ecomm = bgp_attr_get_ipv6_ecommunity(attr); + if (old_ecomm) { + new_ecomm = ecommunity_dup(old_ecomm); + if (ecommunity_strip_non_transitive(new_ecomm)) { + bgp_attr_set_ipv6_ecommunity(attr, new_ecomm); + if (!old_ecomm->refcnt) + ecommunity_free(&old_ecomm); + if (bgp_debug_update(NULL, p, subgrp->update_group, 0)) + zlog_debug("%pBP: %pFX stripped non-transitive ipv6 extended communities", + peer, p); + } else { + ecommunity_free(&new_ecomm); + } + } + } + return true; } @@ -4618,10 +4673,12 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id, * will not be interned. In which case, it is ok to update the * attr->evpn_overlay, so that, this can be stored in adj_in. */ - if ((afi == AFI_L2VPN) && evpn) - bgp_attr_set_evpn_overlay(attr, evpn); - else - evpn_overlay_free(evpn); + if (evpn) { + if (afi == AFI_L2VPN) + bgp_attr_set_evpn_overlay(attr, evpn); + else + evpn_overlay_free(evpn); + } bgp_adj_in_set(dest, peer, attr, addpath_id, &bgp_labels); } @@ -4797,10 +4854,12 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id, * attr->evpn_overlay with evpn directly. Instead memcpy * evpn to new_atr.evpn_overlay before it is interned. */ - if (soft_reconfig && (afi == AFI_L2VPN) && evpn) - bgp_attr_set_evpn_overlay(&new_attr, evpn); - else - evpn_overlay_free(evpn); + if (soft_reconfig && evpn) { + if (afi == AFI_L2VPN) + bgp_attr_set_evpn_overlay(&new_attr, evpn); + else + evpn_overlay_free(evpn); + } /* Apply incoming route-map. * NB: new_attr may now contain newly allocated values from route-map @@ -12270,7 +12329,7 @@ void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp, mpls_lse_decode(dest->local_label, &label, &ttl, &exp, &bos); - has_valid_label = bgp_is_valid_label(&label); + has_valid_label = bgp_is_valid_label(&dest->local_label); if (safi == SAFI_EVPN) { if (!json) { |
