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:
7 * http://www.apache.org/licenses/LICENSE-2.0
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.
15 #include <stats/stats.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>
24 stats_main_t stats_main;
26 #include <vnet/ip/ip.h>
28 #include <vpp-api/vpe_msg_enum.h>
31 #define f64_print(a,b)
33 #define vl_typedefs /* define message structures */
34 #include <vpp-api/vpe_all_api_h.h>
37 #define vl_endianfun /* define message structures */
38 #include <vpp-api/vpe_all_api_h.h>
41 /* instantiate all the print functions we know about */
42 #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
44 #include <vpp-api/vpe_all_api_h.h>
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)
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
61 #define STATS_RELEASE_DELAY_NS (1000 * 1000 * 5)
65 dslock (stats_main_t * sm, int release_hint, int tag)
68 data_structure_lock_t *l = sm->data_structure_lock;
70 if (PREDICT_FALSE (l == 0))
73 thread_id = os_get_cpu_number ();
74 if (l->lock && l->thread_id == thread_id)
83 while (__sync_lock_test_and_set (&l->lock, 1))
86 l->thread_id = thread_id;
91 stats_dslock_with_hint (int hint, int tag)
93 stats_main_t *sm = &stats_main;
94 dslock (sm, hint, tag);
98 dsunlock (stats_main_t * sm)
101 data_structure_lock_t *l = sm->data_structure_lock;
103 if (PREDICT_FALSE (l == 0))
106 thread_id = os_get_cpu_number ();
107 ASSERT (l->lock && l->thread_id == thread_id);
113 CLIB_MEMORY_BARRIER ();
119 stats_dsunlock (int hint, int tag)
121 stats_main_t *sm = &stats_main;
126 do_simple_interface_counters (stats_main_t * sm)
128 vl_api_vnet_interface_counters_t *mp = 0;
129 vnet_interface_main_t *im = sm->interface_main;
130 api_main_t *am = sm->api_main;
131 vl_shmem_hdr_t *shmem_hdr = am->shmem_hdr;
132 unix_shared_memory_queue_t *q = shmem_hdr->vl_input_queue;
133 vlib_simple_counter_main_t *cm;
134 u32 items_this_message = 0;
139 * Prevent interface registration from expanding / moving the vectors...
140 * That tends never to happen, so we can hold this lock for a while.
142 vnet_interface_counter_lock (im);
144 vec_foreach (cm, im->sw_if_counters)
147 for (i = 0; i < vec_len (cm->maxi); i++)
151 items_this_message = clib_min (SIMPLE_COUNTER_BATCH_SIZE,
152 vec_len (cm->maxi) - i);
154 mp = vl_msg_api_alloc_as_if_client
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;
159 mp->first_sw_if_index = htonl (i);
161 vp = (u64 *) mp->data;
163 v = vlib_get_simple_counter (cm, i);
164 clib_mem_unaligned (vp, u64) = clib_host_to_net_u64 (v);
167 if (mp->count == items_this_message)
169 mp->count = htonl (items_this_message);
170 /* Send to the main thread... */
171 vl_msg_api_send_shmem (q, (u8 *) & mp);
177 vnet_interface_counter_unlock (im);
181 do_combined_interface_counters (stats_main_t * sm)
183 vl_api_vnet_interface_counters_t *mp = 0;
184 vnet_interface_main_t *im = sm->interface_main;
185 api_main_t *am = sm->api_main;
186 vl_shmem_hdr_t *shmem_hdr = am->shmem_hdr;
187 unix_shared_memory_queue_t *q = shmem_hdr->vl_input_queue;
188 vlib_combined_counter_main_t *cm;
189 u32 items_this_message = 0;
190 vlib_counter_t v, *vp = 0;
193 vnet_interface_counter_lock (im);
195 vec_foreach (cm, im->combined_sw_if_counters)
198 for (i = 0; i < vec_len (cm->maxi); i++)
202 items_this_message = clib_min (COMBINED_COUNTER_BATCH_SIZE,
203 vec_len (cm->maxi) - i);
205 mp = vl_msg_api_alloc_as_if_client
206 (sizeof (*mp) + items_this_message * sizeof (v));
207 mp->_vl_msg_id = ntohs (VL_API_VNET_INTERFACE_COUNTERS);
208 mp->vnet_counter_type = cm - im->combined_sw_if_counters;
210 mp->first_sw_if_index = htonl (i);
212 vp = (vlib_counter_t *) mp->data;
214 vlib_get_combined_counter (cm, i, &v);
215 clib_mem_unaligned (&vp->packets, u64)
216 = clib_host_to_net_u64 (v.packets);
217 clib_mem_unaligned (&vp->bytes, u64) = clib_host_to_net_u64 (v.bytes);
220 if (mp->count == items_this_message)
222 mp->count = htonl (items_this_message);
223 /* Send to the main thread... */
224 vl_msg_api_send_shmem (q, (u8 *) & mp);
230 vnet_interface_counter_unlock (im);
233 /* from .../vnet/vnet/ip/lookup.c. Yuck */
234 typedef CLIB_PACKED (struct
236 ip4_address_t address;
237 u32 address_length: 6;
242 ip46_fib_stats_delay (stats_main_t * sm, u32 sec, u32 nsec)
244 struct timespec _req, *req = &_req;
245 struct timespec _rem, *rem = &_rem;
251 if (nanosleep (req, rem) == 0)
256 clib_unix_warning ("nanosleep");
262 do_ip4_fibs (stats_main_t * sm)
264 ip4_main_t *im4 = &ip4_main;
265 api_main_t *am = sm->api_main;
266 vl_shmem_hdr_t *shmem_hdr = am->shmem_hdr;
267 unix_shared_memory_queue_t *q = shmem_hdr->vl_input_queue;
268 static ip4_route_t *routes;
271 ip_lookup_main_t *lm = &im4->lookup_main;
272 static uword *results;
273 vl_api_vnet_ip4_fib_counters_t *mp = 0;
274 u32 items_this_message;
275 vl_api_ip4_fib_counter_t *ctrp = 0;
276 u32 start_at_fib_index = 0;
281 pool_foreach (fib, im4->fibs,
283 /* We may have bailed out due to control-plane activity */
284 while ((fib - im4->fibs) < start_at_fib_index)
289 items_this_message = IP4_FIB_COUNTER_BATCH_SIZE;
290 mp = vl_msg_api_alloc_as_if_client
292 items_this_message * sizeof (vl_api_ip4_fib_counter_t));
293 mp->_vl_msg_id = ntohs (VL_API_VNET_IP4_FIB_COUNTERS);
295 mp->vrf_id = ntohl (fib->ft_table_id);
296 ctrp = (vl_api_ip4_fib_counter_t *) mp->c;
300 /* happens if the last FIB was empty... */
301 ASSERT (mp->count == 0);
302 mp->vrf_id = ntohl (fib->ft_table_id);
305 dslock (sm, 0 /* release hint */ , 1 /* tag */ );
307 vec_reset_length (routes);
308 vec_reset_length (results);
310 for (i = 0; i < ARRAY_LEN (fib->v4.fib_entry_by_dst_address); i++)
312 uword *hash = fib->v4.fib_entry_by_dst_address[i];
316 x.address_length = i;
318 hash_foreach_pair (p, hash,
320 x.address.data_u32 = p->key;
321 if (lm->fib_result_n_words > 1)
323 x.index = vec_len (results);
324 vec_add (results, p->value, lm->fib_result_n_words);
327 x.index = p->value[0];
329 vec_add1 (routes, x);
330 if (sm->data_structure_lock->release_hint)
332 start_at_fib_index = fib - im4->fibs;
334 ip46_fib_stats_delay (sm, 0 /* sec */,
335 STATS_RELEASE_DELAY_NS);
337 ctrp = (vl_api_ip4_fib_counter_t *)mp->c;
343 vec_foreach (r, routes)
347 vlib_get_combined_counter (&load_balance_main.lbm_to_counters,
351 * seen at least one packet, send it.
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);
364 if (mp->count == items_this_message)
366 mp->count = htonl (items_this_message);
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.
372 unix_shared_memory_queue_lock (q);
373 if (unix_shared_memory_queue_is_full (q))
376 vl_msg_api_send_shmem_nolock (q, (u8 *) & mp);
377 unix_shared_memory_queue_unlock (q);
379 ip46_fib_stats_delay (sm, 0 /* sec */ ,
380 STATS_RELEASE_DELAY_NS);
383 vl_msg_api_send_shmem_nolock (q, (u8 *) & mp);
384 unix_shared_memory_queue_unlock (q);
386 items_this_message = IP4_FIB_COUNTER_BATCH_SIZE;
387 mp = vl_msg_api_alloc_as_if_client
389 items_this_message * sizeof (vl_api_ip4_fib_counter_t));
390 mp->_vl_msg_id = ntohs (VL_API_VNET_IP4_FIB_COUNTERS);
392 mp->vrf_id = ntohl (fib->ft_table_id);
393 ctrp = (vl_api_ip4_fib_counter_t *) mp->c;
395 } /* for each (mp or single) adj */
396 if (sm->data_structure_lock->release_hint)
398 start_at_fib_index = fib - im4->fibs;
400 ip46_fib_stats_delay (sm, 0 /* sec */ , STATS_RELEASE_DELAY_NS);
402 ctrp = (vl_api_ip4_fib_counter_t *) mp->c;
405 } /* vec_foreach (routes) */
409 /* Flush any data from this fib */
412 mp->count = htonl (mp->count);
413 vl_msg_api_send_shmem (q, (u8 *) & mp);
419 /* If e.g. the last FIB had no reportable routes, free the buffer */
421 vl_msg_api_free (mp);
426 ip6_address_t address;
434 ip6_route_t **routep;
436 } add_routes_in_fib_arg_t;
439 add_routes_in_fib (BVT (clib_bihash_kv) * kvp, void *arg)
441 add_routes_in_fib_arg_t *ap = arg;
442 stats_main_t *sm = ap->sm;
444 if (sm->data_structure_lock->release_hint)
445 clib_longjmp (&sm->jmp_buf, 1);
447 if (kvp->key[2] >> 32 == ap->fib_index)
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;
460 do_ip6_fibs (stats_main_t * sm)
462 ip6_main_t *im6 = &ip6_main;
463 api_main_t *am = sm->api_main;
464 vl_shmem_hdr_t *shmem_hdr = am->shmem_hdr;
465 unix_shared_memory_queue_t *q = shmem_hdr->vl_input_queue;
466 static ip6_route_t *routes;
469 static uword *results;
470 vl_api_vnet_ip6_fib_counters_t *mp = 0;
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;
479 pool_foreach (fib, im6->fibs,
481 /* We may have bailed out due to control-plane activity */
482 while ((fib - im6->fibs) < start_at_fib_index)
487 items_this_message = IP6_FIB_COUNTER_BATCH_SIZE;
488 mp = vl_msg_api_alloc_as_if_client
490 items_this_message * sizeof (vl_api_ip6_fib_counter_t));
491 mp->_vl_msg_id = ntohs (VL_API_VNET_IP6_FIB_COUNTERS);
493 mp->vrf_id = ntohl (fib->ft_table_id);
494 ctrp = (vl_api_ip6_fib_counter_t *) mp->c;
497 dslock (sm, 0 /* release hint */ , 1 /* tag */ );
499 vec_reset_length (routes);
500 vec_reset_length (results);
502 a->fib_index = fib - im6->fibs;
506 if (clib_setjmp (&sm->jmp_buf, 0) == 0)
508 start_at_fib_index = fib - im6->fibs;
509 BV (clib_bihash_foreach_key_value_pair) (h, add_routes_in_fib, a);
514 ip46_fib_stats_delay (sm, 0 /* sec */ ,
515 STATS_RELEASE_DELAY_NS);
517 ctrp = (vl_api_ip6_fib_counter_t *) mp->c;
521 vec_foreach (r, routes)
525 vlib_get_combined_counter (&load_balance_main.lbm_to_counters,
529 * seen at least one packet, send it.
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);
542 if (mp->count == items_this_message)
544 mp->count = htonl (items_this_message);
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.
550 unix_shared_memory_queue_lock (q);
551 if (unix_shared_memory_queue_is_full (q))
554 vl_msg_api_send_shmem_nolock (q, (u8 *) & mp);
555 unix_shared_memory_queue_unlock (q);
557 ip46_fib_stats_delay (sm, 0 /* sec */ ,
558 STATS_RELEASE_DELAY_NS);
561 vl_msg_api_send_shmem_nolock (q, (u8 *) & mp);
562 unix_shared_memory_queue_unlock (q);
564 items_this_message = IP6_FIB_COUNTER_BATCH_SIZE;
565 mp = vl_msg_api_alloc_as_if_client
567 items_this_message * sizeof (vl_api_ip6_fib_counter_t));
568 mp->_vl_msg_id = ntohs (VL_API_VNET_IP6_FIB_COUNTERS);
570 mp->vrf_id = ntohl (fib->ft_table_id);
571 ctrp = (vl_api_ip6_fib_counter_t *) mp->c;
575 if (sm->data_structure_lock->release_hint)
577 start_at_fib_index = fib - im6->fibs;
579 ip46_fib_stats_delay (sm, 0 /* sec */ , STATS_RELEASE_DELAY_NS);
581 ctrp = (vl_api_ip6_fib_counter_t *) mp->c;
584 } /* vec_foreach (routes) */
588 /* Flush any data from this fib */
591 mp->count = htonl (mp->count);
592 vl_msg_api_send_shmem (q, (u8 *) & mp);
598 /* If e.g. the last FIB had no reportable routes, free the buffer */
600 vl_msg_api_free (mp);
604 stats_thread_fn (void *arg)
606 stats_main_t *sm = &stats_main;
607 vlib_worker_thread_t *w = (vlib_worker_thread_t *) arg;
608 vlib_thread_main_t *tm = vlib_get_thread_main ();
610 /* stats thread wants no signals. */
614 pthread_sigmask (SIG_SETMASK, &s, 0);
617 if (vec_len (tm->thread_prefix))
618 vlib_set_thread_name ((char *)
619 format (0, "%v_stats%c", tm->thread_prefix, '\0'));
621 clib_mem_set_heap (w->thread_mheap);
625 /* 10 second poll interval */
626 ip46_fib_stats_delay (sm, 10 /* secs */ , 0 /* nsec */ );
628 if (!(sm->enable_poller))
630 do_simple_interface_counters (sm);
631 do_combined_interface_counters (sm);
638 vl_api_vnet_interface_counters_t_handler (vl_api_vnet_interface_counters_t *
641 vpe_client_registration_t *reg;
642 stats_main_t *sm = &stats_main;
643 unix_shared_memory_queue_t *q, *q_prev = NULL;
644 vl_api_vnet_interface_counters_t *mp_copy = NULL;
649 u32 count, sw_if_index;
653 mp_size = sizeof (*mp) + (ntohl (mp->count) *
654 (mp->is_combined ? sizeof (vlib_counter_t) :
658 pool_foreach(reg, sm->stats_registrations,
660 q = vl_api_client_index_to_input_queue (reg->client_index);
663 if (q_prev && (q_prev->cursize < q_prev->maxsize))
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);
676 count = ntohl (mp->count);
677 sw_if_index = ntohl (mp->first_sw_if_index);
678 if (mp->is_combined == 0)
681 vp = (u64 *) mp->data;
683 switch (mp->vnet_counter_type)
685 case VNET_INTERFACE_COUNTER_DROP:
686 counter_name = "drop";
688 case VNET_INTERFACE_COUNTER_PUNT:
689 counter_name = "punt";
691 case VNET_INTERFACE_COUNTER_IP4:
692 counter_name = "ip4";
694 case VNET_INTERFACE_COUNTER_IP6:
695 counter_name = "ip6";
697 case VNET_INTERFACE_COUNTER_RX_NO_BUF:
698 counter_name = "rx-no-buff";
700 case VNET_INTERFACE_COUNTER_RX_MISS:
701 , counter_name = "rx-miss";
703 case VNET_INTERFACE_COUNTER_RX_ERROR:
704 , counter_name = "rx-error (fifo-full)";
706 case VNET_INTERFACE_COUNTER_TX_ERROR:
707 , counter_name = "tx-error (fifo-full)";
710 counter_name = "bogus";
713 for (i = 0; i < count; i++)
715 v = clib_mem_unaligned (vp, u64);
716 v = clib_net_to_host_u64 (v);
718 fformat (stdout, "%U.%s %lld\n", format_vnet_sw_if_index_name,
719 sm->vnet_main, sw_if_index, counter_name, v);
727 vp = (vlib_counter_t *) mp->data;
729 switch (mp->vnet_counter_type)
731 case VNET_INTERFACE_COUNTER_RX:
734 case VNET_INTERFACE_COUNTER_TX:
738 counter_name = "bogus";
741 for (i = 0; i < count; i++)
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);
748 fformat (stdout, "%U.%s.packets %lld\n",
749 format_vnet_sw_if_index_name,
750 sm->vnet_main, sw_if_index, counter_name, packets);
751 fformat (stdout, "%U.%s.bytes %lld\n",
752 format_vnet_sw_if_index_name,
753 sm->vnet_main, sw_if_index, counter_name, bytes);
758 if (q_prev && (q_prev->cursize < q_prev->maxsize))
760 vl_msg_api_send_shmem (q_prev, (u8 *) & mp);
764 vl_msg_api_free (mp);
769 vl_api_vnet_ip4_fib_counters_t_handler (vl_api_vnet_ip4_fib_counters_t * mp)
771 vpe_client_registration_t *reg;
772 stats_main_t *sm = &stats_main;
773 unix_shared_memory_queue_t *q, *q_prev = NULL;
774 vl_api_vnet_ip4_fib_counters_t *mp_copy = NULL;
777 mp_size = sizeof (*mp_copy) +
778 ntohl (mp->count) * sizeof (vl_api_ip4_fib_counter_t);
781 pool_foreach(reg, sm->stats_registrations,
783 q = vl_api_client_index_to_input_queue (reg->client_index);
786 if (q_prev && (q_prev->cursize < q_prev->maxsize))
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);
797 if (q_prev && (q_prev->cursize < q_prev->maxsize))
799 vl_msg_api_send_shmem (q_prev, (u8 *) & mp);
803 vl_msg_api_free (mp);
808 vl_api_vnet_ip6_fib_counters_t_handler (vl_api_vnet_ip6_fib_counters_t * mp)
810 vpe_client_registration_t *reg;
811 stats_main_t *sm = &stats_main;
812 unix_shared_memory_queue_t *q, *q_prev = NULL;
813 vl_api_vnet_ip6_fib_counters_t *mp_copy = NULL;
816 mp_size = sizeof (*mp_copy) +
817 ntohl (mp->count) * sizeof (vl_api_ip6_fib_counter_t);
820 pool_foreach(reg, sm->stats_registrations,
822 q = vl_api_client_index_to_input_queue (reg->client_index);
825 if (q_prev && (q_prev->cursize < q_prev->maxsize))
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);
836 if (q_prev && (q_prev->cursize < q_prev->maxsize))
838 vl_msg_api_send_shmem (q_prev, (u8 *) & mp);
842 vl_msg_api_free (mp);
847 vl_api_want_stats_reply_t_handler (vl_api_want_stats_reply_t * mp)
849 clib_warning ("BUG");
853 vl_api_want_stats_t_handler (vl_api_want_stats_t * mp)
855 stats_main_t *sm = &stats_main;
856 vpe_client_registration_t *rp;
857 vl_api_want_stats_reply_t *rmp;
860 unix_shared_memory_queue_t *q;
862 p = hash_get (sm->stats_registration_hash, mp->client_index);
865 if (mp->enable_disable)
867 clib_warning ("pid %d: already enabled...", mp->pid);
873 rp = pool_elt_at_index (sm->stats_registrations, p[0]);
874 pool_put (sm->stats_registrations, rp);
875 hash_unset (sm->stats_registration_hash, mp->client_index);
879 if (mp->enable_disable == 0)
881 clib_warning ("pid %d: already disabled...", mp->pid);
885 pool_get (sm->stats_registrations, rp);
886 rp->client_index = mp->client_index;
887 rp->client_pid = mp->pid;
888 hash_set (sm->stats_registration_hash, rp->client_index,
889 rp - sm->stats_registrations);
892 if (pool_elts (sm->stats_registrations))
893 sm->enable_poller = 1;
895 sm->enable_poller = 0;
897 q = vl_api_client_index_to_input_queue (mp->client_index);
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;
907 vl_msg_api_send_shmem (q, (u8 *) & rmp);
911 stats_memclnt_delete_callback (u32 client_index)
913 vpe_client_registration_t *rp;
914 stats_main_t *sm = &stats_main;
917 p = hash_get (sm->stats_registration_hash, client_index);
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);
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
933 static clib_error_t *
934 stats_init (vlib_main_t * vm)
936 stats_main_t *sm = &stats_main;
937 api_main_t *am = &api_main;
938 void *vlib_worker_thread_bootstrap_fn (void *arg);
941 sm->vnet_main = vnet_get_main ();
942 sm->interface_main = &vnet_get_main ()->interface_main;
944 sm->stats_poll_interval_in_seconds = 10;
945 sm->data_structure_lock =
946 clib_mem_alloc_aligned (sizeof (data_structure_lock_t),
947 CLIB_CACHE_LINE_BYTES);
948 memset (sm->data_structure_lock, 0, sizeof (*sm->data_structure_lock));
951 vl_msg_api_set_handlers(VL_API_##N, #n, \
952 vl_api_##n##_t_handler, \
954 vl_api_##n##_t_endian, \
955 vl_api_##n##_t_print, \
956 sizeof(vl_api_##n##_t), 0 /* do NOT trace! */);
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;
968 VLIB_INIT_FUNCTION (stats_init);
971 VLIB_REGISTER_THREAD (stats_thread_reg, static) = {
973 .function = stats_thread_fn,
976 .no_data_structure_clone = 1,
982 * fd.io coding-style-patch-verification: ON
985 * eval: (c-set-style "gnu")