return VPPCOM_OK;
}
+static inline void
+vppcom_session_table_add_listener (u64 listener_handle, u32 value)
+{
+ /* Session and listener handles have different formats. The latter has
+ * the thread index in the upper 32 bits while the former has the session
+ * type. Knowing that, for listeners we just flip the MSB to 1 */
+ listener_handle |= 1ULL << 63;
+ hash_set (vcm->session_index_by_vpp_handles, listener_handle, value);
+}
+
+static inline session_t *
+vppcom_session_table_lookup_listener (u64 listener_handle)
+{
+ uword *p;
+ u64 handle = listener_handle | (1ULL << 63);
+ p = hash_get (vcm->session_index_by_vpp_handles, handle);
+ if (!p)
+ {
+ clib_warning ("[%d] couldn't find listen session: unknown vpp "
+ "listener handle %llx", getpid (), listener_handle);
+ return 0;
+ }
+ if (pool_is_free_index (vcm->sessions, p[0]))
+ {
+ if (VPPCOM_DEBUG > 1)
+ clib_warning ("[%d] invalid listen session, sid (%u)", getpid (),
+ p[0]);
+ return 0;
+ }
+
+ return pool_elt_at_index (vcm->sessions, p[0]);
+}
+
+static inline void
+vppcom_session_table_del_listener (u64 listener_handle)
+{
+ listener_handle |= 1ULL << 63;
+ hash_unset (vcm->session_index_by_vpp_handles, listener_handle);
+}
+
static int
vppcom_connect_to_vpp (char *app_name)
{
mp)
{
uword *p;
+ u32 session_index = ~0;
p = hash_get (vcm->session_index_by_vpp_handles, mp->handle);
if (p)
{
session_t *session = 0;
int rv;
+
+ session_index = p[0];
+ hash_unset (vcm->session_index_by_vpp_handles, mp->handle);
clib_spinlock_lock (&vcm->sessions_lockp);
- rv = vppcom_session_at_index (p[0], &session);
+ rv = vppcom_session_at_index (session_index, &session);
if (PREDICT_FALSE (rv))
{
if (VPPCOM_DEBUG > 1)
- clib_warning ("[%d] invalid session, sid (%u) has been closed!",
- getpid (), p[0]);
+ clib_warning ("[%d] invalid session, sid %u has been closed!",
+ getpid (), session_index);
+ }
+ else
+ {
+ if (VPPCOM_DEBUG > 1)
+ clib_warning ("[%d] vpp handle 0x%llx, sid %u disconnected!",
+ getpid (), mp->handle, session_index);
+
+ session->state = STATE_DISCONNECT;
}
- hash_unset (vcm->session_index_by_vpp_handles, mp->handle);
- session->state = STATE_DISCONNECT;
clib_spinlock_unlock (&vcm->sessions_lockp);
}
else
{
if (VPPCOM_DEBUG > 1)
- clib_warning ("[%d] couldn't find session key %llx", getpid (),
- mp->handle);
+ clib_warning ("[%d] couldn't find session: unknown vpp handle 0x%llx",
+ getpid (), mp->handle);
}
if (mp->retval)
- clib_warning ("[%d] disconnect_session failed: %U", getpid (),
+ clib_warning ("[%d] disconnect_session vpp handle 0x%llx, sid %u "
+ "failed: %U", getpid (), mp->handle, session_index,
format_api_error, ntohl (mp->retval));
}
session_t *session = 0;
vl_api_disconnect_session_reply_t *rmp;
uword *p;
- int rv = 0;
+ int rv = 0, rval;
p = hash_get (vcm->session_index_by_vpp_handles, mp->handle);
+ if (VPPCOM_DEBUG > 0)
+ {
+ if (!p)
+ {
+ clib_warning ("[%d] request to disconnect invalid handle (%u)!",
+ getpid (), mp->handle);
+ rv = -11;
+ goto done;
+ }
+ clib_warning ("[%d] disconnecting handle %u sid (%u)!", getpid (),
+ mp->handle, p[0]);
+ }
+
+ goto done;
+
if (p)
{
- int rval;
clib_spinlock_lock (&vcm->sessions_lockp);
rval = vppcom_session_at_index (p[0], &session);
if (PREDICT_FALSE (rval))
}
else
{
- clib_warning ("[%d] couldn't find session key %llx", getpid (),
- mp->handle);
+ clib_warning ("[%d] couldn't find session: unknown vpp handle 0x%llx",
+ getpid (), mp->handle);
rv = -11;
}
+done:
rmp = vl_msg_api_alloc (sizeof (*rmp));
memset (rmp, 0, sizeof (*rmp));
}
else
{
- clib_warning ("[%d] couldn't find session key %llx", getpid (),
- mp->handle);
+ clib_warning ("[%d] couldn't find session: unknown vpp handle 0x%llx",
+ getpid (), mp->handle);
rv = -11;
}
hash_set (vcm->session_index_by_vpp_handles, mp->handle, session_index);
if (VPPCOM_DEBUG > 1)
- clib_warning ("[%d] client sid %d\n"
+ clib_warning ("[%d] client sid %d, vpp handle 0x%llx\n"
" session_rx_fifo %p, refcnt %d\n"
" session_tx_fifo %p, refcnt %d",
- getpid (), session_index,
+ getpid (), session_index, mp->handle,
session->server_rx_fifo,
session->server_rx_fifo->refcnt,
session->server_tx_fifo, session->server_tx_fifo->refcnt);
if (rv == VPPCOM_OK)
{
session->vpp_handle = mp->handle;
- hash_set (vcm->session_index_by_vpp_handles, mp->handle,
- vcm->bind_session_index);
+ 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, vcm->bind_session_index);
session->state = mp->retval ? STATE_FAILED : STATE_LISTEN;
vcm->bind_session_index = ~0;
}
vl_api_unbind_sock_reply_t_handler (vl_api_unbind_sock_reply_t * mp)
{
session_t *session = 0;
- int rv;
clib_spinlock_lock (&vcm->sessions_lockp);
- rv = vppcom_session_at_index (vcm->bind_session_index, &session);
- if (rv == VPPCOM_OK)
+ session = vppcom_session_table_lookup_listener (vcm->bind_session_index);
+
+ if (session)
{
if ((VPPCOM_DEBUG > 1) && (mp->retval))
clib_warning ("[%d] unbind failed: %U", getpid (), format_api_error,
ntohl (mp->retval));
+ vppcom_session_table_del_listener (vcm->bind_session_index);
vcm->bind_session_index = ~0;
session->state = STATE_START;
}
vl_api_accept_session_t_handler (vl_api_accept_session_t * mp)
{
svm_fifo_t *rx_fifo, *tx_fifo;
- session_t *session;
+ 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 (VNET_API_ERROR_QUEUE_FULL,
- mp->handle);
+ vppcom_send_accept_session_reply (mp->handle,
+ 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;
}
/* 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)
}
static void
-vppcom_send_connect_session_reply (session_t * session, u32 context,
- int retval, int handle)
+vppcom_send_connect_session_reply (session_t * session, int retval)
{
vl_api_connect_session_reply_t *rmp;
u32 len;
memset (rmp, 0, sizeof (*rmp));
rmp->_vl_msg_id = ntohs (VL_API_CONNECT_SESSION_REPLY);
- rmp->context = session ? session->client_context : context;
+ rmp->context = session->client_context;
rmp->retval = htonl (retval);
- rmp->handle = session ? session->vpp_handle : handle;
-
- if (session)
- {
- 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->lcl_addr.ip46.as_u8,
- sizeof (rmp->lcl_ip));
- rmp->is_ip4 = session->lcl_addr.is_ip4;
- }
-
+ 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->lcl_addr.ip46.as_u8,
+ sizeof (rmp->lcl_ip));
+ rmp->is_ip4 = session->lcl_addr.is_ip4;
client_q = uword_to_pointer (session->client_queue_address,
unix_shared_memory_queue_t *);
ASSERT (client_q);
if (VPPCOM_DEBUG > 1)
clib_warning ("[%d] client session queue is full!", getpid ());
clib_spinlock_unlock (&vcm->sessions_lockp);
- vppcom_send_accept_session_reply (VNET_API_ERROR_QUEUE_FULL, 0);
+ /* TBD: fix handle */
+ vppcom_send_accept_session_reply (0, VNET_API_ERROR_QUEUE_FULL);
return;
}
}
clib_spinlock_unlock (&vcm->sessions_lockp);
+ if (vcm->bind_session_index != session_index)
+ clib_warning ("[%d] ERROR: unbinding a not bound listener %u (%u)",
+ session_index, vcm->bind_session_index);
vcm->bind_session_index = session_index;
vppcom_send_unbind_sock (session_index);
rv = vppcom_wait_for_session_state_change (session_index, STATE_START,
if (!session->is_cut_thru)
{
+ if (VPPCOM_DEBUG > 1)
+ clib_warning ("[%d] disconnecting sid (%u)", getpid (),
+ session_index);
vppcom_send_disconnect (session);
clib_spinlock_unlock (&vcm->sessions_lockp);
rv = vppcom_wait_for_session_state_change (session_index,
STATE_DISCONNECT, 1.0);
+ /* TBD: Force clean up on error/timeout since there is no other
+ * way to recover from a failed disconnect.
+ */
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);
+ {
+ /* TBD: Handle cut-thru disconnect */
+ clib_spinlock_unlock (&vcm->sessions_lockp);
+ }
return VPPCOM_OK;
}
vcl_mem = mmap (0, vcl_cfg->heapsize, PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS, -1, 0);
- if (vcl_mem <= 0)
+ if (vcl_mem == MAP_FAILED)
{
clib_unix_error ("[%d] ERROR: mmap(0, %lld == 0x%llx, "
"PROT_READ | PROT_WRITE,MAP_SHARED | MAP_ANONYMOUS, "
int
vppcom_session_accept (uint32_t listen_session_index, vppcom_endpt_t * ep,
- double wait_for_time)
+ uint32_t flags, double wait_for_time)
{
session_t *listen_session = 0;
session_t *client_session = 0;
- u32 client_session_index;
+ u32 client_session_index = ~0;
int rv;
f64 wait_for;
char *cut_thru_str;
ASSERT (client_session->peer_addr.is_ip4 ==
listen_session->lcl_addr.is_ip4);
+ client_session->is_nonblocking = (flags & O_NONBLOCK) ? 1 : 0;
if (VPPCOM_DEBUG > 0)
- clib_warning ("[%d] Got a request: client sid %d", getpid (),
- client_session_index);
+ clib_warning ("[%d] Got a request: client sid %d, flags %d, "
+ " is_nonblocking %u", getpid (), client_session_index,
+ flags, client_session->is_nonblocking);
ep->vrf = client_session->vrf;
ep->is_cut_thru = client_session->is_cut_thru;
getpid (), a->segment_name);
vec_reset_length (a->new_segment_indices);
rv = VNET_API_ERROR_URI_FIFO_CREATE_FAILED;
- vppcom_send_connect_session_reply (client_session, 0, rv, 0);
+ vppcom_send_connect_session_reply (client_session, rv);
clib_spinlock_unlock (&vcm->sessions_lockp);
return VPPCOM_ENOMEM;
}
getpid (), vcm->cfg.rx_fifo_size,
vcm->cfg.rx_fifo_size);
rv = VNET_API_ERROR_URI_FIFO_CREATE_FAILED;
- vppcom_send_connect_session_reply (client_session, 0, rv, 0);
+ vppcom_send_connect_session_reply (client_session, rv);
clib_spinlock_unlock (&vcm->sessions_lockp);
return VPPCOM_ENOMEM;
}
getpid (), vcm->cfg.tx_fifo_size,
vcm->cfg.tx_fifo_size);
rv = VNET_API_ERROR_URI_FIFO_CREATE_FAILED;
- vppcom_send_connect_session_reply (client_session, 0, rv, 0);
+ vppcom_send_connect_session_reply (client_session, rv);
clib_spinlock_unlock (&vcm->sessions_lockp);
return VPPCOM_ENOMEM;
}
ssvm_unlock_non_recursive (sh);
}
#endif
- vppcom_send_connect_session_reply (client_session, 0, 0, 0);
+ vppcom_send_connect_session_reply (client_session, 0);
}
else
{
cut_thru_str = " ";
- vppcom_send_accept_session_reply (0, client_session->vpp_handle);
+ vppcom_send_accept_session_reply (client_session->vpp_handle, 0);
}
if (VPPCOM_DEBUG > 0)
{
case VPPCOM_ATTR_GET_NREAD:
rv = vppcom_session_read_ready (session, session_index);
- if (VPPCOM_DEBUG > 1)
- clib_warning ("[%d] VPPCOM_ATTR_GET_NREAD: nread = %d",
+ if (VPPCOM_DEBUG > 2)
+ clib_warning ("[%d] VPPCOM_ATTR_GET_NREAD: sid %u, nread = %d",
getpid (), rv);
break;
- case VPPCOM_ATTR_PEEK_NREAD:
- /* TBD */
+ case VPPCOM_ATTR_GET_NWRITE:
+ rv = vppcom_session_write_ready (session, session_index);
+ if (VPPCOM_DEBUG > 2)
+ clib_warning ("[%d] VPPCOM_ATTR_GET_NWRITE: sid %u, nwrite = %d",
+ getpid (), session_index, rv);
+
break;
case VPPCOM_ATTR_GET_FLAGS:
{
*flags = O_RDWR | ((session->is_nonblocking) ? O_NONBLOCK : 0);
*buflen = sizeof (*flags);
- if (VPPCOM_DEBUG > 1)
- clib_warning ("[%d] VPPCOM_ATTR_GET_FLAGS: flags = 0x%08x, "
- "is_nonblocking = %u", getpid (), *flags,
- session->is_nonblocking);
+ if (VPPCOM_DEBUG > 2)
+ clib_warning ("[%d] VPPCOM_ATTR_GET_FLAGS: sid %u, "
+ "flags = 0x%08x, is_nonblocking = %u", getpid (),
+ session_index, *flags, session->is_nonblocking);
}
else
rv = VPPCOM_EINVAL;
if (buffer && buflen && (*buflen >= sizeof (*flags)))
{
session->is_nonblocking = (*flags & O_NONBLOCK) ? 1 : 0;
- if (VPPCOM_DEBUG > 1)
- clib_warning ("[%d] VPPCOM_ATTR_SET_FLAGS: flags = 0x%08x, "
- "is_nonblocking = %u", getpid (), *flags,
- session->is_nonblocking);
+ if (VPPCOM_DEBUG > 2)
+ clib_warning ("[%d] VPPCOM_ATTR_SET_FLAGS: sid %u, "
+ "flags = 0x%08x, is_nonblocking = %u",
+ getpid (), *flags, session->is_nonblocking);
}
else
rv = VPPCOM_EINVAL;
sizeof (ip6_address_t));
*buflen = sizeof (*ep);
if (VPPCOM_DEBUG > 1)
- clib_warning ("[%d] VPPCOM_ATTR_GET_PEER_ADDR: sid %u is_ip4 = "
+ clib_warning ("[%d] VPPCOM_ATTR_GET_PEER_ADDR: sid %u, is_ip4 = "
"%u, addr = %U, port %u", getpid (),
session_index, ep->is_ip4, format_ip46_address,
&session->peer_addr.ip46, ep->is_ip4,
sizeof (ip6_address_t));
*buflen = sizeof (*ep);
if (VPPCOM_DEBUG > 1)
- clib_warning ("[%d] VPPCOM_ATTR_GET_LCL_ADDR: sid %u is_ip4 = "
+ clib_warning ("[%d] VPPCOM_ATTR_GET_LCL_ADDR: sid %u, is_ip4 = "
"%u, addr = %U port %d", getpid (),
session_index, ep->is_ip4, format_ip46_address,
&session->lcl_addr.ip46, ep->is_ip4,