FD.io VPP  v17.07.01-10-g3be13f0
Vector Packet Processing
stats.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include <vpp/stats/stats.h>
16 #include <signal.h>
17 #include <vlib/threads.h>
18 #include <vnet/fib/fib_entry.h>
19 #include <vnet/fib/fib_table.h>
20 #include <vnet/fib/ip4_fib.h>
21 #include <vnet/dpo/load_balance.h>
22 
23 #define STATS_DEBUG 0
24 
26 
27 #include <vnet/ip/ip.h>
28 
29 #include <vpp/api/vpe_msg_enum.h>
30 
31 #define f64_endian(a)
32 #define f64_print(a,b)
33 
34 #define vl_typedefs /* define message structures */
35 #include <vpp/api/vpe_all_api_h.h>
36 #undef vl_typedefs
37 
38 #define vl_endianfun /* define message structures */
39 #include <vpp/api/vpe_all_api_h.h>
40 #undef vl_endianfun
41 
42 /* instantiate all the print functions we know about */
43 #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
44 #define vl_printfun
45 #include <vpp/api/vpe_all_api_h.h>
46 #undef vl_printfun
47 
48 #define foreach_stats_msg \
49 _(WANT_STATS, want_stats) \
50 _(VNET_INTERFACE_SIMPLE_COUNTERS, vnet_interface_simple_counters) \
51 _(VNET_INTERFACE_COMBINED_COUNTERS, vnet_interface_combined_counters) \
52 _(VNET_IP4_FIB_COUNTERS, vnet_ip4_fib_counters) \
53 _(VNET_IP6_FIB_COUNTERS, vnet_ip6_fib_counters) \
54 _(VNET_IP4_NBR_COUNTERS, vnet_ip4_nbr_counters) \
55 _(VNET_IP6_NBR_COUNTERS, vnet_ip6_nbr_counters)
56 
57 /* These constants ensure msg sizes <= 1024, aka ring allocation */
58 #define SIMPLE_COUNTER_BATCH_SIZE 126
59 #define COMBINED_COUNTER_BATCH_SIZE 63
60 #define IP4_FIB_COUNTER_BATCH_SIZE 48
61 #define IP6_FIB_COUNTER_BATCH_SIZE 30
62 
63 /* 5ms */
64 #define STATS_RELEASE_DELAY_NS (1000 * 1000 * 5)
65 /* ns/us us/ms */
66 
67 void
68 dslock (stats_main_t * sm, int release_hint, int tag)
69 {
70  u32 thread_index;
72 
73  if (PREDICT_FALSE (l == 0))
74  return;
75 
76  thread_index = vlib_get_thread_index ();
77  if (l->lock && l->thread_index == thread_index)
78  {
79  l->count++;
80  return;
81  }
82 
83  if (release_hint)
84  l->release_hint++;
85 
86  while (__sync_lock_test_and_set (&l->lock, 1))
87  /* zzzz */ ;
88  l->tag = tag;
89  l->thread_index = thread_index;
90  l->count = 1;
91 }
92 
93 void
94 stats_dslock_with_hint (int hint, int tag)
95 {
96  stats_main_t *sm = &stats_main;
97  dslock (sm, hint, tag);
98 }
99 
100 void
102 {
103  u32 thread_index;
105 
106  if (PREDICT_FALSE (l == 0))
107  return;
108 
109  thread_index = vlib_get_thread_index ();
110  ASSERT (l->lock && l->thread_index == thread_index);
111  l->count--;
112  if (l->count == 0)
113  {
114  l->tag = -l->tag;
115  l->release_hint = 0;
117  l->lock = 0;
118  }
119 }
120 
121 void
122 stats_dsunlock (int hint, int tag)
123 {
124  stats_main_t *sm = &stats_main;
125  dsunlock (sm);
126 }
127 
128 static void
130 {
133  api_main_t *am = sm->api_main;
137  u32 items_this_message = 0;
138  u64 v, *vp = 0;
139  int i, n_counts;
140 
141  /*
142  * Prevent interface registration from expanding / moving the vectors...
143  * That tends never to happen, so we can hold this lock for a while.
144  */
146 
147  vec_foreach (cm, im->sw_if_counters)
148  {
149  n_counts = vlib_simple_counter_n_counters (cm);
150  for (i = 0; i < n_counts; i++)
151  {
152  if (mp == 0)
153  {
154  items_this_message = clib_min (SIMPLE_COUNTER_BATCH_SIZE,
155  n_counts - i);
156 
158  (sizeof (*mp) + items_this_message * sizeof (v));
159  mp->_vl_msg_id = ntohs (VL_API_VNET_INTERFACE_SIMPLE_COUNTERS);
160  mp->vnet_counter_type = cm - im->sw_if_counters;
161  mp->first_sw_if_index = htonl (i);
162  mp->count = 0;
163  vp = (u64 *) mp->data;
164  }
165  v = vlib_get_simple_counter (cm, i);
166  clib_mem_unaligned (vp, u64) = clib_host_to_net_u64 (v);
167  vp++;
168  mp->count++;
169  if (mp->count == items_this_message)
170  {
171  mp->count = htonl (items_this_message);
172  /* Send to the main thread... */
173  vl_msg_api_send_shmem (q, (u8 *) & mp);
174  mp = 0;
175  }
176  }
177  ASSERT (mp == 0);
178  }
180 }
181 
182 static void
184 {
187  api_main_t *am = sm->api_main;
191  u32 items_this_message = 0;
192  vlib_counter_t v, *vp = 0;
193  int i, n_counts;
194 
196 
198  {
199  n_counts = vlib_combined_counter_n_counters (cm);
200  for (i = 0; i < n_counts; i++)
201  {
202  if (mp == 0)
203  {
204  items_this_message = clib_min (COMBINED_COUNTER_BATCH_SIZE,
205  n_counts - i);
206 
208  (sizeof (*mp) + items_this_message * sizeof (v));
209  mp->_vl_msg_id = ntohs (VL_API_VNET_INTERFACE_COMBINED_COUNTERS);
211  mp->first_sw_if_index = htonl (i);
212  mp->count = 0;
213  vp = (vlib_counter_t *) mp->data;
214  }
215  vlib_get_combined_counter (cm, i, &v);
217  = clib_host_to_net_u64 (v.packets);
218  clib_mem_unaligned (&vp->bytes, u64) = clib_host_to_net_u64 (v.bytes);
219  vp++;
220  mp->count++;
221  if (mp->count == items_this_message)
222  {
223  mp->count = htonl (items_this_message);
224  /* Send to the main thread... */
225  vl_msg_api_send_shmem (q, (u8 *) & mp);
226  mp = 0;
227  }
228  }
229  ASSERT (mp == 0);
230  }
232 }
233 
234 /* from .../vnet/vnet/ip/lookup.c. Yuck */
235 typedef CLIB_PACKED (struct
236  {
237  ip4_address_t address;
238 u32 address_length: 6;
239 u32 index: 26;
240  }) ip4_route_t;
241 
242 static void
243 ip46_fib_stats_delay (stats_main_t * sm, u32 sec, u32 nsec)
244 {
245  struct timespec _req, *req = &_req;
246  struct timespec _rem, *rem = &_rem;
247 
248  req->tv_sec = sec;
249  req->tv_nsec = nsec;
250  while (1)
251  {
252  if (nanosleep (req, rem) == 0)
253  break;
254  *req = *rem;
255  if (errno == EINTR)
256  continue;
257  clib_unix_warning ("nanosleep");
258  break;
259  }
260 }
261 
262 /**
263  * @brief The context passed when collecting adjacency counters
264  */
265 typedef struct ip4_nbr_stats_ctx_t_
266 {
267  /**
268  * The SW IF index all these adjs belong to
269  */
271 
272  /**
273  * A vector of ip4 nbr counters
274  */
277 
278 static adj_walk_rc_t
280 {
281  vl_api_ip4_nbr_counter_t *vl_counter;
282  vlib_counter_t adj_counter;
283  ip4_nbr_stats_ctx_t *ctx;
284  ip_adjacency_t *adj;
285 
286  ctx = arg;
287  vlib_get_combined_counter (&adjacency_counters, ai, &adj_counter);
288 
289  if (0 != adj_counter.packets)
290  {
291  vec_add2 (ctx->counters, vl_counter, 1);
292  adj = adj_get (ai);
293 
294  vl_counter->packets = clib_host_to_net_u64 (adj_counter.packets);
295  vl_counter->bytes = clib_host_to_net_u64 (adj_counter.bytes);
296  vl_counter->address = adj->sub_type.nbr.next_hop.ip4.as_u32;
297  vl_counter->link_type = adj->ia_link;
298  }
299  return (ADJ_WALK_RC_CONTINUE);
300 }
301 
302 #define MIN(x,y) (((x)<(y))?(x):(y))
303 
304 static void
306 {
307  api_main_t *am = sm->api_main;
311  int first = 0;
312 
313  /*
314  * If the walk context has counters, which may be left over from the last
315  * suspend, then we continue from there.
316  */
317  while (0 != vec_len (ctx->counters))
318  {
319  u32 n_items = MIN (vec_len (ctx->counters),
321  u8 pause = 0;
322 
323  dslock (sm, 0 /* release hint */ , 1 /* tag */ );
324 
325  mp = vl_msg_api_alloc_as_if_client (sizeof (*mp) +
326  (n_items *
327  sizeof
329  mp->_vl_msg_id = ntohs (VL_API_VNET_IP4_NBR_COUNTERS);
330  mp->count = ntohl (n_items);
331  mp->sw_if_index = ntohl (ctx->sw_if_index);
332  mp->begin = first;
333  first = 0;
334 
335  /*
336  * copy the counters from the back of the context, then we can easily
337  * 'erase' them by resetting the vector length.
338  * The order we push the stats to the caller is not important.
339  */
340  clib_memcpy (mp->c,
341  &ctx->counters[vec_len (ctx->counters) - n_items],
342  n_items * sizeof (*ctx->counters));
343 
344  _vec_len (ctx->counters) = vec_len (ctx->counters) - n_items;
345 
346  /*
347  * send to the shm q
348  */
351 
352  vl_msg_api_send_shmem_nolock (q, (u8 *) & mp);
354  dsunlock (sm);
355 
356  if (pause)
357  ip46_fib_stats_delay (sm, 0 /* sec */ ,
359  }
360 }
361 
362 static void
364 {
365  vnet_main_t *vnm = vnet_get_main ();
368 
369  ip4_nbr_stats_ctx_t ctx = {
370  .sw_if_index = 0,
371  .counters = NULL,
372  };
373 
374  /* *INDENT-OFF* */
375  pool_foreach (si, im->sw_interfaces,
376  ({
377  /*
378  * update the interface we are now concerned with
379  */
380  ctx.sw_if_index = si->sw_if_index;
381 
382  /*
383  * we are about to walk another interface, so we shouldn't have any pending
384  * stats to export.
385  */
386  ASSERT(ctx.counters == NULL);
387 
388  /*
389  * visit each neighbour adjacency on the interface and collect
390  * its current stats.
391  * Because we hold the lock the walk is synchronous, so safe to routing
392  * updates. It's limited in work by the number of adjacenies on an
393  * interface, which is typically not huge.
394  */
395  dslock (sm, 0 /* release hint */ , 1 /* tag */ );
396  adj_nbr_walk (si->sw_if_index,
397  FIB_PROTOCOL_IP4,
398  ip4_nbr_stats_cb,
399  &ctx);
400  dsunlock (sm);
401 
402  /*
403  * if this interface has some adjacencies with counters then ship them,
404  * else continue to the next interface.
405  */
406  if (NULL != ctx.counters)
407  {
408  ip4_nbr_ship(sm, &ctx);
409  }
410  }));
411  /* *INDENT-OFF* */
412 }
413 
414 /**
415  * @brief The context passed when collecting adjacency counters
416  */
417 typedef struct ip6_nbr_stats_ctx_t_
418 {
419  /**
420  * The SW IF index all these adjs belong to
421  */
423 
424  /**
425  * A vector of ip6 nbr counters
426  */
429 
430 static adj_walk_rc_t
432  void *arg)
433 {
434  vl_api_ip6_nbr_counter_t *vl_counter;
435  vlib_counter_t adj_counter;
436  ip6_nbr_stats_ctx_t *ctx;
437  ip_adjacency_t *adj;
438 
439  ctx = arg;
440  vlib_get_combined_counter(&adjacency_counters, ai, &adj_counter);
441 
442  if (0 != adj_counter.packets)
443  {
444  vec_add2(ctx->counters, vl_counter, 1);
445  adj = adj_get(ai);
446 
447  vl_counter->packets = clib_host_to_net_u64(adj_counter.packets);
448  vl_counter->bytes = clib_host_to_net_u64(adj_counter.bytes);
449  vl_counter->address[0] = adj->sub_type.nbr.next_hop.ip6.as_u64[0];
450  vl_counter->address[1] = adj->sub_type.nbr.next_hop.ip6.as_u64[1];
451  vl_counter->link_type = adj->ia_link;
452  }
453  return (ADJ_WALK_RC_CONTINUE);
454 }
455 
456 #define MIN(x,y) (((x)<(y))?(x):(y))
457 
458 static void
460  ip6_nbr_stats_ctx_t *ctx)
461 {
462  api_main_t *am = sm->api_main;
466  int first = 0;
467 
468  /*
469  * If the walk context has counters, which may be left over from the last
470  * suspend, then we continue from there.
471  */
472  while (0 != vec_len(ctx->counters))
473  {
474  u32 n_items = MIN (vec_len (ctx->counters),
476  u8 pause = 0;
477 
478  dslock (sm, 0 /* release hint */ , 1 /* tag */ );
479 
480  mp = vl_msg_api_alloc_as_if_client (sizeof (*mp) +
481  (n_items *
482  sizeof
484  mp->_vl_msg_id = ntohs (VL_API_VNET_IP6_NBR_COUNTERS);
485  mp->count = ntohl (n_items);
486  mp->sw_if_index = ntohl (ctx->sw_if_index);
487  mp->begin = first;
488  first = 0;
489 
490  /*
491  * copy the counters from the back of the context, then we can easily
492  * 'erase' them by resetting the vector length.
493  * The order we push the stats to the caller is not important.
494  */
495  clib_memcpy (mp->c,
496  &ctx->counters[vec_len (ctx->counters) - n_items],
497  n_items * sizeof (*ctx->counters));
498 
499  _vec_len (ctx->counters) = vec_len (ctx->counters) - n_items;
500 
501  /*
502  * send to the shm q
503  */
506 
507  vl_msg_api_send_shmem_nolock (q, (u8 *) & mp);
509  dsunlock (sm);
510 
511  if (pause)
512  ip46_fib_stats_delay (sm, 0 /* sec */ ,
514  }
515 }
516 
517 static void
519 {
520  vnet_main_t *vnm = vnet_get_main ();
523 
524  ip6_nbr_stats_ctx_t ctx = {
525  .sw_if_index = 0,
526  .counters = NULL,
527  };
528 
529  /* *INDENT-OFF* */
530  pool_foreach (si, im->sw_interfaces,
531  ({
532  /*
533  * update the interface we are now concerned with
534  */
535  ctx.sw_if_index = si->sw_if_index;
536 
537  /*
538  * we are about to walk another interface, so we shouldn't have any pending
539  * stats to export.
540  */
541  ASSERT(ctx.counters == NULL);
542 
543  /*
544  * visit each neighbour adjacency on the interface and collect
545  * its current stats.
546  * Because we hold the lock the walk is synchronous, so safe to routing
547  * updates. It's limited in work by the number of adjacenies on an
548  * interface, which is typically not huge.
549  */
550  dslock (sm, 0 /* release hint */ , 1 /* tag */ );
551  adj_nbr_walk (si->sw_if_index,
552  FIB_PROTOCOL_IP6,
553  ip6_nbr_stats_cb,
554  &ctx);
555  dsunlock (sm);
556 
557  /*
558  * if this interface has some adjacencies with counters then ship them,
559  * else continue to the next interface.
560  */
561  if (NULL != ctx.counters)
562  {
563  ip6_nbr_ship(sm, &ctx);
564  }
565  }));
566  /* *INDENT-OFF* */
567 }
568 
569 static void
571 {
572  ip4_main_t *im4 = &ip4_main;
573  api_main_t *am = sm->api_main;
576  static ip4_route_t *routes;
577  ip4_route_t *r;
578  fib_table_t *fib;
579  ip4_fib_t *v4_fib;
580  ip_lookup_main_t *lm = &im4->lookup_main;
581  static uword *results;
583  u32 items_this_message;
584  vl_api_ip4_fib_counter_t *ctrp = 0;
585  u32 start_at_fib_index = 0;
586  int i;
587 
588 again:
589  /* *INDENT-OFF* */
590  pool_foreach (fib, im4->fibs,
591  ({
592  /* We may have bailed out due to control-plane activity */
593  while ((fib - im4->fibs) < start_at_fib_index)
594  continue;
595 
596  v4_fib = pool_elt_at_index (im4->v4_fibs, fib->ft_index);
597 
598  if (mp == 0)
599  {
600  items_this_message = IP4_FIB_COUNTER_BATCH_SIZE;
601  mp = vl_msg_api_alloc_as_if_client
602  (sizeof (*mp) +
603  items_this_message * sizeof (vl_api_ip4_fib_counter_t));
604  mp->_vl_msg_id = ntohs (VL_API_VNET_IP4_FIB_COUNTERS);
605  mp->count = 0;
606  mp->vrf_id = ntohl (fib->ft_table_id);
607  ctrp = (vl_api_ip4_fib_counter_t *) mp->c;
608  }
609  else
610  {
611  /* happens if the last FIB was empty... */
612  ASSERT (mp->count == 0);
613  mp->vrf_id = ntohl (fib->ft_table_id);
614  }
615 
616  dslock (sm, 0 /* release hint */ , 1 /* tag */ );
617 
618  vec_reset_length (routes);
619  vec_reset_length (results);
620 
621  for (i = 0; i < ARRAY_LEN (v4_fib->fib_entry_by_dst_address); i++)
622  {
623  uword *hash = v4_fib->fib_entry_by_dst_address[i];
624  hash_pair_t *p;
625  ip4_route_t x;
626 
627  x.address_length = i;
628 
629  hash_foreach_pair (p, hash,
630  ({
631  x.address.data_u32 = p->key;
632  x.index = p->value[0];
633 
634  vec_add1 (routes, x);
636  {
637  start_at_fib_index = fib - im4->fibs;
638  dsunlock (sm);
639  ip46_fib_stats_delay (sm, 0 /* sec */,
641  mp->count = 0;
642  ctrp = (vl_api_ip4_fib_counter_t *)mp->c;
643  goto again;
644  }
645  }));
646  }
647 
648  vec_foreach (r, routes)
649  {
651 
653  r->index, &c);
654  /*
655  * If it has actually
656  * seen at least one packet, send it.
657  */
658  if (c.packets > 0)
659  {
660 
661  /* already in net byte order */
662  ctrp->address = r->address.as_u32;
663  ctrp->address_length = r->address_length;
664  ctrp->packets = clib_host_to_net_u64 (c.packets);
665  ctrp->bytes = clib_host_to_net_u64 (c.bytes);
666  mp->count++;
667  ctrp++;
668 
669  if (mp->count == items_this_message)
670  {
671  mp->count = htonl (items_this_message);
672  /*
673  * If the main thread's input queue is stuffed,
674  * drop the data structure lock (which the main thread
675  * may want), and take a pause.
676  */
679  {
680  dsunlock (sm);
681  vl_msg_api_send_shmem_nolock (q, (u8 *) & mp);
683  mp = 0;
684  ip46_fib_stats_delay (sm, 0 /* sec */ ,
686  goto again;
687  }
688  vl_msg_api_send_shmem_nolock (q, (u8 *) & mp);
690 
691  items_this_message = IP4_FIB_COUNTER_BATCH_SIZE;
693  (sizeof (*mp) +
694  items_this_message * sizeof (vl_api_ip4_fib_counter_t));
695  mp->_vl_msg_id = ntohs (VL_API_VNET_IP4_FIB_COUNTERS);
696  mp->count = 0;
697  mp->vrf_id = ntohl (fib->ft_table_id);
698  ctrp = (vl_api_ip4_fib_counter_t *) mp->c;
699  }
700  } /* for each (mp or single) adj */
702  {
703  start_at_fib_index = fib - im4->fibs;
704  dsunlock (sm);
705  ip46_fib_stats_delay (sm, 0 /* sec */ , STATS_RELEASE_DELAY_NS);
706  mp->count = 0;
707  ctrp = (vl_api_ip4_fib_counter_t *) mp->c;
708  goto again;
709  }
710  } /* vec_foreach (routes) */
711 
712  dsunlock (sm);
713 
714  /* Flush any data from this fib */
715  if (mp->count)
716  {
717  mp->count = htonl (mp->count);
718  vl_msg_api_send_shmem (q, (u8 *) & mp);
719  mp = 0;
720  }
721  }));
722  /* *INDENT-ON* */
723 
724  /* If e.g. the last FIB had no reportable routes, free the buffer */
725  if (mp)
726  vl_msg_api_free (mp);
727 }
728 
729 typedef struct
730 {
734 } ip6_route_t;
735 
736 typedef struct
737 {
742 
743 static void
744 add_routes_in_fib (BVT (clib_bihash_kv) * kvp, void *arg)
745 {
746  add_routes_in_fib_arg_t *ap = arg;
747  stats_main_t *sm = ap->sm;
748 
750  clib_longjmp (&sm->jmp_buf, 1);
751 
752  if (kvp->key[2] >> 32 == ap->fib_index)
753  {
755  ip6_route_t *r;
756  addr = (ip6_address_t *) kvp;
757  vec_add2 (*ap->routep, r, 1);
758  r->address = addr[0];
759  r->address_length = kvp->key[2] & 0xFF;
760  r->index = kvp->value;
761  }
762 }
763 
764 static void
766 {
767  ip6_main_t *im6 = &ip6_main;
768  api_main_t *am = sm->api_main;
771  static ip6_route_t *routes;
772  ip6_route_t *r;
773  fib_table_t *fib;
774  static uword *results;
776  u32 items_this_message;
777  vl_api_ip6_fib_counter_t *ctrp = 0;
778  u32 start_at_fib_index = 0;
779  BVT (clib_bihash) * h = &im6->ip6_table[IP6_FIB_TABLE_FWDING].ip6_hash;
780  add_routes_in_fib_arg_t _a, *a = &_a;
781 
782 again:
783  /* *INDENT-OFF* */
784  pool_foreach (fib, im6->fibs,
785  ({
786  /* We may have bailed out due to control-plane activity */
787  while ((fib - im6->fibs) < start_at_fib_index)
788  continue;
789 
790  if (mp == 0)
791  {
792  items_this_message = IP6_FIB_COUNTER_BATCH_SIZE;
793  mp = vl_msg_api_alloc_as_if_client
794  (sizeof (*mp) +
795  items_this_message * sizeof (vl_api_ip6_fib_counter_t));
796  mp->_vl_msg_id = ntohs (VL_API_VNET_IP6_FIB_COUNTERS);
797  mp->count = 0;
798  mp->vrf_id = ntohl (fib->ft_table_id);
799  ctrp = (vl_api_ip6_fib_counter_t *) mp->c;
800  }
801 
802  dslock (sm, 0 /* release hint */ , 1 /* tag */ );
803 
804  vec_reset_length (routes);
805  vec_reset_length (results);
806 
807  a->fib_index = fib - im6->fibs;
808  a->routep = &routes;
809  a->sm = sm;
810 
811  if (clib_setjmp (&sm->jmp_buf, 0) == 0)
812  {
813  start_at_fib_index = fib - im6->fibs;
815  }
816  else
817  {
818  dsunlock (sm);
819  ip46_fib_stats_delay (sm, 0 /* sec */ ,
821  mp->count = 0;
822  ctrp = (vl_api_ip6_fib_counter_t *) mp->c;
823  goto again;
824  }
825 
826  vec_foreach (r, routes)
827  {
829 
831  r->index, &c);
832  /*
833  * If it has actually
834  * seen at least one packet, send it.
835  */
836  if (c.packets > 0)
837  {
838  /* already in net byte order */
839  ctrp->address[0] = r->address.as_u64[0];
840  ctrp->address[1] = r->address.as_u64[1];
841  ctrp->address_length = (u8) r->address_length;
842  ctrp->packets = clib_host_to_net_u64 (c.packets);
843  ctrp->bytes = clib_host_to_net_u64 (c.bytes);
844  mp->count++;
845  ctrp++;
846 
847  if (mp->count == items_this_message)
848  {
849  mp->count = htonl (items_this_message);
850  /*
851  * If the main thread's input queue is stuffed,
852  * drop the data structure lock (which the main thread
853  * may want), and take a pause.
854  */
857  {
858  dsunlock (sm);
859  vl_msg_api_send_shmem_nolock (q, (u8 *) & mp);
861  mp = 0;
862  ip46_fib_stats_delay (sm, 0 /* sec */ ,
864  goto again;
865  }
866  vl_msg_api_send_shmem_nolock (q, (u8 *) & mp);
868 
869  items_this_message = IP6_FIB_COUNTER_BATCH_SIZE;
871  (sizeof (*mp) +
872  items_this_message * sizeof (vl_api_ip6_fib_counter_t));
873  mp->_vl_msg_id = ntohs (VL_API_VNET_IP6_FIB_COUNTERS);
874  mp->count = 0;
875  mp->vrf_id = ntohl (fib->ft_table_id);
876  ctrp = (vl_api_ip6_fib_counter_t *) mp->c;
877  }
878  }
879 
881  {
882  start_at_fib_index = fib - im6->fibs;
883  dsunlock (sm);
884  ip46_fib_stats_delay (sm, 0 /* sec */ , STATS_RELEASE_DELAY_NS);
885  mp->count = 0;
886  ctrp = (vl_api_ip6_fib_counter_t *) mp->c;
887  goto again;
888  }
889  } /* vec_foreach (routes) */
890 
891  dsunlock (sm);
892 
893  /* Flush any data from this fib */
894  if (mp->count)
895  {
896  mp->count = htonl (mp->count);
897  vl_msg_api_send_shmem (q, (u8 *) & mp);
898  mp = 0;
899  }
900  }));
901  /* *INDENT-ON* */
902 
903  /* If e.g. the last FIB had no reportable routes, free the buffer */
904  if (mp)
905  vl_msg_api_free (mp);
906 }
907 
908 static void
909 stats_thread_fn (void *arg)
910 {
911  stats_main_t *sm = &stats_main;
914 
915  /* stats thread wants no signals. */
916  {
917  sigset_t s;
918  sigfillset (&s);
919  pthread_sigmask (SIG_SETMASK, &s, 0);
920  }
921 
922  if (vec_len (tm->thread_prefix))
923  vlib_set_thread_name ((char *)
924  format (0, "%v_stats%c", tm->thread_prefix, '\0'));
925 
927 
928  while (1)
929  {
930  /* 10 second poll interval */
931  ip46_fib_stats_delay (sm, 10 /* secs */ , 0 /* nsec */ );
932 
933  if (!(sm->enable_poller))
934  continue;
937  do_ip4_fibs (sm);
938  do_ip6_fibs (sm);
939  do_ip4_nbrs (sm);
940  do_ip6_nbrs (sm);
941  }
942 }
943 
944 static void
947 {
949  stats_main_t *sm = &stats_main;
950  unix_shared_memory_queue_t *q, *q_prev = NULL;
952  u32 mp_size;
953 
954 #if STATS_DEBUG > 0
955  char *counter_name;
956  u32 count, sw_if_index;
957  int i;
958 #endif
959 
960  mp_size = sizeof (*mp) + (ntohl (mp->count) * sizeof (u64));
961 
962  /* *INDENT-OFF* */
964  ({
965  q = vl_api_client_index_to_input_queue (reg->client_index);
966  if (q)
967  {
968  if (q_prev && (q_prev->cursize < q_prev->maxsize))
969  {
970  mp_copy = vl_msg_api_alloc_as_if_client(mp_size);
971  clib_memcpy(mp_copy, mp, mp_size);
972  vl_msg_api_send_shmem (q_prev, (u8 *)&mp);
973  mp = mp_copy;
974  }
975  q_prev = q;
976  }
977  }));
978  /* *INDENT-ON* */
979 
980 #if STATS_DEBUG > 0
981  count = ntohl (mp->count);
982  sw_if_index = ntohl (mp->first_sw_if_index);
983  u64 *vp, v;
984  vp = (u64 *) mp->data;
985 
986  switch (mp->vnet_counter_type)
987  {
989  counter_name = "drop";
990  break;
992  counter_name = "punt";
993  break;
995  counter_name = "ip4";
996  break;
998  counter_name = "ip6";
999  break;
1001  counter_name = "rx-no-buff";
1002  break;
1004  , counter_name = "rx-miss";
1005  break;
1007  , counter_name = "rx-error (fifo-full)";
1008  break;
1010  , counter_name = "tx-error (fifo-full)";
1011  break;
1012  default:
1013  counter_name = "bogus";
1014  break;
1015  }
1016  for (i = 0; i < count; i++)
1017  {
1018  v = clib_mem_unaligned (vp, u64);
1019  v = clib_net_to_host_u64 (v);
1020  vp++;
1021  fformat (stdout, "%U.%s %lld\n", format_vnet_sw_if_index_name,
1022  sm->vnet_main, sw_if_index, counter_name, v);
1023  sw_if_index++;
1024  }
1025 #endif
1026  if (q_prev && (q_prev->cursize < q_prev->maxsize))
1027  {
1028  vl_msg_api_send_shmem (q_prev, (u8 *) & mp);
1029  }
1030  else
1031  {
1032  vl_msg_api_free (mp);
1033  }
1034 }
1035 
1036 static void
1039 {
1041  stats_main_t *sm = &stats_main;
1042  unix_shared_memory_queue_t *q, *q_prev = NULL;
1044  u32 mp_size;
1045 
1046 #if STATS_DEBUG > 0
1047  char *counter_name;
1048  u32 count, sw_if_index;
1049  int i;
1050 #endif
1051 
1052  mp_size = sizeof (*mp) + (ntohl (mp->count) * sizeof (vlib_counter_t));
1053 
1054  /* *INDENT-OFF* */
1056  ({
1057  q = vl_api_client_index_to_input_queue (reg->client_index);
1058  if (q)
1059  {
1060  if (q_prev && (q_prev->cursize < q_prev->maxsize))
1061  {
1062  mp_copy = vl_msg_api_alloc_as_if_client(mp_size);
1063  clib_memcpy(mp_copy, mp, mp_size);
1064  vl_msg_api_send_shmem (q_prev, (u8 *)&mp);
1065  mp = mp_copy;
1066  }
1067  q_prev = q;
1068  }
1069  }));
1070  /* *INDENT-ON* */
1071 
1072 #if STATS_DEBUG > 0
1073  count = ntohl (mp->count);
1074  sw_if_index = ntohl (mp->first_sw_if_index);
1075 
1076  vlib_counter_t *vp;
1077  u64 packets, bytes;
1078  vp = (vlib_counter_t *) mp->data;
1079 
1080  switch (mp->vnet_counter_type)
1081  {
1083  counter_name = "rx";
1084  break;
1086  counter_name = "tx";
1087  break;
1088  default:
1089  counter_name = "bogus";
1090  break;
1091  }
1092  for (i = 0; i < count; i++)
1093  {
1094  packets = clib_mem_unaligned (&vp->packets, u64);
1095  packets = clib_net_to_host_u64 (packets);
1096  bytes = clib_mem_unaligned (&vp->bytes, u64);
1097  bytes = clib_net_to_host_u64 (bytes);
1098  vp++;
1099  fformat (stdout, "%U.%s.packets %lld\n",
1101  sm->vnet_main, sw_if_index, counter_name, packets);
1102  fformat (stdout, "%U.%s.bytes %lld\n",
1104  sm->vnet_main, sw_if_index, counter_name, bytes);
1105  sw_if_index++;
1106  }
1107 
1108 #endif
1109  if (q_prev && (q_prev->cursize < q_prev->maxsize))
1110  {
1111  vl_msg_api_send_shmem (q_prev, (u8 *) & mp);
1112  }
1113  else
1114  {
1115  vl_msg_api_free (mp);
1116  }
1117 }
1118 
1119 static void
1121 {
1123  stats_main_t *sm = &stats_main;
1124  unix_shared_memory_queue_t *q, *q_prev = NULL;
1126  u32 mp_size;
1127 
1128  mp_size = sizeof (*mp_copy) +
1129  ntohl (mp->count) * sizeof (vl_api_ip4_fib_counter_t);
1130 
1131  /* *INDENT-OFF* */
1133  ({
1134  q = vl_api_client_index_to_input_queue (reg->client_index);
1135  if (q)
1136  {
1137  if (q_prev && (q_prev->cursize < q_prev->maxsize))
1138  {
1139  mp_copy = vl_msg_api_alloc_as_if_client(mp_size);
1140  clib_memcpy(mp_copy, mp, mp_size);
1141  vl_msg_api_send_shmem (q_prev, (u8 *)&mp);
1142  mp = mp_copy;
1143  }
1144  q_prev = q;
1145  }
1146  }));
1147  /* *INDENT-ON* */
1148  if (q_prev && (q_prev->cursize < q_prev->maxsize))
1149  {
1150  vl_msg_api_send_shmem (q_prev, (u8 *) & mp);
1151  }
1152  else
1153  {
1154  vl_msg_api_free (mp);
1155  }
1156 }
1157 
1158 static void
1160 {
1162  stats_main_t *sm = &stats_main;
1163  unix_shared_memory_queue_t *q, *q_prev = NULL;
1165  u32 mp_size;
1166 
1167  mp_size = sizeof (*mp_copy) +
1168  ntohl (mp->count) * sizeof (vl_api_ip4_nbr_counter_t);
1169 
1170  /* *INDENT-OFF* */
1172  ({
1173  q = vl_api_client_index_to_input_queue (reg->client_index);
1174  if (q)
1175  {
1176  if (q_prev && (q_prev->cursize < q_prev->maxsize))
1177  {
1178  mp_copy = vl_msg_api_alloc_as_if_client(mp_size);
1179  clib_memcpy(mp_copy, mp, mp_size);
1180  vl_msg_api_send_shmem (q_prev, (u8 *)&mp);
1181  mp = mp_copy;
1182  }
1183  q_prev = q;
1184  }
1185  }));
1186  /* *INDENT-ON* */
1187  if (q_prev && (q_prev->cursize < q_prev->maxsize))
1188  {
1189  vl_msg_api_send_shmem (q_prev, (u8 *) & mp);
1190  }
1191  else
1192  {
1193  vl_msg_api_free (mp);
1194  }
1195 }
1196 
1197 static void
1199 {
1201  stats_main_t *sm = &stats_main;
1202  unix_shared_memory_queue_t *q, *q_prev = NULL;
1204  u32 mp_size;
1205 
1206  mp_size = sizeof (*mp_copy) +
1207  ntohl (mp->count) * sizeof (vl_api_ip6_fib_counter_t);
1208 
1209  /* *INDENT-OFF* */
1211  ({
1212  q = vl_api_client_index_to_input_queue (reg->client_index);
1213  if (q)
1214  {
1215  if (q_prev && (q_prev->cursize < q_prev->maxsize))
1216  {
1217  mp_copy = vl_msg_api_alloc_as_if_client(mp_size);
1218  clib_memcpy(mp_copy, mp, mp_size);
1219  vl_msg_api_send_shmem (q_prev, (u8 *)&mp);
1220  mp = mp_copy;
1221  }
1222  q_prev = q;
1223  }
1224  }));
1225  /* *INDENT-ON* */
1226  if (q_prev && (q_prev->cursize < q_prev->maxsize))
1227  {
1228  vl_msg_api_send_shmem (q_prev, (u8 *) & mp);
1229  }
1230  else
1231  {
1232  vl_msg_api_free (mp);
1233  }
1234 }
1235 
1236 static void
1238 {
1240  stats_main_t *sm = &stats_main;
1241  unix_shared_memory_queue_t *q, *q_prev = NULL;
1243  u32 mp_size;
1244 
1245  mp_size = sizeof (*mp_copy) +
1246  ntohl (mp->count) * sizeof (vl_api_ip6_nbr_counter_t);
1247 
1248  /* *INDENT-OFF* */
1250  ({
1251  q = vl_api_client_index_to_input_queue (reg->client_index);
1252  if (q)
1253  {
1254  if (q_prev && (q_prev->cursize < q_prev->maxsize))
1255  {
1256  mp_copy = vl_msg_api_alloc_as_if_client(mp_size);
1257  clib_memcpy(mp_copy, mp, mp_size);
1258  vl_msg_api_send_shmem (q_prev, (u8 *)&mp);
1259  mp = mp_copy;
1260  }
1261  q_prev = q;
1262  }
1263  }));
1264  /* *INDENT-ON* */
1265  if (q_prev && (q_prev->cursize < q_prev->maxsize))
1266  {
1267  vl_msg_api_send_shmem (q_prev, (u8 *) & mp);
1268  }
1269  else
1270  {
1271  vl_msg_api_free (mp);
1272  }
1273 }
1274 
1275 static void
1277 {
1278  stats_main_t *sm = &stats_main;
1280  vl_api_want_stats_reply_t *rmp;
1281  uword *p;
1282  i32 retval = 0;
1284 
1286  if (p)
1287  {
1288  if (mp->enable_disable)
1289  {
1290  clib_warning ("pid %d: already enabled...", mp->pid);
1291  retval = -2;
1292  goto reply;
1293  }
1294  else
1295  {
1296  rp = pool_elt_at_index (sm->stats_registrations, p[0]);
1297  pool_put (sm->stats_registrations, rp);
1299  goto reply;
1300  }
1301  }
1302  if (mp->enable_disable == 0)
1303  {
1304  clib_warning ("pid %d: already disabled...", mp->pid);
1305  retval = -3;
1306  goto reply;
1307  }
1308  pool_get (sm->stats_registrations, rp);
1309  rp->client_index = mp->client_index;
1310  rp->client_pid = mp->pid;
1312  rp - sm->stats_registrations);
1313 
1314 reply:
1315  if (pool_elts (sm->stats_registrations))
1316  sm->enable_poller = 1;
1317  else
1318  sm->enable_poller = 0;
1319 
1321 
1322  if (!q)
1323  return;
1324 
1325  rmp = vl_msg_api_alloc (sizeof (*rmp));
1326  rmp->_vl_msg_id = ntohs (VL_API_WANT_STATS_REPLY);
1327  rmp->context = mp->context;
1328  rmp->retval = retval;
1329 
1330  vl_msg_api_send_shmem (q, (u8 *) & rmp);
1331 }
1332 
1333 int
1335 {
1337  stats_main_t *sm = &stats_main;
1338  uword *p;
1339 
1340  p = hash_get (sm->stats_registration_hash, client_index);
1341  if (p)
1342  {
1343  rp = pool_elt_at_index (sm->stats_registrations, p[0]);
1344  pool_put (sm->stats_registrations, rp);
1345  hash_unset (sm->stats_registration_hash, client_index);
1346  }
1347 
1348  return 0;
1349 }
1350 
1351 #define vl_api_vnet_interface_simple_counters_t_endian vl_noop_handler
1352 #define vl_api_vnet_interface_simple_counters_t_print vl_noop_handler
1353 #define vl_api_vnet_interface_combined_counters_t_endian vl_noop_handler
1354 #define vl_api_vnet_interface_combined_counters_t_print vl_noop_handler
1355 #define vl_api_vnet_ip4_fib_counters_t_endian vl_noop_handler
1356 #define vl_api_vnet_ip4_fib_counters_t_print vl_noop_handler
1357 #define vl_api_vnet_ip6_fib_counters_t_endian vl_noop_handler
1358 #define vl_api_vnet_ip6_fib_counters_t_print vl_noop_handler
1359 #define vl_api_vnet_ip4_nbr_counters_t_endian vl_noop_handler
1360 #define vl_api_vnet_ip4_nbr_counters_t_print vl_noop_handler
1361 #define vl_api_vnet_ip6_nbr_counters_t_endian vl_noop_handler
1362 #define vl_api_vnet_ip6_nbr_counters_t_print vl_noop_handler
1363 
1364 static clib_error_t *
1366 {
1367  stats_main_t *sm = &stats_main;
1368  api_main_t *am = &api_main;
1369  void *vlib_worker_thread_bootstrap_fn (void *arg);
1370 
1371  sm->vlib_main = vm;
1372  sm->vnet_main = vnet_get_main ();
1374  sm->api_main = am;
1376  sm->data_structure_lock =
1379  memset (sm->data_structure_lock, 0, sizeof (*sm->data_structure_lock));
1380 
1381 #define _(N,n) \
1382  vl_msg_api_set_handlers(VL_API_##N, #n, \
1383  vl_api_##n##_t_handler, \
1384  vl_noop_handler, \
1385  vl_api_##n##_t_endian, \
1386  vl_api_##n##_t_print, \
1387  sizeof(vl_api_##n##_t), 0 /* do NOT trace! */);
1389 #undef _
1390 
1391  /* tell the msg infra not to free these messages... */
1392  am->message_bounce[VL_API_VNET_INTERFACE_SIMPLE_COUNTERS] = 1;
1393  am->message_bounce[VL_API_VNET_INTERFACE_COMBINED_COUNTERS] = 1;
1394  am->message_bounce[VL_API_VNET_IP4_FIB_COUNTERS] = 1;
1395  am->message_bounce[VL_API_VNET_IP6_FIB_COUNTERS] = 1;
1396  am->message_bounce[VL_API_VNET_IP4_NBR_COUNTERS] = 1;
1397  am->message_bounce[VL_API_VNET_IP6_NBR_COUNTERS] = 1;
1398 
1399  return 0;
1400 }
1401 
1403 
1404 /* *INDENT-OFF* */
1405 VLIB_REGISTER_THREAD (stats_thread_reg, static) = {
1406  .name = "stats",
1407  .function = stats_thread_fn,
1408  .fixed_count = 1,
1409  .count = 1,
1410  .no_data_structure_clone = 1,
1411  .use_pthreads = 1,
1412 };
1413 /* *INDENT-ON* */
1414 
1415 /*
1416  * fd.io coding-style-patch-verification: ON
1417  *
1418  * Local Variables:
1419  * eval: (c-set-style "gnu")
1420  * End:
1421  */
static void stats_thread_fn(void *arg)
Definition: stats.c:909
void * vl_msg_api_alloc_as_if_client(int nbytes)
Want Stats, register for stats updates.
Definition: vpe.api:145
vlib_combined_counter_main_t lbm_to_counters
Definition: load_balance.h:46
#define hash_set(h, key, value)
Definition: hash.h:254
u32 vlib_simple_counter_n_counters(const vlib_simple_counter_main_t *cm)
The number of counters (not the number of per-thread counters)
Definition: counter.c:107
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:337
#define clib_min(x, y)
Definition: clib.h:332
vl_api_vlib_counter_t data[count]
Definition: interface.api:244
#define hash_unset(h, key)
Definition: hash.h:260
a
Definition: bitmap.h:516
int unix_shared_memory_queue_is_full(unix_shared_memory_queue_t *q)
static adj_walk_rc_t ip6_nbr_stats_cb(adj_index_t ai, void *arg)
Definition: stats.c:431
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
struct ip_adjacency_t_::@37::@38 nbr
IP_LOOKUP_NEXT_ARP/IP_LOOKUP_NEXT_REWRITE.
vnet_interface_main_t interface_main
Definition: vnet.h:56
static void vl_api_vnet_interface_simple_counters_t_handler(vl_api_vnet_interface_simple_counters_t *mp)
Definition: stats.c:946
u64 as_u64[2]
Definition: ip6_packet.h:51
unix_shared_memory_queue_t * vl_input_queue
Definition: api_common.h:68
#define NULL
Definition: clib.h:55
IP unicast adjacency.
Definition: adj.h:174
u8 * message_bounce
Definition: api_common.h:176
u32 enable_poller
Definition: stats.h:45
u32 sw_if_index
The SW IF index all these adjs belong to.
Definition: stats.c:422
vlib_main_t * vlib_main
Definition: stats.h:57
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:522
Combined counter to hold both packets and byte differences.
Definition: counter.h:139
#define vec_add2(V, P, N)
Add N elements to end of vector V, return pointer to new elements in P.
Definition: vec.h:561
vl_api_ip4_nbr_counter_t c[count]
Definition: vpe.api:190
VLIB_REGISTER_THREAD(stats_thread_reg, static)
ip_lookup_main_t lookup_main
Definition: ip4.h:85
void clib_longjmp(clib_longjmp_t *save, uword return_value)
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:419
union ip_adjacency_t_::@37 sub_type
Combined stats counters structure.
Definition: interface.api:238
#define MIN(x, y)
Definition: stats.c:456
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:200
uword clib_setjmp(clib_longjmp_t *save, uword return_value_not_taken)
static void vl_api_vnet_ip4_fib_counters_t_handler(vl_api_vnet_ip4_fib_counters_t *mp)
Definition: stats.c:1120
static clib_error_t * stats_init(vlib_main_t *vm)
Definition: stats.c:1365
format_function_t format_vnet_sw_if_index_name
uword * stats_registration_hash
Definition: stats.h:47
vpe_client_registration_t * stats_registrations
Definition: stats.h:48
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
uword value[0]
Definition: hash.h:164
vnet_link_t ia_link
link/ether-type 1 bytes
Definition: adj.h:195
static void vl_api_vnet_ip4_nbr_counters_t_handler(vl_api_vnet_ip4_nbr_counters_t *mp)
Definition: stats.c:1159
volatile u32 release_hint
Definition: stats.h:32
static counter_t vlib_get_simple_counter(vlib_simple_counter_main_t *cm, u32 index)
Get the value of a simple counter Scrapes the entire set of per-thread counters.
Definition: counter.h:97
static ip_adjacency_t * adj_get(adj_index_t adj_index)
Get a pointer to an adjacency object from its index.
Definition: adj.h:365
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:376
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:111
vlib_combined_counter_main_t * combined_sw_if_counters
Definition: interface.h:653
static BVT(clib_bihash)
Definition: adj_nbr.c:26
enum adj_walk_rc_t_ adj_walk_rc_t
return codes from a adjacency walker callback function
int i32
Definition: types.h:81
#define IP6_FIB_COUNTER_BATCH_SIZE
Definition: stats.c:61
unsigned long u64
Definition: types.h:89
struct vl_shmem_hdr_ * shmem_hdr
Definition: api_common.h:189
volatile u32 lock
Definition: stats.h:31
static void do_ip4_nbrs(stats_main_t *sm)
Definition: stats.c:363
A collection of simple counters.
Definition: counter.h:58
static adj_walk_rc_t ip4_nbr_stats_cb(adj_index_t ai, void *arg)
Definition: stats.c:279
void vlib_set_thread_name(char *name)
Definition: threads.c:51
void * vl_msg_api_alloc(int nbytes)
stats_main_t stats_main
Definition: stats.c:25
#define foreach_stats_msg
Definition: stats.c:48
vl_shmem_hdr_t * shmem_hdr
static heap_elt_t * first(heap_header_t *h)
Definition: heap.c:59
void dsunlock(stats_main_t *sm)
Definition: stats.c:101
struct ip4_nbr_stats_ctx_t_ ip4_nbr_stats_ctx_t
The context passed when collecting adjacency counters.
vl_api_ip4_nbr_counter_t * counters
A vector of ip4 nbr counters.
Definition: stats.c:275
#define hash_get(h, key)
Definition: hash.h:248
void * thread_mheap
Definition: threads.h:95
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:397
counter_t packets
packet counter
Definition: counter.h:141
static void do_ip6_fibs(stats_main_t *sm)
Definition: stats.c:765
#define v
Definition: acl.c:320
u32 vlib_combined_counter_n_counters(const vlib_combined_counter_main_t *cm)
The number of counters (not the number of per-thread counters)
Definition: counter.c:100
void vl_msg_api_free(void *)
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:241
#define PREDICT_FALSE(x)
Definition: clib.h:97
vlib_simple_counter_main_t * sw_if_counters
Definition: interface.h:652
load_balance_main_t load_balance_main
The one instance of load-balance main.
Definition: load_balance.c:55
static void ip4_nbr_ship(stats_main_t *sm, ip4_nbr_stats_ctx_t *ctx)
Definition: stats.c:305
#define SIMPLE_COUNTER_BATCH_SIZE
Definition: stats.c:58
void unix_shared_memory_queue_lock(unix_shared_memory_queue_t *q)
#define COMBINED_COUNTER_BATCH_SIZE
Definition: stats.c:59
vl_api_ip6_nbr_counter_t * counters
A vector of ip6 nbr counters.
Definition: stats.c:427
vlib_combined_counter_main_t adjacency_counters
Adjacency packet counters.
Definition: adj.c:25
static void do_simple_interface_counters(stats_main_t *sm)
Definition: stats.c:129
u32 index
Definition: stats.c:733
word fformat(FILE *f, char *fmt,...)
Definition: format.c:453
The context passed when collecting adjacency counters.
Definition: stats.c:265
void clib_bihash_foreach_key_value_pair(clib_bihash *h, void *callback, void *arg)
Visit active (key,value) pairs in a bi-hash table.
The IPv4 FIB.
Definition: ip4_fib.h:39
u32 sw_if_index
The SW IF index all these adjs belong to.
Definition: stats.c:270
static void add_routes_in_fib(BVT(clib_bihash_kv)*kvp, void *arg)
Definition: stats.c:744
stats_main_t * sm
Definition: stats.c:740
api_main_t api_main
Definition: api_shared.c:35
svmdb_client_t * c
static_always_inline uword vlib_get_thread_index(void)
Definition: threads.h:185
u32 ft_table_id
Table ID (hash key) for this FIB.
Definition: fib_table.h:44
static void vlib_get_combined_counter(const vlib_combined_counter_main_t *cm, u32 index, vlib_counter_t *result)
Get the value of a combined counter, never called in the speed path Scrapes the entire set of per-thr...
Definition: counter.h:250
clib_longjmp_t jmp_buf
Definition: stats.h:54
#define IP4_FIB_COUNTER_BATCH_SIZE
Definition: stats.c:60
static void * clib_mem_set_heap(void *heap)
Definition: mem.h:223
#define clib_warning(format, args...)
Definition: error.h:59
This table stores the routes that are used to forward traffic.
Definition: ip6.h:115
#define clib_memcpy(a, b, c)
Definition: string.h:69
unix_shared_memory_queue_t * vl_api_client_index_to_input_queue(u32 index)
static void vnet_interface_counter_unlock(vnet_interface_main_t *im)
Definition: interface.h:678
static void vl_api_vnet_ip6_fib_counters_t_handler(vl_api_vnet_ip6_fib_counters_t *mp)
Definition: stats.c:1198
api_main_t * api_main
Definition: stats.h:60
u32 adj_index_t
An index for adjacencies.
Definition: adj_types.h:30
#define ARRAY_LEN(x)
Definition: clib.h:59
vl_api_ip6_fib_counter_t c[count]
Definition: vpe.api:205
typedef CLIB_PACKED(struct{ip4_address_t address;u32 address_length:6;u32 index:26;})
Definition: stats.c:235
static void vnet_interface_counter_lock(vnet_interface_main_t *im)
Definition: interface.h:670
struct ip6_nbr_stats_ctx_t_ ip6_nbr_stats_ctx_t
The context passed when collecting adjacency counters.
void vl_msg_api_send_shmem(unix_shared_memory_queue_t *q, u8 *elem)
static void do_ip6_nbrs(stats_main_t *sm)
Definition: stats.c:518
#define ASSERT(truth)
void stats_dslock_with_hint(int hint, int tag)
Definition: stats.c:94
unsigned int u32
Definition: types.h:88
ip6_main_t ip6_main
Definition: ip6_forward.c:2926
static void ip6_nbr_ship(stats_main_t *sm, ip6_nbr_stats_ctx_t *ctx)
Definition: stats.c:459
#define STATS_RELEASE_DELAY_NS
Definition: stats.c:64
The context passed when collecting adjacency counters.
Definition: stats.c:417
IPv4 main type.
Definition: ip4.h:83
int stats_memclnt_delete_callback(u32 client_index)
Definition: stats.c:1334
static void do_combined_interface_counters(stats_main_t *sm)
Definition: stats.c:183
Simple stats counters structure.
Definition: interface.api:222
u32 stats_poll_interval_in_seconds
Definition: stats.h:44
ip6_fib_table_instance_t ip6_table[IP6_FIB_NUM_TABLES]
The two FIB tables; fwding and non-fwding.
Definition: ip6.h:146
u64 uword
Definition: types.h:112
void dslock(stats_main_t *sm, int release_hint, int tag)
Definition: stats.c:68
vl_api_ip4_fib_counter_t c[count]
Definition: vpe.api:165
counter_t bytes
byte counter
Definition: counter.h:142
data_structure_lock_t * data_structure_lock
Definition: stats.h:51
Per-neighbour (i.e.
Definition: vpe.api:185
void vl_msg_api_send_shmem_nolock(unix_shared_memory_queue_t *q, u8 *elem)
void unix_shared_memory_queue_unlock(unix_shared_memory_queue_t *q)
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
vnet_interface_main_t * interface_main
Definition: stats.h:59
unsigned char u8
Definition: types.h:56
static void vl_api_want_stats_t_handler(vl_api_want_stats_t *mp)
Definition: stats.c:1276
#define hash_foreach_pair(p, v, body)
Iterate over hash pairs.
Definition: hash.h:349
vnet_sw_interface_t * sw_interfaces
Definition: interface.h:644
#define clib_unix_warning(format, args...)
Definition: error.h:68
u32 address_length
Definition: stats.c:732
A collection of combined counters.
Definition: counter.h:180
uword * fib_entry_by_dst_address[33]
Definition: ip4_fib.h:48
#define clib_mem_unaligned(pointer, type)
Definition: types.h:155
static void do_ip4_fibs(stats_main_t *sm)
Definition: stats.c:570
static void vl_api_vnet_ip6_nbr_counters_t_handler(vl_api_vnet_ip6_nbr_counters_t *mp)
Definition: stats.c:1237
static void * clib_mem_alloc_aligned(uword size, uword align)
Definition: mem.h:117
ip4_main_t ip4_main
Global ip4 main structure.
Definition: ip4_forward.c:1168
static vlib_thread_main_t * vlib_get_thread_main()
Definition: global_funcs.h:32
ip6_route_t ** routep
Definition: stats.c:739
struct fib_table_t_ * fibs
Vector of FIBs.
Definition: ip4.h:88
#define vec_foreach(var, vec)
Vector iterator.
void * vlib_worker_thread_bootstrap_fn(void *arg)
Definition: threads.c:454
#define CLIB_MEMORY_BARRIER()
Definition: clib.h:101
static void vl_api_vnet_interface_combined_counters_t_handler(vl_api_vnet_interface_combined_counters_t *mp)
Definition: stats.c:1038
vhost_vring_addr_t addr
Definition: vhost-user.h:82
void stats_dsunlock(int hint, int tag)
Definition: stats.c:122
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:67
vnet_main_t * vnet_main
Definition: stats.h:58
struct fib_table_t_ * fibs
Definition: ip6.h:151
uword key
Definition: hash.h:161
vl_api_ip6_nbr_counter_t c[count]
Definition: vpe.api:221
A protocol Independent FIB table.
Definition: fib_table.h:29
struct _unix_shared_memory_queue unix_shared_memory_queue_t
ip6_address_t address
Definition: stats.c:731
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:109