session: Add sock_name option to add_ns
[vpp.git] / src / vnet / session / session_lookup.c
index f267a4c..5cd1712 100644 (file)
@@ -156,25 +156,28 @@ make_v6_ss_kv_from_tc (session_kv6_t * kv, transport_connection_t * tc)
 }
 
 static session_table_t *
-session_table_get_or_alloc (u8 fib_proto, u8 fib_index)
+session_table_get_or_alloc (u8 fib_proto, u32 fib_index)
 {
   session_table_t *st;
   u32 table_index;
-  if (vec_len (fib_index_to_table_index[fib_proto]) <= fib_index)
+  ASSERT (fib_index != ~0);
+  if (vec_len (fib_index_to_table_index[fib_proto]) > fib_index &&
+      fib_index_to_table_index[fib_proto][fib_index] != ~0)
+    {
+      table_index = fib_index_to_table_index[fib_proto][fib_index];
+      return session_table_get (table_index);
+    }
+  else
     {
       st = session_table_alloc ();
       table_index = session_table_index (st);
-      vec_validate (fib_index_to_table_index[fib_proto], fib_index);
+      vec_validate_init_empty (fib_index_to_table_index[fib_proto], fib_index,
+                              ~0);
       fib_index_to_table_index[fib_proto][fib_index] = table_index;
       st->active_fib_proto = fib_proto;
       session_table_init (st, fib_proto);
       return st;
     }
-  else
-    {
-      table_index = fib_index_to_table_index[fib_proto][fib_index];
-      return session_table_get (table_index);
-    }
 }
 
 static session_table_t *
@@ -211,6 +214,14 @@ session_lookup_get_index_for_fib (u32 fib_proto, u32 fib_index)
   return fib_index_to_table_index[fib_proto][fib_index];
 }
 
