aboutsummaryrefslogtreecommitdiffstats
path: root/src/vnet
diff options
context:
space:
mode:
Diffstat (limited to 'src/vnet')
-rw-r--r--src/vnet/session-apps/echo_client.c3
-rw-r--r--src/vnet/session/application.c38
-rw-r--r--src/vnet/session/application_interface.h109
-rw-r--r--src/vnet/session/segment_manager.c4
-rw-r--r--src/vnet/session/session.c11
-rw-r--r--src/vnet/session/session.h23
-rwxr-xr-xsrc/vnet/session/session_api.c207
-rwxr-xr-xsrc/vnet/session/session_cli.c2
-rw-r--r--src/vnet/session/session_node.c187
9 files changed, 521 insertions, 63 deletions
diff --git a/src/vnet/session-apps/echo_client.c b/src/vnet/session-apps/echo_client.c
index 3d1af676186..e67de959a28 100644
--- a/src/vnet/session-apps/echo_client.c
+++ b/src/vnet/session-apps/echo_client.c
@@ -359,7 +359,7 @@ echo_clients_session_connected_callback (u32 app_index, u32 api_context,
echo_client_main_t *ecm = &echo_client_main;
eclient_session_t *session;
u32 session_index;
- u8 thread_index = s->thread_index;
+ u8 thread_index;
if (is_fail)
{
@@ -368,6 +368,7 @@ echo_clients_session_connected_callback (u32 app_index, u32 api_context,
return 0;
}
+ thread_index = s->thread_index;
ASSERT (thread_index == vlib_get_thread_index ()
|| session_transport_service_type (s) == TRANSPORT_SERVICE_CL);
diff --git a/src/vnet/session/application.c b/src/vnet/session/application.c
index 6041b49712d..1dc04f0afa7 100644
--- a/src/vnet/session/application.c
+++ b/src/vnet/session/application.c
@@ -810,22 +810,7 @@ application_get_segment_manager_properties (u32 app_index)
static inline int
app_enqueue_evt (svm_msg_q_t * mq, svm_msg_q_msg_t * msg, u8 lock)
{
- if (PREDICT_TRUE (!svm_msg_q_is_full (mq)))
- {
- if (lock)
- {
- svm_msg_q_add_w_lock (mq, msg);
- svm_msg_q_unlock (mq);
- }
- else if (svm_msg_q_add (mq, msg, SVM_Q_WAIT))
- {
- clib_warning ("msg q add returned");
- if (lock)
- svm_msg_q_unlock (mq);
- return -1;
- }
- }
- else
+ if (PREDICT_FALSE (svm_msg_q_is_full (mq)))
{
clib_warning ("evt q full");
svm_msg_q_free_msg (mq, msg);
@@ -833,13 +818,26 @@ app_enqueue_evt (svm_msg_q_t * mq, svm_msg_q_msg_t * msg, u8 lock)
svm_msg_q_unlock (mq);
return -1;
}
+
+ if (lock)
+ {
+ svm_msg_q_add_and_unlock (mq, msg);
+ return 0;
+ }
+
+ /* Even when not locking the ring, we must wait for queue mutex */
+ if (svm_msg_q_add (mq, msg, SVM_Q_WAIT))
+ {
+ clib_warning ("msg q add returned");
+ return -1;
+ }
return 0;
}
static inline int
app_send_io_evt_rx (application_t * app, stream_session_t * s, u8 lock)
{
- session_fifo_event_t *evt;
+ session_event_t *evt;
svm_msg_q_msg_t msg;
svm_msg_q_t *mq;
@@ -873,7 +871,7 @@ app_send_io_evt_rx (application_t * app, stream_session_t * s, u8 lock)
msg = svm_msg_q_alloc_msg_w_ring (mq, SESSION_MQ_IO_EVT_RING);
ASSERT (!svm_msg_q_msg_is_invalid (&msg));
- evt = (session_fifo_event_t *) svm_msg_q_msg_data (mq, &msg);
+ evt = (session_event_t *) svm_msg_q_msg_data (mq, &msg);
evt->fifo = s->server_rx_fifo;
evt->event_type = FIFO_EVENT_APP_RX;
@@ -884,7 +882,7 @@ static inline int
app_send_io_evt_tx (application_t * app, stream_session_t * s, u8 lock)
{
svm_msg_q_t *mq;
- session_fifo_event_t *evt;
+ session_event_t *evt;
svm_msg_q_msg_t msg;
if (application_is_builtin (app))
@@ -905,7 +903,7 @@ app_send_io_evt_tx (application_t * app, stream_session_t * s, u8 lock)
msg = svm_msg_q_alloc_msg_w_ring (mq, SESSION_MQ_IO_EVT_RING);
ASSERT (!svm_msg_q_msg_is_invalid (&msg));
- evt = (session_fifo_event_t *) svm_msg_q_msg_data (mq, &msg);
+ evt = (session_event_t *) svm_msg_q_msg_data (mq, &msg);
evt->event_type = FIFO_EVENT_APP_TX;
evt->fifo = s->server_tx_fifo;
diff --git a/src/vnet/session/application_interface.h b/src/vnet/session/application_interface.h
index 50c043493f2..0aabd380f8f 100644
--- a/src/vnet/session/application_interface.h
+++ b/src/vnet/session/application_interface.h
@@ -137,6 +137,7 @@ typedef enum
_(IS_PROXY, "Application is proxying") \
_(USE_GLOBAL_SCOPE, "App can use global session scope") \
_(USE_LOCAL_SCOPE, "App can use local session scope") \
+ _(USE_MQ_FOR_CTRL_MSGS, "Use message queue for ctr msgs") \
typedef enum _app_options
{
@@ -197,6 +198,102 @@ typedef struct
#undef _
} app_session_t;
+typedef struct session_accepted_msg_
+{
+ u32 context;
+ u64 listener_handle;
+ u64 handle;
+ u64 server_rx_fifo;
+ u64 server_tx_fifo;
+ u64 vpp_event_queue_address;
+ u64 server_event_queue_address;
+ u16 port;
+ u8 is_ip4;
+ u8 ip[16];
+} session_accepted_msg_t;
+
+typedef struct session_accepted_reply_msg_
+{
+ u32 context;
+ i32 retval;
+ u64 handle;
+} session_accepted_reply_msg_t;
+
+/* Make sure this is not too large, otherwise it won't fit when dequeued in
+ * the session queue node */
+STATIC_ASSERT (sizeof (session_accepted_reply_msg_t) <= 16, "accept reply");
+
+typedef struct session_connected_msg_
+{
+ u32 context;
+ i32 retval;
+ u64 handle;
+ u64 server_rx_fifo;
+ u64 server_tx_fifo;
+ u64 vpp_event_queue_address;
+ u64 client_event_queue_address;
+ u32 segment_size;
+ u8 segment_name_length;
+ u8 segment_name[64];
+ u8 lcl_ip[16];
+ u8 is_ip4;
+ u16 lcl_port;
+} session_connected_msg_t;
+
+typedef struct session_disconnected_msg_
+{
+ u32 client_index;
+ u32 context;
+ u64 handle;
+} session_disconnected_msg_t;
+
+typedef struct session_disconnected_reply_msg_
+{
+ u32 context;
+ i32 retval;
+ u64 handle;
+} session_disconnected_reply_msg_t;
+
+typedef struct session_reset_msg_
+{
+ u32 client_index;
+ u32 context;
+ u64 handle;
+} session_reset_msg_t;
+
+typedef struct session_reset_reply_msg_
+{
+ u32 client_index;
+ u32 context;
+ i32 retval;
+ u64 handle;
+} session_reset_reply_msg_t;
+
+typedef struct app_session_event_
+{
+ svm_msg_q_msg_t msg;
+ session_event_t *evt;
+} app_session_evt_t;
+
+static inline void
+app_alloc_ctrl_evt_to_vpp (svm_msg_q_t * mq, app_session_evt_t * app_evt,
+ u8 evt_type)
+{
+ svm_msg_q_lock_and_alloc_msg_w_ring (mq,
+ SESSION_MQ_CTRL_EVT_RING,
+ SVM_Q_WAIT, &app_evt->msg);
+ svm_msg_q_unlock (mq);
+ app_evt->evt = svm_msg_q_msg_data (mq, &app_evt->msg);
+ memset (app_evt->evt, 0, sizeof (*app_evt->evt));
+ app_evt->evt->event_type = evt_type;
+}
+
+static inline void
+app_send_ctrl_evt_to_vpp (svm_msg_q_t * mq, app_session_evt_t * app_evt)
+{
+ svm_msg_q_add (mq, &app_evt->msg, SVM_Q_WAIT);
+}
+
/**
* Send fifo io event to vpp worker thread
*
@@ -213,7 +310,7 @@ static inline int
app_send_io_evt_to_vpp (svm_msg_q_t * mq, svm_fifo_t * f, u8 evt_type,
u8 noblock)
{
- session_fifo_event_t *evt;
+ session_event_t *evt;
svm_msg_q_msg_t msg;
if (noblock)
@@ -231,11 +328,10 @@ app_send_io_evt_to_vpp (svm_msg_q_t * mq, svm_fifo_t * f, u8 evt_type,
svm_msg_q_unlock (mq);
return -2;
}
- evt = (session_fifo_event_t *) svm_msg_q_msg_data (mq, &msg);
+ evt = (session_event_t *) svm_msg_q_msg_data (mq, &msg);
evt->fifo = f;
evt->event_type = evt_type;
- svm_msg_q_add_w_lock (mq, &msg);
- svm_msg_q_unlock (mq);
+ svm_msg_q_add_and_unlock (mq, &msg);
return 0;
}
else
@@ -247,13 +343,12 @@ app_send_io_evt_to_vpp (svm_msg_q_t * mq, svm_fifo_t * f, u8 evt_type,
svm_msg_q_wait (mq);
msg = svm_msg_q_alloc_msg_w_ring (mq, SESSION_MQ_IO_EVT_RING);
}
- evt = (session_fifo_event_t *) svm_msg_q_msg_data (mq, &msg);
+ evt = (session_event_t *) svm_msg_q_msg_data (mq, &msg);
evt->fifo = f;
evt->event_type = evt_type;
if (svm_msg_q_is_full (mq))
svm_msg_q_wait (mq);
- svm_msg_q_add_w_lock (mq, &msg);
- svm_msg_q_unlock (mq);
+ svm_msg_q_add_and_unlock (mq, &msg);
return 0;
}
}
diff --git a/src/vnet/session/segment_manager.c b/src/vnet/session/segment_manager.c
index b00bcd5bbc8..c7d2482d6bf 100644
--- a/src/vnet/session/segment_manager.c
+++ b/src/vnet/session/segment_manager.c
@@ -605,7 +605,7 @@ segment_manager_evt_q_expected_size (u32 q_len)
u32 fifo_evt_size, notif_q_size, q_hdrs;
u32 msg_q_sz, fifo_evt_ring_sz, session_ntf_ring_sz;
- fifo_evt_size = 1 << max_log2 (sizeof (session_fifo_event_t));
+ fifo_evt_size = 1 << max_log2 (sizeof (session_event_t));
notif_q_size = clib_max (16, q_len >> 4);
msg_q_sz = q_len * sizeof (svm_msg_q_msg_t);
@@ -630,7 +630,7 @@ segment_manager_alloc_queue (svm_fifo_segment_private_t * segment,
svm_msg_q_t *q;
void *oldheap;
- fifo_evt_size = sizeof (session_fifo_event_t);
+ fifo_evt_size = sizeof (session_event_t);
notif_q_size = clib_max (16, queue_size >> 4);
/* *INDENT-OFF* */
svm_msg_q_ring_cfg_t rc[SESSION_MQ_N_RINGS] = {
diff --git a/src/vnet/session/session.c b/src/vnet/session/session.c
index 38a0521af94..897cb1a5a1e 100644
--- a/src/vnet/session/session.c
+++ b/src/vnet/session/session.c
@@ -31,7 +31,7 @@ static inline int
session_send_evt_to_thread (void *data, void *args, u32 thread_index,
session_evt_type_t evt_type)
{
- session_fifo_event_t *evt;
+ session_event_t *evt;
svm_msg_q_msg_t msg;
svm_msg_q_t *mq;
u32 tries = 0, max_tries;
@@ -57,7 +57,7 @@ session_send_evt_to_thread (void *data, void *args, u32 thread_index,
svm_msg_q_unlock (mq);
return -2;
}
- evt = (session_fifo_event_t *) svm_msg_q_msg_data (mq, &msg);
+ evt = (session_event_t *) svm_msg_q_msg_data (mq, &msg);
evt->event_type = evt_type;
switch (evt_type)
{
@@ -78,8 +78,7 @@ session_send_evt_to_thread (void *data, void *args, u32 thread_index,
return -1;
}
- svm_msg_q_add_w_lock (mq, &msg);
- svm_msg_q_unlock (mq);
+ svm_msg_q_add_and_unlock (mq, &msg);
return 0;
}
@@ -1095,7 +1094,7 @@ stream_session_disconnect (stream_session_t * s)
{
u32 thread_index = vlib_get_thread_index ();
session_manager_main_t *smm = &session_manager_main;
- session_fifo_event_t *evt;
+ session_event_t *evt;
if (!s)
return;
@@ -1197,7 +1196,7 @@ session_tx_is_dgram (stream_session_t * s)
void
session_vpp_event_queues_allocate (session_manager_main_t * smm)
{
- u32 evt_q_length = 2048, evt_size = sizeof (session_fifo_event_t);
+ u32 evt_q_length = 2048, evt_size = sizeof (session_event_t);
ssvm_private_t *eqs = &smm->evt_qs_segment;
api_main_t *am = &api_main;
u64 eqs_size = 64 << 20;
diff --git a/src/vnet/session/session.h b/src/vnet/session/session.h
index 879b3823e5d..19176167b50 100644
--- a/src/vnet/session/session.h
+++ b/src/vnet/session/session.h
@@ -34,10 +34,17 @@ typedef enum
{
FIFO_EVENT_APP_RX,
FIFO_EVENT_APP_TX,
- FIFO_EVENT_TIMEOUT,
FIFO_EVENT_DISCONNECT,
FIFO_EVENT_BUILTIN_RX,
FIFO_EVENT_RPC,
+ SESSION_CTRL_EVT_ACCEPTED,
+ SESSION_CTRL_EVT_ACCEPTED_REPLY,
+ SESSION_CTRL_EVT_CONNECTED,
+ SESSION_CTRL_EVT_CONNECTED_REPLY,
+ SESSION_CTRL_EVT_DISCONNECTED,
+ SESSION_CTRL_EVT_DISCONNECTED_REPLY,
+ SESSION_CTRL_EVT_RESET,
+ SESSION_CTRL_EVT_RESET_REPLY
} session_evt_type_t;
static inline const char *
@@ -49,8 +56,6 @@ fifo_event_type_str (session_evt_type_t et)
return "FIFO_EVENT_APP_RX";
case FIFO_EVENT_APP_TX:
return "FIFO_EVENT_APP_TX";
- case FIFO_EVENT_TIMEOUT:
- return "FIFO_EVENT_TIMEOUT";
case FIFO_EVENT_DISCONNECT:
return "FIFO_EVENT_DISCONNECT";
case FIFO_EVENT_BUILTIN_RX:
@@ -112,7 +117,7 @@ typedef struct
u8 data[0];
};
};
-} __clib_packed session_fifo_event_t;
+} __clib_packed session_event_t;
/* *INDENT-ON* */
#define SESSION_MSG_NULL { }
@@ -168,14 +173,14 @@ typedef struct _session_manager_main session_manager_main_t;
typedef int
(session_fifo_rx_fn) (vlib_main_t * vm, vlib_node_runtime_t * node,
- session_fifo_event_t * e0, stream_session_t * s0,
+ session_event_t * e0, stream_session_t * s0,
int *n_tx_pkts);
extern session_fifo_rx_fn session_tx_fifo_peek_and_snd;
extern session_fifo_rx_fn session_tx_fifo_dequeue_and_snd;
extern session_fifo_rx_fn session_tx_fifo_dequeue_internal;
-u8 session_node_lookup_fifo_event (svm_fifo_t * f, session_fifo_event_t * e);
+u8 session_node_lookup_fifo_event (svm_fifo_t * f, session_event_t * e);
struct _session_manager_main
{
@@ -195,13 +200,13 @@ struct _session_manager_main
u32 **tx_buffers;
/** Per worker-thread vector of partially read events */
- session_fifo_event_t **free_event_vector;
+ session_event_t **free_event_vector;
/** per-worker active event vectors */
- session_fifo_event_t **pending_event_vector;
+ session_event_t **pending_event_vector;
/** per-worker postponed disconnects */
- session_fifo_event_t **pending_disconnects;
+ session_event_t **pending_disconnects;
/** per-worker session context */
session_tx_context_t *ctx;
diff --git a/src/vnet/session/session_api.c b/src/vnet/session/session_api.c
index f9fddea6148..724aff1598d 100755
--- a/src/vnet/session/session_api.c
+++ b/src/vnet/session/session_api.c
@@ -363,6 +363,207 @@ static session_cb_vft_t session_cb_vft = {
.del_segment_callback = send_del_segment_callback,
};
+static int
+mq_send_session_accepted_cb (stream_session_t * s)
+{
+ application_t *app = application_get (s->app_index);
+ svm_msg_q_msg_t _msg, *msg = &_msg;
+ svm_msg_q_t *vpp_queue, *app_mq;
+ transport_proto_vft_t *tp_vft;
+ transport_connection_t *tc;
+ stream_session_t *listener;
+ session_accepted_msg_t *mp;
+ session_event_t *evt;
+
+ app_mq = app->event_queue;
+ svm_msg_q_lock_and_alloc_msg_w_ring (app_mq, SESSION_MQ_CTRL_EVT_RING,
+ SVM_Q_WAIT, msg);
+ svm_msg_q_unlock (app_mq);
+
+ evt = svm_msg_q_msg_data (app_mq, msg);
+ memset (evt, 0, sizeof (*evt));
+ evt->event_type = SESSION_CTRL_EVT_ACCEPTED;
+ mp = (session_accepted_msg_t *) evt->data;
+ mp->context = app->index;
+ mp->server_rx_fifo = pointer_to_uword (s->server_rx_fifo);
+ mp->server_tx_fifo = pointer_to_uword (s->server_tx_fifo);
+
+ if (session_has_transport (s))
+ {
+ listener = listen_session_get (s->listener_index);
+ mp->listener_handle = listen_session_get_handle (listener);
+ if (application_is_proxy (app))
+ {
+ listener =
+ application_first_listener (app, session_get_fib_proto (s),
+ session_get_transport_proto (s));
+ if (listener)
+ mp->listener_handle = listen_session_get_handle (listener);
+ }
+ vpp_queue = session_manager_get_vpp_event_queue (s->thread_index);
+ mp->vpp_event_queue_address = pointer_to_uword (vpp_queue);
+ mp->handle = session_handle (s);
+ tp_vft = transport_protocol_get_vft (session_get_transport_proto (s));
+ tc = tp_vft->get_connection (s->connection_index, s->thread_index);
+ mp->port = tc->rmt_port;
+ mp->is_ip4 = tc->is_ip4;
+ clib_memcpy (&mp->ip, &tc->rmt_ip, sizeof (tc->rmt_ip));
+ }
+ else
+ {
+ local_session_t *ls = (local_session_t *) s;
+ local_session_t *ll;
+ if (application_local_session_listener_has_transport (ls))
+ {
+ listener = listen_session_get (ls->listener_index);
+ mp->listener_handle = listen_session_get_handle (listener);
+ mp->is_ip4 = session_type_is_ip4 (listener->session_type);
+ }
+ else
+ {
+ ll = application_get_local_listen_session (app, ls->listener_index);
+ if (ll->transport_listener_index != ~0)
+ {
+ listener = listen_session_get (ll->transport_listener_index);
+ mp->listener_handle = listen_session_get_handle (listener);
+ }
+ else
+ {
+ mp->listener_handle = application_local_session_handle (ll);
+ }
+ mp->is_ip4 = session_type_is_ip4 (ll->listener_session_type);
+ }
+ mp->handle = application_local_session_handle (ls);
+ mp->port = ls->port;
+ mp->vpp_event_queue_address = ls->client_evt_q;
+ mp->server_event_queue_address = ls->server_evt_q;
+ }
+ svm_msg_q_add (app_mq, msg, SVM_Q_WAIT);
+
+ return 0;
+}
+
+static void
+mq_send_session_disconnected_cb (stream_session_t * s)
+{
+ application_t *app = application_get (s->app_index);
+ svm_msg_q_msg_t _msg, *msg = &_msg;
+ session_disconnected_msg_t *mp;
+ svm_msg_q_t *app_mq;
+ session_event_t *evt;
+
+ app_mq = app->event_queue;
+ svm_msg_q_lock_and_alloc_msg_w_ring (app_mq, SESSION_MQ_CTRL_EVT_RING,
+ SVM_Q_WAIT, msg);
+ svm_msg_q_unlock (app_mq);
+ evt = svm_msg_q_msg_data (app_mq, msg);
+ memset (evt, 0, sizeof (*evt));
+ evt->event_type = SESSION_CTRL_EVT_DISCONNECTED;
+ mp = (session_disconnected_msg_t *) evt->data;
+ mp->handle = session_handle (s);
+ mp->context = app->api_client_index;
+ svm_msg_q_add (app_mq, msg, SVM_Q_WAIT);
+}
+
+static void
+mq_send_session_reset_cb (stream_session_t * s)
+{
+ application_t *app = application_get (s->app_index);
+ svm_msg_q_msg_t _msg, *msg = &_msg;
+ session_reset_msg_t *mp;
+ svm_msg_q_t *app_mq;
+ session_event_t *evt;
+
+ app_mq = app->event_queue;
+ svm_msg_q_lock_and_alloc_msg_w_ring (app_mq, SESSION_MQ_CTRL_EVT_RING,
+ SVM_Q_WAIT, msg);
+ svm_msg_q_unlock (app_mq);
+ evt = svm_msg_q_msg_data (app_mq, msg);
+ memset (evt, 0, sizeof (*evt));
+ evt->event_type = SESSION_CTRL_EVT_RESET;
+ mp = (session_reset_msg_t *) evt->data;
+ mp->handle = session_handle (s);
+ svm_msg_q_add (app_mq, msg, SVM_Q_WAIT);
+}
+
+static int
+mq_send_session_connected_cb (u32 app_index, u32 api_context,
+ stream_session_t * s, u8 is_fail)
+{
+ svm_msg_q_msg_t _msg, *msg = &_msg;
+ session_connected_msg_t *mp;
+ svm_msg_q_t *vpp_mq, *app_mq;
+ transport_connection_t *tc;
+ session_event_t *evt;
+ application_t *app;
+
+ app = application_get (app_index);
+ app_mq = app->event_queue;
+ if (!app_mq)
+ {
+ clib_warning ("app %u with api index: %u not attached", app->index,
+ app->api_client_index);
+ return -1;
+ }
+
+ svm_msg_q_lock_and_alloc_msg_w_ring (app_mq, SESSION_MQ_CTRL_EVT_RING,
+ SVM_Q_WAIT, msg);
+ svm_msg_q_unlock (app_mq);
+ evt = svm_msg_q_msg_data (app_mq, msg);
+ memset (evt, 0, sizeof (*evt));
+ evt->event_type = SESSION_CTRL_EVT_CONNECTED;
+ mp = (session_connected_msg_t *) evt->data;
+ mp->context = api_context;
+
+ if (is_fail)
+ goto done;
+
+ if (session_has_transport (s))
+ {
+ tc = session_get_transport (s);
+ if (!tc)
+ {
+ is_fail = 1;
+ goto done;
+ }
+
+ vpp_mq = session_manager_get_vpp_event_queue (s->thread_index);
+ mp->handle = session_handle (s);
+ mp->vpp_event_queue_address = pointer_to_uword (vpp_mq);
+ clib_memcpy (mp->lcl_ip, &tc->lcl_ip, sizeof (tc->lcl_ip));
+ mp->is_ip4 = tc->is_ip4;
+ mp->lcl_port = tc->lcl_port;
+ mp->server_rx_fifo = pointer_to_uword (s->server_rx_fifo);
+ mp->server_tx_fifo = pointer_to_uword (s->server_tx_fifo);
+ }
+ else
+ {
+ local_session_t *ls = (local_session_t *) s;
+ mp->handle = application_local_session_handle (ls);
+ mp->lcl_port = ls->port;
+ mp->vpp_event_queue_address = ls->server_evt_q;
+ mp->client_event_queue_address = ls->client_evt_q;
+ mp->server_rx_fifo = pointer_to_uword (s->server_tx_fifo);
+ mp->server_tx_fifo = pointer_to_uword (s->server_rx_fifo);
+ }
+
+done:
+ mp->retval = is_fail ?
+ clib_host_to_net_u32 (VNET_API_ERROR_SESSION_CONNECT) : 0;
+
+ svm_msg_q_add (app_mq, msg, SVM_Q_WAIT);
+ return 0;
+}
+
+static session_cb_vft_t session_mq_cb_vft = {
+ .session_accept_callback = mq_send_session_accepted_cb,
+ .session_disconnect_callback = mq_send_session_disconnected_cb,
+ .session_connected_callback = mq_send_session_connected_cb,
+ .session_reset_callback = mq_send_session_reset_cb,
+ .add_segment_callback = send_add_segment_callback,
+ .del_segment_callback = send_del_segment_callback,
+};
+
static void
vl_api_session_enable_disable_t_handler (vl_api_session_enable_disable_t * mp)
{
@@ -401,7 +602,11 @@ vl_api_application_attach_t_handler (vl_api_application_attach_t * mp)
memset (a, 0, sizeof (*a));
a->api_client_index = mp->client_index;
a->options = mp->options;
- a->session_cb_vft = &session_cb_vft;
+
+ if (a->options[APP_OPTIONS_FLAGS] & APP_OPTIONS_FLAGS_USE_MQ_FOR_CTRL_MSGS)
+ a->session_cb_vft = &session_mq_cb_vft;
+ else
+ a->session_cb_vft = &session_cb_vft;
if (mp->namespace_id_len > 64)
{
diff --git a/src/vnet/session/session_cli.c b/src/vnet/session/session_cli.c
index 201f6f1d66e..06d98ae01db 100755
--- a/src/vnet/session/session_cli.c
+++ b/src/vnet/session/session_cli.c
@@ -20,7 +20,7 @@ format_stream_session_fifos (u8 * s, va_list * args)
{
stream_session_t *ss = va_arg (*args, stream_session_t *);
int verbose = va_arg (*args, int);
- session_fifo_event_t _e, *e = &_e;
+ session_event_t _e, *e = &_e;
u8 found;
if (!ss->server_rx_fifo || !ss->server_tx_fifo)
diff --git a/src/vnet/session/session_node.c b/src/vnet/session/session_node.c
index 350282bd902..bf0c3959471 100644
--- a/src/vnet/session/session_node.c
+++ b/src/vnet/session/session_node.c
@@ -20,9 +20,154 @@
#include <vnet/session/transport.h>
#include <vnet/session/session.h>
#include <vnet/session/application.h>
+#include <vnet/session/application_interface.h>
#include <vnet/session/session_debug.h>
#include <svm/queue.h>
+static void
+session_mq_accepted_reply_handler (void *data)
+{
+ session_accepted_reply_msg_t *mp = (session_accepted_reply_msg_t *) data;
+ vnet_disconnect_args_t _a = { 0 }, *a = &_a;
+ local_session_t *ls;
+ stream_session_t *s;
+
+ /* Server isn't interested, kill the session */
+ if (mp->retval)
+ {
+ a->app_index = mp->context;
+ a->handle = mp->handle;
+ vnet_disconnect_session (a);
+ return;
+ }
+
+ if (session_handle_is_local (mp->handle))
+ {
+ ls = application_get_local_session_from_handle (mp->handle);
+ if (!ls || ls->app_index != mp->context)
+ {
+ clib_warning ("server %u doesn't own local handle %llu",
+ mp->context, mp->handle);
+ return;
+ }
+ if (application_local_session_connect_notify (ls))
+ return;
+ ls->session_state = SESSION_STATE_READY;
+ }
+ else
+ {
+ s = session_get_from_handle_if_valid (mp->handle);
+ if (!s)
+ {
+ clib_warning ("session doesn't exist");
+ return;
+ }
+ if (s->app_index != mp->context)
+ {
+ clib_warning ("app doesn't own session");
+ return;
+ }
+ s->session_state = SESSION_STATE_READY;
+ }
+}
+
+static void
+session_mq_reset_reply_handler (void *data)
+{
+ session_reset_reply_msg_t *mp;
+ application_t *app;
+ stream_session_t *s;
+ u32 index, thread_index;
+
+ mp = (session_reset_reply_msg_t *) data;
+ app = application_lookup (mp->client_index);
+ if (!app)
+ return;
+
+ session_parse_handle (mp->handle, &index, &thread_index);
+ s = session_get_if_valid (index, thread_index);
+ if (s == 0 || app->index != s->app_index)
+ {
+ clib_warning ("Invalid session!");
+ return;
+ }
+
+ /* Client objected to resetting the session, log and continue */
+ if (mp->retval)
+ {
+ clib_warning ("client retval %d", mp->retval);
+ return;
+ }
+
+ /* This comes as a response to a reset, transport only waiting for
+ * confirmation to remove connection state, no need to disconnect */
+ stream_session_cleanup (s);
+}
+
+static void
+session_mq_disconnected_handler (void *data)
+{
+ session_disconnected_reply_msg_t *rmp;
+ vnet_disconnect_args_t _a, *a = &_a;
+ svm_msg_q_msg_t _msg, *msg = &_msg;
+ session_disconnected_msg_t *mp;
+ session_event_t *evt;
+ application_t *app;
+ int rv = 0;
+
+ mp = (session_disconnected_msg_t *) data;
+ app = application_lookup (mp->client_index);
+ if (app)
+ {
+ a->handle = mp->handle;
+ a->app_index = app->index;
+ rv = vnet_disconnect_session (a);
+ }
+ else
+ {
+ rv = VNET_API_ERROR_APPLICATION_NOT_ATTACHED;
+ }
+
+ svm_msg_q_lock_and_alloc_msg_w_ring (app->event_queue,
+ SESSION_MQ_CTRL_EVT_RING,
+ SVM_Q_WAIT, msg);
+ svm_msg_q_unlock (app->event_queue);
+ evt = svm_msg_q_msg_data (app->event_queue, msg);
+ memset (evt, 0, sizeof (*evt));
+ evt->event_type = SESSION_CTRL_EVT_DISCONNECTED;
+ rmp = (session_disconnected_reply_msg_t *) evt->data;
+ rmp->handle = mp->handle;
+ rmp->context = mp->context;
+ rmp->retval = rv;
+ svm_msg_q_add (app->event_queue, msg, SVM_Q_WAIT);
+}
+
+static void
+session_mq_disconnected_reply_handler (void *data)
+{
+ session_disconnected_reply_msg_t *mp;
+ vnet_disconnect_args_t _a, *a = &_a;
+ application_t *app;
+
+ mp = (session_disconnected_reply_msg_t *) data;
+
+ /* Client objected to disconnecting the session, log and continue */
+ if (mp->retval)
+ {
+ clib_warning ("client retval %d", mp->retval);
+ return;
+ }
+
+ /* Disconnect has been confirmed. Confirm close to transport */
+ app = application_lookup (mp->context);
+ if (app)
+ {
+ a->handle = mp->handle;
+ a->app_index = app->index;
+ vnet_disconnect_session (a);
+ }
+}
+
vlib_node_registration_t session_queue_node;
typedef struct
@@ -44,8 +189,6 @@ format_session_queue_trace (u8 * s, va_list * args)
return s;
}
-vlib_node_registration_t session_queue_node;
-
#define foreach_session_queue_error \
_(TX, "Packets transmitted") \
_(TIMER, "Timer events") \
@@ -72,7 +215,6 @@ enum
SESSION_TX_OK
};
-
static void
session_tx_trace_frame (vlib_main_t * vm, vlib_node_runtime_t * node,
u32 next_index, u32 * to_next, u16 n_segs,
@@ -369,7 +511,7 @@ session_tx_set_dequeue_params (vlib_main_t * vm, session_tx_context_t * ctx,
always_inline int
session_tx_fifo_read_and_snd_i (vlib_main_t * vm, vlib_node_runtime_t * node,
- session_fifo_event_t * e,
+ session_event_t * e,
stream_session_t * s, int *n_tx_packets,
u8 peek_data)
{
@@ -538,7 +680,7 @@ session_tx_fifo_read_and_snd_i (vlib_main_t * vm, vlib_node_runtime_t * node,
int
session_tx_fifo_peek_and_snd (vlib_main_t * vm, vlib_node_runtime_t * node,
- session_fifo_event_t * e,
+ session_event_t * e,
stream_session_t * s, int *n_tx_pkts)
{
return session_tx_fifo_read_and_snd_i (vm, node, e, s, n_tx_pkts, 1);
@@ -546,7 +688,7 @@ session_tx_fifo_peek_and_snd (vlib_main_t * vm, vlib_node_runtime_t * node,
int
session_tx_fifo_dequeue_and_snd (vlib_main_t * vm, vlib_node_runtime_t * node,
- session_fifo_event_t * e,
+ session_event_t * e,
stream_session_t * s, int *n_tx_pkts)
{
return session_tx_fifo_read_and_snd_i (vm, node, e, s, n_tx_pkts, 0);
@@ -555,7 +697,7 @@ session_tx_fifo_dequeue_and_snd (vlib_main_t * vm, vlib_node_runtime_t * node,
int
session_tx_fifo_dequeue_internal (vlib_main_t * vm,
vlib_node_runtime_t * node,
- session_fifo_event_t * e,
+ session_event_t * e,
stream_session_t * s, int *n_tx_pkts)
{
application_t *app;
@@ -565,7 +707,7 @@ session_tx_fifo_dequeue_internal (vlib_main_t * vm,
}
always_inline stream_session_t *
-session_event_get_session (session_fifo_event_t * e, u8 thread_index)
+session_event_get_session (session_event_t * e, u8 thread_index)
{
return session_get_if_valid (e->fifo->master_session_index, thread_index);
}
@@ -576,8 +718,8 @@ session_queue_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
{
session_manager_main_t *smm = vnet_get_session_manager_main ();
u32 thread_index = vm->thread_index, n_to_dequeue, n_events;
- session_fifo_event_t *pending_events, *e;
- session_fifo_event_t *fifo_events;
+ session_event_t *pending_events, *e;
+ session_event_t *fifo_events;
svm_msg_q_msg_t _msg, *msg = &_msg;
f64 now = vlib_time_now (vm);
int n_tx_packets = 0, i, rv;
@@ -644,7 +786,7 @@ skip_dequeue:
for (i = 0; i < n_events; i++)
{
stream_session_t *s; /* $$$ prefetch 1 ahead maybe */
- session_fifo_event_t *e;
+ session_event_t *e;
u32 to_dequeue;
e = &fifo_events[i];
@@ -715,7 +857,20 @@ skip_dequeue:
fp = e->rpc_args.fp;
(*fp) (e->rpc_args.arg);
break;
-
+ case SESSION_CTRL_EVT_DISCONNECTED:
+ session_mq_disconnected_handler (e->data);
+ break;
+ case SESSION_CTRL_EVT_ACCEPTED_REPLY:
+ session_mq_accepted_reply_handler (e->data);
+ break;
+ case SESSION_CTRL_EVT_CONNECTED_REPLY:
+ break;
+ case SESSION_CTRL_EVT_DISCONNECTED_REPLY:
+ session_mq_disconnected_reply_handler (e->data);
+ break;
+ case SESSION_CTRL_EVT_RESET_REPLY:
+ session_mq_reset_reply_handler (e->data);
+ break;
default:
clib_warning ("unhandled event type %d", e->event_type);
}
@@ -751,7 +906,7 @@ dump_thread_0_event_queue (void)
session_manager_main_t *smm = vnet_get_session_manager_main ();
vlib_main_t *vm = &vlib_global_main;
u32 my_thread_index = vm->thread_index;
- session_fifo_event_t _e, *e = &_e;
+ session_event_t _e, *e = &_e;
svm_msg_q_ring_t *ring;
stream_session_t *s0;
svm_msg_q_msg_t *msg;
@@ -804,7 +959,7 @@ dump_thread_0_event_queue (void)
}
static u8
-session_node_cmp_event (session_fifo_event_t * e, svm_fifo_t * f)
+session_node_cmp_event (session_event_t * e, svm_fifo_t * f)
{
stream_session_t *s;
switch (e->event_type)
@@ -834,11 +989,11 @@ session_node_cmp_event (session_fifo_event_t * e, svm_fifo_t * f)
}
u8
-session_node_lookup_fifo_event (svm_fifo_t * f, session_fifo_event_t * e)
+session_node_lookup_fifo_event (svm_fifo_t * f, session_event_t * e)
{
session_manager_main_t *smm = vnet_get_session_manager_main ();
svm_msg_q_t *mq;
- session_fifo_event_t *pending_event_vector, *evt;
+ session_event_t *pending_event_vector, *evt;
int i, index, found = 0;
svm_msg_q_msg_t *msg;
svm_msg_q_ring_t *ring;