Cleanup/refactor session layer code 88/7588/8
authorFlorin Coras <fcoras@cisco.com>
Mon, 17 Jul 2017 00:12:15 +0000 (17:12 -0700)
committerDave Barach <openvpp@barachs.net>
Tue, 25 Jul 2017 11:17:20 +0000 (11:17 +0000)
Change-Id: Ica99e8cb919fca6b069c37c969d60e8ccc2c6bf9
Signed-off-by: Florin Coras <fcoras@cisco.com>
17 files changed:
src/uri/uri_tcp_test.c
src/uri/uri_udp_test.c
src/vnet.am
src/vnet/session/hashes.c [deleted file]
src/vnet/session/session.c
src/vnet/session/session.h
src/vnet/session/session_lookup.c [new file with mode: 0644]
src/vnet/session/session_lookup.h [new file with mode: 0644]
src/vnet/session/session_node.c [moved from src/vnet/session/node.c with 100% similarity]
src/vnet/session/stream_session.h [new file with mode: 0644]
src/vnet/session/transport.c [deleted file]
src/vnet/session/transport.h
src/vnet/session/transport_interface.c [new file with mode: 0644]
src/vnet/session/transport_interface.h [new file with mode: 0644]
src/vnet/tcp/tcp.c
src/vnet/tcp/tcp_input.c
src/vnet/udp/udp.c

index 80aab18..f5fbbd2 100755 (executable)
 #include <vpp/api/vpe_all_api_h.h>
 #undef vl_printfun
 
