]> git.proxmox.com Git - mirror_frr.git/commitdiff
bgpd: fix "show bgp statistics" for the VPN safi
authorRenato Westphal <renatowestphal@gmail.com>
Sat, 30 Mar 2019 03:53:16 +0000 (00:53 -0300)
committerRenato Westphal <renatowestphal@gmail.com>
Sat, 30 Mar 2019 04:09:23 +0000 (01:09 -0300)
In order to iterate over MPLS VPN routes, it's necessary to use
two nested loops (the outer loop iterates over the MPLS VPN RDs,
and the inner loop iterates over the VPN routes from that RD).

The bgp_table_stats_walker() function wasn't giving this special
treatment to the MPLS VPN safi as it should, which was leading to
crashes and malfunctioning. Fix this.

Signed-off-by: Renato Westphal <renatowestphal@gmail.com>
bgpd/bgp_route.c

index 5716cc0896ad3eb861729e3852bcc8f19bb5ccca..ad9d22a7a5d332e281b2cec675c8696410872938 100644 (file)
@@ -10225,39 +10225,20 @@ ravg_tally (unsigned long count, unsigned long oldavg, unsigned long newval)
 }
 #endif
 
-static int bgp_table_stats_walker(struct thread *t)
+static void bgp_table_stats_rn(struct bgp_node *rn, struct bgp_node *top,
+                              struct bgp_table_stats *ts, unsigned int space)
 {
-       struct bgp_node *rn;
-       struct bgp_node *top;
-       struct bgp_table_stats *ts = THREAD_ARG(t);
-       unsigned int space = 0;
-
-       if (!(top = bgp_table_top(ts->table)))
-               return 0;
-
-       switch (top->p.family) {
-       case AF_INET:
-               space = IPV4_MAX_BITLEN;
-               break;
-       case AF_INET6:
-               space = IPV6_MAX_BITLEN;
-               break;
-       }
-
-       ts->counts[BGP_STATS_MAXBITLEN] = space;
-
-       for (rn = top; rn; rn = bgp_route_next(rn)) {
-               struct bgp_path_info *pi;
-               struct bgp_node *prn = bgp_node_parent_nolock(rn);
+       struct bgp_node *prn = bgp_node_parent_nolock(rn);
+       struct bgp_path_info *pi;
 
-               if (rn == top)
-                       continue;
+       if (rn == top)
+               return;
 
-               if (!bgp_node_has_bgp_path_info_data(rn))
-                       continue;
+       if (!bgp_node_has_bgp_path_info_data(rn))
+               return;
 
-               ts->counts[BGP_STATS_PREFIXES]++;
-               ts->counts[BGP_STATS_TOTPLEN] += rn->p.prefixlen;
+       ts->counts[BGP_STATS_PREFIXES]++;
+       ts->counts[BGP_STATS_TOTPLEN] += rn->p.prefixlen;
 
 #if 0
       ts->counts[BGP_STATS_AVGPLEN]
@@ -10266,48 +10247,43 @@ static int bgp_table_stats_walker(struct thread *t)
                       rn->p.prefixlen);
 #endif
 
-               /* check if the prefix is included by any other announcements */
-               while (prn && !bgp_node_has_bgp_path_info_data(prn))
-                       prn = bgp_node_parent_nolock(prn);
+       /* check if the prefix is included by any other announcements */
+       while (prn && !bgp_node_has_bgp_path_info_data(prn))
+               prn = bgp_node_parent_nolock(prn);
 
-               if (prn == NULL || prn == top) {
-                       ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
-                       /* announced address space */
-                       if (space)
-                               ts->total_space +=
-                                       pow(2.0, space - rn->p.prefixlen);
-               } else if (bgp_node_has_bgp_path_info_data(prn))
-                       ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
+       if (prn == NULL || prn == top) {
+               ts->counts[BGP_STATS_UNAGGREGATEABLE]++;
+               /* announced address space */
+               if (space)
+                       ts->total_space += pow(2.0, space - rn->p.prefixlen);
+       } else if (bgp_node_has_bgp_path_info_data(prn))
+               ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++;
 
-               for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
-                       ts->counts[BGP_STATS_RIB]++;
-
-                       if (pi->attr
-                           && (CHECK_FLAG(pi->attr->flag,
-                                          ATTR_FLAG_BIT(
-                                                  BGP_ATTR_ATOMIC_AGGREGATE))))
-                               ts->counts[BGP_STATS_AGGREGATES]++;
-
-                       /* as-path stats */
-                       if (pi->attr && pi->attr->aspath) {
-                               unsigned int hops =
-                                       aspath_count_hops(pi->attr->aspath);
-                               unsigned int size =
-                                       aspath_size(pi->attr->aspath);
-                               as_t highest = aspath_highest(pi->attr->aspath);
-
-                               ts->counts[BGP_STATS_ASPATH_COUNT]++;
-
-                               if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
-                                       ts->counts[BGP_STATS_ASPATH_MAXHOPS] =
-                                               hops;
-
-                               if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
-                                       ts->counts[BGP_STATS_ASPATH_MAXSIZE] =
-                                               size;
-
-                               ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
-                               ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
+
+       for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
+               ts->counts[BGP_STATS_RIB]++;
+
+               if (pi->attr
+                   && (CHECK_FLAG(pi->attr->flag,
+                                  ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE))))
+                       ts->counts[BGP_STATS_AGGREGATES]++;
+
+               /* as-path stats */
+               if (pi->attr && pi->attr->aspath) {
+                       unsigned int hops = aspath_count_hops(pi->attr->aspath);
+                       unsigned int size = aspath_size(pi->attr->aspath);
+                       as_t highest = aspath_highest(pi->attr->aspath);
+
+                       ts->counts[BGP_STATS_ASPATH_COUNT]++;
+
+                       if (hops > ts->counts[BGP_STATS_ASPATH_MAXHOPS])
+                               ts->counts[BGP_STATS_ASPATH_MAXHOPS] = hops;
+
+                       if (size > ts->counts[BGP_STATS_ASPATH_MAXSIZE])
+                               ts->counts[BGP_STATS_ASPATH_MAXSIZE] = size;
+
+                       ts->counts[BGP_STATS_ASPATH_TOTHOPS] += hops;
+                       ts->counts[BGP_STATS_ASPATH_TOTSIZE] += size;
 #if 0
               ts->counts[BGP_STATS_ASPATH_AVGHOPS]
                 = ravg_tally (ts->counts[BGP_STATS_ASPATH_COUNT],
@@ -10318,12 +10294,52 @@ static int bgp_table_stats_walker(struct thread *t)
                               ts->counts[BGP_STATS_ASPATH_AVGSIZE],
                               size);
 #endif
-                               if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
-                                       ts->counts[BGP_STATS_ASN_HIGHEST] =
-                                               highest;
-                       }
+                       if (highest > ts->counts[BGP_STATS_ASN_HIGHEST])
+                               ts->counts[BGP_STATS_ASN_HIGHEST] = highest;
+               }
+       }
+}
+
+static int bgp_table_stats_walker(struct thread *t)
+{
+       struct bgp_node *rn, *nrn;
+       struct bgp_node *top;
+       struct bgp_table_stats *ts = THREAD_ARG(t);
+       unsigned int space = 0;
+
+       if (!(top = bgp_table_top(ts->table)))
+               return 0;
+
+       switch (ts->table->afi) {
+       case AFI_IP:
+               space = IPV4_MAX_BITLEN;
+               break;
+       case AFI_IP6:
+               space = IPV6_MAX_BITLEN;
+               break;
+       default:
+               return 0;
+       }
+
+       ts->counts[BGP_STATS_MAXBITLEN] = space;
+
+       for (rn = top; rn; rn = bgp_route_next(rn)) {
+               if (ts->table->safi == SAFI_MPLS_VPN) {
+                       struct bgp_table *table;
+
+                       table = bgp_node_get_bgp_table_info(rn);
+                       if (!table)
+                               continue;
+
+                       top = bgp_table_top(table);
+                       for (nrn = bgp_table_top(table); nrn;
+                            nrn = bgp_route_next(nrn))
+                               bgp_table_stats_rn(nrn, top, ts, space);
+               } else {
+                       bgp_table_stats_rn(rn, top, ts, space);
                }
        }
+
        return 0;
 }