diff options
52 files changed, 919 insertions, 395 deletions
diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h index 5386f24a0b..164aa5ae79 100644 --- a/bgpd/bgp_attr.h +++ b/bgpd/bgp_attr.h @@ -517,9 +517,11 @@ static inline void bgp_attr_set_ecommunity(struct attr *attr, { attr->ecommunity = ecomm; - if (ecomm) + if (ecomm) { SET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)); - else + if (ecommunity_select_color(ecomm)) + SET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_SRTE_COLOR)); + } else UNSET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)); } diff --git a/bgpd/bgp_damp.c b/bgpd/bgp_damp.c index 80425ebe7a..6b6387b1b5 100644 --- a/bgpd/bgp_damp.c +++ b/bgpd/bgp_damp.c @@ -150,7 +150,7 @@ static void bgp_reuse_timer(struct event *t) bgp_aggregate_increment( bgp, bgp_dest_get_prefix(bdi->dest), bdi->path, bdi->afi, bdi->safi); - bgp_process(bgp, bdi->dest, bdi->afi, + bgp_process(bgp, bdi->dest, bdi->path, bdi->afi, bdi->safi); } @@ -306,8 +306,10 @@ void bgp_damp_info_free(struct bgp_damp_info *bdi, int withdraw, afi_t afi, bgp_path_info_unset_flag(bdi->dest, path, BGP_PATH_HISTORY | BGP_PATH_DAMPED); - if (bdi->lastrecord == BGP_RECORD_WITHDRAW && withdraw) + if (bdi->lastrecord == BGP_RECORD_WITHDRAW && withdraw) { bgp_path_info_delete(bdi->dest, path); + bgp_process(path->peer->bgp, bdi->dest, path, afi, safi); + } XFREE(MTYPE_BGP_DAMP_INFO, bdi); } diff --git a/bgpd/bgp_ecommunity.h b/bgpd/bgp_ecommunity.h index d20ad01c35..794c5a3975 100644 --- a/bgpd/bgp_ecommunity.h +++ b/bgpd/bgp_ecommunity.h @@ -52,10 +52,8 @@ * 0x0c Flow-spec Redirect to IPv4 - draft-ietf-idr-flowspec-redirect */ #define ECOMMUNITY_FLOWSPEC_REDIRECT_IPV4 0x0c -/* from draft-ietf-idr-flow-spec-v6-09 - * 0x0b Flow-spec Redirect to IPv6 - */ -#define ECOMMUNITY_FLOWSPEC_REDIRECT_IPV6 0x0b +/* RFC 8956 */ +#define ECOMMUNITY_FLOWSPEC_REDIRECT_IPV6 0x0d /* Low-order octet of the Extended Communities type field for EVPN types */ #define ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY 0x00 diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c index e142ff6a34..1c3b4e05c6 100644 --- a/bgpd/bgp_evpn.c +++ b/bgpd/bgp_evpn.c @@ -1429,7 +1429,7 @@ static void evpn_delete_old_local_route(struct bgp *bgp, struct bgpevpn *vpn, * this table. */ if (pi) - bgp_process(bgp, global_dest, afi, safi); + bgp_process(bgp, global_dest, pi, afi, safi); bgp_dest_unlock_node(global_dest); } @@ -1443,14 +1443,29 @@ static void evpn_delete_old_local_route(struct bgp *bgp, struct bgpevpn *vpn, * Note: vpn is NULL for local EAD-ES routes. */ int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn, - struct bgp_dest *dest) + struct bgp_dest *dest, struct bgp_path_info *pi) { - struct bgp_path_info *old_select, *new_select; + struct bgp_path_info *old_select, *new_select, *first; struct bgp_path_info_pair old_and_new; afi_t afi = AFI_L2VPN; safi_t safi = SAFI_EVPN; int ret = 0; + first = bgp_dest_get_bgp_path_info(dest); + SET_FLAG(pi->flags, BGP_PATH_UNSORTED); + if (pi != first) { + if (pi->next) + pi->next->prev = pi->prev; + if (pi->prev) + pi->prev->next = pi->next; + + if (first) + first->prev = pi; + pi->next = first; + pi->prev = NULL; + bgp_dest_set_bgp_path_info(dest, pi); + } + /* Compute the best path. */ bgp_best_selection(bgp, dest, &bgp->maxpaths[afi][safi], &old_and_new, afi, safi); @@ -1582,7 +1597,8 @@ static struct bgp_path_info *bgp_evpn_route_get_local_path( static int update_evpn_type5_route_entry(struct bgp *bgp_evpn, struct bgp *bgp_vrf, afi_t afi, safi_t safi, struct bgp_dest *dest, - struct attr *attr, int *route_changed) + struct attr *attr, int *route_changed, + struct bgp_path_info **entry) { struct attr *attr_new = NULL; struct bgp_path_info *pi = NULL; @@ -1620,8 +1636,8 @@ static int update_evpn_type5_route_entry(struct bgp *bgp_evpn, /* add the route entry to route node*/ bgp_path_info_add(dest, pi); + *entry = pi; } else { - tmp_pi = local_pi; if (!attrhash_cmp(tmp_pi->attr, attr)) { @@ -1643,6 +1659,7 @@ static int update_evpn_type5_route_entry(struct bgp *bgp_evpn, tmp_pi->attr = attr_new; tmp_pi->uptime = monotime(NULL); } + *entry = local_pi; } return 0; } @@ -1658,6 +1675,7 @@ static int update_evpn_type5_route(struct bgp *bgp_vrf, struct prefix_evpn *evp, struct bgp_dest *dest = NULL; struct bgp *bgp_evpn = NULL; int route_changed = 0; + struct bgp_path_info *pi = NULL; bgp_evpn = bgp_get_evpn(); if (!bgp_evpn) @@ -1739,11 +1757,11 @@ static int update_evpn_type5_route(struct bgp *bgp_vrf, struct prefix_evpn *evp, /* create or update the route entry within the route node */ update_evpn_type5_route_entry(bgp_evpn, bgp_vrf, afi, safi, dest, &attr, - &route_changed); + &route_changed, &pi); /* schedule for processing and unlock node */ if (route_changed) { - bgp_process(bgp_evpn, dest, afi, safi); + bgp_process(bgp_evpn, dest, pi, afi, safi); bgp_dest_unlock_node(dest); } @@ -2253,7 +2271,7 @@ static int update_evpn_route(struct bgp *bgp, struct bgpevpn *vpn, * 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, dest); + evpn_route_select_install(bgp, vpn, dest, pi); /* * If the new local route was not selected evict it and tell zebra * to re-add the best remote dest. BGP doesn't retain non-best local @@ -2309,7 +2327,7 @@ static int update_evpn_route(struct bgp *bgp, struct bgpevpn *vpn, false /* setup_sync */, NULL /* old_is_sync */); /* Schedule for processing and unlock node. */ - bgp_process(bgp, dest, afi, safi); + bgp_process(bgp, dest, global_pi, afi, safi); bgp_dest_unlock_node(dest); } @@ -2369,7 +2387,7 @@ static int delete_evpn_type5_route(struct bgp *bgp_vrf, struct prefix_evpn *evp) delete_evpn_route_entry(bgp_evpn, afi, safi, dest, &pi); if (pi) - bgp_process(bgp_evpn, dest, afi, safi); + bgp_process(bgp_evpn, dest, pi, afi, safi); bgp_dest_unlock_node(dest); return 0; } @@ -2409,7 +2427,7 @@ static int delete_evpn_route(struct bgp *bgp, struct bgpevpn *vpn, * this table. */ if (pi) - bgp_process(bgp, global_dest, afi, safi); + bgp_process(bgp, global_dest, pi, afi, safi); bgp_dest_unlock_node(global_dest); } @@ -2417,9 +2435,8 @@ static int delete_evpn_route(struct bgp *bgp, struct bgpevpn *vpn, */ delete_evpn_route_entry(bgp, afi, safi, dest, &pi); if (pi) { - dest = bgp_path_info_reap(dest, pi); - assert(dest); - evpn_route_select_install(bgp, vpn, dest); + bgp_path_info_delete(dest, pi); + evpn_route_select_install(bgp, vpn, dest, pi); } /* dest should still exist due to locking make coverity happy */ @@ -2533,7 +2550,7 @@ void bgp_evpn_update_type2_route_entry(struct bgp *bgp, struct bgpevpn *vpn, * advertised to peers; otherwise, ensure it is evicted and * (re)install the remote route into zebra. */ - evpn_route_select_install(bgp, vpn, dest); + evpn_route_select_install(bgp, vpn, dest, pi); if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) { route_change = 0; @@ -2581,7 +2598,7 @@ void bgp_evpn_update_type2_route_entry(struct bgp *bgp, struct bgpevpn *vpn, NULL /* old_is_sync */); /* Schedule for processing and unlock node. */ - bgp_process(bgp, global_dest, afi, safi); + bgp_process(bgp, global_dest, global_pi, afi, safi); bgp_dest_unlock_node(global_dest); } @@ -2666,7 +2683,7 @@ static void delete_global_type2_routes(struct bgp *bgp, struct bgpevpn *vpn) delete_evpn_route_entry(bgp, afi, safi, dest, &pi); if (pi) - bgp_process(bgp, dest, afi, safi); + bgp_process(bgp, dest, pi, afi, safi); } /* Unlock RD node. */ @@ -3135,7 +3152,7 @@ static int install_evpn_route_entry_in_vrf(struct bgp *bgp_vrf, safi); /* Perform route selection and update zebra, if required. */ - bgp_process(bgp_vrf, dest, afi, safi); + bgp_process(bgp_vrf, dest, pi, afi, safi); /* Process for route leaking. */ vpn_leak_from_vrf_update(bgp_get_default(), bgp_vrf, pi); @@ -3247,7 +3264,7 @@ static int install_evpn_route_entry_in_vni_common( bgp_evpn_remote_ip_hash_add(vpn, pi); /* Perform route selection and update zebra, if required. */ - ret = evpn_route_select_install(bgp, vpn, dest); + ret = evpn_route_select_install(bgp, vpn, dest, pi); /* if the best path is a local path with a non-zero ES * sync info against the local path may need to be updated @@ -3289,7 +3306,7 @@ static int uninstall_evpn_route_entry_in_vni_common( bgp_path_info_delete(dest, pi); /* Perform route selection and update zebra, if required. */ - ret = evpn_route_select_install(bgp, vpn, dest); + ret = evpn_route_select_install(bgp, vpn, dest, pi); /* if the best path is a local path with a non-zero ES * sync info against the local path may need to be updated @@ -3497,7 +3514,7 @@ static int uninstall_evpn_route_entry_in_vrf(struct bgp *bgp_vrf, bgp_evpn_path_nh_del(bgp_vrf, pi); /* Perform route selection and update zebra, if required. */ - bgp_process(bgp_vrf, dest, afi, safi); + bgp_process(bgp_vrf, dest, pi, afi, safi); /* Unlock route node. */ bgp_dest_unlock_node(dest); @@ -3862,7 +3879,7 @@ int bgp_evpn_route_entry_install_if_vrf_match(struct bgp *bgp_vrf, * Install or uninstall mac-ip routes are appropriate for this * particular VRF. */ -static int install_uninstall_routes_for_vrf(struct bgp *bgp_vrf, int install) +static int install_uninstall_routes_for_vrf(struct bgp *bgp_vrf, bool install) { afi_t afi; safi_t safi; @@ -3926,9 +3943,7 @@ static int install_uninstall_routes_for_vrf(struct bgp *bgp_vrf, int install) * particular VNI. */ static int install_uninstall_routes_for_vni(struct bgp *bgp, - struct bgpevpn *vpn, - bgp_evpn_route_type rtype, - int install) + struct bgpevpn *vpn, bool install) { afi_t afi; safi_t safi; @@ -3959,7 +3974,9 @@ static int install_uninstall_routes_for_vni(struct bgp *bgp, (const struct prefix_evpn *)bgp_dest_get_prefix( dest); - if (evp->prefix.route_type != rtype) + if (evp->prefix.route_type != BGP_EVPN_IMET_ROUTE && + evp->prefix.route_type != BGP_EVPN_AD_ROUTE && + evp->prefix.route_type != BGP_EVPN_MAC_IP_ROUTE) continue; for (pi = bgp_dest_get_bgp_path_info(dest); pi; @@ -3986,16 +4003,16 @@ static int install_uninstall_routes_for_vni(struct bgp *bgp, bgp, vpn, evp, pi); if (ret) { - flog_err( - EC_BGP_EVPN_FAIL, - "%u: Failed to %s EVPN %s route in VNI %u", - bgp->vrf_id, - install ? "install" - : "uninstall", - rtype == BGP_EVPN_MAC_IP_ROUTE - ? "MACIP" - : "IMET", - vpn->vni); + flog_err(EC_BGP_EVPN_FAIL, + "%u: Failed to %s EVPN %s route in VNI %u", + bgp->vrf_id, + install ? "install" + : "uninstall", + evp->prefix.route_type == + BGP_EVPN_MAC_IP_ROUTE + ? "MACIP" + : "IMET", + vpn->vni); bgp_dest_unlock_node(rd_dest); bgp_dest_unlock_node(dest); @@ -4013,7 +4030,7 @@ static int install_uninstall_routes_for_vni(struct bgp *bgp, */ static int install_routes_for_vrf(struct bgp *bgp_vrf) { - install_uninstall_routes_for_vrf(bgp_vrf, 1); + install_uninstall_routes_for_vrf(bgp_vrf, true); return 0; } @@ -4024,29 +4041,17 @@ static int install_routes_for_vrf(struct bgp *bgp_vrf) */ static int install_routes_for_vni(struct bgp *bgp, struct bgpevpn *vpn) { - int ret; - - /* Install type-3 routes followed by type-2 routes - the ones applicable + /* + * Install type-3 routes followed by type-2 routes - the ones applicable * for this VNI. */ - ret = install_uninstall_routes_for_vni(bgp, vpn, BGP_EVPN_IMET_ROUTE, - 1); - if (ret) - return ret; - - ret = install_uninstall_routes_for_vni(bgp, vpn, BGP_EVPN_AD_ROUTE, - 1); - if (ret) - return ret; - - return install_uninstall_routes_for_vni(bgp, vpn, BGP_EVPN_MAC_IP_ROUTE, - 1); + return install_uninstall_routes_for_vni(bgp, vpn, true); } /* uninstall routes from l3vni vrf. */ static int uninstall_routes_for_vrf(struct bgp *bgp_vrf) { - install_uninstall_routes_for_vrf(bgp_vrf, 0); + install_uninstall_routes_for_vrf(bgp_vrf, false); return 0; } @@ -4056,25 +4061,11 @@ static int uninstall_routes_for_vrf(struct bgp *bgp_vrf) */ static int uninstall_routes_for_vni(struct bgp *bgp, struct bgpevpn *vpn) { - int ret; - - /* Uninstall type-2 routes followed by type-3 routes - the ones - * applicable - * for this VNI. + /* + * Uninstall type-2 routes followed by type-3 routes - the ones + * applicable for this VNI. */ - ret = install_uninstall_routes_for_vni(bgp, vpn, BGP_EVPN_MAC_IP_ROUTE, - 0); - if (ret) - return ret; - - ret = install_uninstall_routes_for_vni(bgp, vpn, BGP_EVPN_AD_ROUTE, - 0); - if (ret) - return ret; - - - return install_uninstall_routes_for_vni(bgp, vpn, BGP_EVPN_IMET_ROUTE, - 0); + return install_uninstall_routes_for_vni(bgp, vpn, false); } /* @@ -4494,7 +4485,7 @@ static void update_advertise_vni_route(struct bgp *bgp, struct bgpevpn *vpn, } /* Schedule for processing and unlock node. */ - bgp_process(bgp, global_dest, afi, safi); + bgp_process(bgp, global_dest, global_pi, afi, safi); bgp_dest_unlock_node(global_dest); } @@ -4544,7 +4535,7 @@ static void update_advertise_vni_routes(struct bgp *bgp, struct bgpevpn *vpn) false /* setup_sync */, NULL /* old_is_sync */); /* Schedule for processing and unlock node. */ - bgp_process(bgp, global_dest, afi, safi); + bgp_process(bgp, global_dest, pi, afi, safi); bgp_dest_unlock_node(global_dest); } @@ -4589,7 +4580,7 @@ static int delete_withdraw_vni_routes(struct bgp *bgp, struct bgpevpn *vpn) * this table. */ if (pi) - bgp_process(bgp, global_dest, afi, safi); + bgp_process(bgp, global_dest, pi, afi, safi); bgp_dest_unlock_node(global_dest); } @@ -6499,9 +6490,10 @@ void bgp_filter_evpn_routes_upon_martian_change( for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) { + struct bgp_path_info *next; - for (pi = bgp_dest_get_bgp_path_info(dest); pi; - pi = pi->next) { + for (pi = bgp_dest_get_bgp_path_info(dest); + (pi != NULL) && (next = pi->next, 1); pi = next) { bool affected = false; const struct prefix *p; diff --git a/bgpd/bgp_evpn_mh.c b/bgpd/bgp_evpn_mh.c index 601b8e91ba..d63e011560 100644 --- a/bgpd/bgp_evpn_mh.c +++ b/bgpd/bgp_evpn_mh.c @@ -92,7 +92,8 @@ static void bgp_evpn_path_nh_unlink(struct bgp_path_evpn_nh_info *nh_info); */ static int bgp_evpn_es_route_select_install(struct bgp *bgp, struct bgp_evpn_es *es, - struct bgp_dest *dest) + struct bgp_dest *dest, + struct bgp_path_info *pi) { int ret = 0; int zret = 0; @@ -102,6 +103,8 @@ static int bgp_evpn_es_route_select_install(struct bgp *bgp, struct bgp_path_info *new_select; /* new best */ struct bgp_path_info_pair old_and_new; + SET_FLAG(pi->flags, BGP_PATH_UNSORTED); + /* Compute the best path. */ bgp_best_selection(bgp, dest, &bgp->maxpaths[afi][safi], &old_and_new, afi, safi); @@ -233,7 +236,7 @@ static int bgp_evpn_es_route_install(struct bgp *bgp, } /* Perform route selection and update zebra, if required. */ - ret = bgp_evpn_es_route_select_install(bgp, es, dest); + ret = bgp_evpn_es_route_select_install(bgp, es, dest, pi); bgp_dest_unlock_node(dest); @@ -274,7 +277,7 @@ static int bgp_evpn_es_route_uninstall(struct bgp *bgp, struct bgp_evpn_es *es, bgp_path_info_delete(dest, pi); /* Perform route selection and update zebra, if required. */ - ret = bgp_evpn_es_route_select_install(bgp, es, dest); + ret = bgp_evpn_es_route_select_install(bgp, es, dest, pi); /* Unlock route node. */ bgp_dest_unlock_node(dest); @@ -513,7 +516,7 @@ static int bgp_evpn_mh_route_delete(struct bgp *bgp, struct bgp_evpn_es *es, * this table. */ if (pi) - bgp_process(bgp, global_dest, afi, safi); + bgp_process(bgp, global_dest, pi, afi, safi); bgp_dest_unlock_node(global_dest); } @@ -564,7 +567,7 @@ int delete_global_ead_evi_routes(struct bgp *bgp, struct bgpevpn *vpn) delete_evpn_route_entry(bgp, afi, safi, bd, &pi); if (pi) - bgp_process(bgp, bd, afi, safi); + bgp_process(bgp, bd, pi, afi, safi); } } @@ -670,7 +673,7 @@ static int bgp_evpn_type4_route_update(struct bgp *bgp, * this is just to set the flags correctly * as local route in the ES always wins. */ - bgp_evpn_es_route_select_install(bgp, es, dest); + bgp_evpn_es_route_select_install(bgp, es, dest, pi); bgp_dest_unlock_node(dest); /* If this is a new route or some attribute has changed, export the @@ -688,7 +691,7 @@ static int bgp_evpn_type4_route_update(struct bgp *bgp, attr_new, &global_pi, &route_changed); /* Schedule for processing and unlock node. */ - bgp_process(bgp, dest, afi, safi); + bgp_process(bgp, dest, global_pi, afi, safi); bgp_dest_unlock_node(dest); } @@ -1010,7 +1013,7 @@ static int bgp_evpn_type1_route_update(struct bgp *bgp, struct bgp_evpn_es *es, * this is just to set the flags correctly as local route in * the ES always wins. */ - evpn_route_select_install(bgp, vpn, dest); + evpn_route_select_install(bgp, vpn, dest, pi); bgp_dest_unlock_node(dest); /* If this is a new route or some attribute has changed, export the @@ -1027,7 +1030,7 @@ static int bgp_evpn_type1_route_update(struct bgp *bgp, struct bgp_evpn_es *es, attr_new, &global_pi, &route_changed); /* Schedule for processing and unlock node. */ - bgp_process(bgp, dest, afi, safi); + bgp_process(bgp, dest, global_pi, afi, safi); bgp_dest_unlock_node(dest); } diff --git a/bgpd/bgp_evpn_private.h b/bgpd/bgp_evpn_private.h index 5af99afa34..07bba9b426 100644 --- a/bgpd/bgp_evpn_private.h +++ b/bgpd/bgp_evpn_private.h @@ -716,7 +716,8 @@ extern void delete_evpn_route_entry(struct bgp *bgp, afi_t afi, safi_t safi, struct bgp_path_info **pi); int vni_list_cmp(void *p1, void *p2); extern int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn, - struct bgp_dest *dest); + struct bgp_dest *dest, + struct bgp_path_info *pi); extern struct bgp_dest * bgp_evpn_global_node_get(struct bgp_table *table, afi_t afi, safi_t safi, const struct prefix_evpn *evp, struct prefix_rd *prd, diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c index a2d3172882..7866adbdcd 100644 --- a/bgpd/bgp_fsm.c +++ b/bgpd/bgp_fsm.c @@ -1796,6 +1796,22 @@ bgp_connect_fail(struct peer_connection *connection) return bgp_stop(connection); } +/* after connect is called(), getpeername is able to return + * port and address on non established streams + */ +static void bgp_connect_in_progress_update_connection(struct peer *peer) +{ + bgp_getsockname(peer); + if (!peer->su_remote && !BGP_CONNECTION_SU_UNSPEC(peer->connection)) { + /* if connect initiated, then dest port and dest addresses are well known */ + peer->su_remote = sockunion_dup(&peer->connection->su); + if (sockunion_family(peer->su_remote) == AF_INET) + peer->su_remote->sin.sin_port = htons(peer->port); + else if (sockunion_family(peer->su_remote) == AF_INET6) + peer->su_remote->sin6.sin6_port = htons(peer->port); + } +} + /* This function is the first starting point of all BGP connection. It * try to connect to remote peer with non-blocking IO. */ @@ -1892,6 +1908,8 @@ static enum bgp_fsm_state_progress bgp_start(struct peer_connection *connection) __func__, peer->connection->fd); return BGP_FSM_FAILURE; } + bgp_connect_in_progress_update_connection(peer); + /* * - when the socket becomes ready, poll() will signify POLLOUT * - if it fails to connect, poll() will signify POLLHUP diff --git a/bgpd/bgp_label.c b/bgpd/bgp_label.c index 7327ab5182..68104967b2 100644 --- a/bgpd/bgp_label.c +++ b/bgpd/bgp_label.c @@ -74,7 +74,7 @@ int bgp_parse_fec_update(void) bgp_set_valid_label(&dest->local_label); } SET_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED); - bgp_process(bgp, dest, afi, safi); + bgp_process(bgp, dest, NULL, afi, safi); bgp_dest_unlock_node(dest); return 1; } diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c index 985af84ea9..2404ceffb1 100644 --- a/bgpd/bgp_mplsvpn.c +++ b/bgpd/bgp_mplsvpn.c @@ -1208,7 +1208,7 @@ leak_update(struct bgp *to_bgp, struct bgp_dest *bn, /* Process change. */ bgp_aggregate_increment(to_bgp, p, bpi, afi, safi); - bgp_process(to_bgp, bn, afi, safi); + bgp_process(to_bgp, bn, bpi, afi, safi); if (debug) zlog_debug("%s: ->%s: %pBD Found route, changed attr", @@ -1270,7 +1270,7 @@ leak_update(struct bgp *to_bgp, struct bgp_dest *bn, bgp_aggregate_increment(to_bgp, p, new, afi, safi); bgp_path_info_add(bn, new); - bgp_process(to_bgp, bn, afi, safi); + bgp_process(to_bgp, bn, new, afi, safi); if (debug) zlog_debug("%s: ->%s: %pBD: Added new route", __func__, @@ -1956,7 +1956,7 @@ void vpn_leak_from_vrf_withdraw(struct bgp *to_bgp, /* to */ bgp_aggregate_decrement(to_bgp, p, bpi, afi, safi); bgp_path_info_delete(bn, bpi); - bgp_process(to_bgp, bn, afi, safi); + bgp_process(to_bgp, bn, bpi, afi, safi); } bgp_dest_unlock_node(bn); } @@ -1976,7 +1976,7 @@ void vpn_leak_from_vrf_withdraw_all(struct bgp *to_bgp, struct bgp *from_bgp, struct bgp_table *table; struct bgp_dest *bn; - struct bgp_path_info *bpi; + struct bgp_path_info *bpi, *next; /* This is the per-RD table of prefixes */ table = bgp_dest_get_bgp_table_info(pdest); @@ -1991,7 +1991,8 @@ void vpn_leak_from_vrf_withdraw_all(struct bgp *to_bgp, struct bgp *from_bgp, __func__, bn); } - for (; bpi; bpi = bpi->next) { + for (; (bpi != NULL) && (next = bpi->next, 1); + bpi = next) { if (debug) zlog_debug("%s: type %d, sub_type %d", __func__, bpi->type, @@ -2012,7 +2013,7 @@ void vpn_leak_from_vrf_withdraw_all(struct bgp *to_bgp, struct bgp *from_bgp, to_bgp, bgp_dest_get_prefix(bn), bpi, afi, safi); bgp_path_info_delete(bn, bpi); - bgp_process(to_bgp, bn, afi, safi); + bgp_process(to_bgp, bn, bpi, afi, safi); bgp_mplsvpn_path_nh_label_unlink( bpi->extra->vrfleak->parent); } @@ -2506,7 +2507,7 @@ void vpn_leak_to_vrf_withdraw(struct bgp_path_info *path_vpn) bpi); bgp_aggregate_decrement(bgp, p, bpi, afi, safi); bgp_path_info_delete(bn, bpi); - bgp_process(bgp, bn, afi, safi); + bgp_process(bgp, bn, bpi, afi, safi); } bgp_dest_unlock_node(bn); } @@ -2515,7 +2516,7 @@ void vpn_leak_to_vrf_withdraw(struct bgp_path_info *path_vpn) void vpn_leak_to_vrf_withdraw_all(struct bgp *to_bgp, afi_t afi) { struct bgp_dest *bn; - struct bgp_path_info *bpi; + struct bgp_path_info *bpi, *next; safi_t safi = SAFI_UNICAST; int debug = BGP_DEBUG(vpn, VPN_LEAK_TO_VRF); @@ -2526,9 +2527,8 @@ void vpn_leak_to_vrf_withdraw_all(struct bgp *to_bgp, afi_t afi) */ for (bn = bgp_table_top(to_bgp->rib[afi][safi]); bn; bn = bgp_route_next(bn)) { - - for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; - bpi = bpi->next) { + for (bpi = bgp_dest_get_bgp_path_info(bn); + (bpi != NULL) && (next = bpi->next, 1); bpi = next) { if (bpi->extra && bpi->extra->vrfleak && bpi->extra->vrfleak->bgp_orig != to_bgp && bpi->extra->vrfleak->parent && @@ -2538,7 +2538,7 @@ void vpn_leak_to_vrf_withdraw_all(struct bgp *to_bgp, afi_t afi) bgp_dest_get_prefix(bn), bpi, afi, safi); bgp_path_info_delete(bn, bpi); - bgp_process(to_bgp, bn, afi, safi); + bgp_process(to_bgp, bn, bpi, afi, safi); } } } @@ -2567,8 +2567,11 @@ void vpn_leak_no_retain(struct bgp *to_bgp, struct bgp *vpn_from, afi_t afi) continue; for (bn = bgp_table_top(table); bn; bn = bgp_route_next(bn)) { - for (bpi = bgp_dest_get_bgp_path_info(bn); bpi; - bpi = bpi->next) { + struct bgp_path_info *next; + + for (bpi = bgp_dest_get_bgp_path_info(bn); + (bpi != NULL) && (next = bpi->next, 1); + bpi = next) { if (bpi->extra && bpi->extra->vrfleak && bpi->extra->vrfleak->bgp_orig == to_bgp) continue; @@ -4189,7 +4192,7 @@ static int bgp_mplsvpn_nh_label_bind_get_local_label_cb(mpls_label_t label, if (!table) continue; SET_FLAG(pi->net->flags, BGP_NODE_LABEL_CHANGED); - bgp_process(table->bgp, pi->net, table->afi, table->safi); + bgp_process(table->bgp, pi->net, pi, table->afi, table->safi); } return 0; diff --git a/bgpd/bgp_network.c b/bgpd/bgp_network.c index dbb34b048f..b409cbe706 100644 --- a/bgpd/bgp_network.c +++ b/bgpd/bgp_network.c @@ -875,11 +875,7 @@ int bgp_getsockname(struct peer *peer) } peer->su_local = sockunion_getsockname(peer->connection->fd); - if (!peer->su_local) - return -1; peer->su_remote = sockunion_getpeername(peer->connection->fd); - if (!peer->su_remote) - return -1; if (!bgp_zebra_nexthop_set(peer->su_local, peer->su_remote, &peer->nexthop, peer)) { diff --git a/bgpd/bgp_nht.c b/bgpd/bgp_nht.c index 20a285b9d9..80ec9bcf77 100644 --- a/bgpd/bgp_nht.c +++ b/bgpd/bgp_nht.c @@ -1435,7 +1435,7 @@ void evaluate_paths(struct bgp_nexthop_cache *bnc) } } - bgp_process(bgp_path, dest, afi, safi); + bgp_process(bgp_path, dest, path, afi, safi); } if (peer) { diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index e2b1687e99..848e8ffd8d 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -114,6 +114,46 @@ static const struct message bgp_pmsi_tnltype_str[] = { #define VRFID_NONE_STR "-" #define SOFT_RECONFIG_TASK_MAX_PREFIX 25000 +static inline char *bgp_route_dump_path_info_flags(struct bgp_path_info *pi, + char *buf, size_t len) +{ + uint32_t flags = pi->flags; + + if (flags == 0) { + snprintfrr(buf, len, "None "); + return buf; + } + + snprintfrr(buf, len, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", + CHECK_FLAG(flags, BGP_PATH_IGP_CHANGED) ? "IGP Changed " : "", + CHECK_FLAG(flags, BGP_PATH_DAMPED) ? "Damped" : "", + CHECK_FLAG(flags, BGP_PATH_HISTORY) ? "History " : "", + CHECK_FLAG(flags, BGP_PATH_SELECTED) ? "Selected " : "", + CHECK_FLAG(flags, BGP_PATH_VALID) ? "Valid " : "", + CHECK_FLAG(flags, BGP_PATH_ATTR_CHANGED) ? "Attr Changed " + : "", + CHECK_FLAG(flags, BGP_PATH_DMED_CHECK) ? "Dmed Check " : "", + CHECK_FLAG(flags, BGP_PATH_DMED_SELECTED) ? "Dmed Selected " + : "", + CHECK_FLAG(flags, BGP_PATH_STALE) ? "Stale " : "", + CHECK_FLAG(flags, BGP_PATH_REMOVED) ? "Removed " : "", + CHECK_FLAG(flags, BGP_PATH_COUNTED) ? "Counted " : "", + CHECK_FLAG(flags, BGP_PATH_MULTIPATH) ? "Mpath " : "", + CHECK_FLAG(flags, BGP_PATH_MULTIPATH_CHG) ? "Mpath Chg " : "", + CHECK_FLAG(flags, BGP_PATH_RIB_ATTR_CHG) ? "Rib Chg " : "", + CHECK_FLAG(flags, BGP_PATH_ANNC_NH_SELF) ? "NH Self " : "", + CHECK_FLAG(flags, BGP_PATH_LINK_BW_CHG) ? "LinkBW Chg " : "", + CHECK_FLAG(flags, BGP_PATH_ACCEPT_OWN) ? "Accept Own " : "", + CHECK_FLAG(flags, BGP_PATH_MPLSVPN_LABEL_NH) ? "MPLS Label " + : "", + CHECK_FLAG(flags, BGP_PATH_MPLSVPN_NH_LABEL_BIND) + ? "MPLS Label Bind " + : "", + CHECK_FLAG(flags, BGP_PATH_UNSORTED) ? "Unsorted " : ""); + + return buf; +} + DEFINE_HOOK(bgp_process, (struct bgp * bgp, afi_t afi, safi_t safi, struct bgp_dest *bn, struct peer *peer, bool withdraw), @@ -442,6 +482,7 @@ void bgp_path_info_add_with_caller(const char *name, struct bgp_dest *dest, top->prev = pi; bgp_dest_set_bgp_path_info(dest, pi); + SET_FLAG(pi->flags, BGP_PATH_UNSORTED); bgp_path_info_lock(pi); bgp_dest_lock_node(dest); peer_lock(pi->peer); /* bgp_path_info peer reference */ @@ -462,8 +503,26 @@ struct bgp_dest *bgp_path_info_reap(struct bgp_dest *dest, bgp_dest_set_bgp_path_info(dest, pi->next); bgp_path_info_mpath_dequeue(pi); + + pi->next = NULL; + pi->prev = NULL; + + hook_call(bgp_snmp_update_stats, dest, pi, false); + bgp_path_info_unlock(pi); + return bgp_dest_unlock_node(dest); +} + +static struct bgp_dest *bgp_path_info_reap_unsorted(struct bgp_dest *dest, + struct bgp_path_info *pi) +{ + bgp_path_info_mpath_dequeue(pi); + + pi->next = NULL; + pi->prev = NULL; + hook_call(bgp_snmp_update_stats, dest, pi, false); + bgp_path_info_unlock(pi); return bgp_dest_unlock_node(dest); } @@ -553,6 +612,15 @@ void bgp_path_info_unset_flag(struct bgp_dest *dest, struct bgp_path_info *pi, bgp_pcount_adjust(dest, pi); } +static bool use_bgp_med_value(struct attr *attr, struct bgp *bgp) +{ + if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC) || + CHECK_FLAG(bgp->flags, BGP_FLAG_MED_MISSING_AS_WORST)) + return true; + + return false; +} + /* Get MED value. If MED value is missing and "bgp bestpath missing-as-worst" is specified, treat it as the worst value. */ static uint32_t bgp_med_value(struct attr *attr, struct bgp *bgp) @@ -679,12 +747,18 @@ int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new, } if (debug) { + char buf1[256], buf2[256]; + bpi_ultimate = bgp_get_imported_bpi_ultimate(exist); bgp_path_info_path_with_addpath_rx_str(bpi_ultimate, exist_buf, sizeof(exist_buf)); - zlog_debug("%s(%s): Comparing %s flags 0x%x with %s flags 0x%x", - pfx_buf, bgp->name_pretty, new_buf, new->flags, - exist_buf, exist->flags); + zlog_debug("%s(%s): Comparing %s flags %s with %s flags %s", + pfx_buf, bgp->name_pretty, new_buf, + bgp_route_dump_path_info_flags(new, buf1, + sizeof(buf1)), + exist_buf, + bgp_route_dump_path_info_flags(exist, buf2, + sizeof(buf2))); } newattr = new->attr; @@ -2736,17 +2810,18 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest, struct bgp_path_info_pair *result, afi_t afi, safi_t safi) { - struct bgp_path_info *new_select; - struct bgp_path_info *old_select; + struct bgp_path_info *new_select, *look_thru; + struct bgp_path_info *old_select, *worse, *first; struct bgp_path_info *pi; struct bgp_path_info *pi1; struct bgp_path_info *pi2; - struct bgp_path_info *nextpi = NULL; int paths_eq, do_mpath; - bool debug; + bool debug, any_comparisons; struct list mp_list; char pfx_buf[PREFIX2STR_BUFFER] = {}; char path_buf[PATH_ADDPATH_STR_BUFFER]; + enum bgp_path_selection_reason reason = bgp_path_selection_none; + bool unsorted_items = true; bgp_mp_list_init(&mp_list); do_mpath = @@ -2757,16 +2832,16 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest, if (debug) prefix2str(bgp_dest_get_prefix(dest), pfx_buf, sizeof(pfx_buf)); - dest->reason = bgp_path_selection_none; /* bgp deterministic-med */ new_select = NULL; if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)) { - /* Clear BGP_PATH_DMED_SELECTED for all paths */ for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1; - pi1 = pi1->next) + pi1 = pi1->next) { bgp_path_info_unset_flag(dest, pi1, BGP_PATH_DMED_SELECTED); + UNSET_FLAG(pi1->flags, BGP_PATH_DMED_CHECK); + } for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1; pi1 = pi1->next) { @@ -2829,68 +2904,273 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest, } } - /* Check old selected route and new selected route. */ + /* + * Let's grab the unsorted items from the list + */ + struct bgp_path_info *unsorted_list = NULL; + struct bgp_path_info *unsorted_list_spot = NULL; + struct bgp_path_info *unsorted_holddown = NULL; + old_select = NULL; - new_select = NULL; - for (pi = bgp_dest_get_bgp_path_info(dest); - (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) { - enum bgp_path_selection_reason reason; + pi = bgp_dest_get_bgp_path_info(dest); + while (pi && CHECK_FLAG(pi->flags, BGP_PATH_UNSORTED)) { + struct bgp_path_info *next = pi->next; if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) old_select = pi; - if (BGP_PATH_HOLDDOWN(pi)) { - /* reap REMOVED routes, if needs be + /* + * Pull off pi off the list + */ + if (pi->next) + pi->next->prev = NULL; + + bgp_dest_set_bgp_path_info(dest, pi->next); + pi->next = NULL; + pi->prev = NULL; + + /* + * Place it on the unsorted list + */ + if (unsorted_list_spot) { + unsorted_list_spot->next = pi; + pi->prev = unsorted_list_spot; + pi->next = NULL; + } else { + unsorted_list = pi; + + pi->next = NULL; + pi->prev = NULL; + } + + unsorted_list_spot = pi; + pi = next; + } + + if (!old_select) { + old_select = bgp_dest_get_bgp_path_info(dest); + if (old_select && + !CHECK_FLAG(old_select->flags, BGP_PATH_SELECTED)) + old_select = NULL; + } + + if (!unsorted_list) + unsorted_items = true; + else + unsorted_items = false; + + any_comparisons = false; + worse = NULL; + while (unsorted_list) { + first = unsorted_list; + unsorted_list = unsorted_list->next; + + if (unsorted_list) + unsorted_list->prev = NULL; + first->next = NULL; + first->prev = NULL; + + /* + * It's not likely that the just received unsorted entry + * is in holddown and scheduled for removal but we should + * check + */ + if (BGP_PATH_HOLDDOWN(first)) { + /* + * reap REMOVED routes, if needs be * selected route must stay for a while longer though */ if (debug) - zlog_debug( - "%s: %pBD(%s) pi from %s in holddown", - __func__, dest, bgp->name_pretty, - pi->peer->host); + zlog_debug("%s: %pBD(%s) pi %p from %s in holddown", + __func__, dest, bgp->name_pretty, + first, first->peer->host); - if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED) && - (pi != old_select)) { - dest = bgp_path_info_reap(dest, pi); + if (old_select != first && + CHECK_FLAG(first->flags, BGP_PATH_REMOVED)) { + dest = bgp_path_info_reap_unsorted(dest, first); assert(dest); - } + } else { + /* + * We are in hold down, so we cannot sort this + * item yet. Let's wait, so hold the unsorted + * to the side + */ + if (unsorted_holddown) { + first->next = unsorted_holddown; + unsorted_holddown->prev = first; + unsorted_holddown = first; + } else + unsorted_holddown = first; + UNSET_FLAG(first->flags, BGP_PATH_UNSORTED); + } continue; } - if (pi->peer && pi->peer != bgp->peer_self - && !CHECK_FLAG(pi->peer->sflags, PEER_STATUS_NSF_WAIT)) - if (!peer_established(pi->peer->connection)) { + bgp_path_info_unset_flag(dest, first, BGP_PATH_DMED_CHECK); + + worse = NULL; + + struct bgp_path_info *look_thru_next; + + for (look_thru = bgp_dest_get_bgp_path_info(dest); look_thru; + look_thru = look_thru_next) { + /* look thru can be reaped save the next pointer */ + look_thru_next = look_thru->next; + + /* + * Now we have the first unsorted and the best selected + * Let's do best path comparison + */ + if (BGP_PATH_HOLDDOWN(look_thru)) { + /* reap REMOVED routes, if needs be + * selected route must stay for a while longer though + */ if (debug) - zlog_debug( - "%s: %pBD(%s) non self peer %s not estab state", - __func__, dest, - bgp->name_pretty, - pi->peer->host); + zlog_debug("%s: %pBD(%s) pi from %s %p in holddown", + __func__, dest, + bgp->name_pretty, + look_thru->peer->host, + look_thru); + + if (CHECK_FLAG(look_thru->flags, + BGP_PATH_REMOVED) && + (look_thru != old_select)) { + dest = bgp_path_info_reap(dest, + look_thru); + assert(dest); + } continue; } - bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK); + if (look_thru->peer && + look_thru->peer != bgp->peer_self && + !CHECK_FLAG(look_thru->peer->sflags, + PEER_STATUS_NSF_WAIT)) + if (!peer_established( + look_thru->peer->connection)) { + if (debug) + zlog_debug("%s: %pBD(%s) non self peer %s not estab state", + __func__, dest, + bgp->name_pretty, + look_thru->peer->host); - if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED) && - (!CHECK_FLAG(pi->flags, BGP_PATH_DMED_SELECTED))) { - if (debug) - zlog_debug("%s: %pBD(%s) pi %s dmed", __func__, - dest, bgp->name_pretty, - pi->peer->host); - continue; + continue; + } + + bgp_path_info_unset_flag(dest, look_thru, + BGP_PATH_DMED_CHECK); + if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED) && + (!CHECK_FLAG(look_thru->flags, + BGP_PATH_DMED_SELECTED))) { + bgp_path_info_unset_flag(dest, look_thru, + BGP_PATH_DMED_CHECK); + if (debug) + zlog_debug("%s: %pBD(%s) pi %s dmed", + __func__, dest, + bgp->name_pretty, + look_thru->peer->host); + + worse = look_thru; + continue; + } + + reason = dest->reason; + any_comparisons = true; + if (bgp_path_info_cmp(bgp, first, look_thru, &paths_eq, + mpath_cfg, debug, pfx_buf, afi, + safi, &reason)) { + first->reason = reason; + worse = look_thru; + /* + * We can stop looking + */ + break; + } + + look_thru->reason = reason; } - reason = dest->reason; - if (bgp_path_info_cmp(bgp, pi, new_select, &paths_eq, mpath_cfg, - debug, pfx_buf, afi, safi, - &dest->reason)) { - if (new_select == NULL && - reason != bgp_path_selection_none) - dest->reason = reason; - new_select = pi; + if (!any_comparisons) + first->reason = bgp_path_selection_first; + + /* + * At this point worse if NON-NULL is where the first + * pointer should be before. if worse is NULL then + * first is bestpath too. Let's remove first from the + * list and place it in the right spot + */ + + if (!worse) { + struct bgp_path_info *end = + bgp_dest_get_bgp_path_info(dest); + + for (; end && end->next != NULL; end = end->next) + ; + + if (end) + end->next = first; + else + bgp_dest_set_bgp_path_info(dest, first); + first->prev = end; + first->next = NULL; + + dest->reason = first->reason; + } else { + if (worse->prev) + worse->prev->next = first; + first->next = worse; + if (worse) { + first->prev = worse->prev; + worse->prev = first; + } else + first->prev = NULL; + + if (dest->info == worse) { + bgp_dest_set_bgp_path_info(dest, first); + dest->reason = first->reason; + } } + UNSET_FLAG(first->flags, BGP_PATH_UNSORTED); + } + + if (!unsorted_items) { + new_select = bgp_dest_get_bgp_path_info(dest); + while (new_select && BGP_PATH_HOLDDOWN(new_select)) + new_select = new_select->next; + + if (new_select) { + if (new_select->reason == bgp_path_selection_none) + new_select->reason = bgp_path_selection_first; + else if (new_select == bgp_dest_get_bgp_path_info(dest) && + new_select->next == NULL) + new_select->reason = bgp_path_selection_first; + dest->reason = new_select->reason; + } else + dest->reason = bgp_path_selection_none; + } else + new_select = old_select; + + + /* + * Reinsert all the unsorted_holddown items for future processing + * at the end of the list. + */ + if (unsorted_holddown) { + struct bgp_path_info *top = bgp_dest_get_bgp_path_info(dest); + struct bgp_path_info *prev = NULL; + + while (top != NULL) { + prev = top; + top = top->next; + } + + if (prev) { + prev->next = unsorted_holddown; + unsorted_holddown->prev = prev; + } else + bgp_dest_set_bgp_path_info(dest, unsorted_holddown); } /* Now that we know which path is the bestpath see if any of the other @@ -3339,7 +3619,9 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest, return; } +#ifdef ENABLE_BGP_VNC const struct prefix *p = bgp_dest_get_prefix(dest); +#endif debug = bgp_debug_bestpath(dest); if (debug) @@ -3464,7 +3746,8 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest, bgp_path_info_unset_flag(dest, old_select, BGP_PATH_SELECTED); if (new_select) { if (debug) - zlog_debug("%s: setting SELECTED flag", __func__); + zlog_debug("%s: %pBD setting SELECTED flag", __func__, + dest); bgp_path_info_set_flag(dest, new_select, BGP_PATH_SELECTED); bgp_path_info_unset_flag(dest, new_select, BGP_PATH_ATTR_CHANGED); @@ -3689,13 +3972,38 @@ static struct bgp_process_queue *bgp_processq_alloc(struct bgp *bgp) return pqnode; } -void bgp_process(struct bgp *bgp, struct bgp_dest *dest, afi_t afi, safi_t safi) +void bgp_process(struct bgp *bgp, struct bgp_dest *dest, + struct bgp_path_info *pi, afi_t afi, safi_t safi) { #define ARBITRARY_PROCESS_QLEN 10000 struct work_queue *wq = bgp->process_queue; struct bgp_process_queue *pqnode; int pqnode_reuse = 0; + /* + * Indicate that *this* pi is in an unsorted + * situation, even if the node is already + * scheduled. + */ + if (pi) { + struct bgp_path_info *first = bgp_dest_get_bgp_path_info(dest); + + SET_FLAG(pi->flags, BGP_PATH_UNSORTED); + + if (pi != first) { + if (pi->next) + pi->next->prev = pi->prev; + if (pi->prev) + pi->prev->next = pi->next; + + if (first) + first->prev = pi; + pi->next = first; + pi->prev = NULL; + bgp_dest_set_bgp_path_info(dest, pi); + } + } + /* already scheduled for processing? */ if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED)) return; @@ -3944,7 +4252,7 @@ void bgp_rib_remove(struct bgp_dest *dest, struct bgp_path_info *pi, } hook_call(bgp_process, peer->bgp, afi, safi, dest, peer, true); - bgp_process(peer->bgp, dest, afi, safi); + bgp_process(peer->bgp, dest, pi, afi, safi); } static void bgp_rib_withdraw(struct bgp_dest *dest, struct bgp_path_info *pi, @@ -4550,7 +4858,7 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id, != BGP_DAMP_SUPPRESSED) { bgp_aggregate_increment(bgp, p, pi, afi, safi); - bgp_process(bgp, dest, afi, safi); + bgp_process(bgp, dest, pi, afi, safi); } } else /* Duplicate - odd */ { @@ -4578,7 +4886,7 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id, bgp_path_info_unset_flag( dest, pi, BGP_PATH_STALE); bgp_dest_set_defer_flag(dest, false); - bgp_process(bgp, dest, afi, safi); + bgp_process(bgp, dest, pi, afi, safi); } } @@ -4868,7 +5176,7 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id, /* Process change. */ bgp_aggregate_increment(bgp, p, pi, afi, safi); - bgp_process(bgp, dest, afi, safi); + bgp_process(bgp, dest, pi, afi, safi); bgp_dest_unlock_node(dest); if (SAFI_UNICAST == safi @@ -5013,7 +5321,7 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id, hook_call(bgp_process, bgp, afi, safi, dest, peer, false); /* Process change. */ - bgp_process(bgp, dest, afi, safi); + bgp_process(bgp, dest, new, afi, safi); if (SAFI_UNICAST == safi && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF @@ -5584,7 +5892,7 @@ static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data) struct bgp_clear_node_queue *cnq = data; struct bgp_dest *dest = cnq->dest; struct peer *peer = wq->spec.data; - struct bgp_path_info *pi; + struct bgp_path_info *pi, *next; struct bgp *bgp; afi_t afi = bgp_dest_table(dest)->afi; safi_t safi = bgp_dest_table(dest)->safi; @@ -5595,7 +5903,8 @@ static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data) /* It is possible that we have multiple paths for a prefix from a peer * if that peer is using AddPath. */ - for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) { + for (pi = bgp_dest_get_bgp_path_info(dest); + (pi != NULL) && (next = pi->next, 1); pi = next) { if (pi->peer != peer) continue; @@ -5857,7 +6166,7 @@ void bgp_clear_adj_in(struct peer *peer, afi_t afi, safi_t safi) void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi) { struct bgp_dest *dest; - struct bgp_path_info *pi; + struct bgp_path_info *pi, *next; struct bgp_table *table; if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) { @@ -5872,8 +6181,9 @@ void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi) for (rm = bgp_table_top(table); rm; rm = bgp_route_next(rm)) - for (pi = bgp_dest_get_bgp_path_info(rm); pi; - pi = pi->next) { + for (pi = bgp_dest_get_bgp_path_info(rm); + (pi != NULL) && (next = pi->next, 1); + pi = next) { if (pi->peer != peer) continue; if (CHECK_FLAG( @@ -5906,8 +6216,8 @@ void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi) } else { for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest; dest = bgp_route_next(dest)) - for (pi = bgp_dest_get_bgp_path_info(dest); pi; - pi = pi->next) { + for (pi = bgp_dest_get_bgp_path_info(dest); + (pi != NULL) && (next = pi->next, 1); pi = next) { if (pi->peer != peer) continue; if (CHECK_FLAG(peer->af_sflags[afi][safi], @@ -6520,7 +6830,7 @@ void bgp_static_update(struct bgp *bgp, const struct prefix *p, /* Process change. */ bgp_aggregate_increment(bgp, p, pi, afi, safi); - bgp_process(bgp, dest, afi, safi); + bgp_process(bgp, dest, pi, afi, safi); if (SAFI_MPLS_VPN == safi && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) { @@ -6578,7 +6888,7 @@ void bgp_static_update(struct bgp *bgp, const struct prefix *p, bgp_dest_unlock_node(dest); /* Process change. */ - bgp_process(bgp, dest, afi, safi); + bgp_process(bgp, dest, new, afi, safi); if (SAFI_UNICAST == safi && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF || @@ -6617,6 +6927,7 @@ void bgp_static_withdraw(struct bgp *bgp, const struct prefix *p, afi_t afi, /* Withdraw static BGP route from routing table. */ if (pi) { + SET_FLAG(pi->flags, BGP_PATH_UNSORTED); #ifdef ENABLE_BGP_VNC if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP) rfapiProcessWithdraw(pi->peer, NULL, p, prd, pi->attr, @@ -6635,7 +6946,7 @@ void bgp_static_withdraw(struct bgp *bgp, const struct prefix *p, afi_t afi, bgp_aggregate_decrement(bgp, p, pi, afi, safi); bgp_unlink_nexthop(pi); bgp_path_info_delete(dest, pi); - bgp_process(bgp, dest, afi, safi); + bgp_process(bgp, dest, pi, afi, safi); } /* Unlock bgp_node_lookup. */ @@ -7036,7 +7347,7 @@ static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi, safi); bgp_unlink_nexthop(pi); bgp_path_info_delete(dest, pi); - bgp_process(bgp, dest, afi, safi); + bgp_process(bgp, dest, pi, afi, safi); } } } @@ -7399,8 +7710,10 @@ static void bgp_aggregate_install( /* * Mark the old as unusable */ - if (pi) + if (pi) { bgp_path_info_delete(dest, pi); + bgp_process(bgp, dest, pi, afi, safi); + } attr = bgp_attr_aggregate_intern( bgp, origin, aspath, community, ecommunity, lcommunity, @@ -7425,7 +7738,7 @@ static void bgp_aggregate_install( SET_FLAG(new->flags, BGP_PATH_VALID); bgp_path_info_add(dest, new); - bgp_process(bgp, dest, afi, safi); + bgp_process(bgp, dest, new, afi, safi); } else { uninstall_aggregate_route: for (pi = orig; pi; pi = pi->next) @@ -7437,7 +7750,7 @@ static void bgp_aggregate_install( /* Withdraw static BGP route from routing table. */ if (pi) { bgp_path_info_delete(dest, pi); - bgp_process(bgp, dest, afi, safi); + bgp_process(bgp, dest, pi, afi, safi); } } @@ -7523,7 +7836,6 @@ void bgp_aggregate_toggle_suppressed(struct bgp_aggregate *aggregate, const struct prefix *dest_p; struct bgp_dest *dest, *top; struct bgp_path_info *pi; - bool toggle_suppression; /* We've found a different MED we must revert any suppressed routes. */ top = bgp_node_get(table, p); @@ -7533,7 +7845,6 @@ void bgp_aggregate_toggle_suppressed(struct bgp_aggregate *aggregate, if (dest_p->prefixlen <= p->prefixlen) continue; - toggle_suppression = false; for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) { if (BGP_PATH_HOLDDOWN(pi)) continue; @@ -7544,17 +7855,14 @@ void bgp_aggregate_toggle_suppressed(struct bgp_aggregate *aggregate, if (suppress) { /* Suppress route if not suppressed already. */ if (aggr_suppress_path(aggregate, pi)) - toggle_suppression = true; + bgp_process(bgp, dest, pi, afi, safi); continue; } /* Install route if there is no more suppression. */ if (aggr_unsuppress_path(aggregate, pi)) - toggle_suppression = true; + bgp_process(bgp, dest, pi, afi, safi); } - - if (toggle_suppression) - bgp_process(bgp, dest, afi, safi); } bgp_dest_unlock_node(top); } @@ -7613,7 +7921,6 @@ bool bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi, struct ecommunity *ecommunity = NULL; struct lcommunity *lcommunity = NULL; struct bgp_path_info *pi; - unsigned long match = 0; uint8_t atomic_aggregate = 0; /* If the bgp instance is being deleted or self peer is deleted @@ -7663,8 +7970,6 @@ bool bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi, if (!bgp_check_advertise(bgp, dest, safi)) continue; - match = 0; - for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) { if (BGP_PATH_HOLDDOWN(pi)) continue; @@ -7688,7 +7993,7 @@ bool bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi, if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate)) { if (aggr_suppress_path(aggregate, pi)) - match++; + bgp_process(bgp, dest, pi, afi, safi); } /* @@ -7704,7 +8009,7 @@ bool bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi, && AGGREGATE_MED_VALID(aggregate) && aggr_suppress_map_test(bgp, aggregate, pi)) { if (aggr_suppress_path(aggregate, pi)) - match++; + bgp_process(bgp, dest, pi, afi, safi); } aggregate->count++; @@ -7765,8 +8070,6 @@ bool bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi, aggregate, bgp_attr_get_lcommunity(pi->attr)); } - if (match) - bgp_process(bgp, dest, afi, safi); } if (aggregate->as_set) { bgp_compute_aggregate_aspath_val(aggregate); @@ -7826,7 +8129,6 @@ void bgp_aggregate_delete(struct bgp *bgp, const struct prefix *p, afi_t afi, struct bgp_dest *top; struct bgp_dest *dest; struct bgp_path_info *pi; - unsigned long match; table = bgp->rib[afi][safi]; @@ -7838,7 +8140,6 @@ void bgp_aggregate_delete(struct bgp *bgp, const struct prefix *p, afi_t afi, if (dest_p->prefixlen <= p->prefixlen) continue; - match = 0; for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) { if (BGP_PATH_HOLDDOWN(pi)) @@ -7856,10 +8157,11 @@ void bgp_aggregate_delete(struct bgp *bgp, const struct prefix *p, afi_t afi, if (pi->extra && pi->extra->aggr_suppressors && listcount(pi->extra->aggr_suppressors)) { if (aggr_unsuppress_path(aggregate, pi)) - match++; + bgp_process(bgp, dest, pi, afi, safi); } - aggregate->count--; + if (aggregate->count > 0) + aggregate->count--; if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE) aggregate->incomplete_origin_count--; @@ -7898,10 +8200,6 @@ void bgp_aggregate_delete(struct bgp *bgp, const struct prefix *p, afi_t afi, pi->attr)); } } - - /* If this node was suppressed, process the change. */ - if (match) - bgp_process(bgp, dest, afi, safi); } if (aggregate->as_set) { aspath_free(aggregate->aspath); @@ -8050,7 +8348,6 @@ static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi, struct community *community = NULL; struct ecommunity *ecommunity = NULL; struct lcommunity *lcommunity = NULL; - unsigned long match = 0; /* If the bgp instance is being deleted or self peer is deleted * then do not create aggregate route @@ -8067,12 +8364,12 @@ static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi, if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate)) if (aggr_unsuppress_path(aggregate, pi)) - match++; + bgp_process(bgp, pi->net, pi, afi, safi); if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate) && aggr_suppress_map_test(bgp, aggregate, pi)) if (aggr_unsuppress_path(aggregate, pi)) - match++; + bgp_process(bgp, pi->net, pi, afi, safi); /* * This must be called after `summary`, `suppress-map` check to avoid @@ -8114,10 +8411,6 @@ static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi, aggregate, bgp_attr_get_lcommunity(pi->attr)); } - /* If this node was suppressed, process the change. */ - if (match) - bgp_process(bgp, pi->net, afi, safi); - origin = BGP_ORIGIN_IGP; if (aggregate->incomplete_origin_count > 0) origin = BGP_ORIGIN_INCOMPLETE; @@ -8727,7 +9020,7 @@ void bgp_redistribute_add(struct bgp *bgp, struct prefix *p, /* Process change. */ bgp_aggregate_increment(bgp, p, bpi, afi, SAFI_UNICAST); - bgp_process(bgp, bn, afi, SAFI_UNICAST); + bgp_process(bgp, bn, bpi, afi, SAFI_UNICAST); bgp_dest_unlock_node(bn); aspath_unintern(&attr.aspath); @@ -8750,7 +9043,7 @@ void bgp_redistribute_add(struct bgp *bgp, struct prefix *p, bgp_path_info_add(bn, new); bgp_dest_unlock_node(bn); SET_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED); - bgp_process(bgp, bn, afi, SAFI_UNICAST); + bgp_process(bgp, bn, new, afi, SAFI_UNICAST); if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF) || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) { @@ -8791,7 +9084,7 @@ void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, uint8_t type, } bgp_aggregate_decrement(bgp, p, pi, afi, SAFI_UNICAST); bgp_path_info_delete(dest, pi); - bgp_process(bgp, dest, afi, SAFI_UNICAST); + bgp_process(bgp, dest, pi, afi, SAFI_UNICAST); } bgp_dest_unlock_node(dest); } @@ -8825,7 +9118,7 @@ void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type, bgp_path_info_delete(dest, pi); if (!CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS)) - bgp_process(bgp, dest, afi, SAFI_UNICAST); + bgp_process(bgp, dest, pi, afi, SAFI_UNICAST); else { dest = bgp_path_info_reap(dest, pi); assert(dest); @@ -8971,6 +9264,9 @@ static void route_vty_short_status_out(struct vty *vty, if (path->extra && bgp_path_suppressed(path)) json_object_boolean_true_add(json_path, "suppressed"); + if (CHECK_FLAG(path->flags, BGP_PATH_UNSORTED)) + json_object_boolean_true_add(json_path, "unsorted"); + if (CHECK_FLAG(path->flags, BGP_PATH_VALID) && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) json_object_boolean_true_add(json_path, "valid"); @@ -9033,6 +9329,8 @@ static void route_vty_short_status_out(struct vty *vty, /* Selected */ if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) vty_out(vty, "h"); + else if (CHECK_FLAG(path->flags, BGP_PATH_UNSORTED)) + vty_out(vty, "u"); else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) vty_out(vty, "d"); else if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) @@ -9405,14 +9703,16 @@ void route_vty_out(struct vty *vty, const struct prefix *p, } /* MED/Metric */ - if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) + if (use_bgp_med_value(attr, path->peer->bgp)) { + uint32_t value = bgp_med_value(attr, path->peer->bgp); + if (json_paths) - json_object_int_add(json_path, "metric", attr->med); + json_object_int_add(json_path, "metric", value); else if (wide) - vty_out(vty, "%7u", attr->med); + vty_out(vty, "%7u", value); else - vty_out(vty, "%10u", attr->med); - else if (!json_paths) { + vty_out(vty, "%10u", value); + } else if (!json_paths) { if (wide) vty_out(vty, "%*s", 7, " "); else @@ -9533,7 +9833,7 @@ void route_vty_out(struct vty *vty, const struct prefix *p, } /* called from terminal list command */ -void route_vty_out_tmp(struct vty *vty, struct bgp_dest *dest, +void route_vty_out_tmp(struct vty *vty, struct bgp *bgp, struct bgp_dest *dest, const struct prefix *p, struct attr *attr, safi_t safi, bool use_json, json_object *json_ar, bool wide) { @@ -9592,10 +9892,11 @@ void route_vty_out_tmp(struct vty *vty, struct bgp_dest *dest, &attr->mp_nexthop_global_in); } - if (attr->flag - & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) - json_object_int_add(json_net, "metric", - attr->med); + if (use_bgp_med_value(attr, bgp)) { + uint32_t value = bgp_med_value(attr, bgp); + + json_object_int_add(json_net, "metric", value); + } if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) json_object_int_add(json_net, "locPrf", @@ -9635,13 +9936,15 @@ void route_vty_out_tmp(struct vty *vty, struct bgp_dest *dest, else vty_out(vty, "%*s", len, " "); } - if (attr->flag - & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) + + if (use_bgp_med_value(attr, bgp)) { + uint32_t value = bgp_med_value(attr, bgp); + if (wide) - vty_out(vty, "%7u", attr->med); + vty_out(vty, "%7u", value); else - vty_out(vty, "%10u", attr->med); - else if (wide) + vty_out(vty, "%10u", value); + } else if (wide) vty_out(vty, " "); else vty_out(vty, " "); @@ -10638,11 +10941,13 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn, vty_out(vty, " Origin %s", bgp_origin_long_str[attr->origin]); - if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) { + if (use_bgp_med_value(attr, bgp)) { + uint32_t value = bgp_med_value(attr, bgp); + if (json_paths) - json_object_int_add(json_path, "metric", attr->med); + json_object_int_add(json_path, "metric", value); else - vty_out(vty, ", metric %u", attr->med); + vty_out(vty, ", metric %u", value); } if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) { @@ -13673,21 +13978,23 @@ enum bgp_pcounts { PCOUNT_COUNTED, PCOUNT_BPATH_SELECTED, PCOUNT_PFCNT, /* the figure we display to users */ + PCOUNT_UNSORTED, PCOUNT_MAX, }; static const char *const pcount_strs[] = { - [PCOUNT_ADJ_IN] = "Adj-in", - [PCOUNT_DAMPED] = "Damped", - [PCOUNT_REMOVED] = "Removed", - [PCOUNT_HISTORY] = "History", - [PCOUNT_STALE] = "Stale", - [PCOUNT_VALID] = "Valid", - [PCOUNT_ALL] = "All RIB", - [PCOUNT_COUNTED] = "PfxCt counted", - [PCOUNT_BPATH_SELECTED] = "PfxCt Best Selected", - [PCOUNT_PFCNT] = "Useable", - [PCOUNT_MAX] = NULL, + [PCOUNT_ADJ_IN] = "Adj-in", + [PCOUNT_DAMPED] = "Damped", + [PCOUNT_REMOVED] = "Removed", + [PCOUNT_HISTORY] = "History", + [PCOUNT_STALE] = "Stale", + [PCOUNT_VALID] = "Valid", + [PCOUNT_ALL] = "All RIB", + [PCOUNT_COUNTED] = "PfxCt counted", + [PCOUNT_BPATH_SELECTED] = "PfxCt Best Selected", + [PCOUNT_PFCNT] = "Useable", + [PCOUNT_UNSORTED] = "Unsorted", + [PCOUNT_MAX] = NULL, }; struct peer_pcounts { @@ -13728,6 +14035,8 @@ static void bgp_peer_count_proc(struct bgp_dest *rn, struct peer_pcounts *pc) pc->count[PCOUNT_PFCNT]++; if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) pc->count[PCOUNT_BPATH_SELECTED]++; + if (CHECK_FLAG(pi->flags, BGP_PATH_UNSORTED)) + pc->count[PCOUNT_UNSORTED]++; if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) { pc->count[PCOUNT_COUNTED]++; @@ -14286,7 +14595,7 @@ show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table, json_ar, json_net, "%pFX", rn_p); } else - route_vty_out_tmp(vty, dest, rn_p, + route_vty_out_tmp(vty, bgp, dest, rn_p, &attr, safi, use_json, json_ar, wide); bgp_attr_flush(&attr); @@ -14349,11 +14658,15 @@ show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table, "%pFX", rn_p); } else - route_vty_out_tmp( - vty, dest, rn_p, - &attr, safi, - use_json, - json_ar, wide); + route_vty_out_tmp(vty, + bgp, + dest, + rn_p, + &attr, + safi, + use_json, + json_ar, + wide); (*output_count)++; } else { (*filtered_count)++; @@ -14391,9 +14704,10 @@ show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table, json_ar, json_net, "%pFX", rn_p); } else - route_vty_out_tmp( - vty, dest, rn_p, pi->attr, safi, - use_json, json_ar, wide); + route_vty_out_tmp(vty, bgp, dest, rn_p, + pi->attr, safi, + use_json, json_ar, + wide); (*output_count)++; } } diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h index 9be3f063f3..25fc327a17 100644 --- a/bgpd/bgp_route.h +++ b/bgpd/bgp_route.h @@ -59,7 +59,7 @@ enum bgp_show_adj_route_type { #define BGP_SHOW_SCODE_HEADER \ "Status codes: s suppressed, d damped, " \ - "h history, * valid, > best, = multipath,\n" \ + "h history, u unsorted, * valid, > best, = multipath,\n" \ " i internal, r RIB-failure, S Stale, R Removed\n" #define BGP_SHOW_OCODE_HEADER \ "Origin codes: i - IGP, e - EGP, ? - incomplete\n" @@ -327,6 +327,7 @@ struct bgp_path_info { #define BGP_PATH_ACCEPT_OWN (1 << 16) #define BGP_PATH_MPLSVPN_LABEL_NH (1 << 17) #define BGP_PATH_MPLSVPN_NH_LABEL_BIND (1 << 18) +#define BGP_PATH_UNSORTED (1 << 19) /* BGP route type. This can be static, RIP, OSPF, BGP etc. */ uint8_t type; @@ -345,6 +346,8 @@ struct bgp_path_info { unsigned short instance; + enum bgp_path_selection_reason reason; + /* Addpath identifiers */ uint32_t addpath_rx_id; struct bgp_addpath_info_data tx_addpath; @@ -801,7 +804,8 @@ extern void bgp_withdraw(struct peer *peer, const struct prefix *p, struct bgp_route_evpn *evpn); /* for bgp_nexthop and bgp_damp */ -extern void bgp_process(struct bgp *, struct bgp_dest *, afi_t, safi_t); +extern void bgp_process(struct bgp *bgp, struct bgp_dest *dest, + struct bgp_path_info *pi, afi_t afi, safi_t safi); /* * Add an end-of-initial-update marker to the process queue. This is just a @@ -845,10 +849,10 @@ extern void route_vty_out(struct vty *vty, const struct prefix *p, extern void route_vty_out_tag(struct vty *vty, const struct prefix *p, struct bgp_path_info *path, int display, safi_t safi, json_object *json); -extern void route_vty_out_tmp(struct vty *vty, struct bgp_dest *dest, - const struct prefix *p, struct attr *attr, - safi_t safi, bool use_json, json_object *json_ar, - bool wide); +extern void route_vty_out_tmp(struct vty *vty, struct bgp *bgp, + struct bgp_dest *dest, const struct prefix *p, + struct attr *attr, safi_t safi, bool use_json, + json_object *json_ar, bool wide); extern void route_vty_out_overlay(struct vty *vty, const struct prefix *p, struct bgp_path_info *path, int display, json_object *json); diff --git a/bgpd/bgp_updgrp_adv.c b/bgpd/bgp_updgrp_adv.c index 5d7a8b2ba1..0a852c75de 100644 --- a/bgpd/bgp_updgrp_adv.c +++ b/bgpd/bgp_updgrp_adv.c @@ -328,15 +328,16 @@ static void subgrp_show_adjq_vty(struct update_subgroup *subgrp, } if ((flags & UPDWALK_FLAGS_ADVQUEUE) && adj->adv && adj->adv->baa) { - route_vty_out_tmp( - vty, dest, dest_p, adj->adv->baa->attr, - SUBGRP_SAFI(subgrp), 0, NULL, false); + route_vty_out_tmp(vty, bgp, dest, dest_p, + adj->adv->baa->attr, + SUBGRP_SAFI(subgrp), 0, NULL, + false); output_count++; } if ((flags & UPDWALK_FLAGS_ADVERTISED) && adj->attr) { - route_vty_out_tmp(vty, dest, dest_p, adj->attr, - SUBGRP_SAFI(subgrp), 0, NULL, - false); + route_vty_out_tmp(vty, bgp, dest, dest_p, + adj->attr, SUBGRP_SAFI(subgrp), + 0, NULL, false); output_count++; } } diff --git a/bgpd/bgp_vpn.c b/bgpd/bgp_vpn.c index 8fe24ebe20..2470fb8844 100644 --- a/bgpd/bgp_vpn.c +++ b/bgpd/bgp_vpn.c @@ -191,7 +191,7 @@ int show_adj_route_vpn(struct vty *vty, struct peer *peer, } rd_header = 0; } - route_vty_out_tmp(vty, rm, bgp_dest_get_prefix(rm), + route_vty_out_tmp(vty, bgp, rm, bgp_dest_get_prefix(rm), attr, safi, use_json, json_routes, false); output_count++; diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index bcd029dcad..9faba65a58 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -3035,14 +3035,17 @@ DEFUN (bgp_graceful_restart, VTY_DECLVAR_CONTEXT(bgp, bgp); ret = bgp_gr_update_all(bgp, GLOBAL_GR_CMD); - - VTY_BGP_GR_ROUTER_DETECT_AND_SEND_CAPABILITY_TO_ZEBRA(bgp, bgp->peer, - ret); + if (ret == BGP_GR_SUCCESS) { + VTY_BGP_GR_ROUTER_DETECT_AND_SEND_CAPABILITY_TO_ZEBRA(bgp, + bgp->peer, + ret); + vty_out(vty, + "Graceful restart configuration changed, reset all peers to take effect\n"); + } if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART)) zlog_debug("[BGP_GR] bgp_graceful_restart_cmd : END "); - vty_out(vty, - "Graceful restart configuration changed, reset all peers to take effect\n"); + return bgp_vty_return(vty, ret); } @@ -3062,14 +3065,16 @@ DEFUN (no_bgp_graceful_restart, int ret = BGP_GR_FAILURE; ret = bgp_gr_update_all(bgp, NO_GLOBAL_GR_CMD); - - VTY_BGP_GR_ROUTER_DETECT_AND_SEND_CAPABILITY_TO_ZEBRA(bgp, bgp->peer, - ret); + if (ret == BGP_GR_SUCCESS) { + VTY_BGP_GR_ROUTER_DETECT_AND_SEND_CAPABILITY_TO_ZEBRA(bgp, + bgp->peer, + ret); + vty_out(vty, + "Graceful restart configuration changed, reset all peers to take effect\n"); + } if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART)) zlog_debug("[BGP_GR] no_bgp_graceful_restart_cmd : END "); - vty_out(vty, - "Graceful restart configuration changed, reset all peers to take effect\n"); return bgp_vty_return(vty, ret); } @@ -3277,24 +3282,25 @@ DEFUN (bgp_graceful_restart_disable, VTY_DECLVAR_CONTEXT(bgp, bgp); ret = bgp_gr_update_all(bgp, GLOBAL_DISABLE_CMD); + if (ret == BGP_GR_SUCCESS) { + VTY_BGP_GR_ROUTER_DETECT_AND_SEND_CAPABILITY_TO_ZEBRA(bgp, + bgp->peer, + ret); + vty_out(vty, + "Graceful restart configuration changed, reset all peers to take effect\n"); - VTY_BGP_GR_ROUTER_DETECT_AND_SEND_CAPABILITY_TO_ZEBRA(bgp, - bgp->peer, ret); + for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { + bgp_capability_send(peer, AFI_IP, SAFI_UNICAST, + CAPABILITY_CODE_RESTART, + CAPABILITY_ACTION_UNSET); + bgp_capability_send(peer, AFI_IP, SAFI_UNICAST, + CAPABILITY_CODE_LLGR, + CAPABILITY_ACTION_UNSET); + } + } if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART)) - zlog_debug( - "[BGP_GR] bgp_graceful_restart_disable_cmd : END "); - vty_out(vty, - "Graceful restart configuration changed, reset all peers to take effect\n"); - - for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) { - bgp_capability_send(peer, AFI_IP, SAFI_UNICAST, - CAPABILITY_CODE_RESTART, - CAPABILITY_ACTION_UNSET); - bgp_capability_send(peer, AFI_IP, SAFI_UNICAST, - CAPABILITY_CODE_LLGR, - CAPABILITY_ACTION_UNSET); - } + zlog_debug("[BGP_GR] bgp_graceful_restart_disable_cmd : END "); return bgp_vty_return(vty, ret); } @@ -3316,15 +3322,17 @@ DEFUN (no_bgp_graceful_restart_disable, int ret = BGP_GR_FAILURE; ret = bgp_gr_update_all(bgp, NO_GLOBAL_DISABLE_CMD); - - VTY_BGP_GR_ROUTER_DETECT_AND_SEND_CAPABILITY_TO_ZEBRA(bgp, bgp->peer, - ret); + if (ret == BGP_GR_SUCCESS) { + VTY_BGP_GR_ROUTER_DETECT_AND_SEND_CAPABILITY_TO_ZEBRA(bgp, + bgp->peer, + ret); + vty_out(vty, + "Graceful restart configuration changed, reset all peers to take effect\n"); + } if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART)) zlog_debug( "[BGP_GR] no_bgp_graceful_restart_disable_cmd : END "); - vty_out(vty, - "Graceful restart configuration changed, reset all peers to take effect\n"); return bgp_vty_return(vty, ret); } @@ -3352,15 +3360,16 @@ DEFUN (bgp_neighbor_graceful_restart_set, return CMD_WARNING_CONFIG_FAILED; ret = bgp_neighbor_graceful_restart(peer, PEER_GR_CMD); - - VTY_BGP_GR_ROUTER_DETECT(bgp, peer, peer->bgp->peer); - VTY_SEND_BGP_GR_CAPABILITY_TO_ZEBRA(peer->bgp, ret); + if (ret == BGP_GR_SUCCESS) { + VTY_BGP_GR_ROUTER_DETECT(bgp, peer, peer->bgp->peer); + VTY_SEND_BGP_GR_CAPABILITY_TO_ZEBRA(peer->bgp, ret); + vty_out(vty, + "Graceful restart configuration changed, reset this peer to take effect\n"); + } if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART)) zlog_debug( "[BGP_GR] bgp_neighbor_graceful_restart_set_cmd : END "); - vty_out(vty, - "Graceful restart configuration changed, reset this peer to take effect\n"); return bgp_vty_return(vty, ret); } @@ -3389,15 +3398,16 @@ DEFUN (no_bgp_neighbor_graceful_restart, "[BGP_GR] no_bgp_neighbor_graceful_restart_set_cmd : START "); ret = bgp_neighbor_graceful_restart(peer, NO_PEER_GR_CMD); - - VTY_BGP_GR_ROUTER_DETECT(bgp, peer, peer->bgp->peer); - VTY_SEND_BGP_GR_CAPABILITY_TO_ZEBRA(peer->bgp, ret); + if (ret == BGP_GR_SUCCESS) { + VTY_BGP_GR_ROUTER_DETECT(bgp, peer, peer->bgp->peer); + VTY_SEND_BGP_GR_CAPABILITY_TO_ZEBRA(peer->bgp, ret); + vty_out(vty, + "Graceful restart configuration changed, reset this peer to take effect\n"); + } if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART)) zlog_debug( "[BGP_GR] no_bgp_neighbor_graceful_restart_set_cmd : END "); - vty_out(vty, - "Graceful restart configuration changed, reset this peer to take effect\n"); return bgp_vty_return(vty, ret); } @@ -3427,15 +3437,16 @@ DEFUN (bgp_neighbor_graceful_restart_helper_set, ret = bgp_neighbor_graceful_restart(peer, PEER_HELPER_CMD); - - VTY_BGP_GR_ROUTER_DETECT(bgp, peer, peer->bgp->peer); - VTY_SEND_BGP_GR_CAPABILITY_TO_ZEBRA(peer->bgp, ret); + if (ret == BGP_GR_SUCCESS) { + VTY_BGP_GR_ROUTER_DETECT(bgp, peer, peer->bgp->peer); + VTY_SEND_BGP_GR_CAPABILITY_TO_ZEBRA(peer->bgp, ret); + vty_out(vty, + "Graceful restart configuration changed, reset this peer to take effect\n"); + } if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART)) zlog_debug( "[BGP_GR] bgp_neighbor_graceful_restart_helper_set_cmd : END "); - vty_out(vty, - "Graceful restart configuration changed, reset this peer to take effect\n"); return bgp_vty_return(vty, ret); } @@ -3464,15 +3475,16 @@ DEFUN (no_bgp_neighbor_graceful_restart_helper, "[BGP_GR] no_bgp_neighbor_graceful_restart_helper_set_cmd : START "); ret = bgp_neighbor_graceful_restart(peer, NO_PEER_HELPER_CMD); - - VTY_BGP_GR_ROUTER_DETECT(bgp, peer, peer->bgp->peer); - VTY_SEND_BGP_GR_CAPABILITY_TO_ZEBRA(peer->bgp, ret); + if (ret == BGP_GR_SUCCESS) { + VTY_BGP_GR_ROUTER_DETECT(bgp, peer, peer->bgp->peer); + VTY_SEND_BGP_GR_CAPABILITY_TO_ZEBRA(peer->bgp, ret); + vty_out(vty, + "Graceful restart configuration changed, reset this peer to take effect\n"); + } if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART)) zlog_debug( "[BGP_GR] no_bgp_neighbor_graceful_restart_helper_set_cmd : END "); - vty_out(vty, - "Graceful restart configuration changed, reset this peer to take effect\n"); return bgp_vty_return(vty, ret); } @@ -3500,18 +3512,19 @@ DEFUN (bgp_neighbor_graceful_restart_disable_set, return CMD_WARNING_CONFIG_FAILED; ret = bgp_neighbor_graceful_restart(peer, PEER_DISABLE_CMD); + if (ret == BGP_GR_SUCCESS) { + if (peer->bgp->t_startup) + bgp_peer_gr_flags_update(peer); - if (peer->bgp->t_startup) - bgp_peer_gr_flags_update(peer); - - VTY_BGP_GR_ROUTER_DETECT(bgp, peer, peer->bgp->peer); - VTY_SEND_BGP_GR_CAPABILITY_TO_ZEBRA(peer->bgp, ret); + VTY_BGP_GR_ROUTER_DETECT(bgp, peer, peer->bgp->peer); + VTY_SEND_BGP_GR_CAPABILITY_TO_ZEBRA(peer->bgp, ret); + vty_out(vty, + "Graceful restart configuration changed, reset this peer to take effect\n"); + } if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART)) zlog_debug( "[BGP_GR]bgp_neighbor_graceful_restart_disable_set_cmd : END "); - vty_out(vty, - "Graceful restart configuration changed, reset this peer to take effect\n"); return bgp_vty_return(vty, ret); } @@ -3540,15 +3553,16 @@ DEFUN (no_bgp_neighbor_graceful_restart_disable, "[BGP_GR] no_bgp_neighbor_graceful_restart_disable_set_cmd : START "); ret = bgp_neighbor_graceful_restart(peer, NO_PEER_DISABLE_CMD); - - VTY_BGP_GR_ROUTER_DETECT(bgp, peer, peer->bgp->peer); - VTY_SEND_BGP_GR_CAPABILITY_TO_ZEBRA(peer->bgp, ret); + if (ret == BGP_GR_SUCCESS) { + VTY_BGP_GR_ROUTER_DETECT(bgp, peer, peer->bgp->peer); + VTY_SEND_BGP_GR_CAPABILITY_TO_ZEBRA(peer->bgp, ret); + vty_out(vty, + "Graceful restart configuration changed, reset this peer to take effect\n"); + } if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART)) zlog_debug( "[BGP_GR] no_bgp_neighbor_graceful_restart_disable_set_cmd : END "); - vty_out(vty, - "Graceful restart configuration changed, reset this peer to take effect\n"); return bgp_vty_return(vty, ret); } @@ -4340,6 +4354,9 @@ DEFUN (bgp_network_import_check, return CMD_SUCCESS; } +#if CONFDATE > 20241013 +CPP_NOTICE("Drop `bgp network import-check exact` command") +#endif ALIAS_HIDDEN(bgp_network_import_check, bgp_network_import_check_exact_cmd, "bgp network import-check exact", BGP_STR @@ -10738,7 +10755,10 @@ static int bgp_clear_prefix(struct vty *vty, const char *view_name, if (rm_p->prefixlen == match.prefixlen) { SET_FLAG(rm->flags, BGP_NODE_USER_CLEAR); - bgp_process(bgp, rm, afi, safi); + bgp_process(bgp, rm, + bgp_dest_get_bgp_path_info( + rm), + afi, safi); } bgp_dest_unlock_node(rm); } @@ -10750,7 +10770,9 @@ static int bgp_clear_prefix(struct vty *vty, const char *view_name, if (dest_p->prefixlen == match.prefixlen) { SET_FLAG(dest->flags, BGP_NODE_USER_CLEAR); - bgp_process(bgp, dest, afi, safi); + bgp_process(bgp, dest, + bgp_dest_get_bgp_path_info(dest), + afi, safi); } bgp_dest_unlock_node(dest); } @@ -21187,6 +21209,15 @@ void bgp_vty_init(void) install_element(BGP_VPNV6_NODE, &neighbor_maximum_prefix_threshold_restart_cmd); install_element(BGP_VPNV6_NODE, &no_neighbor_maximum_prefix_cmd); + install_element(BGP_EVPN_NODE, &neighbor_maximum_prefix_cmd); + install_element(BGP_EVPN_NODE, &neighbor_maximum_prefix_threshold_cmd); + install_element(BGP_EVPN_NODE, &neighbor_maximum_prefix_warning_cmd); + install_element(BGP_EVPN_NODE, + &neighbor_maximum_prefix_threshold_warning_cmd); + install_element(BGP_EVPN_NODE, &neighbor_maximum_prefix_restart_cmd); + install_element(BGP_EVPN_NODE, + &neighbor_maximum_prefix_threshold_restart_cmd); + install_element(BGP_EVPN_NODE, &no_neighbor_maximum_prefix_cmd); /* "neighbor allowas-in" */ install_element(BGP_NODE, &neighbor_allowas_in_hidden_cmd); diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index dbba1dc71a..9a81965773 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -1782,7 +1782,7 @@ static void bgp_handle_route_announcements_to_zebra(struct event *e) table = bgp_dest_table(dest); install = CHECK_FLAG(dest->flags, BGP_NODE_SCHEDULE_FOR_INSTALL); - if (table && table->afi == AFI_L2VPN && table->safi == SAFI_EVPN) + if (table->afi == AFI_L2VPN && table->safi == SAFI_EVPN) is_evpn = true; if (BGP_DEBUG(zebra, ZEBRA)) @@ -2154,7 +2154,7 @@ bool bgp_redistribute_metric_set(struct bgp *bgp, struct bgp_redist *red, bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED); - bgp_process(bgp, dest, afi, SAFI_UNICAST); + bgp_process(bgp, dest, pi, afi, SAFI_UNICAST); } } } diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index d98df754ef..5fd4ebe8cc 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -1377,7 +1377,7 @@ int bgp_global_gr_init(struct bgp *bgp) /*GLOBAL_GR_cmd */ /*no_Global_GR_cmd*/ GLOBAL_GR, GLOBAL_INVALID, /*GLOBAL_DISABLE_cmd*//*no_Global_Disable_cmd*/ - GLOBAL_INVALID, GLOBAL_HELPER + GLOBAL_DISABLE, GLOBAL_HELPER }, /* GLOBAL_INVALID Mode */ { @@ -1411,13 +1411,13 @@ int bgp_peer_gr_init(struct peer *peer) /* Event-> */ /* PEER_DISABLE_CMD */ /* NO_PEER_DISABLE_CMD */ {PEER_DISABLE, bgp_peer_gr_action }, {PEER_INVALID, NULL }, /* Event-> */ /* PEER_HELPER_cmd */ /* NO_PEER_HELPER_CMD */ - { PEER_INVALID, NULL }, {PEER_GLOBAL_INHERIT, + { PEER_HELPER, NULL }, {PEER_GLOBAL_INHERIT, bgp_peer_gr_action } }, { /* PEER_GR Mode */ /* Event-> */ /* PEER_GR_CMD */ /* NO_PEER_GR_CMD */ - { PEER_INVALID, NULL }, { PEER_GLOBAL_INHERIT, + { PEER_GR, NULL }, { PEER_GLOBAL_INHERIT, bgp_peer_gr_action }, /* Event-> */ /* PEER_DISABLE_CMD */ /* NO_PEER_DISABLE_CMD */ {PEER_DISABLE, bgp_peer_gr_action }, { PEER_INVALID, NULL }, @@ -1429,7 +1429,7 @@ int bgp_peer_gr_init(struct peer *peer) /* Event-> */ /* PEER_GR_CMD */ /* NO_PEER_GR_CMD */ { PEER_GR, bgp_peer_gr_action }, { PEER_INVALID, NULL }, /* Event-> */ /* PEER_DISABLE_CMD */ /* NO_PEER_DISABLE_CMD */ - { PEER_INVALID, NULL }, { PEER_GLOBAL_INHERIT, + { PEER_DISABLE, NULL }, { PEER_GLOBAL_INHERIT, bgp_peer_gr_action }, /* Event-> */ /* PEER_HELPER_cmd */ /* NO_PEER_HELPER_CMD */ { PEER_HELPER, bgp_peer_gr_action }, { PEER_INVALID, NULL } @@ -1853,21 +1853,31 @@ void bgp_peer_conf_if_to_su_update(struct peer_connection *connection) void bgp_recalculate_afi_safi_bestpaths(struct bgp *bgp, afi_t afi, safi_t safi) { struct bgp_dest *dest, *ndest; + struct bgp_path_info *pi, *next; struct bgp_table *table; for (dest = bgp_table_top(bgp->rib[afi][safi]); dest; dest = bgp_route_next(dest)) { table = bgp_dest_get_bgp_table_info(dest); - if (table != NULL) { - /* Special handling for 2-level routing - * tables. */ - if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP - || safi == SAFI_EVPN) { - for (ndest = bgp_table_top(table); ndest; - ndest = bgp_route_next(ndest)) - bgp_process(bgp, ndest, afi, safi); - } else - bgp_process(bgp, dest, afi, safi); + + if (!table) + continue; + + /* Special handling for 2-level routing + * tables. */ + if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP + || safi == SAFI_EVPN) { + for (ndest = bgp_table_top(table); ndest; + ndest = bgp_route_next(ndest)) { + for (pi = bgp_dest_get_bgp_path_info(ndest); + (pi != NULL) && (next = pi->next, 1); + pi = next) + bgp_process(bgp, ndest, pi, afi, safi); + } + } else { + for (pi = bgp_dest_get_bgp_path_info(dest); + (pi != NULL) && (next = pi->next, 1); pi = next) + bgp_process(bgp, dest, pi, afi, safi); } } } diff --git a/bgpd/rfapi/rfapi.c b/bgpd/rfapi/rfapi.c index 382af05c24..ae899daf82 100644 --- a/bgpd/rfapi/rfapi.c +++ b/bgpd/rfapi/rfapi.c @@ -463,7 +463,7 @@ void del_vnc_route(struct rfapi_descriptor *rfd, bgp_aggregate_decrement(bgp, p, bpi, afi, safi); bgp_path_info_delete(bn, bpi); - bgp_process(bgp, bn, afi, safi); + bgp_process(bgp, bn, bpi, afi, safi); } else { vnc_zlog_debug_verbose( "%s: Couldn't find route (safi=%d) at prefix %pFX", @@ -1001,7 +1001,7 @@ void add_vnc_route(struct rfapi_descriptor *rfd, /* cookie, VPN UN addr, peer */ /* Process change. */ bgp_aggregate_increment(bgp, p, bpi, afi, safi); - bgp_process(bgp, bn, afi, safi); + bgp_process(bgp, bn, bpi, afi, safi); bgp_dest_unlock_node(bn); vnc_zlog_debug_any( @@ -1046,7 +1046,7 @@ void add_vnc_route(struct rfapi_descriptor *rfd, /* cookie, VPN UN addr, peer */ } bgp_dest_unlock_node(bn); - bgp_process(bgp, bn, afi, safi); + bgp_process(bgp, bn, new, afi, safi); vnc_zlog_debug_any( "%s: Added route (safi=%s) at prefix %s (bn=%p, prd=%pRDP)", diff --git a/doc/user/bgp.rst b/doc/user/bgp.rst index 4619fec6a7..68ae796bc9 100644 --- a/doc/user/bgp.rst +++ b/doc/user/bgp.rst @@ -425,6 +425,11 @@ Route Selection Disabled by default. +.. clicmd:: bgp bestpath med missing-as-worst + + If the paths MED value is missing and this command is configured + then treat it as the worse possible value that it can be. + .. clicmd:: maximum-paths (1-128) Sets the maximum-paths value used for ecmp calculations for this diff --git a/isisd/isis_spf.c b/isisd/isis_spf.c index 36986a19c5..294c03def1 100644 --- a/isisd/isis_spf.c +++ b/isisd/isis_spf.c @@ -2908,7 +2908,7 @@ static void show_isis_route_common(struct vty *vty, int levels, struct isis_spftree *spftree; struct listnode *node; struct isis_area *area; - char key[8]; + char key[18]; if (!isis->area_list || isis->area_list->count == 0) return; diff --git a/ospf6d/ospf6_gr_helper.c b/ospf6d/ospf6_gr_helper.c index be1042f260..229e0a4db8 100644 --- a/ospf6d/ospf6_gr_helper.c +++ b/ospf6d/ospf6_gr_helper.c @@ -938,15 +938,6 @@ static void show_ospf6_gr_helper_details(struct vty *vty, struct ospf6 *ospf6, ? "Enabled" : "Disabled"); -#if CONFDATE > 20240401 - CPP_NOTICE("Remove deprecated json key: restartSupoort") -#endif - json_object_string_add( - json, "restartSupoort", - (ospf6->ospf6_helper_cfg.only_planned_restart) - ? "Planned Restart only" - : "Planned and Unplanned Restarts"); - json_object_string_add( json, "restartSupport", (ospf6->ospf6_helper_cfg.only_planned_restart) diff --git a/ospfd/ospf_sr.c b/ospfd/ospf_sr.c index e26fe6f53a..198309c1ef 100644 --- a/ospfd/ospf_sr.c +++ b/ospfd/ospf_sr.c @@ -2740,9 +2740,9 @@ static void show_sr_node(struct vty *vty, struct json_object *json, if (srn->algo[i] == SR_ALGORITHM_UNSET) continue; json_obj = json_object_new_object(); - char tmp[2]; + char tmp[12]; - snprintf(tmp, sizeof(tmp), "%u", i); + snprintf(tmp, sizeof(tmp), "%d", i); json_object_string_add(json_obj, tmp, srn->algo[i] == SR_ALGORITHM_SPF ? "SPF" diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index bf131ff225..b366b3ca30 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -10446,15 +10446,6 @@ static int ospf_show_gr_helper_details(struct vty *vty, struct ospf *ospf, json_object_string_add(json_vrf, "strictLsaCheck", (ospf->strict_lsa_check) ? "Enabled" : "Disabled"); -#if CONFDATE > 20240401 - CPP_NOTICE("Remove deprecated json key: restartSupoort") -#endif - json_object_string_add( - json_vrf, "restartSupoort", - (ospf->only_planned_restart) - ? "Planned Restart only" - : "Planned and Unplanned Restarts"); - json_object_string_add( json_vrf, "restartSupport", (ospf->only_planned_restart) diff --git a/tests/topotests/all_protocol_startup/r1/show_bgp_ipv4-post4.1.ref b/tests/topotests/all_protocol_startup/r1/show_bgp_ipv4-post4.1.ref index 80c727c7e7..eb4e51a074 100644 --- a/tests/topotests/all_protocol_startup/r1/show_bgp_ipv4-post4.1.ref +++ b/tests/topotests/all_protocol_startup/r1/show_bgp_ipv4-post4.1.ref @@ -1,5 +1,5 @@ BGP table version is 1, local router ID is 192.168.0.1, vrf id 0 -Status codes: s suppressed, d damped, h history, * valid, > best, = multipath, +Status codes: s suppressed, d damped, h history, u unsorted, * valid, > best, = multipath, i internal, r RIB-failure, S Stale, R Removed Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self Origin codes: i - IGP, e - EGP, ? - incomplete diff --git a/tests/topotests/all_protocol_startup/r1/show_bgp_ipv4-post5.0.ref b/tests/topotests/all_protocol_startup/r1/show_bgp_ipv4-post5.0.ref index 6a837f5ae7..8fe3ea41a6 100644 --- a/tests/topotests/all_protocol_startup/r1/show_bgp_ipv4-post5.0.ref +++ b/tests/topotests/all_protocol_startup/r1/show_bgp_ipv4-post5.0.ref @@ -1,5 +1,5 @@ BGP table version is 1, local router ID is 192.168.0.1, vrf id 0 -Status codes: s suppressed, d damped, h history, * valid, > best, = multipath, +Status codes: s suppressed, d damped, h history, u unsorted, * valid, > best, = multipath, i internal, r RIB-failure, S Stale, R Removed Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self Origin codes: i - IGP, e - EGP, ? - incomplete diff --git a/tests/topotests/all_protocol_startup/r1/show_bgp_ipv4-post6.1.ref b/tests/topotests/all_protocol_startup/r1/show_bgp_ipv4-post6.1.ref index cc3c098518..67b907131c 100644 --- a/tests/topotests/all_protocol_startup/r1/show_bgp_ipv4-post6.1.ref +++ b/tests/topotests/all_protocol_startup/r1/show_bgp_ipv4-post6.1.ref @@ -1,6 +1,6 @@ BGP table version is 1, local router ID is 192.168.0.1, vrf id 0 Default local pref 100, local AS 100 -Status codes: s suppressed, d damped, h history, * valid, > best, = multipath, +Status codes: s suppressed, d damped, h history, u unsorted, * valid, > best, = multipath, i internal, r RIB-failure, S Stale, R Removed Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self Origin codes: i - IGP, e - EGP, ? - incomplete diff --git a/tests/topotests/all_protocol_startup/r1/show_bgp_ipv4.ref b/tests/topotests/all_protocol_startup/r1/show_bgp_ipv4.ref index 9b6f2f1c94..4f21a5711b 100644 --- a/tests/topotests/all_protocol_startup/r1/show_bgp_ipv4.ref +++ b/tests/topotests/all_protocol_startup/r1/show_bgp_ipv4.ref @@ -1,5 +1,5 @@ BGP table version is 1, local router ID is 192.168.0.1 -Status codes: s suppressed, d damped, h history, * valid, > best, = multipath, +Status codes: s suppressed, d damped, h history, u unsorted, * valid, > best, = multipath, i internal, r RIB-failure, S Stale, R Removed Origin codes: i - IGP, e - EGP, ? - incomplete diff --git a/tests/topotests/all_protocol_startup/r1/show_bgp_ipv6-post4.1.ref b/tests/topotests/all_protocol_startup/r1/show_bgp_ipv6-post4.1.ref index 5fe04bfa23..69e44e77ed 100644 --- a/tests/topotests/all_protocol_startup/r1/show_bgp_ipv6-post4.1.ref +++ b/tests/topotests/all_protocol_startup/r1/show_bgp_ipv6-post4.1.ref @@ -1,5 +1,5 @@ BGP table version is 1, local router ID is 192.168.0.1, vrf id 0 -Status codes: s suppressed, d damped, h history, * valid, > best, = multipath, +Status codes: s suppressed, d damped, h history, u unsorted, * valid, > best, = multipath, i internal, r RIB-failure, S Stale, R Removed Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self Origin codes: i - IGP, e - EGP, ? - incomplete diff --git a/tests/topotests/all_protocol_startup/r1/show_bgp_ipv6.ref b/tests/topotests/all_protocol_startup/r1/show_bgp_ipv6.ref index c4469d2230..77aab38b0d 100644 --- a/tests/topotests/all_protocol_startup/r1/show_bgp_ipv6.ref +++ b/tests/topotests/all_protocol_startup/r1/show_bgp_ipv6.ref @@ -1,5 +1,5 @@ BGP table version is 1, local router ID is 192.168.0.1 -Status codes: s suppressed, d damped, h history, * valid, > best, = multipath, +Status codes: s suppressed, d damped, h history, u unsorted, * valid, > best, = multipath, i internal, r RIB-failure, S Stale, R Removed Origin codes: i - IGP, e - EGP, ? - incomplete diff --git a/tests/topotests/all_protocol_startup/r1/show_bgp_ipv6_post6.1.ref b/tests/topotests/all_protocol_startup/r1/show_bgp_ipv6_post6.1.ref index 6ca07ec01d..a99400a6b0 100644 --- a/tests/topotests/all_protocol_startup/r1/show_bgp_ipv6_post6.1.ref +++ b/tests/topotests/all_protocol_startup/r1/show_bgp_ipv6_post6.1.ref @@ -1,6 +1,6 @@ BGP table version is 1, local router ID is 192.168.0.1, vrf id 0 Default local pref 100, local AS 100 -Status codes: s suppressed, d damped, h history, * valid, > best, = multipath, +Status codes: s suppressed, d damped, h history, u unsorted, * valid, > best, = multipath, i internal, r RIB-failure, S Stale, R Removed Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self Origin codes: i - IGP, e - EGP, ? - incomplete diff --git a/tests/topotests/bgp_evpn_maximum_prefix/__init__.py b/tests/topotests/bgp_evpn_maximum_prefix/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/topotests/bgp_evpn_maximum_prefix/__init__.py diff --git a/tests/topotests/bgp_evpn_maximum_prefix/c1/frr.conf b/tests/topotests/bgp_evpn_maximum_prefix/c1/frr.conf new file mode 100644 index 0000000000..7476a3723d --- /dev/null +++ b/tests/topotests/bgp_evpn_maximum_prefix/c1/frr.conf @@ -0,0 +1,4 @@ +! +int c1-eth0 + ip address 192.168.0.1/24 +! diff --git a/tests/topotests/bgp_evpn_maximum_prefix/c2/frr.conf b/tests/topotests/bgp_evpn_maximum_prefix/c2/frr.conf new file mode 100644 index 0000000000..a203daae05 --- /dev/null +++ b/tests/topotests/bgp_evpn_maximum_prefix/c2/frr.conf @@ -0,0 +1,4 @@ +! +int c2-eth0 + ip address 192.168.0.2/24 +! diff --git a/tests/topotests/bgp_evpn_maximum_prefix/r1/frr.conf b/tests/topotests/bgp_evpn_maximum_prefix/r1/frr.conf new file mode 100644 index 0000000000..0534518cfb --- /dev/null +++ b/tests/topotests/bgp_evpn_maximum_prefix/r1/frr.conf @@ -0,0 +1,30 @@ +! +!debug bgp neighbor +!debug route-map detail +! +vni 10 +! +int lo + ip address 10.10.10.1/32 +! +int r1-eth1 + ip address 192.168.1.1/24 +! +router bgp 65001 + no bgp ebgp-requires-policy + no bgp network import-check + neighbor 192.168.1.2 remote-as external + neighbor 192.168.1.2 timers 1 3 + neighbor 192.168.1.2 timers connect 1 + ! + address-family ipv4 unicast + redistribute connected + network 10.10.10.10/32 + exit-address-family + ! + address-family l2vpn evpn + neighbor 192.168.1.2 activate + advertise-all-vni + advertise ipv4 unicast + exit-address-family +! diff --git a/tests/topotests/bgp_evpn_maximum_prefix/r2/frr.conf b/tests/topotests/bgp_evpn_maximum_prefix/r2/frr.conf new file mode 100644 index 0000000000..353302b9e7 --- /dev/null +++ b/tests/topotests/bgp_evpn_maximum_prefix/r2/frr.conf @@ -0,0 +1,25 @@ +! +!debug bgp neighbor +! +int lo + ip address 10.10.10.2/32 +! +int r2-eth0 + ip address 192.168.1.2/24 +! +router bgp 65002 + no bgp ebgp-requires-policy + neighbor 192.168.1.1 remote-as external + neighbor 192.168.1.1 timers 1 3 + neighbor 192.168.1.1 timers connect 1 + ! + address-family ipv4 unicast + redistribute connected + exit-address-family + ! + address-family l2vpn evpn + neighbor 192.168.1.1 activate + neighbor 192.168.1.1 maximum-prefix 2 + advertise-all-vni + exit-address-family +! diff --git a/tests/topotests/bgp_evpn_maximum_prefix/test_bgp_evpn_maximum_prefix.py b/tests/topotests/bgp_evpn_maximum_prefix/test_bgp_evpn_maximum_prefix.py new file mode 100644 index 0000000000..5469eff144 --- /dev/null +++ b/tests/topotests/bgp_evpn_maximum_prefix/test_bgp_evpn_maximum_prefix.py @@ -0,0 +1,92 @@ +#!/usr/bin/env python +# SPDX-License-Identifier: ISC + +# Copyright (c) 2024 by +# Donatas Abraitis <donatas@opensourcerouting.org> +# + +import os +import re +import sys +import json +import pytest +import functools + +CWD = os.path.dirname(os.path.realpath(__file__)) +sys.path.append(os.path.join(CWD, "../")) + +# pylint: disable=C0413 +from lib import topotest +from lib.topogen import Topogen, TopoRouter, get_topogen + +pytestmark = [pytest.mark.bgpd] + + +def setup_module(mod): + topodef = {"s1": ("c1", "r1"), "s2": ("r1", "r2"), "s3": ("r2", "c2")} + tgen = Topogen(topodef, mod.__name__) + tgen.start_topology() + + tgen.net["r1"].cmd( + """ +ip link add vxlan10 type vxlan id 10 dstport 4789 local 10.10.10.1 nolearning +ip link add name br10 type bridge +ip link set dev vxlan10 master br10 +ip link set dev r1-eth0 master br10 +ip link set up dev br10 +ip link set up dev vxlan10""" + ) + + tgen.net["r2"].cmd( + """ +ip link add vxlan10 type vxlan id 10 dstport 4789 local 10.10.10.2 nolearning +ip link add name br10 type bridge +ip link set dev vxlan10 master br10 +ip link set dev r2-eth1 master br10 +ip link set up dev br10 +ip link set up dev vxlan10""" + ) + + router_list = tgen.routers() + + for _, (rname, router) in enumerate(router_list.items(), 1): + router.load_frr_config(os.path.join(CWD, "{}/frr.conf".format(rname))) + + tgen.start_router() + + +def teardown_module(mod): + tgen = get_topogen() + tgen.stop_topology() + + +def test_bgp_evpn_maximum_prefix(): + tgen = get_topogen() + + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + r2 = tgen.gears["r2"] + + def _bgp_converge(): + output = json.loads(r2.vtysh_cmd("show bgp l2vpn evpn summary failed json")) + expected = { + "peers": { + "192.168.1.1": { + "lastNotificationReason": "Cease/Maximum Number of Prefixes Reached", + "lastResetDueTo": "BGP Notification send", + } + }, + } + return topotest.json_cmp(output, expected) + + test_func = functools.partial( + _bgp_converge, + ) + _, result = topotest.run_and_expect(test_func, None, count=60, wait=1) + assert result is None, "Can't limit maximum-prefixes for EVPN routes" + + +if __name__ == "__main__": + args = ["-s"] + sys.argv[1:] + sys.exit(pytest.main(args)) diff --git a/tests/topotests/bgp_evpn_mh/leaf1/evpn.conf b/tests/topotests/bgp_evpn_mh/leaf1/evpn.conf index 33b6d08aba..d246517898 100644 --- a/tests/topotests/bgp_evpn_mh/leaf1/evpn.conf +++ b/tests/topotests/bgp_evpn_mh/leaf1/evpn.conf @@ -1,6 +1,7 @@ frr defaults datacenter ! router bgp 65101 + timers bgp 3 10 bgp router-id 192.168.100.13 no bgp ebgp-requires-policy neighbor 192.168.50.1 remote-as external diff --git a/tests/topotests/bgp_evpn_mh/leaf2/evpn.conf b/tests/topotests/bgp_evpn_mh/leaf2/evpn.conf index 428998b0fe..6855a436d4 100644 --- a/tests/topotests/bgp_evpn_mh/leaf2/evpn.conf +++ b/tests/topotests/bgp_evpn_mh/leaf2/evpn.conf @@ -1,6 +1,7 @@ frr defaults datacenter ! router bgp 65101 + timers bgp 3 10 bgp router-id 192.168.100.14 no bgp ebgp-requires-policy neighbor 192.168.61.1 remote-as external diff --git a/tests/topotests/bgp_evpn_mh/spine1/evpn.conf b/tests/topotests/bgp_evpn_mh/spine1/evpn.conf index b9fce46ea4..7d6fef699d 100644 --- a/tests/topotests/bgp_evpn_mh/spine1/evpn.conf +++ b/tests/topotests/bgp_evpn_mh/spine1/evpn.conf @@ -1,6 +1,7 @@ frr defaults datacenter ! router bgp 65001 + timers bgp 3 10 bgp router-id 192.168.100.13 no bgp ebgp-requires-policy neighbor 192.168.50.2 remote-as external diff --git a/tests/topotests/bgp_evpn_mh/spine2/evpn.conf b/tests/topotests/bgp_evpn_mh/spine2/evpn.conf index 1430e10b68..c651ada686 100644 --- a/tests/topotests/bgp_evpn_mh/spine2/evpn.conf +++ b/tests/topotests/bgp_evpn_mh/spine2/evpn.conf @@ -1,6 +1,7 @@ frr defaults datacenter ! router bgp 65001 + timers bgp 3 10 bgp router-id 192.168.100.14 no bgp ebgp-requires-policy neighbor 192.168.60.2 remote-as external diff --git a/tests/topotests/bgp_evpn_mh/torm11/evpn.conf b/tests/topotests/bgp_evpn_mh/torm11/evpn.conf index 2c1c695a18..62b7ec5855 100644 --- a/tests/topotests/bgp_evpn_mh/torm11/evpn.conf +++ b/tests/topotests/bgp_evpn_mh/torm11/evpn.conf @@ -7,6 +7,7 @@ frr defaults datacenter ! ! router bgp 65002 + timers bgp 3 10 bgp router-id 192.168.100.15 no bgp ebgp-requires-policy neighbor 192.168.1.1 remote-as external diff --git a/tests/topotests/bgp_evpn_mh/torm12/evpn.conf b/tests/topotests/bgp_evpn_mh/torm12/evpn.conf index 8b0ce1d98f..3ceb974c47 100644 --- a/tests/topotests/bgp_evpn_mh/torm12/evpn.conf +++ b/tests/topotests/bgp_evpn_mh/torm12/evpn.conf @@ -7,6 +7,7 @@ frr defaults datacenter ! ! router bgp 65003 + timers bgp 3 10 bgp router-id 192.168.100.16 no bgp ebgp-requires-policy neighbor 192.168.2.1 remote-as external diff --git a/tests/topotests/bgp_evpn_mh/torm21/evpn.conf b/tests/topotests/bgp_evpn_mh/torm21/evpn.conf index 5247dc1ebd..ecaf85ddb7 100644 --- a/tests/topotests/bgp_evpn_mh/torm21/evpn.conf +++ b/tests/topotests/bgp_evpn_mh/torm21/evpn.conf @@ -7,6 +7,7 @@ frr defaults datacenter ! ! router bgp 65004 + timers bgp 3 10 bgp router-id 192.168.100.17 no bgp ebgp-requires-policy neighbor 192.168.3.1 remote-as external diff --git a/tests/topotests/bgp_evpn_mh/torm22/evpn.conf b/tests/topotests/bgp_evpn_mh/torm22/evpn.conf index ec56360176..c7e152498c 100644 --- a/tests/topotests/bgp_evpn_mh/torm22/evpn.conf +++ b/tests/topotests/bgp_evpn_mh/torm22/evpn.conf @@ -6,6 +6,7 @@ frr defaults datacenter ! debug bgp zebra ! router bgp 65005 + timers bgp 3 10 bgp router-id 192.168.100.18 no bgp ebgp-requires-policy neighbor 192.168.4.1 remote-as external diff --git a/tests/topotests/ospf_basic_functionality/test_ospf_rte_calc.py b/tests/topotests/ospf_basic_functionality/test_ospf_rte_calc.py index f0950a2db3..45c1325917 100644 --- a/tests/topotests/ospf_basic_functionality/test_ospf_rte_calc.py +++ b/tests/topotests/ospf_basic_functionality/test_ospf_rte_calc.py @@ -49,7 +49,7 @@ from lib.ospf import ( verify_ospf_interface, ) -pytestmark = [pytest.mark.ospfd, pytest.mark.staticd] +pytestmark = [pytest.mark.bgpd, pytest.mark.ospfd, pytest.mark.staticd] # Global variables diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index f092fc5c85..dde4704936 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -1550,7 +1550,7 @@ static ssize_t fill_seg6ipt_encap(char *buffer, size_t buflen, srh->first_segment = segs->num_segs - 1; for (i = 0; i < segs->num_segs; i++) { - memcpy(&srh->segments[i], &segs->seg[i], + memcpy(&srh->segments[segs->num_segs - i - 1], &segs->seg[i], sizeof(struct in6_addr)); } diff --git a/zebra/zebra_nb_config.c b/zebra/zebra_nb_config.c index 04eac63d3e..ae6232a1bb 100644 --- a/zebra/zebra_nb_config.c +++ b/zebra/zebra_nb_config.c @@ -3187,6 +3187,7 @@ int lib_interface_zebra_ipv6_router_advertisements_dnssl_dnssl_domain_create( strlcpy(dnssl.name, yang_dnode_get_string(args->dnode, "domain"), sizeof(dnssl.name)); ret = rtadv_dnssl_encode(dnssl.encoded_name, dnssl.name); + dnssl.encoded_len = ret; if (args->event == NB_EV_VALIDATE) { if (ret < 0) { diff --git a/zebra/zebra_neigh.c b/zebra/zebra_neigh.c index 941088afd6..a222e7f6e8 100644 --- a/zebra/zebra_neigh.c +++ b/zebra/zebra_neigh.c @@ -83,7 +83,7 @@ zebra_neigh_new(ifindex_t ifindex, struct ipaddr *ip, struct ethaddr *mac) n->ifindex = ifindex; if (mac) { memcpy(&n->mac, mac, sizeof(*mac)); - n->flags |= ZEBRA_NEIGH_ENT_ACTIVE; + SET_FLAG(n->flags, ZEBRA_NEIGH_ENT_ACTIVE); } /* Add to rb_tree */ @@ -118,10 +118,8 @@ static void zebra_neigh_free(struct zebra_neigh_ent *n) /* if rules are still using the neigh mark it as inactive and * update the dataplane */ - if (n->flags & ZEBRA_NEIGH_ENT_ACTIVE) { - n->flags &= ~ZEBRA_NEIGH_ENT_ACTIVE; - memset(&n->mac, 0, sizeof(n->mac)); - } + UNSET_FLAG(n->flags, ZEBRA_NEIGH_ENT_ACTIVE); + memset(&n->mac, 0, sizeof(n->mac)); zebra_neigh_pbr_rules_update(n); return; } @@ -181,7 +179,7 @@ void zebra_neigh_add(struct interface *ifp, struct ipaddr *ip, return; memcpy(&n->mac, mac, sizeof(*mac)); - n->flags |= ZEBRA_NEIGH_ENT_ACTIVE; + SET_FLAG(n->flags, ZEBRA_NEIGH_ENT_ACTIVE); /* update rules linked to the neigh */ zebra_neigh_pbr_rules_update(n); @@ -201,7 +199,7 @@ void zebra_neigh_deref(struct zebra_pbr_rule *rule) rule->action.neigh = NULL; /* remove rule from the list and free if it is inactive */ list_delete_node(n->pbr_rule_list, &rule->action.neigh_listnode); - if (!(n->flags & ZEBRA_NEIGH_ENT_ACTIVE)) + if (!CHECK_FLAG(n->flags, ZEBRA_NEIGH_ENT_ACTIVE)) zebra_neigh_free(n); } diff --git a/zebra/zebra_netns_id.c b/zebra/zebra_netns_id.c index 1af3a3e857..4cee3b89f1 100644 --- a/zebra/zebra_netns_id.c +++ b/zebra/zebra_netns_id.c @@ -42,7 +42,7 @@ #define NETLINK_SOCKET_BUFFER_SIZE 512 #define NETLINK_ALIGNTO 4 #define NETLINK_ALIGN(len) \ - (((len) + NETLINK_ALIGNTO - 1) & ~(NETLINK_ALIGNTO - 1)) + CHECK_FLAG(((len) + NETLINK_ALIGNTO - 1), ~(NETLINK_ALIGNTO - 1)) #define NETLINK_NLATTR_LEN(_a, _b) (unsigned int)((char *)_a - (char *)_b) #endif /* defined(HAVE_NETLINK) */ @@ -66,7 +66,7 @@ static struct nlmsghdr *initiate_nlh(char *buf, unsigned int *seq, int type) nlh->nlmsg_type = type; nlh->nlmsg_flags = NLM_F_REQUEST; if (type == RTM_NEWNSID) - nlh->nlmsg_flags |= NLM_F_ACK; + SET_FLAG(nlh->nlmsg_flags, NLM_F_ACK); nlh->nlmsg_seq = *seq = frr_sequence32_next(); return nlh; } diff --git a/zebra/zebra_netns_notify.c b/zebra/zebra_netns_notify.c index 1bb1292e34..617a2225f8 100644 --- a/zebra/zebra_netns_notify.c +++ b/zebra/zebra_netns_notify.c @@ -304,7 +304,7 @@ static void zebra_ns_notify_read(struct event *t) char *netnspath; struct zebra_netns_info *netnsinfo; - if (!(event->mask & (IN_CREATE | IN_DELETE))) + if (!CHECK_FLAG(event->mask, (IN_CREATE | IN_DELETE))) continue; if (offsetof(struct inotify_event, name) + event->len @@ -350,7 +350,7 @@ static void zebra_ns_notify_read(struct event *t) memcpy(event_name, event->name, event->len); event_name[event->len - 1] = 0; - if (event->mask & IN_DELETE) { + if (CHECK_FLAG(event->mask, IN_DELETE)) { zebra_ns_delete(event_name); continue; } diff --git a/zebra/zebra_nhg.c b/zebra/zebra_nhg.c index 934b8ba0db..ff97a11c17 100644 --- a/zebra/zebra_nhg.c +++ b/zebra/zebra_nhg.c @@ -1795,8 +1795,8 @@ static struct nexthop *nexthop_set_resolved(afi_t afi, break; } - if (newhop->flags & NEXTHOP_FLAG_ONLINK) - resolved_hop->flags |= NEXTHOP_FLAG_ONLINK; + if (CHECK_FLAG(newhop->flags, NEXTHOP_FLAG_ONLINK)) + SET_FLAG(resolved_hop->flags, NEXTHOP_FLAG_ONLINK); /* Copy labels of the resolved route and the parent resolving to it */ if (policy) { |