-/* Satisfy external references when not linking with -lvlib */
-vlib_main_t vlib_global_main;
-vlib_main_t **vlib_mains;
-
 typedef struct
 {
   svm_fifo_t *server_rx_fifo;
index a8e39ea..aea4707 100644 (file)
 #include <vpp/api/vpe_all_api_h.h>
 #undef vl_printfun
 
-/* Satisfy external references when not linking with -lvlib */
-vlib_main_t vlib_global_main;
-vlib_main_t **vlib_mains;
-
 typedef enum
 {
   STATE_START,
index ebcf0a0..060e3f3 100644 (file)
@@ -832,19 +832,22 @@ nobase_include_HEADERS +=                 \
 
 libvnet_la_SOURCES +=                          \
   vnet/session/session.c                       \
-  vnet/session/node.c                          \
-  vnet/session/transport.c                     \
+  vnet/session/session_lookup.c                        \
+  vnet/session/session_node.c                  \
+  vnet/session/transport_interface.c           \
   vnet/session/application.c                   \
   vnet/session/session_cli.c                   \
-  vnet/session/hashes.c                                \
   vnet/session/application_interface.c         \
   vnet/session/segment_manager.c               \
   vnet/session/session_api.c
 
 nobase_include_HEADERS +=                      \
   vnet/session/session.h                       \
+  vnet/session/stream_session.h                        \
+  vnet/session/session_lookup.h                        \
   vnet/session/application.h                   \
   vnet/session/transport.h                     \
+  vnet/session/transport_interface.h           \
   vnet/session/application_interface.h         \
   vnet/session/session_debug.h                 \
   vnet/session/segment_manager.h               \
diff --git a/src/vnet/session/hashes.c b/src/vnet/session/hashes.c
deleted file mode 100644 (file)
index 1808dd7..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (c) 2016 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/** Generate typed init functions for multiple hash table styles... */
-
-#include <vppinfra/bihash_16_8.h>
-#include <vppinfra/bihash_template.h>
-
-#include <vppinfra/bihash_template.c>
-
-#undef __included_bihash_template_h__
-
-#include <vppinfra/bihash_48_8.h>
-#include <vppinfra/bihash_template.h>
-
-#include <vppinfra/bihash_template.c>
index 09bc00e..48000a6 100644 (file)
  */
 
 #include <vnet/session/session.h>
+#include <vnet/session/session_debug.h>
+#include <vnet/session/application.h>
 #include <vlibmemory/api.h>
 #include <vnet/dpo/load_balance.h>
 #include <vnet/fib/ip4_fib.h>
-#include <vnet/session/application.h>
 #include <vnet/tcp/tcp.h>
-#include <vnet/session/session_debug.h>
-
-/**
- * Per-type vector of transport protocol virtual function tables
- */
-static transport_proto_vft_t *tp_vfts;
 
 session_manager_main_t session_manager_main;
-
-transport_connection_t *
-stream_session_lookup_half_open (transport_connection_t * tc)
-{
-  session_manager_main_t *smm = &session_manager_main;
-  session_kv4_t kv4;
-  int rv;
-  if (tc->is_ip4)
-    {
-      make_v4_ss_kv_from_tc (&kv4, tc);
-      rv = clib_bihash_search_inline_16_8 (&smm->v4_half_open_hash, &kv4);
-      if (rv == 0)
-       return tp_vfts[tc->proto].get_half_open (kv4.value & 0xFFFFFFFFULL);
-    }
-  return 0;
-}
-
-/*
- * Session lookup key; (src-ip, dst-ip, src-port, dst-port, session-type)
- * Value: (owner thread index << 32 | session_index);
- */
-void
-stream_session_table_add_for_tc (transport_connection_t * tc, u64 value)
-{
-  session_manager_main_t *smm = &session_manager_main;
-  session_kv4_t kv4;
-  session_kv6_t kv6;
-
-  switch (tc->proto)
-    {
-    case SESSION_TYPE_IP4_UDP:
-    case SESSION_TYPE_IP4_TCP:
-      make_v4_ss_kv_from_tc (&kv4, tc);
-      kv4.value = value;
-      clib_bihash_add_del_16_8 (&smm->v4_session_hash, &kv4, 1 /* is_add */ );
-      break;
-    case SESSION_TYPE_IP6_UDP:
-    case SESSION_TYPE_IP6_TCP:
-      make_v6_ss_kv_from_tc (&kv6, tc);
-      kv6.value = value;
-      clib_bihash_add_del_48_8 (&smm->v6_session_hash, &kv6, 1 /* is_add */ );
-      break;
-    default:
-      clib_warning ("Session type not supported");
-      ASSERT (0);
-    }
-}
-
-void
-stream_session_table_add (session_manager_main_t * smm, stream_session_t * s,
-                         u64 value)
-{
-  transport_connection_t *tc;
-
-  tc = tp_vfts[s->session_type].get_connection (s->connection_index,
-                                               s->thread_index);
-  stream_session_table_add_for_tc (tc, value);
-}
-
-static void
-stream_session_half_open_table_add (session_type_t sst,
-                                   transport_connection_t * tc, u64 value)
-{
-  session_manager_main_t *smm = &session_manager_main;
-  session_kv4_t kv4;
-  session_kv6_t kv6;
-
-  switch (sst)
-    {
-    case SESSION_TYPE_IP4_UDP:
-    case SESSION_TYPE_IP4_TCP:
-      make_v4_ss_kv_from_tc (&kv4, tc);
-      kv4.value = value;
-      clib_bihash_add_del_16_8 (&smm->v4_half_open_hash, &kv4,
-                               1 /* is_add */ );
-      break;
-    case SESSION_TYPE_IP6_UDP:
-    case SESSION_TYPE_IP6_TCP:
-      make_v6_ss_kv_from_tc (&kv6, tc);
-      kv6.value = value;
-      clib_bihash_add_del_48_8 (&smm->v6_half_open_hash, &kv6,
-                               1 /* is_add */ );
-      break;
-    default:
-      clib_warning ("Session type not supported");
-      ASSERT (0);
-    }
-}
-
-int
-stream_session_table_del_for_tc (transport_connection_t * tc)
-{
-  session_manager_main_t *smm = &session_manager_main;
-  session_kv4_t kv4;
-  session_kv6_t kv6;
-  switch (tc->proto)
-    {
-    case SESSION_TYPE_IP4_UDP:
-    case SESSION_TYPE_IP4_TCP:
-      make_v4_ss_kv_from_tc (&kv4, tc);
-      return clib_bihash_add_del_16_8 (&smm->v4_session_hash, &kv4,
-                                      0 /* is_add */ );
-      break;
-    case SESSION_TYPE_IP6_UDP:
-    case SESSION_TYPE_IP6_TCP:
-      make_v6_ss_kv_from_tc (&kv6, tc);
-      return clib_bihash_add_del_48_8 (&smm->v6_session_hash, &kv6,
-                                      0 /* is_add */ );
-      break;
-    default:
-      clib_warning ("Session type not supported");
-      ASSERT (0);
-    }
-
-  return 0;
-}
-
-static int
-stream_session_table_del (session_manager_main_t * smm, stream_session_t * s)
-{
-  transport_connection_t *ts;
-
-  ts = tp_vfts[s->session_type].get_connection (s->connection_index,
-                                               s->thread_index);
-  return stream_session_table_del_for_tc (ts);
-}
-
-static void
-stream_session_half_open_table_del (session_manager_main_t * smm, u8 sst,
-                                   transport_connection_t * tc)
-{
-  session_kv4_t kv4;
-  session_kv6_t kv6;
-
-  switch (sst)
-    {
-    case SESSION_TYPE_IP4_UDP:
-    case SESSION_TYPE_IP4_TCP:
-      make_v4_ss_kv_from_tc (&kv4, tc);
-      clib_bihash_add_del_16_8 (&smm->v4_half_open_hash, &kv4,
-                               0 /* is_add */ );
-      break;
-    case SESSION_TYPE_IP6_UDP:
-    case SESSION_TYPE_IP6_TCP:
-      make_v6_ss_kv_from_tc (&kv6, tc);
-      clib_bihash_add_del_48_8 (&smm->v6_half_open_hash, &kv6,
-                               0 /* is_add */ );
-      break;
-    default:
-      clib_warning ("Session type not supported");
-      ASSERT (0);
-    }
-}
-
-stream_session_t *
-stream_session_lookup_listener4 (ip4_address_t * lcl, u16 lcl_port, u8 proto)
-{
-  session_manager_main_t *smm = &session_manager_main;
-  session_kv4_t kv4;
-  int rv;
-
-  make_v4_listener_kv (&kv4, lcl, lcl_port, proto);
-  rv = clib_bihash_search_inline_16_8 (&smm->v4_session_hash, &kv4);
-  if (rv == 0)
-    return pool_elt_at_index (smm->listen_sessions[proto], (u32) kv4.value);
-
-  /* Zero out the lcl ip */
-  kv4.key[0] = 0;
-  rv = clib_bihash_search_inline_16_8 (&smm->v4_session_hash, &kv4);
-  if (rv == 0)
-    return pool_elt_at_index (smm->listen_sessions[proto], kv4.value);
-
-  return 0;
-}
-
-/** Looks up a session based on the 5-tuple passed as argument.
- *
- * First it tries to find an established session, if this fails, it tries
- * finding a listener session if this fails, it tries a lookup with a
- * wildcarded local source (listener bound to all interfaces)
- */
-stream_session_t *
-stream_session_lookup4 (ip4_address_t * lcl, ip4_address_t * rmt,
-                       u16 lcl_port, u16 rmt_port, u8 proto)
-{
-  session_manager_main_t *smm = &session_manager_main;
-  session_kv4_t kv4;
-  stream_session_t *s;
-  int rv;
-
-  /* Lookup session amongst established ones */
-  make_v4_ss_kv (&kv4, lcl, rmt, lcl_port, rmt_port, proto);
-  rv = clib_bihash_search_inline_16_8 (&smm->v4_session_hash, &kv4);
-  if (rv == 0)
-    return stream_session_get_from_handle (kv4.value);
-
-  /* If nothing is found, check if any listener is available */
-  if ((s = stream_session_lookup_listener4 (lcl, lcl_port, proto)))
-    return s;
-
-  /* Finally, try half-open connections */
-  rv = clib_bihash_search_inline_16_8 (&smm->v4_half_open_hash, &kv4);
-  if (rv == 0)
-    return stream_session_get_from_handle (kv4.value);
-  return 0;
-}
-
-stream_session_t *
-stream_session_lookup_listener6 (ip6_address_t * lcl, u16 lcl_port, u8 proto)
-{
-  session_manager_main_t *smm = &session_manager_main;
-  session_kv6_t kv6;
-  int rv;
-
-  make_v6_listener_kv (&kv6, lcl, lcl_port, proto);
-  rv = clib_bihash_search_inline_48_8 (&smm->v6_session_hash, &kv6);
-  if (rv == 0)
-    return pool_elt_at_index (smm->listen_sessions[proto], kv6.value);
-
-  /* Zero out the lcl ip */
-  kv6.key[0] = kv6.key[1] = 0;
-  rv = clib_bihash_search_inline_48_8 (&smm->v6_session_hash, &kv6);
-  if (rv == 0)
-    return pool_elt_at_index (smm->listen_sessions[proto], kv6.value);
-
-  return 0;
-}
-
-/* Looks up a session based on the 5-tuple passed as argument.
- * First it tries to find an established session, if this fails, it tries
- * finding a listener session if this fails, it tries a lookup with a
- * wildcarded local source (listener bound to all interfaces) */
-stream_session_t *
-stream_session_lookup6 (ip6_address_t * lcl, ip6_address_t * rmt,
-                       u16 lcl_port, u16 rmt_port, u8 proto)
-{
-  session_manager_main_t *smm = vnet_get_session_manager_main ();
-  session_kv6_t kv6;
-  stream_session_t *s;
-  int rv;
-
-  make_v6_ss_kv (&kv6, lcl, rmt, lcl_port, rmt_port, proto);
-  rv = clib_bihash_search_inline_48_8 (&smm->v6_session_hash, &kv6);
-  if (rv == 0)
-    return stream_session_get_from_handle (kv6.value);
-
-  /* If nothing is found, check if any listener is available */
-  if ((s = stream_session_lookup_listener6 (lcl, lcl_port, proto)))
-    return s;
-
-  /* Finally, try half-open connections */
-  rv = clib_bihash_search_inline_48_8 (&smm->v6_half_open_hash, &kv6);
-  if (rv == 0)
-    return stream_session_get_from_handle (kv6.value);
-  return 0;
-}
-
-stream_session_t *
-stream_session_lookup_listener (ip46_address_t * lcl, u16 lcl_port, u8 proto)
-{
-  switch (proto)
-    {
-    case SESSION_TYPE_IP4_UDP:
-    case SESSION_TYPE_IP4_TCP:
-      return stream_session_lookup_listener4 (&lcl->ip4, lcl_port, proto);
-      break;
-    case SESSION_TYPE_IP6_UDP:
-    case SESSION_TYPE_IP6_TCP:
-      return stream_session_lookup_listener6 (&lcl->ip6, lcl_port, proto);
-      break;
-    }
-  return 0;
-}
-
-static u64
-stream_session_half_open_lookup (session_manager_main_t * smm,
-                                ip46_address_t * lcl, ip46_address_t * rmt,
-                                u16 lcl_port, u16 rmt_port, u8 proto)
-{
-  session_kv4_t kv4;
-  session_kv6_t kv6;
-  int rv;
-
-  switch (proto)
-    {
-    case SESSION_TYPE_IP4_UDP:
-    case SESSION_TYPE_IP4_TCP:
-      make_v4_ss_kv (&kv4, &lcl->ip4, &rmt->ip4, lcl_port, rmt_port, proto);
-      rv = clib_bihash_search_inline_16_8 (&smm->v4_half_open_hash, &kv4);
-
-      if (rv == 0)
-       return kv4.value;
-
-      return (u64) ~ 0;
-      break;
-    case SESSION_TYPE_IP6_UDP:
-    case SESSION_TYPE_IP6_TCP:
-      make_v6_ss_kv (&kv6, &lcl->ip6, &rmt->ip6, lcl_port, rmt_port, proto);
-      rv = clib_bihash_search_inline_48_8 (&smm->v6_half_open_hash, &kv6);
-
-      if (rv == 0)
-       return kv6.value;
-
-      return (u64) ~ 0;
-      break;
-    }
-  return 0;
-}
-
-transport_connection_t *
-stream_session_lookup_transport_wt4 (ip4_address_t * lcl, ip4_address_t * rmt,
-                                    u16 lcl_port, u16 rmt_port, u8 proto,
-                                    u32 my_thread_index)
-{
-  session_manager_main_t *smm = &session_manager_main;
-  session_kv4_t kv4;
-  stream_session_t *s;
-  int rv;
-
-  /* Lookup session amongst established ones */
-  make_v4_ss_kv (&kv4, lcl, rmt, lcl_port, rmt_port, proto);
-  rv = clib_bihash_search_inline_16_8 (&smm->v4_session_hash, &kv4);
-  if (rv == 0)
-    {
-      s = stream_session_get_tsi (kv4.value, my_thread_index);
-
-      return tp_vfts[s->session_type].get_connection (s->connection_index,
-                                                     my_thread_index);
-    }
-
-  /* If nothing is found, check if any listener is available */
-  s = stream_session_lookup_listener4 (lcl, lcl_port, proto);
-  if (s)
-    return tp_vfts[s->session_type].get_listener (s->connection_index);
-
-  /* Finally, try half-open connections */
-  rv = clib_bihash_search_inline_16_8 (&smm->v4_half_open_hash, &kv4);
-  if (rv == 0)
-    return tp_vfts[proto].get_half_open (kv4.value & 0xFFFFFFFF);
-  return 0;
-}
-
-transport_connection_t *
-stream_session_lookup_transport4 (ip4_address_t * lcl, ip4_address_t * rmt,
-                                 u16 lcl_port, u16 rmt_port, u8 proto)
-{
-  session_manager_main_t *smm = &session_manager_main;
-  session_kv4_t kv4;
-  stream_session_t *s;
-  int rv;
-
-  /* Lookup session amongst established ones */
-  make_v4_ss_kv (&kv4, lcl, rmt, lcl_port, rmt_port, proto);
-  rv = clib_bihash_search_inline_16_8 (&smm->v4_session_hash, &kv4);
-  if (rv == 0)
-    {
-      s = stream_session_get_from_handle (kv4.value);
-      return tp_vfts[s->session_type].get_connection (s->connection_index,
-                                                     s->thread_index);
-    }
-
-  /* If nothing is found, check if any listener is available */
-  s = stream_session_lookup_listener4 (lcl, lcl_port, proto);
-  if (s)
-    return tp_vfts[s->session_type].get_listener (s->connection_index);
-
-  /* Finally, try half-open connections */
-  rv = clib_bihash_search_inline_16_8 (&smm->v4_half_open_hash, &kv4);
-  if (rv == 0)
-    return tp_vfts[proto].get_half_open (kv4.value & 0xFFFFFFFF);
-  return 0;
-}
-
-transport_connection_t *
-stream_session_lookup_transport_wt6 (ip6_address_t * lcl, ip6_address_t * rmt,
-                                    u16 lcl_port, u16 rmt_port, u8 proto,
-                                    u32 my_thread_index)
-{
-  session_manager_main_t *smm = &session_manager_main;
-  stream_session_t *s;
-  session_kv6_t kv6;
-  int rv;
-
-  make_v6_ss_kv (&kv6, lcl, rmt, lcl_port, rmt_port, proto);
-  rv = clib_bihash_search_inline_48_8 (&smm->v6_session_hash, &kv6);
-  if (rv == 0)
-    {
-      s = stream_session_get_tsi (kv6.value, my_thread_index);
-
-      return tp_vfts[s->session_type].get_connection (s->connection_index,
-                                                     my_thread_index);
-    }
-
-  /* If nothing is found, check if any listener is available */
-  s = stream_session_lookup_listener6 (lcl, lcl_port, proto);
-  if (s)
-    return tp_vfts[s->session_type].get_listener (s->connection_index);
-
-  /* Finally, try half-open connections */
-  rv = clib_bihash_search_inline_48_8 (&smm->v6_half_open_hash, &kv6);
-  if (rv == 0)
-    return tp_vfts[proto].get_half_open (kv6.value & 0xFFFFFFFF);
-
-  return 0;
-}
-
-transport_connection_t *
-stream_session_lookup_transport6 (ip6_address_t * lcl, ip6_address_t * rmt,
-                                 u16 lcl_port, u16 rmt_port, u8 proto)
-{
-  session_manager_main_t *smm = &session_manager_main;
-  stream_session_t *s;
-  session_kv6_t kv6;
-  int rv;
-
-  make_v6_ss_kv (&kv6, lcl, rmt, lcl_port, rmt_port, proto);
-  rv = clib_bihash_search_inline_48_8 (&smm->v6_session_hash, &kv6);
-  if (rv == 0)
-    {
-      s = stream_session_get_from_handle (kv6.value);
-      return tp_vfts[s->session_type].get_connection (s->connection_index,
-                                                     s->thread_index);
-    }
-
-  /* If nothing is found, check if any listener is available */
-  s = stream_session_lookup_listener6 (lcl, lcl_port, proto);
-  if (s)
-    return tp_vfts[s->session_type].get_listener (s->connection_index);
-
-  /* Finally, try half-open connections */
-  rv = clib_bihash_search_inline_48_8 (&smm->v6_half_open_hash, &kv6);
-  if (rv == 0)
-    return tp_vfts[proto].get_half_open (kv6.value & 0xFFFFFFFF);
-
-  return 0;
-}
+extern transport_proto_vft_t *tp_vfts;
 
 int
 stream_session_create_i (segment_manager_t * sm, transport_connection_t * tc,
@@ -797,16 +357,15 @@ int
 stream_session_connect_notify (transport_connection_t * tc, u8 sst,
                               u8 is_fail)
 {
-  session_manager_main_t *smm = &session_manager_main;
   application_t *app;
   stream_session_t *new_s = 0;
   u64 handle;
   u32 api_context = 0;
   int error = 0;
 
-  handle = stream_session_half_open_lookup (smm, &tc->lcl_ip, &tc->rmt_ip,
-                                           tc->lcl_port, tc->rmt_port,
-                                           tc->proto);
+  handle = stream_session_half_open_lookup_handle (&tc->lcl_ip, &tc->rmt_ip,
+                                                  tc->lcl_port, tc->rmt_port,
+                                                  tc->proto);
   if (handle == HALF_OPEN_LOOKUP_INVALID_VALUE)
     {
       clib_warning ("This can't be good!");
@@ -847,7 +406,7 @@ stream_session_connect_notify (transport_connection_t * tc, u8 sst,
     }
 
   /* Cleanup session lookup */
-  stream_session_half_open_table_del (smm, sst, tc);
+  stream_session_half_open_table_del (sst, tc);
 
   return error;
 }
@@ -891,7 +450,7 @@ stream_session_delete (stream_session_t * s)
   int rv;
 
   /* Delete from the main lookup table. */
-  if ((rv = stream_session_table_del (smm, s)))
+  if ((rv = stream_session_table_del (s)))
     clib_warning ("hash delete error, rv %d", rv);
 
   /* Cleanup fifo segments */
@@ -986,14 +545,14 @@ stream_session_accept (transport_connection_t * tc, u32 listener_index,
  */
 int
 stream_session_open (u32 app_index, session_type_t st,
-                    transport_endpoint_t * tep,
+                    transport_endpoint_t * rmt,
                     transport_connection_t ** res)
 {
   transport_connection_t *tc;
   int rv;
   u64 handle;
 
-  rv = tp_vfts[st].open (&tep->ip, tep->port);
+  rv = tp_vfts[st].open (rmt);
   if (rv < 0)
     {
       clib_warning ("Transport failed to open connection.");
@@ -1030,7 +589,7 @@ stream_session_listen (stream_session_t * s, transport_endpoint_t * tep)
   u32 tci;
 
   /* Transport bind/listen  */
-  tci = tp_vfts[s->session_type].bind (s->session_index, &tep->ip, tep->port);
+  tci = tp_vfts[s->session_type].bind (s->session_index, tep);
 
   if (tci == (u32) ~ 0)
     return -1;
@@ -1132,41 +691,18 @@ stream_session_disconnect (stream_session_t * s)
 void
 stream_session_cleanup (stream_session_t * s)
 {
-  session_manager_main_t *smm = &session_manager_main;
   int rv;
 
   s->session_state = SESSION_STATE_CLOSED;
 
   /* Delete from the main lookup table to avoid more enqueues */
-  rv = stream_session_table_del (smm, s);
+  rv = stream_session_table_del (s);
   if (rv)
     clib_warning ("hash delete error, rv %d", rv);
 
   tp_vfts[s->session_type].cleanup (s->connection_index, s->thread_index);
 }
 
-void
-session_register_transport (u8 type, const transport_proto_vft_t * vft)
-{
-  session_manager_main_t *smm = vnet_get_session_manager_main ();
-
-  vec_validate (tp_vfts, type);
-  tp_vfts[type] = *vft;
-
-  /* If an offset function is provided, then peek instead of dequeue */
-  smm->session_tx_fns[type] =
-    (vft->tx_fifo_offset) ? session_tx_fifo_peek_and_snd :
-    session_tx_fifo_dequeue_and_snd;
-}
-
-transport_proto_vft_t *
-session_get_transport_vft (u8 type)
-{
-  if (type >= vec_len (tp_vfts))
-    return 0;
-  return &tp_vfts[type];
-}
-
 /**
  * Allocate vpp event queue (once) per worker thread
  */
@@ -1269,19 +805,7 @@ session_manager_main_enable (vlib_main_t * vm)
   for (i = 0; i < smm->preallocated_sessions; i++)
     pool_put_index (smm->sessions[0], i);
 
-  clib_bihash_init_16_8 (&smm->v4_session_hash, "v4 session table",
-                        200000 /* $$$$ config parameter nbuckets */ ,
-                        (64 << 20) /*$$$ config parameter table size */ );
-  clib_bihash_init_48_8 (&smm->v6_session_hash, "v6 session table",
-                        200000 /* $$$$ config parameter nbuckets */ ,
-                        (64 << 20) /*$$$ config parameter table size */ );
-
-  clib_bihash_init_16_8 (&smm->v4_half_open_hash, "v4 half-open table",
-                        200000 /* $$$$ config parameter nbuckets */ ,
-                        (64 << 20) /*$$$ config parameter table size */ );
-  clib_bihash_init_48_8 (&smm->v6_half_open_hash, "v6 half-open table",
-                        200000 /* $$$$ config parameter nbuckets */ ,
-                        (64 << 20) /*$$$ config parameter table size */ );
+  session_lookup_init ();
 
   smm->is_enabled = 1;
 
@@ -1328,11 +852,7 @@ clib_error_t *
 session_manager_main_init (vlib_main_t * vm)
 {
   session_manager_main_t *smm = &session_manager_main;
-
-  smm->vlib_main = vm;
-  smm->vnet_main = vnet_get_main ();
   smm->is_enabled = 0;
-
   return 0;
 }
 
index 6c61632..bb22f10 100644 (file)
@@ -15,7 +15,9 @@
 #ifndef __included_session_h__
 #define __included_session_h__
 
-#include <vnet/session/transport.h>
+#include <vnet/session/stream_session.h>
+#include <vnet/session/session_lookup.h>
+#include <vnet/session/transport_interface.h>
 #include <vlibmemory/unix_shared_memory_queue.h>
 #include <vnet/session/session_debug.h>
 #include <vnet/session/segment_manager.h>
@@ -66,37 +68,6 @@ typedef enum
   SESSION_QUEUE_N_NEXT,
 } session_queue_next_t;
 
-#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;
-
-
-session_type_t
-session_type_from_proto_and_ip (transport_proto_t proto, u8 is_ip4);
-
-/*
- * Application session state
- */
-typedef enum
-{
-  SESSION_STATE_LISTENING,
-  SESSION_STATE_CONNECTING,
-  SESSION_STATE_ACCEPTING,
-  SESSION_STATE_READY,
-  SESSION_STATE_CLOSED,
-  SESSION_STATE_N_STATES,
-} stream_session_state_t;
-
 typedef struct
 {
   void *fp;
@@ -116,48 +87,6 @@ typedef CLIB_PACKED (struct {
 }) session_fifo_event_t;
 /* *INDENT-ON* */
 
-typedef struct _stream_session_t
-{
-  /** fifo pointers. Once allocated, these do not move */
-  svm_fifo_t *server_rx_fifo;
-  svm_fifo_t *server_tx_fifo;
-
-  /** Type */
-  u8 session_type;
-
-  /** State */
-  u8 session_state;
-
-  u8 thread_index;
-
-  /** To avoid n**2 "one event per frame" check */
-  u8 enqueue_epoch;
-
-  /** Pad to a multiple of 8 octets */
-  u8 align_pad[4];
-
-  /** svm segment index where fifos were allocated */
-  u32 svm_segment_index;
-
-  /** Session index in per_thread pool */
-  u32 session_index;
-
-  /** Transport specific */
-  u32 connection_index;
-
-  /** Application specific */
-  u32 pid;
-
-  /** stream server pool index */
-  u32 app_index;
-
-  /** Parent listener session if the result of an accept */
-  u32 listener_index;
-
-  /** Opaque, pad to a 64-octet boundary */
-  u64 opaque[2];
-} stream_session_t;
-
 /* Forward definition */
 typedef struct _session_manager_main session_manager_main_t;
 
@@ -174,14 +103,6 @@ u8 session_node_lookup_fifo_event (svm_fifo_t * f, session_fifo_event_t * e);
 
 struct _session_manager_main
 {
-  /** Lookup tables for established sessions and listeners */
-  clib_bihash_16_8_t v4_session_hash;
-  clib_bihash_48_8_t v6_session_hash;
-
-  /** Lookup tables for half-open sessions */
-  clib_bihash_16_8_t v4_half_open_hash;
-  clib_bihash_48_8_t v6_half_open_hash;
-
   /** Per worker thread session pools */
   stream_session_t **sessions;
 
@@ -224,10 +145,6 @@ struct _session_manager_main
   /** Preallocate session config parameter */
   u32 preallocated_sessions;
 
-  /* Convenience */
-  vlib_main_t *vlib_main;
-  vnet_main_t *vnet_main;
-
 #if SESSION_DBG
   /**
    * last event poll time by thread
@@ -250,60 +167,6 @@ vnet_get_session_manager_main ()
   return &session_manager_main;
 }
 
-/*
- * Stream session functions
- */
-
-stream_session_t *stream_session_lookup_listener4 (ip4_address_t * lcl,
-                                                  u16 lcl_port, u8 proto);
-stream_session_t *stream_session_lookup4 (ip4_address_t * lcl,
-                                         ip4_address_t * rmt, u16 lcl_port,
-                                         u16 rmt_port, u8 proto);
-stream_session_t *stream_session_lookup_listener6 (ip6_address_t * lcl,
-                                                  u16 lcl_port, u8 proto);
-stream_session_t *stream_session_lookup6 (ip6_address_t * lcl,
-                                         ip6_address_t * rmt, u16 lcl_port,
-                                         u16 rmt_port, u8 proto);
-transport_connection_t
-  * stream_session_lookup_transport_wt4 (ip4_address_t * lcl,
-                                        ip4_address_t * rmt, u16 lcl_port,
-                                        u16 rmt_port, u8 proto,
-                                        u32 thread_index);
-transport_connection_t *stream_session_lookup_transport4 (ip4_address_t * lcl,
-                                                         ip4_address_t * rmt,
-                                                         u16 lcl_port,
-                                                         u16 rmt_port,
-                                                         u8 proto);
-transport_connection_t *stream_session_lookup_transport_wt6 (ip6_address_t *
-                                                            lcl,
-                                                            ip6_address_t *
-                                                            rmt,
-                                                            u16 lcl_port,
-                                                            u16 rmt_port,
-                                                            u8 proto,
-                                                            u32
-                                                            thread_index);
-transport_connection_t *stream_session_lookup_transport6 (ip6_address_t * lcl,
-                                                         ip6_address_t * rmt,
-                                                         u16 lcl_port,
-                                                         u16 rmt_port,
-                                                         u8 proto);
-
-stream_session_t *stream_session_lookup_listener (ip46_address_t * lcl,
-                                                 u16 lcl_port, u8 proto);
-transport_connection_t
-  * stream_session_lookup_half_open (transport_connection_t * tc);
-void stream_session_table_add_for_tc (transport_connection_t * tc, u64 value);
-int stream_session_table_del_for_tc (transport_connection_t * tc);
-
-always_inline stream_session_t *
-stream_session_get_tsi (u64 ti_and_si, u32 thread_index)
-{
-  ASSERT ((u32) (ti_and_si >> 32) == thread_index);
-  return pool_elt_at_index (session_manager_main.sessions[thread_index],
-                           ti_and_si & 0xFFFFFFFFULL);
-}
-
 always_inline u8
 stream_session_is_valid (u32 si, u8 thread_index)
 {
@@ -445,9 +308,6 @@ send_session_connected_callback (u32 app_index, u32 api_context,
                                 stream_session_t * s, u8 is_fail);
 
 
-void session_register_transport (u8 type, const transport_proto_vft_t * vft);
-transport_proto_vft_t *session_get_transport_vft (u8 type);
-
 clib_error_t *vnet_session_enable_disable (vlib_main_t * vm, u8 is_en);
 
 always_inline unix_shared_memory_queue_t *
@@ -510,6 +370,24 @@ listen_session_del (stream_session_t * s)
   pool_put (session_manager_main.listen_sessions[s->session_type], s);
 }
 
+always_inline stream_session_t *
+session_manager_get_listener (u8 type, u32 index)
+{
+  return pool_elt_at_index (session_manager_main.listen_sessions[type],
+                           index);
+}
+
+always_inline void
+session_manager_set_transport_rx_fn (u8 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_lookup.c b/src/vnet/session/session_lookup.c
new file mode 100644 (file)
index 0000000..b3862ee
--- /dev/null
@@ -0,0 +1,620 @@
+/*
+ * Copyright (c) 2017 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/** Generate typed init functions for multiple hash table styles... */
+#include <vppinfra/bihash_16_8.h>
+#include <vppinfra/bihash_template.h>
+
+#include <vppinfra/bihash_template.c>
+
+#undef __included_bihash_template_h__
+
+#include <vppinfra/bihash_48_8.h>
+#include <vppinfra/bihash_template.h>
+
+#include <vppinfra/bihash_template.c>
+#include <vnet/session/session_lookup.h>
+#include <vnet/session/session.h>
+
+static session_lookup_t session_lookup;
+extern transport_proto_vft_t *tp_vfts;
+
+/* *INDENT-OFF* */
+/* 16 octets */
+typedef CLIB_PACKED (struct {
+  union
+    {
+      struct
+       {
+         ip4_address_t src;
+         ip4_address_t dst;
+         u16 src_port;
+         u16 dst_port;
+         /* align by making this 4 octets even though its a 1-bit field
+          * NOTE: avoid key overlap with other transports that use 5 tuples for
+          * session identification.
+          */
+         u32 proto;
+       };
+      u64 as_u64[2];
+    };
+}) v4_connection_key_t;
+
+typedef CLIB_PACKED (struct {
+  union
+    {
+      struct
+       {
+         /* 48 octets */
+         ip6_address_t src;
+         ip6_address_t dst;
+         u16 src_port;
+         u16 dst_port;
+         u32 proto;
+         u64 unused;
+       };
+      u64 as_u64[6];
+    };
+}) v6_connection_key_t;
+/* *INDENT-ON* */
+
+typedef clib_bihash_kv_16_8_t session_kv4_t;
+typedef clib_bihash_kv_48_8_t session_kv6_t;
+
+always_inline void
+make_v4_ss_kv (session_kv4_t * kv, ip4_address_t * lcl, ip4_address_t * rmt,
+              u16 lcl_port, u16 rmt_port, u8 proto)
+{
+  v4_connection_key_t *key = (v4_connection_key_t *) kv->key;
+
+  key->src.as_u32 = lcl->as_u32;
+  key->dst.as_u32 = rmt->as_u32;
+  key->src_port = lcl_port;
+  key->dst_port = rmt_port;
+  key->proto = proto;
+
+  kv->value = ~0ULL;
+}
+
+always_inline void
+make_v4_listener_kv (session_kv4_t * kv, ip4_address_t * lcl, u16 lcl_port,
+                    u8 proto)
+{
+  v4_connection_key_t *key = (v4_connection_key_t *) kv->key;
+
+  key->src.as_u32 = lcl->as_u32;
+  key->dst.as_u32 = 0;
+  key->src_port = lcl_port;
+  key->dst_port = 0;
+  key->proto = proto;
+
+  kv->value = ~0ULL;
+}
+
+always_inline void
+make_v4_ss_kv_from_tc (session_kv4_t * kv, transport_connection_t * t)
+{
+  return make_v4_ss_kv (kv, &t->lcl_ip.ip4, &t->rmt_ip.ip4, t->lcl_port,
+                       t->rmt_port, t->proto);
+}
+
+always_inline void
+make_v6_ss_kv (session_kv6_t * kv, ip6_address_t * lcl, ip6_address_t * rmt,
+              u16 lcl_port, u16 rmt_port, u8 proto)
+{
+  v6_connection_key_t *key = (v6_connection_key_t *) kv->key;
+
+  key->src.as_u64[0] = lcl->as_u64[0];
+  key->src.as_u64[1] = lcl->as_u64[1];
+  key->dst.as_u64[0] = rmt->as_u64[0];
+  key->dst.as_u64[1] = rmt->as_u64[1];
+  key->src_port = lcl_port;
+  key->dst_port = rmt_port;
+  key->proto = proto;
+  key->unused = 0;
+
+  kv->value = ~0ULL;
+}
+
+always_inline void
+make_v6_listener_kv (session_kv6_t * kv, ip6_address_t * lcl, u16 lcl_port,
+                    u8 proto)
+{
+  v6_connection_key_t *key = (v6_connection_key_t *) kv->key;
+
+  key->src.as_u64[0] = lcl->as_u64[0];
+  key->src.as_u64[1] = lcl->as_u64[1];
+  key->dst.as_u64[0] = 0;
+  key->dst.as_u64[1] = 0;
+  key->src_port = lcl_port;
+  key->dst_port = 0;
+  key->proto = proto;
+  key->unused = 0;
+
+  kv->value = ~0ULL;
+}
+
+always_inline void
+make_v6_ss_kv_from_tc (session_kv6_t * kv, transport_connection_t * t)
+{
+  make_v6_ss_kv (kv, &t->lcl_ip.ip6, &t->rmt_ip.ip6, t->lcl_port,
+                t->rmt_port, t->proto);
+}
+
+/*
+ * Session lookup key; (src-ip, dst-ip, src-port, dst-port, session-type)
+ * Value: (owner thread index << 32 | session_index);
+ */
+void
+stream_session_table_add_for_tc (transport_connection_t * tc, u64 value)
+{
+  session_lookup_t *sl = &session_lookup;
+  session_kv4_t kv4;
+  session_kv6_t kv6;
+
+  switch (tc->proto)
+    {
+    case SESSION_TYPE_IP4_UDP:
+    case SESSION_TYPE_IP4_TCP:
+      make_v4_ss_kv_from_tc (&kv4, tc);
+      kv4.value = value;
+      clib_bihash_add_del_16_8 (&sl->v4_session_hash, &kv4, 1 /* is_add */ );
+      break;
+    case SESSION_TYPE_IP6_UDP:
+    case SESSION_TYPE_IP6_TCP:
+      make_v6_ss_kv_from_tc (&kv6, tc);
+      kv6.value = value;
+      clib_bihash_add_del_48_8 (&sl->v6_session_hash, &kv6, 1 /* is_add */ );
+      break;
+    default:
+      clib_warning ("Session type not supported");
+      ASSERT (0);
+    }
+}
+
+void
+stream_session_table_add (session_manager_main_t * smm, stream_session_t * s,
+                         u64 value)
+{
+  transport_connection_t *tc;
+
+  tc = tp_vfts[s->session_type].get_connection (s->connection_index,
+                                               s->thread_index);
+  stream_session_table_add_for_tc (tc, value);
+}
+
+void
+stream_session_half_open_table_add (session_type_t sst,
+                                   transport_connection_t * tc, u64 value)
+{
+  session_lookup_t *sl = &session_lookup;
+  session_kv4_t kv4;
+  session_kv6_t kv6;
+
+  switch (sst)
+    {
+    case SESSION_TYPE_IP4_UDP:
+    case SESSION_TYPE_IP4_TCP:
+      make_v4_ss_kv_from_tc (&kv4, tc);
+      kv4.value = value;
+      clib_bihash_add_del_16_8 (&sl->v4_half_open_hash, &kv4,
+                               1 /* is_add */ );
+      break;
+    case SESSION_TYPE_IP6_UDP:
+    case SESSION_TYPE_IP6_TCP:
+      make_v6_ss_kv_from_tc (&kv6, tc);
+      kv6.value = value;
+      clib_bihash_add_del_48_8 (&sl->v6_half_open_hash, &kv6,
+                               1 /* is_add */ );
+      break;
+    default:
+      clib_warning ("Session type not supported");
+      ASSERT (0);
+    }
+}
+
+int
+stream_session_table_del_for_tc (transport_connection_t * tc)
+{
+  session_lookup_t *sl = &session_lookup;
+  session_kv4_t kv4;
+  session_kv6_t kv6;
+  switch (tc->proto)
+    {
+    case SESSION_TYPE_IP4_UDP:
+    case SESSION_TYPE_IP4_TCP:
+      make_v4_ss_kv_from_tc (&kv4, tc);
+      return clib_bihash_add_del_16_8 (&sl->v4_session_hash, &kv4,
+                                      0 /* is_add */ );
+      break;
+    case SESSION_TYPE_IP6_UDP:
+    case SESSION_TYPE_IP6_TCP:
+      make_v6_ss_kv_from_tc (&kv6, tc);
+      return clib_bihash_add_del_48_8 (&sl->v6_session_hash, &kv6,
+                                      0 /* is_add */ );
+      break;
+    default:
+      clib_warning ("Session type not supported");
+      ASSERT (0);
+    }
+
+  return 0;
+}
+
+int
+stream_session_table_del (stream_session_t * s)
+{
+  transport_connection_t *ts;
+  ts = tp_vfts[s->session_type].get_connection (s->connection_index,
+                                               s->thread_index);
+  return stream_session_table_del_for_tc (ts);
+}
+
+void
+stream_session_half_open_table_del (u8 sst, transport_connection_t * tc)
+{
+  session_lookup_t *sl = &session_lookup;
+  session_kv4_t kv4;
+  session_kv6_t kv6;
+
+  switch (sst)
+    {
+    case SESSION_TYPE_IP4_UDP:
+    case SESSION_TYPE_IP4_TCP:
+      make_v4_ss_kv_from_tc (&kv4, tc);
+      clib_bihash_add_del_16_8 (&sl->v4_half_open_hash, &kv4,
+                               0 /* is_add */ );
+      break;
+    case SESSION_TYPE_IP6_UDP:
+    case SESSION_TYPE_IP6_TCP:
+      make_v6_ss_kv_from_tc (&kv6, tc);
+      clib_bihash_add_del_48_8 (&sl->v6_half_open_hash, &kv6,
+                               0 /* is_add */ );
+      break;
+    default:
+      clib_warning ("Session type not supported");
+      ASSERT (0);
+    }
+}
+
+stream_session_t *
+stream_session_lookup_listener4 (ip4_address_t * lcl, u16 lcl_port, u8 proto)
+{
+  session_lookup_t *sl = &session_lookup;
+  session_kv4_t kv4;
+  int rv;
+
+  make_v4_listener_kv (&kv4, lcl, lcl_port, proto);
+  rv = clib_bihash_search_inline_16_8 (&sl->v4_session_hash, &kv4);
+  if (rv == 0)
+    return session_manager_get_listener (proto, (u32) kv4.value);
+
+  /* Zero out the lcl ip */
+  kv4.key[0] = 0;
+  rv = clib_bihash_search_inline_16_8 (&sl->v4_session_hash, &kv4);
+  if (rv == 0)
+    return session_manager_get_listener (proto, (u32) kv4.value);
+
+  return 0;
+}
+
+/** Looks up a session based on the 5-tuple passed as argument.
+ *
+ * First it tries to find an established session, if this fails, it tries
+ * finding a listener session if this fails, it tries a lookup with a
+ * wildcarded local source (listener bound to all interfaces)
+ */
+stream_session_t *
+stream_session_lookup4 (ip4_address_t * lcl, ip4_address_t * rmt,
+                       u16 lcl_port, u16 rmt_port, u8 proto)
+{
+  session_lookup_t *sl = &session_lookup;
+  session_kv4_t kv4;
+  stream_session_t *s;
+  int rv;
+
+  /* Lookup session amongst established ones */
+  make_v4_ss_kv (&kv4, lcl, rmt, lcl_port, rmt_port, proto);
+  rv = clib_bihash_search_inline_16_8 (&sl->v4_session_hash, &kv4);
+  if (rv == 0)
+    return stream_session_get_from_handle (kv4.value);
+
+  /* If nothing is found, check if any listener is available */
+  if ((s = stream_session_lookup_listener4 (lcl, lcl_port, proto)))
+    return s;
+
+  /* Finally, try half-open connections */
+  rv = clib_bihash_search_inline_16_8 (&sl->v4_half_open_hash, &kv4);
+  if (rv == 0)
+    return stream_session_get_from_handle (kv4.value);
+  return 0;
+}
+
+stream_session_t *
+stream_session_lookup_listener6 (ip6_address_t * lcl, u16 lcl_port, u8 proto)
+{
+  session_lookup_t *sl = &session_lookup;
+  session_kv6_t kv6;
+  int rv;
+
+  make_v6_listener_kv (&kv6, lcl, lcl_port, proto);
+  rv = clib_bihash_search_inline_48_8 (&sl->v6_session_hash, &kv6);
+  if (rv == 0)
+    return session_manager_get_listener (proto, (u32) kv6.value);
+
+  /* Zero out the lcl ip */
+  kv6.key[0] = kv6.key[1] = 0;
+  rv = clib_bihash_search_inline_48_8 (&sl->v6_session_hash, &kv6);
+  if (rv == 0)
+    return session_manager_get_listener (proto, (u32) kv6.value);
+
+  return 0;
+}
+
+/* Looks up a session based on the 5-tuple passed as argument.
+ * First it tries to find an established session, if this fails, it tries
+ * finding a listener session if this fails, it tries a lookup with a
+ * wildcarded local source (listener bound to all interfaces) */
+stream_session_t *
+stream_session_lookup6 (ip6_address_t * lcl, ip6_address_t * rmt,
+                       u16 lcl_port, u16 rmt_port, u8 proto)
+{
+  session_lookup_t *sl = &session_lookup;
+  session_kv6_t kv6;
+  stream_session_t *s;
+  int rv;
+
+  make_v6_ss_kv (&kv6, lcl, rmt, lcl_port, rmt_port, proto);
+  rv = clib_bihash_search_inline_48_8 (&sl->v6_session_hash, &kv6);
+  if (rv == 0)
+    return stream_session_get_from_handle (kv6.value);
+
+  /* If nothing is found, check if any listener is available */
+  if ((s = stream_session_lookup_listener6 (lcl, lcl_port, proto)))
+    return s;
+
+  /* Finally, try half-open connections */
+  rv = clib_bihash_search_inline_48_8 (&sl->v6_half_open_hash, &kv6);
+  if (rv == 0)
+    return stream_session_get_from_handle (kv6.value);
+  return 0;
+}
+
+stream_session_t *
+stream_session_lookup_listener (ip46_address_t * lcl, u16 lcl_port, u8 proto)
+{
+  switch (proto)
+    {
+    case SESSION_TYPE_IP4_UDP:
+    case SESSION_TYPE_IP4_TCP:
+      return stream_session_lookup_listener4 (&lcl->ip4, lcl_port, proto);
+      break;
+    case SESSION_TYPE_IP6_UDP:
+    case SESSION_TYPE_IP6_TCP:
+      return stream_session_lookup_listener6 (&lcl->ip6, lcl_port, proto);
+      break;
+    }
+  return 0;
+}
+
+u64
+stream_session_half_open_lookup_handle (ip46_address_t * lcl,
+                                       ip46_address_t * rmt, u16 lcl_port,
+                                       u16 rmt_port, u8 proto)
+{
+  session_lookup_t *sl = &session_lookup;
+  session_kv4_t kv4;
+  session_kv6_t kv6;
+  int rv;
+
+  switch (proto)
+    {
+    case SESSION_TYPE_IP4_UDP:
+    case SESSION_TYPE_IP4_TCP:
+      make_v4_ss_kv (&kv4, &lcl->ip4, &rmt->ip4, lcl_port, rmt_port, proto);
+      rv = clib_bihash_search_inline_16_8 (&sl->v4_half_open_hash, &kv4);
+
+      if (rv == 0)
+       return kv4.value;
+
+      return HALF_OPEN_LOOKUP_INVALID_VALUE;
+      break;
+    case SESSION_TYPE_IP6_UDP:
+    case SESSION_TYPE_IP6_TCP:
+      make_v6_ss_kv (&kv6, &lcl->ip6, &rmt->ip6, lcl_port, rmt_port, proto);
+      rv = clib_bihash_search_inline_48_8 (&sl->v6_half_open_hash, &kv6);
+
+      if (rv == 0)
+       return kv6.value;
+
+      return HALF_OPEN_LOOKUP_INVALID_VALUE;
+      break;
+    }
+  return HALF_OPEN_LOOKUP_INVALID_VALUE;
+}
+
+transport_connection_t *
+stream_session_half_open_lookup (ip46_address_t * lcl, ip46_address_t * rmt,
+                                u16 lcl_port, u16 rmt_port, u8 proto)
+{
+  u64 handle;
+  handle =
+    stream_session_half_open_lookup_handle (lcl, rmt, lcl_port, rmt_port,
+                                           proto);
+  if (handle != HALF_OPEN_LOOKUP_INVALID_VALUE)
+    return tp_vfts[proto].get_half_open (handle & 0xFFFFFFFF);
+  return 0;
+}
+
+always_inline stream_session_t *
+stream_session_get_tsi (u64 ti_and_si, u32 thread_index)
+{
+  ASSERT ((u32) (ti_and_si >> 32) == thread_index);
+  return pool_elt_at_index (session_manager_main.sessions[thread_index],
+                           ti_and_si & 0xFFFFFFFFULL);
+}
+
+transport_connection_t *
+stream_session_lookup_transport_wt4 (ip4_address_t * lcl, ip4_address_t * rmt,
+                                    u16 lcl_port, u16 rmt_port, u8 proto,
+                                    u32 my_thread_index)
+{
+  session_lookup_t *sl = &session_lookup;
+  session_kv4_t kv4;
+  stream_session_t *s;
+  int rv;
+
+  /* Lookup session amongst established ones */
+  make_v4_ss_kv (&kv4, lcl, rmt, lcl_port, rmt_port, proto);
+  rv = clib_bihash_search_inline_16_8 (&sl->v4_session_hash, &kv4);
+  if (rv == 0)
+    {
+      s = stream_session_get_tsi (kv4.value, my_thread_index);
+      return tp_vfts[s->session_type].get_connection (s->connection_index,
+                                                     my_thread_index);
+    }
+
+  /* If nothing is found, check if any listener is available */
+  s = stream_session_lookup_listener4 (lcl, lcl_port, proto);
+  if (s)
+    return tp_vfts[s->session_type].get_listener (s->connection_index);
+
+  /* Finally, try half-open connections */
+  rv = clib_bihash_search_inline_16_8 (&sl->v4_half_open_hash, &kv4);
+  if (rv == 0)
+    return tp_vfts[proto].get_half_open (kv4.value & 0xFFFFFFFF);
+  return 0;
+}
+
+transport_connection_t *
+stream_session_lookup_transport4 (ip4_address_t * lcl, ip4_address_t * rmt,
+                                 u16 lcl_port, u16 rmt_port, u8 proto)
+{
+  session_lookup_t *sl = &session_lookup;
+  session_kv4_t kv4;
+  stream_session_t *s;
+  int rv;
+
+  /* Lookup session amongst established ones */
+  make_v4_ss_kv (&kv4, lcl, rmt, lcl_port, rmt_port, proto);
+  rv = clib_bihash_search_inline_16_8 (&sl->v4_session_hash, &kv4);
+  if (rv == 0)
+    {
+      s = stream_session_get_from_handle (kv4.value);
+      return tp_vfts[s->session_type].get_connection (s->connection_index,
+                                                     s->thread_index);
+    }
+
+  /* If nothing is found, check if any listener is available */
+  s = stream_session_lookup_listener4 (lcl, lcl_port, proto);
+  if (s)
+    return tp_vfts[s->session_type].get_listener (s->connection_index);
+
+  /* Finally, try half-open connections */
+  rv = clib_bihash_search_inline_16_8 (&sl->v4_half_open_hash, &kv4);
+  if (rv == 0)
+    return tp_vfts[proto].get_half_open (kv4.value & 0xFFFFFFFF);
+  return 0;
+}
+
+transport_connection_t *
+stream_session_lookup_transport_wt6 (ip6_address_t * lcl, ip6_address_t * rmt,
+                                    u16 lcl_port, u16 rmt_port, u8 proto,
+                                    u32 my_thread_index)
+{
+  session_lookup_t *sl = &session_lookup;
+  stream_session_t *s;
+  session_kv6_t kv6;
+  int rv;
+
+  make_v6_ss_kv (&kv6, lcl, rmt, lcl_port, rmt_port, proto);
+  rv = clib_bihash_search_inline_48_8 (&sl->v6_session_hash, &kv6);
+  if (rv == 0)
+    {
+      s = stream_session_get_tsi (kv6.value, my_thread_index);
+      return tp_vfts[s->session_type].get_connection (s->connection_index,
+                                                     my_thread_index);
+    }
+
+  /* If nothing is found, check if any listener is available */
+  s = stream_session_lookup_listener6 (lcl, lcl_port, proto);
+  if (s)
+    return tp_vfts[s->session_type].get_listener (s->connection_index);
+
+  /* Finally, try half-open connections */
+  rv = clib_bihash_search_inline_48_8 (&sl->v6_half_open_hash, &kv6);
+  if (rv == 0)
+    return tp_vfts[proto].get_half_open (kv6.value & 0xFFFFFFFF);
+
+  return 0;
+}
+
+transport_connection_t *
+stream_session_lookup_transport6 (ip6_address_t * lcl, ip6_address_t * rmt,
+                                 u16 lcl_port, u16 rmt_port, u8 proto)
+{
+  session_lookup_t *sl = &session_lookup;
+  stream_session_t *s;
+  session_kv6_t kv6;
+  int rv;
+
+  make_v6_ss_kv (&kv6, lcl, rmt, lcl_port, rmt_port, proto);
+  rv = clib_bihash_search_inline_48_8 (&sl->v6_session_hash, &kv6);
+  if (rv == 0)
+    {
+      s = stream_session_get_from_handle (kv6.value);
+      return tp_vfts[s->session_type].get_connection (s->connection_index,
+                                                     s->thread_index);
+    }
+
+  /* If nothing is found, check if any listener is available */
+  s = stream_session_lookup_listener6 (lcl, lcl_port, proto);
+  if (s)
+    return tp_vfts[s->session_type].get_listener (s->connection_index);
+
+  /* Finally, try half-open connections */
+  rv = clib_bihash_search_inline_48_8 (&sl->v6_half_open_hash, &kv6);
+  if (rv == 0)
+    return tp_vfts[proto].get_half_open (kv6.value & 0xFFFFFFFF);
+
+  return 0;
+}
+
+void
+session_lookup_init (void)
+{
+  session_lookup_t *sl = &session_lookup;
+  clib_bihash_init_16_8 (&sl->v4_session_hash, "v4 session table",
+                        200000 /* $$$$ config parameter nbuckets */ ,
+                        (64 << 20) /*$$$ config parameter table size */ );
+  clib_bihash_init_48_8 (&sl->v6_session_hash, "v6 session table",
+                        200000 /* $$$$ config parameter nbuckets */ ,
+                        (64 << 20) /*$$$ config parameter table size */ );
+
+  clib_bihash_init_16_8 (&sl->v4_half_open_hash, "v4 half-open table",
+                        200000 /* $$$$ config parameter nbuckets */ ,
+                        (64 << 20) /*$$$ config parameter table size */ );
+  clib_bihash_init_48_8 (&sl->v6_half_open_hash, "v6 half-open table",
+                        200000 /* $$$$ config parameter nbuckets */ ,
+                        (64 << 20) /*$$$ config parameter table size */ );
+}
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */
diff --git a/src/vnet/session/session_lookup.h b/src/vnet/session/session_lookup.h
new file mode 100644 (file)
index 0000000..9e92dab
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2017 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SRC_VNET_SESSION_SESSION_LOOKUP_H_
+#define SRC_VNET_SESSION_SESSION_LOOKUP_H_
+
+#include <vnet/session/stream_session.h>
+#include <vnet/session/transport.h>
+
+typedef struct _session_lookup
+{
+  /** Lookup tables for established sessions and listeners */
+  clib_bihash_16_8_t v4_session_hash;
+  clib_bihash_48_8_t v6_session_hash;
+
+  /** Lookup tables for half-open sessions */
+  clib_bihash_16_8_t v4_half_open_hash;
+  clib_bihash_48_8_t v6_half_open_hash;
+} session_lookup_t;
+
+stream_session_t *stream_session_lookup_listener4 (ip4_address_t * lcl,
+                                                  u16 lcl_port, u8 proto);
+stream_session_t *stream_session_lookup4 (ip4_address_t * lcl,
+                                         ip4_address_t * rmt, u16 lcl_port,
+                                         u16 rmt_port, u8 proto);
+stream_session_t *stream_session_lookup_listener6 (ip6_address_t * lcl,
+                                                  u16 lcl_port, u8 proto);
+stream_session_t *stream_session_lookup6 (ip6_address_t * lcl,
+                                         ip6_address_t * rmt, u16 lcl_port,
+                                         u16 rmt_port, u8 proto);
+transport_connection_t *stream_session_lookup_transport_wt4 (ip4_address_t *
+                                                            lcl,
+                                                            ip4_address_t *
+                                                            rmt,
+                                                            u16 lcl_port,
+                                                            u16 rmt_port,
+                                                            u8 proto,
+                                                            u32
+                                                            thread_index);
+transport_connection_t *stream_session_lookup_transport4 (ip4_address_t * lcl,
+                                                         ip4_address_t * rmt,
+                                                         u16 lcl_port,
+                                                         u16 rmt_port,
+                                                         u8 proto);
+transport_connection_t *stream_session_lookup_transport_wt6 (ip6_address_t *
+                                                            lcl,
+                                                            ip6_address_t *
+                                                            rmt,
+                                                            u16 lcl_port,
+                                                            u16 rmt_port,
+                                                            u8 proto,
+                                                            u32
+                                                            thread_index);
+transport_connection_t *stream_session_lookup_transport6 (ip6_address_t * lcl,
+                                                         ip6_address_t * rmt,
+                                                         u16 lcl_port,
+                                                         u16 rmt_port,
+                                                         u8 proto);
+
+stream_session_t *stream_session_lookup_listener (ip46_address_t * lcl,
+                                                 u16 lcl_port, u8 proto);
+u64 stream_session_half_open_lookup_handle (ip46_address_t * lcl,
+                                           ip46_address_t * rmt,
+                                           u16 lcl_port,
+                                           u16 rmt_port, u8 proto);
+transport_connection_t *stream_session_half_open_lookup (ip46_address_t * lcl,
+                                                        ip46_address_t * rmt,
+                                                        u16 lcl_port,
+                                                        u16 rmt_port,
+                                                        u8 proto);
+void stream_session_table_add_for_tc (transport_connection_t * tc, u64 value);
+int stream_session_table_del_for_tc (transport_connection_t * tc);
+int stream_session_table_del (stream_session_t * s);
+void stream_session_half_open_table_del (u8 sst, transport_connection_t * tc);
+void stream_session_half_open_table_add (session_type_t sst,
+                                        transport_connection_t * tc,
+                                        u64 value);
+
+void session_lookup_init (void);
+
+#endif /* SRC_VNET_SESSION_SESSION_LOOKUP_H_ */
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */
diff --git a/src/vnet/session/stream_session.h b/src/vnet/session/stream_session.h
new file mode 100644 (file)
index 0000000..82bbf52
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2017 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SRC_VNET_SESSION_STREAM_SESSION_H_
+#define SRC_VNET_SESSION_STREAM_SESSION_H_
+
+#include <vnet/vnet.h>
+#include <svm/svm_fifo.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;
+
+/*
+ * Application session state
+ */
+typedef enum
+{
+  SESSION_STATE_LISTENING,
+  SESSION_STATE_CONNECTING,
+  SESSION_STATE_ACCEPTING,
+  SESSION_STATE_READY,
+  SESSION_STATE_CLOSED,
+  SESSION_STATE_N_STATES,
+} stream_session_state_t;
+
+typedef struct _stream_session_t
+{
+  /** fifo pointers. Once allocated, these do not move */
+  svm_fifo_t *server_rx_fifo;
+  svm_fifo_t *server_tx_fifo;
+
+  /** Type */
+  u8 session_type;
+
+  /** State */
+  u8 session_state;
+
+  u8 thread_index;
+
+  /** To avoid n**2 "one event per frame" check */
+  u8 enqueue_epoch;
+
+  /** Pad to a multiple of 8 octets */
+  u8 align_pad[4];
+
+  /** svm segment index where fifos were allocated */
+  u32 svm_segment_index;
+
+  /** Session index in per_thread pool */
+  u32 session_index;
+
+  /** Transport specific */
+  u32 connection_index;
+
+  /** stream server pool index */
+  u32 app_index;
+
+  /** Parent listener session if the result of an accept */
+  u32 listener_index;
+
+  u32 opaque2;
+
+  /** Opaque, pad to a 64-octet boundary */
+  u64 opaque[2];
+} stream_session_t;
+
+#endif /* SRC_VNET_SESSION_STREAM_SESSION_H_ */
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */
diff --git a/src/vnet/session/transport.c b/src/vnet/session/transport.c
deleted file mode 100644 (file)
index abd94ba..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (c) 2017 Cisco and/or its affiliates.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at:
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <vnet/session/transport.h>
-
-u32
-transport_endpoint_lookup (transport_endpoint_table_t *ht, ip46_address_t *ip,
-                           u16 port)
-{
-  clib_bihash_kv_24_8_t kv;
-  int rv;
-
-  kv.key[0] = ip->as_u64[0];
-  kv.key[1] = ip->as_u64[1];
-  kv.key[2] = port;
-
-  rv = clib_bihash_search_inline_24_8 (ht, &kv);
-  if (rv == 0)
-    return kv.value;
-
-  return TRANSPORT_ENDPOINT_INVALID_INDEX;
-}
-
-void
-transport_endpoint_table_add (transport_endpoint_table_t *ht,
-                              transport_endpoint_t *te, u32 value)
-{
-  clib_bihash_kv_24_8_t kv;
-
-  kv.key[0] = te->ip.as_u64[0];
-  kv.key[1] = te->ip.as_u64[1];
-  kv.key[2] = te->port;
-  kv.value = value;
-
-  clib_bihash_add_del_24_8 (ht, &kv, 1);
-}
-
-void
-transport_endpoint_table_del (transport_endpoint_table_t *ht,
-                              transport_endpoint_t *te)
-{
-  clib_bihash_kv_24_8_t kv;
-
-  kv.key[0] = te->ip.as_u64[0];
-  kv.key[1] = te->ip.as_u64[1];
-  kv.key[2] = te->port;
-
-  clib_bihash_add_del_24_8 (ht, &kv, 0);
-}
-
-
-
index 9c38bab..3895a60 100644 (file)
@@ -21,6 +21,7 @@
 #include <vppinfra/bihash_16_8.h>
 #include <vppinfra/bihash_48_8.h>
 #include <vnet/tcp/tcp_debug.h>
+
 /*
  * Protocol independent transport properties associated to a session
  */
@@ -31,6 +32,7 @@ typedef struct _transport_connection
   u16 lcl_port;                        /**< Local port */
   u16 rmt_port;                        /**< Remote port */
   u8 proto;                    /**< Protocol id (also session type) */
+  u32 vrf;                     /**< FIB table id */
 
   u32 s_index;                 /**< Parent session index */
   u32 c_index;                 /**< Connection index in transport pool */
@@ -55,6 +57,7 @@ typedef struct _transport_connection
 #define c_lcl_port connection.lcl_port
 #define c_rmt_port connection.rmt_port
 #define c_proto connection.proto
+#define c_vrf connection.vrf
 #define c_state connection.state
 #define c_s_index connection.s_index
 #define c_c_index connection.c_index
@@ -66,165 +69,6 @@ typedef struct _transport_connection
 #define c_rmt_dpo connection.rmt_dpo
 } transport_connection_t;
 
-/*
- * Transport protocol virtual function table
- */
-typedef struct _transport_proto_vft
-{
-  /*
-   * Setup
-   */
-  u32 (*bind) (u32, ip46_address_t *, u16);
-  u32 (*unbind) (u32);
-  int (*open) (ip46_address_t * addr, u16 port_host_byte_order);
-  void (*close) (u32 conn_index, u32 thread_index);
-  void (*cleanup) (u32 conn_index, u32 thread_index);
-
-  /*
-   * Transmission
-   */
-    u32 (*push_header) (transport_connection_t * tconn, vlib_buffer_t * b);
-    u16 (*send_mss) (transport_connection_t * tc);
-    u32 (*send_space) (transport_connection_t * tc);
-    u32 (*tx_fifo_offset) (transport_connection_t * tc);
-
-  /*
-   * Connection retrieval
-   */
-  transport_connection_t *(*get_connection) (u32 conn_idx, u32 thread_idx);
-  transport_connection_t *(*get_listener) (u32 conn_index);
-  transport_connection_t *(*get_half_open) (u32 conn_index);
-
-  /*
-   * Format
-   */
-  u8 *(*format_connection) (u8 * s, va_list * args);
-  u8 *(*format_listener) (u8 * s, va_list * args);
-  u8 *(*format_half_open) (u8 * s, va_list * args);
-} transport_proto_vft_t;
-
-/* *INDENT-OFF* */
-/* 16 octets */
-typedef CLIB_PACKED (struct {
-  union
-    {
-      struct
-       {
-         ip4_address_t src;
-         ip4_address_t dst;
-         u16 src_port;
-         u16 dst_port;
-         /* align by making this 4 octets even though its a 1-bit field
-          * NOTE: avoid key overlap with other transports that use 5 tuples for
-          * session identification.
-          */
-         u32 proto;
-       };
-      u64 as_u64[2];
-    };
-}) v4_connection_key_t;
-
-typedef CLIB_PACKED (struct {
-  union
-    {
-      struct
-       {
-         /* 48 octets */
-         ip6_address_t src;
-         ip6_address_t dst;
-         u16 src_port;
-         u16 dst_port;
-         u32 proto;
-         u64 unused;
-       };
-      u64 as_u64[6];
-    };
-}) v6_connection_key_t;
-/* *INDENT-ON* */
-
-typedef clib_bihash_kv_16_8_t session_kv4_t;
-typedef clib_bihash_kv_48_8_t session_kv6_t;
-
-always_inline void
-make_v4_ss_kv (session_kv4_t * kv, ip4_address_t * lcl, ip4_address_t * rmt,
-              u16 lcl_port, u16 rmt_port, u8 proto)
-{
-  v4_connection_key_t *key = (v4_connection_key_t *) kv->key;
-
-  key->src.as_u32 = lcl->as_u32;
-  key->dst.as_u32 = rmt->as_u32;
-  key->src_port = lcl_port;
-  key->dst_port = rmt_port;
-  key->proto = proto;
-
-  kv->value = ~0ULL;
-}
-
-always_inline void
-make_v4_listener_kv (session_kv4_t * kv, ip4_address_t * lcl, u16 lcl_port,
-                    u8 proto)
-{
-  v4_connection_key_t *key = (v4_connection_key_t *) kv->key;
-
-  key->src.as_u32 = lcl->as_u32;
-  key->dst.as_u32 = 0;
-  key->src_port = lcl_port;
-  key->dst_port = 0;
-  key->proto = proto;
-
-  kv->value = ~0ULL;
-}
-
-always_inline void
-make_v4_ss_kv_from_tc (session_kv4_t * kv, transport_connection_t * t)
-{
-  return make_v4_ss_kv (kv, &t->lcl_ip.ip4, &t->rmt_ip.ip4, t->lcl_port,
-                       t->rmt_port, t->proto);
-}
-
-always_inline void
-make_v6_ss_kv (session_kv6_t * kv, ip6_address_t * lcl, ip6_address_t * rmt,
-              u16 lcl_port, u16 rmt_port, u8 proto)
-{
-  v6_connection_key_t *key = (v6_connection_key_t *) kv->key;
-
-  key->src.as_u64[0] = lcl->as_u64[0];
-  key->src.as_u64[1] = lcl->as_u64[1];
-  key->dst.as_u64[0] = rmt->as_u64[0];
-  key->dst.as_u64[1] = rmt->as_u64[1];
-  key->src_port = lcl_port;
-  key->dst_port = rmt_port;
-  key->proto = proto;
-  key->unused = 0;
-
-  kv->value = ~0ULL;
-}
-
-always_inline void
-make_v6_listener_kv (session_kv6_t * kv, ip6_address_t * lcl, u16 lcl_port,
-                    u8 proto)
-{
-  v6_connection_key_t *key = (v6_connection_key_t *) kv->key;
-
-  key->src.as_u64[0] = lcl->as_u64[0];
-  key->src.as_u64[1] = lcl->as_u64[1];
-  key->dst.as_u64[0] = 0;
-  key->dst.as_u64[1] = 0;
-  key->src_port = lcl_port;
-  key->dst_port = 0;
-  key->proto = proto;
-  key->unused = 0;
-
-  kv->value = ~0ULL;
-}
-
-always_inline void
-make_v6_ss_kv_from_tc (session_kv6_t * kv, transport_connection_t * t)
-{
-  make_v6_ss_kv (kv, &t->lcl_ip.ip6, &t->rmt_ip.ip6, t->lcl_port,
-                t->rmt_port, t->proto);
-}
-
 typedef enum _transport_proto
 {
   TRANSPORT_PROTO_TCP,
@@ -239,18 +83,6 @@ typedef struct _transport_endpoint
   u32 vrf;             /** fib table the endpoint is associated with */
 } transport_endpoint_t;
 
-typedef clib_bihash_24_8_t transport_endpoint_table_t;
-
-#define TRANSPORT_ENDPOINT_INVALID_INDEX ((u32)~0)
-
-u32
-transport_endpoint_lookup (transport_endpoint_table_t * ht,
-                          ip46_address_t * ip, u16 port);
-void transport_endpoint_table_add (transport_endpoint_table_t * ht,
-                                  transport_endpoint_t * te, u32 value);
-void transport_endpoint_table_del (transport_endpoint_table_t * ht,
-                                  transport_endpoint_t * te);
-
 #endif /* VNET_VNET_URI_TRANSPORT_H_ */
 
 /*
diff --git a/src/vnet/session/transport_interface.c b/src/vnet/session/transport_interface.c
new file mode 100644 (file)
index 0000000..eb12aa6
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2017 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <vnet/session/transport_interface.h>
+#include <vnet/session/session.h>
+
+/**
+ * Per-type vector of transport protocol virtual function tables
+ */
+transport_proto_vft_t *tp_vfts;
+
+u32
+transport_endpoint_lookup (transport_endpoint_table_t * ht,
+                          ip46_address_t * ip, u16 port)
+{
+  clib_bihash_kv_24_8_t kv;
+  int rv;
+
+  kv.key[0] = ip->as_u64[0];
+  kv.key[1] = ip->as_u64[1];
+  kv.key[2] = port;
+
+  rv = clib_bihash_search_inline_24_8 (ht, &kv);
+  if (rv == 0)
+    return kv.value;
+
+  return TRANSPORT_ENDPOINT_INVALID_INDEX;
+}
+
+void
+transport_endpoint_table_add (transport_endpoint_table_t * ht,
+                             transport_endpoint_t * te, u32 value)
+{
+  clib_bihash_kv_24_8_t kv;
+
+  kv.key[0] = te->ip.as_u64[0];
+  kv.key[1] = te->ip.as_u64[1];
+  kv.key[2] = te->port;
+  kv.value = value;
+
+  clib_bihash_add_del_24_8 (ht, &kv, 1);
+}
+
+void
+transport_endpoint_table_del (transport_endpoint_table_t * ht,
+                             transport_endpoint_t * te)
+{
+  clib_bihash_kv_24_8_t kv;
+
+  kv.key[0] = te->ip.as_u64[0];
+  kv.key[1] = te->ip.as_u64[1];
+  kv.key[2] = te->port;
+
+  clib_bihash_add_del_24_8 (ht, &kv, 0);
+}
+
+/**
+ * Register transport virtual function table.
+ *
+ * @param type - session type (not protocol type)
+ * @param vft - virtual function table
+ */
+void
+session_register_transport (u8 session_type,
+                           const transport_proto_vft_t * vft)
+{
+  vec_validate (tp_vfts, session_type);
+  tp_vfts[session_type] = *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);
+}
+
+/**
+ * Get transport virtual function table
+ *
+ * @param type - session type (not protocol type)
+ */
+transport_proto_vft_t *
+session_get_transport_vft (u8 session_type)
+{
+  if (session_type >= vec_len (tp_vfts))
+    return 0;
+  return &tp_vfts[session_type];
+}
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */
diff --git a/src/vnet/session/transport_interface.h b/src/vnet/session/transport_interface.h
new file mode 100644 (file)
index 0000000..b7e86ee
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2017 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SRC_VNET_SESSION_TRANSPORT_INTERFACE_H_
+#define SRC_VNET_SESSION_TRANSPORT_INTERFACE_H_
+
+#include <vnet/vnet.h>
+#include <vnet/session/transport.h>
+
+/*
+ * Transport protocol virtual function table
+ */
+typedef struct _transport_proto_vft
+{
+  /*
+   * Setup
+   */
+  u32 (*bind) (u32 session_index, transport_endpoint_t * lcl);
+  u32 (*unbind) (u32);
+  int (*open) (transport_endpoint_t * rmt);
+  void (*close) (u32 conn_index, u32 thread_index);
+  void (*cleanup) (u32 conn_index, u32 thread_index);
+
+  /*
+   * Transmission
+   */
+    u32 (*push_header) (transport_connection_t * tconn, vlib_buffer_t * b);
+    u16 (*send_mss) (transport_connection_t * tc);
+    u32 (*send_space) (transport_connection_t * tc);
+    u32 (*tx_fifo_offset) (transport_connection_t * tc);
+
+  /*
+   * Connection retrieval
+   */
+  transport_connection_t *(*get_connection) (u32 conn_idx, u32 thread_idx);
+  transport_connection_t *(*get_listener) (u32 conn_index);
+  transport_connection_t *(*get_half_open) (u32 conn_index);
+
+  /*
+   * Format
+   */
+  u8 *(*format_connection) (u8 * s, va_list * args);
+  u8 *(*format_listener) (u8 * s, va_list * args);
+  u8 *(*format_half_open) (u8 * s, va_list * args);
+} transport_proto_vft_t;
+
+typedef clib_bihash_24_8_t transport_endpoint_table_t;
+
+#define TRANSPORT_ENDPOINT_INVALID_INDEX ((u32)~0)
+
+u32 transport_endpoint_lookup (transport_endpoint_table_t * ht,
+                              ip46_address_t * ip, u16 port);
+void transport_endpoint_table_add (transport_endpoint_table_t * ht,
+                                  transport_endpoint_t * te, u32 value);
+void transport_endpoint_table_del (transport_endpoint_table_t * ht,
+                                  transport_endpoint_t * te);
+
+void session_register_transport (u8 session_type,
+                                const transport_proto_vft_t * vft);
+transport_proto_vft_t *session_get_transport_vft (u8 session_type);
+
+#endif /* SRC_VNET_SESSION_TRANSPORT_INTERFACE_H_ */
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */
index a221415..6d1cfa0 100644 (file)
@@ -22,8 +22,7 @@
 tcp_main_t tcp_main;
 
 static u32
-tcp_connection_bind (u32 session_index, ip46_address_t * ip,
-                    u16 port_host_byte_order, u8 is_ip4)
+tcp_connection_bind (u32 session_index, transport_endpoint_t * lcl)
 {
   tcp_main_t *tm = &tcp_main;
   tcp_connection_t *listener;
@@ -32,17 +31,18 @@ tcp_connection_bind (u32 session_index, ip46_address_t * ip,
   memset (listener, 0, sizeof (*listener));
 
   listener->c_c_index = listener - tm->listener_pool;
-  listener->c_lcl_port = clib_host_to_net_u16 (port_host_byte_order);
+  listener->c_lcl_port = clib_host_to_net_u16 (lcl->port);
 
-  if (is_ip4)
+  if (lcl->is_ip4)
     {
-      listener->c_lcl_ip4.as_u32 = ip->ip4.as_u32;
+      listener->c_lcl_ip4.as_u32 = lcl->ip.ip4.as_u32;
       listener->c_is_ip4 = 1;
       listener->c_proto = SESSION_TYPE_IP4_TCP;
     }
   else
     {
-      clib_memcpy (&listener->c_lcl_ip6, &ip->ip6, sizeof (ip6_address_t));
+      clib_memcpy (&listener->c_lcl_ip6, &lcl->ip.ip6,
+                  sizeof (ip6_address_t));
       listener->c_proto = SESSION_TYPE_IP6_TCP;
     }
 
@@ -57,17 +57,9 @@ tcp_connection_bind (u32 session_index, ip46_address_t * ip,
 }
 
 u32
-tcp_session_bind_ip4 (u32 session_index, ip46_address_t * ip,
-                     u16 port_host_byte_order)
-{
-  return tcp_connection_bind (session_index, ip, port_host_byte_order, 1);
-}
-
-u32
-tcp_session_bind_ip6 (u32 session_index, ip46_address_t * ip,
-                     u16 port_host_byte_order)
+tcp_session_bind (u32 session_index, transport_endpoint_t * tep)
 {
-  return tcp_connection_bind (session_index, ip, port_host_byte_order, 0);
+  return tcp_connection_bind (session_index, tep);
 }
 
 static void
@@ -133,10 +125,7 @@ tcp_connection_cleanup (tcp_connection_t * tc)
   /* Check if half-open */
   if (tc->state == TCP_STATE_SYN_SENT)
     {
-      /* Poison the entry */
-      if (CLIB_DEBUG > 0)
-       memset (tc, 0xFA, sizeof (*tc));
-      pool_put (tm->half_open_connections, tc);
+      tcp_half_open_connection_del (tc);
     }
   else
     {
@@ -172,9 +161,21 @@ tcp_half_open_connection_del (tcp_connection_t * tc)
   tcp_main_t *tm = vnet_get_tcp_main ();
   if (CLIB_DEBUG)
     memset (tc, 0xFA, sizeof (*tc));
-  clib_spinlock_lock (&tm->half_open_lock);
+  clib_spinlock_lock_if_init (&tm->half_open_lock);
   pool_put (tm->half_open_connections, tc);
-  clib_spinlock_unlock (&tm->half_open_lock);
+  clib_spinlock_unlock_if_init (&tm->half_open_lock);
+}
+
+tcp_connection_t *
+tcp_half_open_connection_new ()
+{
+  tcp_main_t *tm = vnet_get_tcp_main ();
+  tcp_connection_t *tc = 0;
+  clib_spinlock_lock_if_init (&tm->half_open_lock);
+  pool_get (tm->half_open_connections, tc);
+  clib_spinlock_unlock_if_init (&tm->half_open_lock);
+  memset (tc, 0, sizeof (*tc));
+  return tc;
 }
 
 tcp_connection_t *
@@ -456,11 +457,13 @@ fib_node_index_t
 tcp_lookup_rmt_in_fib (tcp_connection_t * tc)
 {
   fib_prefix_t prefix;
+  u32 fib_index;
 
   clib_memcpy (&prefix.fp_addr, &tc->c_rmt_ip, sizeof (prefix.fp_addr));
   prefix.fp_proto = tc->c_is_ip4 ? FIB_PROTOCOL_IP4 : FIB_PROTOCOL_IP6;
   prefix.fp_len = tc->c_is_ip4 ? 32 : 128;
-  return fib_table_lookup (0, &prefix);
+  fib_index = fib_table_find (prefix.fp_proto, tc->c_vrf);
+  return fib_table_lookup (fib_index, &prefix);
 }
 
 static int
@@ -512,13 +515,13 @@ tcp_connection_init_vars (tcp_connection_t * tc)
 }
 
 int
-tcp_connection_open (ip46_address_t * rmt_addr, u16 rmt_port, u8 is_ip4)
+tcp_connection_open (transport_endpoint_t * rmt)
 {
   tcp_main_t *tm = vnet_get_tcp_main ();
   tcp_connection_t *tc;
   fib_prefix_t prefix;
   fib_node_index_t fei;
-  u32 sw_if_index;
+  u32 sw_if_index, fib_index;
   ip46_address_t lcl_addr;
   int lcl_port;
 
@@ -528,11 +531,12 @@ tcp_connection_open (ip46_address_t * rmt_addr, u16 rmt_port, u8 is_ip4)
   memset (&lcl_addr, 0, sizeof (lcl_addr));
 
   /* Find a FIB path to the destination */
-  clib_memcpy (&prefix.fp_addr, rmt_addr, sizeof (*rmt_addr));
-  prefix.fp_proto = is_ip4 ? FIB_PROTOCOL_IP4 : FIB_PROTOCOL_IP6;
-  prefix.fp_len = is_ip4 ? 32 : 128;
+  clib_memcpy (&prefix.fp_addr, &rmt->ip, sizeof (rmt->ip));
+  prefix.fp_proto = rmt->is_ip4 ? FIB_PROTOCOL_IP4 : FIB_PROTOCOL_IP6;
+  prefix.fp_len = rmt->is_ip4 ? 32 : 128;
 
-  fei = fib_table_lookup (0, &prefix);
+  fib_index = fib_table_find (prefix.fp_proto, rmt->vrf);
+  fei = fib_table_lookup (fib_index, &prefix);
 
   /* Couldn't find route to destination. Bail out. */
   if (fei == FIB_NODE_INDEX_INVALID)
@@ -546,11 +550,11 @@ tcp_connection_open (ip46_address_t * rmt_addr, u16 rmt_port, u8 is_ip4)
   if (sw_if_index == (u32) ~ 0)
     {
       clib_warning ("no resolving interface for %U", format_ip46_address,
-                   rmt_addr, IP46_TYPE_IP4);
+                   &rmt->ip, IP46_TYPE_IP4);
       return -1;
     }
 
-  if (is_ip4)
+  if (rmt->is_ip4)
     {
       ip4_address_t *ip4;
       int index;
@@ -599,17 +603,16 @@ tcp_connection_open (ip46_address_t * rmt_addr, u16 rmt_port, u8 is_ip4)
    * Create connection and send SYN
    */
 
-  pool_get (tm->half_open_connections, tc);
-  memset (tc, 0, sizeof (*tc));
+  tc = tcp_half_open_connection_new ();
 
-  clib_memcpy (&tc->c_rmt_ip, rmt_addr, sizeof (ip46_address_t));
+  clib_memcpy (&tc->c_rmt_ip, &rmt->ip, sizeof (ip46_address_t));
   clib_memcpy (&tc->c_lcl_ip, &lcl_addr, sizeof (ip46_address_t));
-  tc->c_rmt_port = clib_host_to_net_u16 (rmt_port);
+  tc->c_rmt_port = clib_host_to_net_u16 (rmt->port);
   tc->c_lcl_port = clib_host_to_net_u16 (lcl_port);
   tc->c_c_index = tc - tm->half_open_connections;
-  tc->c_is_ip4 = is_ip4;
-  tc->c_proto = is_ip4 ? SESSION_TYPE_IP4_TCP : SESSION_TYPE_IP6_TCP;
-
+  tc->c_is_ip4 = rmt->is_ip4;
+  tc->c_proto = rmt->is_ip4 ? SESSION_TYPE_IP4_TCP : SESSION_TYPE_IP6_TCP;
+  tc->c_vrf = rmt->vrf;
   /* The other connection vars will be initialized after SYN ACK */
   tcp_connection_timers_init (tc);
 
@@ -621,15 +624,9 @@ tcp_connection_open (ip46_address_t * rmt_addr, u16 rmt_port, u8 is_ip4)
 }
 
 int
-tcp_session_open_ip4 (ip46_address_t * addr, u16 port)
-{
-  return tcp_connection_open (addr, port, 1);
-}
-
-int
-tcp_session_open_ip6 (ip46_address_t * addr, u16 port)
+tcp_session_open (transport_endpoint_t * tep)
 {
-  return tcp_connection_open (addr, port, 0);
+  return tcp_connection_open (tep);
 }
 
 const char *tcp_dbg_evt_str[] = {
@@ -1025,32 +1022,14 @@ tcp_session_tx_fifo_offset (transport_connection_t * trans_conn)
 }
 
 /* *INDENT-OFF* */
-const static transport_proto_vft_t tcp4_proto = {
-  .bind = tcp_session_bind_ip4,
-  .unbind = tcp_session_unbind,
-  .push_header = tcp_push_header,
-  .get_connection = tcp_session_get_transport,
-  .get_listener = tcp_session_get_listener,
-  .get_half_open = tcp_half_open_session_get_transport,
-  .open = tcp_session_open_ip4,
-  .close = tcp_session_close,
-  .cleanup = tcp_session_cleanup,
-  .send_mss = tcp_session_send_mss,
-  .send_space = tcp_session_send_space,
-  .tx_fifo_offset = tcp_session_tx_fifo_offset,
-  .format_connection = format_tcp_session,
-  .format_listener = format_tcp_listener_session,
-  .format_half_open = format_tcp_half_open_session,
-};
-
-const static transport_proto_vft_t tcp6_proto = {
-  .bind = tcp_session_bind_ip6,
+const static transport_proto_vft_t tcp_proto = {
+  .bind = tcp_session_bind,
   .unbind = tcp_session_unbind,
   .push_header = tcp_push_header,
   .get_connection = tcp_session_get_transport,
   .get_listener = tcp_session_get_listener,
   .get_half_open = tcp_half_open_session_get_transport,
-  .open = tcp_session_open_ip6,
+  .open = tcp_session_open,
   .close = tcp_session_close,
   .cleanup = tcp_session_cleanup,
   .send_mss = tcp_session_send_mss,
@@ -1200,9 +1179,9 @@ tcp_main_enable (vlib_main_t * vm)
 
   ip4_register_protocol (IP_PROTOCOL_TCP, tcp4_input_node.index);
 
-  /* Register as transport with URI */
-  session_register_transport (SESSION_TYPE_IP4_TCP, &tcp4_proto);
-  session_register_transport (SESSION_TYPE_IP6_TCP, &tcp6_proto);
+  /* Register as transport with session layer */
+  session_register_transport (SESSION_TYPE_IP4_TCP, &tcp_proto);
+  session_register_transport (SESSION_TYPE_IP6_TCP, &tcp_proto);
 
   /*
    * Initialize data structures
@@ -1247,7 +1226,8 @@ tcp_main_enable (vlib_main_t * vm)
   clib_bihash_init_24_8 (&tm->local_endpoints_table, "local endpoint table",
                         200000 /* $$$$ config parameter nbuckets */ ,
                         (64 << 20) /*$$$ config parameter table size */ );
-  clib_spinlock_init (&tm->half_open_lock);
+  if (num_threads > 1)
+    clib_spinlock_init (&tm->half_open_lock);
   return error;
 }
 
index cc5cecd..d32b4fc 100644 (file)
@@ -2742,7 +2742,10 @@ tcp_lookup_is_valid (tcp_connection_t * tc, tcp_header_t * hdr)
 
   if (!is_valid)
     {
-      if ((tmp = stream_session_lookup_half_open (&tc->connection)))
+      if ((tmp =
+          stream_session_half_open_lookup (&tc->c_lcl_ip, &tc->c_rmt_ip,
+                                           tc->c_lcl_port, tc->c_rmt_port,
+                                           tc->c_proto)))
        {
          if (tmp->lcl_port == hdr->dst_port
              && tmp->rmt_port == hdr->src_port)
index 57e4a60..ff76a82 100644 (file)
 udp_uri_main_t udp_uri_main;
 
 u32
-udp_session_bind_ip4 (u32 session_index,
-                     ip46_address_t * ip, u16 port_number_host_byte_order)
+udp_session_bind_ip4 (u32 session_index, transport_endpoint_t * lcl)
 {
   udp_uri_main_t *um = vnet_get_udp_main ();
   udp_connection_t *listener;
 
   pool_get (um->udp_listeners, listener);
   memset (listener, 0, sizeof (udp_connection_t));
-  listener->c_lcl_port = clib_host_to_net_u16 (port_number_host_byte_order);
-  listener->c_lcl_ip4.as_u32 = ip->ip4.as_u32;
+  listener->c_lcl_port = clib_host_to_net_u16 (lcl->port);
+  listener->c_lcl_ip4.as_u32 = lcl->ip.ip4.as_u32;
   listener->c_proto = SESSION_TYPE_IP4_UDP;
-  udp_register_dst_port (um->vlib_main, port_number_host_byte_order,
-                        udp4_uri_input_node.index, 1 /* is_ipv4 */ );
+  udp_register_dst_port (um->vlib_main, lcl->port, udp4_uri_input_node.index,
+                        1 /* is_ipv4 */ );
   return 0;
 }
 
 u32
-udp_session_bind_ip6 (u32 session_index,
-                     ip46_address_t * ip, u16 port_number_host_byte_order)
+udp_session_bind_ip6 (u32 session_index, transport_endpoint_t * lcl)
 {
   udp_uri_main_t *um = vnet_get_udp_main ();
   udp_connection_t *listener;
 
   pool_get (um->udp_listeners, listener);
-  listener->c_lcl_port = clib_host_to_net_u16 (port_number_host_byte_order);
-  clib_memcpy (&listener->c_lcl_ip6, &ip->ip6, sizeof (ip6_address_t));
+  listener->c_lcl_port = clib_host_to_net_u16 (lcl->port);
+  clib_memcpy (&listener->c_lcl_ip6, &lcl->ip.ip6, sizeof (ip6_address_t));
   listener->c_proto = SESSION_TYPE_IP6_UDP;
-  udp_register_dst_port (um->vlib_main, port_number_host_byte_order,
+  udp_register_dst_port (um->vlib_main, lcl->port,
                         udp4_uri_input_node.index, 0 /* is_ipv4 */ );
   return 0;
 }
@@ -251,7 +249,7 @@ udp_send_space_uri (transport_connection_t * t)
 }
 
 int
-udp_open_connection (ip46_address_t * addr, u16 port)
+udp_open_connection (transport_endpoint_t * tep)
 {
   clib_warning ("Not implemented");
   return 0;