session: support for cl port reuse
[vpp.git] / src / vnet / session / application.c
index fdd5a0a..5c8efe1 100644 (file)
@@ -52,6 +52,7 @@ static void
 app_listener_free (application_t * app, app_listener_t * app_listener)
 {
   clib_bitmap_free (app_listener->workers);
+  vec_free (app_listener->cl_listeners);
   if (CLIB_DEBUG)
     clib_memset (app_listener, 0xfa, sizeof (*app_listener));
   pool_put (app->listeners, app_listener);
@@ -321,6 +322,13 @@ app_listener_get_local_session (app_listener_t * al)
   return listen_session_get (al->local_index);
 }
 
+session_t *
+app_listener_get_wrk_cl_session (app_listener_t *al, u32 wrk_map_index)
+{
+  u32 si = vec_elt (al->cl_listeners, wrk_map_index);
+  return session_get (si, 0 /* listener thread */);
+}
+
 static app_worker_map_t *
 app_worker_map_alloc (application_t * app)
 {
@@ -1017,6 +1025,53 @@ application_listener_select_worker (session_t * ls)
   return app_listener_select_worker (app, al);
 }
 
+always_inline u32
+app_listener_cl_flow_hash (session_dgram_hdr_t *hdr)
+{
+  u32 hash = 0;
+
+  if (hdr->is_ip4)
+    {
+      hash = clib_crc32c_u32 (hash, hdr->rmt_ip.ip4.as_u32);
+      hash = clib_crc32c_u32 (hash, hdr->lcl_ip.ip4.as_u32);
+      hash = clib_crc32c_u16 (hash, hdr->rmt_port);
+      hash = clib_crc32c_u16 (hash, hdr->lcl_port);
+    }
+  else
+    {
+      hash = clib_crc32c_u64 (hash, hdr->rmt_ip.ip6.as_u64[0]);
+      hash = clib_crc32c_u64 (hash, hdr->rmt_ip.ip6.as_u64[1]);
+      hash = clib_crc32c_u64 (hash, hdr->lcl_ip.ip6.as_u64[0]);
+      hash = clib_crc32c_u64 (hash, hdr->lcl_ip.ip6.as_u64[1]);
+      hash = clib_crc32c_u16 (hash, hdr->rmt_port);
+      hash = clib_crc32c_u16 (hash, hdr->lcl_port);
+    }
+
+  return hash;
+}
+
+session_t *
+app_listener_select_wrk_cl_session (session_t *ls, session_dgram_hdr_t *hdr)
+{
+  u32 wrk_map_index = 0;
+  application_t *app;
+  app_listener_t *al;
+
+  app = application_get (ls->app_index);
+  al = app_listener_get (app, ls->al_index);
+  /* Crude test to check if only worker 0 is set */
+  if (al->workers[0] != 1)
+    {
+      u32 hash = app_listener_cl_flow_hash (hdr);
+      hash %= vec_len (al->workers) * sizeof (uword);
+      wrk_map_index = clib_bitmap_next_set (al->workers, hash);
+      if (wrk_map_index == ~0)
+       wrk_map_index = clib_bitmap_first_set (al->workers);
+    }
+
+  return app_listener_get_wrk_cl_session (al, wrk_map_index);
+}
+
 int
 application_alloc_worker_and_init (application_t * app, app_worker_t ** wrk)
 {