+ start = vec_len (vlib_mains) > 1 ? 1 : 0;
+
+ for (i = start; i < vec_len (vlib_mains); i++)
+ {
+ this_vlib_main = vlib_mains[i];
+ vector_rate += vlib_last_vector_length_per_node (this_vlib_main);
+ }
+ vector_rate /= (f64) (i - start);
+
+ sm->directory_vector[STAT_COUNTER_VECTOR_RATE].value =
+ vector_rate / ((f64) (vec_len (vlib_mains) - start));
+
+ /*
+ * Compute the aggregate input rate
+ */
+ now = vlib_time_now (vm);
+ dt = now - sm->directory_vector[STAT_COUNTER_LAST_UPDATE].value;
+ input_packets = vnet_get_aggregate_rx_packets ();
+ sm->directory_vector[STAT_COUNTER_INPUT_RATE].value =
+ (f64) (input_packets - sm->last_input_packets) / dt;
+ sm->directory_vector[STAT_COUNTER_LAST_UPDATE].value = now;
+ sm->last_input_packets = input_packets;
+ sm->directory_vector[STAT_COUNTER_LAST_STATS_CLEAR].value =
+ vm->node_main.time_last_runtime_stats_clear;
+
+ if (sm->node_counters_enabled)
+ update_node_counters (sm);
+
+ /* Heartbeat, so clients detect we're still here */
+ sm->directory_vector[STAT_COUNTER_HEARTBEAT].value++;
+}
+
+/*
+ * Accept connection on the socket and exchange the fd for the shared
+ * memory segment.
+ */
+static clib_error_t *
+stats_socket_accept_ready (clib_file_t * uf)
+{
+ stat_segment_main_t *sm = &stat_segment_main;
+ clib_error_t *err;
+ clib_socket_t client = { 0 };
+
+ err = clib_socket_accept (sm->socket, &client);
+ if (err)
+ {
+ clib_error_report (err);
+ return err;
+ }
+
+ /* Send the fd across and close */
+ err = clib_socket_sendmsg (&client, 0, 0, &sm->memfd, 1);
+ if (err)
+ clib_error_report (err);
+ clib_socket_close (&client);
+
+ return 0;
+}
+
+static void
+stats_segment_socket_init (void)
+{
+ stat_segment_main_t *sm = &stat_segment_main;
+ clib_error_t *error;
+ clib_socket_t *s = clib_mem_alloc (sizeof (clib_socket_t));
+
+ s->config = (char *) sm->socket_name;
+ s->flags = CLIB_SOCKET_F_IS_SERVER | CLIB_SOCKET_F_SEQPACKET |
+ CLIB_SOCKET_F_ALLOW_GROUP_WRITE | CLIB_SOCKET_F_PASSCRED;
+ if ((error = clib_socket_init (s)))
+ {
+ clib_error_report (error);
+ return;
+ }
+
+ clib_file_t template = { 0 };
+ template.read_function = stats_socket_accept_ready;
+ template.file_descriptor = s->fd;
+ template.description =
+ format (0, "stats segment listener %s", STAT_SEGMENT_SOCKET_FILE);
+ clib_file_add (&file_main, &template);
+
+ sm->socket = s;
+}
+
+static uword
+stat_segment_collector_process (vlib_main_t * vm, vlib_node_runtime_t * rt,
+ vlib_frame_t * f)
+{
+ stat_segment_main_t *sm = &stat_segment_main;
+
+ /* Wait for Godot... */
+ f64 sleep_duration = 10;