#include <vlibapi/api_common.h>
#include <vlibmemory/memory_client.h>
+#include <vapi/memclnt.api.vapi.h>
+#include <vapi/vlib.api.vapi.h>
+
/* we need to use control pings for some stuff and because we're forced to put
* the code in headers, we need a way to be able to grab the ids of these
* messages - so declare them here as extern */
vapi_msg_id_t vapi_msg_id_control_ping = 0;
vapi_msg_id_t vapi_msg_id_control_ping_reply = 0;
+DEFINE_VAPI_MSG_IDS_MEMCLNT_API_JSON;
+DEFINE_VAPI_MSG_IDS_VLIB_API_JSON;
+
struct
{
size_t count;
u16 vl_msg_id_max;
vapi_msg_id_t *vl_msg_id_to_vapi_msg_t;
bool connected;
+ bool handle_keepalives;
pthread_mutex_t requests_mutex;
};
return NULL;
}
void *rv = vl_msg_api_alloc_or_null (size);
+ if (rv)
+ {
+ clib_memset (rv, 0, size);
+ }
return rv;
}
{
return ctx->vl_msg_id_to_vapi_msg_t[vl_msg_id];
}
- return INVALID_MSG_ID;
+ return VAPI_INVALID_MSG_ID;
}
vapi_error_e
{
goto fail;
}
+ clib_memset (ctx->vapi_msg_id_t_to_vl_msg_id, ~0,
+ __vapi_metadata.count *
+ sizeof (*ctx->vapi_msg_id_t_to_vl_msg_id));
ctx->event_cbs = calloc (__vapi_metadata.count, sizeof (*ctx->event_cbs));
if (!ctx->event_cbs)
{
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)
+ int response_queue_size, vapi_mode_e mode,
+ bool handle_keepalives)
{
if (response_queue_size <= 0 || max_outstanding_requests <= 0)
{
return VAPI_EINVAL;
}
+ if (!clib_mem_get_per_cpu_heap () && !clib_mem_init (0, 1024 * 1024 * 32))
+ {
+ return VAPI_ENOMEM;
+ }
ctx->requests_size = max_outstanding_requests;
const size_t size = ctx->requests_size * sizeof (*ctx->requests);
void *tmp = realloc (ctx->requests, size);
return VAPI_ENOMEM;
}
ctx->requests = tmp;
- memset (ctx->requests, 0, size);
+ clib_memset (ctx->requests, 0, size);
/* coverity[MISSING_LOCK] - 177211 requests_mutex is not needed here */
ctx->requests_start = ctx->requests_count = 0;
if (chroot_prefix)
u8 scratch[m->name_with_crc_len + 1];
memcpy (scratch, m->name_with_crc, m->name_with_crc_len + 1);
u32 id = vl_msg_api_get_msg_index (scratch);
- if (INVALID_MSG_ID != id)
+ if (VAPI_INVALID_MSG_ID != id)
{
if (id > UINT16_MAX)
{
}
ctx->mode = mode;
ctx->connected = true;
+ if (vapi_is_msg_available (ctx, vapi_msg_id_memclnt_keepalive))
+ {
+ ctx->handle_keepalives = handle_keepalives;
+ }
+ else
+ {
+ ctx->handle_keepalives = false;
+ }
return VAPI_OK;
fail:
vl_client_disconnect ();
goto out;
}
int tmp;
- svm_queue_t *q = api_main.shmem_hdr->vl_input_queue;
+ svm_queue_t *q = vlibapi_get_main ()->shmem_hdr->vl_input_queue;
#if VAPI_DEBUG
unsigned msgid = be16toh (*(u16 *) msg);
if (msgid <= ctx->vl_msg_id_max)
{
rv = VAPI_EAGAIN;
}
+ else
+ VL_MSG_API_POISON (msg);
out:
VAPI_DBG ("vapi_send() rv = %d", rv);
return rv;
rv = VAPI_EINVAL;
goto out;
}
- svm_queue_t *q = api_main.shmem_hdr->vl_input_queue;
+ svm_queue_t *q = vlibapi_get_main ()->shmem_hdr->vl_input_queue;
#if VAPI_DEBUG
unsigned msgid1 = be16toh (*(u16 *) msg1);
unsigned msgid2 = be16toh (*(u16 *) msg2);
{
rv = VAPI_EAGAIN;
}
+ else
+ VL_MSG_API_POISON (msg1);
out:
VAPI_DBG ("vapi_send() rv = %d", rv);
return rv;
return VAPI_EINVAL;
}
vapi_error_e rv = VAPI_OK;
- api_main_t *am = &api_main;
+ api_main_t *am = vlibapi_get_main ();
uword data;
if (am->our_pid == 0)
}
svm_queue_t *q = am->vl_input_queue;
+again:
VAPI_DBG ("doing shm queue sub");
int tmp = svm_queue_sub (q, (u8 *) & data, cond, time);
if (tmp == 0)
{
+ VL_MSG_API_UNPOISON ((void *) data);
#if VAPI_DEBUG_ALLOC
vapi_add_to_be_freed ((void *) data);
#endif
VAPI_DBG ("recv msg@%p:%u[UNKNOWN]", *msg, msgid);
}
#endif
+ if (ctx->handle_keepalives)
+ {
+ unsigned msgid = be16toh (*(u16 *) * msg);
+ if (msgid ==
+ vapi_lookup_vl_msg_id (ctx, vapi_msg_id_memclnt_keepalive))
+ {
+ vapi_msg_memclnt_keepalive_reply *reply = NULL;
+ do
+ {
+ reply = vapi_msg_alloc (ctx, sizeof (*reply));
+ }
+ while (!reply);
+ reply->header.context = vapi_get_client_index (ctx);
+ reply->header._vl_msg_id =
+ vapi_lookup_vl_msg_id (ctx,
+ vapi_msg_id_memclnt_keepalive_reply);
+ reply->payload.retval = 0;
+ vapi_msg_memclnt_keepalive_reply_hton (reply);
+ while (VAPI_EAGAIN == vapi_send (ctx, reply));
+ vapi_msg_free (ctx, *msg);
+ VAPI_DBG ("autohandled memclnt_keepalive");
+ goto again;
+ }
+ }
}
else
{
{
VAPI_ERR ("No response to req with context=%u",
(unsigned) ctx->requests[tmp].context);
- ctx->requests[ctx->requests_start].callback (ctx,
- ctx->requests
+ ctx->requests[ctx->requests_start].callback (ctx, ctx->requests
[ctx->
requests_start].callback_ctx,
VAPI_ENORESP, true,
NULL);
- memset (&ctx->requests[ctx->requests_start], 0,
- sizeof (ctx->requests[ctx->requests_start]));
+ clib_memset (&ctx->requests[ctx->requests_start], 0,
+ sizeof (ctx->requests[ctx->requests_start]));
++ctx->requests_start;
--ctx->requests_count;
if (ctx->requests_start == ctx->requests_size)
}
if (is_last)
{
- memset (&ctx->requests[ctx->requests_start], 0,
- sizeof (ctx->requests[ctx->requests_start]));
+ clib_memset (&ctx->requests[ctx->requests_start], 0,
+ sizeof (ctx->requests[ctx->requests_start]));
++ctx->requests_start;
--ctx->requests_count;
if (ctx->requests_start == ctx->requests_size)
return __vapi_metadata.msgs[id]->has_context;
}
+static int
+vapi_verify_msg_size (vapi_msg_id_t id, void *buf, uword buf_size)
+{
+ assert (id < __vapi_metadata.count);
+ return __vapi_metadata.msgs[id]->verify_msg_size (buf, buf_size);
+}
+
vapi_error_e
vapi_dispatch_one (vapi_ctx_t ctx)
{
VAPI_DBG ("vapi_dispatch_one()");
void *msg;
- size_t size;
- vapi_error_e rv = vapi_recv (ctx, &msg, &size, SVM_Q_WAIT, 0);
+ uword size;
+ svm_q_conditional_wait_t cond =
+ vapi_is_nonblocking (ctx) ? SVM_Q_NOWAIT : SVM_Q_WAIT;
+ vapi_error_e rv = vapi_recv (ctx, &msg, &size, cond, 0);
if (VAPI_OK != rv)
{
VAPI_DBG ("vapi_recv failed with rv=%d", rv);
vapi_msg_free (ctx, msg);
return VAPI_EINVAL;
}
- if (INVALID_MSG_ID == (unsigned) ctx->vl_msg_id_to_vapi_msg_t[vpp_id])
+ if (VAPI_INVALID_MSG_ID == (unsigned) ctx->vl_msg_id_to_vapi_msg_t[vpp_id])
{
VAPI_ERR ("Unknown msg ID received, id `%u' marked as not supported",
(unsigned) vpp_id);
return VAPI_EINVAL;
}
const vapi_msg_id_t id = ctx->vl_msg_id_to_vapi_msg_t[vpp_id];
- const size_t expect_size = vapi_get_message_size (id);
- if (size < expect_size)
+ if (vapi_verify_msg_size (id, msg, size))
{
- VAPI_ERR
- ("Invalid msg received, unexpected size `%zu' < expected min `%zu'",
- size, expect_size);
vapi_msg_free (ctx, msg);
return VAPI_EINVAL;
}
int
vapi_get_client_index (vapi_ctx_t ctx)
{
- return api_main.my_client_index;
+ return vlibapi_get_main ()->my_client_index;
}
bool
return __vapi_metadata.msgs[id]->swap_to_be;
}
-size_t
-vapi_get_message_size (vapi_msg_id_t id)
-{
- assert (id < __vapi_metadata.count);
- return __vapi_metadata.msgs[id]->size;
-}
-
size_t
vapi_get_context_offset (vapi_msg_id_t id)
{