21 #include <arpa/inet.h> 34 #include <vapi/memclnt.api.vapi.h> 137 VAPI_DBG (
"stored@%d: context:%x (start is @%d)", requests_end, context,
144 struct to_be_freed_s;
148 struct to_be_freed_s *next;
151 static struct to_be_freed_s *to_be_freed =
NULL;
154 vapi_add_to_be_freed (
void *
v)
156 struct to_be_freed_s *prev =
NULL;
157 struct to_be_freed_s *tmp;
159 while (tmp && tmp->v)
168 tmp = to_be_freed = calloc (1,
sizeof (*to_be_freed));
172 tmp = prev->next = calloc (1,
sizeof (*to_be_freed));
180 vapi_trace_free (
void *v)
182 struct to_be_freed_s *tmp = to_be_freed;
183 while (tmp && tmp->v != v)
187 if (tmp && tmp->v == v)
194 VAPI_ERR (
"Trying to free untracked pointer %p", v);
200 vapi_to_be_freed_validate ()
202 struct to_be_freed_s *tmp = to_be_freed;
207 VAPI_ERR (
"Unfreed msg %p!", tmp->v);
234 vapi_trace_free (msg);
259 malloc (__vapi_metadata.count *
300 const char *chroot_prefix,
301 int max_outstanding_requests,
305 if (response_queue_size <= 0 || max_outstanding_requests <= 0)
315 void *tmp = realloc (ctx->
requests, size);
326 VAPI_DBG (
"set memory root path `%s'", chroot_prefix);
329 static char api_map[] =
"/vpe-api";
330 VAPI_DBG (
"client api map `%s'", api_map);
335 VAPI_DBG (
"connect client `%s'", name);
341 #if VAPI_DEBUG_CONNECT 342 VAPI_DBG (
"start probing messages");
346 for (i = 0; i < __vapi_metadata.count; ++
i)
356 VAPI_ERR (
"Returned vl_msg_id `%u' > UINT16MAX `%u'!",
id,
377 #if VAPI_DEBUG_CONNECT 388 #if VAPI_DEBUG_CONNECT 389 VAPI_DBG (
"finished probing messages");
395 (
"control ping or control ping reply not available, cannot connect");
426 vapi_to_be_freed_validate ();
450 unsigned msgid = be16toh (*(
u16 *) msg);
454 if (
id < __vapi_metadata.count)
456 VAPI_DBG (
"send msg@%p:%u[%s]", msg, msgid,
457 __vapi_metadata.msgs[
id]->name);
461 VAPI_DBG (
"send msg@%p:%u[UNKNOWN]", msg, msgid);
466 VAPI_DBG (
"send msg@%p:%u[UNKNOWN]", msg, msgid);
476 VAPI_DBG (
"vapi_send() rv = %d", rv);
484 if (!ctx || !msg1 || !msg2 || !ctx->
connected)
491 unsigned msgid1 = be16toh (*(
u16 *) msg1);
492 unsigned msgid2 = be16toh (*(
u16 *) msg2);
493 const char *name1 =
"UNKNOWN";
494 const char *name2 =
"UNKNOWN";
498 if (
id < __vapi_metadata.count)
500 name1 = __vapi_metadata.msgs[
id]->name;
503 if (msgid2 <= ctx->vl_msg_id_max)
506 if (
id < __vapi_metadata.count)
508 name2 = __vapi_metadata.msgs[
id]->name;
511 VAPI_DBG (
"send two: %u[%s], %u[%s]", msgid1, name1, msgid2, name2);
520 VAPI_DBG (
"vapi_send() rv = %d", rv);
528 if (!ctx || !ctx->
connected || !msg || !msg_size)
550 vapi_add_to_be_freed ((
void *) data);
560 *msg_size = ntohl (msgbuf->
data_len);
562 unsigned msgid = be16toh (*(
u16 *) * msg);
566 if (
id < __vapi_metadata.count)
568 VAPI_DBG (
"recv msg@%p:%u[%s]", *msg, msgid,
569 __vapi_metadata.msgs[
id]->name);
573 VAPI_DBG (
"recv msg@%p:%u[UNKNOWN]", *msg, msgid);
578 VAPI_DBG (
"recv msg@%p:%u[UNKNOWN]", *msg, msgid);
583 unsigned msgid = be16toh (*(
u16 *) * msg);
587 vapi_msg_memclnt_keepalive_reply *reply =
NULL;
594 reply->header._vl_msg_id =
596 vapi_msg_id_memclnt_keepalive_reply);
597 reply->payload.retval = 0;
598 vapi_msg_memclnt_keepalive_reply_hton (reply);
601 VAPI_DBG (
"autohandled memclnt_keepalive");
621 u32 context,
void *msg)
626 VAPI_DBG (
"pthread_mutex_lock() failed, rv=%d:%s", mrv, strerror (mrv));
647 VAPI_ERR (
"No response to req with context=%u",
665 void *payload = ((
u8 *) msg) + payload_offset;
669 if (vapi_msg_id_control_ping_reply ==
id)
678 if (payload_offset != -1)
705 VAPI_DBG (
"after dispatch, req start = %d, end = %d, count = %d",
710 VAPI_DBG (
"pthread_mutex_unlock() failed, rv=%d:%s", mrv,
731 (
"No handler/generic handler for msg id %u[%s], message ignored",
732 (
unsigned)
id, __vapi_metadata.msgs[
id]->name);
740 assert (
id <= __vapi_metadata.count);
741 return __vapi_metadata.msgs[
id]->has_context;
753 VAPI_DBG (
"vapi_recv failed with rv=%d", rv);
756 u16 vpp_id = be16toh (*(
u16 *) msg);
759 VAPI_ERR (
"Unknown msg ID received, id `%u', out of range <0,%u>",
766 VAPI_ERR (
"Unknown msg ID received, id `%u' marked as not supported",
773 if (size < expect_size)
776 (
"Invalid msg received, unexpected size `%zu' < expected min `%zu'",
787 VAPI_DBG (
"dispatch, context is %x", context);
788 if (context & context_counter_mask)
822 c->
ctx = callback_ctx;
849 assert (
id < __vapi_metadata.count);
874 assert (
id < __vapi_metadata.count);
875 return __vapi_metadata.msgs[
id]->payload_offset;
880 assert (
id < __vapi_metadata.count);
881 return __vapi_metadata.msgs[
id]->swap_to_host;
886 assert (
id < __vapi_metadata.count);
887 return __vapi_metadata.msgs[
id]->swap_to_be;
893 assert (
id < __vapi_metadata.count);
894 return __vapi_metadata.msgs[
id]->size;
900 assert (
id < __vapi_metadata.count);
901 return __vapi_metadata.msgs[
id]->context_offset;
908 for (i = 0; i < __vapi_metadata.count; ++
i)
911 (msg->
name_with_crc, __vapi_metadata.msgs[i]->name_with_crc))
916 msg->
id = __vapi_metadata.msgs[
i]->id;
921 ++__vapi_metadata.count;
922 __vapi_metadata.msgs =
923 realloc (__vapi_metadata.msgs,
924 sizeof (*__vapi_metadata.msgs) * __vapi_metadata.count);
925 __vapi_metadata.msgs[
id] = msg;
927 if (s > __vapi_metadata.max_len_name_with_crc)
929 __vapi_metadata.max_len_name_with_crc = s;
941 VAPI_DBG (
"pthread_mutex_lock() failed, rv=%d:%s", mrv, strerror (mrv));
954 VAPI_DBG (
"pthread_mutex_unlock() failed, rv=%d:%s", mrv,
965 return __vapi_metadata.count;
971 return __vapi_metadata.msgs[
id]->name;
failure manipulating internal mutex(es)
operations block until response received
int svm_queue_add(svm_queue_t *q, u8 *elem, int nowait)
size_t vapi_get_message_count()
Fixed length block allocator.
int my_client_index
All VLIB-side message handlers use my_client_index to identify the queue / client.
vapi_error_e(* cb)(vapi_ctx_t ctx, void *callback_ctx, vapi_msg_id_t id, void *payload)
vapi_error_e vapi_recv(vapi_ctx_t ctx, void **msg, size_t *msg_size, svm_q_conditional_wait_t cond, u32 time)
low-level api for reading messages from vpp
vapi_error_e vapi_send(vapi_ctx_t ctx, void *msg)
low-level api for sending messages to vpp
vapi_error_e vapi_connect(vapi_ctx_t ctx, const char *name, const char *chroot_prefix, int max_outstanding_requests, int response_queue_size, vapi_mode_e mode, bool handle_keepalives)
connect to vpp
svm_queue_t * vl_input_queue
Peer input queue pointer.
void * vapi_msg_alloc(vapi_ctx_t ctx, size_t size)
allocate vapi message of given size
void vapi_store_request(vapi_ctx_t ctx, u32 context, bool is_dump, vapi_cb_t callback, void *callback_ctx)
vapi_msg_id_t * vl_msg_id_to_vapi_msg_t
void vl_client_api_unmap(void)
int our_pid
Current process PID.
vapi_msg_id_t vapi_register_msg(vapi_message_desc_t *msg)
memset(h->entries, 0, sizeof(h->entries[0])*entries)
vapi_error_e(* vapi_generic_event_cb)(vapi_ctx_t ctx, void *callback_ctx, vapi_msg_id_t id, void *msg)
generic vapi event callback
vapi_error_e vapi_send2(vapi_ctx_t ctx, void *msg1, void *msg2)
low-level api for atomically sending two messages to vpp - either both messages are sent or neither o...
size_t vapi_get_message_size(vapi_msg_id_t id)
int svm_queue_sub(svm_queue_t *q, u8 *elem, svm_q_conditional_wait_t cond, u32 time)
fundamental incompatibility while connecting to vpp (control ping/control ping reply mismatch) ...
size_t vapi_get_request_count(vapi_ctx_t ctx)
vapi_error_e vapi_disconnect(vapi_ctx_t ctx)
disconnect from vpp
static vapi_error_e vapi_dispatch_event(vapi_ctx_t ctx, vapi_msg_id_t id, void *msg)
bool vapi_is_nonblocking(vapi_ctx_t ctx)
struct vl_shmem_hdr_ * shmem_hdr
Binary API shared-memory segment header pointer.
vapi_message_desc_t ** msgs
#define VAPI_INVALID_MSG_ID
int vapi_get_payload_offset(vapi_msg_id_t id)
size_t vapi_get_context_offset(vapi_msg_id_t id)
vapi_event_cb_with_ctx * event_cbs
int svm_queue_add2(svm_queue_t *q, u8 *elem, u8 *elem2, int nowait)
size_t vapi_get_max_request_count(vapi_ctx_t ctx)
void vl_set_memory_root_path(const char *name)
vapi_msg_id_t vapi_msg_id_control_ping_reply
int vl_client_connect(const char *name, int ctx_quota, int input_queue_size)
const char * vapi_get_msg_name(vapi_msg_id_t id)
const char * name_with_crc
u32 vapi_gen_req_context(vapi_ctx_t ctx)
void vapi_set_generic_event_cb(vapi_ctx_t ctx, vapi_generic_event_cb callback, void *callback_ctx)
set generic event callback
bool vapi_requests_empty(vapi_ctx_t ctx)
void(*)(void *msg) vapi_get_swap_to_host_func(vapi_msg_id_t id)
void(*)(void *msg) vapi_get_swap_to_be_func(vapi_msg_id_t id)
invalid value encountered
static void * clib_mem_get_per_cpu_heap(void)
common vpp api C declarations
size_t max_len_name_with_crc
vapi_error_e vapi_dispatch(vapi_ctx_t ctx)
loop vapi_dispatch_one until responses to all currently outstanding requests have been received and t...
failure while mapping api
vapi_error_e(* vapi_cb_t)(struct vapi_ctx_s *, void *, vapi_error_e, bool, void *)
API main structure, used by both vpp and binary API clients.
void * clib_mem_init(void *heap, uword size)
bool vapi_msg_is_with_context(vapi_msg_id_t id)
static vapi_error_e vapi_dispatch_response(vapi_ctx_t ctx, vapi_msg_id_t id, u32 context, void *msg)
vapi_msg_id_t vapi_lookup_vapi_msg_id_t(vapi_ctx_t ctx, u16 vl_msg_id)
u32 vl_msg_api_get_msg_index(u8 *name_and_crc)
struct vapi_ctx_s * vapi_ctx_t
int vl_client_api_map(const char *region_name)
static const u32 context_counter_mask
blocking call - best used in combination with condvars, for eventfds we don't yield the cpu ...
pthread_mutex_t requests_mutex
internal vpp api C declarations
svm_queue_t * vl_input_queue
vapi_msg_id_t vapi_msg_id_control_ping
u16 vapi_lookup_vl_msg_id(vapi_ctx_t ctx, vapi_msg_id_t id)
bool vapi_is_msg_available(vapi_ctx_t ctx, vapi_msg_id_t id)
check if message identified by it's message id is known by the vpp to which the connection is open ...
u32 data_len
message length not including header
Message header structure.
DEFINE_VAPI_MSG_IDS_MEMCLNT_API_JSON
int vapi_get_client_index(vapi_ctx_t ctx)
void vl_msg_api_free(void *)
void vapi_ctx_free(vapi_ctx_t ctx)
free vapi context
void vapi_clear_generic_event_cb(vapi_ctx_t ctx)
clear generic event callback
vapi_error_e(* vapi_event_cb)(vapi_ctx_t ctx, void *callback_ctx, void *payload)
generic vapi event callback
vapi_error_e vapi_dispatch_one(vapi_ctx_t ctx)
pick next message sent by vpp and call the appropriate callback
vapi_error_e vapi_producer_unlock(vapi_ctx_t ctx)
int vl_client_disconnect(void)
bool vapi_requests_full(vapi_ctx_t ctx)
vapi_error_e vapi_get_fd(vapi_ctx_t ctx, int *fd)
get event file descriptor
struct _svm_queue svm_queue_t
vapi_error_e(* cb)(vapi_ctx_t ctx, void *callback_ctx, void *payload)
void vapi_msg_free(vapi_ctx_t ctx, void *msg)
free a vapi message
vapi_error_e vapi_producer_lock(vapi_ctx_t ctx)
u16 * vapi_msg_id_t_to_vl_msg_id
vapi_error_e vapi_ctx_alloc(vapi_ctx_t *result)
allocate vapi context
void * vl_msg_api_alloc_or_null(int nbytes)
unsigned int vapi_msg_id_t
void vapi_set_event_cb(vapi_ctx_t ctx, vapi_msg_id_t id, vapi_event_cb callback, void *callback_ctx)
set event callback to call when message with given id is dispatched
void vapi_clear_event_cb(vapi_ctx_t ctx, vapi_msg_id_t id)
clear event callback for given message id
vapi_generic_cb_with_ctx generic_cb
static int vapi_requests_end(vapi_ctx_t ctx)
vapi_error_e vapi_wait(vapi_ctx_t ctx, vapi_wait_mode_e mode)
wait for connection to become readable or writable
failure while connecting to vpp