mirror of https://github.com/FRRouting/frr.git
Merge pull request #15572 from donaldsharp/best_path_stuff_sigh
bgp_process work
This commit is contained in:
commit
1c043440ea
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
@ -4468,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);
|
||||
}
|
||||
|
||||
|
@ -4518,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);
|
||||
}
|
||||
|
||||
|
@ -4563,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);
|
||||
}
|
||||
|
||||
|
@ -6473,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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
521
bgpd/bgp_route.c
521
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,9 +503,27 @@ 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);
|
||||
bgp_path_info_unlock(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);
|
||||
}
|
||||
|
||||
|
@ -679,12 +738,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 +2801,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 +2823,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 +2895,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
|
||||
|
@ -3466,7 +3737,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);
|
||||
|
@ -3691,13 +3963,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;
|
||||
|
@ -3946,7 +4243,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,
|
||||
|
@ -4552,7 +4849,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 */
|
||||
{
|
||||
|
@ -4580,7 +4877,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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4870,7 +5167,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
|
||||
|
@ -5015,7 +5312,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
|
||||
|
@ -5586,7 +5883,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;
|
||||
|
@ -5597,7 +5894,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;
|
||||
|
||||
|
@ -5859,7 +6157,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) {
|
||||
|
@ -5874,8 +6172,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(
|
||||
|
@ -5908,8 +6207,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],
|
||||
|
@ -6522,7 +6821,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) {
|
||||
|
@ -6580,7 +6879,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 ||
|
||||
|
@ -6619,6 +6918,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,
|
||||
|
@ -6637,7 +6937,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. */
|
||||
|
@ -7038,7 +7338,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7401,8 +7701,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,
|
||||
|
@ -7427,7 +7729,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)
|
||||
|
@ -7439,7 +7741,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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7525,7 +7827,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);
|
||||
|
@ -7535,7 +7836,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;
|
||||
|
@ -7546,17 +7846,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);
|
||||
}
|
||||
|
@ -7615,7 +7912,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
|
||||
|
@ -7665,8 +7961,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;
|
||||
|
@ -7690,7 +7984,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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -7706,7 +8000,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++;
|
||||
|
@ -7767,8 +8061,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);
|
||||
|
@ -7828,7 +8120,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];
|
||||
|
||||
|
@ -7840,7 +8131,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))
|
||||
|
@ -7858,10 +8148,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--;
|
||||
|
@ -7900,10 +8191,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);
|
||||
|
@ -8052,7 +8339,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
|
||||
|
@ -8069,12 +8355,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
|
||||
|
@ -8116,10 +8402,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;
|
||||
|
@ -8729,7 +9011,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);
|
||||
|
||||
|
@ -8752,7 +9034,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)) {
|
||||
|
@ -8793,7 +9075,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);
|
||||
}
|
||||
|
@ -8827,7 +9109,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);
|
||||
|
@ -8973,6 +9255,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");
|
||||
|
@ -9035,6 +9320,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))
|
||||
|
@ -13675,21 +13962,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 {
|
||||
|
@ -13730,6 +14019,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]++;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -10752,7 +10752,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);
|
||||
}
|
||||
|
@ -10764,7 +10767,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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
30
bgpd/bgpd.c
30
bgpd/bgpd.c
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)",
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue