diff options
author | Juergen Werner <juergen@opensourcerouting.org> | 2019-11-19 17:41:04 +0100 |
---|---|---|
committer | Juergen Werner <juergen@opensourcerouting.org> | 2019-11-19 17:41:04 +0100 |
commit | 54317cbae5aa99e9970e304c6b3297825a2412a3 (patch) | |
tree | 895a127e6f15590b478a3b77dd0e1774362bdb28 /bgpd/bgp_route.c | |
parent | Merge pull request #5361 from donaldsharp/fpm_crash (diff) | |
download | frr-54317cbae5aa99e9970e304c6b3297825a2412a3.tar.xz frr-54317cbae5aa99e9970e304c6b3297825a2412a3.zip |
bgpd: Special handling for 2-level routing tables
The command `show ip bgp ipv4|ipv6 vpn neighbors <ip> prefix-counts`
caused a segfault, because the 2-level routing was not accounted for.
Signed-off-by: Juergen Werner <juergen@opensourcerouting.org>
Diffstat (limited to 'bgpd/bgp_route.c')
-rw-r--r-- | bgpd/bgp_route.c | 97 |
1 files changed, 59 insertions, 38 deletions
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 8acaf7bdd..e05aff4cf 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -10860,56 +10860,76 @@ struct peer_pcounts { unsigned int count[PCOUNT_MAX]; const struct peer *peer; const struct bgp_table *table; + safi_t safi; }; -static int bgp_peer_count_walker(struct thread *t) +static void bgp_peer_count_proc(struct bgp_node *rn, + struct peer_pcounts *pc) { - struct bgp_node *rn; - struct peer_pcounts *pc = THREAD_ARG(t); + const struct bgp_adj_in *ain; + const struct bgp_path_info *pi; const struct peer *peer = pc->peer; - for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn)) { - struct bgp_adj_in *ain; - struct bgp_path_info *pi; - - for (ain = rn->adj_in; ain; ain = ain->next) - if (ain->peer == peer) - pc->count[PCOUNT_ADJ_IN]++; + for (ain = rn->adj_in; ain; ain = ain->next) + if (ain->peer == peer) + pc->count[PCOUNT_ADJ_IN]++; - for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) { + for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) { - if (pi->peer != peer) - continue; + if (pi->peer != peer) + continue; - pc->count[PCOUNT_ALL]++; + pc->count[PCOUNT_ALL]++; - if (CHECK_FLAG(pi->flags, BGP_PATH_DAMPED)) - pc->count[PCOUNT_DAMPED]++; - if (CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) - pc->count[PCOUNT_HISTORY]++; - if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) - pc->count[PCOUNT_REMOVED]++; - if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) - pc->count[PCOUNT_STALE]++; - if (CHECK_FLAG(pi->flags, BGP_PATH_VALID)) - pc->count[PCOUNT_VALID]++; + if (CHECK_FLAG(pi->flags, BGP_PATH_DAMPED)) + pc->count[PCOUNT_DAMPED]++; + if (CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) + pc->count[PCOUNT_HISTORY]++; + if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) + pc->count[PCOUNT_REMOVED]++; + if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) + pc->count[PCOUNT_STALE]++; + if (CHECK_FLAG(pi->flags, BGP_PATH_VALID)) + pc->count[PCOUNT_VALID]++; + if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE)) + pc->count[PCOUNT_PFCNT]++; + + if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) { + pc->count[PCOUNT_COUNTED]++; + if (CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE)) + flog_err( + EC_LIB_DEVELOPMENT, + "Attempting to count but flags say it is unusable"); + } else { if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE)) - pc->count[PCOUNT_PFCNT]++; - - if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) { - pc->count[PCOUNT_COUNTED]++; - if (CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE)) - flog_err( - EC_LIB_DEVELOPMENT, - "Attempting to count but flags say it is unusable"); - } else { - if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE)) - flog_err( - EC_LIB_DEVELOPMENT, - "Not counted but flags say we should"); - } + flog_err( + EC_LIB_DEVELOPMENT, + "Not counted but flags say we should"); } } +} + +static int bgp_peer_count_walker(struct thread *t) +{ + struct bgp_node *rn, *rm; + const struct bgp_table *table; + struct peer_pcounts *pc = THREAD_ARG(t); + + if (pc->safi == SAFI_MPLS_VPN || pc->safi == SAFI_ENCAP + || pc->safi == SAFI_EVPN) { + /* Special handling for 2-level routing tables. */ + for (rn = bgp_table_top(pc->table); rn; + rn = bgp_route_next(rn)) { + table = bgp_node_get_bgp_table_info(rn); + if (table != NULL) + for (rm = bgp_table_top(table); rm; + rm = bgp_route_next(rm)) + bgp_peer_count_proc(rm, pc); + } + } else + for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn)) + bgp_peer_count_proc(rn, pc); + return 0; } @@ -10943,6 +10963,7 @@ static int bgp_peer_counts(struct vty *vty, struct peer *peer, afi_t afi, memset(&pcounts, 0, sizeof(pcounts)); pcounts.peer = peer; pcounts.table = peer->bgp->rib[afi][safi]; + pcounts.safi = safi; /* in-place call via thread subsystem so as to record execution time * stats for the thread-walk (i.e. ensure this can't be blamed on |