session: generalize handling of network transports 80/9780/10
authorFlorin Coras <fcoras@cisco.com>
Sat, 9 Dec 2017 18:19:43 +0000 (10:19 -0800)
committerDave Barach <openvpp@barachs.net>
Mon, 11 Dec 2017 21:07:22 +0000 (21:07 +0000)
- 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>
15 files changed:
src/vnet/session/application.c
src/vnet/session/session.c
src/vnet/session/session.h
src/vnet/session/session_api.c
src/vnet/session/session_cli.c
src/vnet/session/session_lookup.c
src/vnet/session/session_node.c
src/vnet/session/stream_session.h
src/vnet/session/transport.c
src/vnet/session/transport.h
src/vnet/session/transport_interface.h
src/vnet/tcp/tcp.c
src/vnet/tcp/tcp.h
src/vnet/tcp/tcp_output.c
src/vnet/udp/udp.c

index 9a540f6..4523d5d 100644 (file)
@@ -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 *
index 616bfc9..408a1f5 100644 (file)
@@ -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;
 }
index d7bb18e..b76e56d 100644 (file)
@@ -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 ()
 {
index 7f1e69b..57f55eb 100755 (executable)
@@ -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);
 
index 3423026..929e604 100755 (executable)
@@ -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",
index 2e4e96a..68886a0 100644 (file)
@@ -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);
index 08baa44..e9cfc7b 100644 (file)
@@ -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* */
 
index 51d5065..b484efe 100644 (file)
 #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;
index b0a5906..2f01ac6 100644 (file)
@@ -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)
@@ -310,6 +327,28 @@ transport_alloc_local_endpoint (u8 proto, transport_endpoint_t * rmt,
   return 0;
 }
 
+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)
 {
index 822dc83..61a2b7b 100644 (file)
@@ -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                            \
index 079e646..09542e6 100644 (file)
@@ -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_ */
 
index aee18d9..8d222e3 100644 (file)
@@ -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;
 }
index a7ae74e..9606a0e 100644 (file)
@@ -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
index dd5b384..0eef942 100644 (file)
@@ -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;
 }
 
index 7009165..9284cd7 100644 (file)
@@ -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