+static void
+ vl_api_want_interface_simple_stats_t_handler
+ (vl_api_want_interface_simple_stats_t * mp)
+{
+ stats_main_t *sm = &stats_main;
+ vpe_client_stats_registration_t *rp;
+ vl_api_want_interface_simple_stats_reply_t *rmp;
+ uword *p;
+ i32 retval = 0;
+ unix_shared_memory_queue_t *q;
+
+ p = hash_get (sm->stats_registration_hash, mp->client_index);
+
+ /* Disable case */
+ if (mp->enable_disable == 0)
+ {
+ if (!p) // No client to disable
+ {
+ clib_warning ("pid %d: already disabled for stats...", mp->pid);
+ retval = 0;
+ goto reply;
+ }
+
+ rp = pool_elt_at_index (sm->stats_registrations, p[0]);
+ if (!rp->stats_registrations & INTERFACE_SIMPLE_COUNTERS) // Client but doesn't want this.
+ {
+ clib_warning
+ ("pid %d: already disabled for interface simple stats...",
+ mp->pid);
+ retval = 0;
+ goto reply;
+ }
+ else
+ {
+ rp->stats_registrations &= ~(INTERFACE_SIMPLE_COUNTERS); // Clear flag
+ if (rp->stats_registrations == 0) // Client isn't listening to anything else
+ {
+ pool_put (sm->stats_registrations, rp);
+ hash_unset (sm->stats_registration_hash, mp->client_index);
+ }
+ goto reply;
+ }
+ }
+ /* Enable case */
+ /* Get client from pool */
+ if (p)
+ rp = pool_elt_at_index (sm->stats_registrations, p[0]);
+
+ if (!p || !rp) // Doesn't exist, make a new entry
+ {
+ pool_get (sm->stats_registrations, rp);
+ rp->client.client_index = mp->client_index;
+ rp->client.client_pid = mp->pid;
+ }
+ rp->stats_registrations |= INTERFACE_SIMPLE_COUNTERS;
+ hash_set (sm->stats_registration_hash, rp->client.client_index,
+ rp - sm->stats_registrations);
+
+reply:
+ if (pool_elts (sm->stats_registrations)) // Someone wants something, somewhere so enable globally for now.
+ sm->enable_poller = 1;
+ else
+ sm->enable_poller = 0;
+
+ q = vl_api_client_index_to_input_queue (mp->client_index);
+
+ if (!q)
+ return;
+
+ rmp = vl_msg_api_alloc (sizeof (*rmp));
+ rmp->_vl_msg_id = ntohs (VL_API_WANT_INTERFACE_SIMPLE_STATS_REPLY);
+ rmp->context = mp->context;
+ rmp->retval = retval;
+
+ vl_msg_api_send_shmem (q, (u8 *) & rmp);
+}
+
+static void
+ vl_api_want_interface_combined_stats_t_handler
+ (vl_api_want_interface_combined_stats_t * mp)
+{
+ stats_main_t *sm = &stats_main;
+ vpe_client_stats_registration_t *rp;
+ vl_api_want_interface_combined_stats_reply_t *rmp;
+ uword *p;
+ i32 retval = 0;
+ unix_shared_memory_queue_t *q;
+
+ p = hash_get (sm->stats_registration_hash, mp->client_index);
+
+ /* Disable case */
+ if (mp->enable_disable == 0)
+ {
+ if (!p) // No client to disable
+ {
+ clib_warning ("pid %d: already disabled for stats...", mp->pid);
+ retval = 0;
+ goto reply;
+ }
+
+ rp = pool_elt_at_index (sm->stats_registrations, p[0]);
+ if (!rp->stats_registrations & INTERFACE_COMBINED_COUNTERS) // Client but doesn't want this.
+ {
+ clib_warning
+ ("pid %d: already disabled for interface COMBINED stats...",
+ mp->pid);
+ retval = 0;
+ goto reply;
+ }
+ else
+ {
+ rp->stats_registrations &= ~(INTERFACE_COMBINED_COUNTERS); // Clear flag
+ if (rp->stats_registrations == 0) // Client isn't listening to anything else
+ {
+ pool_put (sm->stats_registrations, rp);
+ hash_unset (sm->stats_registration_hash, mp->client_index);
+ }
+ goto reply;
+ }
+ }
+ /* Enable case */
+ /* Get client from pool */
+ if (p)
+ rp = pool_elt_at_index (sm->stats_registrations, p[0]);
+
+ if (!p || !rp) // Doesn't exist, make a new entry
+ {
+ pool_get (sm->stats_registrations, rp);
+ rp->client.client_index = mp->client_index;
+ rp->client.client_pid = mp->pid;
+ }
+ rp->stats_registrations |= INTERFACE_COMBINED_COUNTERS;
+ hash_set (sm->stats_registration_hash, rp->client.client_index,
+ rp - sm->stats_registrations);
+
+reply:
+ if (pool_elts (sm->stats_registrations)) // Someone wants something, somewhere so enable globally for now.
+ sm->enable_poller = 1;
+ else
+ sm->enable_poller = 0;
+
+ q = vl_api_client_index_to_input_queue (mp->client_index);
+
+ if (!q)
+ return;
+
+ rmp = vl_msg_api_alloc (sizeof (*rmp));
+ rmp->_vl_msg_id = ntohs (VL_API_WANT_INTERFACE_COMBINED_STATS_REPLY);
+ rmp->context = mp->context;
+ rmp->retval = retval;
+
+ vl_msg_api_send_shmem (q, (u8 *) & rmp);
+}
+
+static void
+vl_api_want_ip4_fib_stats_t_handler (vl_api_want_ip4_fib_stats_t * mp)
+{
+ stats_main_t *sm = &stats_main;
+ vpe_client_stats_registration_t *rp;
+ vl_api_want_ip4_fib_stats_reply_t *rmp;
+ uword *p;
+ i32 retval = 0;
+ unix_shared_memory_queue_t *q;
+
+ p = hash_get (sm->stats_registration_hash, mp->client_index);
+
+ /* Disable case */
+ /*
+ $$$ FIXME: need std return codes. Still undecided if enabling already
+ enabled (and similar for disabled) is really a -'ve error condition or
+ if 0 is sufficient
+ */
+ if (mp->enable_disable == 0)
+ {
+ if (!p) // No client to disable
+ {
+ clib_warning ("pid %d: already disabled for stats...", mp->pid);
+ retval = -3;
+ goto reply;
+ }
+
+ rp = pool_elt_at_index (sm->stats_registrations, p[0]);
+ if (!rp->stats_registrations & IP4_FIB_COUNTERS) // Client but doesn't want this.
+ {
+ clib_warning ("pid %d: already disabled for interface ip4 fib...",
+ mp->pid);
+ retval = -2;
+ goto reply;
+ }
+ else
+ {
+ rp->stats_registrations &= ~(IP4_FIB_COUNTERS); // Clear flag
+ if (rp->stats_registrations == 0) // Client isn't listening to anything else
+ {
+ pool_put (sm->stats_registrations, rp);
+ hash_unset (sm->stats_registration_hash, mp->client_index);
+ }
+ goto reply;
+ }
+ }
+ /* Enable case */
+ /* Get client from pool */
+ if (p)
+ rp = pool_elt_at_index (sm->stats_registrations, p[0]);
+
+ if (!p || !rp) // Doesn't exist, make a new entry
+ {
+ pool_get (sm->stats_registrations, rp);
+ rp->client.client_index = mp->client_index;
+ rp->client.client_pid = mp->pid;
+ }
+ rp->stats_registrations |= IP4_FIB_COUNTERS;
+ hash_set (sm->stats_registration_hash, rp->client.client_index,
+ rp - sm->stats_registrations);
+
+reply:
+ if (pool_elts (sm->stats_registrations)) // Someone wants something, somewhere so enable globally for now.
+ sm->enable_poller = 1;
+ else
+ sm->enable_poller = 0;
+
+ q = vl_api_client_index_to_input_queue (mp->client_index);
+
+ if (!q)
+ return;
+
+ rmp = vl_msg_api_alloc (sizeof (*rmp));
+ rmp->_vl_msg_id = ntohs (VL_API_WANT_IP4_FIB_STATS_REPLY);
+ rmp->context = mp->context;
+ rmp->retval = retval;
+
+ vl_msg_api_send_shmem (q, (u8 *) & rmp);
+}
+
+static void
+vl_api_want_ip6_fib_stats_t_handler (vl_api_want_ip6_fib_stats_t * mp)
+{
+ stats_main_t *sm = &stats_main;
+ vpe_client_stats_registration_t *rp;
+ vl_api_want_ip6_fib_stats_reply_t *rmp;
+ uword *p;
+ i32 retval = 0;
+ unix_shared_memory_queue_t *q;
+
+ p = hash_get (sm->stats_registration_hash, mp->client_index);
+
+ /* Disable case */
+ /*
+ $$$ FIXME: need std return codes. Still undecided if enabling already
+ enabled (and similar for disabled) is really a -'ve error condition or
+ if 0 is sufficient
+ */
+ if (mp->enable_disable == 0)
+ {
+ if (!p) // No client to disable
+ {
+ clib_warning ("pid %d: already disabled for stats...", mp->pid);
+ retval = -3;
+ goto reply;
+ }
+
+ rp = pool_elt_at_index (sm->stats_registrations, p[0]);
+ if (!rp->stats_registrations & IP6_FIB_COUNTERS) // Client but doesn't want this.
+ {
+ clib_warning ("pid %d: already disabled for interface ip6 fib...",
+ mp->pid);
+ retval = -2;
+ goto reply;
+ }
+ else
+ {
+ rp->stats_registrations &= ~(IP6_FIB_COUNTERS); // Clear flag
+ if (rp->stats_registrations == 0) // Client isn't listening to anything else
+ {
+ pool_put (sm->stats_registrations, rp);
+ hash_unset (sm->stats_registration_hash, mp->client_index);
+ }
+ goto reply;
+ }
+ }
+ /* Enable case */
+ /* Get client from pool */
+ if (p)
+ rp = pool_elt_at_index (sm->stats_registrations, p[0]);
+
+ if (!p || !rp) // Doesn't exist, make a new entry
+ {
+ pool_get (sm->stats_registrations, rp);
+ rp->client.client_index = mp->client_index;
+ rp->client.client_pid = mp->pid;
+ }
+ rp->stats_registrations |= IP6_FIB_COUNTERS;
+ hash_set (sm->stats_registration_hash, rp->client.client_index,
+ rp - sm->stats_registrations);
+
+reply:
+ if (pool_elts (sm->stats_registrations)) // Someone wants something, somewhere so enable globally for now.
+ sm->enable_poller = 1;
+ else
+ sm->enable_poller = 0;
+
+ q = vl_api_client_index_to_input_queue (mp->client_index);
+
+ if (!q)
+ return;
+
+ rmp = vl_msg_api_alloc (sizeof (*rmp));
+ rmp->_vl_msg_id = ntohs (VL_API_WANT_IP6_FIB_STATS_REPLY);
+ rmp->context = mp->context;
+ rmp->retval = retval;
+
+ vl_msg_api_send_shmem (q, (u8 *) & rmp);
+}
+
+/* FIXME - NBR stats broken - this will be fixed in subsequent patch */
+static void
+vl_api_want_ip4_nbr_stats_t_handler (vl_api_want_ip4_nbr_stats_t * mp)
+{
+}
+
+static void
+vl_api_want_ip6_nbr_stats_t_handler (vl_api_want_ip6_nbr_stats_t * mp)
+{
+}
+
+static void
+vl_api_vnet_get_summary_stats_t_handler (vl_api_vnet_get_summary_stats_t * mp)
+{
+ stats_main_t *sm = &stats_main;
+ vnet_interface_main_t *im = sm->interface_main;
+ vl_api_vnet_get_summary_stats_reply_t *rmp;
+ vlib_combined_counter_main_t *cm;
+ vlib_counter_t v;
+ int i, which;
+ u64 total_pkts[VLIB_N_RX_TX];
+ u64 total_bytes[VLIB_N_RX_TX];
+
+ unix_shared_memory_queue_t *q =
+ vl_api_client_index_to_input_queue (mp->client_index);
+
+ if (!q)
+ return;
+
+ rmp = vl_msg_api_alloc (sizeof (*rmp));
+ rmp->_vl_msg_id = ntohs (VL_API_VNET_GET_SUMMARY_STATS_REPLY);
+ rmp->context = mp->context;
+ rmp->retval = 0;
+
+ memset (total_pkts, 0, sizeof (total_pkts));
+ memset (total_bytes, 0, sizeof (total_bytes));
+
+ vnet_interface_counter_lock (im);
+
+ vec_foreach (cm, im->combined_sw_if_counters)
+ {
+ which = cm - im->combined_sw_if_counters;
+
+ for (i = 0; i < vlib_combined_counter_n_counters (cm); i++)
+ {
+ vlib_get_combined_counter (cm, i, &v);
+ total_pkts[which] += v.packets;
+ total_bytes[which] += v.bytes;
+ }
+ }
+ vnet_interface_counter_unlock (im);
+
+ rmp->total_pkts[VLIB_RX] = clib_host_to_net_u64 (total_pkts[VLIB_RX]);
+ rmp->total_bytes[VLIB_RX] = clib_host_to_net_u64 (total_bytes[VLIB_RX]);
+ rmp->total_pkts[VLIB_TX] = clib_host_to_net_u64 (total_pkts[VLIB_TX]);
+ rmp->total_bytes[VLIB_TX] = clib_host_to_net_u64 (total_bytes[VLIB_TX]);
+ rmp->vector_rate =
+ clib_host_to_net_u64 (vlib_last_vector_length_per_node (sm->vlib_main));
+
+ vl_msg_api_send_shmem (q, (u8 *) & rmp);
+}
+