session: fix v6 double binds 52/9252/3
authorFlorin Coras <fcoras@cisco.com>
Tue, 7 Nov 2017 07:27:56 +0000 (23:27 -0800)
committerDave Wallace <dwallacelf@gmail.com>
Tue, 7 Nov 2017 15:27:52 +0000 (15:27 +0000)
Change-Id: Ie747b490901254e962cf61814491851b891129ee
Signed-off-by: Florin Coras <fcoras@cisco.com>
src/vnet/session/segment_manager.c
src/vnet/session/segment_manager.h
src/vnet/session/session_lookup.c
src/vnet/session/session_test.c

index cb83d8e..f5a4024 100644 (file)
@@ -217,6 +217,12 @@ segment_manager_app_detached (segment_manager_t * sm)
   return (sm->app_index == SEGMENT_MANAGER_INVALID_APP_INDEX);
 }
 
+void
+segment_manager_app_detach (segment_manager_t * sm)
+{
+  sm->app_index = SEGMENT_MANAGER_INVALID_APP_INDEX;
+}
+
 static void
 segment_manager_del_segment (segment_manager_t * sm, u32 segment_index)
 {
@@ -325,6 +331,7 @@ segment_manager_del (segment_manager_t * sm)
 void
 segment_manager_init_del (segment_manager_t * sm)
 {
+  segment_manager_app_detach (sm);
   if (segment_manager_has_fifos (sm))
     segment_manager_del_sessions (sm);
   else
index 6e5b898..8c43880 100644 (file)
@@ -120,6 +120,7 @@ unix_shared_memory_queue_t *segment_manager_alloc_queue (segment_manager_t *
                                                         sm, u32 queue_size);
 void segment_manager_dealloc_queue (segment_manager_t * sm,
                                    unix_shared_memory_queue_t * q);
+void segment_manager_app_detach (segment_manager_t * sm);
 
 #endif /* SRC_VNET_SESSION_SEGMENT_MANAGER_H_ */
 /*
index 6cdb839..afbb8da 100644 (file)
@@ -407,14 +407,15 @@ session_lookup_session_endpoint (u32 table_index, session_endpoint_t * sep)
   ip6_address_t lcl6;
   u32 ai;
   int rv;
+  u8 sst;
 
+  sst = session_type_from_proto_and_ip (sep->transport_proto, sep->is_ip4);
   st = session_table_get (table_index);
   if (!st)
     return SESSION_INVALID_HANDLE;
   if (sep->is_ip4)
     {
-      make_v4_listener_kv (&kv4, &sep->ip.ip4, sep->port,
-                          sep->transport_proto);
+      make_v4_listener_kv (&kv4, &sep->ip.ip4, sep->port, sst);
       rv = clib_bihash_search_inline_16_8 (&st->v4_session_hash, &kv4);
       if (rv == 0)
        return kv4.value;
@@ -428,8 +429,7 @@ session_lookup_session_endpoint (u32 table_index, session_endpoint_t * sep)
     }
   else
     {
-      make_v6_listener_kv (&kv6, &sep->ip.ip6, sep->port,
-                          sep->transport_proto);
+      make_v6_listener_kv (&kv6, &sep->ip.ip6, sep->port, sst);
       rv = clib_bihash_search_inline_48_8 (&st->v6_session_hash, &kv6);
       if (rv == 0)
        return kv6.value;
index 8d18619..56d40b8 100644 (file)
@@ -98,6 +98,72 @@ static session_cb_vft_t dummy_session_cbs = {
 };
 /* *INDENT-ON* */
 
+static int
+session_test_basic (vlib_main_t * vm, unformat_input_t * input)
+{
+  session_endpoint_t server_sep = SESSION_ENDPOINT_NULL;
+  u64 options[SESSION_OPTIONS_N_OPTIONS], bind4_handle, bind6_handle;
+  u8 segment_name[128];
+  clib_error_t *error = 0;
+  u32 server_index;
+
+  memset (options, 0, sizeof (options));
+  options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_IS_BUILTIN;
+  options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_ACCEPT_REDIRECT;
+  options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE;
+  options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE;
+  vnet_app_attach_args_t attach_args = {
+    .api_client_index = ~0,
+    .options = options,
+    .namespace_id = 0,
+    .session_cb_vft = &dummy_session_cbs,
+    .segment_name = segment_name,
+  };
+
+  error = vnet_application_attach (&attach_args);
+  SESSION_TEST ((error == 0), "app attached");
+  server_index = attach_args.app_index;
+
+  server_sep.is_ip4 = 1;
+  vnet_bind_args_t bind_args = {
+    .sep = server_sep,
+    .app_index = 0,
+  };
+
+  bind_args.app_index = server_index;
+  error = vnet_bind (&bind_args);
+  SESSION_TEST ((error == 0), "server bind4 should work");
+  bind4_handle = bind_args.handle;
+
+  error = vnet_bind (&bind_args);
+  SESSION_TEST ((error != 0), "double server bind4 should not work");
+
+  bind_args.sep.is_ip4 = 0;
+  error = vnet_bind (&bind_args);
+  SESSION_TEST ((error == 0), "server bind6 should work");
+  bind6_handle = bind_args.handle;
+
+  error = vnet_bind (&bind_args);
+  SESSION_TEST ((error != 0), "double server bind6 should not work");
+
+  vnet_unbind_args_t unbind_args = {
+    .handle = bind4_handle,
+    .app_index = server_index,
+  };
+  error = vnet_unbind (&unbind_args);
+  SESSION_TEST ((error == 0), "unbind4 should work");
+
+  unbind_args.handle = bind6_handle;
+  error = vnet_unbind (&unbind_args);
+  SESSION_TEST ((error == 0), "unbind6 should work");
+
+  vnet_app_detach_args_t detach_args = {
+    .app_index = server_index,
+  };
+  vnet_application_detach (&detach_args);
+  return 0;
+}
+
 static int
 session_test_namespace (vlib_main_t * vm, unformat_input_t * input)
 {
@@ -976,6 +1042,10 @@ session_test_rules (vlib_main_t * vm, unformat_input_t * input)
   SESSION_TEST ((error == 0), "Del 1.2.3.4/32 1234 5.6.7.8/32 4321 drop "
                "tag test_rule");
 
+  vnet_app_detach_args_t detach_args = {
+    .app_index = server_index,
+  };
+  vnet_application_detach (&detach_args);
   return 0;
 }
 
@@ -1114,20 +1184,34 @@ session_test (vlib_main_t * vm,
 
   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
     {
-      if (unformat (input, "namespace"))
-       {
-         res = session_test_namespace (vm, input);
-       }
+      if (unformat (input, "basic"))
+       res = session_test_basic (vm, input);
+      else if (unformat (input, "namespace"))
+       res = session_test_namespace (vm, input);
       else if (unformat (input, "rules-table"))
        res = session_test_rule_table (vm, input);
       else if (unformat (input, "rules"))
        res = session_test_rules (vm, input);
       else if (unformat (input, "proxy"))
        res = session_test_proxy (vm, input);
+      else if (unformat (input, "all"))
+       {
+         if ((res = session_test_basic (vm, input)))
+           goto done;
+         if ((res = session_test_namespace (vm, input)))
+           goto done;
+         if ((res = session_test_rule_table (vm, input)))
+           goto done;
+         if ((res = session_test_rules (vm, input)))
+           goto done;
+         if ((res = session_test_proxy (vm, input)))
+           goto done;
+       }
       else
        break;
     }
 
+done:
   if (res)
     return clib_error_return (0, "Session unit test failed");
   return 0;