FD.io VPP  v16.12-rc0-308-g931be3a
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
92 {
93  u32 thread_id;
95 
96  if (PREDICT_FALSE (l == 0))
97  return;
98 
99  thread_id = os_get_cpu_number ();
100  ASSERT (l->lock && l->thread_id == thread_id);
101  l->count--;
102  if (l->count == 0)
103  {
104  l->tag = -l->tag;
105  l->release_hint = 0;
107  l->lock = 0;
108  }
109 }
110 
111 static void
113 {
116  api_main_t *am = sm->api_main;
120  u32 items_this_message = 0;
121  u64 v, *vp = 0;
122  int i;
123 
124  /*
125  * Prevent interface registration from expanding / moving the vectors...
126  * That tends never to happen, so we can hold this lock for a while.
127  */
129 
130  vec_foreach (cm, im->sw_if_counters)
131  {
132 
133  for (i = 0; i < vec_len (cm->maxi); i++)
134  {
135  if (mp == 0)
136  {
137  items_this_message = clib_min (SIMPLE_COUNTER_BATCH_SIZE,
138  vec_len (cm->maxi) - i);
139 
141  (sizeof (*mp) + items_this_message * sizeof (v));
142  mp->_vl_msg_id = ntohs (VL_API_VNET_INTERFACE_COUNTERS);
143  mp->vnet_counter_type = cm - im->sw_if_counters;
144  mp->is_combined = 0;
145  mp->first_sw_if_index = htonl (i);
146  mp->count = 0;
147  vp = (u64 *) mp->data;
148  }
149  v = vlib_get_simple_counter (cm, i);
150  clib_mem_unaligned (vp, u64) = clib_host_to_net_u64 (v);
151  vp++;
152  mp->count++;
153  if (mp->count == items_this_message)
154  {
155  mp->count = htonl (items_this_message);
156  /* Send to the main thread... */
157  vl_msg_api_send_shmem (q, (u8 *) & mp);
158  mp = 0;
159  }
160  }
161  ASSERT (mp == 0);
162  }
164 }
165 
166 static void
168 {
171  api_main_t *am = sm->api_main;
175  u32 items_this_message = 0;
176  vlib_counter_t v, *vp = 0;
177  int i;
178 
180 
182  {
183 
184  for (i = 0; i < vec_len (cm->maxi); i++)
185  {
186  if (mp == 0)
187  {
188  items_this_message = clib_min (COMBINED_COUNTER_BATCH_SIZE,
189  vec_len (cm->maxi) - i);
190 
192  (sizeof (*mp) + items_this_message * sizeof (v));
193  mp->_vl_msg_id = ntohs (VL_API_VNET_INTERFACE_COUNTERS);
195  mp->is_combined = 1;
196  mp->first_sw_if_index = htonl (i);
197  mp->count = 0;
198  vp = (vlib_counter_t *) mp->data;
199  }
200  vlib_get_combined_counter (cm, i, &v);
202  = clib_host_to_net_u64 (v.packets);
203  clib_mem_unaligned (&vp->bytes, u64) = clib_host_to_net_u64 (v.bytes);
204  vp++;
205  mp->count++;
206  if (mp->count == items_this_message)
207  {
208  mp->count = htonl (items_this_message);
209  /* Send to the main thread... */
210  vl_msg_api_send_shmem (q, (u8 *) & mp);
211  mp = 0;
212  }
213  }
214  ASSERT (mp == 0);
215  }
217 }
218 
219 /* from .../vnet/vnet/ip/lookup.c. Yuck */
220 typedef CLIB_PACKED (struct
221  {
222  ip4_address_t address;
223 u32 address_length: 6;
224 u32 index: 26;
225  }) ip4_route_t;
226 
227 static void
228 ip46_fib_stats_delay (stats_main_t * sm, u32 sec, u32 nsec)
229 {
230  struct timespec _req, *req = &_req;
231  struct timespec _rem, *rem = &_rem;
232 
233  req->tv_sec = sec;
234  req->tv_nsec = nsec;
235  while (1)
236  {
237  if (nanosleep (req, rem) == 0)
238  break;
239  *req = *rem;
240  if (errno == EINTR)
241  continue;
242  clib_unix_warning ("nanosleep");
243  break;
244  }
245 }
246 
247 static void
249 {
250  ip4_main_t *im4 = &ip4_main;
251  api_main_t *am = sm->api_main;
254  static ip4_route_t *routes;
255  ip4_route_t *r;
256  fib_table_t *fib;
257  ip_lookup_main_t *lm = &im4->lookup_main;
258  static uword *results;
260  u32 items_this_message;
261  vl_api_ip4_fib_counter_t *ctrp = 0;
262  u32 start_at_fib_index = 0;
263  int i;
264 
265 again:
266  /* *INDENT-OFF* */
267  pool_foreach (fib, im4->fibs,
268  ({
269  /* We may have bailed out due to control-plane activity */
270  while ((fib - im4->fibs) < start_at_fib_index)
271  continue;
272 
273  if (mp == 0)
274  {
275  items_this_message = IP4_FIB_COUNTER_BATCH_SIZE;
276  mp = vl_msg_api_alloc_as_if_client
277  (sizeof (*mp) +
278  items_this_message * sizeof (vl_api_ip4_fib_counter_t));
279  mp->_vl_msg_id = ntohs (VL_API_VNET_IP4_FIB_COUNTERS);
280  mp->count = 0;
281  mp->vrf_id = ntohl (fib->ft_table_id);
282  ctrp = (vl_api_ip4_fib_counter_t *) mp->c;
283  }
284  else
285  {
286  /* happens if the last FIB was empty... */
287  ASSERT (mp->count == 0);
288  mp->vrf_id = ntohl (fib->ft_table_id);
289  }
290 
291  dslock (sm, 0 /* release hint */ , 1 /* tag */ );
292 
293  vec_reset_length (routes);
294  vec_reset_length (results);
295 
296  for (i = 0; i < ARRAY_LEN (fib->v4.fib_entry_by_dst_address); i++)
297  {
298  uword *hash = fib->v4.fib_entry_by_dst_address[i];
299  hash_pair_t *p;
300  ip4_route_t x;
301 
302  x.address_length = i;
303 
304  hash_foreach_pair (p, hash,
305  ({
306  x.address.data_u32 = p->key;
307  if (lm->fib_result_n_words > 1)
308  {
309  x.index = vec_len (results);
310  vec_add (results, p->value, lm->fib_result_n_words);
311  }
312  else
313  x.index = p->value[0];
314 
315  vec_add1 (routes, x);
317  {
318  start_at_fib_index = fib - im4->fibs;
319  dsunlock (sm);
320  ip46_fib_stats_delay (sm, 0 /* sec */,
321  STATS_RELEASE_DELAY_NS);
322  mp->count = 0;
323  ctrp = (vl_api_ip4_fib_counter_t *)mp->c;
324  goto again;
325  }
326  }));
327  }
328 
329  vec_foreach (r, routes)
330  {
332 
334  r->index, &c);
335  /*
336  * If it has actually
337  * seen at least one packet, send it.
338  */
339  if (c.packets > 0)
340  {
341 
342  /* already in net byte order */
343  ctrp->address = r->address.as_u32;
344  ctrp->address_length = r->address_length;
345  ctrp->packets = clib_host_to_net_u64 (c.packets);
346  ctrp->bytes = clib_host_to_net_u64 (c.bytes);
347  mp->count++;
348  ctrp++;
349 
350  if (mp->count == items_this_message)
351  {
352  mp->count = htonl (items_this_message);
353  /*
354  * If the main thread's input queue is stuffed,
355  * drop the data structure lock (which the main thread
356  * may want), and take a pause.
357  */
360  {
361  dsunlock (sm);
362  vl_msg_api_send_shmem_nolock (q, (u8 *) & mp);
364  mp = 0;
365  ip46_fib_stats_delay (sm, 0 /* sec */ ,
367  goto again;
368  }
369  vl_msg_api_send_shmem_nolock (q, (u8 *) & mp);
371 
372  items_this_message = IP4_FIB_COUNTER_BATCH_SIZE;
374  (sizeof (*mp) +
375  items_this_message * sizeof (vl_api_ip4_fib_counter_t));
376  mp->_vl_msg_id = ntohs (VL_API_VNET_IP4_FIB_COUNTERS);
377  mp->count = 0;
378  mp->vrf_id = ntohl (fib->ft_table_id);
379  ctrp = (vl_api_ip4_fib_counter_t *) mp->c;
380  }
381  } /* for each (mp or single) adj */
383  {
384  start_at_fib_index = fib - im4->fibs;
385  dsunlock (sm);
386  ip46_fib_stats_delay (sm, 0 /* sec */ , STATS_RELEASE_DELAY_NS);
387  mp->count = 0;
388  ctrp = (vl_api_ip4_fib_counter_t *) mp->c;
389  goto again;
390  }
391  } /* vec_foreach (routes) */
392 
393  dsunlock (sm);
394 
395  /* Flush any data from this fib */
396  if (mp->count)
397  {
398  mp->count = htonl (mp->count);
399  vl_msg_api_send_shmem (q, (u8 *) & mp);
400  mp = 0;
401  }
402  }));
403  /* *INDENT-ON* */
404 
405  /* If e.g. the last FIB had no reportable routes, free the buffer */
406  if (mp)
407  vl_msg_api_free (mp);
408 }
409 
410 typedef struct
411 {
415 } ip6_route_t;
416 
417 typedef struct
418 {
423 
424 static void
425 add_routes_in_fib (BVT (clib_bihash_kv) * kvp, void *arg)
426 {
427  add_routes_in_fib_arg_t *ap = arg;
428  stats_main_t *sm = ap->sm;
429 
431  clib_longjmp (&sm->jmp_buf, 1);
432 
433  if (kvp->key[2] >> 32 == ap->fib_index)
434  {
436  ip6_route_t *r;
437  addr = (ip6_address_t *) kvp;
438  vec_add2 (*ap->routep, r, 1);
439  r->address = addr[0];
440  r->address_length = kvp->key[2] & 0xFF;
441  r->index = kvp->value;
442  }
443 }
444 
445 static void
447 {
448  ip6_main_t *im6 = &ip6_main;
449  api_main_t *am = sm->api_main;
452  static ip6_route_t *routes;
453  ip6_route_t *r;
454  fib_table_t *fib;
455  static uword *results;
457  u32 items_this_message;
458  vl_api_ip6_fib_counter_t *ctrp = 0;
459  u32 start_at_fib_index = 0;
460  BVT (clib_bihash) * h = &im6->ip6_table[IP6_FIB_TABLE_FWDING].ip6_hash;
461  add_routes_in_fib_arg_t _a, *a = &_a;
462 
463 again:
464  /* *INDENT-OFF* */
465  pool_foreach (fib, im6->fibs,
466  ({
467  /* We may have bailed out due to control-plane activity */
468  while ((fib - im6->fibs) < start_at_fib_index)
469  continue;
470 
471  if (mp == 0)
472  {
473  items_this_message = IP6_FIB_COUNTER_BATCH_SIZE;
474  mp = vl_msg_api_alloc_as_if_client
475  (sizeof (*mp) +
476  items_this_message * sizeof (vl_api_ip6_fib_counter_t));
477  mp->_vl_msg_id = ntohs (VL_API_VNET_IP6_FIB_COUNTERS);
478  mp->count = 0;
479  mp->vrf_id = ntohl (fib->ft_table_id);
480  ctrp = (vl_api_ip6_fib_counter_t *) mp->c;
481  }
482 
483  dslock (sm, 0 /* release hint */ , 1 /* tag */ );
484 
485  vec_reset_length (routes);
486  vec_reset_length (results);
487 
488  a->fib_index = fib - im6->fibs;
489  a->routep = &routes;
490  a->sm = sm;
491 
492  if (clib_setjmp (&sm->jmp_buf, 0) == 0)
493  {
494  start_at_fib_index = fib - im6->fibs;
496  }
497  else
498  {
499  dsunlock (sm);
500  ip46_fib_stats_delay (sm, 0 /* sec */ ,
502  mp->count = 0;
503  ctrp = (vl_api_ip6_fib_counter_t *) mp->c;
504  goto again;
505  }
506 
507  vec_foreach (r, routes)
508  {
510 
512  r->index, &c);
513  /*
514  * If it has actually
515  * seen at least one packet, send it.
516  */
517  if (c.packets > 0)
518  {
519  /* already in net byte order */
520  ctrp->address[0] = r->address.as_u64[0];
521  ctrp->address[1] = r->address.as_u64[1];
522  ctrp->address_length = (u8) r->address_length;
523  ctrp->packets = clib_host_to_net_u64 (c.packets);
524  ctrp->bytes = clib_host_to_net_u64 (c.bytes);
525  mp->count++;
526  ctrp++;
527 
528  if (mp->count == items_this_message)
529  {
530  mp->count = htonl (items_this_message);
531  /*
532  * If the main thread's input queue is stuffed,
533  * drop the data structure lock (which the main thread
534  * may want), and take a pause.
535  */
538  {
539  dsunlock (sm);
540  vl_msg_api_send_shmem_nolock (q, (u8 *) & mp);
542  mp = 0;
543  ip46_fib_stats_delay (sm, 0 /* sec */ ,
545  goto again;
546  }
547  vl_msg_api_send_shmem_nolock (q, (u8 *) & mp);
549 
550  items_this_message = IP6_FIB_COUNTER_BATCH_SIZE;
552  (sizeof (*mp) +
553  items_this_message * sizeof (vl_api_ip6_fib_counter_t));
554  mp->_vl_msg_id = ntohs (VL_API_VNET_IP6_FIB_COUNTERS);
555  mp->count = 0;
556  mp->vrf_id = ntohl (fib->ft_table_id);
557  ctrp = (vl_api_ip6_fib_counter_t *) mp->c;
558  }
559  }
560 
562  {
563  start_at_fib_index = fib - im6->fibs;
564  dsunlock (sm);
565  ip46_fib_stats_delay (sm, 0 /* sec */ , STATS_RELEASE_DELAY_NS);
566  mp->count = 0;
567  ctrp = (vl_api_ip6_fib_counter_t *) mp->c;
568  goto again;
569  }
570  } /* vec_foreach (routes) */
571 
572  dsunlock (sm);
573 
574  /* Flush any data from this fib */
575  if (mp->count)
576  {
577  mp->count = htonl (mp->count);
578  vl_msg_api_send_shmem (q, (u8 *) & mp);
579  mp = 0;
580  }
581  }));
582  /* *INDENT-ON* */
583 
584  /* If e.g. the last FIB had no reportable routes, free the buffer */
585  if (mp)
586  vl_msg_api_free (mp);
587 }
588 
589 static void
590 stats_thread_fn (void *arg)
591 {
592  stats_main_t *sm = &stats_main;
595 
596  /* stats thread wants no signals. */
597  {
598  sigset_t s;
599  sigfillset (&s);
600  pthread_sigmask (SIG_SETMASK, &s, 0);
601  }
602 
603  if (vec_len (tm->thread_prefix))
604  vlib_set_thread_name ((char *)
605  format (0, "%v_stats%c", tm->thread_prefix, '\0'));
606 
608 
609  while (1)
610  {
611  /* 10 second poll interval */
612  ip46_fib_stats_delay (sm, 10 /* secs */ , 0 /* nsec */ );
613 
614  if (!(sm->enable_poller))
615  continue;
618  do_ip4_fibs (sm);
619  do_ip6_fibs (sm);
620  }
621 }
622 
623 static void
625  mp)
626 {
628  stats_main_t *sm = &stats_main;
629  unix_shared_memory_queue_t *q, *q_prev = NULL;
631  u32 mp_size;
632 
633 #if STATS_DEBUG > 0
634  char *counter_name;
635  u32 count, sw_if_index;
636  int i;
637 #endif
638 
639  mp_size = sizeof (*mp) + (ntohl (mp->count) *
640  (mp->is_combined ? sizeof (vlib_counter_t) :
641  sizeof (u64)));
642 
643  /* *INDENT-OFF* */
645  ({
646  q = vl_api_client_index_to_input_queue (reg->client_index);
647  if (q)
648  {
649  if (q_prev && (q_prev->cursize < q_prev->maxsize))
650  {
651  mp_copy = vl_msg_api_alloc_as_if_client(mp_size);
652  clib_memcpy(mp_copy, mp, mp_size);
653  vl_msg_api_send_shmem (q_prev, (u8 *)&mp);
654  mp = mp_copy;
655  }
656  q_prev = q;
657  }
658  }));
659  /* *INDENT-ON* */
660 
661 #if STATS_DEBUG > 0
662  count = ntohl (mp->count);
663  sw_if_index = ntohl (mp->first_sw_if_index);
664  if (mp->is_combined == 0)
665  {
666  u64 *vp, v;
667  vp = (u64 *) mp->data;
668 
669  switch (mp->vnet_counter_type)
670  {
672  counter_name = "drop";
673  break;
675  counter_name = "punt";
676  break;
678  counter_name = "ip4";
679  break;
681  counter_name = "ip6";
682  break;
684  counter_name = "rx-no-buff";
685  break;
687  , counter_name = "rx-miss";
688  break;
690  , counter_name = "rx-error (fifo-full)";
691  break;
693  , counter_name = "tx-error (fifo-full)";
694  break;
695  default:
696  counter_name = "bogus";
697  break;
698  }
699  for (i = 0; i < count; i++)
700  {
701  v = clib_mem_unaligned (vp, u64);
702  v = clib_net_to_host_u64 (v);
703  vp++;
704  fformat (stdout, "%U.%s %lld\n", format_vnet_sw_if_index_name,
705  sm->vnet_main, sw_if_index, counter_name, v);
706  sw_if_index++;
707  }
708  }
709  else
710  {
711  vlib_counter_t *vp;
712  u64 packets, bytes;
713  vp = (vlib_counter_t *) mp->data;
714 
715  switch (mp->vnet_counter_type)
716  {
718  counter_name = "rx";
719  break;
721  counter_name = "tx";
722  break;
723  default:
724  counter_name = "bogus";
725  break;
726  }
727  for (i = 0; i < count; i++)
728  {
729  packets = clib_mem_unaligned (&vp->packets, u64);
730  packets = clib_net_to_host_u64 (packets);
731  bytes = clib_mem_unaligned (&vp->bytes, u64);
732  bytes = clib_net_to_host_u64 (bytes);
733  vp++;
734  fformat (stdout, "%U.%s.packets %lld\n",
736  sm->vnet_main, sw_if_index, counter_name, packets);
737  fformat (stdout, "%U.%s.bytes %lld\n",
739  sm->vnet_main, sw_if_index, counter_name, bytes);
740  sw_if_index++;
741  }
742  }
743 #endif
744  if (q_prev && (q_prev->cursize < q_prev->maxsize))
745  {
746  vl_msg_api_send_shmem (q_prev, (u8 *) & mp);
747  }
748  else
749  {
750  vl_msg_api_free (mp);
751  }
752 }
753 
754 static void
756 {
758  stats_main_t *sm = &stats_main;
759  unix_shared_memory_queue_t *q, *q_prev = NULL;
761  u32 mp_size;
762 
763  mp_size = sizeof (*mp_copy) +
764  ntohl (mp->count) * sizeof (vl_api_ip4_fib_counter_t);
765 
766  /* *INDENT-OFF* */
768  ({
769  q = vl_api_client_index_to_input_queue (reg->client_index);
770  if (q)
771  {
772  if (q_prev && (q_prev->cursize < q_prev->maxsize))
773  {
774  mp_copy = vl_msg_api_alloc_as_if_client(mp_size);
775  clib_memcpy(mp_copy, mp, mp_size);
776  vl_msg_api_send_shmem (q_prev, (u8 *)&mp);
777  mp = mp_copy;
778  }
779  q_prev = q;
780  }
781  }));
782  /* *INDENT-ON* */
783  if (q_prev && (q_prev->cursize < q_prev->maxsize))
784  {
785  vl_msg_api_send_shmem (q_prev, (u8 *) & mp);
786  }
787  else
788  {
789  vl_msg_api_free (mp);
790  }
791 }
792 
793 static void
795 {
797  stats_main_t *sm = &stats_main;
798  unix_shared_memory_queue_t *q, *q_prev = NULL;
800  u32 mp_size;
801 
802  mp_size = sizeof (*mp_copy) +
803  ntohl (mp->count) * sizeof (vl_api_ip6_fib_counter_t);
804 
805  /* *INDENT-OFF* */
807  ({
808  q = vl_api_client_index_to_input_queue (reg->client_index);
809  if (q)
810  {
811  if (q_prev && (q_prev->cursize < q_prev->maxsize))
812  {
813  mp_copy = vl_msg_api_alloc_as_if_client(mp_size);
814  clib_memcpy(mp_copy, mp, mp_size);
815  vl_msg_api_send_shmem (q_prev, (u8 *)&mp);
816  mp = mp_copy;
817  }
818  q_prev = q;
819  }
820  }));
821  /* *INDENT-ON* */
822  if (q_prev && (q_prev->cursize < q_prev->maxsize))
823  {
824  vl_msg_api_send_shmem (q_prev, (u8 *) & mp);
825  }
826  else
827  {
828  vl_msg_api_free (mp);
829  }
830 }
831 
832 static void
834 {
835  clib_warning ("BUG");
836 }
837 
838 static void
840 {
841  stats_main_t *sm = &stats_main;
844  uword *p;
845  i32 retval = 0;
847 
849  if (p)
850  {
851  if (mp->enable_disable)
852  {
853  clib_warning ("pid %d: already enabled...", mp->pid);
854  retval = -2;
855  goto reply;
856  }
857  else
858  {
859  rp = pool_elt_at_index (sm->stats_registrations, p[0]);
860  pool_put (sm->stats_registrations, rp);
862  goto reply;
863  }
864  }
865  if (mp->enable_disable == 0)
866  {
867  clib_warning ("pid %d: already disabled...", mp->pid);
868  retval = -3;
869  goto reply;
870  }
871  pool_get (sm->stats_registrations, rp);
872  rp->client_index = mp->client_index;
873  rp->client_pid = mp->pid;
875  rp - sm->stats_registrations);
876 
877 reply:
878  if (pool_elts (sm->stats_registrations))
879  sm->enable_poller = 1;
880  else
881  sm->enable_poller = 0;
882 
884 
885  if (!q)
886  return;
887 
888  rmp = vl_msg_api_alloc (sizeof (*rmp));
889  rmp->_vl_msg_id = ntohs (VL_API_WANT_STATS_REPLY);
890  rmp->context = mp->context;
891  rmp->retval = retval;
892 
893  vl_msg_api_send_shmem (q, (u8 *) & rmp);
894 }
895 
896 int
898 {
900  stats_main_t *sm = &stats_main;
901  uword *p;
902 
903  p = hash_get (sm->stats_registration_hash, client_index);
904  if (p)
905  {
906  rp = pool_elt_at_index (sm->stats_registrations, p[0]);
907  pool_put (sm->stats_registrations, rp);
908  hash_unset (sm->stats_registration_hash, client_index);
909  }
910 
911  return 0;
912 }
913 
914 #define vl_api_vnet_ip4_fib_counters_t_endian vl_noop_handler
915 #define vl_api_vnet_ip4_fib_counters_t_print vl_noop_handler
916 #define vl_api_vnet_ip6_fib_counters_t_endian vl_noop_handler
917 #define vl_api_vnet_ip6_fib_counters_t_print vl_noop_handler
918 
919 static clib_error_t *
921 {
922  stats_main_t *sm = &stats_main;
923  api_main_t *am = &api_main;
924  void *vlib_worker_thread_bootstrap_fn (void *arg);
925 
926  sm->vlib_main = vm;
927  sm->vnet_main = vnet_get_main ();
929  sm->api_main = am;
931  sm->data_structure_lock =
934  memset (sm->data_structure_lock, 0, sizeof (*sm->data_structure_lock));
935 
936 #define _(N,n) \
937  vl_msg_api_set_handlers(VL_API_##N, #n, \
938  vl_api_##n##_t_handler, \
939  vl_noop_handler, \
940  vl_api_##n##_t_endian, \
941  vl_api_##n##_t_print, \
942  sizeof(vl_api_##n##_t), 0 /* do NOT trace! */);
944 #undef _
945 
946  /* tell the msg infra not to free these messages... */
947  am->message_bounce[VL_API_VNET_INTERFACE_COUNTERS] = 1;
948  am->message_bounce[VL_API_VNET_IP4_FIB_COUNTERS] = 1;
949  am->message_bounce[VL_API_VNET_IP6_FIB_COUNTERS] = 1;
950 
951  return 0;
952 }
953 
955 
956 /* *INDENT-OFF* */
957 VLIB_REGISTER_THREAD (stats_thread_reg, static) = {
958  .name = "stats",
959  .function = stats_thread_fn,
960  .fixed_count = 1,
961  .count = 1,
962  .no_data_structure_clone = 1,
963  .use_pthreads = 1,
964 };
965 /* *INDENT-ON* */
966 
967 /*
968  * fd.io coding-style-patch-verification: ON
969  *
970  * Local Variables:
971  * eval: (c-set-style "gnu")
972  * End:
973  */
static void stats_thread_fn(void *arg)
Definition: stats.c:590
Want Stats, register for stats updates.
Definition: vpe.api:716
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:72
Reply for Want Stats request.
Definition: vpe.api:728
u64 as_u64[2]
Definition: ip6_packet.h:50
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:120
u32 enable_poller
Definition: stats.h:50
vlib_main_t * vlib_main
Definition: stats.h:62
#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:96
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:755
static clib_error_t * stats_init(vlib_main_t *vm)
Definition: stats.c:920
format_function_t format_vnet_sw_if_index_name
uword * stats_registration_hash
Definition: stats.h:52
vpe_client_registration_t * stats_registrations
Definition: stats.h:53
#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.h:185
volatile u32 release_hint
Definition: stats.h:37
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:577
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:132
volatile u32 lock
Definition: stats.h:36
A collection of simple counters.
Definition: counter.h:59
void vlib_set_thread_name(char *name)
Definition: threads.c:92
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:833
vl_shmem_hdr_t * shmem_hdr
void dsunlock(stats_main_t *sm)
Definition: stats.c:91
#define hash_get(h, key)
Definition: hash.h:248
void * thread_mheap
Definition: threads.h:96
#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:50
static void do_ip6_fibs(stats_main_t *sm)
Definition: stats.c:446
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:576
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:112
u32 index
Definition: stats.c:414
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:425
stats_main_t * sm
Definition: stats.c:421
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:59
#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:101
#define clib_unix_warning(format, args...)
Definition: error.h:68
static void vnet_interface_counter_unlock(vnet_interface_main_t *im)
Definition: interface.h:600
static void vl_api_vnet_ip6_fib_counters_t_handler(vl_api_vnet_ip6_fib_counters_t *mp)
Definition: stats.c:794
api_main_t * api_main
Definition: stats.h:65
#define ARRAY_LEN(x)
Definition: clib.h:59
vl_api_ip6_fib_counter_t c[count]
Definition: vpe.api:778
typedef CLIB_PACKED(struct{ip4_address_t address;u32 address_length:6;u32 index:26;})
Definition: stats.c:220
static void vnet_interface_counter_lock(vnet_interface_main_t *im)
Definition: interface.h:592
#define ASSERT(truth)
unsigned int u32
Definition: types.h:88
ip6_main_t ip6_main
Definition: ip6_forward.c:2655
#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:897
static void do_combined_interface_counters(stats_main_t *sm)
Definition: stats.c:167
u32 fib_result_n_words
Definition: lookup.h:364
u32 stats_poll_interval_in_seconds
Definition: stats.h:49
ip6_fib_table_instance_t ip6_table[IP6_FIB_NUM_TABLES]
The two FIB tables; fwding and non-fwding.
Definition: ip6.h:130
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:763
data_structure_lock_t * data_structure_lock
Definition: stats.h:56
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:64
unsigned char u8
Definition: types.h:56
static void vl_api_want_stats_t_handler(vl_api_want_stats_t *mp)
Definition: stats.c:839
#define hash_foreach_pair(p, v, body)
Iterate over hash pairs.
Definition: hash.h:349
u32 address_length
Definition: stats.c:413
Want stats counters structure.
Definition: vpe.api:741
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:248
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:1060
ip6_route_t ** routep
Definition: stats.c:420
struct fib_table_t_ * fibs
Vector of FIBs.
Definition: ip4.h:99
#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
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:67
vnet_main_t * vnet_main
Definition: stats.h:63
struct fib_table_t_ * fibs
Definition: ip6.h:135
static void vl_api_vnet_interface_counters_t_handler(vl_api_vnet_interface_counters_t *mp)
Definition: stats.c:624
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:412
static uword pool_elts(void *v)
Number of active elements in a pool.
Definition: pool.h:109