+u32
+session_lookup_get_or_alloc_index_for_fib (u32 fib_proto, u32 fib_index)
+{
+  session_table_t *st;
+  st = session_table_get_or_alloc (fib_proto, fib_index);
+  return session_table_index (st);
+}
+
 /**
  * Add transport connection to a session table
  *
@@ -300,6 +311,32 @@ session_lookup_del_session_endpoint (u32 table_index,
     }
 }
 
+int
+session_lookup_del_session_endpoint2 (session_endpoint_t * sep)
+{
+  fib_protocol_t fib_proto;
+  session_table_t *st;
+  session_kv4_t kv4;
+  session_kv6_t kv6;
+
+  fib_proto = sep->is_ip4 ? FIB_PROTOCOL_IP4 : FIB_PROTOCOL_IP6;
+  st = session_table_get_for_fib_index (fib_proto, sep->fib_index);
+  if (!st)
+    return -1;
+  if (sep->is_ip4)
+    {
+      make_v4_listener_kv (&kv4, &sep->ip.ip4, sep->port,
+                          sep->transport_proto);
+      return clib_bihash_add_del_16_8 (&st->v4_session_hash, &kv4, 0);
+    }
+  else
+    {
+      make_v6_listener_kv (&kv6, &sep->ip.ip6, sep->port,
+                          sep->transport_proto);
+      return clib_bihash_add_del_48_8 (&st->v6_session_hash, &kv6, 0);
+    }
+}
+
 /**
  * Delete transport connection from session table
  *
@@ -338,6 +375,8 @@ session_lookup_del_session (session_t * s)
   transport_connection_t *ts;
   ts = transport_get_connection (session_get_transport_proto (s),
                                 s->connection_index, s->thread_index);
+  if (!ts || (ts->flags & TRANSPORT_CONNECTION_F_NO_LOOKUP))
+    return 0;
   return session_lookup_del_connection (ts);
 }
 
@@ -652,13 +691,13 @@ session_lookup_listener4_i (session_table_t * st, ip4_address_t * lcl,
 
 session_t *
 session_lookup_listener4 (u32 fib_index, ip4_address_t * lcl, u16 lcl_port,
-                         u8 proto)
+                         u8 proto, u8 use_wildcard)
 {
   session_table_t *st;
   st = session_table_get_for_fib_index (FIB_PROTOCOL_IP4, fib_index);
   if (!st)
     return 0;
-  return session_lookup_listener4_i (st, lcl, lcl_port, proto, 0);
+  return session_lookup_listener4_i (st, lcl, lcl_port, proto, use_wildcard);
 }
 
 static session_t *
@@ -695,13 +734,13 @@ session_lookup_listener6_i (session_table_t * st, ip6_address_t * lcl,
 
 session_t *
 session_lookup_listener6 (u32 fib_index, ip6_address_t * lcl, u16 lcl_port,
-                         u8 proto)
+                         u8 proto, u8 use_wildcard)
 {
   session_table_t *st;
   st = session_table_get_for_fib_index (FIB_PROTOCOL_IP6, fib_index);
   if (!st)
     return 0;
-  return session_lookup_listener6_i (st, lcl, lcl_port, proto, 1);
+  return session_lookup_listener6_i (st, lcl, lcl_port, proto, use_wildcard);
 }
 
 /**
@@ -723,6 +762,27 @@ session_lookup_listener (u32 table_index, session_endpoint_t * sep)
   return 0;
 }
 
+/**
+ * Lookup listener wildcard match
+ */
+session_t *
+session_lookup_listener_wildcard (u32 table_index, session_endpoint_t * sep)
+{
+  session_table_t *st;
+  st = session_table_get (table_index);
+  if (!st)
+    return 0;
+  if (sep->is_ip4)
+    return session_lookup_listener4_i (st, &sep->ip.ip4, sep->port,
+                                      sep->transport_proto,
+                                      1 /* use_wildcard */ );
+  else
+    return session_lookup_listener6_i (st, &sep->ip.ip6, sep->port,
+                                      sep->transport_proto,
+                                      1 /* use_wildcard */ );
+  return 0;
+}
+
 int
 session_lookup_add_half_open (transport_connection_t * tc, u64 value)
 {
@@ -1240,7 +1300,20 @@ session_lookup_safe6 (u32 fib_index, ip6_address_t * lcl, ip6_address_t * rmt,
   return 0;
 }
 
-clib_error_t *
+transport_connection_t *
+session_lookup_connection (u32 fib_index, ip46_address_t * lcl,
+                          ip46_address_t * rmt, u16 lcl_port, u16 rmt_port,
+                          u8 proto, u8 is_ip4)
+{
+  if (is_ip4)
+    return session_lookup_connection4 (fib_index, &lcl->ip4, &rmt->ip4,
+                                      lcl_port, rmt_port, proto);
+  else
+    return session_lookup_connection6 (fib_index, &lcl->ip6, &rmt->ip6,
+                                      lcl_port, rmt_port, proto);
+}
+
+int
 vnet_session_rule_add_del (session_rule_add_del_args_t * args)
 {
   app_namespace_t *app_ns = app_namespace_get (args->appns_index);
@@ -1248,29 +1321,26 @@ vnet_session_rule_add_del (session_rule_add_del_args_t * args)
   session_table_t *st;
   u32 fib_index;
   u8 fib_proto;
-  clib_error_t *error;
+  int rv = 0;
 
   if (!app_ns)
-    return clib_error_return_code (0, VNET_API_ERROR_APP_INVALID_NS, 0,
-                                  "invalid app ns");
+    return VNET_API_ERROR_APP_INVALID_NS;
+
   if (args->scope > 3)
-    return clib_error_return_code (0, VNET_API_ERROR_INVALID_VALUE, 0,
-                                  "invalid scope");
+    return VNET_API_ERROR_INVALID_VALUE;
+
   if (args->transport_proto != TRANSPORT_PROTO_TCP
       && args->transport_proto != TRANSPORT_PROTO_UDP)
-    return clib_error_return_code (0, VNET_API_ERROR_INVALID_VALUE, 0,
-                                  "invalid transport proto");
+    return VNET_API_ERROR_INVALID_VALUE;
+
   if ((args->scope & SESSION_RULE_SCOPE_GLOBAL) || args->scope == 0)
     {
       fib_proto = args->table_args.rmt.fp_proto;
       fib_index = app_namespace_get_fib_index (app_ns, fib_proto);
       st = session_table_get_for_fib_index (fib_proto, fib_index);
       srt = &st->session_rules[args->transport_proto];
-      if ((error = session_rules_table_add_del (srt, &args->table_args)))
-       {
-         clib_error_report (error);
-         return error;
-       }
+      if ((rv = session_rules_table_add_del (srt, &args->table_args)))
+       return rv;
     }
   if (args->scope & SESSION_RULE_SCOPE_LOCAL)
     {
@@ -1279,9 +1349,9 @@ vnet_session_rule_add_del (session_rule_add_del_args_t * args)
       args->table_args.lcl_port = 0;
       st = app_namespace_get_local_table (app_ns);
       srt = &st->session_rules[args->transport_proto];
-      error = session_rules_table_add_del (srt, &args->table_args);
+      rv = session_rules_table_add_del (srt, &args->table_args);
     }
-  return error;
+  return rv;
 }
 
 /**
@@ -1297,7 +1367,7 @@ session_lookup_set_tables_appns (app_namespace_t * app_ns)
   for (fp = 0; fp < ARRAY_LEN (fib_index_to_table_index); fp++)
     {
       fib_index = app_namespace_get_fib_index (app_ns, fp);
-      st = session_table_get_for_fib_index (fp, fib_index);
+      st = session_table_get_or_alloc (fp, fib_index);
       if (st)
        st->appns_index = app_namespace_index (app_ns);
     }
@@ -1307,7 +1377,7 @@ u8 *
 format_ip4_session_lookup_kvp (u8 * s, va_list * args)
 {
   clib_bihash_kv_16_8_t *kvp = va_arg (*args, clib_bihash_kv_16_8_t *);
-  u32 is_local = va_arg (*args, u32), app_wrk_index, session_index;
+  u32 is_local = va_arg (*args, u32);
   v4_connection_key_t *key = (v4_connection_key_t *) kvp->key;
   session_t *session;
   app_worker_t *app_wrk;
@@ -1327,8 +1397,8 @@ format_ip4_session_lookup_kvp (u8 * s, va_list * args)
     }
   else
     {
-      local_session_parse_handle (kvp->value, &app_wrk_index, &session_index);
-      app_wrk = app_worker_get (app_wrk_index);
+      session = session_get_from_handle (kvp->value);
+      app_wrk = app_worker_get (session->app_wrk_index);
       app_name = application_name_from_index (app_wrk->app_index);
       str = format (0, "[%U] %U:%d", format_transport_proto_short, key->proto,
                    format_ip4_address, &key->src,
@@ -1382,13 +1452,16 @@ session_rule_command_fn (vlib_main_t * vm, unformat_input_t * input,
                         vlib_cli_command_t * cmd)
 {
   u32 proto = ~0, lcl_port, rmt_port, action = 0, lcl_plen = 0, rmt_plen = 0;
+  clib_error_t *error = 0;
   u32 appns_index, scope = 0;
   ip46_address_t lcl_ip, rmt_ip;
   u8 is_ip4 = 1, conn_set = 0;
   u8 fib_proto, is_add = 1, *ns_id = 0;
   u8 *tag = 0;
   app_namespace_t *app_ns;
-  clib_error_t *error;
+  int rv;
+
+  session_cli_return_if_not_enabled ();
 
   clib_memset (&lcl_ip, 0, sizeof (lcl_ip));
   clib_memset (&rmt_ip, 0, sizeof (rmt_ip));
@@ -1429,29 +1502,32 @@ session_rule_command_fn (vlib_main_t * vm, unformat_input_t * input,
       else if (unformat (input, "tag %_%v%_", &tag))
        ;
       else
-       return clib_error_return (0, "unknown input `%U'",
-                                 format_unformat_error, input);
+       {
+         error = clib_error_return (0, "unknown input `%U'",
+                                    format_unformat_error, input);
+         goto done;
+       }
     }
 
   if (proto == ~0)
     {
       vlib_cli_output (vm, "proto must be set");
-      return 0;
+      goto done;
     }
   if (is_add && !conn_set && action == ~0)
     {
       vlib_cli_output (vm, "connection and action must be set for add");
-      return 0;
+      goto done;
     }
   if (!is_add && !tag && !conn_set)
     {
       vlib_cli_output (vm, "connection or tag must be set for delete");
-      return 0;
+      goto done;
     }
   if (vec_len (tag) > SESSION_RULE_TAG_MAX_LEN)
     {
       vlib_cli_output (vm, "tag too long (max u64)");
-      return 0;
+      goto done;
     }
 
   if (ns_id)
@@ -1460,7 +1536,7 @@ session_rule_command_fn (vlib_main_t * vm, unformat_input_t * input,
       if (!app_ns)
        {
          vlib_cli_output (vm, "namespace %v does not exist", ns_id);
-         return 0;
+         goto done;
        }
     }
   else
@@ -1471,6 +1547,7 @@ session_rule_command_fn (vlib_main_t * vm, unformat_input_t * input,
 
   fib_proto = is_ip4 ? FIB_PROTOCOL_IP4 : FIB_PROTOCOL_IP6;
   session_rule_add_del_args_t args = {
+    .transport_proto = proto,
     .table_args.lcl.fp_addr = lcl_ip,
     .table_args.lcl.fp_len = lcl_plen,
     .table_args.lcl.fp_proto = fib_proto,
@@ -1485,7 +1562,11 @@ session_rule_command_fn (vlib_main_t * vm, unformat_input_t * input,
     .appns_index = appns_index,
     .scope = scope,
   };
-  error = vnet_session_rule_add_del (&args);
+  if ((rv = vnet_session_rule_add_del (&args)))
+    error = clib_error_return (0, "rule add del returned %u", rv);
+
+done:
+  vec_free (ns_id);
   vec_free (tag);
   return error;
 }
@@ -1537,6 +1618,8 @@ show_session_rules_command_fn (vlib_main_t * vm, unformat_input_t * input,
   session_table_t *st;
   u8 *ns_id = 0, fib_proto;
 
+  session_cli_return_if_not_enabled ();
+
   clib_memset (&lcl_ip, 0, sizeof (lcl_ip));
   clib_memset (&rmt_ip, 0, sizeof (rmt_ip));
   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)