aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorFlorin Coras <fcoras@cisco.com>2017-12-09 10:19:43 -0800
committerDave Barach <openvpp@barachs.net>2017-12-11 21:07:22 +0000
commit561af9b441c7392cf391dd46399b0b16b876a08a (patch)
treed5aa49c73728b6f7cb55071a5398ee9cdba53808 /src
parentd78349109fdb98fa0ba5f5aff779be700ff78357 (diff)
session: generalize handling of network transports
- compute session type out of transport and network protos - make session, session lookup and session queue code network protocol agnostic This does not update the session layer to support non-ip network layer protocols Change-Id: Ifc2f92845e158b649d59462eb7d51c12af536691 Signed-off-by: Florin Coras <fcoras@cisco.com>
Diffstat (limited to 'src')
-rw-r--r--src/vnet/session/application.c30
-rw-r--r--src/vnet/session/session.c97
-rw-r--r--src/vnet/session/session.h57
-rwxr-xr-xsrc/vnet/session/session_api.c2
-rwxr-xr-xsrc/vnet/session/session_cli.c2
-rw-r--r--src/vnet/session/session_lookup.c106
-rw-r--r--src/vnet/session/session_node.c29
-rw-r--r--src/vnet/session/stream_session.h16
-rw-r--r--src/vnet/session/transport.c67
-rw-r--r--src/vnet/session/transport.h1
-rw-r--r--src/vnet/session/transport_interface.h19
-rw-r--r--src/vnet/tcp/tcp.c21
-rw-r--r--src/vnet/tcp/tcp.h9
-rw-r--r--src/vnet/tcp/tcp_output.c1
-rw-r--r--src/vnet/udp/udp.c7
15 files changed, 263 insertions, 201 deletions
diff --git a/src/vnet/session/application.c b/src/vnet/session/application.c
index 9a540f6b78c..4523d5da4e2 100644
--- a/src/vnet/session/application.c
+++ b/src/vnet/session/application.c
@@ -573,8 +573,8 @@ application_start_stop_proxy_fib_proto (application_t * app, u8 fib_proto,
}
void
-application_start_stop_proxy (application_t * app, u8 transport_proto,
- u8 is_start)
+application_start_stop_proxy (application_t * app,
+ transport_proto_t transport_proto, u8 is_start)
{
if (application_has_local_scope (app))
{
@@ -605,24 +605,34 @@ void
application_setup_proxy (application_t * app)
{
u16 transports = app->proxied_transports;
+ transport_proto_t tp;
+
ASSERT (application_is_proxy (app));
if (application_is_builtin (app))
return;
- if (transports & (1 << TRANSPORT_PROTO_TCP))
- application_start_stop_proxy (app, TRANSPORT_PROTO_TCP, 1);
- if (transports & (1 << TRANSPORT_PROTO_UDP))
- application_start_stop_proxy (app, TRANSPORT_PROTO_UDP, 1);
+
+ /* *INDENT-OFF* */
+ transport_proto_foreach (tp, ({
+ if (transports & (1 << tp))
+ application_start_stop_proxy (app, tp, 1);
+ }));
+ /* *INDENT-ON* */
}
void
application_remove_proxy (application_t * app)
{
u16 transports = app->proxied_transports;
+ transport_proto_t tp;
+
ASSERT (application_is_proxy (app));
- if (transports & (1 << TRANSPORT_PROTO_TCP))
- application_start_stop_proxy (app, TRANSPORT_PROTO_TCP, 0);
- if (transports & (1 << TRANSPORT_PROTO_UDP))
- application_start_stop_proxy (app, TRANSPORT_PROTO_UDP, 0);
+
+ /* *INDENT-OFF* */
+ transport_proto_foreach (tp, ({
+ if (transports & (1 << tp))
+ application_start_stop_proxy (app, tp, 0);
+ }));
+ /* *INDENT-ON* */
}
u8 *
diff --git a/src/vnet/session/session.c b/src/vnet/session/session.c
index 616bfc9f150..408a1f5caf0 100644
--- a/src/vnet/session/session.c
+++ b/src/vnet/session/session.c
@@ -23,7 +23,6 @@
#include <vlibmemory/api.h>
#include <vnet/dpo/load_balance.h>
#include <vnet/fib/ip4_fib.h>
-#include <vnet/tcp/tcp.h>
session_manager_main_t session_manager_main;
extern transport_proto_vft_t *tp_vfts;
@@ -623,12 +622,14 @@ static void
session_switch_pool (void *cb_args)
{
session_switch_pool_args_t *args = (session_switch_pool_args_t *) cb_args;
+ transport_proto_t tp;
stream_session_t *s;
ASSERT (args->thread_index == vlib_get_thread_index ());
s = session_get (args->session_index, args->thread_index);
s->server_tx_fifo->master_session_index = args->new_session_index;
s->server_tx_fifo->master_thread_index = args->new_thread_index;
- tp_vfts[s->session_type].cleanup (s->connection_index, s->thread_index);
+ tp = session_get_transport_proto (s);
+ tp_vfts[tp].cleanup (s->connection_index, s->thread_index);
session_free (s);
clib_mem_free (cb_args);
}
@@ -806,22 +807,22 @@ int
session_open (u32 app_index, session_endpoint_t * rmt, u32 opaque)
{
transport_connection_t *tc;
- session_type_t sst;
+ transport_endpoint_t *tep;
segment_manager_t *sm;
stream_session_t *s;
application_t *app;
int rv;
u64 handle;
- sst = session_type_from_proto_and_ip (rmt->transport_proto, rmt->is_ip4);
- rv = tp_vfts[sst].open (session_endpoint_to_transport (rmt));
+ tep = session_endpoint_to_transport (rmt);
+ rv = tp_vfts[rmt->transport_proto].open (tep);
if (rv < 0)
{
SESSION_DBG ("Transport failed to open connection.");
return VNET_API_ERROR_SESSION_CONNECT;
}
- tc = tp_vfts[sst].get_half_open ((u32) rv);
+ tc = tp_vfts[rmt->transport_proto].get_half_open ((u32) rv);
/* If transport offers a stream service, only allocate session once the
* connection has been established.
@@ -874,15 +875,16 @@ stream_session_listen (stream_session_t * s, session_endpoint_t * sep)
u32 tci;
/* Transport bind/listen */
- tci = tp_vfts[s->session_type].bind (s->session_index,
- session_endpoint_to_transport (sep));
+ tci = tp_vfts[sep->transport_proto].bind (s->session_index,
+ session_endpoint_to_transport
+ (sep));
if (tci == (u32) ~ 0)
return -1;
/* Attach transport to session */
s->connection_index = tci;
- tc = tp_vfts[s->session_type].get_listener (tci);
+ tc = tp_vfts[sep->transport_proto].get_listener (tci);
/* Weird but handle it ... */
if (tc == 0)
@@ -901,15 +903,15 @@ stream_session_listen (stream_session_t * s, session_endpoint_t * sep)
int
stream_session_stop_listen (stream_session_t * s)
{
+ transport_proto_t tp = session_get_transport_proto (s);
transport_connection_t *tc;
-
if (s->session_state != SESSION_STATE_LISTENING)
{
clib_warning ("not a listening session");
return -1;
}
- tc = tp_vfts[s->session_type].get_listener (s->connection_index);
+ tc = tp_vfts[tp].get_listener (s->connection_index);
if (!tc)
{
clib_warning ("no transport");
@@ -917,7 +919,7 @@ stream_session_stop_listen (stream_session_t * s)
}
session_lookup_del_connection (tc);
- tp_vfts[s->session_type].unbind (s->connection_index);
+ tp_vfts[tp].unbind (s->connection_index);
return 0;
}
@@ -932,7 +934,8 @@ void
stream_session_disconnect (stream_session_t * s)
{
s->session_state = SESSION_STATE_CLOSED;
- tp_vfts[s->session_type].close (s->connection_index, s->thread_index);
+ tp_vfts[session_get_transport_proto (s)].close (s->connection_index,
+ s->thread_index);
}
/**
@@ -953,7 +956,8 @@ stream_session_cleanup (stream_session_t * s)
if (rv)
clib_warning ("hash delete error, rv %d", rv);
- tp_vfts[s->session_type].cleanup (s->connection_index, s->thread_index);
+ tp_vfts[session_get_transport_proto (s)].cleanup (s->connection_index,
+ s->thread_index);
}
/**
@@ -985,49 +989,66 @@ session_vpp_event_queue_allocate (session_manager_main_t * smm,
}
}
-session_type_t
-session_type_from_proto_and_ip (transport_proto_t proto, u8 is_ip4)
+/**
+ * Initialize session layer for given transport proto and ip version
+ *
+ * Allocates per session type (transport proto + ip version) data structures
+ * and adds arc from session queue node to session type output node.
+ */
+void
+session_register_transport (transport_proto_t transport_proto,
+ const transport_proto_vft_t * vft, u8 is_ip4,
+ u32 output_node)
{
- if (proto == TRANSPORT_PROTO_TCP)
- {
- if (is_ip4)
- return SESSION_TYPE_IP4_TCP;
- else
- return SESSION_TYPE_IP6_TCP;
- }
- else
- {
- if (is_ip4)
- return SESSION_TYPE_IP4_UDP;
- else
- return SESSION_TYPE_IP6_UDP;
- }
+ session_manager_main_t *smm = &session_manager_main;
+ session_type_t session_type;
+ u32 next_index = ~0;
+
+ session_type = session_type_from_proto_and_ip (transport_proto, is_ip4);
+
+ vec_validate (smm->session_type_to_next, session_type);
+ vec_validate (smm->listen_sessions, session_type);
+ vec_validate (smm->session_tx_fns, session_type);
+
+ /* *INDENT-OFF* */
+ foreach_vlib_main (({
+ next_index = vlib_node_add_next (this_vlib_main, session_queue_node.index,
+ output_node);
+ }));
+ /* *INDENT-ON* */
- return SESSION_N_TYPES;
+ smm->session_type_to_next[session_type] = next_index;
+ session_manager_set_transport_rx_fn (session_type,
+ vft->tx_fifo_offset != 0);
}
transport_connection_t *
session_get_transport (stream_session_t * s)
{
+ transport_proto_t tp;
if (s->session_state != SESSION_STATE_LISTENING)
- return tp_vfts[s->session_type].get_connection (s->connection_index,
- s->thread_index);
+ {
+ tp = session_get_transport_proto (s);
+ return tp_vfts[tp].get_connection (s->connection_index,
+ s->thread_index);
+ }
return 0;
}
transport_connection_t *
listen_session_get_transport (stream_session_t * s)
{
- return tp_vfts[s->session_type].get_listener (s->connection_index);
+ transport_proto_t tp = session_get_transport_proto (s);
+ return tp_vfts[tp].get_listener (s->connection_index);
}
int
listen_session_get_local_session_endpoint (stream_session_t * listener,
session_endpoint_t * sep)
{
+ transport_proto_t tp = session_get_transport_proto (listener);
transport_connection_t *tc;
- tc =
- tp_vfts[listener->session_type].get_listener (listener->connection_index);
+ tc = tp_vfts[tp].get_listener (listener->connection_index);
if (!tc)
{
clib_warning ("no transport");
@@ -1128,8 +1149,8 @@ session_manager_main_enable (vlib_main_t * vm)
smm->is_enabled = 1;
- /* Enable TCP transport */
- vnet_tcp_enable_disable (vm, 1);
+ /* Enable transports */
+ transport_enable_disable (vm, 1);
return 0;
}
diff --git a/src/vnet/session/session.h b/src/vnet/session/session.h
index d7bb18e4127..b76e56de50b 100644
--- a/src/vnet/session/session.h
+++ b/src/vnet/session/session.h
@@ -80,17 +80,6 @@ typedef enum
SESSION_N_ERROR,
} session_error_t;
-/* Event queue input node static next indices */
-typedef enum
-{
- SESSION_QUEUE_NEXT_DROP,
- SESSION_QUEUE_NEXT_TCP_IP4_OUTPUT,
- SESSION_QUEUE_NEXT_IP4_LOOKUP,
- SESSION_QUEUE_NEXT_TCP_IP6_OUTPUT,
- SESSION_QUEUE_NEXT_IP6_LOOKUP,
- SESSION_QUEUE_N_NEXT,
-} session_queue_next_t;
-
typedef struct
{
void *fp;
@@ -137,7 +126,7 @@ struct _session_manager_main
clib_spinlock_t *peekers_write_locks;
/** Pool of listen sessions. Same type as stream sessions to ease lookups */
- stream_session_t *listen_sessions[SESSION_N_TYPES];
+ stream_session_t **listen_sessions;
/** Per-proto, per-worker enqueue epoch counters */
u32 *current_enqueue_epoch[TRANSPORT_N_PROTO];
@@ -164,7 +153,12 @@ struct _session_manager_main
u32 unique_segment_name_counter;
/** Per transport rx function that can either dequeue or peek */
- session_fifo_rx_fn *session_tx_fns[SESSION_N_TYPES];
+ session_fifo_rx_fn **session_tx_fns;
+
+ /** Per session type output nodes. Could optimize to group nodes by
+ * fib but lookup would then require session type parsing in session node.
+ * Trade memory for speed, for now */
+ u32 *session_type_to_next;
/** Session manager is enabled */
u8 is_enabled;
@@ -285,6 +279,18 @@ session_get_from_handle (u64 handle)
session_index_from_handle (handle));
}
+always_inline transport_proto_t
+session_get_transport_proto (stream_session_t * s)
+{
+ return (s->session_type >> 1);
+}
+
+always_inline session_type_t
+session_type_from_proto_and_ip (transport_proto_t proto, u8 is_ip4)
+{
+ return (proto << 1 | is_ip4);
+}
+
/**
* Acquires a lock that blocks a session pool from expanding.
*
@@ -443,10 +449,9 @@ uword unformat_stream_session (unformat_input_t * input, va_list * args);
uword unformat_transport_connection (unformat_input_t * input,
va_list * args);
-int
-send_session_connected_callback (u32 app_index, u32 api_context,
- stream_session_t * s, u8 is_fail);
-
+void session_register_transport (transport_proto_t transport_proto,
+ const transport_proto_vft_t * vft, u8 is_ip4,
+ u32 output_node);
clib_error_t *vnet_session_enable_disable (vlib_main_t * vm, u8 is_en);
@@ -517,23 +522,25 @@ listen_session_get_local_session_endpoint (stream_session_t * listener,
session_endpoint_t * sep);
always_inline stream_session_t *
-session_manager_get_listener (u8 type, u32 index)
+session_manager_get_listener (u8 session_type, u32 index)
{
- return pool_elt_at_index (session_manager_main.listen_sessions[type],
- index);
+ return
+ pool_elt_at_index (session_manager_main.listen_sessions[session_type],
+ index);
}
+/**
+ * Set peek or dequeue function for given session type
+ *
+ * Reliable transport protocols will probably want to use a peek function
+ */
always_inline void
-session_manager_set_transport_rx_fn (u8 type, u8 is_peek)
+session_manager_set_transport_rx_fn (session_type_t type, u8 is_peek)
{
- /* If an offset function is provided, then peek instead of dequeue */
session_manager_main.session_tx_fns[type] = (is_peek) ?
session_tx_fifo_peek_and_snd : session_tx_fifo_dequeue_and_snd;
}
-session_type_t
-session_type_from_proto_and_ip (transport_proto_t proto, u8 is_ip4);
-
always_inline u8
session_manager_is_enabled ()
{
diff --git a/src/vnet/session/session_api.c b/src/vnet/session/session_api.c
index 7f1e69b058e..57f55eb0db8 100755
--- a/src/vnet/session/session_api.c
+++ b/src/vnet/session/session_api.c
@@ -103,7 +103,7 @@ send_session_accept_callback (stream_session_t * s)
mp->_vl_msg_id = clib_host_to_net_u16 (VL_API_ACCEPT_SESSION);
mp->context = server->index;
listener = listen_session_get (s->session_type, s->listener_index);
- tp_vft = transport_protocol_get_vft (s->session_type);
+ tp_vft = transport_protocol_get_vft (session_get_transport_proto (s));
tc = tp_vft->get_connection (s->connection_index, s->thread_index);
mp->listener_handle = listen_session_get_handle (listener);
diff --git a/src/vnet/session/session_cli.c b/src/vnet/session/session_cli.c
index 3423026147c..929e604b01e 100755
--- a/src/vnet/session/session_cli.c
+++ b/src/vnet/session/session_cli.c
@@ -55,7 +55,7 @@ format_stream_session (u8 * s, va_list * args)
int verbose = va_arg (*args, int);
transport_proto_vft_t *tp_vft;
u8 *str = 0;
- tp_vft = transport_protocol_get_vft (ss->session_type);
+ tp_vft = transport_protocol_get_vft (session_get_transport_proto (ss));
if (verbose == 1 && ss->session_state >= SESSION_STATE_ACCEPTING)
str = format (0, "%-10u%-10u%-10lld",
diff --git a/src/vnet/session/session_lookup.c b/src/vnet/session/session_lookup.c
index 2e4e96a4dea..68886a09456 100644
--- a/src/vnet/session/session_lookup.c
+++ b/src/vnet/session/session_lookup.c
@@ -127,10 +127,10 @@ make_v4_proxy_kv (session_kv4_t * kv, ip4_address_t * lcl, u8 proto)
}
always_inline void
-make_v4_ss_kv_from_tc (session_kv4_t * kv, transport_connection_t * t)
+make_v4_ss_kv_from_tc (session_kv4_t * kv, transport_connection_t * tc)
{
- make_v4_ss_kv (kv, &t->lcl_ip.ip4, &t->rmt_ip.ip4, t->lcl_port, t->rmt_port,
- session_type_from_proto_and_ip (t->proto, 1));
+ make_v4_ss_kv (kv, &tc->lcl_ip.ip4, &tc->rmt_ip.ip4, tc->lcl_port,
+ tc->rmt_port, tc->proto);
}
always_inline void
@@ -187,10 +187,10 @@ make_v6_proxy_kv (session_kv6_t * kv, ip6_address_t * lcl, u8 proto)
}
always_inline void
-make_v6_ss_kv_from_tc (session_kv6_t * kv, transport_connection_t * t)
+make_v6_ss_kv_from_tc (session_kv6_t * kv, transport_connection_t * tc)
{
- make_v6_ss_kv (kv, &t->lcl_ip.ip6, &t->rmt_ip.ip6, t->lcl_port, t->rmt_port,
- session_type_from_proto_and_ip (t->proto, 0));
+ make_v6_ss_kv (kv, &tc->lcl_ip.ip6, &tc->rmt_ip.ip6, tc->lcl_port,
+ tc->rmt_port, tc->proto);
}
static session_table_t *
@@ -372,9 +372,9 @@ session_lookup_del_connection (transport_connection_t * tc)
int
session_lookup_del_session (stream_session_t * s)
{
+ transport_proto_t tp = session_get_transport_proto (s);
transport_connection_t *ts;
- ts = tp_vfts[s->session_type].get_connection (s->connection_index,
- s->thread_index);
+ ts = tp_vfts[tp].get_connection (s->connection_index, s->thread_index);
return session_lookup_del_connection (ts);
}
@@ -472,9 +472,7 @@ session_lookup_endpoint_listener (u32 table_index, session_endpoint_t * sep,
session_table_t *st;
u32 ai;
int rv;
- u8 sst;
- sst = session_type_from_proto_and_ip (sep->transport_proto, sep->is_ip4);
st = session_table_get (table_index);
if (!st)
return SESSION_INVALID_HANDLE;
@@ -483,7 +481,8 @@ session_lookup_endpoint_listener (u32 table_index, session_endpoint_t * sep,
session_kv4_t kv4;
ip4_address_t lcl4;
- make_v4_listener_kv (&kv4, &sep->ip.ip4, sep->port, sst);
+ make_v4_listener_kv (&kv4, &sep->ip.ip4, sep->port,
+ sep->transport_proto);
rv = clib_bihash_search_inline_16_8 (&st->v4_session_hash, &kv4);
if (rv == 0)
return kv4.value;
@@ -502,7 +501,8 @@ session_lookup_endpoint_listener (u32 table_index, session_endpoint_t * sep,
session_kv6_t kv6;
ip6_address_t lcl6;
- make_v6_listener_kv (&kv6, &sep->ip.ip6, sep->port, sst);
+ make_v6_listener_kv (&kv6, &sep->ip.ip6, sep->port,
+ sep->transport_proto);
rv = clib_bihash_search_inline_48_8 (&st->v6_session_hash, &kv6);
if (rv == 0)
return kv6.value;
@@ -633,14 +633,16 @@ session_lookup_listener4_i (session_table_t * st, ip4_address_t * lcl,
{
session_kv4_t kv4;
int rv;
+ session_type_t session_type;
/*
* First, try a fully formed listener
*/
+ session_type = session_type_from_proto_and_ip (proto, 1);
make_v4_listener_kv (&kv4, lcl, lcl_port, proto);
rv = clib_bihash_search_inline_16_8 (&st->v4_session_hash, &kv4);
if (rv == 0)
- return session_manager_get_listener (proto, (u32) kv4.value);
+ return session_manager_get_listener (session_type, (u32) kv4.value);
/*
* Zero out the lcl ip and check if any 0/0 port binds have been done
@@ -648,7 +650,7 @@ session_lookup_listener4_i (session_table_t * st, ip4_address_t * lcl,
kv4.key[0] = 0;
rv = clib_bihash_search_inline_16_8 (&st->v4_session_hash, &kv4);
if (rv == 0)
- return session_manager_get_listener (proto, (u32) kv4.value);
+ return session_manager_get_listener (session_type, (u32) kv4.value);
/*
* Zero out port and check if we have a proxy set up for our ip
@@ -656,7 +658,7 @@ session_lookup_listener4_i (session_table_t * st, ip4_address_t * lcl,
make_v4_proxy_kv (&kv4, lcl, proto);
rv = clib_bihash_search_inline_16_8 (&st->v4_session_hash, &kv4);
if (rv == 0)
- return session_manager_get_listener (proto, (u32) kv4.value);
+ return session_manager_get_listener (session_type, (u32) kv4.value);
return 0;
}
@@ -678,22 +680,24 @@ session_lookup_listener6_i (session_table_t * st, ip6_address_t * lcl,
{
session_kv6_t kv6;
int rv;
+ session_type_t session_type;
+ session_type = session_type_from_proto_and_ip (proto, 0);
make_v6_listener_kv (&kv6, lcl, lcl_port, proto);
rv = clib_bihash_search_inline_48_8 (&st->v6_session_hash, &kv6);
if (rv == 0)
- return session_manager_get_listener (proto, (u32) kv6.value);
+ return session_manager_get_listener (session_type, (u32) kv6.value);
/* Zero out the lcl ip */
kv6.key[0] = kv6.key[1] = 0;
rv = clib_bihash_search_inline_48_8 (&st->v6_session_hash, &kv6);
if (rv == 0)
- return session_manager_get_listener (proto, (u32) kv6.value);
+ return session_manager_get_listener (session_type, (u32) kv6.value);
make_v6_proxy_kv (&kv6, lcl, proto);
rv = clib_bihash_search_inline_48_8 (&st->v6_session_hash, &kv6);
if (rv == 0)
- return session_manager_get_listener (proto, (u32) kv6.value);
+ return session_manager_get_listener (session_type, (u32) kv6.value);
return 0;
}
@@ -869,8 +873,8 @@ session_lookup_connection_wt4 (u32 fib_index, ip4_address_t * lcl,
{
ASSERT ((u32) (kv4.value >> 32) == thread_index);
s = session_get (kv4.value & 0xFFFFFFFFULL, thread_index);
- return tp_vfts[s->session_type].get_connection (s->connection_index,
- thread_index);
+ return tp_vfts[proto].get_connection (s->connection_index,
+ thread_index);
}
/*
@@ -878,10 +882,7 @@ session_lookup_connection_wt4 (u32 fib_index, ip4_address_t * lcl,
*/
rv = clib_bihash_search_inline_16_8 (&st->v4_half_open_hash, &kv4);
if (rv == 0)
- {
- u32 sst = session_type_from_proto_and_ip (proto, 1);
- return tp_vfts[sst].get_half_open (kv4.value & 0xFFFFFFFF);
- }
+ return tp_vfts[proto].get_half_open (kv4.value & 0xFFFFFFFF);
/*
* Check the session rules table
@@ -894,7 +895,7 @@ session_lookup_connection_wt4 (u32 fib_index, ip4_address_t * lcl,
return 0;
if ((s = session_lookup_action_to_session (action_index,
FIB_PROTOCOL_IP4, proto)))
- return tp_vfts[s->session_type].get_listener (s->connection_index);
+ return tp_vfts[proto].get_listener (s->connection_index);
return 0;
}
@@ -903,7 +904,7 @@ session_lookup_connection_wt4 (u32 fib_index, ip4_address_t * lcl,
*/
s = session_lookup_listener4_i (st, lcl, lcl_port, proto);
if (s)
- return tp_vfts[s->session_type].get_listener (s->connection_index);
+ return tp_vfts[proto].get_listener (s->connection_index);
return 0;
}
@@ -947,8 +948,8 @@ session_lookup_connection4 (u32 fib_index, ip4_address_t * lcl,
if (rv == 0)
{
s = session_get_from_handle (kv4.value);
- return tp_vfts[s->session_type].get_connection (s->connection_index,
- s->thread_index);
+ return tp_vfts[proto].get_connection (s->connection_index,
+ s->thread_index);
}
/*
@@ -956,10 +957,7 @@ session_lookup_connection4 (u32 fib_index, ip4_address_t * lcl,
*/
rv = clib_bihash_search_inline_16_8 (&st->v4_half_open_hash, &kv4);
if (rv == 0)
- {
- u32 sst = session_type_from_proto_and_ip (proto, 1);
- return tp_vfts[sst].get_half_open (kv4.value & 0xFFFFFFFF);
- }
+ return tp_vfts[proto].get_half_open (kv4.value & 0xFFFFFFFF);
/*
* Check the session rules table
@@ -972,7 +970,7 @@ session_lookup_connection4 (u32 fib_index, ip4_address_t * lcl,
return 0;
if ((s = session_lookup_action_to_session (action_index,
FIB_PROTOCOL_IP4, proto)))
- return tp_vfts[s->session_type].get_listener (s->connection_index);
+ return tp_vfts[proto].get_listener (s->connection_index);
return 0;
}
@@ -981,7 +979,7 @@ session_lookup_connection4 (u32 fib_index, ip4_address_t * lcl,
*/
s = session_lookup_listener4_i (st, lcl, lcl_port, proto);
if (s)
- return tp_vfts[s->session_type].get_listener (s->connection_index);
+ return tp_vfts[proto].get_listener (s->connection_index);
return 0;
}
@@ -1090,17 +1088,14 @@ session_lookup_connection_wt6 (u32 fib_index, ip6_address_t * lcl,
{
ASSERT ((u32) (kv6.value >> 32) == thread_index);
s = session_get (kv6.value & 0xFFFFFFFFULL, thread_index);
- return tp_vfts[s->session_type].get_connection (s->connection_index,
- thread_index);
+ return tp_vfts[proto].get_connection (s->connection_index,
+ thread_index);
}
/* Try half-open connections */
rv = clib_bihash_search_inline_48_8 (&st->v6_half_open_hash, &kv6);
if (rv == 0)
- {
- u32 sst = session_type_from_proto_and_ip (proto, 1);
- return tp_vfts[sst].get_half_open (kv6.value & 0xFFFFFFFF);
- }
+ return tp_vfts[proto].get_half_open (kv6.value & 0xFFFFFFFF);
/* Check the session rules table */
action_index = session_rules_table_lookup6 (&st->session_rules[proto], lcl,
@@ -1111,14 +1106,14 @@ session_lookup_connection_wt6 (u32 fib_index, ip6_address_t * lcl,
return 0;
if ((s = session_lookup_action_to_session (action_index,
FIB_PROTOCOL_IP6, proto)))
- return tp_vfts[s->session_type].get_listener (s->connection_index);
+ return tp_vfts[proto].get_listener (s->connection_index);
return 0;
}
/* If nothing is found, check if any listener is available */
s = session_lookup_listener6_i (st, lcl, lcl_port, proto);
if (s)
- return tp_vfts[s->session_type].get_listener (s->connection_index);
+ return tp_vfts[proto].get_listener (s->connection_index);
return 0;
}
@@ -1159,17 +1154,14 @@ session_lookup_connection6 (u32 fib_index, ip6_address_t * lcl,
if (rv == 0)
{
s = session_get_from_handle (kv6.value);
- return tp_vfts[s->session_type].get_connection (s->connection_index,
- s->thread_index);
+ return tp_vfts[proto].get_connection (s->connection_index,
+ s->thread_index);
}
/* Try half-open connections */
rv = clib_bihash_search_inline_48_8 (&st->v6_half_open_hash, &kv6);
if (rv == 0)
- {
- u32 sst = session_type_from_proto_and_ip (proto, 1);
- return tp_vfts[sst].get_half_open (kv6.value & 0xFFFFFFFF);
- }
+ return tp_vfts[proto].get_half_open (kv6.value & 0xFFFFFFFF);
/* Check the session rules table */
action_index = session_rules_table_lookup6 (&st->session_rules[proto], lcl,
@@ -1180,14 +1172,14 @@ session_lookup_connection6 (u32 fib_index, ip6_address_t * lcl,
return 0;
if ((s = session_lookup_action_to_session (action_index,
FIB_PROTOCOL_IP6, proto)))
- return tp_vfts[s->session_type].get_listener (s->connection_index);
+ return tp_vfts[proto].get_listener (s->connection_index);
return 0;
}
/* If nothing is found, check if any listener is available */
s = session_lookup_listener6 (fib_index, lcl, lcl_port, proto);
if (s)
- return tp_vfts[s->session_type].get_listener (s->connection_index);
+ return tp_vfts[proto].get_listener (s->connection_index);
return 0;
}
@@ -1344,22 +1336,22 @@ format_ip4_session_lookup_kvp (u8 * s, va_list * args)
stream_session_t *session;
v4_connection_key_t *key = (v4_connection_key_t *) kvp->key;
- char *proto = key->proto == TRANSPORT_PROTO_TCP ? "T" : "U";
if (!is_local)
{
session = session_get_from_handle (kvp->value);
app_name = application_name_from_index (session->app_index);
- str = format (0, "[%s] %U:%d->%U:%d", proto, format_ip4_address,
- &key->src, clib_net_to_host_u16 (key->src_port),
- format_ip4_address, &key->dst,
- clib_net_to_host_u16 (key->dst_port));
+ str = format (0, "[%U] %U:%d->%U:%d", format_transport_proto_short,
+ key->proto, format_ip4_address, &key->src,
+ clib_net_to_host_u16 (key->src_port), format_ip4_address,
+ &key->dst, clib_net_to_host_u16 (key->dst_port));
s = format (s, "%-40v%-30v", str, app_name);
}
else
{
app_name = application_name_from_index (kvp->value);
- str = format (0, "[%s] %U:%d", proto, format_ip4_address,
- &key->src, clib_net_to_host_u16 (key->src_port));
+ str = format (0, "[%U] %U:%d", format_transport_proto_short, key->proto,
+ format_ip4_address, &key->src,
+ clib_net_to_host_u16 (key->src_port));
s = format (s, "%-30v%-30v", str, app_name);
}
vec_free (app_name);
diff --git a/src/vnet/session/session_node.c b/src/vnet/session/session_node.c
index 08baa447864..e9cfc7be8aa 100644
--- a/src/vnet/session/session_node.c
+++ b/src/vnet/session/session_node.c
@@ -16,8 +16,8 @@
#include <math.h>
#include <vlib/vlib.h>
#include <vnet/vnet.h>
-#include <vnet/tcp/tcp.h>
#include <vppinfra/elog.h>
+#include <vnet/session/transport.h>
#include <vnet/session/application.h>
#include <vnet/session/session_debug.h>
#include <vlibmemory/unix_shared_memory_queue.h>
@@ -64,13 +64,6 @@ static char *session_queue_error_strings[] = {
#undef _
};
-static u32 session_type_to_next[] = {
- SESSION_QUEUE_NEXT_TCP_IP4_OUTPUT,
- SESSION_QUEUE_NEXT_IP4_LOOKUP,
- SESSION_QUEUE_NEXT_TCP_IP6_OUTPUT,
- SESSION_QUEUE_NEXT_IP6_LOOKUP,
-};
-
always_inline void
session_tx_fifo_chain_tail (session_manager_main_t * smm, vlib_main_t * vm,
u8 thread_index, svm_fifo_t * fifo,
@@ -143,6 +136,7 @@ session_tx_fifo_read_and_snd_i (vlib_main_t * vm, vlib_node_runtime_t * node,
u32 n_bufs_per_evt, n_frames_per_evt, n_bufs_per_frame;
transport_connection_t *tc0;
transport_proto_vft_t *transport_vft;
+ transport_proto_t tp;
u32 next_index, next0, *to_next, n_left_to_next, bi0;
vlib_buffer_t *b0;
u32 tx_offset = 0, max_dequeue0, n_bytes_per_seg, left_for_seg;
@@ -152,9 +146,10 @@ session_tx_fifo_read_and_snd_i (vlib_main_t * vm, vlib_node_runtime_t * node,
u32 n_bytes_per_buf, deq_per_buf, deq_per_first_buf;
u32 buffers_allocated, buffers_allocated_this_call;
- next_index = next0 = session_type_to_next[s0->session_type];
+ next_index = next0 = smm->session_type_to_next[s0->session_type];
- transport_vft = transport_protocol_get_vft (s0->session_type);
+ tp = session_get_transport_proto (s0);
+ transport_vft = transport_protocol_get_vft (tp);
tc0 = transport_vft->get_connection (s0->connection_index, thread_index);
/* Make sure we have space to send and there's something to dequeue */
@@ -325,7 +320,6 @@ session_tx_fifo_read_and_snd_i (vlib_main_t * vm, vlib_node_runtime_t * node,
/* *INDENT-ON* */
VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b0);
- tcp_trajectory_add_start (b0, 3);
if (PREDICT_FALSE (n_trace > 0))
{
@@ -550,9 +544,9 @@ session_queue_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
SESSION_EVT_DBG (SESSION_EVT_POLL_GAP_TRACK, smm, my_thread_index);
/*
- * Update TCP time
+ * Update transport time
*/
- tcp_update_time (now, my_thread_index);
+ transport_update_time (now, my_thread_index);
/*
* Get vpp queue events
@@ -695,16 +689,7 @@ VLIB_REGISTER_NODE (session_queue_node) =
.type = VLIB_NODE_TYPE_INPUT,
.n_errors = ARRAY_LEN (session_queue_error_strings),
.error_strings = session_queue_error_strings,
- .n_next_nodes = SESSION_QUEUE_N_NEXT,
.state = VLIB_NODE_STATE_DISABLED,
- .next_nodes =
- {
- [SESSION_QUEUE_NEXT_DROP] = "error-drop",
- [SESSION_QUEUE_NEXT_IP4_LOOKUP] = "ip4-lookup",
- [SESSION_QUEUE_NEXT_IP6_LOOKUP] = "ip6-lookup",
- [SESSION_QUEUE_NEXT_TCP_IP4_OUTPUT] = "tcp4-output",
- [SESSION_QUEUE_NEXT_TCP_IP6_OUTPUT] = "tcp6-output",
- },
};
/* *INDENT-ON* */
diff --git a/src/vnet/session/stream_session.h b/src/vnet/session/stream_session.h
index 51d5065059b..b484efefa01 100644
--- a/src/vnet/session/stream_session.h
+++ b/src/vnet/session/stream_session.h
@@ -20,19 +20,7 @@
#include <svm/svm_fifo.h>
#include <vnet/session/transport.h>
-#define foreach_session_type \
- _(IP4_TCP, ip4_tcp) \
- _(IP4_UDP, ip4_udp) \
- _(IP6_TCP, ip6_tcp) \
- _(IP6_UDP, ip6_udp)
-
-typedef enum
-{
-#define _(A, a) SESSION_TYPE_##A,
- foreach_session_type
-#undef _
- SESSION_N_TYPES,
-} session_type_t;
+typedef u8 session_type_t;
/*
* Application session state
@@ -55,7 +43,7 @@ typedef struct _stream_session_t
svm_fifo_t *server_tx_fifo;
/** Type */
- u8 session_type;
+ session_type_t session_type;
/** State */
volatile u8 session_state;
diff --git a/src/vnet/session/transport.c b/src/vnet/session/transport.c
index b0a5906383d..2f01ac6c092 100644
--- a/src/vnet/session/transport.c
+++ b/src/vnet/session/transport.c
@@ -58,6 +58,22 @@ format_transport_proto (u8 * s, va_list * args)
return s;
}
+u8 *
+format_transport_proto_short (u8 * s, va_list * args)
+{
+ u32 transport_proto = va_arg (*args, u32);
+ switch (transport_proto)
+ {
+ case TRANSPORT_PROTO_TCP:
+ s = format (s, "T");
+ break;
+ case TRANSPORT_PROTO_UDP:
+ s = format (s, "U");
+ break;
+ }
+ return s;
+}
+
uword
unformat_transport_proto (unformat_input_t * input, va_list * args)
{
@@ -123,22 +139,23 @@ transport_endpoint_table_del (transport_endpoint_table_t * ht, u8 proto,
/**
* Register transport virtual function table.
*
- * @param type - session type (not protocol type)
- * @param vft - virtual function table
+ * @param transport_proto - transport protocol type (i.e., TCP, UDP ..)
+ * @param vft - virtual function table for transport proto
+ * @param fib_proto - network layer protocol
+ * @param output_node - output node index that session layer will hand off
+ * buffers to, for requested fib proto
*/
void
-transport_register_protocol (transport_proto_t transport_proto, u8 is_ip4,
- const transport_proto_vft_t * vft)
+transport_register_protocol (transport_proto_t transport_proto,
+ const transport_proto_vft_t * vft,
+ fib_protocol_t fib_proto, u32 output_node)
{
- u8 session_type;
- session_type = session_type_from_proto_and_ip (transport_proto, is_ip4);
+ u8 is_ip4 = fib_proto == FIB_PROTOCOL_IP4;
- vec_validate (tp_vfts, session_type);
- tp_vfts[session_type] = *vft;
+ vec_validate (tp_vfts, transport_proto);
+ tp_vfts[transport_proto] = *vft;
- /* If an offset function is provided, then peek instead of dequeue */
- session_manager_set_transport_rx_fn (session_type,
- vft->tx_fifo_offset != 0);
+ session_register_transport (transport_proto, vft, is_ip4, output_node);
}
/**
@@ -147,11 +164,11 @@ transport_register_protocol (transport_proto_t transport_proto, u8 is_ip4,
* @param type - session type (not protocol type)
*/
transport_proto_vft_t *
-transport_protocol_get_vft (u8 session_type)
+transport_protocol_get_vft (transport_proto_t transport_proto)
{
- if (session_type >= vec_len (tp_vfts))
+ if (transport_proto >= vec_len (tp_vfts))
return 0;
- return &tp_vfts[session_type];
+ return &tp_vfts[transport_proto];
}
#define PORT_MASK ((1 << 16)- 1)
@@ -311,6 +328,28 @@ transport_alloc_local_endpoint (u8 proto, transport_endpoint_t * rmt,
}
void
+transport_update_time (f64 time_now, u8 thread_index)
+{
+ transport_proto_vft_t *vft;
+ vec_foreach (vft, tp_vfts)
+ {
+ if (vft->update_time)
+ (vft->update_time) (time_now, thread_index);
+ }
+}
+
+void
+transport_enable_disable (vlib_main_t * vm, u8 is_en)
+{
+ transport_proto_vft_t *vft;
+ vec_foreach (vft, tp_vfts)
+ {
+ if (vft->enable)
+ (vft->enable) (vm, is_en);
+ }
+}
+
+void
transport_init (void)
{
vlib_thread_main_t *vtm = vlib_get_thread_main ();
diff --git a/src/vnet/session/transport.h b/src/vnet/session/transport.h
index 822dc8317f1..61a2b7b8aa6 100644
--- a/src/vnet/session/transport.h
+++ b/src/vnet/session/transport.h
@@ -74,6 +74,7 @@ typedef enum _transport_proto
} transport_proto_t;
u8 *format_transport_proto (u8 * s, va_list * args);
+u8 *format_transport_proto_short (u8 * s, va_list * args);
uword unformat_transport_proto (unformat_input_t * input, va_list * args);
#define foreach_transport_connection_fields \
diff --git a/src/vnet/session/transport_interface.h b/src/vnet/session/transport_interface.h
index 079e6464268..09542e6a6aa 100644
--- a/src/vnet/session/transport_interface.h
+++ b/src/vnet/session/transport_interface.h
@@ -32,6 +32,7 @@ typedef struct _transport_proto_vft
int (*open) (transport_endpoint_t * rmt);
void (*close) (u32 conn_index, u32 thread_index);
void (*cleanup) (u32 conn_index, u32 thread_index);
+ clib_error_t *(*enable) (vlib_main_t * vm, u8 is_en);
/*
* Transmission
@@ -40,6 +41,7 @@ typedef struct _transport_proto_vft
u16 (*send_mss) (transport_connection_t * tc);
u32 (*send_space) (transport_connection_t * tc);
u32 (*tx_fifo_offset) (transport_connection_t * tc);
+ void (*update_time) (f64 time_now, u8 thread_index);
/*
* Connection retrieval
@@ -56,10 +58,21 @@ typedef struct _transport_proto_vft
u8 *(*format_half_open) (u8 * s, va_list * args);
} transport_proto_vft_t;
+extern transport_proto_vft_t *tp_vfts;
+
+#define transport_proto_foreach(VAR, BODY) \
+do { \
+ for (VAR = 0; VAR < vec_len (tp_vfts); VAR++) \
+ if (tp_vfts[VAR].push_header != 0) \
+ do { BODY; } while (0); \
+} while (0)
+
void transport_register_protocol (transport_proto_t transport_proto,
- u8 is_ip4,
- const transport_proto_vft_t * vft);
-transport_proto_vft_t *transport_protocol_get_vft (u8 session_type);
+ const transport_proto_vft_t * vft,
+ fib_protocol_t fib_proto, u32 output_node);
+transport_proto_vft_t *transport_protocol_get_vft (transport_proto_t tp);
+void transport_update_time (f64 time_now, u8 thread_index);
+void transport_enable_disable (vlib_main_t * vm, u8 is_en);
#endif /* SRC_VNET_SESSION_TRANSPORT_INTERFACE_H_ */
diff --git a/src/vnet/tcp/tcp.c b/src/vnet/tcp/tcp.c
index aee18d997e0..8d222e3c684 100644
--- a/src/vnet/tcp/tcp.c
+++ b/src/vnet/tcp/tcp.c
@@ -1009,8 +1009,18 @@ tcp_session_tx_fifo_offset (transport_connection_t * trans_conn)
return (tc->snd_nxt - tc->snd_una);
}
+void
+tcp_update_time (f64 now, u8 thread_index)
+{
+ tcp_set_time_now (thread_index);
+ tw_timer_expire_timers_16t_2w_512sl (&tcp_main.timer_wheels[thread_index],
+ now);
+ tcp_flush_frames_to_output (thread_index);
+}
+
/* *INDENT-OFF* */
const static transport_proto_vft_t tcp_proto = {
+ .enable = vnet_tcp_enable_disable,
.bind = tcp_session_bind,
.unbind = tcp_session_unbind,
.push_header = tcp_push_header,
@@ -1022,6 +1032,7 @@ const static transport_proto_vft_t tcp_proto = {
.cleanup = tcp_session_cleanup,
.send_mss = tcp_session_send_mss,
.send_space = tcp_session_send_space,
+ .update_time = tcp_update_time,
.tx_fifo_offset = tcp_session_tx_fifo_offset,
.format_connection = format_tcp_session,
.format_listener = format_tcp_listener_session,
@@ -1173,10 +1184,6 @@ tcp_main_enable (vlib_main_t * vm)
ip4_register_protocol (IP_PROTOCOL_TCP, tcp4_input_node.index);
ip6_register_protocol (IP_PROTOCOL_TCP, tcp6_input_node.index);
- /* Register as transport with session layer */
- transport_register_protocol (TRANSPORT_PROTO_TCP, 1, &tcp_proto);
- transport_register_protocol (TRANSPORT_PROTO_TCP, 0, &tcp_proto);
-
/*
* Initialize data structures
*/
@@ -1287,6 +1294,12 @@ tcp_init (vlib_main_t * vm)
pi->format_header = format_tcp_header;
pi->unformat_pg_edit = unformat_pg_tcp_header;
+ /* Register as transport with session layer */
+ transport_register_protocol (TRANSPORT_PROTO_TCP, &tcp_proto,
+ FIB_PROTOCOL_IP4, tcp4_output_node.index);
+ transport_register_protocol (TRANSPORT_PROTO_TCP, &tcp_proto,
+ FIB_PROTOCOL_IP6, tcp6_output_node.index);
+
tcp_api_reference ();
return 0;
}
diff --git a/src/vnet/tcp/tcp.h b/src/vnet/tcp/tcp.h
index a7ae74e06ed..9606a0e1d15 100644
--- a/src/vnet/tcp/tcp.h
+++ b/src/vnet/tcp/tcp.h
@@ -665,15 +665,6 @@ tcp_set_time_now (u32 thread_index)
return tcp_main.time_now[thread_index];
}
-always_inline void
-tcp_update_time (f64 now, u32 thread_index)
-{
- tcp_set_time_now (thread_index);
- tw_timer_expire_timers_16t_2w_512sl (&tcp_main.timer_wheels[thread_index],
- now);
- tcp_flush_frames_to_output (thread_index);
-}
-
u32 tcp_push_header (transport_connection_t * tconn, vlib_buffer_t * b);
u32
diff --git a/src/vnet/tcp/tcp_output.c b/src/vnet/tcp/tcp_output.c
index dd5b384b0c9..0eef942da83 100644
--- a/src/vnet/tcp/tcp_output.c
+++ b/src/vnet/tcp/tcp_output.c
@@ -1973,6 +1973,7 @@ tcp_push_header (transport_connection_t * tconn, vlib_buffer_t * b)
tc->rtt_ts = tcp_time_now ();
tc->rtt_seq = tc->snd_nxt;
}
+ tcp_trajectory_add_start (b0, 3);
return 0;
}
diff --git a/src/vnet/udp/udp.c b/src/vnet/udp/udp.c
index 70091655211..9284cd7b269 100644
--- a/src/vnet/udp/udp.c
+++ b/src/vnet/udp/udp.c
@@ -354,10 +354,11 @@ udp_init (vlib_main_t * vm)
pi->format_header = format_udp_header;
pi->unformat_pg_edit = unformat_pg_udp_header;
-
/* Register as transport with URI */
- transport_register_protocol (TRANSPORT_PROTO_UDP, 1, &udp_proto);
- transport_register_protocol (TRANSPORT_PROTO_UDP, 0, &udp_proto);
+ transport_register_protocol (TRANSPORT_PROTO_UDP, &udp_proto,
+ FIB_PROTOCOL_IP4, ip4_lookup_node.index);
+ transport_register_protocol (TRANSPORT_PROTO_UDP, &udp_proto,
+ FIB_PROTOCOL_IP6, ip6_lookup_node.index);
/*
* Initialize data structures