FD.io VPP  v18.04-17-g3a0d853
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 <vnet/fib/ip4_fib.h>
18 #include <vnet/fib/fib_entry.h>
19 #include <vnet/mfib/mfib_entry.h>
20 #include <vnet/dpo/load_balance.h>
21 #include <vnet/udp/udp_encap.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 _(WANT_INTERFACE_SIMPLE_STATS, want_interface_simple_stats) \
52 _(VNET_INTERFACE_COMBINED_COUNTERS, vnet_interface_combined_counters) \
53 _(WANT_INTERFACE_COMBINED_STATS, want_interface_combined_stats) \
54 _(WANT_PER_INTERFACE_COMBINED_STATS, want_per_interface_combined_stats) \
55 _(WANT_PER_INTERFACE_SIMPLE_STATS, want_per_interface_simple_stats) \
56 _(VNET_IP4_FIB_COUNTERS, vnet_ip4_fib_counters) \
57 _(WANT_IP4_FIB_STATS, want_ip4_fib_stats) \
58 _(VNET_IP6_FIB_COUNTERS, vnet_ip6_fib_counters) \
59 _(WANT_IP6_FIB_STATS, want_ip6_fib_stats) \
60 _(WANT_IP4_MFIB_STATS, want_ip4_mfib_stats) \
61 _(WANT_IP6_MFIB_STATS, want_ip6_mfib_stats) \
62 _(VNET_IP4_NBR_COUNTERS, vnet_ip4_nbr_counters) \
63 _(WANT_IP4_NBR_STATS, want_ip4_nbr_stats) \
64 _(VNET_IP6_NBR_COUNTERS, vnet_ip6_nbr_counters) \
65 _(WANT_IP6_NBR_STATS, want_ip6_nbr_stats) \
66 _(VNET_GET_SUMMARY_STATS, vnet_get_summary_stats) \
67 _(STATS_GET_POLLER_DELAY, stats_get_poller_delay) \
68 _(WANT_UDP_ENCAP_STATS, want_udp_encap_stats)
69 
70 #define vl_msg_name_crc_list
71 #include <vpp/stats/stats.api.h>
72 #undef vl_msg_name_crc_list
73 
74 static void
76 {
77 #define _(id,n,crc) \
78  vl_msg_api_add_msg_name_crc (am, #n "_" #crc, id);
79  foreach_vl_msg_name_crc_stats;
80 #undef _
81 }
82 
83 /* These constants ensure msg sizes <= 1024, aka ring allocation */
84 #define SIMPLE_COUNTER_BATCH_SIZE 126
85 #define COMBINED_COUNTER_BATCH_SIZE 63
86 #define IP4_FIB_COUNTER_BATCH_SIZE 48
87 #define IP6_FIB_COUNTER_BATCH_SIZE 30
88 #define IP4_MFIB_COUNTER_BATCH_SIZE 24
89 #define IP6_MFIB_COUNTER_BATCH_SIZE 15
90 #define UDP_ENCAP_COUNTER_BATCH_SIZE (1024 / sizeof(vl_api_udp_encap_counter_t))
91 
92 /* 5ms */
93 #define STATS_RELEASE_DELAY_NS (1000 * 1000 * 5)
94 /* ns/us us/ms */
95 
96 u8 *
98 {
99  stats_main_t *sm = &stats_main;
102 
103  char *counter_name;
104  u32 count, sw_if_index;
105  int i;
106  count = ntohl (mp->count);
107  sw_if_index = ntohl (mp->first_sw_if_index);
108 
109  vlib_counter_t *vp;
110  u64 packets, bytes;
111  vp = (vlib_counter_t *) mp->data;
112 
113  switch (mp->vnet_counter_type)
114  {
116  counter_name = "rx";
117  break;
119  counter_name = "tx";
120  break;
121  default:
122  counter_name = "bogus";
123  break;
124  }
125  for (i = 0; i < count; i++)
126  {
127  packets = clib_mem_unaligned (&vp->packets, u64);
128  packets = clib_net_to_host_u64 (packets);
129  bytes = clib_mem_unaligned (&vp->bytes, u64);
130  bytes = clib_net_to_host_u64 (bytes);
131  vp++;
132  s = format (s, "%U.%s.packets %lld\n",
134  sm->vnet_main, sw_if_index, counter_name, packets);
135  s = format (s, "%U.%s.bytes %lld\n",
137  sm->vnet_main, sw_if_index, counter_name, bytes);
138  sw_if_index++;
139  }
140  return s;
141 }
142 
143 u8 *
145 {
146  stats_main_t *sm = &stats_main;
148  va_arg (*args, vl_api_vnet_interface_simple_counters_t *);
149  char *counter_name;
150  u32 count, sw_if_index;
151  count = ntohl (mp->count);
152  sw_if_index = ntohl (mp->first_sw_if_index);
153  u64 *vp, v;
154  vp = (u64 *) mp->data;
155  int i;
156 
157  switch (mp->vnet_counter_type)
158  {
160  counter_name = "drop";
161  break;
163  counter_name = "punt";
164  break;
166  counter_name = "ip4";
167  break;
169  counter_name = "ip6";
170  break;
172  counter_name = "rx-no-buff";
173  break;
175  counter_name = "rx-miss";
176  break;
178  counter_name = "rx-error (fifo-full)";
179  break;
181  counter_name = "tx-error (fifo-full)";
182  break;
183  default:
184  counter_name = "bogus";
185  break;
186  }
187  for (i = 0; i < count; i++)
188  {
189  v = clib_mem_unaligned (vp, u64);
190  v = clib_net_to_host_u64 (v);
191  vp++;
192  s = format (s, "%U.%s %lld\n", format_vnet_sw_if_index_name,
193  sm->vnet_main, sw_if_index, counter_name, v);
194  sw_if_index++;
195  }
196 
197  return s;
198 }
199 
200 static void
201 dslock (stats_main_t * sm, int release_hint, int tag)
202 {
203  u32 thread_index;
205 
206  if (PREDICT_FALSE (l == 0))
207  return;
208 
209  thread_index = vlib_get_thread_index ();
210  if (l->lock && l->thread_index == thread_index)
211  {
212  l->count++;
213  return;
214  }
215 
216  if (release_hint)
217  l->release_hint++;
218 
219  while (__sync_lock_test_and_set (&l->lock, 1))
220  /* zzzz */ ;
221  l->tag = tag;
222  l->thread_index = thread_index;
223  l->count = 1;
224 }
225 
226 void
227 stats_dslock_with_hint (int hint, int tag)
228 {
229  stats_main_t *sm = &stats_main;
230  dslock (sm, hint, tag);
231 }
232 
233 static void
235 {
236  u32 thread_index;
238 
239  if (PREDICT_FALSE (l == 0))
240  return;
241 
242  thread_index = vlib_get_thread_index ();
243  ASSERT (l->lock && l->thread_index == thread_index);
244  l->count--;
245  if (l->count == 0)
246  {
247  l->tag = -l->tag;
248  l->release_hint = 0;
250  l->lock = 0;
251  }
252 }
253 
254 void
255 stats_dsunlock (int hint, int tag)
256 {
257  stats_main_t *sm = &stats_main;
258  dsunlock (sm);
259 }
260 
262 get_client_for_stat (u32 reg, u32 item, u32 client_index)
263 {
264  stats_main_t *sm = &stats_main;
265  vpe_client_stats_registration_t *registration;
266  uword *p;
267 
268  /* Is there anything listening for item in that reg */
269  p = hash_get (sm->stats_registration_hash[reg], item);
270 
271  if (!p)
272  return 0; // Fail
273 
274  /* If there is, is our client_index one of them */
275  registration = pool_elt_at_index (sm->stats_registrations[reg], p[0]);
276  p = hash_get (registration->client_hash, client_index);
277 
278  if (!p)
279  return 0; // Fail
280 
281  return pool_elt_at_index (registration->clients, p[0]);
282 
283 }
284 
285 static int
287 {
288  stats_main_t *sm = &stats_main;
289  vpe_client_stats_registration_t *registration;
291  uword *p;
292 
293  /* Is there anything listening for item in that reg */
294  p = hash_get (sm->stats_registration_hash[reg], item);
295 
296  if (!p)
297  {
298  pool_get (sm->stats_registrations[reg], registration);
299  registration->item = item;
300  registration->client_hash = NULL;
301  registration->clients = NULL;
302  hash_set (sm->stats_registration_hash[reg], item,
303  registration - sm->stats_registrations[reg]);
304  }
305  else
306  {
307  registration = pool_elt_at_index (sm->stats_registrations[reg], p[0]);
308  }
309 
310  p = hash_get (registration->client_hash, client->client_index);
311 
312  if (!p)
313  {
314  pool_get (registration->clients, cr);
315  cr->client_index = client->client_index;
316  cr->client_pid = client->client_pid;
317  hash_set (registration->client_hash, cr->client_index,
318  cr - registration->clients);
319  }
320 
321  return 1; //At least one client is doing something ... poll
322 }
323 
324 static void
325 clear_one_client (u32 reg_index, u32 reg, u32 item, u32 client_index)
326 {
327  stats_main_t *sm = &stats_main;
328  vpe_client_stats_registration_t *registration;
330  uword *p;
331 
332  registration = pool_elt_at_index (sm->stats_registrations[reg], reg_index);
333  p = hash_get (registration->client_hash, client_index);
334 
335  if (p)
336  {
337  client = pool_elt_at_index (registration->clients, p[0]);
338  hash_unset (registration->client_hash, client->client_index);
339  pool_put (registration->clients, client);
340 
341  /* Now check if that was the last client for that item */
342  if (0 == pool_elts (registration->clients))
343  {
344  hash_unset (sm->stats_registration_hash[reg], item);
345  hash_free (registration->client_hash);
346  pool_free (registration->clients);
347  pool_put (sm->stats_registrations[reg], registration);
348  }
349  }
350 }
351 
352 int
353 clear_client_for_stat (u32 reg, u32 item, u32 client_index)
354 {
355  stats_main_t *sm = &stats_main;
356  uword *p;
357  int i, elts;
358 
359  /* Clear the client first */
360  /* Is there anything listening for item in that reg */
361  p = hash_get (sm->stats_registration_hash[reg], item);
362 
363  if (!p)
364  goto exit;
365 
366  /* If there is, is our client_index one of them */
367  clear_one_client (p[0], reg, item, client_index);
368 
369 exit:
370  elts = 0;
371  /* Now check if that was the last item in any of the listened to stats */
372  for (i = 0; i < STATS_REG_N_IDX; i++)
373  {
374  elts += pool_elts (sm->stats_registrations[i]);
375  }
376  return elts;
377 }
378 
379 static int
381 {
382  stats_main_t *sm = &stats_main;
383  u32 reg_index, item, reg;
384  int i, elts;
385 
386  /* *INDENT-OFF* */
388  {
389  hash_foreach(item, reg_index, sm->stats_registration_hash[reg],
390  ({
391  clear_one_client(reg_index, reg, item, client_index);
392  }));
393  }
394  /* *INDENT-OFF* */
395 
396  elts = 0;
397  /* Now check if that was the last item in any of the listened to stats */
398  for (i = 0; i < STATS_REG_N_IDX; i++)
399  {
400  elts += pool_elts (sm->stats_registrations[i]);
401  }
402  return elts;
403 }
404 
405 static clib_error_t *
406 want_stats_reaper (u32 client_index)
407 {
408  stats_main_t *sm = &stats_main;
409 
410  sm->enable_poller = clear_client_for_all_stats (client_index);
411 
412  return (NULL);
413 }
414 
416 
417 
418 /*
419  * Return a copy of the clients list.
420  */
423 {
424  stats_main_t *sm = &stats_main;
425  vpe_client_registration_t *client, *clients = 0;
426  vpe_client_stats_registration_t *registration;
427  uword *p;
428 
429  /* Is there anything listening for item in that reg */
430  p = hash_get (sm->stats_registration_hash[reg], item);
431 
432  if (!p)
433  return 0; // Fail
434 
435  /* If there is, is our client_index one of them */
436  registration = pool_elt_at_index (sm->stats_registrations[reg], p[0]);
437 
438  vec_reset_length (clients);
439 
440  /* *INDENT-OFF* */
441  pool_foreach (client, registration->clients,
442  ({
443  vec_add1 (clients, *client);}
444  ));
445  /* *INDENT-ON* */
446  return clients;
447 }
448 
449 
450 static void
451 clear_client_reg (u32 ** registrations)
452 {
453  /* When registrations[x] is a vector of pool indices
454  here is a good place to clean up the pools
455  */
456 #define stats_reg(n) vec_free(registrations[IDX_##n]);
457 #include <vpp/stats/stats.reg>
458 #undef stats_reg
459 
460  vec_free (registrations);
461 }
462 
463 u32 **
464 init_client_reg (u32 ** registrations)
465 {
466 
467  /*
468  Initialise the stats registrations for each
469  type of stat a client can register for as well as
470  a vector of "interested" indexes.
471  Initially this is a u32 of either sw_if_index or fib_index
472  but eventually this should migrate to a pool_index (u32)
473  with a type specific pool that can include more complex things
474  such as timing and structured events.
475  */
476  vec_validate (registrations, STATS_REG_N_IDX);
477 #define stats_reg(n) \
478  vec_reset_length(registrations[IDX_##n]);
479 #include <vpp/stats/stats.reg>
480 #undef stats_reg
481 
482  /*
483  When registrations[x] is a vector of pool indices, here
484  is a good place to init the pools.
485  */
486  return registrations;
487 }
488 
489 u32 **
490 enable_all_client_reg (u32 ** registrations)
491 {
492 
493  /*
494  Enable all stats known by adding
495  ~0 to the index vector. Eventually this
496  should be deprecated.
497  */
498 #define stats_reg(n) \
499  vec_add1(registrations[IDX_##n], ~0);
500 #include <vpp/stats/stats.reg>
501 #undef stats_reg
502  return registrations;
503 }
504 
505 static void
507 {
510  api_main_t *am = sm->api_main;
512  svm_queue_t *q = shmem_hdr->vl_input_queue;
514  u32 items_this_message = 0;
515  u64 v, *vp = 0;
516  int i, n_counts;
517 
518  /*
519  * Prevent interface registration from expanding / moving the vectors...
520  * That tends never to happen, so we can hold this lock for a while.
521  */
523 
524  vec_foreach (cm, im->sw_if_counters)
525  {
526  n_counts = vlib_simple_counter_n_counters (cm);
527  for (i = 0; i < n_counts; i++)
528  {
529  if (mp == 0)
530  {
531  items_this_message = clib_min (SIMPLE_COUNTER_BATCH_SIZE,
532  n_counts - i);
533 
535  (sizeof (*mp) + items_this_message * sizeof (v));
536  mp->_vl_msg_id = ntohs (VL_API_VNET_INTERFACE_SIMPLE_COUNTERS);
537  mp->vnet_counter_type = cm - im->sw_if_counters;
538  mp->first_sw_if_index = htonl (i);
539  mp->count = 0;
540  vp = (u64 *) mp->data;
541  }
542  v = vlib_get_simple_counter (cm, i);
543  clib_mem_unaligned (vp, u64) = clib_host_to_net_u64 (v);
544  vp++;
545  mp->count++;
546  if (mp->count == items_this_message)
547  {
548  mp->count = htonl (items_this_message);
549  /* Send to the main thread... */
550  vl_msg_api_send_shmem (q, (u8 *) & mp);
551  mp = 0;
552  }
553  }
554  ASSERT (mp == 0);
555  }
557 }
558 
559 void
561  u32 item, int enable_disable)
562 {
563  stats_main_t *sm = &stats_main;
564  vpe_client_registration_t *rp, _rp;
565 
566  rp = get_client_for_stat (stat, item, client->client_index);
567 
568  /* Disable case */
569  if (enable_disable == 0)
570  {
571  if (!rp) // No client to disable
572  {
573  clib_warning ("pid %d: already disabled for stats...",
574  client->client_pid);
575  return;
576  }
577  sm->enable_poller =
578  clear_client_for_stat (stat, item, client->client_index);
579  return;
580  }
581  /* Enable case */
582  if (!rp)
583  {
584  rp = &_rp;
585  rp->client_index = client->client_index;
586  rp->client_pid = client->client_pid;
587  sm->enable_poller = set_client_for_stat (stat, item, rp);
588  }
589 }
590 
591 
592 /**********************************
593  * ALL Interface Combined stats - to be deprecated
594  **********************************/
595 
596 /*
597  * This API should be deprecated as _per_interface_ works with ~0 as sw_if_index.
598  */
599 static void
602 {
603  stats_main_t *sm = &stats_main;
605  vl_api_want_interface_combined_stats_reply_t *rmp;
606  uword *p;
607  i32 retval = 0;
609  u32 swif;
610 
611  swif = ~0; //Using same mechanism as _per_interface_
612  rp.client_index = mp->client_index;
613  rp.client_pid = mp->pid;
614 
615  handle_client_registration (&rp, IDX_PER_INTERFACE_COMBINED_COUNTERS, swif,
616  mp->enable_disable);
617 
618 reply:
620  if (!reg)
621  {
622  sm->enable_poller =
623  clear_client_for_stat (IDX_PER_INTERFACE_COMBINED_COUNTERS, swif,
624  mp->client_index);
625  return;
626  }
627 
628  rmp = vl_msg_api_alloc (sizeof (*rmp));
629  rmp->_vl_msg_id = ntohs (VL_API_WANT_INTERFACE_COMBINED_STATS_REPLY);
630  rmp->context = mp->context;
631  rmp->retval = retval;
632 
633  vl_api_send_msg (reg, (u8 *) rmp);
634 }
635 
636 static void
639 {
640  vpe_client_registration_t *clients, client;
641  stats_main_t *sm = &stats_main;
642  vl_api_registration_t *reg, *reg_prev = NULL;
644  u32 mp_size;
645  int i;
646 
647  mp_size = sizeof (*mp) + (ntohl (mp->count) * sizeof (vlib_counter_t));
648 
649  clients =
650  get_clients_for_stat (IDX_PER_INTERFACE_COMBINED_COUNTERS,
651  ~0 /*flag for all */ );
652 
653  for (i = 0; i < vec_len (clients); i++)
654  {
655  client = clients[i];
657  if (reg)
658  {
659  if (reg_prev && vl_api_can_send_msg (reg_prev))
660  {
661  mp_copy = vl_msg_api_alloc_as_if_client (mp_size);
662  clib_memcpy (mp_copy, mp, mp_size);
663  vl_api_send_msg (reg_prev, (u8 *) mp);
664  mp = mp_copy;
665  }
666  reg_prev = reg;
667  }
668  }
669  vec_free (clients);
670 #if STATS_DEBUG > 0
671  fformat (stdout, "%U\n", format_vnet_combined_counters, mp);
672 #endif
673 
674  if (reg_prev && vl_api_can_send_msg (reg_prev))
675  {
676  vl_api_send_msg (reg_prev, (u8 *) mp);
677  }
678  else
679  {
680  vl_msg_api_free (mp);
681  }
682 }
683 
684 static void
686 {
689  api_main_t *am = sm->api_main;
691  svm_queue_t *q = shmem_hdr->vl_input_queue;
693  u32 items_this_message = 0;
694  vlib_counter_t v, *vp = 0;
695  int i, n_counts;
696 
698 
700  {
701  n_counts = vlib_combined_counter_n_counters (cm);
702  for (i = 0; i < n_counts; i++)
703  {
704  if (mp == 0)
705  {
706  items_this_message = clib_min (COMBINED_COUNTER_BATCH_SIZE,
707  n_counts - i);
708 
710  (sizeof (*mp) + items_this_message * sizeof (v));
711  mp->_vl_msg_id = ntohs (VL_API_VNET_INTERFACE_COMBINED_COUNTERS);
713  mp->first_sw_if_index = htonl (i);
714  mp->count = 0;
715  vp = (vlib_counter_t *) mp->data;
716  }
717  vlib_get_combined_counter (cm, i, &v);
719  = clib_host_to_net_u64 (v.packets);
720  clib_mem_unaligned (&vp->bytes, u64) = clib_host_to_net_u64 (v.bytes);
721  vp++;
722  mp->count++;
723  if (mp->count == items_this_message)
724  {
725  mp->count = htonl (items_this_message);
726  /* Send to the main thread... */
727  vl_msg_api_send_shmem (q, (u8 *) & mp);
728  mp = 0;
729  }
730  }
731  ASSERT (mp == 0);
732  }
734 }
735 
736 /**********************************
737  * Per Interface Combined stats
738  **********************************/
739 
740 /* Request from client registering interfaces it wants */
741 static void
744 {
745  stats_main_t *sm = &stats_main;
747  vl_api_want_per_interface_combined_stats_reply_t *rmp;
749  uword *p;
750  i32 retval = 0;
752  u32 i, swif, num = 0;
753 
754  num = ntohl (mp->num);
755 
756  /*
757  * Validate sw_if_indexes before registering
758  */
759  for (i = 0; i < num; i++)
760  {
761  swif = ntohl (mp->sw_ifs[i]);
762 
763  /*
764  * Check its a real sw_if_index that the client is allowed to see
765  */
766  if (swif != ~0)
767  {
769  {
770  retval = VNET_API_ERROR_INVALID_SW_IF_INDEX;
771  goto reply;
772  }
773  }
774  }
775 
776  for (i = 0; i < num; i++)
777  {
778  swif = ntohl (mp->sw_ifs[i]);
779 
780  rp.client_index = mp->client_index;
781  rp.client_pid = mp->pid;
782  handle_client_registration (&rp, IDX_PER_INTERFACE_COMBINED_COUNTERS,
783  swif, ntohl (mp->enable_disable));
784  }
785 
786 reply:
788  if (!reg)
789  {
790  for (i = 0; i < num; i++)
791  {
792  swif = ntohl (mp->sw_ifs[i]);
793 
794  sm->enable_poller =
795  clear_client_for_stat (IDX_PER_INTERFACE_COMBINED_COUNTERS, swif,
796  mp->client_index);
797  }
798  return;
799  }
800 
801  rmp = vl_msg_api_alloc (sizeof (*rmp));
802  rmp->_vl_msg_id = ntohs (VL_API_WANT_PER_INTERFACE_COMBINED_STATS_REPLY);
803  rmp->context = mp->context;
804  rmp->retval = retval;
805 
806  vl_api_send_msg (reg, (u8 *) rmp);
807 }
808 
809 /* Per Interface Combined distribution to client */
810 static void
812 {
815  api_main_t *am = sm->api_main;
817  vl_api_registration_t *vl_reg;
821  u32 i, j;
824  u32 *sw_if_index = 0;
825 
827 
829 
830  /* *INDENT-OFF* */
831  pool_foreach (reg,
832  sm->stats_registrations[IDX_PER_INTERFACE_COMBINED_COUNTERS],
833  ({ vec_add1 (sm->regs_tmp, reg); }));
834  /* *INDENT-ON* */
835 
836  for (i = 0; i < vec_len (sm->regs_tmp); i++)
837  {
838  reg = sm->regs_tmp[i];
839  if (reg->item == ~0)
840  {
844  continue;
845  }
847 
848  /* *INDENT-OFF* */
849  pool_foreach (client, reg->clients, ({ vec_add1 (sm->clients_tmp,
850  client);}));
851  /* *INDENT-ON* */
852 
853  for (j = 0; j < vec_len (sm->clients_tmp); j++)
854  {
855  client = sm->clients_tmp[j];
856 
858 
859  //Client may have disconnected abrubtly, clean up so we don't poll nothing.
860  if (!vl_reg)
861  {
862  sm->enable_poller =
863  clear_client_for_stat (IDX_PER_INTERFACE_COMBINED_COUNTERS,
864  reg->item, client->client_index);
865  continue;
866  }
867  mp = vl_msg_api_alloc_as_if_client (sizeof (*mp) + sizeof (*vp));
868  memset (mp, 0, sizeof (*mp));
869 
870  mp->_vl_msg_id =
871  ntohs (VL_API_VNET_PER_INTERFACE_COMBINED_COUNTERS);
872 
873  /*
874  * count will eventually be used to optimise the batching
875  * of per client messages for each stat. For now setting this to 1 then
876  * iterate. This will not affect API.
877  *
878  * FIXME instead of enqueueing here, this should be sent to a batch
879  * storer for per-client transmission. Each "mp" sent would be a single entry
880  * and if a client is listening to other sw_if_indexes for same, it would be
881  * appended to that *mp
882  *
883  *
884  * FIXME(s):
885  * - capturing the timestamp of the counters "when VPP knew them" is important.
886  * Less so is that the timing of the delivery to the control plane be in the same
887  * timescale.
888 
889  * i.e. As long as the control plane can delta messages from VPP and work out
890  * velocity etc based on the timestamp, it can do so in a more "batch mode".
891 
892  * It would be beneficial to keep a "per-client" message queue, and then
893  * batch all the stat messages for a client into one message, with
894  * discrete timestamps.
895 
896  * Given this particular API is for "per interface" one assumes that the scale
897  * is less than the ~0 case, which the prior API is suited for.
898  */
899 
900  /*
901  * 1 message per api call for now
902  */
903  mp->count = htonl (1);
904  mp->timestamp = htonl (vlib_time_now (sm->vlib_main));
905 
907  vp->sw_if_index = htonl (reg->item);
908 
909  im = &vnet_get_main ()->interface_main;
910 
911 #define _(X, x) \
912  cm = im->combined_sw_if_counters + X; \
913  vlib_get_combined_counter (cm, reg->item, &v); \
914  clib_mem_unaligned (&vp->x##_packets, u64) = \
915  clib_host_to_net_u64 (v.packets); \
916  clib_mem_unaligned (&vp->x##_bytes, u64) = \
917  clib_host_to_net_u64 (v.bytes);
918 
919 
922  _(VNET_INTERFACE_COUNTER_RX_UNICAST, rx_unicast);
923  _(VNET_INTERFACE_COUNTER_TX_UNICAST, tx_unicast);
924  _(VNET_INTERFACE_COUNTER_RX_MULTICAST, rx_multicast);
925  _(VNET_INTERFACE_COUNTER_TX_MULTICAST, tx_multicast);
926  _(VNET_INTERFACE_COUNTER_RX_BROADCAST, rx_broadcast);
927  _(VNET_INTERFACE_COUNTER_TX_BROADCAST, tx_broadcast);
928 
929 #undef _
930 
931  vl_api_send_msg (vl_reg, (u8 *) mp);
932  }
933  }
934 
936 }
937 
938 /**********************************
939  * Per Interface simple stats
940  **********************************/
941 
942 /* Request from client registering interfaces it wants */
943 static void
946 {
947  stats_main_t *sm = &stats_main;
949  vl_api_want_per_interface_simple_stats_reply_t *rmp;
951  uword *p;
952  i32 retval = 0;
954  u32 i, swif, num = 0;
955 
956  num = ntohl (mp->num);
957 
958  for (i = 0; i < num; i++)
959  {
960  swif = ntohl (mp->sw_ifs[i]);
961 
962  /* Check its a real sw_if_index that the client is allowed to see */
963  if (swif != ~0)
964  {
966  {
967  retval = VNET_API_ERROR_INVALID_SW_IF_INDEX;
968  goto reply;
969  }
970  }
971  }
972 
973  for (i = 0; i < num; i++)
974  {
975  swif = ntohl (mp->sw_ifs[i]);
976 
977  rp.client_index = mp->client_index;
978  rp.client_pid = mp->pid;
979  handle_client_registration (&rp, IDX_PER_INTERFACE_SIMPLE_COUNTERS,
980  swif, ntohl (mp->enable_disable));
981  }
982 
983 reply:
985 
986  /* Client may have disconnected abruptly, clean up */
987  if (!reg)
988  {
989  for (i = 0; i < num; i++)
990  {
991  swif = ntohl (mp->sw_ifs[i]);
992  sm->enable_poller =
993  clear_client_for_stat (IDX_PER_INTERFACE_SIMPLE_COUNTERS, swif,
994  mp->client_index);
995  }
996 
997  return;
998  }
999 
1000 
1001  rmp = vl_msg_api_alloc (sizeof (*rmp));
1002  rmp->_vl_msg_id = ntohs (VL_API_WANT_PER_INTERFACE_SIMPLE_STATS_REPLY);
1003  rmp->context = mp->context;
1004  rmp->retval = retval;
1005 
1006  vl_api_send_msg (reg, (u8 *) rmp);
1007 }
1008 
1009 /* Per Interface Simple distribution to client */
1010 static void
1012 {
1015  api_main_t *am = sm->api_main;
1017  vl_api_registration_t *vl_reg;
1019  u32 i, j, size;
1021  vpe_client_registration_t *client;
1022  u32 timestamp, count;
1024  counter_t v;
1025 
1027 
1028  vec_reset_length (sm->regs_tmp);
1029 
1030  /* *INDENT-OFF* */
1031  pool_foreach (reg,
1032  sm->stats_registrations[IDX_PER_INTERFACE_SIMPLE_COUNTERS],
1033  ({ vec_add1 (sm->regs_tmp, reg); }));
1034  /* *INDENT-ON* */
1035 
1036  for (i = 0; i < vec_len (sm->regs_tmp); i++)
1037  {
1038  reg = sm->regs_tmp[i];
1039  if (reg->item == ~0)
1040  {
1044  continue;
1045  }
1047 
1048  /* *INDENT-OFF* */
1049  pool_foreach (client, reg->clients, ({ vec_add1 (sm->clients_tmp,
1050  client);}));
1051  /* *INDENT-ON* */
1052 
1053  for (j = 0; j < vec_len (sm->clients_tmp); j++)
1054  {
1055  client = sm->clients_tmp[j];
1057 
1058  /* Client may have disconnected abrubtly, clean up */
1059  if (!vl_reg)
1060  {
1061  sm->enable_poller =
1062  clear_client_for_stat (IDX_PER_INTERFACE_SIMPLE_COUNTERS,
1063  reg->item, client->client_index);
1064  continue;
1065  }
1066 
1067  mp = vl_msg_api_alloc_as_if_client (sizeof (*mp) + sizeof (*vp));
1068  memset (mp, 0, sizeof (*mp));
1069  mp->_vl_msg_id = ntohs (VL_API_VNET_PER_INTERFACE_SIMPLE_COUNTERS);
1070 
1071  /*
1072  * count will eventually be used to optimise the batching
1073  * of per client messages for each stat. For now setting this to 1 then
1074  * iterate. This will not affect API.
1075  *
1076  * FIXME instead of enqueueing here, this should be sent to a batch
1077  * storer for per-client transmission. Each "mp" sent would be a single entry
1078  * and if a client is listening to other sw_if_indexes for same, it would be
1079  * appended to that *mp
1080  *
1081  *
1082  * FIXME(s):
1083  * - capturing the timestamp of the counters "when VPP knew them" is important.
1084  * Less so is that the timing of the delivery to the control plane be in the same
1085  * timescale.
1086 
1087  * i.e. As long as the control plane can delta messages from VPP and work out
1088  * velocity etc based on the timestamp, it can do so in a more "batch mode".
1089 
1090  * It would be beneficial to keep a "per-client" message queue, and then
1091  * batch all the stat messages for a client into one message, with
1092  * discrete timestamps.
1093 
1094  * Given this particular API is for "per interface" one assumes that the scale
1095  * is less than the ~0 case, which the prior API is suited for.
1096  */
1097 
1098  /*
1099  * 1 message per api call for now
1100  */
1101  mp->count = htonl (1);
1102  mp->timestamp = htonl (vlib_time_now (sm->vlib_main));
1103  vp = (vl_api_vnet_simple_counter_t *) mp->data;
1104 
1105  vp->sw_if_index = htonl (reg->item);
1106 
1107  // VNET_INTERFACE_COUNTER_DROP
1109  v = vlib_get_simple_counter (cm, reg->item);
1110  clib_mem_unaligned (&vp->drop, u64) = clib_host_to_net_u64 (v);
1111 
1112  // VNET_INTERFACE_COUNTER_PUNT
1114  v = vlib_get_simple_counter (cm, reg->item);
1115  clib_mem_unaligned (&vp->punt, u64) = clib_host_to_net_u64 (v);
1116 
1117  // VNET_INTERFACE_COUNTER_IP4
1119  v = vlib_get_simple_counter (cm, reg->item);
1120  clib_mem_unaligned (&vp->rx_ip4, u64) = clib_host_to_net_u64 (v);
1121 
1122  //VNET_INTERFACE_COUNTER_IP6
1124  v = vlib_get_simple_counter (cm, reg->item);
1125  clib_mem_unaligned (&vp->rx_ip6, u64) = clib_host_to_net_u64 (v);
1126 
1127  //VNET_INTERFACE_COUNTER_RX_NO_BUF
1129  v = vlib_get_simple_counter (cm, reg->item);
1131  clib_host_to_net_u64 (v);
1132 
1133  //VNET_INTERFACE_COUNTER_RX_MISS
1135  v = vlib_get_simple_counter (cm, reg->item);
1136  clib_mem_unaligned (&vp->rx_miss, u64) = clib_host_to_net_u64 (v);
1137 
1138  //VNET_INTERFACE_COUNTER_RX_ERROR
1140  v = vlib_get_simple_counter (cm, reg->item);
1141  clib_mem_unaligned (&vp->rx_error, u64) = clib_host_to_net_u64 (v);
1142 
1143  //VNET_INTERFACE_COUNTER_TX_ERROR
1145  v = vlib_get_simple_counter (cm, reg->item);
1146  clib_mem_unaligned (&vp->tx_error, u64) = clib_host_to_net_u64 (v);
1147 
1148  //VNET_INTERFACE_COUNTER_MPLS
1150  v = vlib_get_simple_counter (cm, reg->item);
1151  clib_mem_unaligned (&vp->rx_mpls, u64) = clib_host_to_net_u64 (v);
1152 
1153  vl_api_send_msg (vl_reg, (u8 *) mp);
1154  }
1155  }
1156 
1158 }
1159 
1160 /**********************************
1161  * Per FIB IP4 stats
1162  **********************************/
1163 
1164 static void
1166 {
1167  struct timespec _req, *req = &_req;
1168  struct timespec _rem, *rem = &_rem;
1169 
1170  req->tv_sec = sec;
1171  req->tv_nsec = nsec;
1172  while (1)
1173  {
1174  if (nanosleep (req, rem) == 0)
1175  break;
1176  *req = *rem;
1177  if (errno == EINTR)
1178  continue;
1179  clib_unix_warning ("nanosleep");
1180  break;
1181  }
1182 }
1183 
1184 /**
1185  * @brief The context passed when collecting adjacency counters
1186  */
1187 typedef struct ip4_nbr_stats_ctx_t_
1188 {
1189  /**
1190  * The SW IF index all these adjs belong to
1191  */
1193 
1194  /**
1195  * A vector of ip4 nbr counters
1196  */
1199 
1200 static adj_walk_rc_t
1202 {
1203  vl_api_ip4_nbr_counter_t *vl_counter;
1204  vlib_counter_t adj_counter;
1206  ip_adjacency_t *adj;
1207 
1208  ctx = arg;
1209  vlib_get_combined_counter (&adjacency_counters, ai, &adj_counter);
1210 
1211  if (0 != adj_counter.packets)
1212  {
1213  vec_add2 (ctx->counters, vl_counter, 1);
1214  adj = adj_get (ai);
1215 
1216  vl_counter->packets = clib_host_to_net_u64 (adj_counter.packets);
1217  vl_counter->bytes = clib_host_to_net_u64 (adj_counter.bytes);
1218  vl_counter->address = adj->sub_type.nbr.next_hop.ip4.as_u32;
1219  vl_counter->link_type = adj->ia_link;
1220  }
1221  return (ADJ_WALK_RC_CONTINUE);
1222 }
1223 
1224 #define MIN(x,y) (((x)<(y))?(x):(y))
1225 
1226 static void
1228 {
1229  api_main_t *am = sm->api_main;
1231  svm_queue_t *q = shmem_hdr->vl_input_queue;
1233  int first = 0;
1234 
1235  /*
1236  * If the walk context has counters, which may be left over from the last
1237  * suspend, then we continue from there.
1238  */
1239  while (0 != vec_len (ctx->counters))
1240  {
1241  u32 n_items = MIN (vec_len (ctx->counters),
1243  u8 pause = 0;
1244 
1245  dslock (sm, 0 /* release hint */ , 1 /* tag */ );
1246 
1247  mp = vl_msg_api_alloc_as_if_client (sizeof (*mp) +
1248  (n_items *
1249  sizeof
1251  mp->_vl_msg_id = ntohs (VL_API_VNET_IP4_NBR_COUNTERS);
1252  mp->count = ntohl (n_items);
1253  mp->sw_if_index = ntohl (ctx->sw_if_index);
1254  mp->begin = first;
1255  first = 0;
1256 
1257  /*
1258  * copy the counters from the back of the context, then we can easily
1259  * 'erase' them by resetting the vector length.
1260  * The order we push the stats to the caller is not important.
1261  */
1262  clib_memcpy (mp->c,
1263  &ctx->counters[vec_len (ctx->counters) - n_items],
1264  n_items * sizeof (*ctx->counters));
1265 
1266  _vec_len (ctx->counters) = vec_len (ctx->counters) - n_items;
1267 
1268  /*
1269  * send to the shm q
1270  */
1271  svm_queue_lock (q);
1272  pause = svm_queue_is_full (q);
1273 
1274  vl_msg_api_send_shmem_nolock (q, (u8 *) & mp);
1275  svm_queue_unlock (q);
1276  dsunlock (sm);
1277 
1278  if (pause)
1279  ip46_fib_stats_delay (sm, 0 /* sec */ ,
1281  }
1282 }
1283 
1284 static void
1286 {
1287  vnet_main_t *vnm = vnet_get_main ();
1289  vnet_sw_interface_t *si;
1290 
1292  .sw_if_index = 0,
1293  .counters = NULL,
1294  };
1295 
1296  /* *INDENT-OFF* */
1297  pool_foreach (si, im->sw_interfaces,
1298  ({
1299  /*
1300  * update the interface we are now concerned with
1301  */
1302  ctx.sw_if_index = si->sw_if_index;
1303 
1304  /*
1305  * we are about to walk another interface, so we shouldn't have any pending
1306  * stats to export.
1307  */
1308  ASSERT(ctx.counters == NULL);
1309 
1310  /*
1311  * visit each neighbour adjacency on the interface and collect
1312  * its current stats.
1313  * Because we hold the lock the walk is synchronous, so safe to routing
1314  * updates. It's limited in work by the number of adjacenies on an
1315  * interface, which is typically not huge.
1316  */
1317  dslock (sm, 0 /* release hint */ , 1 /* tag */ );
1318  adj_nbr_walk (si->sw_if_index,
1319  FIB_PROTOCOL_IP4,
1320  ip4_nbr_stats_cb,
1321  &ctx);
1322  dsunlock (sm);
1323 
1324  /*
1325  * if this interface has some adjacencies with counters then ship them,
1326  * else continue to the next interface.
1327  */
1328  if (NULL != ctx.counters)
1329  {
1330  ip4_nbr_ship(sm, &ctx);
1331  }
1332  }));
1333  /* *INDENT-OFF* */
1334 }
1335 
1336 /**
1337  * @brief The context passed when collecting adjacency counters
1338  */
1339 typedef struct ip6_nbr_stats_ctx_t_
1340 {
1341  /**
1342  * The SW IF index all these adjs belong to
1343  */
1345 
1346  /**
1347  * A vector of ip6 nbr counters
1348  */
1351 
1352 static adj_walk_rc_t
1354  void *arg)
1355 {
1356  vl_api_ip6_nbr_counter_t *vl_counter;
1357  vlib_counter_t adj_counter;
1359  ip_adjacency_t *adj;
1360 
1361  ctx = arg;
1362  vlib_get_combined_counter(&adjacency_counters, ai, &adj_counter);
1363 
1364  if (0 != adj_counter.packets)
1365  {
1366  vec_add2(ctx->counters, vl_counter, 1);
1367  adj = adj_get(ai);
1368 
1369  vl_counter->packets = clib_host_to_net_u64(adj_counter.packets);
1370  vl_counter->bytes = clib_host_to_net_u64(adj_counter.bytes);
1371  vl_counter->address[0] = adj->sub_type.nbr.next_hop.ip6.as_u64[0];
1372  vl_counter->address[1] = adj->sub_type.nbr.next_hop.ip6.as_u64[1];
1373  vl_counter->link_type = adj->ia_link;
1374  }
1375  return (ADJ_WALK_RC_CONTINUE);
1376 }
1377 
1378 #define MIN(x,y) (((x)<(y))?(x):(y))
1379 
1380 static void
1383 {
1384  api_main_t *am = sm->api_main;
1386  svm_queue_t *q = shmem_hdr->vl_input_queue;
1388  int first = 0;
1389 
1390  /*
1391  * If the walk context has counters, which may be left over from the last
1392  * suspend, then we continue from there.
1393  */
1394  while (0 != vec_len(ctx->counters))
1395  {
1396  u32 n_items = MIN (vec_len (ctx->counters),
1398  u8 pause = 0;
1399 
1400  dslock (sm, 0 /* release hint */ , 1 /* tag */ );
1401 
1402  mp = vl_msg_api_alloc_as_if_client (sizeof (*mp) +
1403  (n_items *
1404  sizeof
1406  mp->_vl_msg_id = ntohs (VL_API_VNET_IP6_NBR_COUNTERS);
1407  mp->count = ntohl (n_items);
1408  mp->sw_if_index = ntohl (ctx->sw_if_index);
1409  mp->begin = first;
1410  first = 0;
1411 
1412  /*
1413  * copy the counters from the back of the context, then we can easily
1414  * 'erase' them by resetting the vector length.
1415  * The order we push the stats to the caller is not important.
1416  */
1417  clib_memcpy (mp->c,
1418  &ctx->counters[vec_len (ctx->counters) - n_items],
1419  n_items * sizeof (*ctx->counters));
1420 
1421  _vec_len (ctx->counters) = vec_len (ctx->counters) - n_items;
1422 
1423  /*
1424  * send to the shm q
1425  */
1426  svm_queue_lock (q);
1427  pause = svm_queue_is_full (q);
1428 
1429  vl_msg_api_send_shmem_nolock (q, (u8 *) & mp);
1430  svm_queue_unlock (q);
1431  dsunlock (sm);
1432 
1433  if (pause)
1434  ip46_fib_stats_delay (sm, 0 /* sec */ ,
1436  }
1437 }
1438 
1439 static void
1441 {
1442  vnet_main_t *vnm = vnet_get_main ();
1444  vnet_sw_interface_t *si;
1445 
1447  .sw_if_index = 0,
1448  .counters = NULL,
1449  };
1450 
1451  /* *INDENT-OFF* */
1452  pool_foreach (si, im->sw_interfaces,
1453  ({
1454  /*
1455  * update the interface we are now concerned with
1456  */
1457  ctx.sw_if_index = si->sw_if_index;
1458 
1459  /*
1460  * we are about to walk another interface, so we shouldn't have any pending
1461  * stats to export.
1462  */
1463  ASSERT(ctx.counters == NULL);
1464 
1465  /*
1466  * visit each neighbour adjacency on the interface and collect
1467  * its current stats.
1468  * Because we hold the lock the walk is synchronous, so safe to routing
1469  * updates. It's limited in work by the number of adjacenies on an
1470  * interface, which is typically not huge.
1471  */
1472  dslock (sm, 0 /* release hint */ , 1 /* tag */ );
1473  adj_nbr_walk (si->sw_if_index,
1474  FIB_PROTOCOL_IP6,
1475  ip6_nbr_stats_cb,
1476  &ctx);
1477  dsunlock (sm);
1478 
1479  /*
1480  * if this interface has some adjacencies with counters then ship them,
1481  * else continue to the next interface.
1482  */
1483  if (NULL != ctx.counters)
1484  {
1485  ip6_nbr_ship(sm, &ctx);
1486  }
1487  }));
1488  /* *INDENT-OFF* */
1489 }
1490 
1491 static void
1493 {
1494  ip4_main_t *im4 = &ip4_main;
1495  api_main_t *am = sm->api_main;
1497  svm_queue_t *q = shmem_hdr->vl_input_queue;
1498  ip4_route_t *r;
1499  fib_table_t *fib;
1500  ip4_fib_t *v4_fib;
1501  do_ip46_fibs_t *do_fibs;
1503  u32 items_this_message;
1504  vl_api_ip4_fib_counter_t *ctrp = 0;
1505  u32 start_at_fib_index = 0;
1506  int i, j, k;
1507 
1508  do_fibs = &sm->do_ip46_fibs;
1509 
1510 again:
1511  vec_reset_length (do_fibs->fibs);
1512  /* *INDENT-OFF* */
1513  pool_foreach (fib, im4->fibs,
1514  ({vec_add1(do_fibs->fibs,fib);}));
1515 
1516  /* *INDENT-ON* */
1517 
1518  for (j = 0; j < vec_len (do_fibs->fibs); j++)
1519  {
1520  fib = do_fibs->fibs[j];
1521  /* We may have bailed out due to control-plane activity */
1522  while ((fib - im4->fibs) < start_at_fib_index)
1523  continue;
1524 
1525  v4_fib = pool_elt_at_index (im4->v4_fibs, fib->ft_index);
1526 
1527  if (mp == 0)
1528  {
1529  items_this_message = IP4_FIB_COUNTER_BATCH_SIZE;
1531  (sizeof (*mp) +
1532  items_this_message * sizeof (vl_api_ip4_fib_counter_t));
1533  mp->_vl_msg_id = ntohs (VL_API_VNET_IP4_FIB_COUNTERS);
1534  mp->count = 0;
1535  mp->vrf_id = ntohl (fib->ft_table_id);
1536  ctrp = (vl_api_ip4_fib_counter_t *) mp->c;
1537  }
1538  else
1539  {
1540  /* happens if the last FIB was empty... */
1541  ASSERT (mp->count == 0);
1542  mp->vrf_id = ntohl (fib->ft_table_id);
1543  }
1544 
1545  dslock (sm, 0 /* release hint */ , 1 /* tag */ );
1546 
1547  vec_reset_length (do_fibs->ip4routes);
1548  vec_reset_length (do_fibs->results);
1549 
1550  for (i = 0; i < ARRAY_LEN (v4_fib->fib_entry_by_dst_address); i++)
1551  {
1552  uword *hash = v4_fib->fib_entry_by_dst_address[i];
1553  hash_pair_t *p;
1554  ip4_route_t x;
1555 
1556  vec_reset_length (do_fibs->pvec);
1557 
1558  x.address_length = i;
1559 
1560  hash_foreach_pair (p, hash, (
1561  {
1562  vec_add1 (do_fibs->pvec, p);}
1563  ));
1564  for (k = 0; k < vec_len (do_fibs->pvec); k++)
1565  {
1566  p = do_fibs->pvec[k];
1567  x.address.data_u32 = p->key;
1568  x.index = p->value[0];
1569 
1570  vec_add1 (do_fibs->ip4routes, x);
1572  {
1573  start_at_fib_index = fib - im4->fibs;
1574  dsunlock (sm);
1575  ip46_fib_stats_delay (sm, 0 /* sec */ ,
1577  mp->count = 0;
1578  ctrp = (vl_api_ip4_fib_counter_t *) mp->c;
1579  goto again;
1580  }
1581  }
1582  }
1583 
1584  vec_foreach (r, do_fibs->ip4routes)
1585  {
1586  vlib_counter_t c;
1587  const dpo_id_t *dpo_id;
1588  u32 index;
1589 
1590  dpo_id = fib_entry_contribute_ip_forwarding (r->index);
1591  index = (u32) dpo_id->dpoi_index;
1592 
1594  index, &c);
1595  /*
1596  * If it has actually
1597  * seen at least one packet, send it.
1598  */
1599  if (c.packets > 0)
1600  {
1601 
1602  /* already in net byte order */
1603  ctrp->address = r->address.as_u32;
1604  ctrp->address_length = r->address_length;
1605  ctrp->packets = clib_host_to_net_u64 (c.packets);
1606  ctrp->bytes = clib_host_to_net_u64 (c.bytes);
1607  mp->count++;
1608  ctrp++;
1609 
1610  if (mp->count == items_this_message)
1611  {
1612  mp->count = htonl (items_this_message);
1613  /*
1614  * If the main thread's input queue is stuffed,
1615  * drop the data structure lock (which the main thread
1616  * may want), and take a pause.
1617  */
1618  svm_queue_lock (q);
1619  if (svm_queue_is_full (q))
1620  {
1621  dsunlock (sm);
1622  vl_msg_api_send_shmem_nolock (q, (u8 *) & mp);
1623  svm_queue_unlock (q);
1624  mp = 0;
1625  ip46_fib_stats_delay (sm, 0 /* sec */ ,
1627  goto again;
1628  }
1629  vl_msg_api_send_shmem_nolock (q, (u8 *) & mp);
1630  svm_queue_unlock (q);
1631 
1632  items_this_message = IP4_FIB_COUNTER_BATCH_SIZE;
1634  (sizeof (*mp) +
1635  items_this_message * sizeof (vl_api_ip4_fib_counter_t));
1636  mp->_vl_msg_id = ntohs (VL_API_VNET_IP4_FIB_COUNTERS);
1637  mp->count = 0;
1638  mp->vrf_id = ntohl (fib->ft_table_id);
1639  ctrp = (vl_api_ip4_fib_counter_t *) mp->c;
1640  }
1641  } /* for each (mp or single) adj */
1643  {
1644  start_at_fib_index = fib - im4->fibs;
1645  dsunlock (sm);
1646  ip46_fib_stats_delay (sm, 0 /* sec */ , STATS_RELEASE_DELAY_NS);
1647  mp->count = 0;
1648  ctrp = (vl_api_ip4_fib_counter_t *) mp->c;
1649  goto again;
1650  }
1651  } /* vec_foreach (routes) */
1652 
1653  dsunlock (sm);
1654 
1655  /* Flush any data from this fib */
1656  if (mp->count)
1657  {
1658  mp->count = htonl (mp->count);
1659  vl_msg_api_send_shmem (q, (u8 *) & mp);
1660  mp = 0;
1661  }
1662  }
1663 
1664  /* If e.g. the last FIB had no reportable routes, free the buffer */
1665  if (mp)
1666  vl_msg_api_free (mp);
1667 }
1668 
1669 static int
1671 {
1672  stats_main_t *sm = ctx;
1673  do_ip46_fibs_t *do_fibs;
1674  mfib_entry_t *entry;
1675 
1676  do_fibs = &sm->do_ip46_fibs;
1677  entry = mfib_entry_get (fei);
1678 
1679  vec_add1 (do_fibs->mroutes, entry->mfe_prefix);
1680 
1681  return (1);
1682 }
1683 
1684 static void
1686 {
1687  ip4_main_t *im4 = &ip4_main;
1688  api_main_t *am = sm->api_main;
1690  svm_queue_t *q = shmem_hdr->vl_input_queue;
1691  mfib_prefix_t *pfx;
1692  mfib_table_t *mfib;
1693  do_ip46_fibs_t *do_fibs;
1695  u32 items_this_message;
1696  vl_api_ip4_mfib_counter_t *ctrp = 0;
1697  u32 start_at_mfib_index = 0;
1698  int i, j, k;
1699 
1700  do_fibs = &sm->do_ip46_fibs;
1701 
1702  vec_reset_length (do_fibs->mfibs);
1703  /* *INDENT-OFF* */
1704  pool_foreach (mfib, im4->mfibs, ({vec_add1(do_fibs->mfibs, mfib);}));
1705  /* *INDENT-ON* */
1706 
1707  for (j = 0; j < vec_len (do_fibs->mfibs); j++)
1708  {
1709  mfib = do_fibs->mfibs[j];
1710  /* We may have bailed out due to control-plane activity */
1711  while ((mfib - im4->mfibs) < start_at_mfib_index)
1712  continue;
1713 
1714  if (mp == 0)
1715  {
1716  items_this_message = IP4_MFIB_COUNTER_BATCH_SIZE;
1718  (sizeof (*mp) +
1719  items_this_message * sizeof (vl_api_ip4_mfib_counter_t));
1720  mp->_vl_msg_id = ntohs (VL_API_VNET_IP4_MFIB_COUNTERS);
1721  mp->count = 0;
1722  mp->vrf_id = ntohl (mfib->mft_table_id);
1723  ctrp = (vl_api_ip4_mfib_counter_t *) mp->c;
1724  }
1725  else
1726  {
1727  /* happens if the last MFIB was empty... */
1728  ASSERT (mp->count == 0);
1729  mp->vrf_id = ntohl (mfib->mft_table_id);
1730  }
1731 
1732  vec_reset_length (do_fibs->mroutes);
1733 
1734  /*
1735  * walk the table with table updates blocked
1736  */
1737  dslock (sm, 0 /* release hint */ , 1 /* tag */ );
1738 
1739  mfib_table_walk (mfib->mft_index,
1741  dsunlock (sm);
1742 
1743  vec_foreach (pfx, do_fibs->mroutes)
1744  {
1745  const dpo_id_t *dpo_id;
1746  fib_node_index_t mfei;
1747  vlib_counter_t c;
1748  u32 index;
1749 
1750  /*
1751  * re-lookup the entry, since we suspend during the collection
1752  */
1753  mfei = mfib_table_lookup (mfib->mft_index, pfx);
1754 
1755  if (FIB_NODE_INDEX_INVALID == mfei)
1756  continue;
1757 
1758  dpo_id = mfib_entry_contribute_ip_forwarding (mfei);
1759  index = (u32) dpo_id->dpoi_index;
1760 
1762  dpo_id->dpoi_index, &c);
1763  /*
1764  * If it has seen at least one packet, send it.
1765  */
1766  if (c.packets > 0)
1767  {
1768  /* already in net byte order */
1769  memcpy (ctrp->group, &pfx->fp_grp_addr.ip4, 4);
1770  memcpy (ctrp->source, &pfx->fp_src_addr.ip4, 4);
1771  ctrp->group_length = pfx->fp_len;
1772  ctrp->packets = clib_host_to_net_u64 (c.packets);
1773  ctrp->bytes = clib_host_to_net_u64 (c.bytes);
1774  mp->count++;
1775  ctrp++;
1776 
1777  if (mp->count == items_this_message)
1778  {
1779  mp->count = htonl (items_this_message);
1780  /*
1781  * If the main thread's input queue is stuffed,
1782  * drop the data structure lock (which the main thread
1783  * may want), and take a pause.
1784  */
1785  svm_queue_lock (q);
1786 
1787  while (svm_queue_is_full (q))
1788  {
1789  svm_queue_unlock (q);
1790  ip46_fib_stats_delay (sm, 0 /* sec */ ,
1792  svm_queue_lock (q);
1793  }
1794  vl_msg_api_send_shmem_nolock (q, (u8 *) & mp);
1795  svm_queue_unlock (q);
1796 
1797  items_this_message = IP4_MFIB_COUNTER_BATCH_SIZE;
1799  (sizeof (*mp) +
1800  items_this_message * sizeof (vl_api_ip4_mfib_counter_t));
1801  mp->_vl_msg_id = ntohs (VL_API_VNET_IP4_MFIB_COUNTERS);
1802  mp->count = 0;
1803  mp->vrf_id = ntohl (mfib->mft_table_id);
1804  ctrp = (vl_api_ip4_mfib_counter_t *) mp->c;
1805  }
1806  }
1807  }
1808 
1809  /* Flush any data from this mfib */
1810  if (mp->count)
1811  {
1812  mp->count = htonl (mp->count);
1813  vl_msg_api_send_shmem (q, (u8 *) & mp);
1814  mp = 0;
1815  }
1816  }
1817 
1818  /* If e.g. the last FIB had no reportable routes, free the buffer */
1819  if (mp)
1820  vl_msg_api_free (mp);
1821 }
1822 
1823 static void
1825 {
1826  ip6_main_t *im6 = &ip6_main;
1827  api_main_t *am = sm->api_main;
1829  svm_queue_t *q = shmem_hdr->vl_input_queue;
1830  mfib_prefix_t *pfx;
1831  mfib_table_t *mfib;
1832  do_ip46_fibs_t *do_fibs;
1834  u32 items_this_message;
1835  vl_api_ip6_mfib_counter_t *ctrp = 0;
1836  u32 start_at_mfib_index = 0;
1837  int i, j, k;
1838 
1839  do_fibs = &sm->do_ip46_fibs;
1840 
1841  vec_reset_length (do_fibs->mfibs);
1842  /* *INDENT-OFF* */
1843  pool_foreach (mfib, im6->mfibs, ({vec_add1(do_fibs->mfibs, mfib);}));
1844  /* *INDENT-ON* */
1845 
1846  for (j = 0; j < vec_len (do_fibs->mfibs); j++)
1847  {
1848  mfib = do_fibs->mfibs[j];
1849  /* We may have bailed out due to control-plane activity */
1850  while ((mfib - im6->mfibs) < start_at_mfib_index)
1851  continue;
1852 
1853  if (mp == 0)
1854  {
1855  items_this_message = IP6_MFIB_COUNTER_BATCH_SIZE;
1857  (sizeof (*mp) +
1858  items_this_message * sizeof (vl_api_ip6_mfib_counter_t));
1859  mp->_vl_msg_id = ntohs (VL_API_VNET_IP6_MFIB_COUNTERS);
1860  mp->count = 0;
1861  mp->vrf_id = ntohl (mfib->mft_table_id);
1862  ctrp = (vl_api_ip6_mfib_counter_t *) mp->c;
1863  }
1864  else
1865  {
1866  /* happens if the last MFIB was empty... */
1867  ASSERT (mp->count == 0);
1868  mp->vrf_id = ntohl (mfib->mft_table_id);
1869  }
1870 
1871  vec_reset_length (do_fibs->mroutes);
1872 
1873  /*
1874  * walk the table with table updates blocked
1875  */
1876  dslock (sm, 0 /* release hint */ , 1 /* tag */ );
1877 
1878  mfib_table_walk (mfib->mft_index,
1880  dsunlock (sm);
1881 
1882  vec_foreach (pfx, do_fibs->mroutes)
1883  {
1884  const dpo_id_t *dpo_id;
1885  fib_node_index_t mfei;
1886  vlib_counter_t c;
1887  u32 index;
1888 
1889  /*
1890  * re-lookup the entry, since we suspend during the collection
1891  */
1892  mfei = mfib_table_lookup (mfib->mft_index, pfx);
1893 
1894  if (FIB_NODE_INDEX_INVALID == mfei)
1895  continue;
1896 
1897  dpo_id = mfib_entry_contribute_ip_forwarding (mfei);
1898  index = (u32) dpo_id->dpoi_index;
1899 
1901  dpo_id->dpoi_index, &c);
1902  /*
1903  * If it has seen at least one packet, send it.
1904  */
1905  if (c.packets > 0)
1906  {
1907  /* already in net byte order */
1908  memcpy (ctrp->group, &pfx->fp_grp_addr.ip6, 16);
1909  memcpy (ctrp->source, &pfx->fp_src_addr.ip6, 16);
1910  ctrp->group_length = pfx->fp_len;
1911  ctrp->packets = clib_host_to_net_u64 (c.packets);
1912  ctrp->bytes = clib_host_to_net_u64 (c.bytes);
1913  mp->count++;
1914  ctrp++;
1915 
1916  if (mp->count == items_this_message)
1917  {
1918  mp->count = htonl (items_this_message);
1919  /*
1920  * If the main thread's input queue is stuffed,
1921  * drop the data structure lock (which the main thread
1922  * may want), and take a pause.
1923  */
1924  svm_queue_lock (q);
1925 
1926  while (svm_queue_is_full (q))
1927  {
1928  svm_queue_unlock (q);
1929  ip46_fib_stats_delay (sm, 0 /* sec */ ,
1931  svm_queue_lock (q);
1932  }
1933  vl_msg_api_send_shmem_nolock (q, (u8 *) & mp);
1934  svm_queue_unlock (q);
1935 
1936  items_this_message = IP6_MFIB_COUNTER_BATCH_SIZE;
1938  (sizeof (*mp) +
1939  items_this_message * sizeof (vl_api_ip6_mfib_counter_t));
1940  mp->_vl_msg_id = ntohs (VL_API_VNET_IP6_MFIB_COUNTERS);
1941  mp->count = 0;
1942  mp->vrf_id = ntohl (mfib->mft_table_id);
1943  ctrp = (vl_api_ip6_mfib_counter_t *) mp->c;
1944  }
1945  }
1946  }
1947 
1948  /* Flush any data from this mfib */
1949  if (mp->count)
1950  {
1951  mp->count = htonl (mp->count);
1952  vl_msg_api_send_shmem (q, (u8 *) & mp);
1953  mp = 0;
1954  }
1955  }
1956 
1957  /* If e.g. the last FIB had no reportable routes, free the buffer */
1958  if (mp)
1959  vl_msg_api_free (mp);
1960 }
1961 
1962 typedef struct
1963 {
1968 
1969 static void
1970 add_routes_in_fib (BVT (clib_bihash_kv) * kvp, void *arg)
1971 {
1972  add_routes_in_fib_arg_t *ap = arg;
1973  stats_main_t *sm = ap->sm;
1974 
1976  clib_longjmp (&sm->jmp_buf, 1);
1977 
1978  if (kvp->key[2] >> 32 == ap->fib_index)
1979  {
1981  ip6_route_t *r;
1982  addr = (ip6_address_t *) kvp;
1983  vec_add2 (*ap->routep, r, 1);
1984  r->address = addr[0];
1985  r->address_length = kvp->key[2] & 0xFF;
1986  r->index = kvp->value;
1987  }
1988 }
1989 
1990 static void
1992 {
1993  ip6_main_t *im6 = &ip6_main;
1994  api_main_t *am = sm->api_main;
1996  svm_queue_t *q = shmem_hdr->vl_input_queue;
1997  ip6_route_t *r;
1998  fib_table_t *fib;
1999  do_ip46_fibs_t *do_fibs;
2001  u32 items_this_message;
2002  vl_api_ip6_fib_counter_t *ctrp = 0;
2003  u32 start_at_fib_index = 0;
2004  BVT (clib_bihash) * h = &im6->ip6_table[IP6_FIB_TABLE_FWDING].ip6_hash;
2005  add_routes_in_fib_arg_t _a, *a = &_a;
2006  int i;
2007 
2008  do_fibs = &sm->do_ip46_fibs;
2009 again:
2010  vec_reset_length (do_fibs->fibs);
2011  /* *INDENT-OFF* */
2012  pool_foreach (fib, im6->fibs,
2013  ({vec_add1(do_fibs->fibs,fib);}));
2014  /* *INDENT-ON* */
2015 
2016 
2017  for (i = 0; i < vec_len (do_fibs->fibs); i++)
2018  {
2019  fib = do_fibs->fibs[i];
2020  /* We may have bailed out due to control-plane activity */
2021  while ((fib - im6->fibs) < start_at_fib_index)
2022  continue;
2023 
2024  if (mp == 0)
2025  {
2026  items_this_message = IP6_FIB_COUNTER_BATCH_SIZE;
2028  (sizeof (*mp) +
2029  items_this_message * sizeof (vl_api_ip6_fib_counter_t));
2030  mp->_vl_msg_id = ntohs (VL_API_VNET_IP6_FIB_COUNTERS);
2031  mp->count = 0;
2032  mp->vrf_id = ntohl (fib->ft_table_id);
2033  ctrp = (vl_api_ip6_fib_counter_t *) mp->c;
2034  }
2035 
2036  dslock (sm, 0 /* release hint */ , 1 /* tag */ );
2037 
2038  vec_reset_length (do_fibs->ip6routes);
2039  vec_reset_length (do_fibs->results);
2040 
2041  a->fib_index = fib - im6->fibs;
2042  a->routep = &do_fibs->ip6routes;
2043  a->sm = sm;
2044 
2045  if (clib_setjmp (&sm->jmp_buf, 0) == 0)
2046  {
2047  start_at_fib_index = fib - im6->fibs;
2049  }
2050  else
2051  {
2052  dsunlock (sm);
2053  ip46_fib_stats_delay (sm, 0 /* sec */ ,
2055  mp->count = 0;
2056  ctrp = (vl_api_ip6_fib_counter_t *) mp->c;
2057  goto again;
2058  }
2059 
2060  vec_foreach (r, do_fibs->ip6routes)
2061  {
2062  vlib_counter_t c;
2063 
2065  r->index, &c);
2066  /*
2067  * If it has actually
2068  * seen at least one packet, send it.
2069  */
2070  if (c.packets > 0)
2071  {
2072  /* already in net byte order */
2073  ctrp->address[0] = r->address.as_u64[0];
2074  ctrp->address[1] = r->address.as_u64[1];
2075  ctrp->address_length = (u8) r->address_length;
2076  ctrp->packets = clib_host_to_net_u64 (c.packets);
2077  ctrp->bytes = clib_host_to_net_u64 (c.bytes);
2078  mp->count++;
2079  ctrp++;
2080 
2081  if (mp->count == items_this_message)
2082  {
2083  mp->count = htonl (items_this_message);
2084  /*
2085  * If the main thread's input queue is stuffed,
2086  * drop the data structure lock (which the main thread
2087  * may want), and take a pause.
2088  */
2089  svm_queue_lock (q);
2090  if (svm_queue_is_full (q))
2091  {
2092  dsunlock (sm);
2093  vl_msg_api_send_shmem_nolock (q, (u8 *) & mp);
2094  svm_queue_unlock (q);
2095  mp = 0;
2096  ip46_fib_stats_delay (sm, 0 /* sec */ ,
2098  goto again;
2099  }
2100  vl_msg_api_send_shmem_nolock (q, (u8 *) & mp);
2101  svm_queue_unlock (q);
2102 
2103  items_this_message = IP6_FIB_COUNTER_BATCH_SIZE;
2105  (sizeof (*mp) +
2106  items_this_message * sizeof (vl_api_ip6_fib_counter_t));
2107  mp->_vl_msg_id = ntohs (VL_API_VNET_IP6_FIB_COUNTERS);
2108  mp->count = 0;
2109  mp->vrf_id = ntohl (fib->ft_table_id);
2110  ctrp = (vl_api_ip6_fib_counter_t *) mp->c;
2111  }
2112  }
2113 
2115  {
2116  start_at_fib_index = fib - im6->fibs;
2117  dsunlock (sm);
2118  ip46_fib_stats_delay (sm, 0 /* sec */ , STATS_RELEASE_DELAY_NS);
2119  mp->count = 0;
2120  ctrp = (vl_api_ip6_fib_counter_t *) mp->c;
2121  goto again;
2122  }
2123  } /* vec_foreach (routes) */
2124 
2125  dsunlock (sm);
2126 
2127  /* Flush any data from this fib */
2128  if (mp->count)
2129  {
2130  mp->count = htonl (mp->count);
2131  vl_msg_api_send_shmem (q, (u8 *) & mp);
2132  mp = 0;
2133  }
2134  }
2135 
2136  /* If e.g. the last FIB had no reportable routes, free the buffer */
2137  if (mp)
2138  vl_msg_api_free (mp);
2139 }
2140 
2141 typedef struct udp_encap_stat_t_
2142 {
2144  u64 stats[2];
2146 
2148 {
2151 
2152 static int
2154 {
2155  udp_encap_stats_walk_t *ctx = arg;
2156  udp_encap_stat_t *stat;
2157  udp_encap_t *ue;
2158 
2159  ue = udp_encap_get (uei);
2160  vec_add2 (ctx->stats, stat, 1);
2161 
2162  stat->ue_id = uei;
2163  udp_encap_get_stats (ue->ue_id, &stat->stats[0], &stat->stats[1]);
2164 
2165  return (1);
2166 }
2167 
2168 static void
2170 {
2173  stats_main_t *sm;
2174  api_main_t *am;
2175  svm_queue_t *q;
2176 
2177  mp = NULL;
2178  sm = &stats_main;
2179  am = sm->api_main;
2180  shmem_hdr = am->shmem_hdr;
2181  q = shmem_hdr->vl_input_queue;
2182 
2183  /*
2184  * If the walk context has counters, which may be left over from the last
2185  * suspend, then we continue from there.
2186  */
2187  while (0 != vec_len (ctx->stats))
2188  {
2189  u32 n_items = MIN (vec_len (ctx->stats),
2191  u8 pause = 0;
2192 
2193  dslock (sm, 0 /* release hint */ , 1 /* tag */ );
2194 
2195  mp = vl_msg_api_alloc_as_if_client (sizeof (*mp) +
2196  (n_items *
2197  sizeof
2199  mp->_vl_msg_id = ntohs (VL_API_VNET_UDP_ENCAP_COUNTERS);
2200  mp->count = ntohl (n_items);
2201 
2202  /*
2203  * copy the counters from the back of the context, then we can easily
2204  * 'erase' them by resetting the vector length.
2205  * The order we push the stats to the caller is not important.
2206  */
2207  clib_memcpy (mp->c,
2208  &ctx->stats[vec_len (ctx->stats) - n_items],
2209  n_items * sizeof (*ctx->stats));
2210 
2211  _vec_len (ctx->stats) = vec_len (ctx->stats) - n_items;
2212 
2213  /*
2214  * send to the shm q
2215  */
2216  svm_queue_lock (q);
2217  pause = svm_queue_is_full (q);
2218 
2219  vl_msg_api_send_shmem_nolock (q, (u8 *) & mp);
2220  svm_queue_unlock (q);
2221  dsunlock (sm);
2222 
2223  if (pause)
2224  ip46_fib_stats_delay (sm, 0 /* sec */ ,
2226  }
2227 }
2228 
2229 static void
2231 {
2232  udp_encap_stat_t *stat;
2233 
2235  .stats = NULL,
2236  };
2237 
2238  dslock (sm, 0 /* release hint */ , 1 /* tag */ );
2240  dsunlock (sm);
2241 
2242  udp_encap_ship (&ctx);
2243 }
2244 
2245 int
2246 stats_set_poller_delay (u32 poller_delay_sec)
2247 {
2248  stats_main_t *sm = &stats_main;
2249  if (!poller_delay_sec)
2250  {
2251  return VNET_API_ERROR_INVALID_ARGUMENT;
2252  }
2253  else
2254  {
2255  sm->stats_poll_interval_in_seconds = poller_delay_sec;
2256  return 0;
2257  }
2258 }
2259 
2260 static clib_error_t *
2262 {
2263  u32 sec;
2264 
2265  while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
2266  {
2267  if (unformat (input, "interval %u", &sec))
2268  {
2269  int rv = stats_set_poller_delay (sec);
2270  if (rv)
2271  {
2272  return clib_error_return (0,
2273  "`stats_set_poller_delay' API call failed, rv=%d:%U",
2274  (int) rv, format_vnet_api_errno, rv);
2275  }
2276  return 0;
2277  }
2278  else
2279  {
2280  return clib_error_return (0, "unknown input '%U'",
2281  format_unformat_error, input);
2282  }
2283  }
2284  return 0;
2285 }
2286 
2287 /* stats { ... } configuration. */
2288 /*?
2289  *
2290  * @cfgcmd{interval, &lt;seconds&gt;}
2291  * Configure stats poller delay to be @c seconds.
2292  *
2293 ?*/
2295 
2296 static void
2299 {
2300  stats_main_t *sm = &stats_main;
2301  vl_api_registration_t *reg;
2303  if (!reg)
2304  return;
2306 
2307  rmp = vl_msg_api_alloc (sizeof (*rmp));
2308  rmp->_vl_msg_id = ntohs (VL_API_WANT_PER_INTERFACE_SIMPLE_STATS_REPLY);
2309  rmp->context = mp->context;
2310  rmp->retval = 0;
2311  rmp->delay = clib_host_to_net_u32 (sm->stats_poll_interval_in_seconds);
2312 
2313  vl_api_send_msg (reg, (u8 *) rmp);
2314 
2315 }
2316 
2317 static void
2318 stats_thread_fn (void *arg)
2319 {
2320  stats_main_t *sm = &stats_main;
2323 
2324  /* stats thread wants no signals. */
2325  {
2326  sigset_t s;
2327  sigfillset (&s);
2328  pthread_sigmask (SIG_SETMASK, &s, 0);
2329  }
2330 
2331  if (vec_len (tm->thread_prefix))
2332  vlib_set_thread_name ((char *)
2333  format (0, "%v_stats%c", tm->thread_prefix, '\0'));
2334 
2336 
2337  while (1)
2338  {
2340  0 /* nsec */ );
2341 
2342  if (!(sm->enable_poller))
2343  {
2344  continue;
2345  }
2346  if (pool_elts
2347  (sm->stats_registrations[IDX_PER_INTERFACE_COMBINED_COUNTERS]))
2349 
2350  if (pool_elts
2351  (sm->stats_registrations[IDX_PER_INTERFACE_SIMPLE_COUNTERS]))
2353 
2354  if (pool_elts (sm->stats_registrations[IDX_IP4_FIB_COUNTERS]))
2355  do_ip4_fib_counters (sm);
2356 
2357  if (pool_elts (sm->stats_registrations[IDX_IP6_FIB_COUNTERS]))
2358  do_ip6_fib_counters (sm);
2359 
2360  if (pool_elts (sm->stats_registrations[IDX_IP4_MFIB_COUNTERS]))
2361  do_ip4_mfib_counters (sm);
2362 
2363  if (pool_elts (sm->stats_registrations[IDX_IP6_MFIB_COUNTERS]))
2364  do_ip6_mfib_counters (sm);
2365 
2366  if (pool_elts (sm->stats_registrations[IDX_IP4_NBR_COUNTERS]))
2367  do_ip4_nbr_counters (sm);
2368 
2369  if (pool_elts (sm->stats_registrations[IDX_IP6_NBR_COUNTERS]))
2370  do_ip6_nbr_counters (sm);
2371 
2372  if (pool_elts (sm->stats_registrations[IDX_UDP_ENCAP_COUNTERS]))
2373  do_udp_encap_counters (sm);
2374  }
2375 }
2376 
2377 static void
2380 {
2381  vpe_client_registration_t *clients, client;
2382  stats_main_t *sm = &stats_main;
2383  vl_api_registration_t *reg, *reg_prev = NULL;
2385  u32 mp_size;
2386  int i;
2387 
2388  mp_size = sizeof (*mp) + (ntohl (mp->count) * sizeof (u64));
2389 
2390  clients =
2391  get_clients_for_stat (IDX_PER_INTERFACE_SIMPLE_COUNTERS,
2392  ~0 /*flag for all */ );
2393 
2394  for (i = 0; i < vec_len (clients); i++)
2395  {
2396  client = clients[i];
2398  if (reg)
2399  {
2400  if (reg_prev && vl_api_can_send_msg (reg_prev))
2401  {
2402  mp_copy = vl_msg_api_alloc_as_if_client (mp_size);
2403  clib_memcpy (mp_copy, mp, mp_size);
2404  vl_api_send_msg (reg_prev, (u8 *) mp);
2405  mp = mp_copy;
2406  }
2407  reg_prev = reg;
2408  }
2409  else
2410  {
2411  sm->enable_poller =
2412  clear_client_for_stat (IDX_PER_INTERFACE_SIMPLE_COUNTERS, ~0,
2413  client.client_index);
2414  continue;
2415  }
2416  }
2417  vec_free (clients);
2418 
2419 #if STATS_DEBUG > 0
2420  fformat (stdout, "%U\n", format_vnet_simple_counters, mp);
2421 #endif
2422 
2423  if (reg_prev && vl_api_can_send_msg (reg_prev))
2424  {
2425  vl_api_send_msg (reg_prev, (u8 *) mp);
2426  }
2427  else
2428  {
2429  vl_msg_api_free (mp);
2430  }
2431 }
2432 
2433 static void
2435 {
2436  stats_main_t *sm = &stats_main;
2437  vl_api_registration_t *reg, *reg_prev = NULL;
2439  u32 mp_size;
2440  vpe_client_registration_t *clients, client;
2441  int i;
2442 
2443  mp_size = sizeof (*mp_copy) +
2444  ntohl (mp->count) * sizeof (vl_api_ip4_fib_counter_t);
2445 
2446  clients =
2447  get_clients_for_stat (IDX_IP4_FIB_COUNTERS, ~0 /*flag for all */ );
2448 
2449  for (i = 0; i < vec_len (clients); i++)
2450  {
2451  client = clients[i];
2453  if (reg)
2454  {
2455  if (reg_prev && vl_api_can_send_msg (reg_prev))
2456  {
2457  mp_copy = vl_msg_api_alloc_as_if_client (mp_size);
2458  clib_memcpy (mp_copy, mp, mp_size);
2459  vl_api_send_msg (reg_prev, (u8 *) mp);
2460  mp = mp_copy;
2461  }
2462  reg_prev = reg;
2463  }
2464  else
2465  {
2466  sm->enable_poller = clear_client_for_stat (IDX_IP4_FIB_COUNTERS,
2467  ~0, client.client_index);
2468  continue;
2469  }
2470  }
2471  vec_free (clients);
2472 
2473  if (reg_prev && vl_api_can_send_msg (reg_prev))
2474  {
2475  vl_api_send_msg (reg_prev, (u8 *) mp);
2476  }
2477  else
2478  {
2479  vl_msg_api_free (mp);
2480  }
2481 }
2482 
2483 static void
2485 {
2486  stats_main_t *sm = &stats_main;
2487  vl_api_registration_t *reg, *reg_prev = NULL;
2489  u32 mp_size;
2490  vpe_client_registration_t *clients, client;
2491  int i;
2492 
2493  mp_size = sizeof (*mp_copy) +
2494  ntohl (mp->count) * sizeof (vl_api_ip4_nbr_counter_t);
2495 
2496  clients =
2497  get_clients_for_stat (IDX_IP4_NBR_COUNTERS, ~0 /*flag for all */ );
2498 
2499  for (i = 0; i < vec_len (clients); i++)
2500  {
2501  client = clients[i];
2503  if (reg)
2504  {
2505  if (reg_prev && vl_api_can_send_msg (reg_prev))
2506  {
2507  mp_copy = vl_msg_api_alloc_as_if_client (mp_size);
2508  clib_memcpy (mp_copy, mp, mp_size);
2509  vl_api_send_msg (reg_prev, (u8 *) mp);
2510  mp = mp_copy;
2511  }
2512  reg_prev = reg;
2513  }
2514  else
2515  {
2516  sm->enable_poller = clear_client_for_stat (IDX_IP4_NBR_COUNTERS,
2517  ~0, client.client_index);
2518  continue;
2519  }
2520  }
2521  vec_free (clients);
2522 
2523  /* *INDENT-ON* */
2524  if (reg_prev && vl_api_can_send_msg (reg_prev))
2525  {
2526  vl_api_send_msg (reg_prev, (u8 *) mp);
2527  }
2528  else
2529  {
2530  vl_msg_api_free (mp);
2531  }
2532 }
2533 
2534 static void
2536 {
2537  stats_main_t *sm = &stats_main;
2538  vl_api_registration_t *reg, *reg_prev = NULL;
2540  u32 mp_size;
2541  vpe_client_registration_t *clients, client;
2542  int i;
2543 
2544  mp_size = sizeof (*mp_copy) +
2545  ntohl (mp->count) * sizeof (vl_api_ip6_fib_counter_t);
2546 
2547  clients =
2548  get_clients_for_stat (IDX_IP6_FIB_COUNTERS, ~0 /*flag for all */ );
2549 
2550  for (i = 0; i < vec_len (clients); i++)
2551  {
2552  client = clients[i];
2554  if (reg)
2555  {
2556  if (reg_prev && vl_api_can_send_msg (reg_prev))
2557  {
2558  mp_copy = vl_msg_api_alloc_as_if_client (mp_size);
2559  clib_memcpy (mp_copy, mp, mp_size);
2560  vl_api_send_msg (reg_prev, (u8 *) mp);
2561  mp = mp_copy;
2562  }
2563  reg_prev = reg;
2564  }
2565  else
2566  {
2567  sm->enable_poller = clear_client_for_stat (IDX_IP6_FIB_COUNTERS,
2568  ~0, client.client_index);
2569  continue;
2570  }
2571  }
2572  vec_free (clients);
2573 
2574  /* *INDENT-ON* */
2575  if (reg_prev && vl_api_can_send_msg (reg_prev))
2576  {
2577  vl_api_send_msg (reg_prev, (u8 *) mp);
2578  }
2579  else
2580  {
2581  vl_msg_api_free (mp);
2582  }
2583 }
2584 
2585 static void
2587 {
2588  stats_main_t *sm = &stats_main;
2589  vl_api_registration_t *reg, *reg_prev = NULL;
2591  u32 mp_size;
2592  vpe_client_registration_t *clients, client;
2593  int i;
2594 
2595  mp_size = sizeof (*mp_copy) +
2596  ntohl (mp->count) * sizeof (vl_api_ip6_nbr_counter_t);
2597 
2598  clients =
2599  get_clients_for_stat (IDX_IP6_NBR_COUNTERS, ~0 /*flag for all */ );
2600 
2601  for (i = 0; i < vec_len (clients); i++)
2602  {
2603  client = clients[i];
2605  if (reg)
2606  {
2607  if (reg_prev && vl_api_can_send_msg (reg_prev))
2608  {
2609  mp_copy = vl_msg_api_alloc_as_if_client (mp_size);
2610  clib_memcpy (mp_copy, mp, mp_size);
2611  vl_api_send_msg (reg_prev, (u8 *) mp);
2612  mp = mp_copy;
2613  }
2614  reg_prev = reg;
2615  }
2616  else
2617  {
2618  sm->enable_poller = clear_client_for_stat (IDX_IP6_NBR_COUNTERS,
2619  ~0, client.client_index);
2620  continue;
2621  }
2622  }
2623  vec_free (clients);
2624 
2625  /* *INDENT-ON* */
2626  if (reg_prev && vl_api_can_send_msg (reg_prev))
2627  {
2628  vl_api_send_msg (reg_prev, (u8 *) mp);
2629  }
2630  else
2631  {
2632  vl_msg_api_free (mp);
2633  }
2634 }
2635 
2636 static void
2638 {
2639  stats_main_t *sm = &stats_main;
2641  vl_api_want_udp_encap_stats_reply_t *rmp;
2642  uword *p;
2643  i32 retval = 0;
2644  vl_api_registration_t *reg;
2645  u32 fib;
2646 
2647  fib = ~0; //Using same mechanism as _per_interface_
2648  rp.client_index = mp->client_index;
2649  rp.client_pid = mp->pid;
2650 
2651  handle_client_registration (&rp, IDX_UDP_ENCAP_COUNTERS, fib, mp->enable);
2652 
2653 reply:
2655 
2656  if (!reg)
2657  {
2658  sm->enable_poller = clear_client_for_stat (IDX_UDP_ENCAP_COUNTERS,
2659  fib, mp->client_index);
2660  return;
2661  }
2662 
2663  rmp = vl_msg_api_alloc (sizeof (*rmp));
2664  rmp->_vl_msg_id = ntohs (VL_API_WANT_UDP_ENCAP_STATS_REPLY);
2665  rmp->context = mp->context;
2666  rmp->retval = retval;
2667 
2668  vl_api_send_msg (reg, (u8 *) rmp);
2669 }
2670 
2671 static void
2673 {
2674  stats_main_t *sm = &stats_main;
2676  vl_api_want_stats_reply_t *rmp;
2677  uword *p;
2678  i32 retval = 0;
2679  u32 item;
2680  vl_api_registration_t *reg;
2681 
2682  item = ~0; //"ALL THE THINGS IN THE THINGS
2683  rp.client_index = mp->client_index;
2684  rp.client_pid = mp->pid;
2685 
2686  handle_client_registration (&rp, IDX_PER_INTERFACE_SIMPLE_COUNTERS,
2687  item, mp->enable_disable);
2688 
2689  handle_client_registration (&rp, IDX_PER_INTERFACE_COMBINED_COUNTERS,
2690  item, mp->enable_disable);
2691 
2692  handle_client_registration (&rp, IDX_IP4_FIB_COUNTERS,
2693  item, mp->enable_disable);
2694 
2695  handle_client_registration (&rp, IDX_IP4_NBR_COUNTERS,
2696  item, mp->enable_disable);
2697 
2698  handle_client_registration (&rp, IDX_IP6_FIB_COUNTERS,
2699  item, mp->enable_disable);
2700 
2701  handle_client_registration (&rp, IDX_IP6_NBR_COUNTERS,
2702  item, mp->enable_disable);
2703 
2704 reply:
2706  if (!reg)
2707  return;
2708 
2709  rmp = vl_msg_api_alloc (sizeof (*rmp));
2710  rmp->_vl_msg_id = ntohs (VL_API_WANT_STATS_REPLY);
2711  rmp->context = mp->context;
2712  rmp->retval = retval;
2713 
2714  vl_api_send_msg (reg, (u8 *) rmp);
2715 }
2716 
2717 static void
2720 {
2721  stats_main_t *sm = &stats_main;
2723  vl_api_want_interface_simple_stats_reply_t *rmp;
2724  uword *p;
2725  i32 retval = 0;
2726  u32 swif;
2727  vl_api_registration_t *reg;
2728 
2729  swif = ~0; //Using same mechanism as _per_interface_
2730  rp.client_index = mp->client_index;
2731  rp.client_pid = mp->pid;
2732 
2733  handle_client_registration (&rp, IDX_PER_INTERFACE_SIMPLE_COUNTERS, swif,
2734  mp->enable_disable);
2735 
2736 reply:
2738 
2739  if (!reg)
2740  {
2741  sm->enable_poller =
2742  clear_client_for_stat (IDX_PER_INTERFACE_SIMPLE_COUNTERS, swif,
2743  mp->client_index);
2744  return;
2745  }
2746 
2747  rmp = vl_msg_api_alloc (sizeof (*rmp));
2748  rmp->_vl_msg_id = ntohs (VL_API_WANT_INTERFACE_SIMPLE_STATS_REPLY);
2749  rmp->context = mp->context;
2750  rmp->retval = retval;
2751 
2752  vl_api_send_msg (reg, (u8 *) rmp);
2753 }
2754 
2755 
2756 static void
2758 {
2759  stats_main_t *sm = &stats_main;
2761  vl_api_want_ip4_fib_stats_reply_t *rmp;
2762  uword *p;
2763  i32 retval = 0;
2764  vl_api_registration_t *reg;
2765  u32 fib;
2766 
2767  fib = ~0; //Using same mechanism as _per_interface_
2768  rp.client_index = mp->client_index;
2769  rp.client_pid = mp->pid;
2770 
2771  handle_client_registration (&rp, IDX_IP4_FIB_COUNTERS, fib,
2772  mp->enable_disable);
2773 
2774 reply:
2776 
2777  if (!reg)
2778  {
2779  sm->enable_poller = clear_client_for_stat (IDX_IP4_FIB_COUNTERS,
2780  fib, mp->client_index);
2781  return;
2782  }
2783 
2784  rmp = vl_msg_api_alloc (sizeof (*rmp));
2785  rmp->_vl_msg_id = ntohs (VL_API_WANT_IP4_FIB_STATS_REPLY);
2786  rmp->context = mp->context;
2787  rmp->retval = retval;
2788 
2789  vl_api_send_msg (reg, (u8 *) rmp);
2790 }
2791 
2792 static void
2794 {
2795  stats_main_t *sm = &stats_main;
2797  vl_api_want_ip4_mfib_stats_reply_t *rmp;
2798  uword *p;
2799  i32 retval = 0;
2800  vl_api_registration_t *reg;
2801  u32 mfib;
2802 
2803  mfib = ~0; //Using same mechanism as _per_interface_
2804  rp.client_index = mp->client_index;
2805  rp.client_pid = mp->pid;
2806 
2807  handle_client_registration (&rp, IDX_IP4_MFIB_COUNTERS, mfib,
2808  mp->enable_disable);
2809 
2810 reply:
2812  if (!reg)
2813  {
2814  sm->enable_poller = clear_client_for_stat (IDX_IP4_MFIB_COUNTERS,
2815  mfib, mp->client_index);
2816  return;
2817  }
2818 
2819  rmp = vl_msg_api_alloc (sizeof (*rmp));
2820  rmp->_vl_msg_id = ntohs (VL_API_WANT_IP4_MFIB_STATS_REPLY);
2821  rmp->context = mp->context;
2822  rmp->retval = retval;
2823 
2824  vl_api_send_msg (reg, (u8 *) rmp);
2825 }
2826 
2827 static void
2829 {
2830  stats_main_t *sm = &stats_main;
2832  vl_api_want_ip4_fib_stats_reply_t *rmp;
2833  uword *p;
2834  i32 retval = 0;
2835  vl_api_registration_t *reg;
2836  u32 fib;
2837 
2838  fib = ~0; //Using same mechanism as _per_interface_
2839  rp.client_index = mp->client_index;
2840  rp.client_pid = mp->pid;
2841 
2842  handle_client_registration (&rp, IDX_IP6_FIB_COUNTERS, fib,
2843  mp->enable_disable);
2844 
2845 reply:
2847  if (!reg)
2848  {
2849  sm->enable_poller = clear_client_for_stat (IDX_IP6_FIB_COUNTERS,
2850  fib, mp->client_index);
2851  return;
2852  }
2853 
2854  rmp = vl_msg_api_alloc (sizeof (*rmp));
2855  rmp->_vl_msg_id = ntohs (VL_API_WANT_IP6_FIB_STATS_REPLY);
2856  rmp->context = mp->context;
2857  rmp->retval = retval;
2858 
2859  vl_api_send_msg (reg, (u8 *) rmp);
2860 }
2861 
2862 static void
2864 {
2865  stats_main_t *sm = &stats_main;
2867  vl_api_want_ip4_mfib_stats_reply_t *rmp;
2868  uword *p;
2869  i32 retval = 0;
2870  vl_api_registration_t *reg;
2871  u32 mfib;
2872 
2873  mfib = ~0; //Using same mechanism as _per_interface_
2874  rp.client_index = mp->client_index;
2875  rp.client_pid = mp->pid;
2876 
2877  handle_client_registration (&rp, IDX_IP6_MFIB_COUNTERS, mfib,
2878  mp->enable_disable);
2879 
2880 reply:
2882  if (!reg)
2883  {
2884  sm->enable_poller = clear_client_for_stat (IDX_IP6_MFIB_COUNTERS,
2885  mfib, mp->client_index);
2886  return;
2887  }
2888 
2889  rmp = vl_msg_api_alloc (sizeof (*rmp));
2890  rmp->_vl_msg_id = ntohs (VL_API_WANT_IP6_MFIB_STATS_REPLY);
2891  rmp->context = mp->context;
2892  rmp->retval = retval;
2893 
2894  vl_api_send_msg (reg, (u8 *) rmp);
2895 }
2896 
2897 /* FIXME - NBR stats broken - this will be fixed in subsequent patch */
2898 static void
2900 {
2901 }
2902 
2903 static void
2905 {
2906 }
2907 
2908 static void
2910 {
2911  stats_main_t *sm = &stats_main;
2915  vlib_counter_t v;
2916  int i, which;
2917  u64 total_pkts[VLIB_N_RX_TX];
2918  u64 total_bytes[VLIB_N_RX_TX];
2919  vl_api_registration_t *reg;
2920 
2922  if (!reg)
2923  return;
2924 
2925  rmp = vl_msg_api_alloc (sizeof (*rmp));
2926  rmp->_vl_msg_id = ntohs (VL_API_VNET_GET_SUMMARY_STATS_REPLY);
2927  rmp->context = mp->context;
2928  rmp->retval = 0;
2929 
2930  memset (total_pkts, 0, sizeof (total_pkts));
2931  memset (total_bytes, 0, sizeof (total_bytes));
2932 
2934 
2936  {
2937  which = cm - im->combined_sw_if_counters;
2938 
2939  for (i = 0; i < vlib_combined_counter_n_counters (cm); i++)
2940  {
2941  vlib_get_combined_counter (cm, i, &v);
2942  total_pkts[which] += v.packets;
2943  total_bytes[which] += v.bytes;
2944  }
2945  }
2947 
2948  rmp->total_pkts[VLIB_RX] = clib_host_to_net_u64 (total_pkts[VLIB_RX]);
2949  rmp->total_bytes[VLIB_RX] = clib_host_to_net_u64 (total_bytes[VLIB_RX]);
2950  rmp->total_pkts[VLIB_TX] = clib_host_to_net_u64 (total_pkts[VLIB_TX]);
2951  rmp->total_bytes[VLIB_TX] = clib_host_to_net_u64 (total_bytes[VLIB_TX]);
2952  rmp->vector_rate =
2953  clib_host_to_net_u64 (vlib_last_vector_length_per_node (sm->vlib_main));
2954 
2955  vl_api_send_msg (reg, (u8 *) rmp);
2956 }
2957 
2958 int
2960 {
2962  stats_main_t *sm = &stats_main;
2963  uword *p;
2964 
2965  // FIXME
2966  /* p = hash_get (sm->stats_registration_hash, client_index); */
2967  /* if (p) */
2968  /* { */
2969  /* rp = pool_elt_at_index (sm->stats_registrations, p[0]); */
2970  /* pool_put (sm->stats_registrations, rp); */
2971  /* hash_unset (sm->stats_registration_hash, client_index); */
2972  /* } */
2973 
2974  return 0;
2975 }
2976 
2977 #define vl_api_vnet_interface_simple_counters_t_endian vl_noop_handler
2978 #define vl_api_vnet_interface_simple_counters_t_print vl_noop_handler
2979 #define vl_api_vnet_interface_combined_counters_t_endian vl_noop_handler
2980 #define vl_api_vnet_interface_combined_counters_t_print vl_noop_handler
2981 #define vl_api_vnet_ip4_fib_counters_t_endian vl_noop_handler
2982 #define vl_api_vnet_ip4_fib_counters_t_print vl_noop_handler
2983 #define vl_api_vnet_ip6_fib_counters_t_endian vl_noop_handler
2984 #define vl_api_vnet_ip6_fib_counters_t_print vl_noop_handler
2985 #define vl_api_vnet_ip4_nbr_counters_t_endian vl_noop_handler
2986 #define vl_api_vnet_ip4_nbr_counters_t_print vl_noop_handler
2987 #define vl_api_vnet_ip6_nbr_counters_t_endian vl_noop_handler
2988 #define vl_api_vnet_ip6_nbr_counters_t_print vl_noop_handler
2989 
2990 static clib_error_t *
2992 {
2993  stats_main_t *sm = &stats_main;
2994  api_main_t *am = &api_main;
2995  void *vlib_worker_thread_bootstrap_fn (void *arg);
2996 
2997  sm->vlib_main = vm;
2998  sm->vnet_main = vnet_get_main ();
3000  sm->api_main = am;
3002  sm->data_structure_lock =
3005  memset (sm->data_structure_lock, 0, sizeof (*sm->data_structure_lock));
3006 
3007 #define _(N,n) \
3008  vl_msg_api_set_handlers(VL_API_##N, #n, \
3009  vl_api_##n##_t_handler, \
3010  vl_noop_handler, \
3011  vl_api_##n##_t_endian, \
3012  vl_api_##n##_t_print, \
3013  sizeof(vl_api_##n##_t), 0 /* do NOT trace! */);
3015 #undef _
3016 
3017  /* tell the msg infra not to free these messages... */
3018  am->message_bounce[VL_API_VNET_INTERFACE_SIMPLE_COUNTERS] = 1;
3019  am->message_bounce[VL_API_VNET_INTERFACE_COMBINED_COUNTERS] = 1;
3020  am->message_bounce[VL_API_VNET_IP4_FIB_COUNTERS] = 1;
3021  am->message_bounce[VL_API_VNET_IP6_FIB_COUNTERS] = 1;
3022  am->message_bounce[VL_API_VNET_IP4_NBR_COUNTERS] = 1;
3023  am->message_bounce[VL_API_VNET_IP6_NBR_COUNTERS] = 1;
3024 
3025  /*
3026  * Set up the (msg_name, crc, message-id) table
3027  */
3029 
3032 #define stats_reg(n) \
3033  sm->stats_registrations[IDX_##n] = 0; \
3034  sm->stats_registration_hash[IDX_##n] = 0;
3035 #include <vpp/stats/stats.reg>
3036 #undef stats_reg
3037 
3038  return 0;
3039 }
3040 
3042 
3043 /* *INDENT-OFF* */
3044 VLIB_REGISTER_THREAD (stats_thread_reg, static) = {
3045  .name = "stats",
3046  .function = stats_thread_fn,
3047  .fixed_count = 1,
3048  .count = 1,
3049  .no_data_structure_clone = 1,
3050  .use_pthreads = 1,
3051 };
3052 /* *INDENT-ON* */
3053 
3054 /*
3055  * fd.io coding-style-patch-verification: ON
3056  *
3057  * Local Variables:
3058  * eval: (c-set-style "gnu")
3059  * End:
3060  */
#define IP4_MFIB_COUNTER_BATCH_SIZE
Definition: stats.c:88
static void vl_api_stats_get_poller_delay_t_handler(vl_api_stats_get_poller_delay_t *mp)
Definition: stats.c:2298
void udp_encap_walk(udp_encap_walk_cb_t cb, void *ctx)
Walk each of the encap objects.
Definition: udp_encap.c:595
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:434
static void vl_api_vnet_get_summary_stats_t_handler(vl_api_vnet_get_summary_stats_t *mp)
Definition: stats.c:2909
static void udp_encap_ship(udp_encap_stats_walk_t *ctx)
Definition: stats.c:2169
Want Interface Simple Stats, register for detailed interface stats.
Definition: stats.api:85
static void stats_thread_fn(void *arg)
Definition: stats.c:2318
static int set_client_for_stat(u32 reg, u32 item, vpe_client_registration_t *client)
Definition: stats.c:286
#define vec_foreach_index(var, v)
Iterate over vector indices.
vpe_client_registration_t ** clients_tmp
Definition: stats.h:158
Want Stats, enable/disable ALL stats updates.
Definition: stats.api:69
vlib_combined_counter_main_t lbm_to_counters
Definition: load_balance.h:46
ip46_address_t fp_src_addr
Definition: mfib_types.h:47
#define hash_set(h, key, value)
Definition: hash.h:254
fib_node_index_t mfib_table_lookup(u32 fib_index, const mfib_prefix_t *prefix)
Perfom a longest prefix match in the non-forwarding table.
Definition: mfib_table.c:65
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
do_ip46_fibs_t do_ip46_fibs
Definition: stats.h:151
#define clib_min(x, y)
Definition: clib.h:340
vl_api_vlib_counter_t data[count]
Definition: stats.api:366
The UDP encap represenation.
Definition: udp_encap.h:46
int svm_queue_is_full(svm_queue_t *q)
Definition: queue.c:115
vl_api_vnet_combined_counter_t data[count]
Definition: stats.api:391
vpe_client_registration_t * clients
Definition: stats.h:93
#define hash_unset(h, key)
Definition: hash.h:260
a
Definition: bitmap.h:516
vl_api_vnet_simple_counter_t data[count]
Definition: stats.api:379
vl_api_ip6_mfib_counter_t c[count]
Definition: stats.api:316
static adj_walk_rc_t ip6_nbr_stats_cb(adj_index_t ai, void *arg)
Definition: stats.c:1353
hash_pair_t ** pvec
Definition: stats.h:68
vnet_main_t * vnet_get_main(void)
Definition: misc.c:47
mfib_table_t ** mfibs
Definition: stats.h:67
static void vl_api_want_interface_simple_stats_t_handler(vl_api_want_interface_simple_stats_t *mp)
Definition: stats.c:2719
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:2379
u64 as_u64[2]
Definition: ip6_packet.h:51
#define NULL
Definition: clib.h:55
An entry in a FIB table.
Definition: mfib_entry.h:31
Request for a single block of summary stats.
Definition: stats.api:398
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:227
IP unicast adjacency.
Definition: adj.h:175
static void vl_api_send_msg(vl_api_registration_t *rp, u8 *elem)
Definition: api.h:34
const dpo_id_t * fib_entry_contribute_ip_forwarding(fib_node_index_t fib_entry_index)
Definition: fib_entry.c:478
u8 * message_bounce
Don&#39;t automatically free message buffer vetor.
Definition: api_common.h:219
u32 enable_poller
Definition: stats.h:106
u32 sw_if_index
The SW IF index all these adjs belong to.
Definition: stats.c:1344
vlib_main_t * vlib_main
Definition: stats.h:161
u32 index_t
A Data-Path Object is an object that represents actions that are applied to packets are they are swit...
Definition: dpo.h:41
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:520
struct ip_adjacency_t_::@43::@44 nbr
IP_LOOKUP_NEXT_ARP/IP_LOOKUP_NEXT_REWRITE.
VL_MSG_API_REAPER_FUNCTION(want_stats_reaper)
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:559
struct udp_encap_stats_walk_t_ udp_encap_stats_walk_t
int i
vl_api_ip4_nbr_counter_t c[count]
Definition: stats.api:285
VLIB_REGISTER_THREAD(stats_thread_reg, static)
Want UDP encap Stats, register for continuous stats.
Definition: stats.api:448
void clib_longjmp(clib_longjmp_t *save, uword return_value)
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:419
static void ip46_fib_stats_delay(stats_main_t *sm, u32 sec, u32 nsec)
Definition: stats.c:1165
void handle_client_registration(vpe_client_registration_t *client, u32 stat, u32 item, int enable_disable)
Definition: stats.c:560
Combined stats counters structure.
Definition: stats.api:361
#define MIN(x, y)
Definition: stats.c:1378
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:227
uword clib_setjmp(clib_longjmp_t *save, uword return_value_not_taken)
void * vl_msg_api_alloc(int nbytes)
static void vl_api_vnet_ip4_fib_counters_t_handler(vl_api_vnet_ip4_fib_counters_t *mp)
Definition: stats.c:2434
static clib_error_t * stats_init(vlib_main_t *vm)
Definition: stats.c:2991
format_function_t format_vnet_sw_if_index_name
void svm_queue_unlock(svm_queue_t *q)
Definition: queue.c:109
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
uword value[0]
Definition: hash.h:164
union ip_adjacency_t_::@43 sub_type
vnet_link_t ia_link
link/ether-type 1 bytes
Definition: adj.h:196
static void do_ip6_nbr_counters(stats_main_t *sm)
Definition: stats.c:1440
u32 ue_id
The ID given by the user/client.
Definition: udp_encap.h:96
static void vl_api_vnet_ip4_nbr_counters_t_handler(vl_api_vnet_ip4_nbr_counters_t *mp)
Definition: stats.c:2484
static f64 vlib_last_vector_length_per_node(vlib_main_t *vm)
Definition: main.h:318
static clib_error_t * stats_config(vlib_main_t *vm, unformat_input_t *input)
Definition: stats.c:2261
#define IP6_MFIB_COUNTER_BATCH_SIZE
Definition: stats.c:89
static int vl_api_can_send_msg(vl_api_registration_t *rp)
Definition: api.h:47
volatile u32 release_hint
Definition: stats.h:34
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:376
Combined stats counters structure per interface.
Definition: stats.api:387
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:440
static void vl_api_want_ip4_mfib_stats_t_handler(vl_api_want_ip4_mfib_stats_t *mp)
Definition: stats.c:2793
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:111
vpe_client_stats_registration_t ** regs_tmp
Definition: stats.h:157
u64 stats[2]
Definition: stats.c:2144
fib_node_index_t mft_index
Index into FIB vector.
Definition: mfib_table.h:71
udp_encap_stat_t * stats
Definition: stats.c:2149
static void do_ip4_fib_counters(stats_main_t *sm)
Definition: stats.c:1492
vlib_combined_counter_main_t * combined_sw_if_counters
Definition: interface.h:718
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 hash_foreach(key_var, value_var, h, body)
Definition: hash.h:441
#define IP6_FIB_COUNTER_BATCH_SIZE
Definition: stats.c:87
#define clib_error_return(e, args...)
Definition: error.h:99
mfib_prefix_t mfe_prefix
The prefix of the route.
Definition: mfib_entry.h:40
unsigned long u64
Definition: types.h:89
struct vl_shmem_hdr_ * shmem_hdr
Binary API shared-memory segment header pointer.
Definition: api_common.h:262
volatile u32 lock
Definition: stats.h:33
struct mfib_table_t_ * mfibs
Vector of MFIBs.
Definition: ip4.h:106
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:1201
static void vl_api_want_ip6_mfib_stats_t_handler(vl_api_want_ip6_mfib_stats_t *mp)
Definition: stats.c:2863
int stats_set_poller_delay(u32 poller_delay_sec)
Definition: stats.c:2246
void vlib_set_thread_name(char *name)
Definition: threads.c:267
stats_main_t stats_main
Definition: stats.c:25
#define foreach_stats_msg
Definition: stats.c:48
static void vl_api_want_ip4_fib_stats_t_handler(vl_api_want_ip4_fib_stats_t *mp)
Definition: stats.c:2757
vl_shmem_hdr_t * shmem_hdr
static heap_elt_t * first(heap_header_t *h)
Definition: heap.c:59
The identity of a DPO is a combination of its type and its instance number/index of objects of that t...
Definition: dpo.h:168
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:1197
#define hash_get(h, key)
Definition: hash.h:248
Want Per Interface simple Stats, register for continuous stats.
Definition: stats.api:101
static void vl_api_want_per_interface_combined_stats_t_handler(vl_api_want_per_interface_combined_stats_t *mp)
Definition: stats.c:743
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:461
u32 size
ip6_route_t * ip6routes
Definition: stats.h:64
u32 ** enable_all_client_reg(u32 **registrations)
Definition: stats.c:490
counter_t packets
packet counter
Definition: counter.h:141
static void vl_api_want_ip6_fib_stats_t_handler(vl_api_want_ip6_fib_stats_t *mp)
Definition: stats.c:2828
void svm_queue_lock(svm_queue_t *q)
Definition: queue.c:103
static void vl_api_want_ip4_nbr_stats_t_handler(vl_api_want_ip4_nbr_stats_t *mp)
Definition: stats.c:2899
#define v
Definition: acl.c:495
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
struct _unformat_input_t unformat_input_t
static void vl_api_want_ip6_nbr_stats_t_handler(vl_api_want_ip6_nbr_stats_t *mp)
Definition: stats.c:2904
#define hash_free(h)
Definition: hash.h:309
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:273
static void vl_api_want_udp_encap_stats_t_handler(vl_api_want_udp_encap_stats_t *mp)
Definition: stats.c:2637
Stat for one UDP encap object.
Definition: stats.api:461
vlib_combined_counter_main_t repm_counters
Definition: replicate_dpo.h:35
#define PREDICT_FALSE(x)
Definition: clib.h:105
#define VLIB_CONFIG_FUNCTION(x, n,...)
Definition: init.h:119
vlib_simple_counter_main_t * sw_if_counters
Definition: interface.h:717
load_balance_main_t load_balance_main
The one instance of load-balance main.
Definition: load_balance.c:56
static u8 * format_vnet_api_errno(u8 *s, va_list *args)
Definition: api_errno.h:157
static void ip4_nbr_ship(stats_main_t *sm, ip4_nbr_stats_ctx_t *ctx)
Definition: stats.c:1227
#define SIMPLE_COUNTER_BATCH_SIZE
Definition: stats.c:84
ip4_route_t * ip4routes
Definition: stats.h:63
#define COMBINED_COUNTER_BATCH_SIZE
Definition: stats.c:85
vl_api_ip6_nbr_counter_t * counters
A vector of ip6 nbr counters.
Definition: stats.c:1349
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:506
static mfib_entry_t * mfib_entry_get(fib_node_index_t index)
Definition: mfib_entry.h:153
u32 index
Definition: stats.h:58
word fformat(FILE *f, char *fmt,...)
Definition: format.c:453
The context passed when collecting adjacency counters.
Definition: stats.c:1187
API main structure, used by both vpp and binary API clients.
Definition: api_common.h:199
int clear_client_for_stat(u32 reg, u32 item, u32 client_index)
Definition: stats.c:353
#define pool_free(p)
Free a pool.
Definition: pool.h:354
An API client registration, only in vpp/vlib.
Definition: api_common.h:44
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
u8 * format_vnet_interface_combined_counters(u8 *s, va_list *args)
Definition: stats.c:97
u32 sw_if_index
The SW IF index all these adjs belong to.
Definition: stats.c:1192
fib_node_index_t ft_index
Index into FIB vector.
Definition: fib_table.h:94
void mfib_table_walk(u32 fib_index, fib_protocol_t proto, mfib_table_walk_fn_t fn, void *ctx)
Walk all entries in a FIB table N.B: This is NOT safe to deletes.
Definition: mfib_table.c:599
static void add_routes_in_fib(BVT(clib_bihash_kv)*kvp, void *arg)
Definition: stats.c:1970
stats_main_t * sm
Definition: stats.c:1966
void vl_msg_api_send_shmem(svm_queue_t *q, u8 *elem)
static vpe_client_registration_t * get_client_for_stat(u32 reg, u32 item, u32 client_index)
Definition: stats.c:262
#define UNFORMAT_END_OF_INPUT
Definition: format.h:143
svmdb_client_t * c
static_always_inline uword vlib_get_thread_index(void)
Definition: threads.h:221
u32 ft_table_id
Table ID (hash key) for this FIB.
Definition: fib_table.h:89
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:294
uword * results
Definition: stats.h:69
static void do_udp_encap_counters(stats_main_t *sm)
Definition: stats.c:2230
clib_longjmp_t jmp_buf
Definition: stats.h:148
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:336
#define IP4_FIB_COUNTER_BATCH_SIZE
Definition: stats.c:86
static void * clib_mem_set_heap(void *heap)
Definition: mem.h:226
Want Interface Combined Stats, register for continuous stats.
Definition: stats.api:121
#define clib_warning(format, args...)
Definition: error.h:59
This table stores the routes that are used to forward traffic.
Definition: ip6.h:128
#define clib_memcpy(a, b, c)
Definition: string.h:75
static void vnet_interface_counter_unlock(vnet_interface_main_t *im)
Definition: interface.h:743
u32 fib_node_index_t
A typedef of a node index.
Definition: fib_types.h:30
static void vl_api_vnet_ip6_fib_counters_t_handler(vl_api_vnet_ip6_fib_counters_t *mp)
Definition: stats.c:2535
#define pool_is_free_index(P, I)
Use free bitmap to query whether given index is free.
Definition: pool.h:270
Want IP6 FIB Stats, register for continuous stats.
Definition: stats.api:168
api_main_t * api_main
Definition: stats.h:164
u32 adj_index_t
An index for adjacencies.
Definition: adj_types.h:30
#define ARRAY_LEN(x)
Definition: clib.h:59
static vl_api_registration_t * vl_api_client_index_to_registration(u32 index)
Definition: api.h:56
vl_api_ip6_fib_counter_t c[count]
Definition: stats.api:300
Simple per interface stats counters structure.
Definition: stats.api:375
svm_queue_t * vl_input_queue
Definition: memory_shared.h:84
Aggregrate type for a prefix.
Definition: mfib_types.h:24
static void clear_one_client(u32 reg_index, u32 reg, u32 item, u32 client_index)
Definition: stats.c:325
static void vnet_interface_counter_lock(vnet_interface_main_t *im)
Definition: interface.h:735
struct ip6_nbr_stats_ctx_t_ ip6_nbr_stats_ctx_t
The context passed when collecting adjacency counters.
#define ASSERT(truth)
void stats_dslock_with_hint(int hint, int tag)
Definition: stats.c:227
unsigned int u32
Definition: types.h:88
ip6_main_t ip6_main
Definition: ip6_forward.c:2750
static void ip6_nbr_ship(stats_main_t *sm, ip6_nbr_stats_ctx_t *ctx)
Definition: stats.c:1381
long ctx[MAX_CONNS]
Definition: main.c:126
#define STATS_RELEASE_DELAY_NS
Definition: stats.c:93
The context passed when collecting adjacency counters.
Definition: stats.c:1339
static void setup_message_id_table(api_main_t *am)
Definition: stats.c:75
uword ** stats_registration_hash
Definition: stats.h:141
#define UDP_ENCAP_COUNTER_BATCH_SIZE
Definition: stats.c:90
IPv4 main type.
Definition: ip4.h:95
const dpo_id_t * mfib_entry_contribute_ip_forwarding(fib_node_index_t mfib_entry_index)
Definition: mfib_entry.c:1230
int stats_memclnt_delete_callback(u32 client_index)
Definition: stats.c:2959
static void do_combined_interface_counters(stats_main_t *sm)
Definition: stats.c:685
vpe_client_stats_registration_t ** stats_registrations
Definition: stats.h:142
struct mfib_table_t_ * mfibs
Vector of MFIBs.
Definition: ip6.h:170
Combined interface counter data type for vnet_interface_combined_counters.
Definition: interface.api:257
fib_table_t ** fibs
Definition: stats.h:66
size_t count
Definition: vapi.c:42
u64 counter_t
64bit counters
Definition: counter.h:54
u32 mft_table_id
Table ID (hash key) for this FIB.
Definition: mfib_table.h:66
Simple stats counters structure.
Definition: stats.api:344
vl_api_udp_encap_counter_t c[count]
Definition: stats.api:472
Want IP6 NBR Stats, register for continuous stats.
Definition: stats.api:224
static int udp_encap_stats_walk_cb(index_t uei, void *arg)
Definition: stats.c:2153
void udp_encap_get_stats(index_t uei, u64 *packets, u64 *bytes)
Definition: udp_encap.c:312
u32 stats_poll_interval_in_seconds
Definition: stats.h:105
ip6_fib_table_instance_t ip6_table[IP6_FIB_NUM_TABLES]
The two FIB tables; fwding and non-fwding.
Definition: ip6.h:159
Get delay between polling statistics.
Definition: stats.api:424
void vl_msg_api_free(void *)
u64 uword
Definition: types.h:112
vl_api_ip4_fib_counter_t c[count]
Definition: stats.api:244
counter_t bytes
byte counter
Definition: counter.h:142
Want IP4 FIB Stats, register for continuous stats.
Definition: stats.api:154
data_structure_lock_t * data_structure_lock
Definition: stats.h:145
Definition: defs.h:47
u32 ** init_client_reg(u32 **registrations)
Definition: stats.c:464
struct udp_encap_stat_t_ udp_encap_stat_t
Per-neighbour (i.e.
Definition: stats.api:280
index_t dpoi_index
the index of objects of that type
Definition: dpo.h:184
Want IP6 multicast FIB Stats, register for continuous stats.
Definition: stats.api:196
#define FIB_NODE_INDEX_INVALID
Definition: fib_types.h:31
struct ip4_fib_t_ * v4_fibs
Vector of MTries.
Definition: ip4.h:103
u8 * format_vnet_interface_simple_counters(u8 *s, va_list *args)
Definition: stats.c:144
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
vpe_client_registration_t * get_clients_for_stat(u32 reg, u32 item)
Definition: stats.c:422
vnet_interface_main_t * interface_main
Definition: stats.h:163
unsigned char u8
Definition: types.h:56
static void vl_api_want_stats_t_handler(vl_api_want_stats_t *mp)
Definition: stats.c:2672
#define hash_foreach_pair(p, v, body)
Iterate over hash pairs.
Definition: hash.h:372
static void clear_client_reg(u32 **registrations)
Definition: stats.c:451
static void do_ip4_mfib_counters(stats_main_t *sm)
Definition: stats.c:1685
static int clear_client_for_all_stats(u32 client_index)
Definition: stats.c:380
vnet_sw_interface_t * sw_interfaces
Definition: interface.h:709
static int mfib_table_stats_walk_cb(fib_node_index_t fei, void *ctx)
Definition: stats.c:1670
#define clib_unix_warning(format, args...)
Definition: error.h:68
u32 address_length
Definition: stats.h:57
replicate_main_t replicate_main
The one instance of replicate main.
Definition: replicate_dpo.c:62
A collection of combined counters.
Definition: counter.h:180
Want Per Interface Combined Stats, register for continuous stats.
Definition: stats.api:137
uword * fib_entry_by_dst_address[33]
Definition: ip4_fib.h:48
struct _svm_queue svm_queue_t
#define clib_mem_unaligned(pointer, type)
Definition: types.h:155
vl_api_ip4_mfib_counter_t c[count]
Definition: stats.api:260
static void vl_api_vnet_ip6_nbr_counters_t_handler(vl_api_vnet_ip6_nbr_counters_t *mp)
Definition: stats.c:2586
static void * clib_mem_alloc_aligned(uword size, uword align)
Definition: mem.h:120
static void do_ip6_fib_counters(stats_main_t *sm)
Definition: stats.c:1991
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
static void do_simple_per_interface_counters(stats_main_t *sm)
Definition: stats.c:1011
A protocol Independent IP multicast FIB table.
Definition: mfib_table.h:35
ip4_main_t ip4_main
Global ip4 main structure.
Definition: ip4_forward.c:818
static vlib_thread_main_t * vlib_get_thread_main()
Definition: global_funcs.h:32
static void do_ip6_mfib_counters(stats_main_t *sm)
Definition: stats.c:1824
Reply for vnet_get_summary_stats request.
Definition: stats.api:411
ip6_route_t ** routep
Definition: stats.c:1965
struct fib_table_t_ * fibs
Vector of FIBs.
Definition: ip4.h:100
Get delay between polling statistics reply.
Definition: stats.api:435
#define vec_foreach(var, vec)
Vector iterator.
Want IP4 NBR Stats, register for continuous stats.
Definition: stats.api:210
static void vl_api_want_interface_combined_stats_t_handler(vl_api_want_interface_combined_stats_t *mp)
Definition: stats.c:601
void * vlib_worker_thread_bootstrap_fn(void *arg)
Definition: threads.c:670
#define CLIB_MEMORY_BARRIER()
Definition: clib.h:109
static void do_combined_per_interface_counters(stats_main_t *sm)
Definition: stats.c:811
static void vl_api_vnet_interface_combined_counters_t_handler(vl_api_vnet_interface_combined_counters_t *mp)
Definition: stats.c:638
void * vl_msg_api_alloc_as_if_client(int nbytes)
vhost_vring_addr_t addr
Definition: vhost-user.h:83
void stats_dsunlock(int hint, int tag)
Definition: stats.c:255
u16 fp_len
The mask length.
Definition: mfib_types.h:28
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:59
vnet_main_t * vnet_main
Definition: stats.h:162
static clib_error_t * want_stats_reaper(u32 client_index)
Definition: stats.c:406
api_main_t api_main
Definition: api_shared.c:35
struct fib_table_t_ * fibs
Definition: ip6.h:164
void vl_msg_api_send_shmem_nolock(svm_queue_t *q, u8 *elem)
static void vl_api_want_per_interface_simple_stats_t_handler(vl_api_want_per_interface_simple_stats_t *mp)
Definition: stats.c:945
static void dsunlock(stats_main_t *sm)
Definition: stats.c:234
static void do_ip4_nbr_counters(stats_main_t *sm)
Definition: stats.c:1285
static void dslock(stats_main_t *sm, int release_hint, int tag)
Definition: stats.c:201
uword key
Definition: hash.h:161
Simple interface counter data type for vnet_interface_simple_counters.
Definition: interface.api:291
static udp_encap_t * udp_encap_get(index_t uei)
Definition: udp_encap.h:147
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:972
vl_api_ip6_nbr_counter_t c[count]
Definition: stats.api:332
Definition: defs.h:46
Want IP4 muilticast FIB Stats, register for continuous stats.
Definition: stats.api:182
ip46_address_t fp_grp_addr
The address type is not deriveable from the fp_addr member.
Definition: mfib_types.h:46
mfib_prefix_t * mroutes
Definition: stats.h:65
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:169
A protocol Independent FIB table.
Definition: fib_table.h:69
ip6_address_t address
Definition: stats.h:56
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:128