FD.io VPP  v17.04-9-g99c0734
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/dpo/load_balance.h>
21 
22 #define STATS_DEBUG 0
23 
25 
26 #include <vnet/ip/ip.h>
27 
28 #include <vpp/api/vpe_msg_enum.h>
29 
30 #define f64_endian(a)
31 #define f64_print(a,b)
32 
33 #define vl_typedefs /* define message structures */
34 #include <vpp/api/vpe_all_api_h.h>
35 #undef vl_typedefs
36 
37 #define vl_endianfun /* define message structures */
38 #include <vpp/api/vpe_all_api_h.h>
39 #undef vl_endianfun
40 
41 /* instantiate all the print functions we know about */
42 #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
43 #define vl_printfun
44 #include <vpp/api/vpe_all_api_h.h>
45 #undef vl_printfun
46 
47 #define foreach_stats_msg \
48 _(WANT_STATS, want_stats) \
49 _(VNET_INTERFACE_COUNTERS, vnet_interface_counters) \
50 _(VNET_IP4_FIB_COUNTERS, vnet_ip4_fib_counters) \
51 _(VNET_IP6_FIB_COUNTERS, vnet_ip6_fib_counters) \
52 _(VNET_IP4_NBR_COUNTERS, vnet_ip4_nbr_counters) \
53 _(VNET_IP6_NBR_COUNTERS, vnet_ip6_nbr_counters)
54 
55 /* These constants ensure msg sizes <= 1024, aka ring allocation */
56 #define SIMPLE_COUNTER_BATCH_SIZE 126
57 #define COMBINED_COUNTER_BATCH_SIZE 63
58 #define IP4_FIB_COUNTER_BATCH_SIZE 48
59 #define IP6_FIB_COUNTER_BATCH_SIZE 30
60 
61 /* 5ms */
62 #define STATS_RELEASE_DELAY_NS (1000 * 1000 * 5)
63 /* ns/us us/ms */
64 
65 void
66 dslock (stats_main_t * sm, int release_hint, int tag)
67 {
68  u32 thread_id;
70 
71  if (PREDICT_FALSE (l == 0))
72  return;
73 
74  thread_id = os_get_cpu_number ();
75  if (l->lock && l->thread_id == thread_id)
76  {
77  l->count++;
78  return;
79  }
80 
81  if (release_hint)
82  l->release_hint++;
83 
84  while (__sync_lock_test_and_set (&l->lock, 1))
85  /* zzzz */ ;
86  l->tag = tag;
87  l->thread_id = thread_id;
88  l->count = 1;
89 }
90 
91 void
92 stats_dslock_with_hint (int hint, int tag)
93 {
94  stats_main_t *sm = &stats_main;
95  dslock (sm, hint, tag);
96 }
97 
98 void
100 {
101  u32 thread_id;
103 
104  if (PREDICT_FALSE (l == 0))
105  return;
106 
107  thread_id = os_get_cpu_number ();
108  ASSERT (l->lock && l->thread_id == thread_id);
109  l->count--;
110  if (l->count == 0)
111  {
112  l->tag = -l->tag;
113  l->release_hint = 0;
115  l->lock = 0;
116  }
117 }
118 
119 void
120 stats_dsunlock (int hint, int tag)
121 {
122  stats_main_t *sm = &stats_main;
123  dsunlock (sm);
124 }
125 
126 static void
128 {
131  api_main_t *am = sm->api_main;
135  u32 items_this_message = 0;
136  u64 v, *vp = 0;
137  int i, n_counts;
138 
139  /*
140  * Prevent interface registration from expanding / moving the vectors...
141  * That tends never to happen, so we can hold this lock for a while.
142  */
144 
145  vec_foreach (cm, im->sw_if_counters)
146  {
147  n_counts = vlib_simple_counter_n_counters (cm);
148  for (i = 0; i < n_counts; i++)
149  {
150  if (mp == 0)
151  {
152  items_this_message = clib_min (SIMPLE_COUNTER_BATCH_SIZE,
153  n_counts - i);
154 
156  (sizeof (*mp) + items_this_message * sizeof (v));
157  mp->_vl_msg_id = ntohs (VL_API_VNET_INTERFACE_COUNTERS);
158  mp->vnet_counter_type = cm - im->sw_if_counters;
159  mp->is_combined = 0;
160  mp->first_sw_if_index = htonl (i);
161  mp->count = 0;
162  vp = (u64 *) mp->data;
163  }
164  v = vlib_get_simple_counter (cm, i);
165  clib_mem_unaligned (vp, u64) = clib_host_to_net_u64 (v);
166  vp++;
167  mp->count++;
168  if (mp->count == items_this_message)
169  {
170  mp->count = htonl (items_this_message);
171  /* Send to the main thread... */
172  vl_msg_api_send_shmem (q, (u8 *) & mp);
173  mp = 0;
174  }
175  }
176  ASSERT (mp == 0);
177  }
179 }
180 
181 static void
183 {
186  api_main_t *am = sm->api_main;
190  u32 items_this_message = 0;
191  vlib_counter_t v, *vp = 0;
192  int i, n_counts;
193 
195 
197  {
198  n_counts = vlib_combined_counter_n_counters (cm);
199  for (i = 0; i < n_counts; i++)
200  {
201  if (mp == 0)
202  {
203  items_this_message = clib_min (COMBINED_COUNTER_BATCH_SIZE,
204  n_counts - i);
205 
207  (sizeof (*mp) + items_this_message * sizeof (v));
208  mp->_vl_msg_id = ntohs (VL_API_VNET_INTERFACE_COUNTERS);
210  mp->is_combined = 1;
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  ip_lookup_main_t *lm = &im4->lookup_main;
580  static uword *results;
582  u32 items_this_message;
583  vl_api_ip4_fib_counter_t *ctrp = 0;
584  u32 start_at_fib_index = 0;
585  int i;
586 
587 again:
588  /* *INDENT-OFF* */
589  pool_foreach (fib, im4->fibs,
590  ({
591  /* We may have bailed out due to control-plane activity */
592  while ((fib - im4->fibs) < start_at_fib_index)
593  continue;
594 
595  if (mp == 0)
596  {
597  items_this_message = IP4_FIB_COUNTER_BATCH_SIZE;
598  mp = vl_msg_api_alloc_as_if_client
599  (sizeof (*mp) +
600  items_this_message * sizeof (vl_api_ip4_fib_counter_t));
601  mp->_vl_msg_id = ntohs (VL_API_VNET_IP4_FIB_COUNTERS);
602  mp->count = 0;
603  mp->vrf_id = ntohl (fib->ft_table_id);
604  ctrp = (vl_api_ip4_fib_counter_t *) mp->c;
605  }
606  else
607  {
608  /* happens if the last FIB was empty... */
609  ASSERT (mp->count == 0);
610  mp->vrf_id = ntohl (fib->ft_table_id);
611  }
612 
613  dslock (sm, 0 /* release hint */ , 1 /* tag */ );
614 
615  vec_reset_length (routes);
616  vec_reset_length (results);
617 
618  for (i = 0; i < ARRAY_LEN (fib->v4.fib_entry_by_dst_address); i++)
619  {
620  uword *hash = fib->v4.fib_entry_by_dst_address[i];
621  hash_pair_t *p;
622  ip4_route_t x;
623 
624  x.address_length = i;
625 
626  hash_foreach_pair (p, hash,
627  ({
628  x.address.data_u32 = p->key;
629  x.index = p->value[0];
630 
631  vec_add1 (routes, x);
633  {
634  start_at_fib_index = fib - im4->fibs;
635  dsunlock (sm);
636  ip46_fib_stats_delay (sm, 0 /* sec */,
638  mp->count = 0;
639  ctrp = (vl_api_ip4_fib_counter_t *)mp->c;
640  goto again;
641  }
642  }));
643  }
644 
645  vec_foreach (r, routes)
646  {
648 
650  r->index, &c);
651  /*
652  * If it has actually
653  * seen at least one packet, send it.
654  */
655  if (c.packets > 0)
656  {
657 
658  /* already in net byte order */
659  ctrp->address = r->address.as_u32;
660  ctrp->address_length = r->address_length;
661  ctrp->packets = clib_host_to_net_u64 (c.packets);
662  ctrp->bytes = clib_host_to_net_u64 (c.bytes);
663  mp->count++;
664  ctrp++;
665 
666  if (mp->count == items_this_message)
667  {
668  mp->count = htonl (items_this_message);
669  /*
670  * If the main thread's input queue is stuffed,
671  * drop the data structure lock (which the main thread
672  * may want), and take a pause.
673  */
676  {
677  dsunlock (sm);
678  vl_msg_api_send_shmem_nolock (q, (u8 *) & mp);
680  mp = 0;
681  ip46_fib_stats_delay (sm, 0 /* sec */ ,
683  goto again;
684  }
685  vl_msg_api_send_shmem_nolock (q, (u8 *) & mp);
687 
688  items_this_message = IP4_FIB_COUNTER_BATCH_SIZE;
690  (sizeof (*mp) +
691  items_this_message * sizeof (vl_api_ip4_fib_counter_t));
692  mp->_vl_msg_id = ntohs (VL_API_VNET_IP4_FIB_COUNTERS);
693  mp->count = 0;
694  mp->vrf_id = ntohl (fib->ft_table_id);
695  ctrp = (vl_api_ip4_fib_counter_t *) mp->c;
696  }
697  } /* for each (mp or single) adj */
699  {
700  start_at_fib_index = fib - im4->fibs;
701  dsunlock (sm);
702  ip46_fib_stats_delay (sm, 0 /* sec */ , STATS_RELEASE_DELAY_NS);
703  mp->count = 0;
704  ctrp = (vl_api_ip4_fib_counter_t *) mp->c;
705  goto again;
706  }
707  } /* vec_foreach (routes) */
708 
709  dsunlock (sm);
710 
711  /* Flush any data from this fib */
712  if (mp->count)
713  {
714  mp->count = htonl (mp->count);
715  vl_msg_api_send_shmem (q, (u8 *) & mp);
716  mp = 0;
717  }
718  }));
719  /* *INDENT-ON* */
720 
721  /* If e.g. the last FIB had no reportable routes, free the buffer */
722  if (mp)
723  vl_msg_api_free (mp);
724 }
725 
726 typedef struct
727 {
731 } ip6_route_t;
732 
733 typedef struct
734 {
739 
740 static void
741 add_routes_in_fib (BVT (clib_bihash_kv) * kvp, void *arg)
742 {
743  add_routes_in_fib_arg_t *ap = arg;
744  stats_main_t *sm = ap->sm;
745 
747  clib_longjmp (&sm->jmp_buf, 1);
748 
749  if (kvp->key[2] >> 32 == ap->fib_index)
750  {
752  ip6_route_t *r;
753  addr = (ip6_address_t *) kvp;
754  vec_add2 (*ap->routep, r, 1);
755  r->address = addr[0];
756  r->address_length = kvp->key[2] & 0xFF;
757  r->index = kvp->value;
758  }
759 }
760 
761 static void
763 {
764  ip6_main_t *im6 = &ip6_main;
765  api_main_t *am = sm->api_main;
768  static ip6_route_t *routes;
769  ip6_route_t *r;
770  fib_table_t *fib;
771  static uword *results;
773  u32 items_this_message;
774  vl_api_ip6_fib_counter_t *ctrp = 0;
775  u32 start_at_fib_index = 0;
776  BVT (clib_bihash) * h = &im6->ip6_table[IP6_FIB_TABLE_FWDING].ip6_hash;
777  add_routes_in_fib_arg_t _a, *a = &_a;
778 
779 again:
780  /* *INDENT-OFF* */
781  pool_foreach (fib, im6->fibs,
782  ({
783  /* We may have bailed out due to control-plane activity */
784  while ((fib - im6->fibs) < start_at_fib_index)
785  continue;
786 
787  if (mp == 0)
788  {
789  items_this_message = IP6_FIB_COUNTER_BATCH_SIZE;
790  mp = vl_msg_api_alloc_as_if_client
791  (sizeof (*mp) +
792  items_this_message * sizeof (vl_api_ip6_fib_counter_t));
793  mp->_vl_msg_id = ntohs (VL_API_VNET_IP6_FIB_COUNTERS);
794  mp->count = 0;
795  mp->vrf_id = ntohl (fib->ft_table_id);
796  ctrp = (vl_api_ip6_fib_counter_t *) mp->c;
797  }
798 
799  dslock (sm, 0 /* release hint */ , 1 /* tag */ );
800 
801  vec_reset_length (routes);
802  vec_reset_length (results);
803 
804  a->fib_index = fib - im6->fibs;
805  a->routep = &routes;
806  a->sm = sm;
807 
808  if (clib_setjmp (&sm->jmp_buf, 0) == 0)
809  {
810  start_at_fib_index = fib - im6->fibs;
812  }
813  else
814  {
815  dsunlock (sm);
816  ip46_fib_stats_delay (sm, 0 /* sec */ ,
818  mp->count = 0;
819  ctrp = (vl_api_ip6_fib_counter_t *) mp->c;
820  goto again;
821  }
822 
823  vec_foreach (r, routes)
824  {
826 
828  r->index, &c);
829  /*
830  * If it has actually
831  * seen at least one packet, send it.
832  */
833  if (c.packets > 0)
834  {
835  /* already in net byte order */
836  ctrp->address[0] = r->address.as_u64[0];
837  ctrp->address[1] = r->address.as_u64[1];
838  ctrp->address_length = (u8) r->address_length;
839  ctrp->packets = clib_host_to_net_u64 (c.packets);
840  ctrp->bytes = clib_host_to_net_u64 (c.bytes);
841  mp->count++;
842  ctrp++;
843 
844  if (mp->count == items_this_message)
845  {
846  mp->count = htonl (items_this_message);
847  /*
848  * If the main thread's input queue is stuffed,
849  * drop the data structure lock (which the main thread
850  * may want), and take a pause.
851  */
854  {
855  dsunlock (sm);
856  vl_msg_api_send_shmem_nolock (q, (u8 *) & mp);
858  mp = 0;
859  ip46_fib_stats_delay (sm, 0 /* sec */ ,
861  goto again;
862  }
863  vl_msg_api_send_shmem_nolock (q, (u8 *) & mp);
865 
866  items_this_message = IP6_FIB_COUNTER_BATCH_SIZE;
868  (sizeof (*mp) +
869  items_this_message * sizeof (vl_api_ip6_fib_counter_t));
870  mp->_vl_msg_id = ntohs (VL_API_VNET_IP6_FIB_COUNTERS);
871  mp->count = 0;
872  mp->vrf_id = ntohl (fib->ft_table_id);
873  ctrp = (vl_api_ip6_fib_counter_t *) mp->c;
874  }
875  }
876 
878  {
879  start_at_fib_index = fib - im6->fibs;
880  dsunlock (sm);
881  ip46_fib_stats_delay (sm, 0 /* sec */ , STATS_RELEASE_DELAY_NS);
882  mp->count = 0;
883  ctrp = (vl_api_ip6_fib_counter_t *) mp->c;
884  goto again;
885  }
886  } /* vec_foreach (routes) */
887 
888  dsunlock (sm);
889 
890  /* Flush any data from this fib */
891  if (mp->count)
892  {
893  mp->count = htonl (mp->count);
894  vl_msg_api_send_shmem (q, (u8 *) & mp);
895  mp = 0;
896  }
897  }));
898  /* *INDENT-ON* */
899 
900  /* If e.g. the last FIB had no reportable routes, free the buffer */
901  if (mp)
902  vl_msg_api_free (mp);
903 }
904 
905 static void
906 stats_thread_fn (void *arg)
907 {
908  stats_main_t *sm = &stats_main;
911 
912  /* stats thread wants no signals. */
913  {
914  sigset_t s;
915  sigfillset (&s);
916  pthread_sigmask (SIG_SETMASK, &s, 0);
917  }
918 
919  if (vec_len (tm->thread_prefix))
920  vlib_set_thread_name ((char *)
921  format (0, "%v_stats%c", tm->thread_prefix, '\0'));
922 
924 
925  while (1)
926  {
927  /* 10 second poll interval */
928  ip46_fib_stats_delay (sm, 10 /* secs */ , 0 /* nsec */ );
929 
930  if (!(sm->enable_poller))
931  continue;
934  do_ip4_fibs (sm);
935  do_ip6_fibs (sm);
936  do_ip4_nbrs (sm);
937  do_ip6_nbrs (sm);
938  }
939 }
940 
941 static void
943  mp)
944 {
946  stats_main_t *sm = &stats_main;
947  unix_shared_memory_queue_t *q, *q_prev = NULL;
949  u32 mp_size;
950 
951 #if STATS_DEBUG > 0
952  char *counter_name;
953  u32 count, sw_if_index;
954  int i;
955 #endif
956 
957  mp_size = sizeof (*mp) + (ntohl (mp->count) *
958  (mp->is_combined ? sizeof (vlib_counter_t) :
959  sizeof (u64)));
960 
961  /* *INDENT-OFF* */
963  ({
964  q = vl_api_client_index_to_input_queue (reg->client_index);
965  if (q)
966  {
967  if (q_prev && (q_prev->cursize < q_prev->maxsize))
968  {
969  mp_copy = vl_msg_api_alloc_as_if_client(mp_size);
970  clib_memcpy(mp_copy, mp, mp_size);
971  vl_msg_api_send_shmem (q_prev, (u8 *)&mp);
972  mp = mp_copy;
973  }
974  q_prev = q;
975  }
976  }));
977  /* *INDENT-ON* */
978 
979 #if STATS_DEBUG > 0
980  count = ntohl (mp->count);
981  sw_if_index = ntohl (mp->first_sw_if_index);
982  if (mp->is_combined == 0)
983  {
984  u64 *vp, v;
985  vp = (u64 *) mp->data;
986 
987  switch (mp->vnet_counter_type)
988  {
990  counter_name = "drop";
991  break;
993  counter_name = "punt";
994  break;
996  counter_name = "ip4";
997  break;
999  counter_name = "ip6";
1000  break;
1002  counter_name = "rx-no-buff";
1003  break;
1005  , counter_name = "rx-miss";
1006  break;
1008  , counter_name = "rx-error (fifo-full)";
1009  break;
1011  , counter_name = "tx-error (fifo-full)";
1012  break;
1013  default:
1014  counter_name = "bogus";
1015  break;
1016  }
1017  for (i = 0; i < count; i++)
1018  {
1019  v = clib_mem_unaligned (vp, u64);
1020  v = clib_net_to_host_u64 (v);
1021  vp++;
1022  fformat (stdout, "%U.%s %lld\n", format_vnet_sw_if_index_name,
1023  sm->vnet_main, sw_if_index, counter_name, v);
1024  sw_if_index++;
1025  }
1026  }
1027  else
1028  {
1029  vlib_counter_t *vp;
1030  u64 packets, bytes;
1031  vp = (vlib_counter_t *) mp->data;
1032 
1033  switch (mp->vnet_counter_type)
1034  {
1036  counter_name = "rx";
1037  break;
1039  counter_name = "tx";
1040  break;
1041  default:
1042  counter_name = "bogus";
1043  break;
1044  }
1045  for (i = 0; i < count; i++)
1046  {
1047  packets = clib_mem_unaligned (&vp->packets, u64);
1048  packets = clib_net_to_host_u64 (packets);
1049  bytes = clib_mem_unaligned (&vp->bytes, u64);
1050  bytes = clib_net_to_host_u64 (bytes);
1051  vp++;
1052  fformat (stdout, "%U.%s.packets %lld\n",
1054  sm->vnet_main, sw_if_index, counter_name, packets);
1055  fformat (stdout, "%U.%s.bytes %lld\n",
1057  sm->vnet_main, sw_if_index, counter_name, bytes);
1058  sw_if_index++;
1059  }
1060  }
1061 #endif
1062  if (q_prev && (q_prev->cursize < q_prev->maxsize))
1063  {
1064  vl_msg_api_send_shmem (q_prev, (u8 *) & mp);
1065  }
1066  else
1067  {
1068  vl_msg_api_free (mp);
1069  }
1070 }
1071 
1072 static void
1074 {
1076  stats_main_t *sm = &stats_main;
1077  unix_shared_memory_queue_t *q, *q_prev = NULL;
1079  u32 mp_size;
1080 
1081  mp_size = sizeof (*mp_copy) +
1082  ntohl (mp->count) * sizeof (vl_api_ip4_fib_counter_t);
1083 
1084  /* *INDENT-OFF* */
1086  ({
1087  q = vl_api_client_index_to_input_queue (reg->client_index);
1088  if (q)
1089  {
1090  if (q_prev && (q_prev->cursize < q_prev->maxsize))
1091  {
1092  mp_copy = vl_msg_api_alloc_as_if_client(mp_size);
1093  clib_memcpy(mp_copy, mp, mp_size);
1094  vl_msg_api_send_shmem (q_prev, (u8 *)&mp);
1095  mp = mp_copy;
1096  }
1097  q_prev = q;
1098  }
1099  }));
1100  /* *INDENT-ON* */
1101  if (q_prev && (q_prev->cursize < q_prev->maxsize))
1102  {
1103  vl_msg_api_send_shmem (q_prev, (u8 *) & mp);
1104  }
1105  else
1106  {
1107  vl_msg_api_free (mp);
1108  }
1109 }
1110 
1111 static void
1113 {
1115  stats_main_t *sm = &stats_main;
1116  unix_shared_memory_queue_t *q, *q_prev = NULL;
1118  u32 mp_size;
1119 
1120  mp_size = sizeof (*mp_copy) +
1121  ntohl (mp->count) * sizeof (vl_api_ip4_nbr_counter_t);
1122 
1123  /* *INDENT-OFF* */
1125  ({
1126  q = vl_api_client_index_to_input_queue (reg->client_index);
1127  if (q)
1128  {
1129  if (q_prev && (q_prev->cursize < q_prev->maxsize))
1130  {
1131  mp_copy = vl_msg_api_alloc_as_if_client(mp_size);
1132  clib_memcpy(mp_copy, mp, mp_size);
1133  vl_msg_api_send_shmem (q_prev, (u8 *)&mp);
1134  mp = mp_copy;
1135  }
1136  q_prev = q;
1137  }
1138  }));
1139  /* *INDENT-ON* */
1140  if (q_prev && (q_prev->cursize < q_prev->maxsize))
1141  {
1142  vl_msg_api_send_shmem (q_prev, (u8 *) & mp);
1143  }
1144  else
1145  {
1146  vl_msg_api_free (mp);
1147  }
1148 }
1149 
1150 static void
1152 {
1154  stats_main_t *sm = &stats_main;
1155  unix_shared_memory_queue_t *q, *q_prev = NULL;
1157  u32 mp_size;
1158 
1159  mp_size = sizeof (*mp_copy) +
1160  ntohl (mp->count) * sizeof (vl_api_ip6_fib_counter_t);
1161 
1162  /* *INDENT-OFF* */
1164  ({
1165  q = vl_api_client_index_to_input_queue (reg->client_index);
1166  if (q)
1167  {
1168  if (q_prev && (q_prev->cursize < q_prev->maxsize))
1169  {
1170  mp_copy = vl_msg_api_alloc_as_if_client(mp_size);
1171  clib_memcpy(mp_copy, mp, mp_size);
1172  vl_msg_api_send_shmem (q_prev, (u8 *)&mp);
1173  mp = mp_copy;
1174  }
1175  q_prev = q;
1176  }
1177  }));
1178  /* *INDENT-ON* */
1179  if (q_prev && (q_prev->cursize < q_prev->maxsize))
1180  {
1181  vl_msg_api_send_shmem (q_prev, (u8 *) & mp);
1182  }
1183  else
1184  {
1185  vl_msg_api_free (mp);
1186  }
1187 }
1188 
1189 static void
1191 {
1193  stats_main_t *sm = &stats_main;
1194  unix_shared_memory_queue_t *q, *q_prev = NULL;
1196  u32 mp_size;
1197 
1198  mp_size = sizeof (*mp_copy) +
1199  ntohl (mp->count) * sizeof (vl_api_ip6_nbr_counter_t);
1200 
1201  /* *INDENT-OFF* */
1203  ({
1204  q = vl_api_client_index_to_input_queue (reg->client_index);
1205  if (q)
1206  {
1207  if (q_prev && (q_prev->cursize < q_prev->maxsize))
1208  {
1209  mp_copy = vl_msg_api_alloc_as_if_client(mp_size);
1210  clib_memcpy(mp_copy, mp, mp_size);
1211  vl_msg_api_send_shmem (q_prev, (u8 *)&mp);
1212  mp = mp_copy;
1213  }
1214  q_prev = q;
1215  }
1216  }));
1217  /* *INDENT-ON* */
1218  if (q_prev && (q_prev->cursize < q_prev->maxsize))
1219  {
1220  vl_msg_api_send_shmem (q_prev, (u8 *) & mp);
1221  }
1222  else
1223  {
1224  vl_msg_api_free (mp);
1225  }
1226 }
1227 
1228 static void
1230 {
1231  stats_main_t *sm = &stats_main;
1234  uword *p;
1235  i32 retval = 0;
1237 
1239  if (p)
1240  {
1241  if (mp->enable_disable)
1242  {
1243  clib_warning ("pid %d: already enabled...", mp->pid);
1244  retval = -2;
1245  goto reply;
1246  }
1247  else
1248  {
1249  rp = pool_elt_at_index (sm->stats_registrations, p[0]);
1250  pool_put (sm->stats_registrations, rp);
1252  goto reply;
1253  }
1254  }
1255  if (mp->enable_disable == 0)
1256  {
1257  clib_warning ("pid %d: already disabled...", mp->pid);
1258  retval = -3;
1259  goto reply;
1260  }
1261  pool_get (sm->stats_registrations, rp);
1262  rp->client_index = mp->client_index;
1263  rp->client_pid = mp->pid;
1265  rp - sm->stats_registrations);
1266 
1267 reply:
1268  if (pool_elts (sm->stats_registrations))
1269  sm->enable_poller = 1;
1270  else
1271  sm->enable_poller = 0;
1272 
1274 
1275  if (!q)
1276  return;
1277 
1278  rmp = vl_msg_api_alloc (sizeof (*rmp));
1279  rmp->_vl_msg_id = ntohs (VL_API_WANT_STATS_REPLY);
1280  rmp->context = mp->context;
1281  rmp->retval = retval;
1282 
1283  vl_msg_api_send_shmem (q, (u8 *) & rmp);
1284 }
1285 
1286 int
1288 {
1290  stats_main_t *sm = &stats_main;
1291  uword *p;
1292 
1293  p = hash_get (sm->stats_registration_hash, client_index);
1294  if (p)
1295  {
1296  rp = pool_elt_at_index (sm->stats_registrations, p[0]);
1297  pool_put (sm->stats_registrations, rp);
1298  hash_unset (sm->stats_registration_hash, client_index);
1299  }
1300 
1301  return 0;
1302 }
1303 
1304 #define vl_api_vnet_ip4_fib_counters_t_endian vl_noop_handler
1305 #define vl_api_vnet_ip4_fib_counters_t_print vl_noop_handler
1306 #define vl_api_vnet_ip6_fib_counters_t_endian vl_noop_handler
1307 #define vl_api_vnet_ip6_fib_counters_t_print vl_noop_handler
1308 #define vl_api_vnet_ip4_nbr_counters_t_endian vl_noop_handler
1309 #define vl_api_vnet_ip4_nbr_counters_t_print vl_noop_handler
1310 #define vl_api_vnet_ip6_nbr_counters_t_endian vl_noop_handler
1311 #define vl_api_vnet_ip6_nbr_counters_t_print vl_noop_handler
1312 
1313 static clib_error_t *
1315 {
1316  stats_main_t *sm = &stats_main;
1317  api_main_t *am = &api_main;
1318  void *vlib_worker_thread_bootstrap_fn (void *arg);
1319 
1320  sm->vlib_main = vm;
1321  sm->vnet_main = vnet_get_main ();
1323  sm->api_main = am;
1325  sm->data_structure_lock =
1328  memset (sm->data_structure_lock, 0, sizeof (*sm->data_structure_lock));
1329 
1330 #define _(N,n) \
1331  vl_msg_api_set_handlers(VL_API_##N, #n, \
1332  vl_api_##n##_t_handler, \
1333  vl_noop_handler, \
1334  vl_api_##n##_t_endian, \
1335  vl_api_##n##_t_print, \
1336  sizeof(vl_api_##n##_t), 0 /* do NOT trace! */);
1338 #undef _
1339 
1340  /* tell the msg infra not to free these messages... */
1341  am->message_bounce[VL_API_VNET_INTERFACE_COUNTERS] = 1;
1342  am->message_bounce[VL_API_VNET_IP4_FIB_COUNTERS] = 1;
1343  am->message_bounce[VL_API_VNET_IP6_FIB_COUNTERS] = 1;
1344  am->message_bounce[VL_API_VNET_IP4_NBR_COUNTERS] = 1;
1345  am->message_bounce[VL_API_VNET_IP6_NBR_COUNTERS] = 1;
1346 
1347  return 0;
1348 }
1349 
1351 
1352 /* *INDENT-OFF* */
1353 VLIB_REGISTER_THREAD (stats_thread_reg, static) = {
1354  .name = "stats",
1355  .function = stats_thread_fn,
1356  .fixed_count = 1,
1357  .count = 1,
1358  .no_data_structure_clone = 1,
1359  .use_pthreads = 1,
1360 };
1361 /* *INDENT-ON* */
1362 
1363 /*
1364  * fd.io coding-style-patch-verification: ON
1365  *
1366  * Local Variables:
1367  * eval: (c-set-style "gnu")
1368  * End:
1369  */
static void stats_thread_fn(void *arg)
Definition: stats.c:906
Want Stats, register for stats updates.
Definition: vpe.api:203
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:343
#define clib_min(x, y)
Definition: clib.h:332
#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
void vl_msg_api_send_shmem(unix_shared_memory_queue_t *q, u8 *elem)
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
struct ip_adjacency_t_::@138::@139 nbr
IP_LOOKUP_NEXT_ARP/IP_LOOKUP_NEXT_REWRITE.
vnet_interface_main_t interface_main
Definition: vnet.h:57
Reply for Want Stats request.
Definition: vpe.api:215
u64 as_u64[2]
Definition: ip6_packet.h:51
unix_shared_memory_queue_t * vl_input_queue
Definition: api.h:73
#define NULL
Definition: clib.h:55
IP unicast adjacency.
Definition: lookup.h:193
u8 * message_bounce
Definition: api.h:131
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
unix_shared_memory_queue_t * vl_api_client_index_to_input_queue(u32 index)
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:258
VLIB_REGISTER_THREAD(stats_thread_reg, static)
ip_lookup_main_t lookup_main
Definition: ip4.h:109
void clib_longjmp(clib_longjmp_t *save, uword return_value)
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:418
union ip_adjacency_t_::@138 sub_type
#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:1073
static clib_error_t * stats_init(vlib_main_t *vm)
Definition: stats.c:1314
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
Definition: lookup.h:214
static void vl_api_vnet_ip4_nbr_counters_t_handler(vl_api_vnet_ip4_nbr_counters_t *mp)
Definition: stats.c:1112
api_main_t api_main
Definition: api_shared.c:35
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:128
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:376
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:111
void vl_msg_api_free(void *)
vlib_combined_counter_main_t * combined_sw_if_counters
Definition: interface.h:626
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:59
unsigned long u64
Definition: types.h:89
struct vl_shmem_hdr_ * shmem_hdr
Definition: api.h:144
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:74
stats_main_t stats_main
Definition: stats.c:24
#define foreach_stats_msg
Definition: stats.c:47
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:99
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
uword * fib_entry_by_dst_address[33]
Definition: ip4.h:51
counter_t packets
packet counter
Definition: counter.h:141
static void do_ip6_fibs(stats_main_t *sm)
Definition: stats.c:762
#define v
Definition: acl.c:246
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
uword os_get_cpu_number(void)
Definition: unix-misc.c:224
#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:625
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:56
void unix_shared_memory_queue_lock(unix_shared_memory_queue_t *q)
#define COMBINED_COUNTER_BATCH_SIZE
Definition: stats.c:57
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:31
static void do_simple_interface_counters(stats_main_t *sm)
Definition: stats.c:127
u32 index
Definition: stats.c:730
word fformat(FILE *f, char *fmt,...)
Definition: format.c:452
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.
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:741
stats_main_t * sm
Definition: stats.c:737
void * vl_msg_api_alloc(int nbytes)
svmdb_client_t * c
u32 ft_table_id
Table ID (hash key) for this FIB.
Definition: fib_table.h:56
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
vlib_main_t * vm
Definition: buffer.c:276
vec_header_t h
Definition: buffer.c:275
clib_longjmp_t jmp_buf
Definition: stats.h:54
#define IP4_FIB_COUNTER_BATCH_SIZE
Definition: stats.c:58
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:118
#define clib_memcpy(a, b, c)
Definition: string.h:69
static void vnet_interface_counter_unlock(vnet_interface_main_t *im)
Definition: interface.h:651
static void vl_api_vnet_ip6_fib_counters_t_handler(vl_api_vnet_ip6_fib_counters_t *mp)
Definition: stats.c:1151
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:273
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:643
struct ip6_nbr_stats_ctx_t_ ip6_nbr_stats_ctx_t
The context passed when collecting adjacency counters.
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:92
unsigned int u32
Definition: types.h:88
ip6_main_t ip6_main
Definition: ip6_forward.c:2846
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:62
The context passed when collecting adjacency counters.
Definition: stats.c:417
IPv4 main type.
Definition: ip4.h:107
int stats_memclnt_delete_callback(u32 client_index)
Definition: stats.c:1287
static void do_combined_interface_counters(stats_main_t *sm)
Definition: stats.c:182
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:149
u64 uword
Definition: types.h:112
void dslock(stats_main_t *sm, int release_hint, int tag)
Definition: stats.c:66
vl_api_ip4_fib_counter_t c[count]
Definition: vpe.api:233
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:253
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:1229
#define hash_foreach_pair(p, v, body)
Iterate over hash pairs.
Definition: hash.h:349
vnet_sw_interface_t * sw_interfaces
Definition: interface.h:617
#define clib_unix_warning(format, args...)
Definition: error.h:68
u32 address_length
Definition: stats.c:729
Stats counters structure.
Definition: interface.api:266
A collection of combined counters.
Definition: counter.h:180
#define clib_mem_unaligned(pointer, type)
Definition: types.h:155
ip4_fib_t v4
Definition: fib_table.h:38
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:1190
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:1117
static vlib_thread_main_t * vlib_get_thread_main()
Definition: global_funcs.h:32
ip6_route_t ** routep
Definition: stats.c:736
struct fib_table_t_ * fibs
Vector of FIBs.
Definition: ip4.h:112
#define vec_foreach(var, vec)
Vector iterator.
void vl_msg_api_send_shmem_nolock(unix_shared_memory_queue_t *q, u8 *elem)
void * vlib_worker_thread_bootstrap_fn(void *arg)
Definition: threads.c:492
#define CLIB_MEMORY_BARRIER()
Definition: clib.h:101
void * vl_msg_api_alloc_as_if_client(int nbytes)
vhost_vring_addr_t addr
Definition: vhost-user.h:84
void stats_dsunlock(int hint, int tag)
Definition: stats.c:120
#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:154
static void vl_api_vnet_interface_counters_t_handler(vl_api_vnet_interface_counters_t *mp)
Definition: stats.c:942
uword key
Definition: hash.h:161
vl_api_ip6_nbr_counter_t c[count]
Definition: vpe.api:289
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:728
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:109