- VCL_LOCK_AND_GET_SESSION (session_index, &session);
-done:
- if (mp->retval)
- {
- clib_warning ("[%d] ERROR: vpp handle 0x%llx, sid %u: bind failed: %U",
- getpid (), mp->handle, session_index, format_api_error,
- ntohl (mp->retval));
- rv = vppcom_session_at_index (session_index, &session);
- if (rv == VPPCOM_OK)
- {
- session->state = STATE_FAILED;
- session->vpp_handle = mp->handle;
- }
- else
- {
- clib_warning ("[%s] ERROR: vpp handle 0x%llx, sid %u: "
- "Invalid session index (%u)!",
- getpid (), mp->handle, session_index);
- }
- goto done_unlock;
- }
-
- session->vpp_handle = mp->handle;
- session->lcl_addr.is_ip4 = mp->lcl_is_ip4;
- clib_memcpy (&session->lcl_addr.ip46, mp->lcl_ip,
- sizeof (session->peer_addr.ip46));
- session->lcl_port = mp->lcl_port;
- vppcom_session_table_add_listener (mp->handle, session_index);
- session->is_listen = 1;
- session->state = STATE_LISTEN;
-
- if (VPPCOM_DEBUG > 1)
- clib_warning ("[%d] vpp handle 0x%llx, sid %u: bind succeeded!",
- getpid (), mp->handle, mp->context);
-done_unlock:
- clib_spinlock_unlock (&vcm->sessions_lockp);
-}
-
-static void
-vl_api_unbind_sock_reply_t_handler (vl_api_unbind_sock_reply_t * mp)
-{
- if (mp->retval)
- clib_warning ("[%d] ERROR: sid %u: unbind failed: %U",
- getpid (), mp->context, format_api_error,
- ntohl (mp->retval));
-
- else if (VPPCOM_DEBUG > 1)
- clib_warning ("[%d] sid %u: unbind succeeded!", getpid (), mp->context);
-}
-
-u8 *
-format_ip4_address (u8 * s, va_list * args)
-{
- u8 *a = va_arg (*args, u8 *);
- return format (s, "%d.%d.%d.%d", a[0], a[1], a[2], a[3]);
-}
-
-u8 *
-format_ip6_address (u8 * s, va_list * args)
-{
- ip6_address_t *a = va_arg (*args, ip6_address_t *);
- u32 i, i_max_n_zero, max_n_zeros, i_first_zero, n_zeros, last_double_colon;
-
- i_max_n_zero = ARRAY_LEN (a->as_u16);
- max_n_zeros = 0;
- i_first_zero = i_max_n_zero;
- n_zeros = 0;
- for (i = 0; i < ARRAY_LEN (a->as_u16); i++)
- {
- u32 is_zero = a->as_u16[i] == 0;
- if (is_zero && i_first_zero >= ARRAY_LEN (a->as_u16))
- {
- i_first_zero = i;
- n_zeros = 0;
- }
- n_zeros += is_zero;
- if ((!is_zero && n_zeros > max_n_zeros)
- || (i + 1 >= ARRAY_LEN (a->as_u16) && n_zeros > max_n_zeros))
- {
- i_max_n_zero = i_first_zero;
- max_n_zeros = n_zeros;
- i_first_zero = ARRAY_LEN (a->as_u16);
- n_zeros = 0;
- }
- }
-
- last_double_colon = 0;
- for (i = 0; i < ARRAY_LEN (a->as_u16); i++)
- {
- if (i == i_max_n_zero && max_n_zeros > 1)
- {
- s = format (s, "::");
- i += max_n_zeros - 1;
- last_double_colon = 1;
- }
- else
- {
- s = format (s, "%s%x",
- (last_double_colon || i == 0) ? "" : ":",
- clib_net_to_host_u16 (a->as_u16[i]));
- last_double_colon = 0;
- }
- }
-
- return s;
-}
-
-/* Format an IP46 address. */
-u8 *
-format_ip46_address (u8 * s, va_list * args)
-{
- ip46_address_t *ip46 = va_arg (*args, ip46_address_t *);
- ip46_type_t type = va_arg (*args, ip46_type_t);
- int is_ip4 = 1;
-
- switch (type)
- {
- case IP46_TYPE_ANY:
- is_ip4 = ip46_address_is_ip4 (ip46);
- break;
- case IP46_TYPE_IP4:
- is_ip4 = 1;
- break;
- case IP46_TYPE_IP6:
- is_ip4 = 0;
- break;
- }
-
- return is_ip4 ?
- format (s, "%U", format_ip4_address, &ip46->ip4) :
- format (s, "%U", format_ip6_address, &ip46->ip6);
-}
-
-static inline void
-vppcom_send_accept_session_reply (u64 handle, u32 context, int retval)
-{
- vl_api_accept_session_reply_t *rmp;
-
- 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 (retval);
- rmp->context = context;
- rmp->handle = handle;
- vl_msg_api_send_shmem (vcm->vl_input_queue, (u8 *) & rmp);
-}
-
-static void
-vl_api_accept_session_t_handler (vl_api_accept_session_t * mp)
-{
- svm_fifo_t *rx_fifo, *tx_fifo;
- session_t *session, *listen_session;
- u32 session_index;
-
- clib_spinlock_lock (&vcm->sessions_lockp);
- if (!clib_fifo_free_elts (vcm->client_session_index_fifo))
- {
- clib_warning ("[%d] client session queue is full!", getpid ());
- vppcom_send_accept_session_reply (mp->handle, mp->context,
- VNET_API_ERROR_QUEUE_FULL);
- clib_spinlock_unlock (&vcm->sessions_lockp);
- return;
- }
-
- listen_session = vppcom_session_table_lookup_listener (mp->listener_handle);
- if (!listen_session)
- {
- clib_warning ("[%d] ERROR: couldn't find listen session: unknown vpp "
- "listener handle %llx", getpid (), mp->listener_handle);
- clib_spinlock_unlock (&vcm->sessions_lockp);
- return;
- }
-
- /* 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->vpp_handle = mp->handle;
- session->client_context = mp->context;
- session->server_rx_fifo = rx_fifo;
- session->server_tx_fifo = tx_fifo;
- session->vpp_event_queue = uword_to_pointer (mp->vpp_event_queue_address,
- svm_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);
- session->lcl_port = listen_session->lcl_port;
- session->lcl_addr = listen_session->lcl_addr;
-
- /* TBD: move client_session_index_fifo into listener session */
- clib_fifo_add1 (vcm->client_session_index_fifo, session_index);
-
- clib_spinlock_unlock (&vcm->sessions_lockp);
-
- if (VPPCOM_DEBUG > 1)
- clib_warning ("[%d] vpp handle 0x%llx, sid %u: client accept "
- "request from %s address %U port %d queue %p!", getpid (),
- mp->handle, session_index, mp->is_ip4 ? "IPv4" : "IPv6",
- format_ip46_address, &mp->ip, mp->is_ip4,
- clib_net_to_host_u16 (mp->port), session->vpp_event_queue);
-
- if (VPPCOM_DEBUG > 0)
- {
- session->elog_track.name =
- (char *) format (0, "C:%d:S:%d%c", vcm->my_client_index,
- session_index, 0);
- elog_track_register (&vcm->elog_main, &session->elog_track);
-
- if (session->peer_addr.is_ip4)
- {
- /* *INDENT-OFF* */
- ELOG_TYPE_DECLARE (e) =
- {
- .format =
- "client_accept:handle:%x addr:%d.%d.%d.%d:%d",
- .format_args = "i8i1i1i1i1i2",
- };
-
- CLIB_PACKED (struct {
- u64 handle; //8
- u8 addr[4]; //4
- u16 port; //2
- }) * ed;
-
- ed = ELOG_TRACK_DATA (&vcm->elog_main, e, session->elog_track);
-
- ed->handle = mp->handle;
- ed->addr[0] = session->peer_addr.ip46.ip4.as_u8[0];
- ed->addr[1] = session->peer_addr.ip46.ip4.as_u8[1];
- ed->addr[2] = session->peer_addr.ip46.ip4.as_u8[2];
- ed->addr[3] = session->peer_addr.ip46.ip4.as_u8[3];
- ed->port = session->peer_port;
- /* *INDENT-ON* */
- }
- else
- {
- clib_warning ("ip6");
- }
- }
-
-}
-
-static void
-vppcom_send_connect_session_reply (session_t * session, u32 session_index,
- u64 vpp_handle, u32 context, int retval)
-{
- vl_api_connect_session_reply_t *rmp;
- u32 len;
- svm_queue_t *client_q;
-
- rmp = vl_msg_api_alloc (sizeof (*rmp));
- memset (rmp, 0, sizeof (*rmp));
- rmp->_vl_msg_id = ntohs (VL_API_CONNECT_SESSION_REPLY);
-
- if (!session)
- {
- rmp->context = context;
- rmp->handle = vpp_handle;
- rmp->retval = htonl (retval);
- vl_msg_api_send_shmem (vcm->vl_input_queue, (u8 *) & rmp);
- return;
- }
-
- rmp->context = session->client_context;
- rmp->retval = htonl (retval);
- rmp->handle = session->vpp_handle;
- rmp->server_rx_fifo = pointer_to_uword (session->server_rx_fifo);
- rmp->server_tx_fifo = pointer_to_uword (session->server_tx_fifo);
- rmp->vpp_event_queue_address = pointer_to_uword (session->vpp_event_queue);
- rmp->segment_size = vcm->cfg.segment_size;
- len = vec_len (session->segment_name);
- rmp->segment_name_length = clib_min (len, sizeof (rmp->segment_name));
- clib_memcpy (rmp->segment_name, session->segment_name,
- rmp->segment_name_length - 1);
- clib_memcpy (rmp->lcl_ip, session->peer_addr.ip46.as_u8,
- sizeof (rmp->lcl_ip));
- rmp->is_ip4 = session->peer_addr.is_ip4;
- rmp->lcl_port = session->peer_port;
- client_q = uword_to_pointer (session->client_queue_address, svm_queue_t *);
- ASSERT (client_q);
- vl_msg_api_send_shmem (client_q, (u8 *) & rmp);
-}
-
-/*
- * Acting as server for redirected connect requests
- */
-static void
-vl_api_connect_sock_t_handler (vl_api_connect_sock_t * mp)
-{
- u32 session_index;
- session_t *session = 0;
-
- clib_spinlock_lock (&vcm->sessions_lockp);
- if (!clib_fifo_free_elts (vcm->client_session_index_fifo))
- {
- clib_spinlock_unlock (&vcm->sessions_lockp);
-
- if (VPPCOM_DEBUG > 1)
- clib_warning ("[%d] client session queue is full!", getpid ());
-
- /* TBD: Fix api to include vpp handle */
- vppcom_send_connect_session_reply (0 /* session */ , 0 /* sid */ ,
- 0 /* handle */ , mp->context,
- VNET_API_ERROR_QUEUE_FULL);
- return;
- }
-
- pool_get (vcm->sessions, session);
- memset (session, 0, sizeof (*session));
- session_index = session - vcm->sessions;
-
- session->client_context = mp->context;
- session->vpp_handle = session_index;
- session->client_queue_address = mp->client_queue_address;
- session->is_cut_thru = 1;
- session->is_server = 1;
- session->lcl_port = mp->port;
- session->lcl_addr.is_ip4 = mp->is_ip4;
- clib_memcpy (&session->lcl_addr.ip46, mp->ip,
- sizeof (session->lcl_addr.ip46));
-
- /* TBD: missing peer info in api msg.
- */
- session->peer_addr.is_ip4 = mp->is_ip4;
- ASSERT (session->lcl_addr.is_ip4 == session->peer_addr.is_ip4);
-
- session->state = STATE_ACCEPT;
- clib_fifo_add1 (vcm->client_session_index_fifo, session_index);
- if (VPPCOM_DEBUG > 1)
- clib_warning ("[%d] sid %u: Got a cut-thru connect request! "
- "clib_fifo_elts %u!\n", getpid (), session_index,
- clib_fifo_elts (vcm->client_session_index_fifo));
-
- if (VPPCOM_DEBUG > 0)
- {
- session->elog_track.name =
- (char *) format (0, "C:%d:S:%d%c", vcm->my_client_index,
- session_index, 0);
- elog_track_register (&vcm->elog_main, &session->elog_track);
-
- /* *INDENT-OFF* */
- ELOG_TYPE_DECLARE (e) =
- {
- .format = "cut-thru-connect:S:%d clib_fifo_elts:%d",
- .format_args = "i4i4",
- };
-
- struct
- {
- u32 data[2];
- } *ed;
-
- ed = ELOG_TRACK_DATA (&vcm->elog_main, e, session->elog_track);
-
- ed->data[0] = session_index;
- ed->data[1] = clib_fifo_elts (vcm->client_session_index_fifo);
- /* *INDENT-ON* */
- }
-
- clib_spinlock_unlock (&vcm->sessions_lockp);
-}
-
-static void
-vppcom_send_bind_sock (session_t * session, u32 session_index)
-{
- 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 = session_index;
- 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 (u64 vpp_handle)
-{
- vl_api_unbind_sock_t *ump;
-
- 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 = vpp_handle;
- vl_msg_api_send_shmem (vcm->vl_input_queue, (u8 *) & ump);
-}
-
-static int
-vppcom_session_unbind (u32 session_index)
-{
- session_t *session = 0;
- int rv;
- u64 vpp_handle;
-
- VCL_LOCK_AND_GET_SESSION (session_index, &session);