vcl: ldp support SO_ORIGINAL_DST
[vpp.git] / src / vnet / session / session.c
index 93bdf6c..228234c 100644 (file)
@@ -17,6 +17,7 @@
  * @brief Session and session manager
  */
 
+#include <vnet/plugin/plugin.h>
 #include <vnet/session/session.h>
 #include <vnet/session/application.h>
 #include <vnet/dpo/load_balance.h>
@@ -307,8 +308,19 @@ session_cleanup_half_open (session_handle_t ho_handle)
                         ho->connection_index, ho->app_index /* overloaded */);
     }
   else
-    transport_cleanup_half_open (session_get_transport_proto (ho),
-                                ho->connection_index);
+    {
+      /* Cleanup half-open session lookup table if need be */
+      if (ho->session_state != SESSION_STATE_TRANSPORT_CLOSED)
+       {
+         transport_connection_t *tc;
+         tc = transport_get_half_open (session_get_transport_proto (ho),
+                                       ho->connection_index);
+         if (tc && !(tc->flags & TRANSPORT_CONNECTION_F_NO_LOOKUP))
+           session_lookup_del_half_open (tc);
+       }
+      transport_cleanup_half_open (session_get_transport_proto (ho),
+                                  ho->connection_index);
+    }
   session_free (ho);
 }
 
@@ -317,9 +329,10 @@ session_half_open_free (session_t *ho)
 {
   app_worker_t *app_wrk;
 
-  ASSERT (vlib_get_thread_index () <= 1);
-  app_wrk = app_worker_get (ho->app_wrk_index);
-  app_worker_del_half_open (app_wrk, ho);
+  ASSERT (vlib_get_thread_index () <= transport_cl_thread ());
+  app_wrk = app_worker_get_if_valid (ho->app_wrk_index);
+  if (app_wrk)
+    app_worker_del_half_open (app_wrk, ho);
   session_free (ho);
 }
 
@@ -333,10 +346,19 @@ session_half_open_free_rpc (void *args)
 void
 session_half_open_delete_notify (transport_connection_t *tc)
 {
+  session_t *ho = ho_session_get (tc->s_index);
+
+  /* Cleanup half-open lookup table if need be */
+  if (ho->session_state != SESSION_STATE_TRANSPORT_CLOSED)
+    {
+      if (!(tc->flags & TRANSPORT_CONNECTION_F_NO_LOOKUP))
+       session_lookup_del_half_open (tc);
+    }
+
   /* Notification from ctrl thread accepted without rpc */
   if (tc->thread_index == transport_cl_thread ())
     {
-      session_half_open_free (ho_session_get (tc->s_index));
+      session_half_open_free (ho);
     }
   else
     {
@@ -351,6 +373,9 @@ session_half_open_migrate_notify (transport_connection_t *tc)
 {
   session_t *ho;
 
+  /* Support half-open migrations only for transports with no lookup */
+  ASSERT (tc->flags & TRANSPORT_CONNECTION_F_NO_LOOKUP);
+
   ho = ho_session_get (tc->s_index);
   ho->flags |= SESSION_F_IS_MIGRATING;
   ho->connection_index = ~0;
@@ -887,6 +912,7 @@ session_stream_connect_notify (transport_connection_t * tc,
   session_lookup_del_half_open (tc);
 
   ho = ho_session_get (tc->s_index);
+  session_set_state (ho, SESSION_STATE_TRANSPORT_CLOSED);
   opaque = ho->opaque;
   app_wrk = app_worker_get_if_valid (ho->app_wrk_index);
   if (!app_wrk)
@@ -1737,6 +1763,22 @@ session_segment_handle (session_t * s)
                                              f->segment_index);
 }
 
+void
+session_get_original_dst (transport_endpoint_t *i2o_src,
+                         transport_endpoint_t *i2o_dst,
+                         transport_proto_t transport_proto, u32 *original_dst,
+                         u16 *original_dst_port)
+{
+  session_main_t *smm = vnet_get_session_main ();
+  ip_protocol_t proto =
+    (transport_proto == TRANSPORT_PROTO_TCP ? IPPROTO_TCP : IPPROTO_UDP);
+  if (!smm->original_dst_lookup || !i2o_dst->is_ip4)
+    return;
+  smm->original_dst_lookup (&i2o_src->ip.ip4, i2o_src->port, &i2o_dst->ip.ip4,
+                           i2o_dst->port, proto, original_dst,
+                           original_dst_port);
+}
+
 /* *INDENT-OFF* */
 static session_fifo_rx_fn *session_tx_fns[TRANSPORT_TX_N_FNS] = {
     session_tx_fifo_peek_and_snd,
@@ -2267,6 +2309,11 @@ session_config_fn (vlib_main_t * vm, unformat_input_t * input)
        smm->no_adaptive = 1;
       else if (unformat (input, "use-dma"))
        smm->dma_enabled = 1;
+      else if (unformat (input, "nat44-original-dst-enable"))
+       {
+         smm->original_dst_lookup = vlib_get_plugin_symbol (
+           "nat_plugin.so", "nat44_original_dst_lookup");
+       }
       /*
        * Deprecated but maintained for compatibility
        */