- return is_ip4 ?
- format (s, "%U", format_ip4_address, &ip46->ip4) :
- format (s, "%U", format_ip6_address, &ip46->ip6);
-}
-
-static void
-vl_api_accept_session_t_handler (vl_api_accept_session_t * mp)
-{
- vl_api_accept_session_reply_t *rmp;
- svm_fifo_t *rx_fifo, *tx_fifo;
- session_t *session;
- u32 session_index;
- int rv = 0;
-
- if (!clib_fifo_free_elts (vcm->client_session_index_fifo))
- {
- clib_warning ("[%d] client session queue is full!", getpid ());
- rv = VNET_API_ERROR_QUEUE_FULL;
- goto send_reply;
- }
-
- if (VPPCOM_DEBUG > 1)
- {
- u8 *ip_str = format (0, "%U", format_ip46_address, &mp->ip, mp->is_ip4);
- clib_warning ("[%d] accepted session from: %s:%d", getpid (), ip_str,
- clib_net_to_host_u16 (mp->port));
- vec_free (ip_str);
- }
-
- clib_spinlock_lock (&vcm->sessions_lockp);
- /* Allocate local session and set it up */
- pool_get (vcm->sessions, session);
- memset (session, 0, sizeof (*session));
- session_index = session - vcm->sessions;
-
- rx_fifo = uword_to_pointer (mp->server_rx_fifo, svm_fifo_t *);
- rx_fifo->client_session_index = session_index;
- tx_fifo = uword_to_pointer (mp->server_tx_fifo, svm_fifo_t *);
- tx_fifo->client_session_index = session_index;
-
- session->server_rx_fifo = rx_fifo;
- session->server_tx_fifo = tx_fifo;
- session->vpp_event_queue = uword_to_pointer (mp->vpp_event_queue_address,
- unix_shared_memory_queue_t *);
- session->state = STATE_ACCEPT;
- session->is_cut_thru = 0;
- session->is_server = 1;
- session->peer_port = mp->port;
- session->peer_addr.is_ip4 = mp->is_ip4;
- clib_memcpy (&session->peer_addr.ip46, mp->ip,
- sizeof (session->peer_addr.ip46));
-
- /* Add it to lookup table */
- hash_set (vcm->session_index_by_vpp_handles, mp->handle, session_index);
-
- clib_fifo_add1 (vcm->client_session_index_fifo, session_index);
- clib_spinlock_unlock (&vcm->sessions_lockp);
-
- /*
- * Send accept reply to vpp
- */
-send_reply:
- rmp = vl_msg_api_alloc (sizeof (*rmp));
- memset (rmp, 0, sizeof (*rmp));
- rmp->_vl_msg_id = ntohs (VL_API_ACCEPT_SESSION_REPLY);
- rmp->retval = htonl (rv);
- rmp->handle = mp->handle;
- vl_msg_api_send_shmem (vcm->vl_input_queue, (u8 *) & rmp);
-}
-
-/*
- * Acting as server for redirected connect requests
- */
-static void
-vl_api_connect_sock_t_handler (vl_api_connect_sock_t * mp)
-{
- static svm_fifo_segment_create_args_t _a;
- svm_fifo_segment_create_args_t *a = &_a;
- u32 session_index;
- svm_fifo_segment_private_t *seg;
- unix_shared_memory_queue_t *client_q;
- vl_api_connect_session_reply_t *rmp;
- session_t *session = 0;
- int rv = 0;
- svm_fifo_t *rx_fifo;
- svm_fifo_t *tx_fifo;
- unix_shared_memory_queue_t *event_q = 0;
-
- clib_spinlock_lock (&vcm->sessions_lockp);
- if (!clib_fifo_free_elts (vcm->client_session_index_fifo))
- {
- if (VPPCOM_DEBUG > 1)
- clib_warning ("[%d] client session queue is full!", getpid ());
- rv = VNET_API_ERROR_QUEUE_FULL;
- clib_spinlock_unlock (&vcm->sessions_lockp);
- goto send_reply;
- }
-
- /* Create the segment */
- memset (a, 0, sizeof (*a));
- a->segment_name = (char *) format ((u8 *) a->segment_name, "%d:segment%d%c",
- getpid (), vcm->unique_segment_index++,
- 0);
- a->segment_size = vcm->cfg.segment_size;
- a->preallocated_fifo_pairs = vcm->cfg.preallocated_fifo_pairs;
- a->rx_fifo_size = vcm->cfg.rx_fifo_size;
- a->tx_fifo_size = vcm->cfg.tx_fifo_size;
-
- rv = svm_fifo_segment_create (a);
- if (PREDICT_FALSE (rv))
- {
- if (VPPCOM_DEBUG > 1)
- clib_warning ("[%d] svm_fifo_segment_create ('%s') failed",
- getpid (), a->segment_name);
- vec_reset_length (a->new_segment_indices);
- rv = VNET_API_ERROR_URI_FIFO_CREATE_FAILED;
- goto send_reply;
- }
-
- if (VPPCOM_DEBUG > 1)
- clib_warning ("[%d] created segment '%s'", getpid (), a->segment_name);
-
- pool_get (vcm->sessions, session);
- memset (session, 0, sizeof (*session));
- session_index = session - vcm->sessions;
-
- session->sm_seg_index = a->new_segment_indices[0];
- vec_reset_length (a->new_segment_indices);
-
- seg = svm_fifo_segment_get_segment (session->sm_seg_index);
- rx_fifo = session->server_rx_fifo =
- svm_fifo_segment_alloc_fifo (seg, vcm->cfg.rx_fifo_size,
- FIFO_SEGMENT_RX_FREELIST);
- if (PREDICT_FALSE (!session->server_rx_fifo))
- {
- svm_fifo_segment_delete (seg);
- clib_warning ("[%d] rx fifo alloc failed, size %ld (0x%lx)",
- getpid (), vcm->cfg.rx_fifo_size, vcm->cfg.rx_fifo_size);
- rv = VNET_API_ERROR_URI_FIFO_CREATE_FAILED;
- clib_spinlock_unlock (&vcm->sessions_lockp);
- goto send_reply;
- }
-
- tx_fifo = session->server_tx_fifo =
- svm_fifo_segment_alloc_fifo (seg, vcm->cfg.tx_fifo_size,
- FIFO_SEGMENT_TX_FREELIST);
- if (PREDICT_FALSE (!session->server_tx_fifo))
- {
- svm_fifo_segment_delete (seg);
- if (VPPCOM_DEBUG > 1)
- clib_warning ("[%d] tx fifo alloc failed, size %ld (0x%lx)",
- getpid (), vcm->cfg.tx_fifo_size,
- vcm->cfg.tx_fifo_size);
- rv = VNET_API_ERROR_URI_FIFO_CREATE_FAILED;
- clib_spinlock_unlock (&vcm->sessions_lockp);
- goto send_reply;
- }
-
- session->server_rx_fifo->master_session_index = session_index;
- session->server_tx_fifo->master_session_index = session_index;
- session->client_queue_address = mp->client_queue_address;
- session->is_cut_thru = 1;
- session->is_server = 1;
- session->peer_port = mp->port;
- session->peer_addr.is_ip4 = mp->is_ip4;
- clib_memcpy (&session->peer_addr.ip46, mp->ip,
- sizeof (session->peer_addr.ip46));
- {
- void *oldheap;
- ssvm_shared_header_t *sh = seg->ssvm.sh;
-
- ssvm_lock_non_recursive (sh, 1);
- oldheap = ssvm_push_heap (sh);
- event_q = session->vpp_event_queue =
- unix_shared_memory_queue_init (vcm->cfg.event_queue_size,
- sizeof (session_fifo_event_t),
- getpid (), 0 /* signal not sent */ );
- ssvm_pop_heap (oldheap);
- ssvm_unlock_non_recursive (sh);
- }
-
- session->state = STATE_ACCEPT;
- clib_fifo_add1 (vcm->client_session_index_fifo, session_index);
- if (VPPCOM_DEBUG > 1)
- clib_warning
- ("[%d] Connected cut-thru to client: sid %d, clib_fifo_elts %u!",
- getpid (), session_index,
- clib_fifo_elts (vcm->client_session_index_fifo));
- clib_spinlock_unlock (&vcm->sessions_lockp);
-
-send_reply:
- rmp = vl_msg_api_alloc (sizeof (*rmp));
- memset (rmp, 0, sizeof (*rmp));
-
- rmp->_vl_msg_id = ntohs (VL_API_CONNECT_SESSION_REPLY);
- rmp->context = mp->context;
- rmp->retval = htonl (rv);
- rmp->segment_name_length = vec_len (a->segment_name);
- clib_memcpy (rmp->segment_name, a->segment_name, vec_len (a->segment_name));
- vec_reset_length (a->segment_name);
-
- if (event_q)
- {
- rmp->vpp_event_queue_address = pointer_to_uword (event_q);
- rmp->server_rx_fifo = pointer_to_uword (rx_fifo);
- rmp->server_tx_fifo = pointer_to_uword (tx_fifo);
- }
- client_q =
- uword_to_pointer (mp->client_queue_address, unix_shared_memory_queue_t *);
-
- ASSERT (client_q);
- vl_msg_api_send_shmem (client_q, (u8 *) & rmp);
-}
-
-static void
-vppcom_send_bind_sock (session_t * session)
-{
- vl_api_bind_sock_t *bmp;
-
- /* Assumes caller has acquired spinlock: vcm->sessions_lockp */
- session->is_server = 1;
- bmp = vl_msg_api_alloc (sizeof (*bmp));
- memset (bmp, 0, sizeof (*bmp));
-
- bmp->_vl_msg_id = ntohs (VL_API_BIND_SOCK);
- bmp->client_index = vcm->my_client_index;
- bmp->context = htonl (0xfeedface);
- bmp->vrf = session->vrf;
- bmp->is_ip4 = session->lcl_addr.is_ip4;
- clib_memcpy (bmp->ip, &session->lcl_addr.ip46, sizeof (bmp->ip));
- bmp->port = session->lcl_port;
- bmp->proto = session->proto;
- clib_memcpy (bmp->options, session->options, sizeof (bmp->options));
- vl_msg_api_send_shmem (vcm->vl_input_queue, (u8 *) & bmp);
-}
-
-static void
-vppcom_send_unbind_sock (u32 session_index)
-{
- vl_api_unbind_sock_t *ump;
- session_t *session = 0;
- int rv;
-
- clib_spinlock_lock (&vcm->sessions_lockp);
- rv = vppcom_session_at_index (session_index, &session);
- if (PREDICT_FALSE (rv))
- {
- clib_spinlock_unlock (&vcm->sessions_lockp);
- if (VPPCOM_DEBUG > 0)
- clib_warning ("[%d] invalid session, sid (%u) has been closed!",
- getpid (), session_index);
- return;
- }
-
- ump = vl_msg_api_alloc (sizeof (*ump));
- memset (ump, 0, sizeof (*ump));
-
- ump->_vl_msg_id = ntohs (VL_API_UNBIND_SOCK);
- ump->client_index = vcm->my_client_index;
- ump->handle = session->vpp_session_handle;
- clib_spinlock_unlock (&vcm->sessions_lockp);
- vl_msg_api_send_shmem (vcm->vl_input_queue, (u8 *) & ump);
-}
-
-static int
-vppcom_session_unbind_cut_thru (session_t * session)
-{
- svm_fifo_segment_main_t *sm = &svm_fifo_segment_main;
- svm_fifo_segment_private_t *seg;
- int rv = VPPCOM_OK;
-
- seg = vec_elt_at_index (sm->segments, session->sm_seg_index);
- svm_fifo_segment_free_fifo (seg, session->server_rx_fifo,
- FIFO_SEGMENT_RX_FREELIST);
- svm_fifo_segment_free_fifo (seg, session->server_tx_fifo,
- FIFO_SEGMENT_TX_FREELIST);
- svm_fifo_segment_delete (seg);
-
- return rv;
-}
-
-static int
-vppcom_session_unbind (u32 session_index)
-{
- int rv;
-
- clib_spinlock_lock (&vcm->sessions_lockp);
- if (PREDICT_FALSE (pool_is_free_index (vcm->sessions, session_index)))
- {
- clib_spinlock_unlock (&vcm->sessions_lockp);
- if (VPPCOM_DEBUG > 1)
- clib_warning ("[%d] invalid session, sid (%u) has been closed!",
- getpid (), session_index);
- return VPPCOM_EBADFD;
- }
- clib_spinlock_unlock (&vcm->sessions_lockp);
-
- vcm->bind_session_index = session_index;
- vppcom_send_unbind_sock (session_index);
- rv = vppcom_wait_for_session_state_change (session_index, STATE_START,
- vcm->cfg.session_timeout);
- if (PREDICT_FALSE (rv))
- {
- vcm->bind_session_index = ~0;
- if (VPPCOM_DEBUG > 0)
- clib_warning ("[%d] server unbind timed out, rv = %s (%d)",
- getpid (), vppcom_retval_str (rv), rv);
- return rv;
- }
- return VPPCOM_OK;
-}
-
-static inline int
-vppcom_session_disconnect (u32 session_index)
-{
- int rv;
- session_t *session;
-
- clib_spinlock_lock (&vcm->sessions_lockp);
- rv = vppcom_session_at_index (session_index, &session);
- if (PREDICT_FALSE (rv))
- {
- clib_spinlock_unlock (&vcm->sessions_lockp);
- if (VPPCOM_DEBUG > 1)
- clib_warning ("[%d] invalid session, sid (%u) has been closed!",
- getpid (), session_index);
- return rv;
- }
-
- if (!session->is_cut_thru)
- {
- vppcom_send_disconnect (session);
- clib_spinlock_unlock (&vcm->sessions_lockp);
-
- rv = vppcom_wait_for_session_state_change (session_index,
- STATE_DISCONNECT, 1.0);
- if ((VPPCOM_DEBUG > 0) && (rv < 0))
- clib_warning ("[%d] disconnect (session %d) failed, rv = %s (%d)",
- getpid (), session_index, vppcom_retval_str (rv), rv);
- }
- else
- clib_spinlock_unlock (&vcm->sessions_lockp);
-
- return VPPCOM_OK;
-}
-
-#define foreach_sock_msg \
-_(SESSION_ENABLE_DISABLE_REPLY, session_enable_disable_reply) \
-_(BIND_SOCK_REPLY, bind_sock_reply) \
-_(UNBIND_SOCK_REPLY, unbind_sock_reply) \
-_(ACCEPT_SESSION, accept_session) \
-_(CONNECT_SOCK, connect_sock) \
-_(CONNECT_SESSION_REPLY, connect_session_reply) \
-_(DISCONNECT_SESSION, disconnect_session) \
-_(DISCONNECT_SESSION_REPLY, disconnect_session_reply) \
-_(RESET_SESSION, reset_session) \
-_(APPLICATION_ATTACH_REPLY, application_attach_reply) \
-_(APPLICATION_DETACH_REPLY, application_detach_reply) \
-_(MAP_ANOTHER_SEGMENT, map_another_segment)
-
-static void
-vppcom_api_hookup (void)
-{
-#define _(N,n) \
- vl_msg_api_set_handlers(VL_API_##N, #n, \
- vl_api_##n##_t_handler, \
- vl_noop_handler, \
- vl_api_##n##_t_endian, \
- vl_api_##n##_t_print, \
- sizeof(vl_api_##n##_t), 1);
- foreach_sock_msg;
-#undef _
-}
-
-static void
-vppcom_cfg_init (vppcom_cfg_t * vcl_cfg)
-{
- ASSERT (vcl_cfg);
-
- vcl_cfg->heapsize = (256ULL << 20);
- vcl_cfg->segment_baseva = 0x200000000ULL;
- vcl_cfg->segment_size = (256 << 20);
- vcl_cfg->add_segment_size = (128 << 20);
- vcl_cfg->preallocated_fifo_pairs = 8;
- vcl_cfg->rx_fifo_size = (1 << 20);
- vcl_cfg->tx_fifo_size = (1 << 20);
- vcl_cfg->event_queue_size = 2048;
- vcl_cfg->listen_queue_size = CLIB_CACHE_LINE_BYTES / sizeof (u32);
- vcl_cfg->app_timeout = 10 * 60.0;
- vcl_cfg->session_timeout = 10 * 60.0;
- vcl_cfg->accept_timeout = 60.0;
-}
-
-static void
-vppcom_cfg_heapsize (char *conf_fname)
-{
- vppcom_cfg_t *vcl_cfg = &vcm->cfg;
- FILE *fp;
- char inbuf[4096];
- int argc = 1;
- char **argv = NULL;
- char *arg = NULL;
- char *p;
- int i;
- u8 *sizep;
- u32 size;
- void *vcl_mem;
- void *heap;
-
- fp = fopen (conf_fname, "r");
- if (fp == NULL)
- {
- if (VPPCOM_DEBUG > 0)
- fprintf (stderr, "open configuration file '%s' failed\n", conf_fname);
- goto defaulted;
- }
- argv = calloc (1, sizeof (char *));
- if (argv == NULL)
- goto defaulted;
-
- while (1)
- {
- if (fgets (inbuf, 4096, fp) == 0)
- break;
- p = strtok (inbuf, " \t\n");
- while (p != NULL)
- {
- if (*p == '#')
- break;
- argc++;
- char **tmp = realloc (argv, argc * sizeof (char *));
- if (tmp == NULL)
- goto defaulted;
- argv = tmp;
- arg = strndup (p, 1024);
- if (arg == NULL)
- goto defaulted;
- argv[argc - 1] = arg;
- p = strtok (NULL, " \t\n");
- }
- }