FD.io VPP  v16.06
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 
19 #define STATS_DEBUG 0
20 
22 
23 #include <vnet/ip/ip.h>
24 
25 #include <api/vpe_msg_enum.h>
26 
27 #define f64_endian(a)
28 #define f64_print(a,b)
29 
30 #define vl_typedefs /* define message structures */
31 #include <api/vpe_all_api_h.h>
32 #undef vl_typedefs
33 
34 #define vl_endianfun /* define message structures */
35 #include <api/vpe_all_api_h.h>
36 #undef vl_endianfun
37 
38 /* instantiate all the print functions we know about */
39 #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
40 #define vl_printfun
41 #include <api/vpe_all_api_h.h>
42 #undef vl_printfun
43 
44 #define foreach_stats_msg \
45 _(WANT_STATS, want_stats) \
46 _(WANT_STATS_REPLY, want_stats_reply) \
47 _(VNET_INTERFACE_COUNTERS, vnet_interface_counters) \
48 _(VNET_IP4_FIB_COUNTERS, vnet_ip4_fib_counters) \
49 _(VNET_IP6_FIB_COUNTERS, vnet_ip6_fib_counters)
50 
51 /* These constants ensure msg sizes <= 1024, aka ring allocation */
52 #define SIMPLE_COUNTER_BATCH_SIZE 126
53 #define COMBINED_COUNTER_BATCH_SIZE 63
54 #define IP4_FIB_COUNTER_BATCH_SIZE 48
55 #define IP6_FIB_COUNTER_BATCH_SIZE 30
56 
57 /* 5ms */
58 #define STATS_RELEASE_DELAY_NS (1000 * 1000 * 5)
59 /* ns/us us/ms */
60 
61 void dslock (stats_main_t *sm, int release_hint, int tag)
62 {
63  u32 thread_id;
65 
66  if(PREDICT_FALSE(l == 0))
67  return;
68 
69  thread_id = os_get_cpu_number();
70  if (l->lock && l->thread_id == thread_id) {
71  l->count++;
72  return;
73  }
74 
75  if (release_hint)
76  l->release_hint++;
77 
78  while (__sync_lock_test_and_set (&l->lock, 1))
79  /* zzzz */ ;
80  l->tag = tag;
81  l->thread_id = thread_id;
82  l->count = 1;
83 }
84 
86 {
87  u32 thread_id;
89 
90  if(PREDICT_FALSE(l == 0))
91  return;
92 
93  thread_id = os_get_cpu_number();
94  ASSERT (l->lock && l->thread_id == thread_id);
95  l->count--;
96  if (l->count == 0) {
97  l->tag = -l->tag;
98  l->release_hint = 0;
100  l->lock = 0;
101  }
102 }
103 
105 {
108  api_main_t * am = sm->api_main;
112  u32 items_this_message = 0;
113  u64 v, *vp = 0;
114  int i;
115 
116  /*
117  * Prevent interface registration from expanding / moving the vectors...
118  * That tends never to happen, so we can hold this lock for a while.
119  */
121 
122  vec_foreach (cm, im->sw_if_counters) {
123 
124  for (i = 0; i < vec_len (cm->maxi); i++) {
125  if (mp == 0) {
126  items_this_message = clib_min (SIMPLE_COUNTER_BATCH_SIZE,
127  vec_len (cm->maxi) - i);
128 
130  (sizeof (*mp) + items_this_message * sizeof (v));
131  mp->_vl_msg_id = ntohs (VL_API_VNET_INTERFACE_COUNTERS);
132  mp->vnet_counter_type = cm - im->sw_if_counters;
133  mp->is_combined = 0;
134  mp->first_sw_if_index = htonl (i);
135  mp->count = 0;
136  vp = (u64 *) mp->data;
137  }
138  v = vlib_get_simple_counter (cm, i);
139  clib_mem_unaligned (vp, u64) = clib_host_to_net_u64 (v);
140  vp++;
141  mp->count++;
142  if (mp->count == items_this_message) {
143  mp->count = htonl (items_this_message);
144  /* Send to the main thread... */
145  vl_msg_api_send_shmem (q, (u8 *)&mp);
146  mp = 0;
147  }
148  }
149  ASSERT (mp == 0);
150  }
152 }
153 
155 {
158  api_main_t * am = sm->api_main;
162  u32 items_this_message = 0;
163  vlib_counter_t v, *vp = 0;
164  int i;
165 
167 
169 
170  for (i = 0; i < vec_len (cm->maxi); i++) {
171  if (mp == 0) {
172  items_this_message = clib_min (COMBINED_COUNTER_BATCH_SIZE,
173  vec_len (cm->maxi) - i);
174 
176  (sizeof (*mp) + items_this_message * sizeof (v));
177  mp->_vl_msg_id = ntohs (VL_API_VNET_INTERFACE_COUNTERS);
179  mp->is_combined = 1;
180  mp->first_sw_if_index = htonl (i);
181  mp->count = 0;
182  vp = (vlib_counter_t *)mp->data;
183  }
184  vlib_get_combined_counter (cm, i, &v);
186  = clib_host_to_net_u64 (v.packets);
187  clib_mem_unaligned (&vp->bytes, u64)
188  = clib_host_to_net_u64 (v.bytes);
189  vp++;
190  mp->count++;
191  if (mp->count == items_this_message) {
192  mp->count = htonl (items_this_message);
193  /* Send to the main thread... */
194  vl_msg_api_send_shmem (q, (u8 *)&mp);
195  mp = 0;
196  }
197  }
198  ASSERT (mp == 0);
199  }
201 }
202 
203 /* from .../vnet/vnet/ip/lookup.c. Yuck */
204 typedef CLIB_PACKED (struct {
205  ip4_address_t address;
206 
207  u32 address_length : 6;
208 
209  u32 index : 26;
210 }) ip4_route_t;
211 
212 static void ip46_fib_stats_delay (stats_main_t * sm, u32 sec, u32 nsec)
213 {
214  struct timespec _req, *req = &_req;
215  struct timespec _rem, *rem = &_rem;
216 
217  req->tv_sec = sec;
218  req->tv_nsec = nsec;
219  while (1) {
220  if (nanosleep (req, rem) == 0)
221  break;
222  *req = *rem;
223  if (errno == EINTR)
224  continue;
225  clib_unix_warning ("nanosleep");
226  break;
227  }
228 }
229 
230 static void do_ip4_fibs (stats_main_t * sm)
231 {
232  ip4_main_t * im4 = &ip4_main;
233  api_main_t * am = sm->api_main;
236  static ip4_route_t * routes;
237  ip4_route_t * r;
238  ip4_fib_t * fib;
239  ip_lookup_main_t * lm = &im4->lookup_main;
240  static uword * results;
242  u32 items_this_message;
243  vl_api_ip4_fib_counter_t *ctrp = 0;
244  u32 start_at_fib_index = 0;
245  int i;
246 
247 again:
248  vec_foreach (fib, im4->fibs) {
249  /* We may have bailed out due to control-plane activity */
250  while ((fib - im4->fibs) < start_at_fib_index)
251  continue;
252 
253  if (mp == 0) {
254  items_this_message = IP4_FIB_COUNTER_BATCH_SIZE;
256  (sizeof(*mp) +
257  items_this_message*sizeof(vl_api_ip4_fib_counter_t));
258  mp->_vl_msg_id = ntohs (VL_API_VNET_IP4_FIB_COUNTERS);
259  mp->count = 0;
260  mp->vrf_id = ntohl(fib->table_id);
261  ctrp = (vl_api_ip4_fib_counter_t *)mp->c;
262  } else {
263  /* happens if the last FIB was empty... */
264  ASSERT(mp->count == 0);
265  mp->vrf_id = ntohl(fib->table_id);
266  }
267 
268  dslock (sm, 0 /* release hint */, 1 /* tag */);
269 
270  vec_reset_length (routes);
271  vec_reset_length (results);
272 
273  for (i = 0; i < ARRAY_LEN (fib->adj_index_by_dst_address); i++) {
274  uword * hash = fib->adj_index_by_dst_address[i];
275  hash_pair_t * p;
276  ip4_route_t x;
277 
278  x.address_length = i;
279 
280  hash_foreach_pair (p, hash,
281  ({
282  x.address.data_u32 = p->key;
283  if (lm->fib_result_n_words > 1) {
284  x.index = vec_len (results);
285  vec_add (results, p->value, lm->fib_result_n_words);
286  }
287  else
288  x.index = p->value[0];
289 
290  vec_add1 (routes, x);
292  start_at_fib_index = fib - im4->fibs;
293  dsunlock (sm);
294  ip46_fib_stats_delay (sm, 0 /* sec */,
295  STATS_RELEASE_DELAY_NS);
296  mp->count = 0;
297  ctrp = (vl_api_ip4_fib_counter_t *)mp->c;
298  goto again;
299  }
300  }));
301  }
302 
303  vec_foreach (r, routes) {
304  vlib_counter_t c, sum;
305  uword i, j, n_left, n_nhs, adj_index, * result = 0;
306  ip_adjacency_t * adj;
307  ip_multipath_next_hop_t * nhs, tmp_nhs[1];
308 
309  adj_index = r->index;
310  if (lm->fib_result_n_words > 1) {
311  result = vec_elt_at_index (results, adj_index);
312  adj_index = result[0];
313  }
314 
315  adj = ip_get_adjacency (lm, adj_index);
316  if (adj->n_adj == 1) {
317  nhs = &tmp_nhs[0];
318  nhs[0].next_hop_adj_index = ~0; /* not used */
319  nhs[0].weight = 1;
320  n_nhs = 1;
321  } else {
324  adj->heap_handle);
325  nhs = heap_elt_at_index
326  (lm->next_hop_heap,
328  n_nhs = madj->normalized_next_hops.count;
329  }
330 
331  n_left = nhs[0].weight;
332  vlib_counter_zero (&sum);
333  for (i = j = 0; i < adj->n_adj; i++) {
334  n_left -= 1;
336  adj_index + i, &c);
337  vlib_counter_add (&sum, &c);
338  /*
339  * If we're done with this adj and it has actually
340  * seen at least one packet, send it.
341  */
342  if (n_left == 0 && sum.packets > 0) {
343 
344  /* already in net byte order */
345  ctrp->address = r->address.as_u32;
346  ctrp->address_length = r->address_length;
347  ctrp->packets = clib_host_to_net_u64 (sum.packets);
348  ctrp->bytes = clib_host_to_net_u64(sum.bytes);
349  mp->count++;
350  ctrp++;
351 
352  if (mp->count == items_this_message) {
353  mp->count = htonl (items_this_message);
354  /*
355  * If the main thread's input queue is stuffed,
356  * drop the data structure lock (which the main thread
357  * may want), and take a pause.
358  */
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*
376  sizeof(vl_api_ip4_fib_counter_t));
377  mp->_vl_msg_id = ntohs (VL_API_VNET_IP4_FIB_COUNTERS);
378  mp->count = 0;
379  mp->vrf_id = ntohl(fib->table_id);
380  ctrp = (vl_api_ip4_fib_counter_t *)mp->c;
381  }
382 
383  j++;
384  if (j < n_nhs) {
385  n_left = nhs[j].weight;
386  vlib_counter_zero (&sum);
387  }
388  }
389  } /* for each (mp or single) adj */
391  start_at_fib_index = fib - im4->fibs;
392  dsunlock (sm);
393  ip46_fib_stats_delay (sm, 0 /* sec */, STATS_RELEASE_DELAY_NS);
394  mp->count = 0;
395  ctrp = (vl_api_ip4_fib_counter_t *)mp->c;
396  goto again;
397  }
398  } /* vec_foreach (routes) */
399 
400  dsunlock(sm);
401 
402  /* Flush any data from this fib */
403  if (mp->count) {
404  mp->count = htonl (mp->count);
405  vl_msg_api_send_shmem (q, (u8 *)&mp);
406  mp = 0;
407  }
408  } /* vec_foreach (fib) */
409  /* If e.g. the last FIB had no reportable routes, free the buffer */
410  if (mp)
411  vl_msg_api_free (mp);
412 }
413 
414 typedef struct {
415  ip6_address_t address;
416  u32 address_length;
417  u32 index;
418 } ip6_route_t;
419 
420 typedef struct {
421  u32 fib_index;
422  ip6_route_t ** routep;
425 
426 static void add_routes_in_fib (BVT(clib_bihash_kv) * kvp, void *arg)
427 {
428  add_routes_in_fib_arg_t * ap = arg;
429  stats_main_t * sm = ap->sm;
430 
432  clib_longjmp (&sm->jmp_buf, 1);
433 
434  if (kvp->key[2]>>32 == ap->fib_index)
435  {
437  ip6_route_t * r;
438  addr = (ip6_address_t *) kvp;
439  vec_add2 (*ap->routep, r, 1);
440  r->address = addr[0];
441  r->address_length = kvp->key[2] & 0xFF;
442  r->index = kvp->value;
443  }
444 }
445 
446 static void do_ip6_fibs (stats_main_t * sm)
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  ip6_fib_t * fib;
455  ip_lookup_main_t * lm = &im6->lookup_main;
456  static uword * results;
458  u32 items_this_message;
459  vl_api_ip6_fib_counter_t *ctrp = 0;
460  u32 start_at_fib_index = 0;
461  BVT(clib_bihash) * h = &im6->ip6_lookup_table;
462  add_routes_in_fib_arg_t _a, *a=&_a;
463 
464 again:
465  vec_foreach (fib, im6->fibs) {
466  /* We may have bailed out due to control-plane activity */
467  while ((fib - im6->fibs) < start_at_fib_index)
468  continue;
469 
470  if (mp == 0) {
471  items_this_message = IP6_FIB_COUNTER_BATCH_SIZE;
473  (sizeof(*mp) +
474  items_this_message*sizeof(vl_api_ip6_fib_counter_t));
475  mp->_vl_msg_id = ntohs (VL_API_VNET_IP6_FIB_COUNTERS);
476  mp->count = 0;
477  mp->vrf_id = ntohl(fib->table_id);
478  ctrp = (vl_api_ip6_fib_counter_t *)mp->c;
479  }
480 
481  dslock (sm, 0 /* release hint */, 1 /* tag */);
482 
483  vec_reset_length (routes);
484  vec_reset_length (results);
485 
486  a->fib_index = fib - im6->fibs;
487  a->routep = &routes;
488  a->sm = sm;
489 
490  if (clib_setjmp(&sm->jmp_buf, 0) == 0)
491  {
492  start_at_fib_index = fib - im6->fibs;
494  }
495  else
496  {
497  dsunlock (sm);
498  ip46_fib_stats_delay (sm, 0 /* sec */,
500  mp->count = 0;
501  ctrp = (vl_api_ip6_fib_counter_t *)mp->c;
502  goto again;
503  }
504 
505  vec_foreach (r, routes) {
506  vlib_counter_t c, sum;
507  uword i, j, n_left, n_nhs, adj_index, * result = 0;
508  ip_adjacency_t * adj;
509  ip_multipath_next_hop_t * nhs, tmp_nhs[1];
510 
511  adj_index = r->index;
512  if (lm->fib_result_n_words > 1) {
513  result = vec_elt_at_index (results, adj_index);
514  adj_index = result[0];
515  }
516 
517  adj = ip_get_adjacency (lm, adj_index);
518  if (adj->n_adj == 1) {
519  nhs = &tmp_nhs[0];
520  nhs[0].next_hop_adj_index = ~0; /* not used */
521  nhs[0].weight = 1;
522  n_nhs = 1;
523  } else {
526  adj->heap_handle);
527  nhs = heap_elt_at_index
528  (lm->next_hop_heap,
530  n_nhs = madj->normalized_next_hops.count;
531  }
532 
533  n_left = nhs[0].weight;
534  vlib_counter_zero (&sum);
535  for (i = j = 0; i < adj->n_adj; i++) {
536  n_left -= 1;
538  adj_index + i, &c);
539  vlib_counter_add (&sum, &c);
540  if (n_left == 0 && sum.packets > 0) {
541 
542  /* already in net byte order */
543  ctrp->address[0] = r->address.as_u64[0];
544  ctrp->address[1] = r->address.as_u64[1];
545  ctrp->address_length = (u8) r->address_length;
546  ctrp->packets = clib_host_to_net_u64 (sum.packets);
547  ctrp->bytes = clib_host_to_net_u64(sum.bytes);
548  mp->count++;
549  ctrp++;
550 
551  if (mp->count == items_this_message) {
552  mp->count = htonl (items_this_message);
553  /*
554  * If the main thread's input queue is stuffed,
555  * drop the data structure lock (which the main thread
556  * may want), and take a pause.
557  */
560  dsunlock (sm);
561  vl_msg_api_send_shmem_nolock (q, (u8 *)&mp);
563  mp = 0;
564  ip46_fib_stats_delay (sm, 0 /* sec */,
566  goto again;
567  }
568  vl_msg_api_send_shmem_nolock (q, (u8 *)&mp);
570 
571  items_this_message = IP6_FIB_COUNTER_BATCH_SIZE;
573  (sizeof(*mp) +
574  items_this_message*
575  sizeof(vl_api_ip6_fib_counter_t));
576  mp->_vl_msg_id = ntohs (VL_API_VNET_IP6_FIB_COUNTERS);
577  mp->count = 0;
578  mp->vrf_id = ntohl(fib->table_id);
579  ctrp = (vl_api_ip6_fib_counter_t *)mp->c;
580  }
581 
582  j++;
583  if (j < n_nhs) {
584  n_left = nhs[j].weight;
585  vlib_counter_zero (&sum);
586  }
587  }
588  } /* for each (mp or single) adj */
590  start_at_fib_index = fib - im6->fibs;
591  dsunlock (sm);
592  ip46_fib_stats_delay (sm, 0 /* sec */, STATS_RELEASE_DELAY_NS);
593  mp->count = 0;
594  ctrp = (vl_api_ip6_fib_counter_t *)mp->c;
595  goto again;
596  }
597  } /* vec_foreach (routes) */
598 
599  dsunlock(sm);
600 
601  /* Flush any data from this fib */
602  if (mp->count) {
603  mp->count = htonl (mp->count);
604  vl_msg_api_send_shmem (q, (u8 *)&mp);
605  mp = 0;
606  }
607  } /* vec_foreach (fib) */
608  /* If e.g. the last FIB had no reportable routes, free the buffer */
609  if (mp)
610  vl_msg_api_free (mp);
611 }
612 
613 static void stats_thread_fn (void *arg)
614 {
615  stats_main_t *sm = &stats_main;
618 
619  /* stats thread wants no signals. */
620  {
621  sigset_t s;
622  sigfillset (&s);
623  pthread_sigmask (SIG_SETMASK, &s, 0);
624  }
625 
626  if (vec_len(tm->thread_prefix))
627  vlib_set_thread_name((char *)
628  format(0, "%v_stats%c", tm->thread_prefix, '\0'));
629 
631 
632  while (1) {
633  /* 10 second poll interval */
634  ip46_fib_stats_delay (sm, 10 /* secs */, 0 /* nsec */);
635 
636  if (! (sm->enable_poller))
637  continue;
640  do_ip4_fibs (sm);
641  do_ip6_fibs (sm);
642  }
643 }
644 
647 {
649  stats_main_t * sm = &stats_main;
650  unix_shared_memory_queue_t *q, *q_prev = NULL;
652  u32 mp_size;
653 
654 #if STATS_DEBUG > 0
655  char *counter_name;
656  u32 count, sw_if_index;
657  int i;
658 #endif
659 
660  mp_size = sizeof (*mp) + (ntohl(mp->count) *
661  (mp->is_combined ? sizeof (vlib_counter_t) : sizeof (u64)));
662 
664  ({
665  q = vl_api_client_index_to_input_queue (reg->client_index);
666  if (q) {
667  if (q_prev && (q_prev->cursize < q_prev->maxsize)) {
668  mp_copy = vl_msg_api_alloc_as_if_client(mp_size);
669  clib_memcpy(mp_copy, mp, mp_size);
670  vl_msg_api_send_shmem (q_prev, (u8 *)&mp);
671  mp = mp_copy;
672  }
673  q_prev = q;
674  }
675  }));
676 
677 #if STATS_DEBUG > 0
678  count = ntohl (mp->count);
679  sw_if_index = ntohl (mp->first_sw_if_index);
680  if (mp->is_combined == 0) {
681  u64 * vp, v;
682  vp = (u64 *) mp->data;
683 
684  switch (mp->vnet_counter_type) {
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  v = clib_mem_unaligned (vp, u64);
715  v = clib_net_to_host_u64 (v);
716  vp++;
717  fformat (stdout, "%U.%s %lld\n", format_vnet_sw_if_index_name,
718  sm->vnet_main, sw_if_index, counter_name, v);
719  sw_if_index++;
720  }
721  } else {
722  vlib_counter_t *vp;
723  u64 packets, bytes;
724  vp = (vlib_counter_t *) mp->data;
725 
726  switch (mp->vnet_counter_type) {
728  counter_name = "rx";
729  break;
731  counter_name = "tx";
732  break;
733  default:
734  counter_name = "bogus";
735  break;
736  }
737  for (i = 0; i < count; i++) {
738  packets = clib_mem_unaligned (&vp->packets, u64);
739  packets = clib_net_to_host_u64 (packets);
740  bytes = clib_mem_unaligned (&vp->bytes, u64);
741  bytes = clib_net_to_host_u64 (bytes);
742  vp++;
743  fformat (stdout, "%U.%s.packets %lld\n",
745  sm->vnet_main, sw_if_index, counter_name, packets);
746  fformat (stdout, "%U.%s.bytes %lld\n",
748  sm->vnet_main, sw_if_index, counter_name, bytes);
749  sw_if_index++;
750  }
751  }
752 #endif
753  if (q_prev &&
754  (q_prev->cursize < q_prev->maxsize)) {
755  vl_msg_api_send_shmem (q_prev, (u8 *)&mp);
756  } else {
757  vl_msg_api_free (mp);
758  }
759 }
760 
763 {
765  stats_main_t * sm = &stats_main;
766  unix_shared_memory_queue_t *q, *q_prev = NULL;
768  u32 mp_size;
769 
770  mp_size = sizeof(*mp_copy) +
771  ntohl(mp->count) * sizeof(vl_api_ip4_fib_counter_t);
772 
774  ({
775  q = vl_api_client_index_to_input_queue (reg->client_index);
776  if (q) {
777  if (q_prev && (q_prev->cursize < q_prev->maxsize)) {
778  mp_copy = vl_msg_api_alloc_as_if_client(mp_size);
779  clib_memcpy(mp_copy, mp, mp_size);
780  vl_msg_api_send_shmem (q_prev, (u8 *)&mp);
781  mp = mp_copy;
782  }
783  q_prev = q;
784  }
785  }));
786  if (q_prev &&
787  (q_prev->cursize < q_prev->maxsize)) {
788  vl_msg_api_send_shmem (q_prev, (u8 *)&mp);
789  } else {
790  vl_msg_api_free (mp);
791  }
792 }
793 
796 {
798  stats_main_t * sm = &stats_main;
799  unix_shared_memory_queue_t *q, *q_prev = NULL;
801  u32 mp_size;
802 
803  mp_size = sizeof(*mp_copy) +
804  ntohl(mp->count) * sizeof(vl_api_ip6_fib_counter_t);
805 
807  ({
808  q = vl_api_client_index_to_input_queue (reg->client_index);
809  if (q) {
810  if (q_prev && (q_prev->cursize < q_prev->maxsize)) {
811  mp_copy = vl_msg_api_alloc_as_if_client(mp_size);
812  clib_memcpy(mp_copy, mp, mp_size);
813  vl_msg_api_send_shmem (q_prev, (u8 *)&mp);
814  mp = mp_copy;
815  }
816  q_prev = q;
817  }
818  }));
819  if (q_prev &&
820  (q_prev->cursize < q_prev->maxsize)) {
821  vl_msg_api_send_shmem (q_prev, (u8 *)&mp);
822  } else {
823  vl_msg_api_free (mp);
824  }
825 }
826 
828 { clib_warning ("BUG"); }
829 
832 {
833  stats_main_t *sm = &stats_main;
836  uword *p;
837  i32 retval = 0;
839 
841  if (p) {
842  if (mp->enable_disable) {
843  clib_warning ("pid %d: already enabled...", mp->pid);
844  retval = -2;
845  goto reply;
846  } else {
847  rp = pool_elt_at_index (sm->stats_registrations, p[0]);
848  pool_put (sm->stats_registrations, rp);
850  goto reply;
851  }
852  }
853  if (mp->enable_disable == 0) {
854  clib_warning ("pid %d: already disabled...", mp->pid);
855  retval = -3;
856  goto reply;
857  }
858  pool_get (sm->stats_registrations, rp);
859  rp->client_index = mp->client_index;
860  rp->client_pid = mp->pid;
862  rp - sm->stats_registrations);
863 
864 reply:
866  sm->enable_poller = 1;
867  else
868  sm->enable_poller = 0;
869 
871 
872  if (!q)
873  return;
874 
875  rmp = vl_msg_api_alloc (sizeof (*rmp));
876  rmp->_vl_msg_id = ntohs(VL_API_WANT_STATS_REPLY);
877  rmp->context = mp->context;
878  rmp->retval = retval;
879 
880  vl_msg_api_send_shmem (q, (u8 *)&rmp);
881 }
882 
884 {
886  stats_main_t *sm = &stats_main;
887  uword * p;
888 
889  p = hash_get (sm->stats_registration_hash, client_index);
890  if (p) {
891  rp = pool_elt_at_index (sm->stats_registrations, p[0]);
892  pool_put (sm->stats_registrations, rp);
893  hash_unset (sm->stats_registration_hash, client_index);
894  }
895 
896  return 0;
897 }
898 
899 #define vl_api_vnet_ip4_fib_counters_t_endian vl_noop_handler
900 #define vl_api_vnet_ip4_fib_counters_t_print vl_noop_handler
901 #define vl_api_vnet_ip6_fib_counters_t_endian vl_noop_handler
902 #define vl_api_vnet_ip6_fib_counters_t_print vl_noop_handler
903 
905 {
906  stats_main_t * sm = &stats_main;
907  api_main_t * am = &api_main;
908  void *vlib_worker_thread_bootstrap_fn (void *arg);
909 
910  sm->vlib_main = vm;
911  sm->vnet_main = vnet_get_main();
913  sm->api_main = am;
915  sm->data_structure_lock =
918  memset(sm->data_structure_lock, 0, sizeof (*sm->data_structure_lock));
919 
920 #define _(N,n) \
921  vl_msg_api_set_handlers(VL_API_##N, #n, \
922  vl_api_##n##_t_handler, \
923  vl_noop_handler, \
924  vl_api_##n##_t_endian, \
925  vl_api_##n##_t_print, \
926  sizeof(vl_api_##n##_t), 0 /* do NOT trace! */);
928 #undef _
929 
930  /* tell the msg infra not to free these messages... */
931  am->message_bounce [VL_API_VNET_INTERFACE_COUNTERS] = 1;
932  am->message_bounce [VL_API_VNET_IP4_FIB_COUNTERS] = 1;
933  am->message_bounce [VL_API_VNET_IP6_FIB_COUNTERS] = 1;
934 
935  return 0;
936 }
937 
939 
940 VLIB_REGISTER_THREAD (stats_thread_reg, static) = {
941  .name = "stats",
942  .function = stats_thread_fn,
943  .fixed_count = 1,
944  .count = 1,
945  .no_data_structure_clone = 1,
946  .use_pthreads = 1,
947 };
static void stats_thread_fn(void *arg)
Definition: stats.c:613
void * vlib_worker_thread_bootstrap_fn(void *arg)
Definition: threads.c:474
Want Stats, register for stats updates.
Definition: vpe.api:604
#define hash_set(h, key, value)
Definition: hash.h:237
always_inline vlib_thread_main_t * vlib_get_thread_main()
Definition: global_funcs.h:32
sll srl srl sll sra u16x4 i
Definition: vector_sse2.h:267
#define clib_min(x, y)
Definition: clib.h:295
#define hash_unset(h, key)
Definition: hash.h:243
a
Definition: bitmap.h:393
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:62
u32 table_id
Definition: ip4.h:58
Reply for Want Stats request.
Definition: vpe.api:615
u64 as_u64[2]
Definition: ip6_packet.h:50
unix_shared_memory_queue_t * vl_input_queue
Definition: api.h:71
#define NULL
Definition: clib.h:55
vlib_counter_t * maxi
Definition: counter.h:181
u8 * message_bounce
Definition: api.h:113
u32 enable_poller
Definition: stats.h:47
vlib_main_t * vlib_main
Definition: stats.h:59
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:480
#define heap_elt_at_index(v, index)
Definition: heap.h:267
unix_shared_memory_queue_t * vl_api_client_index_to_input_queue(u32 index)
#define vec_add2(V, P, N)
Add N elements to end of vector V, return pointer to new elements in P.
Definition: vec.h:519
always_inline u64 vlib_get_simple_counter(vlib_simple_counter_main_t *cm, u32 index)
Definition: counter.h:93
VLIB_REGISTER_THREAD(stats_thread_reg, static)
ip_lookup_main_t lookup_main
Definition: ip4.h:129
void clib_longjmp(clib_longjmp_t *save, uword return_value)
#define pool_get(P, E)
Definition: pool.h:186
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:761
static clib_error_t * stats_init(vlib_main_t *vm)
Definition: stats.c:904
format_function_t format_vnet_sw_if_index_name
vl_api_ip6_fib_counter_t c[0]
Definition: vpe.api:659
uword * stats_registration_hash
Definition: stats.h:49
vpe_client_registration_t * stats_registrations
Definition: stats.h:50
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
uword value[0]
Definition: hash.h:151
api_main_t api_main
Definition: api.h:162
volatile u32 release_hint
Definition: stats.h:35
vnet_main_t * vnet_get_main(void)
Definition: misc.c:45
always_inline void vlib_counter_add(vlib_counter_t *a, vlib_counter_t *b)
Definition: counter.h:148
void BV() clib_bihash_foreach_key_value_pair(BVT(clib_bihash)*h, void *callback, void *arg)
#define pool_foreach(VAR, POOL, BODY)
Definition: pool.h:328
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:109
void vl_msg_api_free(void *)
vlib_combined_counter_main_t * combined_sw_if_counters
Definition: interface.h:458
int i32
Definition: types.h:81
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
#define IP6_FIB_COUNTER_BATCH_SIZE
Definition: stats.c:55
always_inline uword pool_elts(void *v)
Definition: pool.h:97
#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:125
volatile u32 lock
Definition: stats.h:34
ip6_fib_t * fibs
Definition: ip6.h:143
stats_main_t stats_main
Definition: stats.c:21
#define foreach_stats_msg
Definition: stats.c:44
static void vl_api_want_stats_reply_t_handler(vl_api_want_stats_reply_t *mp)
Definition: stats.c:827
vl_shmem_hdr_t * shmem_hdr
always_inline void * clib_mem_alloc_aligned(uword size, uword align)
Definition: mem.h:113
void dsunlock(stats_main_t *sm)
Definition: stats.c:85
#define hash_get(h, key)
Definition: hash.h:231
void * thread_mheap
Definition: threads.h:91
#define pool_elt_at_index(p, i)
Definition: pool.h:346
static void do_ip6_fibs(stats_main_t *sm)
Definition: stats.c:446
always_inline void vlib_counter_zero(vlib_counter_t *a)
Definition: counter.h:164
uword os_get_cpu_number(void)
Definition: unix-misc.c:206
#define pool_put(P, E)
Definition: pool.h:200
static void vlib_get_combined_counter(vlib_combined_counter_main_t *cm, u32 index, vlib_counter_t *result)
Definition: counter.h:248
#define PREDICT_FALSE(x)
Definition: clib.h:97
always_inline void * clib_mem_set_heap(void *heap)
Definition: mem.h:190
vlib_simple_counter_main_t * sw_if_counters
Definition: interface.h:457
#define SIMPLE_COUNTER_BATCH_SIZE
Definition: stats.c:52
void unix_shared_memory_queue_lock(unix_shared_memory_queue_t *q)
#define COMBINED_COUNTER_BATCH_SIZE
Definition: stats.c:53
static void do_simple_interface_counters(stats_main_t *sm)
Definition: stats.c:104
u32 index
Definition: lookup.c:2053
static void add_routes_in_fib(BVT(clib_bihash_kv)*kvp, void *arg)
Definition: stats.c:426
stats_main_t * sm
Definition: stats.c:423
void * vl_msg_api_alloc(int nbytes)
clib_longjmp_t jmp_buf
Definition: stats.h:56
#define IP4_FIB_COUNTER_BATCH_SIZE
Definition: stats.c:54
Definition: ip6.h:62
Definition: ip4.h:47
#define clib_unix_warning(format, args...)
Definition: error.h:68
static void vnet_interface_counter_unlock(vnet_interface_main_t *im)
Definition: interface.h:478
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:62
#define ARRAY_LEN(x)
Definition: clib.h:59
struct ip_multipath_adjacency_t::@117 normalized_next_hops
typedef CLIB_PACKED(struct{ip4_address_t address;u32 address_length:6;u32 index:26;})
Definition: stats.c:204
vlib_combined_counter_main_t adjacency_counters
Definition: lookup.h:353
static void vnet_interface_counter_lock(vnet_interface_main_t *im)
Definition: interface.h:472
#define ASSERT(truth)
unsigned int u32
Definition: types.h:88
ip4_fib_t * fibs
Definition: ip4.h:132
ip6_main_t ip6_main
Definition: ip6_forward.c:2490
ip_lookup_main_t lookup_main
Definition: ip6.h:135
#define STATS_RELEASE_DELAY_NS
Definition: stats.c:58
u8 * format(u8 *s, char *fmt,...)
Definition: format.c:405
int stats_memclnt_delete_callback(u32 client_index)
Definition: stats.c:883
#define BV(a)
static void do_combined_interface_counters(stats_main_t *sm)
Definition: stats.c:154
u32 fib_result_n_words
Definition: lookup.h:405
u32 stats_poll_interval_in_seconds
Definition: stats.h:46
always_inline ip_adjacency_t * ip_get_adjacency(ip_lookup_main_t *lm, u32 adj_index)
Definition: lookup.h:423
u64 uword
Definition: types.h:112
void dslock(stats_main_t *sm, int release_hint, int tag)
Definition: stats.c:61
data_structure_lock_t * data_structure_lock
Definition: stats.h:53
ip6_route_t ** routep
Definition: lookup.c:2058
#define BVT(a)
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:61
unsigned char u8
Definition: types.h:56
static void vl_api_want_stats_t_handler(vl_api_want_stats_t *mp)
Definition: stats.c:830
#define hash_foreach_pair(p, v, body)
Definition: hash.h:311
u32 heap_handle
Definition: lookup.h:150
u32 address_length
Definition: lookup.c:2051
Want stats counters structure.
Definition: vpe.api:627
word fformat(FILE *f, char *fmt,...)
Definition: format.c:437
#define clib_mem_unaligned(pointer, type)
Definition: types.h:153
static void do_ip4_fibs(stats_main_t *sm)
Definition: stats.c:230
ip_multipath_next_hop_t * next_hop_heap
Definition: lookup.h:356
ip_multipath_adjacency_t * multipath_adjacencies
Definition: lookup.h:359
ip4_main_t ip4_main
Definition: ip4_forward.c:1394
#define vec_foreach(var, vec)
Vector iterator.
void vl_msg_api_send_shmem_nolock(unix_shared_memory_queue_t *q, u8 *elem)
#define CLIB_MEMORY_BARRIER()
Definition: clib.h:101
u32 table_id
Definition: ip6.h:64
uword * adj_index_by_dst_address[33]
Definition: ip4.h:49
void * vl_msg_api_alloc_as_if_client(int nbytes)
vhost_vring_addr_t addr
Definition: vhost-user.h:78
#define CLIB_CACHE_LINE_BYTES
Definition: cache.h:67
vnet_main_t * vnet_main
Definition: stats.h:60
void vlib_set_thread_name(char *name)
Definition: threads.c:85
static void vl_api_vnet_interface_counters_t_handler(vl_api_vnet_interface_counters_t *mp)
Definition: stats.c:645
vl_api_ip4_fib_counter_t c[0]
Definition: vpe.api:646
uword key
Definition: hash.h:148
struct _unix_shared_memory_queue unix_shared_memory_queue_t
ip6_address_t address
Definition: lookup.c:2049