summaryrefslogtreecommitdiff
path: root/bgpd/bgp_route.c
diff options
context:
space:
mode:
Diffstat (limited to 'bgpd/bgp_route.c')
-rw-r--r--bgpd/bgp_route.c147
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) {