mp->segment_handle, mp->server_rx_fifo, mp->server_tx_fifo,
mp->vpp_event_queue_address, mp->mq_index, 0, session))
{
- VDBG (0, "failed to attach fifos for %u", session->session_index);
+ VDBG (0, "session %u [0x%llx]: failed to attach fifos",
+ session->session_index, mp->handle);
goto error;
}
session->listener_index = listen_session->session_index;
listen_session->n_accepted_sessions++;
- VDBG (1,
- "session %u [0x%llx]: client accept request from %s address %U"
- " port %d queue %p!",
- session->session_index, mp->handle, mp->rmt.is_ip4 ? "IPv4" : "IPv6",
- vcl_format_ip46_address, &mp->rmt.ip,
- mp->rmt.is_ip4 ? IP46_TYPE_IP4 : IP46_TYPE_IP6,
- clib_net_to_host_u16 (mp->rmt.port), session->vpp_evt_q);
vcl_evt (VCL_EVT_ACCEPT, session, listen_session, session_index);
vcl_send_session_accepted_reply (session->vpp_evt_q, mp->context,
session = vcl_session_get (wrk, session_index);
if (PREDICT_FALSE (!session))
{
- VDBG (0, "ERROR: vpp handle 0x%llx has no session index (%u)!",
- mp->handle, session_index);
+ VERR ("vpp handle 0x%llx has no session index (%u)!", mp->handle,
+ session_index);
/* Should not happen but if it does, force vpp session cleanup */
vcl_session_t tmp_session = {
.vpp_handle = mp->handle,
vcl_send_session_disconnect (wrk, &tmp_session);
return VCL_INVALID_SESSION_INDEX;
}
+
if (mp->retval)
{
- VDBG (0, "ERROR: session index %u: connect failed! %U",
- session_index, format_session_error, mp->retval);
+ VDBG (0, "session %u: connect failed! %U", session_index,
+ format_session_error, mp->retval);
session->session_state = VCL_STATE_DETACHED;
- session->vpp_handle = mp->handle;
+ session->vpp_handle = VCL_INVALID_SESSION_HANDLE;
return session_index;
}
session->vpp_handle = mp->handle;
+ /* Add to lookup table. Even if something fails, session cannot be
+ * cleaned up prior to notifying vpp and going through the cleanup
+ * "procedure" see @ref vcl_session_cleanup_handler */
+ vcl_session_table_add_vpp_handle (wrk, mp->handle, session_index);
+
if (vcl_segment_attach_session (
mp->segment_handle, mp->server_rx_fifo, mp->server_tx_fifo,
mp->vpp_event_queue_address, mp->mq_index, 0, session))
{
- VDBG (0, "failed to attach fifos for %u", session->session_index);
- session->session_state = VCL_STATE_DETACHED;
+ VDBG (0, "session %u [0x%llx]: failed to attach fifos",
+ session->session_index, session->vpp_handle);
+ session->session_state = VCL_STATE_UPDATED;
vcl_send_session_disconnect (wrk, session);
return session_index;
}
mp->ct_tx_fifo, (uword) ~0, ~0, 1,
session))
{
- VDBG (0, "failed to attach ct fifos for %u", session->session_index);
- session->session_state = VCL_STATE_DETACHED;
+ VDBG (0, "session %u [0x%llx]: failed to attach ct fifos",
+ session->session_index, session->vpp_handle);
+ session->session_state = VCL_STATE_UPDATED;
vcl_send_session_disconnect (wrk, session);
return session_index;
}
else
session->session_state = VCL_STATE_READY;
- /* Add it to lookup table */
- vcl_session_table_add_vpp_handle (wrk, mp->handle, session_index);
-
- VDBG (1, "session %u [0x%llx] connected! rx_fifo %p, refcnt %d, tx_fifo %p,"
- " refcnt %d", session_index, mp->handle, session->rx_fifo,
- session->rx_fifo->refcnt, session->tx_fifo, session->tx_fifo->refcnt);
+ VDBG (0, "session %u [0x%llx] connected local: %U:%u remote %U:%u",
+ session->session_index, session->vpp_handle, vcl_format_ip46_address,
+ &session->transport.lcl_ip,
+ session->transport.is_ip4 ? IP46_TYPE_IP4 : IP46_TYPE_IP6,
+ clib_net_to_host_u16 (session->transport.lcl_port),
+ vcl_format_ip46_address, &session->transport.rmt_ip,
+ session->transport.is_ip4 ? IP46_TYPE_IP4 : IP46_TYPE_IP6,
+ clib_net_to_host_u16 (session->transport.rmt_port));
return session_index;
}
if (session->session_state != VCL_STATE_CLOSED)
session->session_state = VCL_STATE_DISCONNECT;
- VDBG (0, "reset session %u [0x%llx]", sid, reset_msg->handle);
+ VDBG (0, "session %u [0x%llx]: reset", sid, reset_msg->handle);
return sid;
}
}
else
{
- VDBG (0, "ERROR: session %u [0x%llx]: Invalid session index!",
- sid, mp->handle);
+ VDBG (0, "session %u [0x%llx]: Invalid session index!", sid,
+ mp->handle);
return VCL_INVALID_SESSION_INDEX;
}
}
mp->tx_fifo, mp->vpp_evt_q, mp->mq_index,
0, session))
{
- VDBG (0, "failed to attach fifos for %u", session->session_index);
+ VDBG (0, "session %u [0x%llx]: failed to attach fifos",
+ session->session_index, session->vpp_handle);
session->session_state = VCL_STATE_DETACHED;
return VCL_INVALID_SESSION_INDEX;
}
session = vcl_session_get_w_vpp_handle (wrk, msg->handle);
if (!session)
{
- VDBG (0, "request to disconnect unknown handle 0x%llx", msg->handle);
+ VWRN ("request to disconnect unknown handle 0x%llx", msg->handle);
return 0;
}
vpp_handle = session->vpp_handle;
state = session->session_state;
- VDBG (1, "session %u [0x%llx] state 0x%x (%s)", session->session_index,
- vpp_handle, state, vcl_session_state_str (state));
+ VDBG (1, "session %u [0x%llx]: disconnecting state (%s)",
+ session->session_index, vpp_handle, vcl_session_state_str (state));
if (PREDICT_FALSE (state == VCL_STATE_LISTEN))
{
if (PREDICT_FALSE (!session->vpp_evt_q))
return VPPCOM_OK;
- VDBG (1, "session %u [0x%llx]: sending disconnect...",
+ VDBG (1, "session %u [0x%llx]: sending disconnect",
session->session_index, vpp_handle);
vcl_send_session_disconnect (wrk, session);
}
session = vcl_session_get_w_vpp_handle (wrk, msg->handle);
if (!session)
{
- VDBG (0, "disconnect confirmed for unknown handle 0x%llx", msg->handle);
+ VWRN ("disconnect confirmed for unknown handle 0x%llx", msg->handle);
return;
}
return;
}
+ /* VPP will reuse the handle so clean it up now */
vcl_session_table_del_vpp_handle (wrk, msg->handle);
- /* Should not happen. App did not close the connection so don't free it. */
+
+ /* App did not close the connection yet so don't free it. */
if (session->session_state != VCL_STATE_CLOSED)
{
- VDBG (0, "app did not close session %d", session->session_index);
+ VDBG (0, "session %u: app did not close", session->session_index);
session->session_state = VCL_STATE_DETACHED;
session->vpp_handle = VCL_INVALID_SESSION_HANDLE;
return;
}
+
+ /* Session probably tracked with epoll, disconnect not yet handled and
+ * 1) both transport and session cleanup completed 2) app closed. Wait
+ * until message is drained to free the session.
+ * See @ref vcl_handle_mq_event */
+ if (session->flags & VCL_SESSION_F_PENDING_DISCONNECT)
+ {
+ session->flags |= VCL_SESSION_F_PENDING_FREE;
+ return;
+ }
+
vcl_session_free (wrk, session);
}
disconnected_msg = (session_disconnected_msg_t *) e->data;
if (!(s = vcl_session_get_w_vpp_handle (wrk, disconnected_msg->handle)))
break;
+ if (s->session_state == VCL_STATE_CLOSED)
+ break;
if (vcl_session_has_attr (s, VCL_SESS_ATTR_NONBLOCK))
{
- vec_add1 (wrk->unhandled_evts_vector, *e);
+ s->session_state = VCL_STATE_VPP_CLOSING;
+ s->flags |= VCL_SESSION_F_PENDING_DISCONNECT;
+ vec_add2 (wrk->unhandled_evts_vector, ecpy, 1);
+ *ecpy = *e;
+ ecpy->postponed = 1;
+ ecpy->session_index = s->session_index;
break;
}
if (!(s = vcl_session_disconnected_handler (wrk, disconnected_msg)))
reset_msg = (session_reset_msg_t *) e->data;
if (!(s = vcl_session_get_w_vpp_handle (wrk, reset_msg->handle)))
break;
+ if (s->session_state == VCL_STATE_CLOSED)
+ break;
if (vcl_session_has_attr (s, VCL_SESS_ATTR_NONBLOCK))
{
- vec_add1 (wrk->unhandled_evts_vector, *e);
+ s->flags |= VCL_SESSION_F_PENDING_DISCONNECT;
+ s->session_state = VCL_STATE_DISCONNECT;
+ vec_add2 (wrk->unhandled_evts_vector, ecpy, 1);
+ *ecpy = *e;
+ ecpy->postponed = 1;
+ ecpy->session_index = s->session_index;
break;
}
vcl_session_reset_handler (wrk, (session_reset_msg_t *) e->data);
}
else if (s->session_state == VCL_STATE_DETACHED)
{
- /* Should not happen. VPP cleaned up before app confirmed close */
VDBG (0, "vpp freed session %d before close", s->session_index);
- goto free_session;
+
+ if (!(s->flags & VCL_SESSION_F_PENDING_DISCONNECT))
+ goto free_session;
+
+ /* Disconnect/reset messages pending but vpp transport and session
+ * cleanups already done. Free only after messages drained. */
+ s->flags |= VCL_SESSION_F_PENDING_FREE;
}
s->session_state = VCL_STATE_CLOSED;
if (PREDICT_FALSE (session->flags & VCL_SESSION_F_IS_VEP))
{
- VDBG (0, "ERROR: cannot connect epoll session %u!",
- session->session_index);
+ VWRN ("cannot connect epoll session %u!", session->session_index);
return VPPCOM_EBADFD;
}
if (PREDICT_FALSE (vcl_session_is_ready (session)))
{
VDBG (0,
- "session handle %u [0x%llx]: session already "
- "connected to %s %U port %d proto %s, state 0x%x (%s)",
- session_handle, session->vpp_handle,
- session->transport.is_ip4 ? "IPv4" : "IPv6",
+ "session %u [0x%llx]: already connected to %U:%d proto %s,"
+ " state (%s)",
+ session->session_index, session->vpp_handle,
vcl_format_ip46_address, &session->transport.rmt_ip,
session->transport.is_ip4 ? IP46_TYPE_IP4 : IP46_TYPE_IP6,
clib_net_to_host_u16 (session->transport.rmt_port),
- vppcom_proto_str (session->session_type), session->session_state,
+ vppcom_proto_str (session->session_type),
vcl_session_state_str (session->session_state));
return VPPCOM_OK;
}
session->parent_handle = VCL_INVALID_SESSION_HANDLE;
session->flags |= VCL_SESSION_F_CONNECTED;
- VDBG (0,
- "session handle %u (%s): connecting to peer %s %U "
- "port %d proto %s",
- session_handle, vcl_session_state_str (session->session_state),
- session->transport.is_ip4 ? "IPv4" : "IPv6", vcl_format_ip46_address,
+ VDBG (0, "session %u: connecting to peer %U:%d proto %s",
+ session->session_index, vcl_format_ip46_address,
&session->transport.rmt_ip,
session->transport.is_ip4 ? IP46_TYPE_IP4 : IP46_TYPE_IP6,
clib_net_to_host_u16 (session->transport.rmt_port),
}
n_read = svm_fifo_segments (rx_fifo, s->rx_bytes_pending,
- (svm_fifo_seg_t *) ds, n_segments, max_bytes);
+ (svm_fifo_seg_t *) ds, &n_segments, max_bytes);
if (n_read < 0)
return VPPCOM_EAGAIN;
case SESSION_IO_EVT_TX:
sid = e->session_index;
s = vcl_session_get (wrk, sid);
- if (vcl_session_is_closed (s))
+ if (!s || !vcl_session_is_open (s))
break;
session_events = s->vep.ev.events;
if (!(EPOLLOUT & session_events))
else
{
s = vcl_session_get (wrk, e->session_index);
+ s->flags &= ~VCL_SESSION_F_PENDING_DISCONNECT;
}
if (vcl_session_is_closed (s) ||
!(s->flags & VCL_SESSION_F_IS_VEP_SESSION))
- break;
+ {
+ if (s && (s->flags & VCL_SESSION_F_PENDING_FREE))
+ vcl_session_free (wrk, s);
+ break;
+ }
sid = s->session_index;
session_events = s->vep.ev.events;
add_event = 1;
break;
case SESSION_CTRL_EVT_RESET:
if (!e->postponed)
- sid = vcl_session_reset_handler (wrk, (session_reset_msg_t *) e->data);
+ {
+ sid =
+ vcl_session_reset_handler (wrk, (session_reset_msg_t *) e->data);
+ s = vcl_session_get (wrk, sid);
+ }
else
- sid = e->session_index;
- s = vcl_session_get (wrk, sid);
+ {
+ sid = e->session_index;
+ s = vcl_session_get (wrk, sid);
+ s->flags &= ~VCL_SESSION_F_PENDING_DISCONNECT;
+ }
if (vcl_session_is_closed (s) ||
!(s->flags & VCL_SESSION_F_IS_VEP_SESSION))
- break;
+ {
+ if (s && (s->flags & VCL_SESSION_F_PENDING_FREE))
+ vcl_session_free (wrk, s);
+ break;
+ }
session_events = s->vep.ev.events;
add_event = 1;
events[*num_ev].events = EPOLLHUP | EPOLLRDHUP;