}
}
-int vl_msg_api_version_check (vl_api_memclnt_create_t * mp)
- __attribute__ ((weak));
-
-int
-vl_msg_api_version_check (vl_api_memclnt_create_t * mp)
+u8 *
+vl_api_serialize_message_table (api_main_t * am, u8 * vector)
{
- return 0;
+ serialize_main_t _sm, *sm = &_sm;
+ hash_pair_t *hp;
+ u32 nmsg = hash_elts (am->msg_index_by_name_and_crc);
+
+ serialize_open_vector (sm, vector);
+
+ /* serialize the count */
+ serialize_integer (sm, nmsg, sizeof (u32));
+
+ hash_foreach_pair (hp, am->msg_index_by_name_and_crc, (
+ {
+ serialize_likely_small_unsigned_integer
+ (sm, hp->value[0]);
+ serialize_cstring
+ (sm,
+ (char *) hp->key);
+ }));
+
+ return serialize_close_vector (sm);
}
/*
vl_api_memclnt_create_reply_t *rp;
svm_region_t *svm;
unix_shared_memory_queue_t *q;
- int rv;
+ int rv = 0;
void *oldheap;
api_main_t *am = &api_main;
-
- /* Indicate API version mismatch if appropriate */
- rv = vl_msg_api_version_check (mp);
+ u8 *serialized_message_table = 0;
/*
* This is tortured. Maintain a vlib-address-space private
svm = am->vlib_rp;
+ if (am->serialized_message_table_in_shmem == 0)
+ serialized_message_table = vl_api_serialize_message_table (am, 0);
+
pthread_mutex_lock (&svm->mutex);
oldheap = svm_push_data_heap (svm);
*regpp = clib_mem_alloc (sizeof (vl_api_registration_t));
regp->name = format (0, "%s", mp->name);
vec_add1 (regp->name, 0);
+ if (serialized_message_table)
+ am->serialized_message_table_in_shmem =
+ vec_dup (serialized_message_table);
pthread_mutex_unlock (&svm->mutex);
svm_pop_heap (oldheap);
+ vec_free (serialized_message_table);
+
rp = vl_msg_api_alloc (sizeof (*rp));
rp->_vl_msg_id = ntohs (VL_API_MEMCLNT_CREATE_REPLY);
rp->handle = (uword) regp;
am->shmem_hdr->application_restarts);
rp->context = mp->context;
rp->response = ntohl (rv);
+ rp->message_table = (u64) am->serialized_message_table_in_shmem;
vl_msg_api_send_shmem (q, (u8 *) & rp);
}
/* *INDENT-OFF* */
VLIB_CLI_COMMAND (cli_show_api_histogram_command, static) = {
- .path = "show api histogram",
- .short_help = "show api histogram",
- .function = vl_api_show_histogram_command,
+ .path = "show api histogram",
+ .short_help = "show api histogram",
+ .function = vl_api_show_histogram_command,
};
/* *INDENT-ON* */
return 0;
}
+static clib_error_t *
+vl_api_status_command (vlib_main_t * vm,
+ unformat_input_t * input, vlib_cli_command_t * cli_cmd)
+{
+ api_main_t *am = &api_main;
+
+ // check if rx_trace and tx_trace are not null pointers
+
+ if (am->rx_trace == 0)
+ {
+ vlib_cli_output (vm, "RX Trace disabled\n");
+ }
+ else
+ {
+ if (am->rx_trace->enabled == 0)
+ vlib_cli_output (vm, "RX Trace disabled\n");
+ else
+ vlib_cli_output (vm, "RX Trace enabled\n");
+ }
+
+ if (am->tx_trace == 0)
+ {
+ vlib_cli_output (vm, "TX Trace disabled\n");
+ }
+ else
+ {
+ if (am->tx_trace->enabled == 0)
+ vlib_cli_output (vm, "TX Trace disabled\n");
+ else
+ vlib_cli_output (vm, "TX Trace enabled\n");
+ }
+
+ return 0;
+}
+
/* *INDENT-OFF* */
VLIB_CLI_COMMAND (cli_show_api_command, static) = {
.path = "show api",
};
/* *INDENT-ON* */
+/* *INDENT-OFF* */
+VLIB_CLI_COMMAND (cli_show_api_status_command, static) = {
+ .path = "show api status",
+ .short_help = "Show API trace status",
+ .function = vl_api_status_command,
+};
+/* *INDENT-ON* */
+
static clib_error_t *
vl_api_message_table_command (vlib_main_t * vm,
unformat_input_t * input,
vlibmemory_init (vlib_main_t * vm)
{
api_main_t *am = &api_main;
- /* Normally NULL / 0, set by cmd line "api-segment" */
- svm_region_init_chroot_uid_gid (am->root_path, am->api_uid, am->api_gid);
+ svm_map_region_args_t _a, *a = &_a;
+
+ memset (a, 0, sizeof (*a));
+ a->root_path = am->root_path;
+ a->name = SVM_GLOBAL_REGION_NAME;
+ a->baseva = (am->global_baseva != 0) ?
+ am->global_baseva : SVM_GLOBAL_REGION_BASEVA;
+ a->size = (am->global_size != 0) ? am->global_size : SVM_GLOBAL_REGION_SIZE;
+ a->flags = SVM_FLAGS_NODATA;
+ a->uid = am->api_uid;
+ a->gid = am->api_gid;
+ a->pvt_heap_size =
+ (am->global_pvt_heap_size !=
+ 0) ? am->global_pvt_heap_size : SVM_PVT_MHEAP_SIZE;
+
+ svm_region_init_args (a);
return 0;
}
vl_api_rpc_call_t *mp;
api_main_t *am = &api_main;
vl_shmem_hdr_t *shmem_hdr = am->shmem_hdr;
+ unix_shared_memory_queue_t *q;
+
+ /* Main thread: call the function directly */
+ if (os_get_cpu_number () == 0)
+ {
+ vlib_main_t *vm = vlib_get_main ();
+ void (*call_fp) (void *);
+ vlib_worker_thread_barrier_sync (vm);
+
+ call_fp = fp;
+ call_fp (data);
+
+ vlib_worker_thread_barrier_release (vm);
+ return;
+ }
+
+ /* Any other thread, actually do an RPC call... */
mp = vl_msg_api_alloc_as_if_client (sizeof (*mp) + data_length);
+
memset (mp, 0, sizeof (*mp));
clib_memcpy (mp->data, data, data_length);
mp->_vl_msg_id = ntohs (VL_API_RPC_CALL);
mp->function = pointer_to_uword (fp);
mp->need_barrier_sync = 1;
- /* Use the "normal" control-plane mechanism for the main thread */
- vl_msg_api_send_shmem (shmem_hdr->vl_input_queue, (u8 *) & mp);
+ /*
+ * Use the "normal" control-plane mechanism for the main thread.
+ * Well, almost. if the main input queue is full, we cannot
+ * block. Otherwise, we can expect a barrier sync timeout.
+ */
+ q = shmem_hdr->vl_input_queue;
+
+ while (pthread_mutex_trylock (&q->mutex))
+ vlib_worker_thread_barrier_check ();
+
+ while (PREDICT_FALSE (unix_shared_memory_queue_is_full (q)))
+ {
+ pthread_mutex_unlock (&q->mutex);
+ vlib_worker_thread_barrier_check ();
+ while (pthread_mutex_trylock (&q->mutex))
+ vlib_worker_thread_barrier_check ();
+ }
+
+ vl_msg_api_send_shmem_nolock (q, (u8 *) & mp);
+
+ pthread_mutex_unlock (&q->mutex);
}
#define foreach_rpc_api_msg \