TCP horizontal scaling

- Remove frame handoff support machinery. We haven't used it in a long
  time.
- Configuration support for the local endpoints bihash table
- Drop lookup failure packets in tcp46_syn_sent

Change-Id: Icd51e6785f74661c741e76fac23d21c4cc998d17
Signed-off-by: Dave Barach <dave@barachs.net>
diff --git a/src/vlib/main.c b/src/vlib/main.c
index 73548fb..5d99e89 100644
--- a/src/vlib/main.c
+++ b/src/vlib/main.c
@@ -138,19 +138,12 @@
   else
     {
       f = clib_mem_alloc_aligned_no_fail (n, VLIB_FRAME_ALIGN);
-      f->thread_index = vm->thread_index;
       fi = vlib_frame_index_no_check (vm, f);
     }
 
   /* Poison frame when debugging. */
   if (CLIB_DEBUG > 0)
-    {
-      u32 save_thread_index = f->thread_index;
-
-      memset (f, 0xfe, n);
-
-      f->thread_index = save_thread_index;
-    }
+    memset (f, 0xfe, n);
 
   /* Insert magic number. */
   {
diff --git a/src/vlib/node.h b/src/vlib/node.h
index 7791427..2acd61c 100644
--- a/src/vlib/node.h
+++ b/src/vlib/node.h
@@ -326,7 +326,7 @@
 
 /* Max number of vector elements to process at once per node. */
 #define VLIB_FRAME_SIZE 256
-#define VLIB_FRAME_ALIGN VLIB_MAX_CPUS
+#define VLIB_FRAME_ALIGN CLIB_CACHE_LINE_BYTES
 
 /* Calling frame (think stack frame) for a node. */
 typedef struct vlib_frame_t
@@ -343,9 +343,6 @@
   /* Number of vector elements currently in frame. */
   u16 n_vectors;
 
-  /* Owner thread / heap id */
-  u16 thread_index;
-
   /* Scalar and vector arguments to next node. */
   u8 arguments[0];
 } vlib_frame_t;
diff --git a/src/vlib/node_funcs.h b/src/vlib/node_funcs.h
index c4c0645..0059b9b 100644
--- a/src/vlib/node_funcs.h
+++ b/src/vlib/node_funcs.h
@@ -216,24 +216,21 @@
 vlib_get_frame_no_check (vlib_main_t * vm, uword frame_index)
 {
   vlib_frame_t *f;
-  u32 thread_index = frame_index & VLIB_CPU_MASK;
-  u32 offset = frame_index & VLIB_OFFSET_MASK;
-  vm = vlib_mains[thread_index];
-  f = vm->heap_base + offset;
+  f = vm->heap_base + (frame_index * VLIB_FRAME_ALIGN);
   return f;
 }
 
 always_inline u32
 vlib_frame_index_no_check (vlib_main_t * vm, vlib_frame_t * f)
 {
-  u32 i;
+  uword i;
 
-  ASSERT (((uword) f & VLIB_CPU_MASK) == 0);
-
-  vm = vlib_mains[f->thread_index];
+  ASSERT (((uword) f & (VLIB_FRAME_ALIGN - 1)) == 0);
 
   i = ((u8 *) f - (u8 *) vm->heap_base);
-  return i | f->thread_index;
+  ASSERT ((i / VLIB_FRAME_ALIGN) <= 0xFFFFFFFFULL);
+
+  return i / VLIB_FRAME_ALIGN;
 }
 
 always_inline vlib_frame_t *
diff --git a/src/vnet/tcp/tcp.c b/src/vnet/tcp/tcp.c
index 197fff9..6b2b475 100644
--- a/src/vnet/tcp/tcp.c
+++ b/src/vnet/tcp/tcp.c
@@ -1321,9 +1321,14 @@
   tm->tstamp_ticks_per_clock = vm->clib_time.seconds_per_clock
     / TCP_TSTAMP_RESOLUTION;
 
+  if (tm->local_endpoints_table_buckets == 0)
+    tm->local_endpoints_table_buckets = 250000;
+  if (tm->local_endpoints_table_memory == 0)
+    tm->local_endpoints_table_memory = 512 << 20;
+
   clib_bihash_init_24_8 (&tm->local_endpoints_table, "local endpoint table",
-			 1000000 /* $$$$ config parameter nbuckets */ ,
-			 (512 << 20) /*$$$ config parameter table size */ );
+			 tm->local_endpoints_table_buckets,
+			 tm->local_endpoints_table_memory);
 
   /* Initialize [port-allocator] random number seed */
   tm->port_allocator_seed = (u32) clib_cpu_time_now ();
@@ -1377,6 +1382,7 @@
 tcp_config_fn (vlib_main_t * vm, unformat_input_t * input)
 {
   tcp_main_t *tm = vnet_get_tcp_main ();
+  u64 tmp;
 
   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
     {
@@ -1387,6 +1393,19 @@
       else if (unformat (input, "preallocated-half-open-connections %d",
 			 &tm->preallocated_half_open_connections))
 	;
+      else if (unformat (input, "local-endpoints-table-memory %U",
+			 unformat_memory_size, &tmp))
+	{
+	  if (tmp >= 0x100000000)
+	    return clib_error_return (0, "memory size %llx (%lld) too large",
+				      tmp, tmp);
+	  tm->local_endpoints_table_memory = tmp;
+	}
+      else if (unformat (input, "local-endpoints-table-buckets %d",
+			 &tm->local_endpoints_table_buckets))
+	;
+
+
       else
 	return clib_error_return (0, "unknown input `%U'",
 				  format_unformat_error, input);
diff --git a/src/vnet/tcp/tcp.h b/src/vnet/tcp/tcp.h
index 9e4660b..11d61f5 100644
--- a/src/vnet/tcp/tcp.h
+++ b/src/vnet/tcp/tcp.h
@@ -399,6 +399,10 @@
   u32 preallocated_connections;
   u32 preallocated_half_open_connections;
 
+  /** Transport table (preallocation) size parameters */
+  u32 local_endpoints_table_memory;
+  u32 local_endpoints_table_buckets;
+
   /** Vectors of src addresses. Optional unless one needs > 63K active-opens */
   ip4_address_t *ip4_src_addresses;
   u32 last_v4_address_rotor;
diff --git a/src/vnet/tcp/tcp_input.c b/src/vnet/tcp/tcp_input.c
index 95f9ade..66e2b88 100644
--- a/src/vnet/tcp/tcp_input.c
+++ b/src/vnet/tcp/tcp_input.c
@@ -1882,7 +1882,11 @@
 	  tc0 =
 	    tcp_half_open_connection_get (vnet_buffer (b0)->
 					  tcp.connection_index);
-	  ASSERT (tc0);
+	  if (PREDICT_FALSE (tc0 == 0))
+	    {
+	      error0 = TCP_ERROR_INVALID_CONNECTION;
+	      goto drop;
+	    }
 
 	  ack0 = vnet_buffer (b0)->tcp.ack_number;
 	  seq0 = vnet_buffer (b0)->tcp.seq_number;