FD.io VPP  v17.01.1-3-gc6833f8
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 <stats/stats.h>
16 #include <signal.h>
17 #include <vlib/threads.h>
18 #include <vnet/fib/fib_entry.h>
19 #include <vnet/fib/fib_table.h>
20 #include <vnet/dpo/load_balance.h>
21 
22 #define STATS_DEBUG 0
23 
25 
26 #include <vnet/ip/ip.h>
27 
28 #include <vpp-api/vpe_msg_enum.h>
29 
30 #define f64_endian(a)
31 #define f64_print(a,b)
32 
33 #define vl_typedefs /* define message structures */
34 #include <vpp-api/vpe_all_api_h.h>
35 #undef vl_typedefs
36 
37 #define vl_endianfun /* define message structures */
38 #include <vpp-api/vpe_all_api_h.h>
39 #undef vl_endianfun
40 
41 /* instantiate all the print functions we know about */
42 #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
43 #define vl_printfun
44 #include <vpp-api/vpe_all_api_h.h>
45 #undef vl_printfun
46 
47 #define foreach_stats_msg \
48 _(WANT_STATS, want_stats) \
49 _(WANT_STATS_REPLY, want_stats_reply) \
50 _(VNET_INTERFACE_COUNTERS, vnet_interface_counters) \
51 _(VNET_IP4_FIB_COUNTERS, vnet_ip4_fib_counters) \
52 _(VNET_IP6_FIB_COUNTERS, vnet_ip6_fib_counters)
53 
54 /* These constants ensure msg sizes <= 1024, aka ring allocation */
55 #define SIMPLE_COUNTER_BATCH_SIZE 126
56 #define COMBINED_COUNTER_BATCH_SIZE 63
57 #define IP4_FIB_COUNTER_BATCH_SIZE 48
58 #define IP6_FIB_COUNTER_BATCH_SIZE 30
59 
60 /* 5ms */
61 #define STATS_RELEASE_DELAY_NS (1000 * 1000 * 5)
62 /* ns/us us/ms */
63 
64 void
65 dslock (stats_main_t * sm, int release_hint, int tag)
66 {
67  u32 thread_id;
69 
70  if (PREDICT_FALSE (l == 0))
71  return;
72 
73  thread_id = os_get_cpu_number ();
74  if (l->lock && l->thread_id == thread_id)
75  {
76  l->count++;
77  return;
78  }
79 
80  if (release_hint)
81  l->release_hint++;
82 
83  while (__sync_lock_test_and_set (&l->lock, 1))
84  /* zzzz */ ;
85  l->tag = tag;
86  l->thread_id = thread_id;
87  l->count = 1;
88 }
89 
90 void
91 stats_dslock_with_hint (int hint, int tag)
92 {
93  stats_main_t *sm = &stats_main;
94  dslock (sm, hint, tag);
95 }
96 
97 void
99 {
100  u32 thread_id;
102 
103  if (PREDICT_FALSE (l == 0))
104  return;
105 
106  thread_id = os_get_cpu_number ();
107  ASSERT (l->lock && l->thread_id == thread_id);
108  l->count--;
109  if (l->count == 0)
110  {
111  l->tag = -l->tag;
112  l->release_hint = 0;
114  l->lock = 0;
115  }
116 }
117 
118 void
119 stats_dsunlock (int hint, int tag)
120 {
121  stats_main_t *sm = &stats_main;
122  dsunlock (sm);
123 }
124 
125 static void
127 {
130  api_main_t *am = sm->api_main;
134  u32 items_this_message = 0;
135  u64 v, *vp = 0;
136  int i;
137 
138  /*
139  * Prevent interface registration from expanding / moving the vectors...
140  * That tends never to happen, so we can hold this lock for a while.
141  */
143 
144  vec_foreach (cm, im->sw_if_counters)
145  {
146 
147  for (i = 0; i < vec_len (cm->maxi); i++)
148  {
149  if (mp == 0)
150  {
151  items_this_message = clib_min (SIMPLE_COUNTER_BATCH_SIZE,
152  vec_len (cm->maxi) - i);
153 
155  (sizeof (*mp) + items_this_message * sizeof (v));
156  mp->_vl_msg_id = ntohs (VL_API_VNET_INTERFACE_COUNTERS);
157  mp->vnet_counter_type = cm - im->sw_if_counters;
158  mp->is_combined = 0;
159  mp->first_sw_if_index = htonl (i);
160  mp->count = 0;
161  vp = (u64 *) mp->data;
162  }
163  v = vlib_get_simple_counter (cm, i);
164  clib_mem_unaligned (vp, u64) = clib_host_to_net_u64 (v);
165  vp++;
166  mp->count++;
167  if (mp->count == items_this_message)
168  {
169  mp->count = htonl (items_this_message);
170  /* Send to the main thread... */
171  vl_msg_api_send_shmem (q, (u8 *) & mp);
172  mp = 0;
173  }
174  }
175  ASSERT (mp == 0);
176  }
178 }
179 
180 static void
182 {
185  api_main_t *am = sm->api_main;
189  u32 items_this_message = 0;
190  vlib_counter_t v, *vp = 0;
191  int i;
192 
194 
196  {
197 
198  for (i = 0; i < vec_len (cm->maxi); i++)
199  {
200  if (mp == 0)
201  {
202  items_this_message = clib_min (COMBINED_COUNTER_BATCH_SIZE,
203  vec_len (cm->maxi) - i);
204 
206  (sizeof (*mp) + items_this_message * sizeof (v));
207  mp->_vl_msg_id = ntohs (VL_API_VNET_INTERFACE_COUNTERS);
209  mp->is_combined = 1;
210  mp->first_sw_if_index = htonl (i);
211  mp->count = 0;
212  vp = (vlib_counter_t *) mp->data;
213  }
214  vlib_get_combined_counter (cm, i, &v);
216  = clib_host_to_net_u64 (v.packets);
217  clib_mem_unaligned (&vp->bytes, u64) = clib_host_to_net_u64 (v.bytes);
218  vp++;
219  mp->count++;
220  if (mp->count == items_this_message)
221  {
222  mp->count = htonl (items_this_message);
223  /* Send to the main thread... */
224  vl_msg_api_send_shmem (q, (u8 *) & mp);
225  mp = 0;
226  }
227  }
228  ASSERT (mp == 0);
229  }
231 }
232 
233 /* from .../vnet/vnet/ip/lookup.c. Yuck */
234 typedef CLIB_PACKED (struct
235  {
236  ip4_address_t address;
237 u32 address_length: 6;
238 u32 index: 26;
239  }) ip4_route_t;
240 
241 static void
242 ip46_fib_stats_delay (stats_main_t * sm, u32 sec, u32 nsec)
243 {
244  struct timespec _req, *req = &_req;
245  struct timespec _rem, *rem = &_rem;
246 
247  req->tv_sec = sec;
248  req->tv_nsec = nsec;
249  while (1)
250  {
251  if (nanosleep (req, rem) == 0)
252  break;
253  *req = *rem;
254  if (errno == EINTR)
255  continue;
256  clib_unix_warning ("nanosleep");
257  break;
258  }
259 }
260 
261 static void
263 {
264  ip4_main_t *im4 = &ip4_main;
265  api_main_t *am = sm->api_main;
268  static ip4_route_t *routes;
269  ip4_route_t *r;
270  fib_table_t *fib;
271  ip_lookup_main_t *lm = &im4->lookup_main;
272  static uword *results;
274  u32 items_this_message;
275  vl_api_ip4_fib_counter_t *ctrp = 0;
276  u32 start_at_fib_index = 0;
277  int i;
278 
279 again:
280  /* *INDENT-OFF* */
281  pool_foreach (fib, im4->fibs,
282  ({
283  /* We may have bailed out due to control-plane activity */
284  while ((fib - im4->fibs) < start_at_fib_index)
285  continue;
286 
287  if (mp == 0)
288  {
289  items_this_message = IP4_FIB_COUNTER_BATCH_SIZE;
290  mp = vl_msg_api_alloc_as_if_client
291  (sizeof (*mp) +
292  items_this_message * sizeof (vl_api_ip4_fib_counter_t));
293  mp->_vl_msg_id = ntohs (VL_API_VNET_IP4_FIB_COUNTERS);
294  mp->count = 0;
295  mp->vrf_id = ntohl (fib->ft_table_id);
296  ctrp = (vl_api_ip4_fib_counter_t *) mp->c;
297  }
298  else
299  {
300  /* happens if the last FIB was empty... */
301  ASSERT (mp->count == 0);
302  mp->vrf_id = ntohl (fib->ft_table_id);
303  }
304 
305  dslock (sm, 0 /* release hint */ , 1 /* tag */ );
306 
307  vec_reset_length (routes);
308  vec_reset_length (results);
309 
310  for (i = 0; i < ARRAY_LEN (fib->v4.fib_entry_by_dst_address); i++)
311  {
312  uword *hash = fib->v4.fib_entry_by_dst_address[i];
313  hash_pair_t *p;
314  ip4_route_t x;
315 
316  x.address_length = i;
317 
318  hash_foreach_pair (p, hash,
319  ({
320  x.address.data_u32 = p->key;
321  if (lm->fib_result_n_words > 1)
322  {
323  x.index = vec_len (results);
324  vec_add (results, p->value, lm->fib_result_n_words);
325  }
326  else
327  x.index = p->value[0];
328 
329  vec_add1 (routes, x);
331  {
332  start_at_fib_index = fib - im4->fibs;
333  dsunlock (sm);
334  ip46_fib_stats_delay (sm, 0 /* sec */,
335  STATS_RELEASE_DELAY_NS);
336  mp->count = 0;
337  ctrp = (vl_api_ip4_fib_counter_t *)mp->c;
338  goto again;
339  }
340  }));
341  }
342 
343  vec_foreach (r, routes)
344  {
346 
348  r->index, &c);
349  /*
350  * If it has actually
351  * seen at least one packet, send it.
352  */
353  if (c.packets > 0)
354  {
355 
356  /* already in net byte order */
357  ctrp->address = r->address.as_u32;
358  ctrp->address_length = r->address_length;
359  ctrp->packets = clib_host_to_net_u64 (c.packets);
360  ctrp->bytes = clib_host_to_net_u64 (c.bytes);
361  mp->count++;
362  ctrp++;
363 
364  if (mp->count == items_this_message)
365  {
366  mp->count = htonl (items_this_message);
367  /*
368  * If the main thread's input queue is stuffed,
369  * drop the data structure lock (which the main thread
370  * may want), and take a pause.
371  */
374  {
375  dsunlock (sm);
376  vl_msg_api_send_shmem_nolock (q, (u8 *) & mp);
378  mp = 0;
379  ip46_fib_stats_delay (sm, 0 /* sec */ ,
381  goto again;
382  }
383  vl_msg_api_send_shmem_nolock (q, (u8 *) & mp);
385 
386  items_this_message = IP4_FIB_COUNTER_BATCH_SIZE;
388  (sizeof (*mp) +
389  items_this_message * sizeof (vl_api_ip4_fib_counter_t));
390  mp->_vl_msg_id = ntohs (VL_API_VNET_IP4_FIB_COUNTERS);
391  mp->count = 0;
392  mp->vrf_id = ntohl (fib->ft_table_id);
393  ctrp = (vl_api_ip4_fib_counter_t *) mp->c;
394  }
395  } /* for each (mp or single) adj */
397  {
398  start_at_fib_index = fib - im4->fibs;
399  dsunlock (sm);
400  ip46_fib_stats_delay (sm, 0 /* sec */ , STATS_RELEASE_DELAY_NS);
401  mp->count = 0;
402  ctrp = (vl_api_ip4_fib_counter_t *) mp->c;
403  goto again;
404  }
405  } /* vec_foreach (routes) */
406 
407  dsunlock (sm);
408 
409  /* Flush any data from this fib */
410  if (mp->count)
411  {
412  mp->count = htonl (mp->count);
413  vl_msg_api_send_shmem (q, (u8 *) & mp);
414  mp = 0;
415  }
416  }));
417  /* *INDENT-ON* */
418 
419  /* If e.g. the last FIB had no reportable routes, free the buffer */
420  if (mp)
421  vl_msg_api_free (mp);
422 }
423 
424 typedef struct
425 {
429 } ip6_route_t;
430 
431 typedef struct
432 {
437 
438 static void
439 add_routes_in_fib (BVT (clib_bihash_kv) * kvp, void *arg)
440 {
441  add_routes_in_fib_arg_t *ap = arg;
442  stats_main_t *sm = ap->sm;
443 
445  clib_longjmp (&sm->jmp_buf, 1);
446 
447  if (kvp->key[2] >> 32 == ap->fib_index)
448  {
450  ip6_route_t *r;
451  addr = (ip6_address_t *) kvp;
452  vec_add2 (*ap->routep, r, 1);
453  r->address = addr[0];
454  r->address_length = kvp->key[2] & 0xFF;
455  r->index = kvp->value;
456  }
457 }
458 
459 static void
461 {
462  ip6_main_t *im6 = &ip6_main;
463  api_main_t *am = sm->api_main;
466  static ip6_route_t *routes;
467  ip6_route_t *r;
468  fib_table_t *fib;
469  static uword *results;
471  u32 items_this_message;
472  vl_api_ip6_fib_counter_t *ctrp = 0;
473  u32 start_at_fib_index = 0;
474  BVT (clib_bihash) * h = &im6->ip6_table[IP6_FIB_TABLE_FWDING].ip6_hash;
475  add_routes_in_fib_arg_t _a, *a = &_a;
476 
477 again:
478  /* *INDENT-OFF* */
479  pool_foreach (fib, im6->fibs,
480  ({
481  /* We may have bailed out due to control-plane activity */
482  while ((fib - im6->fibs) < start_at_fib_index)
483  continue;
484 
485  if (mp == 0)
486  {
487  items_this_message = IP6_FIB_COUNTER_BATCH_SIZE;
488  mp = vl_msg_api_alloc_as_if_client
489  (sizeof (*mp) +
490  items_this_message * sizeof (vl_api_ip6_fib_counter_t));
491  mp->_vl_msg_id = ntohs (VL_API_VNET_IP6_FIB_COUNTERS);
492  mp->count = 0;
493  mp->vrf_id = ntohl (fib->ft_table_id);
494  ctrp = (vl_api_ip6_fib_counter_t *) mp->c;
495  }
496 
497  dslock (sm, 0 /* release hint */ , 1 /* tag */ );
498 
499  vec_reset_length (routes);
500  vec_reset_length (results);
501 
502  a->fib_index = fib - im6->fibs;
503  a->routep = &routes;
504  a->sm = sm;
505 
506  if (clib_setjmp (&sm->jmp_buf, 0) == 0)
507  {
508  start_at_fib_index = fib - im6->fibs;
510  }
511  else
512  {
513  dsunlock (sm);
514  ip46_fib_stats_delay (sm, 0 /* sec */ ,
516  mp->count = 0;
517  ctrp = (vl_api_ip6_fib_counter_t *) mp->c;
518  goto again;
519  }
520 
521  vec_foreach (r, routes)
522  {
524 
526  r->index, &c);
527  /*
528  * If it has actually
529  * seen at least one packet, send it.
530  */
531  if (c.packets > 0)
532  {
533  /* already in net byte order */
534  ctrp->address[0] = r->address.as_u64[0];
535  ctrp->address[1] = r->address.as_u64[1];
536  ctrp->address_length = (u8) r->address_length;
537  ctrp->packets = clib_host_to_net_u64 (c.packets);
538  ctrp->bytes = clib_host_to_net_u64 (c.bytes);
539  mp->count++;
540  ctrp++;
541 
542  if (mp->count == items_this_message)
543  {
544  mp->count = htonl (items_this_message);
545  /*
546  * If the main thread's input queue is stuffed,
547  * drop the data structure lock (which the main thread
548  * may want), and take a pause.
549  */
552  {
553  dsunlock (sm);
554  vl_msg_api_send_shmem_nolock (q, (u8 *) & mp);
556  mp = 0;
557  ip46_fib_stats_delay (sm, 0 /* sec */ ,
559  goto again;
560  }
561  vl_msg_api_send_shmem_nolock (q, (u8 *) & mp);
563 
564  items_this_message = IP6_FIB_COUNTER_BATCH_SIZE;
566  (sizeof (*mp) +
567  items_this_message * sizeof (vl_api_ip6_fib_counter_t));
568  mp->_vl_msg_id = ntohs (VL_API_VNET_IP6_FIB_COUNTERS);
569  mp->count = 0;
570  mp->vrf_id = ntohl (fib->ft_table_id);
571  ctrp = (vl_api_ip6_fib_counter_t *) mp->c;
572  }
573  }
574 
576  {
577  start_at_fib_index = fib - im6->fibs;
578  dsunlock (sm);
579  ip46_fib_stats_delay (sm, 0 /* sec */ , STATS_RELEASE_DELAY_NS);
580  mp->count = 0;
581  ctrp = (vl_api_ip6_fib_counter_t *) mp->c;
582  goto again;
583  }
584  } /* vec_foreach (routes) */
585 
586  dsunlock (sm);
587 
588  /* Flush any data from this fib */
589  if (mp->count)
590  {
591  mp->count = htonl (mp->count);
592  vl_msg_api_send_shmem (q, (u8 *) & mp);
593  mp = 0;
594  }
595  }));
596  /* *INDENT-ON* */
597 
598  /* If e.g. the last FIB had no reportable routes, free the buffer */
599  if (mp)
600  vl_msg_api_free (mp);
601 }
602 
603 static void
604 stats_thread_fn (void *arg)
605 {
606  stats_main_t *sm = &stats_main;
609 
610  /* stats thread wants no signals. */
611  {
612  sigset_t s;
613  sigfillset (&s);
614  pthread_sigmask (SIG_SETMASK, &s, 0);
615  }
616 
617  if (vec_len (tm->thread_prefix))
618  vlib_set_thread_name ((char *)
619  format (0, "%v_stats%c", tm->thread_prefix, '\0'));
620 
622 
623  while (1)
624  {
625  /* 10 second poll interval */
626  ip46_fib_stats_delay (sm, 10 /* secs */ , 0 /* nsec */ );
627 
628  if (!(sm->enable_poller))
629  continue;
632  do_ip4_fibs (sm);
633  do_ip6_fibs (sm);
634  }
635 }
636 
637 static void
639  mp)
640 {
642  stats_main_t *sm = &stats_main;
643  unix_shared_memory_queue_t *q, *q_prev = NULL;
645  u32 mp_size;
646 
647 #if STATS_DEBUG > 0
648  char *counter_name;
649  u32 count, sw_if_index;
650  int i;
651 #endif
652 
653  mp_size = sizeof (*mp) + (ntohl (mp->count) *
654  (mp->is_combined ? sizeof (vlib_counter_t) :
655  sizeof (u64)));
656 
657  /* *INDENT-OFF* */
659  ({
660  q = vl_api_client_index_to_input_queue (reg->client_index);
661  if (q)
662  {
663  if (q_prev && (q_prev->cursize < q_prev->maxsize))
664  {
665  mp_copy = vl_msg_api_alloc_as_if_client(mp_size);
666  clib_memcpy(mp_copy, mp, mp_size);
667  vl_msg_api_send_shmem (q_prev, (u8 *)&mp);
668  mp = mp_copy;
669  }
670  q_prev = q;
671  }
672  }));
673  /* *INDENT-ON* */
674 
675 #if STATS_DEBUG > 0
676  count = ntohl (mp->count);
677  sw_if_index = ntohl (mp->first_sw_if_index);
678  if (mp->is_combined == 0)
679  {
680  u64 *vp, v;
681  vp = (u64 *) mp->data;
682 
683  switch (mp->vnet_counter_type)
684  {
686  counter_name = "drop";
687  break;
689  counter_name = "punt";
690  break;
692  counter_name = "ip4";
693  break;
695  counter_name = "ip6";
696  break;
698  counter_name = "rx-no-buff";
699  break;
701  , counter_name = "rx-miss";
702  break;
704  , counter_name = "rx-error (fifo-full)";
705  break;
707  , counter_name = "tx-error (fifo-full)";
708  break;
709  default:
710  counter_name = "bogus";
711  break;
712  }
713  for (i = 0; i < count; i++)
714  {
715  v = clib_mem_unaligned (vp, u64);
716  v = clib_net_to_host_u64 (v);
717  vp++;
718  fformat (stdout, "%U.%s %lld\n", format_vnet_sw_if_index_name,
719  sm->vnet_main, sw_if_index, counter_name, v);
720  sw_if_index++;
721  }
722  }
723  else
724  {
725  vlib_counter_t *vp;
726  u64 packets, bytes;
727  vp = (vlib_counter_t *) mp->data;
728 
729  switch (mp->vnet_counter_type)
730  {
732  counter_name = "rx";
733  break;
735  counter_name = "tx";
736  break;
737  default:
738  counter_name = "bogus";
739  break;
740  }
741  for (i = 0; i < count; i++)
742  {
743  packets = clib_mem_unaligned (&vp->packets, u64);
744  packets = clib_net_to_host_u64 (packets);
745  bytes = clib_mem_unaligned (&vp->bytes, u64);
746  bytes = clib_net_to_host_u64 (bytes);
747  vp++;
748  fformat (stdout, "%U.%s.packets %lld\n",
750  sm->vnet_main, sw_if_index, counter_name, packets);
751  fformat (stdout, "%U.%s.bytes %lld\n",
753  sm->vnet_main, sw_if_index, counter_name, bytes);
754  sw_if_index++;
755  }
756  }
757 #endif
758  if (q_prev && (q_prev->cursize < q_prev->maxsize))
759  {
760  vl_msg_api_send_shmem (q_prev, (u8 *) & mp);
761  }
762  else
763  {
764  vl_msg_api_free (mp);
765  }
766 }
767 
768 static void
770 {
772  stats_main_t *sm = &stats_main;
773  unix_shared_memory_queue_t *q, *q_prev = NULL;
775  u32 mp_size;
776 
777  mp_size = sizeof (*mp_copy) +
778  ntohl (mp->count) * sizeof (vl_api_ip4_fib_counter_t);
779 
780  /* *INDENT-OFF* */
782  ({
783  q = vl_api_client_index_to_input_queue (reg->client_index);
784  if (q)
785  {
786  if (q_prev && (q_prev->cursize < q_prev->maxsize))
787  {
788  mp_copy = vl_msg_api_alloc_as_if_client(mp_size);
789  clib_memcpy(mp_copy, mp, mp_size);
790  vl_msg_api_send_shmem (q_prev, (u8 *)&mp);
791  mp = mp_copy;
792  }
793  q_prev = q;
794  }
795  }));
796  /* *INDENT-ON* */
797  if (q_prev && (q_prev->cursize < q_prev->maxsize))
798  {
799  vl_msg_api_send_shmem (q_prev, (u8 *) & mp);
800  }
801  else
802  {
803  vl_msg_api_free (mp);
804  }
805 }
806 
807 static void
809 {
811  stats_main_t *sm = &stats_main;
812  unix_shared_memory_queue_t *q, *q_prev = NULL;
814  u32 mp_size;
815 
816  mp_size = sizeof (*mp_copy) +
817  ntohl (mp->count) * sizeof (vl_api_ip6_fib_counter_t);
818 
819  /* *INDENT-OFF* */
821  ({
822  q = vl_api_client_index_to_input_queue (reg->client_index);
823  if (q)
824  {
825  if (q_prev && (q_prev->cursize < q_prev->maxsize))
826  {
827  mp_copy = vl_msg_api_alloc_as_if_client(mp_size);
828  clib_memcpy(mp_copy, mp, mp_size);
829  vl_msg_api_send_shmem (q_prev, (u8 *)&mp);
830  mp = mp_copy;
831  }
832  q_prev = q;
833  }
834  }));
835  /* *INDENT-ON* */
836  if (q_prev && (q_prev->cursize < q_prev->maxsize))
837  {
838  vl_msg_api_send_shmem (q_prev, (u8 *) & mp);
839  }
840  else
841  {
842  vl_msg_api_free (mp);
843  }
844 }
845 
846 static void
848 {
849  clib_warning ("BUG");
850 }
851 
852 static void
854 {
855  stats_main_t *sm = &stats_main;
858  uword *p;
859  i32 retval = 0;
861 
863  if (p)
864  {
865  if (mp->enable_disable)
866  {
867  clib_warning ("pid %d: already enabled...", mp->pid);
868  retval = -2;
869  goto reply;
870  }
871  else
872  {
873  rp = pool_elt_at_index (sm->stats_registrations, p[0]);
874  pool_put (sm->stats_registrations, rp);
876  goto reply;
877  }
878  }
879  if (mp->enable_disable == 0)
880  {
881  clib_warning ("pid %d: already disabled...", mp->pid);
882  retval = -3;
883  goto reply;
884  }
885  pool_get (sm->stats_registrations, rp);
886  rp->client_index = mp->client_index;
887  rp->client_pid = mp->pid;
889  rp - sm->stats_registrations);
890 
891 reply:
892  if (pool_elts (sm->stats_registrations))
893  sm->enable_poller = 1;
894  else
895  sm->enable_poller = 0;
896 
898 
899  if (!q)
900  return;
901 
902  rmp = vl_msg_api_alloc (sizeof (*rmp));
903  rmp->_vl_msg_id = ntohs (VL_API_WANT_STATS_REPLY);
904  rmp->context = mp->context;
905  rmp->retval = retval;
906 
907  vl_msg_api_send_shmem (q, (u8 *) & rmp);
908 }
909 
910 int
912 {
914  stats_main_t *sm = &stats_main;
915  uword *p;
916 
917  p = hash_get (sm->stats_registration_hash, client_index);
918  if (p)
919  {
920  rp = pool_elt_at_index (sm->stats_registrations, p[0]);
921  pool_put (sm->stats_registrations, rp);
922  hash_unset (sm->stats_registration_hash, client_index);
923  }
924 
925  return 0;
926 }
927 
928 #define vl_api_vnet_ip4_fib_counters_t_endian vl_noop_handler
929 #define vl_api_vnet_ip4_fib_counters_t_print vl_noop_handler
930 #define vl_api_vnet_ip6_fib_counters_t_endian vl_noop_handler
931 #define vl_api_vnet_ip6_fib_counters_t_print vl_noop_handler
932 
933 static clib_error_t *
935 {
936  stats_main_t *sm = &stats_main;
937  api_main_t *am = &api_main;
938  void *vlib_worker_thread_bootstrap_fn (void *arg);
939 
940  sm->vlib_main = vm;
941  sm->vnet_main = vnet_get_main ();
943  sm->api_main = am;
945  sm->data_structure_lock =
948  memset (sm->data_structure_lock, 0, sizeof (*sm->data_structure_lock));
949 
950 #define _(N,n) \
951  vl_msg_api_set_handlers(VL_API_##N, #n, \
952  vl_api_##n##_t_handler, \
953  vl_noop_handler, \
954  vl_api_##n##_t_endian, \
955  vl_api_##n##_t_print, \
956  sizeof(vl_api_##n##_t), 0 /* do NOT trace! */);
958 #undef _
959 
960  /* tell the msg infra not to free these messages... */
961  am->message_bounce[VL_API_VNET_INTERFACE_COUNTERS] = 1;
962  am->message_bounce[VL_API_VNET_IP4_FIB_COUNTERS] = 1;
963  am->message_bounce[VL_API_VNET_IP6_FIB_COUNTERS] = 1;
964 
965  return 0;
966 }
967 
969 
970 /* *INDENT-OFF* */
971 VLIB_REGISTER_THREAD (stats_thread_reg, static) = {
972  .name = "stats",
973  .function = stats_thread_fn,
974  .fixed_count = 1,
975  .count = 1,
976  .no_data_structure_clone = 1,
977  .use_pthreads = 1,
978 };
979 /* *INDENT-ON* */
980 
981 /*
982  * fd.io coding-style-patch-verification: ON
983  *
984  * Local Variables:
985  * eval: (c-set-style "gnu")
986  * End:
987  */
static void stats_thread_fn(void *arg)
Definition: stats.c:604
Want Stats, register for stats updates.
Definition: vpe.api:407
vlib_combined_counter_main_t lbm_to_counters
Definition: load_balance.h:45
u64 packets
packet counter
Definition: counter.h:166
#define hash_set(h, key, value)
Definition: hash.h:254
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:343
#define clib_min(x, y)
Definition: clib.h:326
u64 * maxi
Shared wide counters.
Definition: counter.h:62
#define hash_unset(h, key)
Definition: hash.h:260
a
Definition: bitmap.h:516
int unix_shared_memory_queue_is_full(unix_shared_memory_queue_t *q)
void vl_msg_api_send_shmem(unix_shared_memory_queue_t *q, u8 *elem)
vnet_interface_main_t interface_main
Definition: vnet.h:57
Reply for Want Stats request.
Definition: vpe.api:419
u64 as_u64[2]
Definition: ip6_packet.h:51
unix_shared_memory_queue_t * vl_input_queue
Definition: api.h:73
#define NULL
Definition: clib.h:55
vlib_counter_t * maxi
Shared wide counter pairs.
Definition: counter.h:215
u8 * message_bounce
Definition: api.h:123
u32 enable_poller
Definition: stats.h:45
vlib_main_t * vlib_main
Definition: stats.h:57
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:482
unix_shared_memory_queue_t * vl_api_client_index_to_input_queue(u32 index)
Combined counter to hold both packets and byte differences.
Definition: counter.h:164
#define vec_add2(V, P, N)
Add N elements to end of vector V, return pointer to new elements in P.
Definition: vec.h:521
VLIB_REGISTER_THREAD(stats_thread_reg, static)
ip_lookup_main_t lookup_main
Definition: ip4.h:97
void clib_longjmp(clib_longjmp_t *save, uword return_value)
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:200
uword clib_setjmp(clib_longjmp_t *save, uword return_value_not_taken)
static void vl_api_vnet_ip4_fib_counters_t_handler(vl_api_vnet_ip4_fib_counters_t *mp)
Definition: stats.c:769
static clib_error_t * stats_init(vlib_main_t *vm)
Definition: stats.c:934
format_function_t format_vnet_sw_if_index_name
uword * stats_registration_hash
Definition: stats.h:47
vpe_client_registration_t * stats_registrations
Definition: stats.h:48
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
uword value[0]
Definition: hash.h:164
api_main_t api_main
Definition: api_shared.c:39
volatile u32 release_hint
Definition: stats.h:32
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
Definition: pool.h:348
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:111
void vl_msg_api_free(void *)
vlib_combined_counter_main_t * combined_sw_if_counters
Definition: interface.h:615
static BVT(clib_bihash)
Definition: adj_nbr.c:26
int i32
Definition: types.h:81
#define IP6_FIB_COUNTER_BATCH_SIZE
Definition: stats.c:58
#define clib_warning(format, args...)
Definition: error.h:59
unsigned long u64
Definition: types.h:89
struct vl_shmem_hdr_ * shmem_hdr
Definition: api.h:135
volatile u32 lock
Definition: stats.h:31
A collection of simple counters.
Definition: counter.h:59
void vlib_set_thread_name(char *name)
Definition: threads.c:93
stats_main_t stats_main
Definition: stats.c:24
#define foreach_stats_msg
Definition: stats.c:47
static void vl_api_want_stats_reply_t_handler(vl_api_want_stats_reply_t *mp)
Definition: stats.c:847
vl_shmem_hdr_t * shmem_hdr
void dsunlock(stats_main_t *sm)
Definition: stats.c:98
#define hash_get(h, key)
Definition: hash.h:248
void * thread_mheap
Definition: threads.h:95
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:369
uword * fib_entry_by_dst_address[33]
Definition: ip4.h:51
static void do_ip6_fibs(stats_main_t *sm)
Definition: stats.c:460
#define v
Definition: acl.c:314
uword os_get_cpu_number(void)
Definition: unix-misc.c:224
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:214
static void vlib_get_combined_counter(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 mini co...
Definition: counter.h:287
#define PREDICT_FALSE(x)
Definition: clib.h:97
vlib_simple_counter_main_t * sw_if_counters
Definition: interface.h:614
load_balance_main_t load_balance_main
The one instance of load-balance main.
Definition: load_balance.c:55
#define SIMPLE_COUNTER_BATCH_SIZE
Definition: stats.c:55
void unix_shared_memory_queue_lock(unix_shared_memory_queue_t *q)
#define COMBINED_COUNTER_BATCH_SIZE
Definition: stats.c:56
static void do_simple_interface_counters(stats_main_t *sm)
Definition: stats.c:126
u32 index
Definition: stats.c:428
void clib_bihash_foreach_key_value_pair(clib_bihash *h, void *callback, void *arg)
Visit active (key,value) pairs in a bi-hash table.
static void add_routes_in_fib(BVT(clib_bihash_kv)*kvp, void *arg)
Definition: stats.c:439
stats_main_t * sm
Definition: stats.c:435
void * vl_msg_api_alloc(int nbytes)
svmdb_client_t * c
u32 ft_table_id
Table ID (hash key) for this FIB.
Definition: fib_table.h:56
clib_longjmp_t jmp_buf
Definition: stats.h:54
#define IP4_FIB_COUNTER_BATCH_SIZE
Definition: stats.c:57
u64 bytes
byte counter
Definition: counter.h:167
static vlib_thread_main_t * vlib_get_thread_main()
Definition: global_funcs.h:32
static void * clib_mem_set_heap(void *heap)
Definition: mem.h:223
This table stores the routes that are used to forward traffic.
Definition: ip6.h:102
#define clib_unix_warning(format, args...)
Definition: error.h:68
static void vnet_interface_counter_unlock(vnet_interface_main_t *im)
Definition: interface.h:640
static void vl_api_vnet_ip6_fib_counters_t_handler(vl_api_vnet_ip6_fib_counters_t *mp)
Definition: stats.c:808
api_main_t * api_main
Definition: stats.h:60
#define ARRAY_LEN(x)
Definition: clib.h:59
vl_api_ip6_fib_counter_t c[count]
Definition: vpe.api:452
typedef CLIB_PACKED(struct{ip4_address_t address;u32 address_length:6;u32 index:26;})
Definition: stats.c:234
static void vnet_interface_counter_lock(vnet_interface_main_t *im)
Definition: interface.h:632
#define ASSERT(truth)
void stats_dslock_with_hint(int hint, int tag)
Definition: stats.c:91
unsigned int u32
Definition: types.h:88
ip6_main_t ip6_main
Definition: ip6_forward.c:2828
#define STATS_RELEASE_DELAY_NS
Definition: stats.c:61
IPv4 main type.
Definition: ip4.h:95
int stats_memclnt_delete_callback(u32 client_index)
Definition: stats.c:911
static void do_combined_interface_counters(stats_main_t *sm)
Definition: stats.c:181
u32 fib_result_n_words
Definition: lookup.h:394
u32 stats_poll_interval_in_seconds
Definition: stats.h:44
ip6_fib_table_instance_t ip6_table[IP6_FIB_NUM_TABLES]
The two FIB tables; fwding and non-fwding.
Definition: ip6.h:133
u64 uword
Definition: types.h:112
void dslock(stats_main_t *sm, int release_hint, int tag)
Definition: stats.c:65
vl_api_ip4_fib_counter_t c[count]
Definition: vpe.api:437
data_structure_lock_t * data_structure_lock
Definition: stats.h:51
void unix_shared_memory_queue_unlock(unix_shared_memory_queue_t *q)
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
vnet_interface_main_t * interface_main
Definition: stats.h:59
unsigned char u8
Definition: types.h:56
static void vl_api_want_stats_t_handler(vl_api_want_stats_t *mp)
Definition: stats.c:853
#define hash_foreach_pair(p, v, body)
Iterate over hash pairs.
Definition: hash.h:349
u32 address_length
Definition: stats.c:427
Stats counters structure.
Definition: interface.api:251
A collection of combined counters.
Definition: counter.h:212
word fformat(FILE *f, char *fmt,...)
Definition: format.c:452
#define clib_mem_unaligned(pointer, type)
Definition: types.h:155
static u64 vlib_get_simple_counter(vlib_simple_counter_main_t *cm, u32 index)
Get the value of a simple counter Scrapes the entire set of mini counters.
Definition: counter.h:108
ip4_fib_t v4
Definition: fib_table.h:38
static void do_ip4_fibs(stats_main_t *sm)
Definition: stats.c:262
static void * clib_mem_alloc_aligned(uword size, uword align)
Definition: mem.h:117
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:418
ip4_main_t ip4_main
Global ip4 main structure.
Definition: ip4_forward.c:1099
ip6_route_t ** routep
Definition: stats.c:434
struct fib_table_t_ * fibs
Vector of FIBs.
Definition: ip4.h:100
#define vec_foreach(var, vec)
Vector iterator.
void vl_msg_api_send_shmem_nolock(unix_shared_memory_queue_t *q, u8 *elem)
void * vlib_worker_thread_bootstrap_fn(void *arg)
Definition: threads.c:508
#define CLIB_MEMORY_BARRIER()
Definition: clib.h:101
void * vl_msg_api_alloc_as_if_client(int nbytes)
vhost_vring_addr_t addr
Definition: vhost-user.h:81
void stats_dsunlock(int hint, int tag)
Definition: stats.c:119
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:67
vnet_main_t * vnet_main
Definition: stats.h:58
struct fib_table_t_ * fibs
Definition: ip6.h:138
static void vl_api_vnet_interface_counters_t_handler(vl_api_vnet_interface_counters_t *mp)
Definition: stats.c:638
uword key
Definition: hash.h:161
A protocol Independent FIB table.
Definition: fib_table.h:29
struct _unix_shared_memory_queue unix_shared_memory_queue_t
ip6_address_t address
Definition: stats.c:426
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:109