diff options
33 files changed, 2620 insertions, 329 deletions
diff --git a/docs/spelling_wordlist.txt b/docs/spelling_wordlist.txt index e4283909d99..8de7bf4ee24 100644 --- a/docs/spelling_wordlist.txt +++ b/docs/spelling_wordlist.txt @@ -1004,6 +1004,7 @@ screenshot scrollbar scrollbars sctp +sdl sealert seatbelt seg diff --git a/src/plugins/hs_apps/echo_client.c b/src/plugins/hs_apps/echo_client.c index d1443e75e80..8dec5d86824 100644 --- a/src/plugins/hs_apps/echo_client.c +++ b/src/plugins/hs_apps/echo_client.c @@ -429,8 +429,11 @@ ec_init (vlib_main_t *vm) ecm->app_is_init = 1; + session_enable_disable_args_t args = { .is_en = 1, + .rt_engine_type = + RT_BACKEND_ENGINE_RULE_TABLE }; vlib_worker_thread_barrier_sync (vm); - vnet_session_enable_disable (vm, 1 /* turn on session and transports */); + vnet_session_enable_disable (vm, &args); /* Turn on the builtin client input nodes */ foreach_vlib_main () diff --git a/src/plugins/hs_apps/echo_server.c b/src/plugins/hs_apps/echo_server.c index 0243252434a..756a1cc3451 100644 --- a/src/plugins/hs_apps/echo_server.c +++ b/src/plugins/hs_apps/echo_server.c @@ -736,7 +736,10 @@ echo_server_create_command_fn (vlib_main_t * vm, unformat_input_t * input, goto cleanup; } - vnet_session_enable_disable (vm, 1 /* turn on TCP, etc. */ ); + session_enable_disable_args_t args = { .is_en = 1, + .rt_engine_type = + RT_BACKEND_ENGINE_RULE_TABLE }; + vnet_session_enable_disable (vm, &args); if (!server_uri_set) { diff --git a/src/plugins/hs_apps/http_cli.c b/src/plugins/hs_apps/http_cli.c index 17624b3e827..e0bb9afba4a 100644 --- a/src/plugins/hs_apps/http_cli.c +++ b/src/plugins/hs_apps/http_cli.c @@ -731,7 +731,10 @@ start_server: if (hcm->app_index != (u32) ~0) return clib_error_return (0, "test http server is already running"); - vnet_session_enable_disable (vm, 1 /* turn on TCP, etc. */ ); + session_enable_disable_args_t args = { .is_en = 1, + .rt_engine_type = + RT_BACKEND_ENGINE_RULE_TABLE }; + vnet_session_enable_disable (vm, &args); rv = hcs_create (vm); switch (rv) diff --git a/src/plugins/hs_apps/http_client_cli.c b/src/plugins/hs_apps/http_client_cli.c index 722499b24c3..afa173c98df 100644 --- a/src/plugins/hs_apps/http_client_cli.c +++ b/src/plugins/hs_apps/http_client_cli.c @@ -558,8 +558,11 @@ hcc_command_fn (vlib_main_t *vm, unformat_input_t *input, goto done; } + session_enable_disable_args_t args = { .is_en = 1, + .rt_engine_type = + RT_BACKEND_ENGINE_RULE_TABLE }; vlib_worker_thread_barrier_sync (vm); - vnet_session_enable_disable (vm, 1 /* turn on TCP, etc. */); + vnet_session_enable_disable (vm, &args); vlib_worker_thread_barrier_release (vm); err = hcc_run (vm, print_output); diff --git a/src/plugins/hs_apps/http_simple_post.c b/src/plugins/hs_apps/http_simple_post.c index b0b9a38db2d..0c2b30ad25c 100644 --- a/src/plugins/hs_apps/http_simple_post.c +++ b/src/plugins/hs_apps/http_simple_post.c @@ -522,8 +522,11 @@ hsp_command_fn (vlib_main_t *vm, unformat_input_t *input, goto done; } + session_enable_disable_args_t args = { .is_en = 1, + .rt_engine_type = + RT_BACKEND_ENGINE_RULE_TABLE }; vlib_worker_thread_barrier_sync (vm); - vnet_session_enable_disable (vm, 1 /* turn on TCP, etc. */); + vnet_session_enable_disable (vm, &args); vlib_worker_thread_barrier_release (vm); hspm->cli_node_index = @@ -566,4 +569,4 @@ hsp_main_init (vlib_main_t *vm) return 0; } -VLIB_INIT_FUNCTION (hsp_main_init);
\ No newline at end of file +VLIB_INIT_FUNCTION (hsp_main_init); diff --git a/src/plugins/hs_apps/http_tps.c b/src/plugins/hs_apps/http_tps.c index b37c447295a..35a5802f476 100644 --- a/src/plugins/hs_apps/http_tps.c +++ b/src/plugins/hs_apps/http_tps.c @@ -760,7 +760,10 @@ start_server: if (htm->app_index == (u32) ~0) { - vnet_session_enable_disable (vm, 1 /* is_enable */); + session_enable_disable_args_t args = { .is_en = 1, + .rt_engine_type = + RT_BACKEND_ENGINE_RULE_TABLE }; + vnet_session_enable_disable (vm, &args); if (hts_create (vm)) { diff --git a/src/plugins/hs_apps/proxy.c b/src/plugins/hs_apps/proxy.c index e8fedf921a5..5edea0945b0 100644 --- a/src/plugins/hs_apps/proxy.c +++ b/src/plugins/hs_apps/proxy.c @@ -915,7 +915,10 @@ proxy_server_create_command_fn (vlib_main_t * vm, unformat_input_t * input, goto done; } - vnet_session_enable_disable (vm, 1 /* turn on session and transport */ ); + session_enable_disable_args_t args = { .is_en = 1, + .rt_engine_type = + RT_BACKEND_ENGINE_RULE_TABLE }; + vnet_session_enable_disable (vm, &args); rv = proxy_server_create (vm); switch (rv) diff --git a/src/plugins/http_static/http_static.c b/src/plugins/http_static/http_static.c index 9a98763b312..967b8474af8 100644 --- a/src/plugins/http_static/http_static.c +++ b/src/plugins/http_static/http_static.c @@ -85,7 +85,10 @@ hss_enable_api (u32 fifo_size, u32 cache_limit, u32 prealloc_fifos, if (hsm->app_index != ~0) return VNET_API_ERROR_APP_ALREADY_ATTACHED; - vnet_session_enable_disable (hsm->vlib_main, 1 /* turn on TCP, etc. */); + session_enable_disable_args_t args = { .is_en = 1, + .rt_engine_type = + RT_BACKEND_ENGINE_RULE_TABLE }; + vnet_session_enable_disable (hsm->vlib_main, &args); rv = hss_create (hsm->vlib_main); switch (rv) diff --git a/src/plugins/http_static/static_server.c b/src/plugins/http_static/static_server.c index 674ce8a0580..5515a98b446 100644 --- a/src/plugins/http_static/static_server.c +++ b/src/plugins/http_static/static_server.c @@ -950,7 +950,10 @@ no_input: goto done; } - vnet_session_enable_disable (vm, 1 /* turn on TCP, etc. */ ); + session_enable_disable_args_t args = { .is_en = 1, + .rt_engine_type = + RT_BACKEND_ENGINE_RULE_TABLE }; + vnet_session_enable_disable (vm, &args); if ((rv = hss_create (vm))) { diff --git a/src/plugins/tlsopenssl/tls_openssl.c b/src/plugins/tlsopenssl/tls_openssl.c index 5d172a0adcf..19aae3ffadc 100644 --- a/src/plugins/tlsopenssl/tls_openssl.c +++ b/src/plugins/tlsopenssl/tls_openssl.c @@ -1286,7 +1286,10 @@ tls_openssl_set_command_fn (vlib_main_t * vm, unformat_input_t * input, } else { - vnet_session_enable_disable (vm, 1); + session_enable_disable_args_t args = { .is_en = 1, + .rt_engine_type = + RT_BACKEND_ENGINE_RULE_TABLE }; + vnet_session_enable_disable (vm, &args); if (openssl_engine_register (engine_name, engine_alg, async) < 0) { return clib_error_return (0, "Failed to register %s polling", diff --git a/src/plugins/unittest/segment_manager_test.c b/src/plugins/unittest/segment_manager_test.c index a106470ee48..29da662e007 100644 --- a/src/plugins/unittest/segment_manager_test.c +++ b/src/plugins/unittest/segment_manager_test.c @@ -739,8 +739,11 @@ segment_manager_test (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd_arg) { int res = 0; + session_enable_disable_args_t args = { .is_en = 1, + .rt_engine_type = + RT_BACKEND_ENGINE_RULE_TABLE }; - vnet_session_enable_disable (vm, 1); + vnet_session_enable_disable (vm, &args); while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { diff --git a/src/plugins/unittest/session_test.c b/src/plugins/unittest/session_test.c index 6d28b2d25ec..a70a6ea88bf 100644 --- a/src/plugins/unittest/session_test.c +++ b/src/plugins/unittest/session_test.c @@ -13,13 +13,11 @@ * limitations under the License. */ -#include <vnet/session/application_namespace.h> -#include <vnet/session/application_interface.h> +#include <arpa/inet.h> #include <vnet/session/application.h> #include <vnet/session/session.h> -#include <vnet/session/session_rules_table.h> -#include <vnet/tcp/tcp.h> #include <sys/epoll.h> +#include <vnet/session/session_rules_table.h> #define SESSION_TEST_I(_cond, _comment, _args...) \ ({ \ @@ -775,10 +773,37 @@ session_test_namespace (vlib_main_t * vm, unformat_input_t * input) return 0; } +static void +session_test_disable_rt_backend_engine (vlib_main_t *vm) +{ + session_enable_disable_args_t args = { .is_en = 0, + .rt_engine_type = + RT_BACKEND_ENGINE_DISABLE }; + vnet_session_enable_disable (vm, &args); +} + +static void +session_test_enable_rule_table_engine (vlib_main_t *vm) +{ + session_enable_disable_args_t args = { .is_en = 1, + .rt_engine_type = + RT_BACKEND_ENGINE_RULE_TABLE }; + vnet_session_enable_disable (vm, &args); +} + +static void +session_test_enable_sdl_engine (vlib_main_t *vm) +{ + session_enable_disable_args_t args = { .is_en = 1, + .rt_engine_type = + RT_BACKEND_ENGINE_SDL }; + vnet_session_enable_disable (vm, &args); +} + static int session_test_rule_table (vlib_main_t * vm, unformat_input_t * input) { - session_rules_table_t _srt, *srt = &_srt; + session_table_t *st = session_table_alloc (); u16 lcl_port = 1234, rmt_port = 4321; u32 action_index = 1, res; ip4_address_t lcl_lkup, rmt_lkup; @@ -796,8 +821,11 @@ session_test_rule_table (vlib_main_t * vm, unformat_input_t * input) } } - clib_memset (srt, 0, sizeof (*srt)); - session_rules_table_init (srt); + session_test_disable_rt_backend_engine (vm); + session_test_enable_rule_table_engine (vm); + + session_table_init (st, FIB_PROTOCOL_MAX); + session_rules_table_init (st, FIB_PROTOCOL_MAX); ip4_address_t lcl_ip = { .as_u32 = clib_host_to_net_u32 (0x01020304), @@ -836,12 +864,13 @@ session_test_rule_table (vlib_main_t * vm, unformat_input_t * input) .action_index = action_index++, .is_add = 1, }; - error = session_rules_table_add_del (srt, &args); + error = + session_rules_table_add_del (st->srtg_handle, TRANSPORT_PROTO_TCP, &args); SESSION_TEST ((error == 0), "Add 1.2.3.4/16 1234 5.6.7.8/16 4321 action %d", action_index - 1); - res = - session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip, lcl_port, rmt_port); + res = session_rules_table_lookup4 (st->srtg_handle, TRANSPORT_PROTO_TCP, + &lcl_ip, &rmt_ip, lcl_port, rmt_port); SESSION_TEST ((res == 1), "Lookup 1.2.3.4 1234 5.6.7.8 4321, action should " "be 1: %d", res); @@ -852,13 +881,15 @@ session_test_rule_table (vlib_main_t * vm, unformat_input_t * input) args.lcl.fp_addr.ip4 = lcl_ip; args.lcl.fp_len = 24; args.action_index = action_index++; - error = session_rules_table_add_del (srt, &args); + error = + session_rules_table_add_del (st->srtg_handle, TRANSPORT_PROTO_TCP, &args); SESSION_TEST ((error == 0), "Add 1.2.3.4/24 1234 5.6.7.8/16 4321 action %d", action_index - 1); args.rmt.fp_addr.ip4 = rmt_ip; args.rmt.fp_len = 24; args.action_index = action_index++; - error = session_rules_table_add_del (srt, &args); + error = + session_rules_table_add_del (st->srtg_handle, TRANSPORT_PROTO_TCP, &args); SESSION_TEST ((error == 0), "Add 1.2.3.4/24 1234 5.6.7.8/24 4321 action %d", action_index - 1); @@ -870,13 +901,15 @@ session_test_rule_table (vlib_main_t * vm, unformat_input_t * input) args.rmt.fp_addr.ip4 = rmt_ip2; args.rmt.fp_len = 16; args.action_index = action_index++; - error = session_rules_table_add_del (srt, &args); + error = + session_rules_table_add_del (st->srtg_handle, TRANSPORT_PROTO_TCP, &args); SESSION_TEST ((error == 0), "Add 2.2.2.2/24 1234 6.6.6.6/16 4321 action %d", action_index - 1); args.lcl.fp_addr.ip4 = lcl_ip3; args.rmt.fp_addr.ip4 = rmt_ip3; args.action_index = action_index++; - error = session_rules_table_add_del (srt, &args); + error = + session_rules_table_add_del (st->srtg_handle, TRANSPORT_PROTO_TCP, &args); SESSION_TEST ((error == 0), "Add 3.3.3.3/24 1234 7.7.7.7/16 4321 action %d", action_index - 1); @@ -886,7 +919,8 @@ session_test_rule_table (vlib_main_t * vm, unformat_input_t * input) args.lcl.fp_addr.ip4 = lcl_ip3; args.rmt.fp_addr.ip4 = rmt_ip3; args.action_index = action_index++; - error = session_rules_table_add_del (srt, &args); + error = + session_rules_table_add_del (st->srtg_handle, TRANSPORT_PROTO_TCP, &args); SESSION_TEST ((error == 0), "overwrite 3.3.3.3/24 1234 7.7.7.7/16 4321 " "action %d", action_index - 1); @@ -894,23 +928,22 @@ session_test_rule_table (vlib_main_t * vm, unformat_input_t * input) * Lookup 1.2.3.4/32 1234 5.6.7.8/32 4321, 1.2.2.4/32 1234 5.6.7.9/32 4321 * and 3.3.3.3 1234 7.7.7.7 4321 */ - res = - session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip, lcl_port, rmt_port); + res = session_rules_table_lookup4 (st->srtg_handle, TRANSPORT_PROTO_TCP, + &lcl_ip, &rmt_ip, lcl_port, rmt_port); SESSION_TEST ((res == 3), "Lookup 1.2.3.4 1234 5.6.7.8 4321 action " "should be 3: %d", res); lcl_lkup.as_u32 = clib_host_to_net_u32 (0x01020204); rmt_lkup.as_u32 = clib_host_to_net_u32 (0x05060709); - res = - session_rules_table_lookup4 (srt, &lcl_lkup, - &rmt_lkup, lcl_port, rmt_port); + res = session_rules_table_lookup4 (st->srtg_handle, TRANSPORT_PROTO_TCP, + &lcl_lkup, &rmt_lkup, lcl_port, rmt_port); SESSION_TEST ((res == 1), "Lookup 1.2.2.4 1234 5.6.7.9 4321, action " "should be 1: %d", res); - res = - session_rules_table_lookup4 (srt, &lcl_ip3, &rmt_ip3, lcl_port, rmt_port); + res = session_rules_table_lookup4 (st->srtg_handle, TRANSPORT_PROTO_TCP, + &lcl_ip3, &rmt_ip3, lcl_port, rmt_port); SESSION_TEST ((res == 6), "Lookup 3.3.3.3 1234 7.7.7.7 4321, action " "should be 6 (updated): %d", res); @@ -926,17 +959,17 @@ session_test_rule_table (vlib_main_t * vm, unformat_input_t * input) args.lcl_port = 0; args.rmt_port = 0; args.action_index = action_index++; - error = session_rules_table_add_del (srt, &args); + error = + session_rules_table_add_del (st->srtg_handle, TRANSPORT_PROTO_TCP, &args); SESSION_TEST ((error == 0), "Add 1.2.3.4/24 * 5.6.7.8/24 * action %d", action_index - 1); - res = - session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip, lcl_port, rmt_port); + res = session_rules_table_lookup4 (st->srtg_handle, TRANSPORT_PROTO_TCP, + &lcl_ip, &rmt_ip, lcl_port, rmt_port); SESSION_TEST ((res == 7), "Lookup 1.2.3.4 1234 5.6.7.8 4321, action should" " be 7 (lpm dst): %d", res); - res = - session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip, - lcl_port + 1, rmt_port); + res = session_rules_table_lookup4 (st->srtg_handle, TRANSPORT_PROTO_TCP, + &lcl_ip, &rmt_ip, lcl_port + 1, rmt_port); SESSION_TEST ((res == 7), "Lookup 1.2.3.4 1235 5.6.7.8 4321, action should " "be 7: %d", res); @@ -948,7 +981,8 @@ session_test_rule_table (vlib_main_t * vm, unformat_input_t * input) * 1.2.3.4 1235 5.6.7.8 4322 */ args.is_add = 0; - error = session_rules_table_add_del (srt, &args); + error = + session_rules_table_add_del (st->srtg_handle, TRANSPORT_PROTO_TCP, &args); SESSION_TEST ((error == 0), "Del 1.2.3.4/24 * 5.6.7.8/24 *"); args.lcl.fp_addr.ip4 = lcl_ip; @@ -959,7 +993,8 @@ session_test_rule_table (vlib_main_t * vm, unformat_input_t * input) args.rmt_port = 0; args.action_index = action_index++; args.is_add = 1; - error = session_rules_table_add_del (srt, &args); + error = + session_rules_table_add_del (st->srtg_handle, TRANSPORT_PROTO_TCP, &args); SESSION_TEST ((error == 0), "Add 1.2.3.4/16 * 5.6.7.8/16 * action %d", action_index - 1); @@ -971,27 +1006,28 @@ session_test_rule_table (vlib_main_t * vm, unformat_input_t * input) args.rmt_port = rmt_port; args.action_index = action_index++; args.is_add = 1; - error = session_rules_table_add_del (srt, &args); + error = + session_rules_table_add_del (st->srtg_handle, TRANSPORT_PROTO_TCP, &args); SESSION_TEST ((error == 0), "Add 1.2.3.4/24 1235 5.6.7.8/24 4321 action %d", action_index - 1); if (verbose) - session_rules_table_cli_dump (vm, srt, FIB_PROTOCOL_IP4); + session_rules_table_cli_dump (vm, st->srtg_handle, TRANSPORT_PROTO_TCP, + FIB_PROTOCOL_IP4); - res = - session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip, lcl_port, rmt_port); + res = session_rules_table_lookup4 (st->srtg_handle, TRANSPORT_PROTO_TCP, + &lcl_ip, &rmt_ip, lcl_port, rmt_port); SESSION_TEST ((res == 3), "Lookup 1.2.3.4 1234 5.6.7.8 4321, action should " "be 3: %d", res); - res = - session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip, - lcl_port + 1, rmt_port); + res = session_rules_table_lookup4 (st->srtg_handle, TRANSPORT_PROTO_TCP, + &lcl_ip, &rmt_ip, lcl_port + 1, rmt_port); SESSION_TEST ((res == 9), "Lookup 1.2.3.4 1235 5.6.7.8 4321, action should " "be 9: %d", res); res = - session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip, - lcl_port + 1, rmt_port + 1); + session_rules_table_lookup4 (st->srtg_handle, TRANSPORT_PROTO_TCP, &lcl_ip, + &rmt_ip, lcl_port + 1, rmt_port + 1); SESSION_TEST ((res == 8), "Lookup 1.2.3.4 1235 5.6.7.8 4322, action should " "be 8: %d", res); @@ -1005,10 +1041,11 @@ session_test_rule_table (vlib_main_t * vm, unformat_input_t * input) args.lcl.fp_len = 16; args.rmt.fp_len = 16; args.is_add = 0; - error = session_rules_table_add_del (srt, &args); + error = + session_rules_table_add_del (st->srtg_handle, TRANSPORT_PROTO_TCP, &args); SESSION_TEST ((error == 0), "Del 1.2.0.0/16 1234 5.6.0.0/16 4321"); - res = - session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip, lcl_port, rmt_port); + res = session_rules_table_lookup4 (st->srtg_handle, TRANSPORT_PROTO_TCP, + &lcl_ip, &rmt_ip, lcl_port, rmt_port); SESSION_TEST ((res == 3), "Lookup 1.2.3.4 1234 5.6.7.8 4321, action should " "be 3: %d", res); @@ -1016,10 +1053,11 @@ session_test_rule_table (vlib_main_t * vm, unformat_input_t * input) args.lcl_port = 0; args.rmt_port = 0; args.is_add = 0; - error = session_rules_table_add_del (srt, &args); + error = + session_rules_table_add_del (st->srtg_handle, TRANSPORT_PROTO_TCP, &args); SESSION_TEST ((error == 0), "Del 1.2.0.0/16 * 5.6.0.0/16 *"); - res = - session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip, lcl_port, rmt_port); + res = session_rules_table_lookup4 (st->srtg_handle, TRANSPORT_PROTO_TCP, + &lcl_ip, &rmt_ip, lcl_port, rmt_port); SESSION_TEST ((res == 3), "Lookup 1.2.3.4 1234 5.6.7.8 4321, action should " "be 3: %d", res); @@ -1034,12 +1072,15 @@ session_test_rule_table (vlib_main_t * vm, unformat_input_t * input) args.lcl_port = 1234; args.rmt_port = 4321; args.is_add = 0; - error = session_rules_table_add_del (srt, &args); + error = + session_rules_table_add_del (st->srtg_handle, TRANSPORT_PROTO_TCP, &args); SESSION_TEST ((error == 0), "Del 1.2.3.4/24 1234 5.6.7.5/24"); - res = - session_rules_table_lookup4 (srt, &lcl_ip, &rmt_ip, lcl_port, rmt_port); + res = session_rules_table_lookup4 (st->srtg_handle, TRANSPORT_PROTO_TCP, + &lcl_ip, &rmt_ip, lcl_port, rmt_port); SESSION_TEST ((res == 2), "Action should be 2: %d", res); + session_table_free (st, FIB_PROTOCOL_MAX); + return 0; } @@ -1075,6 +1116,9 @@ session_test_rules (vlib_main_t * vm, unformat_input_t * input) } } + session_test_disable_rt_backend_engine (vm); + session_test_enable_rule_table_engine (vm); + server_sep.is_ip4 = 1; server_sep.port = placeholder_port; clib_memset (options, 0, sizeof (options)); @@ -2115,15 +2159,19 @@ session_test_enable_disable (vlib_main_t *vm, unformat_input_t *input) /* warm up */ for (i = 0; i < 10; i++) { - vnet_session_enable_disable (vm, 0); - vnet_session_enable_disable (vm, 1); + session_test_disable_rt_backend_engine (vm); + session_test_enable_sdl_engine (vm); + session_test_disable_rt_backend_engine (vm); + session_test_enable_rule_table_engine (vm); } was_using = session_get_memory_usage (); for (i = 0; i < iteration; i++) { - vnet_session_enable_disable (vm, 0); - vnet_session_enable_disable (vm, 1); + session_test_disable_rt_backend_engine (vm); + session_test_enable_sdl_engine (vm); + session_test_disable_rt_backend_engine (vm); + session_test_enable_rule_table_engine (vm); } now_using = session_get_memory_usage (); @@ -2134,13 +2182,220 @@ session_test_enable_disable (vlib_main_t *vm, unformat_input_t *input) return 0; } +static int +session_test_sdl (vlib_main_t *vm, unformat_input_t *input) +{ + session_table_t *st = session_table_alloc (); + u16 lcl_port = 0, rmt_port = 0; + u32 action_index = 1, res; + int verbose = 0, error; + ip4_address_t lcl_ip; + const char ip_str_1234[] = "1.2.3.4"; + inet_pton (AF_INET, ip_str_1234, &lcl_ip); + ip4_address_t rmt_ip = { + .as_u32 = clib_host_to_net_u32 (0x0), + }; + ip6_address_t rmt_ip6 = { + .as_u64 = { 0, 0 }, + }; + fib_prefix_t lcl_pref = { + .fp_addr.ip4.as_u32 = lcl_ip.as_u32, + .fp_len = 16, + .fp_proto = FIB_PROTOCOL_IP4, + }; + fib_prefix_t rmt_pref = { + .fp_addr.ip4.as_u32 = rmt_ip.as_u32, + .fp_len = 0, + .fp_proto = 0, + }; + session_rule_table_add_del_args_t args = { + .lcl = lcl_pref, + .rmt = rmt_pref, + .lcl_port = lcl_port, + .rmt_port = rmt_port, + .action_index = action_index++, + .is_add = 1, + }; + const char ip_str_1200[] = "1.2.0.0"; + const char ip_str_1230[] = "1.2.3.0"; + const char ip_str_1111[] = "1.1.1.1"; + const char ip6_str[] = "2501:0db8:85a3:0000:0000:8a2e:0371:1"; + const char ip6_str2[] = "2501:0db8:85a3:0000:0000:8a2e:0372:1"; + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "verbose")) + verbose = 1; + else + { + vlib_cli_output (vm, "parse error: '%U'", format_unformat_error, + input); + return -1; + } + } + + session_test_disable_rt_backend_engine (vm); + session_test_enable_sdl_engine (vm); + + session_table_init (st, FIB_PROTOCOL_MAX); + session_rules_table_init (st, FIB_PROTOCOL_MAX); + + /* Add 1.2.0.0/16 */ + args.lcl.fp_len = 16; + inet_pton (AF_INET, ip_str_1200, &args.lcl.fp_addr.ip4.as_u32); + error = + session_rules_table_add_del (st->srtg_handle, TRANSPORT_PROTO_TCP, &args); + SESSION_TEST ((error == 0), "Add %s/%d action %d", ip_str_1200, + args.lcl.fp_len, action_index - 1); + + /* Lookup 1.2.3.4 */ + res = session_rules_table_lookup4 (st->srtg_handle, TRANSPORT_PROTO_TCP, + &lcl_ip, &rmt_ip, lcl_port, rmt_port); + SESSION_TEST ((res == action_index - 1), + "Lookup %s, action should " + "be 1: %d", + ip_str_1234, action_index - 1); + + /* + * Add 1.2.3.0/24 + */ + args.lcl.fp_len = 24; + inet_pton (AF_INET, ip_str_1230, &args.lcl.fp_addr.ip4.as_u32); + args.action_index = action_index++; + error = + session_rules_table_add_del (st->srtg_handle, TRANSPORT_PROTO_TCP, &args); + SESSION_TEST ((error == 0), "Add %s/%d action %d", ip_str_1230, + args.lcl.fp_len, action_index - 1); + + /* Lookup 1.2.3.4 */ + res = session_rules_table_lookup4 (st->srtg_handle, TRANSPORT_PROTO_TCP, + &lcl_ip, &rmt_ip, lcl_port, rmt_port); + SESSION_TEST ((res == action_index - 1), + "Lookup %s, action should " + "be 2: %d", + ip_str_1234, action_index - 1); + + /* look up 1.1.1.1, should be -1 (invalid index) */ + inet_pton (AF_INET, ip_str_1111, &lcl_ip); + res = session_rules_table_lookup4 (st->srtg_handle, TRANSPORT_PROTO_TCP, + &lcl_ip, &rmt_ip, lcl_port, rmt_port); + SESSION_TEST ((res == SESSION_TABLE_INVALID_INDEX), + "Lookup %s, action should " + "be -1: %d", + ip_str_1111, res); + + /* Add again 1.2.0.0/16, should be rejected */ + args.lcl.fp_len = 16; + inet_pton (AF_INET, ip_str_1200, &args.lcl.fp_addr.ip4.as_u32); + error = + session_rules_table_add_del (st->srtg_handle, TRANSPORT_PROTO_TCP, &args); + SESSION_TEST ((error == SESSION_E_IPINUSE), "Add %s/%d action %d", + ip_str_1200, args.lcl.fp_len, error); + /* + * Add 0.0.0.0/0, should get an error + */ + args.lcl.fp_len = 0; + args.lcl.fp_addr.ip4.as_u32 = 0; + error = + session_rules_table_add_del (st->srtg_handle, TRANSPORT_PROTO_TCP, &args); + SESSION_TEST ((error == SESSION_E_IPINUSE), "Add 0.0.0.0/%d action %d", + args.lcl.fp_len, error); + + /* delete 0.0.0.0 should be rejected */ + args.is_add = 0; + error = + session_rules_table_add_del (st->srtg_handle, TRANSPORT_PROTO_TCP, &args); + SESSION_TEST ((error == SESSION_E_NOROUTE), "Del 0.0.0.0/%d action %d", + args.lcl.fp_len, error); + if (verbose) + session_rules_table_cli_dump (vm, st->srtg_handle, TRANSPORT_PROTO_TCP, + FIB_PROTOCOL_IP4); + + /* + * Clean up + * Delete 1.2.0.0/16 + * Delete 1.2.3.0/24 + */ + inet_pton (AF_INET, ip_str_1200, &args.lcl.fp_addr.ip4.as_u32); + args.lcl.fp_len = 16; + args.is_add = 0; + error = + session_rules_table_add_del (st->srtg_handle, TRANSPORT_PROTO_TCP, &args); + SESSION_TEST ((error == 0), "Del %s/%d should 0: %d", ip_str_1200, + args.lcl.fp_len, error); + + inet_pton (AF_INET, ip_str_1230, &args.lcl.fp_addr.ip4.as_u32); + args.lcl.fp_len = 24; + error = + session_rules_table_add_del (st->srtg_handle, TRANSPORT_PROTO_TCP, &args); + SESSION_TEST ((error == 0), "Del %s/%d, should be 0: %d", ip_str_1230, + args.lcl.fp_len, error); + if (verbose) + session_rules_table_cli_dump (vm, st->srtg_handle, TRANSPORT_PROTO_TCP, + FIB_PROTOCOL_IP4); + + /* ip6 tests */ + + /* + * Add ip6 2001:0db8:85a3:0000:0000:8a2e:0371:1/124 + */ + ip6_address_t lcl_lkup; + inet_pton (AF_INET6, ip6_str, &args.lcl.fp_addr.ip6); + args.lcl.fp_len = 124; + args.lcl.fp_proto = FIB_PROTOCOL_IP6; + args.action_index = action_index++; + args.is_add = 1; + error = + session_rules_table_add_del (st->srtg_handle, TRANSPORT_PROTO_TCP, &args); + SESSION_TEST ((error == 0), "Add %s/%d action %d", ip6_str, args.lcl.fp_len, + action_index - 1); + if (verbose) + session_rules_table_cli_dump (vm, st->srtg_handle, TRANSPORT_PROTO_TCP, + FIB_PROTOCOL_IP6); + + /* Lookup 2001:0db8:85a3:0000:0000:8a2e:0371:1 */ + res = session_rules_table_lookup6 (st->srtg_handle, TRANSPORT_PROTO_TCP, + &args.lcl.fp_addr.ip6, &rmt_ip6, lcl_port, + rmt_port); + SESSION_TEST ((res == action_index - 1), + "Lookup %s action should " + "be 3: %d", + ip6_str, action_index - 1); + + /* Lookup 2001:0db8:85a3:0000:0000:8a2e:0372:1 */ + inet_pton (AF_INET6, ip6_str2, &lcl_lkup); + res = session_rules_table_lookup6 (st->srtg_handle, TRANSPORT_PROTO_TCP, + &lcl_lkup, &rmt_ip6, lcl_port, rmt_port); + SESSION_TEST ((res == SESSION_TABLE_INVALID_INDEX), + "Lookup %s action should " + "be -1: %d", + ip6_str2, res); + + /* + * del ip6 2001:0db8:85a3:0000:0000:8a2e:0371:1/124 + */ + args.is_add = 0; + args.lcl.fp_len = 124; + error = + session_rules_table_add_del (st->srtg_handle, TRANSPORT_PROTO_TCP, &args); + SESSION_TEST ((error == 0), "del %s/%d, should be 0: %d", ip6_str, + args.lcl.fp_len, error); + if (verbose) + session_rules_table_cli_dump (vm, st->srtg_handle, TRANSPORT_PROTO_TCP, + FIB_PROTOCOL_IP6); + + session_table_free (st, FIB_PROTOCOL_MAX); + + return 0; +} + static clib_error_t * session_test (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd_arg) { int res = 0; - vnet_session_enable_disable (vm, 1); + session_test_enable_rule_table_engine (vm); while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { @@ -2162,6 +2417,8 @@ session_test (vlib_main_t * vm, res = session_test_mq_basic (vm, input); else if (unformat (input, "enable-disable")) res = session_test_enable_disable (vm, input); + else if (unformat (input, "sdl")) + res = session_test_sdl (vm, input); else if (unformat (input, "all")) { if ((res = session_test_basic (vm, input))) @@ -2180,6 +2437,8 @@ session_test (vlib_main_t * vm, goto done; if ((res = session_test_mq_basic (vm, input))) goto done; + if ((res = session_test_sdl (vm, input))) + goto done; if ((res = session_test_enable_disable (vm, input))) goto done; } diff --git a/src/plugins/unittest/tcp_test.c b/src/plugins/unittest/tcp_test.c index 34033a0b622..bd39474ce93 100644 --- a/src/plugins/unittest/tcp_test.c +++ b/src/plugins/unittest/tcp_test.c @@ -1550,8 +1550,11 @@ tcp_test (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd_arg) { int res = 0; + session_enable_disable_args_t args = { .is_en = 1, + .rt_engine_type = + RT_BACKEND_ENGINE_RULE_TABLE }; - vnet_session_enable_disable (vm, 1); + vnet_session_enable_disable (vm, &args); while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { diff --git a/src/vnet/CMakeLists.txt b/src/vnet/CMakeLists.txt index 1af2d40eff1..6262e803057 100644 --- a/src/vnet/CMakeLists.txt +++ b/src/vnet/CMakeLists.txt @@ -1012,6 +1012,7 @@ list(APPEND VNET_SOURCES session/application_namespace.c session/segment_manager.c session/session_api.c + session/session_sdl.c ) list(APPEND VNET_HEADERS diff --git a/src/vnet/session/application_namespace.c b/src/vnet/session/application_namespace.c index dbc6a6be80f..8b06331d803 100644 --- a/src/vnet/session/application_namespace.c +++ b/src/vnet/session/application_namespace.c @@ -34,6 +34,17 @@ static app_namespace_t *app_namespace_pool; static u8 app_sapi_enabled; +void +app_namespace_walk (app_namespace_walk_fn_t fn, void *ctx) +{ + app_namespace_t *app_ns; + + pool_foreach (app_ns, app_namespace_pool) + { + fn (app_ns, ctx); + } +} + app_namespace_t * app_namespace_get (u32 index) { diff --git a/src/vnet/session/application_namespace.h b/src/vnet/session/application_namespace.h index 261325cbe0e..b441e3c48f2 100644 --- a/src/vnet/session/application_namespace.h +++ b/src/vnet/session/application_namespace.h @@ -15,6 +15,7 @@ #include <vppinfra/socket.h> #include <vnet/vnet.h> +#include <vnet/session/session_types.h> #include <vnet/session/session_table.h> #ifndef SRC_VNET_SESSION_APPLICATION_NAMESPACE_H_ @@ -87,6 +88,9 @@ vnet_app_namespace_add_del (vnet_app_namespace_add_del_args_t *a); u32 app_namespace_get_fib_index (app_namespace_t * app_ns, u8 fib_proto); session_table_t *app_namespace_get_local_table (app_namespace_t * app_ns); +typedef void (*app_namespace_walk_fn_t) (app_namespace_t *app_ns, void *ctx); +extern void app_namespace_walk (app_namespace_walk_fn_t fn, void *ctx); + always_inline app_namespace_t * app_namespace_get_default (void) { diff --git a/src/vnet/session/session.api b/src/vnet/session/session.api index 6affae4112d..26346eaa466 100644 --- a/src/vnet/session/session.api +++ b/src/vnet/session/session.api @@ -13,12 +13,19 @@ * limitations under the License. */ -option version = "4.0.0"; +option version = "4.0.1"; import "vnet/interface_types.api"; import "vnet/ip/ip_types.api"; +typedef sdl_rule +{ + vl_api_prefix_t lcl; + u32 action_index; + string tag[64]; +}; + enum transport_proto : u8 { TRANSPORT_PROTO_API_TCP, @@ -28,6 +35,14 @@ enum transport_proto : u8 TRANSPORT_PROTO_API_QUIC, }; +enum rt_backend_engine : u8 +{ + RT_BACKEND_ENGINE_API_DISABLE = 0, + RT_BACKEND_ENGINE_API_RULE_TABLE, + RT_BACKEND_ENGINE_API_NONE, + RT_BACKEND_ENGINE_API_SDL, +}; + /** \brief Application attach to session layer @param client_index - opaque cookie to identify the sender @param context - sender context, to match reply w/ request @@ -166,11 +181,18 @@ define app_worker_add_del_reply @param is_enable - disable session layer if 0, enable otherwise */ autoreply define session_enable_disable { + option deprecated; u32 client_index; u32 context; bool is_enable [default=true]; }; +autoreply define session_enable_disable_v2 { + u32 client_index; + u32 context; + vl_api_rt_backend_engine_t rt_engine_type; +}; + /** \brief enable/disable session layer socket api @param client_index - opaque cookie to identify the sender client to vpp direction only @@ -417,6 +439,42 @@ define session_rules_details string tag[64]; }; +autoreply define session_sdl_add_del { + u32 client_index; + u32 context; + u32 appns_index; + bool is_add; + u32 count; + vl_api_sdl_rule_t r[count]; +}; + +/** \brief Dump session sdl + @param client_index - opaque cookie to identify the sender + @param context - sender context, to match reply w/ request + */ +define session_sdl_dump +{ + u32 client_index; + u32 context; +}; + +/** \brief Session sdl details + @param context - sender context, to match reply w/ request + @param lcl - local prefix + @param action_index - the only action defined now is forward to + application with index action_index + @param appns_index - application namespace where rule is to be applied to + @param tag - tag + */ +define session_sdl_details +{ + u32 context; + vl_api_prefix_t lcl; + u32 action_index; + u32 appns_index; + string tag[64]; +}; + /* * Local Variables: * eval: (c-set-style "gnu") diff --git a/src/vnet/session/session.c b/src/vnet/session/session.c index c1becf2c5ea..ac02281cf5c 100644 --- a/src/vnet/session/session.c +++ b/src/vnet/session/session.c @@ -24,6 +24,7 @@ #include <vnet/fib/ip4_fib.h> #include <vlib/stats/stats.h> #include <vlib/dma/dma.h> +#include <vnet/session/session_rules_table.h> session_main_t session_main; @@ -1996,7 +1997,8 @@ session_stats_collector_init (void) } static clib_error_t * -session_manager_main_enable (vlib_main_t * vm) +session_manager_main_enable (vlib_main_t *vm, + session_rt_engine_type_t rt_engine_type) { session_main_t *smm = &session_main; vlib_thread_main_t *vtm = vlib_get_thread_main (); @@ -2004,6 +2006,9 @@ session_manager_main_enable (vlib_main_t * vm) session_worker_t *wrk; int i; + if (session_rt_backend_enable_disable (rt_engine_type)) + return clib_error_return (0, "error on enable backend engine"); + /* We only initialize once and do not de-initialized on disable */ if (smm->is_initialized) goto done; @@ -2082,9 +2087,11 @@ done: } static void -session_manager_main_disable (vlib_main_t * vm) +session_manager_main_disable (vlib_main_t *vm, + session_rt_engine_type_t rt_engine_type) { transport_enable_disable (vm, 0 /* is_en */ ); + session_rt_backend_enable_disable (rt_engine_type); } /* in this new callback, cookie hint the index */ @@ -2221,22 +2228,24 @@ session_node_enable_disable (u8 is_en) } clib_error_t * -vnet_session_enable_disable (vlib_main_t * vm, u8 is_en) +vnet_session_enable_disable (vlib_main_t *vm, + session_enable_disable_args_t *args) { clib_error_t *error = 0; - if (is_en) + + if (args->is_en) { if (session_main.is_enabled) return 0; - error = session_manager_main_enable (vm); - session_node_enable_disable (is_en); + error = session_manager_main_enable (vm, args->rt_engine_type); + session_node_enable_disable (1); } else { session_main.is_enabled = 0; - session_manager_main_disable (vm); - session_node_enable_disable (is_en); + session_manager_main_disable (vm, args->rt_engine_type); + session_node_enable_disable (0); } return error; @@ -2263,10 +2272,15 @@ static clib_error_t * session_main_loop_init (vlib_main_t * vm) { session_main_t *smm = &session_main; + if (smm->session_enable_asap) { + session_enable_disable_args_t args = { .is_en = 1, + .rt_engine_type = + smm->rt_engine_type }; + vlib_worker_thread_barrier_sync (vm); - vnet_session_enable_disable (vm, 1 /* is_en */ ); + vnet_session_enable_disable (vm, &args); vlib_worker_thread_barrier_release (vm); } return 0; @@ -2356,8 +2370,22 @@ session_config_fn (vlib_main_t * vm, unformat_input_t * input) smm->port_allocator_min_src_port = tmp; else if (unformat (input, "max-src-port %d", &tmp)) smm->port_allocator_max_src_port = tmp; + else if (unformat (input, "enable rt-backend rule-table")) + { + smm->rt_engine_type = RT_BACKEND_ENGINE_RULE_TABLE; + smm->session_enable_asap = 1; + } + else if (unformat (input, "enable rt-backend sdl")) + { + smm->rt_engine_type = RT_BACKEND_ENGINE_SDL; + smm->session_enable_asap = 1; + } else if (unformat (input, "enable")) - smm->session_enable_asap = 1; + { + /* enable session without rt-backend */ + smm->rt_engine_type = RT_BACKEND_ENGINE_NONE; + smm->session_enable_asap = 1; + } else if (unformat (input, "use-app-socket-api")) (void) appns_sapi_enable_disable (1 /* is_enable */); else if (unformat (input, "poll-main")) diff --git a/src/vnet/session/session.h b/src/vnet/session/session.h index 67a182573e4..24150fbbcd1 100644 --- a/src/vnet/session/session.h +++ b/src/vnet/session/session.h @@ -184,6 +184,19 @@ typedef void (*nat44_original_dst_lookup_fn) ( u16 i2o_dst_port, ip_protocol_t proto, u32 *original_dst, u16 *original_dst_port); +#define foreach_rt_engine \ + _ (DISABLE, "disable") \ + _ (RULE_TABLE, "enable with rt-backend rule table") \ + _ (NONE, "enable without rt-backend") \ + _ (SDL, "enable with rt-backend sdl") + +typedef enum +{ +#define _(v, s) RT_BACKEND_ENGINE_##v, + foreach_rt_engine +#undef _ +} session_rt_engine_type_t; + typedef struct session_main_ { /** Worker contexts */ @@ -235,6 +248,9 @@ typedef struct session_main_ /** Enable session manager at startup */ u8 session_enable_asap; + /** Session engine type */ + session_rt_engine_type_t rt_engine_type; + /** Poll session node in main thread */ u8 poll_main; @@ -292,6 +308,12 @@ typedef enum session_q_process_evt_ SESSION_Q_PROCESS_STOP } session_q_process_evt_t; +typedef struct _session_enable_disable_args_t +{ + session_rt_engine_type_t rt_engine_type; + u8 is_en; +} session_enable_disable_args_t; + #define TRANSPORT_PROTO_INVALID (session_main.last_transport_proto_type + 1) #define TRANSPORT_N_PROTOS (session_main.last_transport_proto_type + 1) @@ -812,7 +834,9 @@ session_wrk_update_time (session_worker_t *wrk, f64 now) void session_wrk_enable_adaptive_mode (session_worker_t *wrk); fifo_segment_t *session_main_get_wrk_mqs_segment (void); void session_node_enable_disable (u8 is_en); -clib_error_t *vnet_session_enable_disable (vlib_main_t * vm, u8 is_en); +clib_error_t * +vnet_session_enable_disable (vlib_main_t *vm, + session_enable_disable_args_t *args); void session_wrk_handle_evts_main_rpc (void *); void session_wrk_program_app_wrk_evts (session_worker_t *wrk, u32 app_wrk_index); @@ -921,6 +945,30 @@ pool_program_safe_realloc (void **p, u32 elt_size, u32 align) } \ while (0) +always_inline u8 +session_is_enabled_without_rt_backend (void) +{ + session_main_t *smm = vnet_get_session_main (); + + return (smm->rt_engine_type == RT_BACKEND_ENGINE_NONE); +} + +always_inline u8 +session_sdl_is_enabled (void) +{ + session_main_t *smm = vnet_get_session_main (); + + return (smm->rt_engine_type == RT_BACKEND_ENGINE_SDL); +} + +always_inline u8 +session_rule_table_is_enabled (void) +{ + session_main_t *smm = vnet_get_session_main (); + + return (smm->rt_engine_type == RT_BACKEND_ENGINE_RULE_TABLE); +} + #endif /* __included_session_h__ */ /* diff --git a/src/vnet/session/session_api.c b/src/vnet/session/session_api.c index 8bb38398e3f..a729baaae29 100644 --- a/src/vnet/session/session_api.c +++ b/src/vnet/session/session_api.c @@ -18,9 +18,10 @@ #include <vnet/session/application.h> #include <vnet/session/application_interface.h> #include <vnet/session/application_local.h> -#include <vnet/session/session_rules_table.h> -#include <vnet/session/session_table.h> #include <vnet/session/session.h> +#include <vnet/session/session_table.h> +#include <vnet/session/session_rules_table.h> +#include <vnet/session/session_sdl.h> #include <vnet/ip/ip_types_api.h> #include <vnet/format_fns.h> @@ -30,6 +31,105 @@ #define REPLY_MSG_ID_BASE session_main.msg_id_base #include <vlibapi/api_helper_macros.h> +VLIB_REGISTER_LOG_CLASS (session_api_log, static) = { .class_name = "session", + .subclass_name = "api" }; + +#define log_debug(fmt, ...) \ + vlib_log_debug (session_api_log.class, "%s: " fmt, __func__, __VA_ARGS__) +#define log_warn(fmt, ...) \ + vlib_log_warn (session_api_log.class, fmt, __VA_ARGS__) +#define log_err(fmt, ...) \ + vlib_log_err (session_api_log.class, fmt, __VA_ARGS__) + +static int +verify_message_len (void *mp, u64 expected_len, char *where) +{ + u32 supplied_len = vl_msg_api_get_msg_length (mp); + + if (supplied_len < expected_len) + { + log_err ("%s: Supplied message length %d is less than expected %d", + where, supplied_len, expected_len); + return 0; + } + else + { + return 1; + } +} + +static void +vl_api_session_sdl_add_del_t_handler (vl_api_session_sdl_add_del_t *mp) +{ + vl_api_session_sdl_add_del_reply_t *rmp; + session_rule_add_del_args_t args; + session_rule_table_add_del_args_t *table_args = &args.table_args; + int rv = 0; + u32 count = clib_net_to_host_u32 (mp->count); + u64 expected_len = sizeof (*mp) + count * sizeof (mp->r[0]); + + if ((session_main.is_enabled == 0) || (session_sdl_is_enabled () == 0)) + { + rv = VNET_API_ERROR_FEATURE_DISABLED; + goto done; + } + + if (!verify_message_len (mp, expected_len, "session_sdl_add_del")) + { + rv = VNET_API_ERROR_INVALID_VALUE; + goto done; + } + + clib_memset (&args, 0, sizeof (args)); + table_args->is_add = mp->is_add; + args.scope = SESSION_RULE_SCOPE_GLOBAL; + args.appns_index = clib_net_to_host_u32 (mp->appns_index); + for (int i = 0; i < count; i++) + { + mp->r[i].tag[sizeof (mp->r[i].tag) - 1] = 0; + table_args->tag = format (0, "%s", mp->r[i].tag); + ip_prefix_decode (&mp->r[i].lcl, &table_args->lcl); + /* + * Need to set fp_proto for vnet_session_rule_add_del to find the + * correct table + */ + table_args->rmt.fp_proto = table_args->lcl.fp_proto; + table_args->action_index = clib_net_to_host_u32 (mp->r[i].action_index); + + rv = vnet_session_rule_add_del (&args); + vec_free (table_args->tag); + if (rv) + { + log_err ("session_sdl add del returned on %U @index %d: %U", + format_ip46_address, &table_args->lcl.fp_addr, + IP46_TYPE_ANY, i, format_session_error, rv); + + /* roll back */ + table_args->is_add = !mp->is_add; + for (int j = i - 1; j >= 0; j--) + { + mp->r[j].tag[sizeof (mp->r[j].tag) - 1] = 0; + table_args->tag = format (0, "%s", mp->r[j].tag); + ip_prefix_decode (&mp->r[j].lcl, &table_args->lcl); + table_args->rmt.fp_proto = table_args->lcl.fp_proto; + table_args->action_index = + clib_net_to_host_u32 (mp->r[j].action_index); + int rv2 = vnet_session_rule_add_del (&args); + vec_free (table_args->tag); + if (rv2) + log_err ("rollback session_sdl add del returned on %U " + "@index %d: %U", + format_ip46_address, &table_args->lcl.fp_addr, + IP46_TYPE_ANY, j, format_session_error, rv2); + } + break; + } + } + +done: + REPLY_MACRO (VL_API_SESSION_SDL_ADD_DEL_REPLY); +} + static transport_proto_t api_session_transport_proto_decode (const vl_api_transport_proto_t * api_tp) { @@ -520,12 +620,54 @@ vl_api_session_enable_disable_t_handler (vl_api_session_enable_disable_t * mp) vl_api_session_enable_disable_reply_t *rmp; vlib_main_t *vm = vlib_get_main (); int rv = 0; + session_enable_disable_args_t args; + + args.is_en = mp->is_enable; + if (mp->is_enable) + args.rt_engine_type = RT_BACKEND_ENGINE_RULE_TABLE; + else + args.rt_engine_type = RT_BACKEND_ENGINE_DISABLE; - vnet_session_enable_disable (vm, mp->is_enable); + if (vnet_session_enable_disable (vm, &args)) + rv = VNET_API_ERROR_INVALID_ARGUMENT; REPLY_MACRO (VL_API_SESSION_ENABLE_DISABLE_REPLY); } static void +vl_api_session_enable_disable_v2_t_handler ( + vl_api_session_enable_disable_v2_t *mp) +{ + vl_api_session_enable_disable_v2_reply_t *rmp; + vlib_main_t *vm = vlib_get_main (); + int rv = 0; + session_enable_disable_args_t args; + + STATIC_ASSERT ((session_rt_engine_type_t) RT_BACKEND_ENGINE_API_DISABLE == + RT_BACKEND_ENGINE_DISABLE, + "API value mismatch"); + STATIC_ASSERT ((session_rt_engine_type_t) RT_BACKEND_ENGINE_API_NONE == + RT_BACKEND_ENGINE_NONE, + "API value mismatch"); + STATIC_ASSERT ((session_rt_engine_type_t) RT_BACKEND_ENGINE_API_RULE_TABLE == + RT_BACKEND_ENGINE_RULE_TABLE, + "API value mismatch"); + STATIC_ASSERT ((session_rt_engine_type_t) RT_BACKEND_ENGINE_API_SDL == + RT_BACKEND_ENGINE_SDL, + "API value mismatch"); + + args.rt_engine_type = (session_rt_engine_type_t) mp->rt_engine_type; + if (args.rt_engine_type == RT_BACKEND_ENGINE_DISABLE) + args.is_en = 0; + else + args.is_en = 1; + + if (vnet_session_enable_disable (vm, &args)) + rv = VNET_API_ERROR_INVALID_VALUE; + + REPLY_MACRO (VL_API_SESSION_ENABLE_DISABLE_V2_REPLY); +} + +static void vl_api_session_sapi_enable_disable_t_handler ( vl_api_session_sapi_enable_disable_t *mp) { @@ -1131,14 +1273,89 @@ vl_api_session_rules_dump_t_handler (vl_api_session_rules_dump_t * mp) return; session_table_foreach (st, ({ - for (tp = 0; tp < TRANSPORT_N_PROTOS; tp++) - { - send_session_rules_table_details (&st->session_rules[tp], - st->active_fib_proto, tp, - st->is_local, st->appns_index, reg, - mp->context); - } - })); + if (st->srtg_handle != SESSION_SRTG_HANDLE_INVALID) + for (tp = 0; tp < TRANSPORT_N_PROTOS; tp++) + { + session_rules_table_t *srt = + srtg_handle_to_srt (st->srtg_handle, tp); + send_session_rules_table_details ( + srt, st->active_fib_proto, tp, st->is_local, + st->appns_index, reg, mp->context); + } + })); +} + +typedef struct session_sdl_table_walk_ctx_ +{ + vl_api_registration_t *reg; + u32 mp_context; + u32 appns_index; +} session_sdl_table_walk_ctx; + +static void +send_session_sdl_details (u32 fei, ip46_address_t *lcl_ip, u16 fp_len, + u32 action_index, u32 fp_proto, u8 *tag, void *args) +{ + session_sdl_table_walk_ctx *ctx = args; + vl_api_registration_t *reg = ctx->reg; + u32 appns_index = ctx->appns_index; + u32 context = ctx->mp_context; + vl_api_session_sdl_details_t *rmp = 0; + fib_prefix_t lcl; + + rmp = vl_msg_api_alloc (sizeof (*rmp)); + clib_memset (rmp, 0, sizeof (*rmp)); + rmp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_SESSION_SDL_DETAILS); + rmp->context = context; + + clib_memset (&lcl, 0, sizeof (lcl)); + if (fp_proto == FIB_PROTOCOL_IP4) + ip_set (&lcl.fp_addr, &lcl_ip->ip4, 1); + else + ip_set (&lcl.fp_addr, &lcl_ip->ip6, 0); + lcl.fp_len = fp_len; + lcl.fp_proto = fp_proto, + + ip_prefix_encode (&lcl, &rmp->lcl); + rmp->action_index = clib_host_to_net_u32 (action_index); + rmp->appns_index = clib_host_to_net_u32 (appns_index); + if (tag) + { + clib_memcpy_fast (rmp->tag, tag, vec_len (tag)); + rmp->tag[vec_len (tag)] = 0; + } + + vl_api_send_msg (reg, (u8 *) rmp); +} + +static void +vl_api_session_sdl_dump_t_handler (vl_api_session_rules_dump_t *mp) +{ + vl_api_registration_t *reg; + session_table_t *st; + session_sdl_table_walk_ctx ctx; + + reg = vl_api_client_index_to_registration (mp->client_index); + if (!reg) + return; + + ctx.reg = reg; + ctx.mp_context = mp->context; + + session_table_foreach ( + st, ({ + if (st->srtg_handle != SESSION_SRTG_HANDLE_INVALID) + { + ctx.appns_index = st->appns_index; + + if (st->active_fib_proto == FIB_PROTOCOL_IP4) + session_sdl_table_walk4 (st->srtg_handle, send_session_sdl_details, + &ctx); + else + session_sdl_table_walk6 (st->srtg_handle, send_session_sdl_details, + &ctx); + } + })); } static void @@ -1836,11 +2053,21 @@ appns_sapi_add_ns_socket (app_namespace_t * app_ns) static clib_error_t * session_api_hookup (vlib_main_t *vm) { + api_main_t *am = vlibapi_get_main (); + /* * Set up the (msg_name, crc, message-id) table */ REPLY_MSG_ID_BASE = setup_message_id_table (); + vl_api_set_msg_thread_safe ( + am, REPLY_MSG_ID_BASE + VL_API_SESSION_SDL_ADD_DEL, 1); + vl_api_set_msg_thread_safe ( + am, REPLY_MSG_ID_BASE + VL_API_SESSION_SDL_ADD_DEL_REPLY, 1); + vl_api_set_msg_thread_safe (am, REPLY_MSG_ID_BASE + VL_API_SESSION_SDL_DUMP, + 1); + vl_api_set_msg_thread_safe ( + am, REPLY_MSG_ID_BASE + VL_API_SESSION_SDL_DETAILS, 1); return 0; } diff --git a/src/vnet/session/session_cli.c b/src/vnet/session/session_cli.c index 569a77bccc1..76ecfeae243 100644 --- a/src/vnet/session/session_cli.c +++ b/src/vnet/session/session_cli.c @@ -482,6 +482,25 @@ session_cli_print_session_states (vlib_main_t * vm) #undef _ } +static u8 * +format_rt_backend (u8 *s, va_list *args) +{ + u32 i = va_arg (*args, u32); + u8 *t = 0; + + switch (i) + { +#define _(v, s) \ + case RT_BACKEND_ENGINE_##v: \ + t = (u8 *) s; \ + break; + foreach_rt_engine +#undef _ + default : return format (s, "unknown"); + } + return format (s, "%s", t); +} + static clib_error_t * show_session_command_fn (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd) @@ -573,6 +592,11 @@ show_session_command_fn (vlib_main_t * vm, unformat_input_t * input, vlib_cli_output (vm, "%U", format_transport_protos); goto done; } + else if (unformat (input, "rt-backend")) + { + vlib_cli_output (vm, "%U", format_rt_backend, smm->rt_engine_type); + goto done; + } else if (unformat (input, "states")) { session_cli_print_session_states (vm); @@ -654,13 +678,12 @@ done: return error; } -VLIB_CLI_COMMAND (vlib_cli_show_session_command) = -{ +VLIB_CLI_COMMAND (vlib_cli_show_session_command) = { .path = "show session", .short_help = "show session [verbose [n]] [listeners <proto>] " "[<session-id> [elog]] [thread <n> [index <n>] " "[proto <proto>] [state <state>] [range <min> [<max>]] " - "[protos] [states] ", + "[protos] [states] [rt-backend]", .function = show_session_command_fn, }; @@ -829,29 +852,47 @@ static clib_error_t * session_enable_disable_fn (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd) { - u8 is_en = 2; + session_enable_disable_args_t args; + session_main_t *smm = &session_main; while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { if (unformat (input, "enable")) - is_en = 1; + { + args.is_en = 1; + if (unformat (input, "rt-backend")) + if (unformat (input, "sdl")) + args.rt_engine_type = RT_BACKEND_ENGINE_SDL; + else if (unformat (input, "rule-table")) + args.rt_engine_type = RT_BACKEND_ENGINE_RULE_TABLE; + else + return clib_error_return (0, "unknown input `%U'", + format_unformat_error, input); + else + args.rt_engine_type = RT_BACKEND_ENGINE_NONE; + } else if (unformat (input, "disable")) - is_en = 0; + { + args.rt_engine_type = RT_BACKEND_ENGINE_DISABLE; + args.is_en = 0; + } else return clib_error_return (0, "unknown input `%U'", format_unformat_error, input); } - if (is_en > 1) - return clib_error_return (0, "expected enable | disable"); + if (smm->is_enabled && args.is_en) + if (args.rt_engine_type != smm->rt_engine_type) + return clib_error_return ( + 0, "session is already enable. Must disable first"); - return vnet_session_enable_disable (vm, is_en); + return vnet_session_enable_disable (vm, &args); } -VLIB_CLI_COMMAND (session_enable_disable_command, static) = -{ +VLIB_CLI_COMMAND (session_enable_disable_command, static) = { .path = "session", - .short_help = "session [enable|disable]", + .short_help = + "session { enable [ rt-backend sdl | rule-table ] } | { disable }", .function = session_enable_disable_fn, }; diff --git a/src/vnet/session/session_lookup.c b/src/vnet/session/session_lookup.c index 217fe9ad209..0d580ba35c6 100644 --- a/src/vnet/session/session_lookup.c +++ b/src/vnet/session/session_lookup.c @@ -28,6 +28,7 @@ #include <vnet/session/session_lookup.h> #include <vnet/session/session.h> #include <vnet/session/application.h> +#include <vnet/session/session_rules_table.h> static session_lookup_main_t sl_main; @@ -241,7 +242,7 @@ session_table_get_for_connection (transport_connection_t * tc) session_table_get (fib_index_to_table_index[fib_proto][tc->fib_index]); } -static session_table_t * +session_table_t * session_table_get_for_fib_index (u32 fib_proto, u32 fib_index) { if (vec_len (fib_index_to_table_index[fib_proto]) <= fib_index) @@ -478,10 +479,10 @@ session_lookup_rules_table_session4 (session_table_t * st, u8 proto, ip4_address_t * lcl, u16 lcl_port, ip4_address_t * rmt, u16 rmt_port) { - session_rules_table_t *srt = &st->session_rules[proto]; u32 action_index, app_index; - action_index = session_rules_table_lookup4 (srt, lcl, rmt, lcl_port, - rmt_port); + + action_index = session_rules_table_lookup4 (st->srtg_handle, proto, lcl, rmt, + lcl_port, rmt_port); app_index = session_lookup_action_to_handle (action_index); /* Nothing sophisticated for now, action index is app index */ return session_lookup_app_listen_session (app_index, FIB_PROTOCOL_IP4, @@ -494,10 +495,10 @@ session_lookup_rules_table_session6 (session_table_t * st, u8 proto, ip6_address_t * lcl, u16 lcl_port, ip6_address_t * rmt, u16 rmt_port) { - session_rules_table_t *srt = &st->session_rules[proto]; u32 action_index, app_index; - action_index = session_rules_table_lookup6 (srt, lcl, rmt, lcl_port, - rmt_port); + + action_index = session_rules_table_lookup6 (st->srtg_handle, proto, lcl, rmt, + lcl_port, rmt_port); app_index = session_lookup_action_to_handle (action_index); return session_lookup_app_listen_session (app_index, FIB_PROTOCOL_IP6, proto); @@ -517,7 +518,6 @@ u64 session_lookup_endpoint_listener (u32 table_index, session_endpoint_t * sep, u8 use_rules) { - session_rules_table_t *srt; session_table_t *st; u32 ai; int rv; @@ -537,10 +537,12 @@ session_lookup_endpoint_listener (u32 table_index, session_endpoint_t * sep, return kv4.value; if (use_rules) { + if (st->srtg_handle == SESSION_SRTG_HANDLE_INVALID) + return SESSION_INVALID_HANDLE; clib_memset (&lcl4, 0, sizeof (lcl4)); - srt = &st->session_rules[sep->transport_proto]; - ai = session_rules_table_lookup4 (srt, &lcl4, &sep->ip.ip4, 0, - sep->port); + ai = + session_rules_table_lookup4 (st->srtg_handle, sep->transport_proto, + &lcl4, &sep->ip.ip4, 0, sep->port); if (session_lookup_action_index_is_valid (ai)) return session_lookup_action_to_handle (ai); } @@ -558,10 +560,12 @@ session_lookup_endpoint_listener (u32 table_index, session_endpoint_t * sep, if (use_rules) { + if (st->srtg_handle == SESSION_SRTG_HANDLE_INVALID) + return SESSION_INVALID_HANDLE; clib_memset (&lcl6, 0, sizeof (lcl6)); - srt = &st->session_rules[sep->transport_proto]; - ai = session_rules_table_lookup6 (srt, &lcl6, &sep->ip.ip6, 0, - sep->port); + ai = + session_rules_table_lookup6 (st->srtg_handle, sep->transport_proto, + &lcl6, &sep->ip.ip6, 0, sep->port); if (session_lookup_action_index_is_valid (ai)) return session_lookup_action_to_handle (ai); } @@ -588,7 +592,6 @@ session_lookup_endpoint_listener (u32 table_index, session_endpoint_t * sep, u64 session_lookup_local_endpoint (u32 table_index, session_endpoint_t * sep) { - session_rules_table_t *srt; session_table_t *st; u32 ai; int rv; @@ -603,15 +606,18 @@ session_lookup_local_endpoint (u32 table_index, session_endpoint_t * sep) session_kv4_t kv4; ip4_address_t lcl4; - /* - * Check if endpoint has special rules associated - */ - clib_memset (&lcl4, 0, sizeof (lcl4)); - srt = &st->session_rules[sep->transport_proto]; - ai = session_rules_table_lookup4 (srt, &lcl4, &sep->ip.ip4, 0, - sep->port); - if (session_lookup_action_index_is_valid (ai)) - return session_lookup_action_to_handle (ai); + if (st->srtg_handle != SESSION_SRTG_HANDLE_INVALID) + { + /* + * Check if endpoint has special rules associated + */ + clib_memset (&lcl4, 0, sizeof (lcl4)); + ai = + session_rules_table_lookup4 (st->srtg_handle, sep->transport_proto, + &lcl4, &sep->ip.ip4, 0, sep->port); + if (session_lookup_action_index_is_valid (ai)) + return session_lookup_action_to_handle (ai); + } /* * Check if session endpoint is a listener @@ -651,12 +657,15 @@ session_lookup_local_endpoint (u32 table_index, session_endpoint_t * sep) session_kv6_t kv6; ip6_address_t lcl6; - clib_memset (&lcl6, 0, sizeof (lcl6)); - srt = &st->session_rules[sep->transport_proto]; - ai = session_rules_table_lookup6 (srt, &lcl6, &sep->ip.ip6, 0, - sep->port); - if (session_lookup_action_index_is_valid (ai)) - return session_lookup_action_to_handle (ai); + if (st->srtg_handle != SESSION_SRTG_HANDLE_INVALID) + { + clib_memset (&lcl6, 0, sizeof (lcl6)); + ai = + session_rules_table_lookup6 (st->srtg_handle, sep->transport_proto, + &lcl6, &sep->ip.ip6, 0, sep->port); + if (session_lookup_action_index_is_valid (ai)) + return session_lookup_action_to_handle (ai); + } make_v6_listener_kv (&kv6, &sep->ip.ip6, sep->port, sep->transport_proto); @@ -984,22 +993,25 @@ session_lookup_connection_wt4 (u32 fib_index, ip4_address_t * lcl, if (rv == 0) return transport_get_half_open (proto, kv4.value & 0xFFFFFFFF); - /* - * Check the session rules table - */ - action_index = session_rules_table_lookup4 (&st->session_rules[proto], lcl, - rmt, lcl_port, rmt_port); - if (session_lookup_action_index_is_valid (action_index)) + if (st->srtg_handle != SESSION_SRTG_HANDLE_INVALID) { - if (action_index == SESSION_RULES_TABLE_ACTION_DROP) + /* + * Check the session rules table + */ + action_index = session_rules_table_lookup4 (st->srtg_handle, proto, lcl, + rmt, lcl_port, rmt_port); + if (session_lookup_action_index_is_valid (action_index)) { - *result = SESSION_LOOKUP_RESULT_FILTERED; + if (action_index == SESSION_RULES_TABLE_ACTION_DROP) + { + *result = SESSION_LOOKUP_RESULT_FILTERED; + return 0; + } + if ((s = session_lookup_action_to_session (action_index, + FIB_PROTOCOL_IP4, proto))) + return transport_get_listener (proto, s->connection_index); return 0; } - if ((s = session_lookup_action_to_session (action_index, - FIB_PROTOCOL_IP4, proto))) - return transport_get_listener (proto, s->connection_index); - return 0; } /* @@ -1061,19 +1073,22 @@ session_lookup_connection4 (u32 fib_index, ip4_address_t * lcl, if (rv == 0) return transport_get_half_open (proto, kv4.value & 0xFFFFFFFF); - /* - * Check the session rules table - */ - action_index = session_rules_table_lookup4 (&st->session_rules[proto], lcl, - rmt, lcl_port, rmt_port); - if (session_lookup_action_index_is_valid (action_index)) + if (st->srtg_handle != SESSION_SRTG_HANDLE_INVALID) { - if (action_index == SESSION_RULES_TABLE_ACTION_DROP) - return 0; - if ((s = session_lookup_action_to_session (action_index, - FIB_PROTOCOL_IP4, proto))) - return transport_get_listener (proto, s->connection_index); - return 0; + /* + * Check the session rules table + */ + action_index = session_rules_table_lookup4 (st->srtg_handle, proto, lcl, + rmt, lcl_port, rmt_port); + if (session_lookup_action_index_is_valid (action_index)) + { + if (action_index == SESSION_RULES_TABLE_ACTION_DROP) + return 0; + if ((s = session_lookup_action_to_session (action_index, + FIB_PROTOCOL_IP4, proto))) + return transport_get_listener (proto, s->connection_index); + return 0; + } } /* @@ -1119,17 +1134,20 @@ session_lookup_safe4 (u32 fib_index, ip4_address_t * lcl, ip4_address_t * rmt, if (rv == 0) return session_get_from_handle_safe (kv4.value); - /* - * Check the session rules table - */ - action_index = session_rules_table_lookup4 (&st->session_rules[proto], lcl, - rmt, lcl_port, rmt_port); - if (session_lookup_action_index_is_valid (action_index)) + if (st->srtg_handle != SESSION_SRTG_HANDLE_INVALID) { - if (action_index == SESSION_RULES_TABLE_ACTION_DROP) - return 0; - return session_lookup_action_to_session (action_index, FIB_PROTOCOL_IP4, - proto); + /* + * Check the session rules table + */ + action_index = session_rules_table_lookup4 (st->srtg_handle, proto, lcl, + rmt, lcl_port, rmt_port); + if (session_lookup_action_index_is_valid (action_index)) + { + if (action_index == SESSION_RULES_TABLE_ACTION_DROP) + return 0; + return session_lookup_action_to_session (action_index, + FIB_PROTOCOL_IP4, proto); + } } /* @@ -1201,20 +1219,23 @@ session_lookup_connection_wt6 (u32 fib_index, ip6_address_t * lcl, if (rv == 0) return transport_get_half_open (proto, kv6.value & 0xFFFFFFFF); - /* Check the session rules table */ - action_index = session_rules_table_lookup6 (&st->session_rules[proto], lcl, - rmt, lcl_port, rmt_port); - if (session_lookup_action_index_is_valid (action_index)) + if (st->srtg_handle != SESSION_SRTG_HANDLE_INVALID) { - if (action_index == SESSION_RULES_TABLE_ACTION_DROP) + /* Check the session rules table */ + action_index = session_rules_table_lookup6 (st->srtg_handle, proto, lcl, + rmt, lcl_port, rmt_port); + if (session_lookup_action_index_is_valid (action_index)) { - *result = SESSION_LOOKUP_RESULT_FILTERED; + if (action_index == SESSION_RULES_TABLE_ACTION_DROP) + { + *result = SESSION_LOOKUP_RESULT_FILTERED; + return 0; + } + if ((s = session_lookup_action_to_session (action_index, + FIB_PROTOCOL_IP6, proto))) + return transport_get_listener (proto, s->connection_index); return 0; } - if ((s = session_lookup_action_to_session (action_index, - FIB_PROTOCOL_IP6, proto))) - return transport_get_listener (proto, s->connection_index); - return 0; } /* If nothing is found, check if any listener is available */ @@ -1270,17 +1291,20 @@ session_lookup_connection6 (u32 fib_index, ip6_address_t * lcl, if (rv == 0) return transport_get_half_open (proto, kv6.value & 0xFFFFFFFF); - /* Check the session rules table */ - action_index = session_rules_table_lookup6 (&st->session_rules[proto], lcl, - rmt, lcl_port, rmt_port); - if (session_lookup_action_index_is_valid (action_index)) + if (st->srtg_handle != SESSION_SRTG_HANDLE_INVALID) { - if (action_index == SESSION_RULES_TABLE_ACTION_DROP) - return 0; - if ((s = session_lookup_action_to_session (action_index, - FIB_PROTOCOL_IP6, proto))) - return transport_get_listener (proto, s->connection_index); - return 0; + /* Check the session rules table */ + action_index = session_rules_table_lookup6 (st->srtg_handle, proto, lcl, + rmt, lcl_port, rmt_port); + if (session_lookup_action_index_is_valid (action_index)) + { + if (action_index == SESSION_RULES_TABLE_ACTION_DROP) + return 0; + if ((s = session_lookup_action_to_session (action_index, + FIB_PROTOCOL_IP6, proto))) + return transport_get_listener (proto, s->connection_index); + return 0; + } } /* If nothing is found, check if any listener is available */ @@ -1323,15 +1347,18 @@ session_lookup_safe6 (u32 fib_index, ip6_address_t * lcl, ip6_address_t * rmt, if (rv == 0) return session_get_from_handle_safe (kv6.value); - /* Check the session rules table */ - action_index = session_rules_table_lookup6 (&st->session_rules[proto], lcl, - rmt, lcl_port, rmt_port); - if (session_lookup_action_index_is_valid (action_index)) + if (st->srtg_handle != SESSION_SRTG_HANDLE_INVALID) { - if (action_index == SESSION_RULES_TABLE_ACTION_DROP) - return 0; - return session_lookup_action_to_session (action_index, FIB_PROTOCOL_IP6, - proto); + /* Check the session rules table */ + action_index = session_rules_table_lookup6 (st->srtg_handle, proto, lcl, + rmt, lcl_port, rmt_port); + if (session_lookup_action_index_is_valid (action_index)) + { + if (action_index == SESSION_RULES_TABLE_ACTION_DROP) + return 0; + return session_lookup_action_to_session (action_index, + FIB_PROTOCOL_IP6, proto); + } } /* If nothing is found, check if any listener is available */ @@ -1357,7 +1384,6 @@ session_error_t vnet_session_rule_add_del (session_rule_add_del_args_t *args) { app_namespace_t *app_ns = app_namespace_get (args->appns_index); - session_rules_table_t *srt; session_table_t *st; u32 fib_index; u8 fib_proto; @@ -1378,8 +1404,9 @@ vnet_session_rule_add_del (session_rule_add_del_args_t *args) 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 ((rv = session_rules_table_add_del (srt, &args->table_args))) + session_rules_table_init (st, fib_proto); + if ((rv = session_rules_table_add_del ( + st->srtg_handle, args->transport_proto, &args->table_args))) return rv; } if (args->scope & SESSION_RULE_SCOPE_LOCAL) @@ -1388,8 +1415,9 @@ vnet_session_rule_add_del (session_rule_add_del_args_t *args) args->table_args.lcl.fp_proto = args->table_args.rmt.fp_proto; args->table_args.lcl_port = 0; st = app_namespace_get_local_table (app_ns); - srt = &st->session_rules[args->transport_proto]; - rv = session_rules_table_add_del (srt, &args->table_args); + session_rules_table_init (st, args->table_args.rmt.fp_proto); + rv = session_rules_table_add_del (st->srtg_handle, args->transport_proto, + &args->table_args); } return rv; } @@ -1523,6 +1551,9 @@ session_rule_command_fn (vlib_main_t * vm, unformat_input_t * input, session_cli_return_if_not_enabled (); + if (session_rule_table_is_enabled () == 0) + return clib_error_return (0, "session rule table engine is 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) @@ -1644,11 +1675,12 @@ session_lookup_dump_rules_table (u32 fib_index, u8 fib_proto, u8 transport_proto) { vlib_main_t *vm = vlib_get_main (); - session_rules_table_t *srt; session_table_t *st; st = session_table_get_for_fib_index (fib_index, fib_proto); - srt = &st->session_rules[transport_proto]; - session_rules_table_cli_dump (vm, srt, fib_proto); + if (st == 0) + return; + session_rules_table_cli_dump (vm, st->srtg_handle, transport_proto, + fib_proto); } void @@ -1656,11 +1688,12 @@ session_lookup_dump_local_rules_table (u32 table_index, u8 fib_proto, u8 transport_proto) { vlib_main_t *vm = vlib_get_main (); - session_rules_table_t *srt; session_table_t *st; st = session_table_get (table_index); - srt = &st->session_rules[transport_proto]; - session_rules_table_cli_dump (vm, srt, fib_proto); + if (st == 0) + return; + session_rules_table_cli_dump (vm, st->srtg_handle, transport_proto, + fib_proto); } static clib_error_t * @@ -1672,7 +1705,6 @@ show_session_rules_command_fn (vlib_main_t * vm, unformat_input_t * input, ip46_address_t lcl_ip, rmt_ip; u8 is_ip4 = 1, show_one = 0; app_namespace_t *app_ns; - session_rules_table_t *srt; session_table_t *st; u8 *ns_id = 0, fib_proto; @@ -1745,11 +1777,18 @@ show_session_rules_command_fn (vlib_main_t * vm, unformat_input_t * input, st = app_namespace_get_local_table (app_ns); } + if (session_rule_table_is_enabled () == 0) + { + vlib_cli_output (vm, "session rule table engine is not enabled"); + goto done; + } + if (show_one) { - srt = &st->session_rules[transport_proto]; - session_rules_table_show_rule (vm, srt, &lcl_ip, lcl_port, &rmt_ip, - rmt_port, is_ip4); + if (st) + session_rules_table_show_rule (vm, st->srtg_handle, transport_proto, + &lcl_ip, lcl_port, &rmt_ip, rmt_port, + is_ip4); goto done; } @@ -1759,9 +1798,10 @@ show_session_rules_command_fn (vlib_main_t * vm, unformat_input_t * input, { if (st) { - srt = &st->session_rules[transport_proto]; - session_rules_table_cli_dump (vm, srt, FIB_PROTOCOL_IP4); - session_rules_table_cli_dump (vm, srt, FIB_PROTOCOL_IP6); + session_rules_table_cli_dump (vm, st->srtg_handle, transport_proto, + FIB_PROTOCOL_IP4); + session_rules_table_cli_dump (vm, st->srtg_handle, transport_proto, + FIB_PROTOCOL_IP6); } } else @@ -1772,18 +1812,14 @@ show_session_rules_command_fn (vlib_main_t * vm, unformat_input_t * input, st = session_table_get_for_fib_index (FIB_PROTOCOL_IP4, app_ns->ip4_fib_index); if (st) - { - srt = &st->session_rules[transport_proto]; - session_rules_table_cli_dump (vm, srt, FIB_PROTOCOL_IP4); - } + session_rules_table_cli_dump (vm, st->srtg_handle, transport_proto, + FIB_PROTOCOL_IP4); st = session_table_get_for_fib_index (FIB_PROTOCOL_IP6, app_ns->ip6_fib_index); if (st) - { - srt = &st->session_rules[transport_proto]; - session_rules_table_cli_dump (vm, srt, FIB_PROTOCOL_IP6); - } + session_rules_table_cli_dump (vm, st->srtg_handle, transport_proto, + FIB_PROTOCOL_IP6); } done: vec_free (ns_id); diff --git a/src/vnet/session/session_lookup.h b/src/vnet/session/session_lookup.h index 95fcca6ff69..9f56af20a87 100644 --- a/src/vnet/session/session_lookup.h +++ b/src/vnet/session/session_lookup.h @@ -19,6 +19,8 @@ #include <vnet/session/session_table.h> #include <vnet/session/session_types.h> #include <vnet/session/application_namespace.h> +#include <vnet/fib/fib_table.h> +#include <vnet/fib/fib_source.h> #define HALF_OPEN_LOOKUP_INVALID_VALUE ((u64)~0) @@ -115,6 +117,17 @@ typedef enum _session_rule_scope SESSION_RULE_SCOPE_LOCAL = 2, } session_rule_scope_e; +typedef struct _session_rules_table_add_del_args +{ + fib_prefix_t lcl; + fib_prefix_t rmt; + u16 lcl_port; + u16 rmt_port; + u32 action_index; + u8 *tag; + u8 is_add; +} session_rule_table_add_del_args_t; + typedef struct _session_rule_add_del_args { /** @@ -140,6 +153,8 @@ session_error_t vnet_session_rule_add_del (session_rule_add_del_args_t *args); void session_lookup_set_tables_appns (app_namespace_t * app_ns); void session_lookup_init (void); +session_table_t *session_table_get_for_fib_index (u32 fib_proto, + u32 fib_index); #endif /* SRC_VNET_SESSION_SESSION_LOOKUP_H_ */ diff --git a/src/vnet/session/session_rules_table.c b/src/vnet/session/session_rules_table.c index d15df48d7b5..acb575b0f7c 100644 --- a/src/vnet/session/session_rules_table.c +++ b/src/vnet/session/session_rules_table.c @@ -17,8 +17,23 @@ #include <vnet/session/mma_template.c> #include <vnet/session/mma_40.h> #include <vnet/session/mma_template.c> -#include <vnet/session/session_rules_table.h> #include <vnet/session/transport.h> +#include <vnet/session/session.h> +#include <vnet/session/session_table.h> +#include <vnet/session/session_rules_table.h> +#include <vnet/session/session_sdl.h> + +VLIB_REGISTER_LOG_CLASS (session_rt_log, static) = { .class_name = "session", + .subclass_name = "rt" }; + +#define log_debug(fmt, ...) \ + vlib_log_debug (session_rt_log.class, "%s: " fmt, __func__, __VA_ARGS__) +#define log_warn(fmt, ...) \ + vlib_log_warn (session_rt_log.class, fmt, __VA_ARGS__) +#define log_err(fmt, ...) vlib_log_err (session_rt_log.class, fmt, __VA_ARGS__) + +static session_rules_table_group_t *srt_instances; +const session_rt_engine_vft_t *session_rt_engine_vft; u32 session_rule_tag_key_index (u32 ri, u8 is_ip4) @@ -119,13 +134,25 @@ fib_pref_normalize (fib_prefix_t * pref) } u8 * +format_session_rule_tag (u8 *s, va_list *args) +{ + static u8 *null_tag = 0; + u8 *tag = va_arg (*args, u8 *); + + if (!null_tag) + null_tag = format (0, "none"); + s = format (s, "%v", (tag != 0) ? tag : null_tag); + return s; +} + +u8 * format_session_rule4 (u8 * s, va_list * args) { session_rules_table_t *srt = va_arg (*args, session_rules_table_t *); mma_rule_16_t *sr = va_arg (*args, mma_rule_16_t *); session_mask_or_match_4_t *mask, *match; mma_rules_table_16_t *srt4; - u8 *tag = 0, *null_tag = format (0, "none"); + u8 *tag = 0; u32 ri; int i; @@ -135,20 +162,18 @@ format_session_rule4 (u8 * s, va_list * args) match = (session_mask_or_match_4_t *) & sr->match; mask = (session_mask_or_match_4_t *) & sr->mask; - s = format (s, "[%d] rule: %U/%d %d %U/%d %d action: %d tag: %v", ri, + s = format (s, "[%d] rule: %U/%d %d %U/%d %d action: %d tag: %U", ri, format_ip4_address, &match->lcl_ip, - ip4_mask_to_preflen (&mask->lcl_ip), - clib_net_to_host_u16 (match->lcl_port), format_ip4_address, - &match->rmt_ip, ip4_mask_to_preflen (&mask->rmt_ip), - clib_net_to_host_u16 (match->rmt_port), sr->action_index, - tag ? tag : null_tag); + ip4_mask_to_preflen (&mask->lcl_ip), match->lcl_port, + format_ip4_address, &match->rmt_ip, + ip4_mask_to_preflen (&mask->rmt_ip), match->rmt_port, + sr->action_index, format_session_rule_tag, tag); if (vec_len (sr->next_indices)) { s = format (s, "\n children: "); for (i = 0; i < vec_len (sr->next_indices); i++) s = format (s, "%d ", sr->next_indices[i]); } - vec_free (null_tag); return s; } @@ -159,7 +184,7 @@ format_session_rule6 (u8 * s, va_list * args) mma_rule_40_t *sr = va_arg (*args, mma_rule_40_t *); session_mask_or_match_6_t *mask, *match; mma_rules_table_40_t *srt6; - u8 *tag = 0, *null_tag = format (0, "none"); + u8 *tag = 0; u32 ri; int i; @@ -169,20 +194,18 @@ format_session_rule6 (u8 * s, va_list * args) match = (session_mask_or_match_6_t *) & sr->match; mask = (session_mask_or_match_6_t *) & sr->mask; - s = format (s, "[%d] rule: %U/%d %d %U/%d %d action: %d tag: %v", ri, + s = format (s, "[%d] rule: %U/%d %d %U/%d %d action: %d tag: %U", ri, format_ip6_address, &match->lcl_ip, - ip6_mask_to_preflen (&mask->lcl_ip), - clib_net_to_host_u16 (match->lcl_port), format_ip6_address, - &match->rmt_ip, ip6_mask_to_preflen (&mask->rmt_ip), - clib_net_to_host_u16 (match->rmt_port), sr->action_index, - tag ? tag : null_tag); + ip6_mask_to_preflen (&mask->lcl_ip), match->lcl_port, + format_ip6_address, &match->rmt_ip, + ip6_mask_to_preflen (&mask->rmt_ip), match->rmt_port, + sr->action_index, format_session_rule_tag, tag); if (vec_len (sr->next_indices)) { s = format (s, "\n children: "); for (i = 0; i < vec_len (sr->next_indices); i++) s = format (s, "%d ", sr->next_indices[i]); } - vec_free (null_tag); return s; } @@ -313,11 +336,10 @@ session_rules_table_alloc_rule_40 (mma_rules_table_40_t * srt, return rule; } -u32 -session_rules_table_lookup_rule4 (session_rules_table_t * srt, - ip4_address_t * lcl_ip, - ip4_address_t * rmt_ip, u16 lcl_port, - u16 rmt_port) +static u32 +session_rules_table_lookup_rule4 (session_rules_table_t *srt, + ip4_address_t *lcl_ip, ip4_address_t *rmt_ip, + u16 lcl_port, u16 rmt_port) { mma_rules_table_16_t *srt4 = &srt->session_rules_tables_16; session_mask_or_match_4_t key = { @@ -326,16 +348,20 @@ session_rules_table_lookup_rule4 (session_rules_table_t * srt, .lcl_port = lcl_port, .rmt_port = rmt_port, }; + + if (srt4->rules == 0) + return SESSION_TABLE_INVALID_INDEX; return mma_rules_table_lookup_rule_16 (srt4, (mma_mask_or_match_16_t *) & key, srt4->root_index); } u32 -session_rules_table_lookup4 (session_rules_table_t * srt, - ip4_address_t * lcl_ip, ip4_address_t * rmt_ip, - u16 lcl_port, u16 rmt_port) +session_rules_table_lookup4_ (u32 srtg_handle, u32 proto, + ip4_address_t *lcl_ip, ip4_address_t *rmt_ip, + u16 lcl_port, u16 rmt_port) { + session_rules_table_t *srt = srtg_handle_to_srt (srtg_handle, proto); mma_rules_table_16_t *srt4 = &srt->session_rules_tables_16; session_mask_or_match_4_t key = { .lcl_ip.as_u32 = lcl_ip->as_u32, @@ -343,21 +369,36 @@ session_rules_table_lookup4 (session_rules_table_t * srt, .lcl_port = lcl_port, .rmt_port = rmt_port, }; + + if (srt4->rules == 0) + return SESSION_TABLE_INVALID_INDEX; return mma_rules_table_lookup_16 (srt4, (mma_mask_or_match_16_t *) & key, srt4->root_index); } -u32 -session_rules_table_lookup_rule6 (session_rules_table_t * srt, - ip6_address_t * lcl_ip, - ip6_address_t * rmt_ip, u16 lcl_port, - u16 rmt_port) +session_rules_table_t * +srtg_handle_to_srt (u32 srtg_handle, u32 proto) +{ + session_rules_table_group_t *srtg = + pool_elt_at_index (srt_instances, srtg_handle); + session_rules_table_t *srt = &srtg->session_rules[proto]; + + return srt; +} + +static u32 +session_rules_table_lookup_rule6 (session_rules_table_t *srt, + ip6_address_t *lcl_ip, ip6_address_t *rmt_ip, + u16 lcl_port, u16 rmt_port) { mma_rules_table_40_t *srt6 = &srt->session_rules_tables_40; session_mask_or_match_6_t key = { .lcl_port = lcl_port, .rmt_port = rmt_port, }; + + if (srt6->rules == 0) + return SESSION_TABLE_INVALID_INDEX; clib_memcpy_fast (&key.lcl_ip, lcl_ip, sizeof (*lcl_ip)); clib_memcpy_fast (&key.rmt_ip, rmt_ip, sizeof (*rmt_ip)); return mma_rules_table_lookup_rule_40 (srt6, @@ -366,15 +407,19 @@ session_rules_table_lookup_rule6 (session_rules_table_t * srt, } u32 -session_rules_table_lookup6 (session_rules_table_t * srt, - ip6_address_t * lcl_ip, ip6_address_t * rmt_ip, - u16 lcl_port, u16 rmt_port) +session_rules_table_lookup6_ (u32 srtg_handle, u32 proto, + ip6_address_t *lcl_ip, ip6_address_t *rmt_ip, + u16 lcl_port, u16 rmt_port) { + session_rules_table_t *srt = srtg_handle_to_srt (srtg_handle, proto); mma_rules_table_40_t *srt6 = &srt->session_rules_tables_40; session_mask_or_match_6_t key = { .lcl_port = lcl_port, .rmt_port = rmt_port, }; + + if (srt6->rules == 0) + return SESSION_TABLE_INVALID_INDEX; clib_memcpy_fast (&key.lcl_ip, lcl_ip, sizeof (*lcl_ip)); clib_memcpy_fast (&key.rmt_ip, rmt_ip, sizeof (*rmt_ip)); return mma_rules_table_lookup_40 (srt6, (mma_mask_or_match_40_t *) & key, @@ -390,9 +435,10 @@ session_rules_table_lookup6 (session_rules_table_t * srt, * @return 0 if success, session_error_t error otherwise */ session_error_t -session_rules_table_add_del (session_rules_table_t *srt, - session_rule_table_add_del_args_t *args) +session_rules_table_add_del_ (u32 srtg_handle, u32 proto, + session_rule_table_add_del_args_t *args) { + session_rules_table_t *srt = srtg_handle_to_srt (srtg_handle, proto); u8 fib_proto = args->rmt.fp_proto, *rt; u32 ri_from_tag, ri; int rv; @@ -515,50 +561,90 @@ session_rules_table_add_del (session_rules_table_t *srt, } void -session_rules_table_free (session_rules_table_t *srt) +session_rules_table_free_ (session_table_t *st, u8 fib_proto) +{ + session_rules_table_group_t *srtg = + pool_elt_at_index (srt_instances, st->srtg_handle); + session_rules_table_t *srt; + + vec_foreach (srt, srtg->session_rules) + { + mma_rules_table_free_16 (&srt->session_rules_tables_16); + mma_rules_table_free_40 (&srt->session_rules_tables_40); + + hash_free (srt->tags_by_rules); + hash_free (srt->rules_by_tag); + } + srtg_instance_free (st); +} + +void +srtg_instance_free (session_table_t *st) { - mma_rules_table_free_16 (&srt->session_rules_tables_16); - mma_rules_table_free_40 (&srt->session_rules_tables_40); + session_rules_table_group_t *srtg = + pool_elt_at_index (srt_instances, st->srtg_handle); - hash_free (srt->tags_by_rules); - hash_free (srt->rules_by_tag); + vec_free (srtg->session_rules); + pool_put (srt_instances, srtg); + st->srtg_handle = SESSION_SRTG_HANDLE_INVALID; +} + +session_rules_table_group_t * +srtg_instance_alloc (session_table_t *st, u32 n_proto) +{ + session_rules_table_group_t *srtg; + + pool_get (srt_instances, srtg); + vec_validate (srtg->session_rules, n_proto); + st->srtg_handle = srtg - srt_instances; + return (srtg); } void -session_rules_table_init (session_rules_table_t * srt) +session_rules_table_init_ (session_table_t *st, u8 fib_proto) { mma_rules_table_16_t *srt4; mma_rules_table_40_t *srt6; mma_rule_16_t *rule4; mma_rule_40_t *rule6; fib_prefix_t null_prefix; + session_rules_table_t *srt; + session_rules_table_group_t *srtg; - clib_memset (&null_prefix, 0, sizeof (null_prefix)); + srtg = srtg_instance_alloc (st, TRANSPORT_N_PROTOS - 1); - srt4 = &srt->session_rules_tables_16; - rule4 = session_rules_table_alloc_rule_16 (srt4, &null_prefix, 0, - &null_prefix, 0); - rule4->action_index = SESSION_RULES_TABLE_INVALID_INDEX; - srt4->root_index = mma_rules_table_rule_index_16 (srt4, rule4); - srt4->rule_cmp_fn = rule_cmp_16; + clib_memset (&null_prefix, 0, sizeof (null_prefix)); + vec_foreach (srt, srtg->session_rules) + { + srt4 = &srt->session_rules_tables_16; - srt6 = &srt->session_rules_tables_40; - rule6 = session_rules_table_alloc_rule_40 (srt6, &null_prefix, 0, - &null_prefix, 0); - rule6->action_index = SESSION_RULES_TABLE_INVALID_INDEX; - srt6->root_index = mma_rules_table_rule_index_40 (srt6, rule6); - srt6->rule_cmp_fn = rule_cmp_40; + ASSERT (srt4->rules == 0); + rule4 = session_rules_table_alloc_rule_16 (srt4, &null_prefix, 0, + &null_prefix, 0); + rule4->action_index = SESSION_RULES_TABLE_INVALID_INDEX; + srt4->root_index = mma_rules_table_rule_index_16 (srt4, rule4); + srt4->rule_cmp_fn = rule_cmp_16; - srt->rules_by_tag = hash_create_vec (0, sizeof (u8), sizeof (uword)); - srt->tags_by_rules = hash_create (0, sizeof (uword)); + srt6 = &srt->session_rules_tables_40; + ASSERT (srt6->rules == 0); + rule6 = session_rules_table_alloc_rule_40 (srt6, &null_prefix, 0, + &null_prefix, 0); + rule6->action_index = SESSION_RULES_TABLE_INVALID_INDEX; + srt6->root_index = mma_rules_table_rule_index_40 (srt6, rule6); + srt6->rule_cmp_fn = rule_cmp_40; + + srt->rules_by_tag = hash_create_vec (0, sizeof (u8), sizeof (uword)); + srt->tags_by_rules = hash_create (0, sizeof (uword)); + } } void -session_rules_table_show_rule (vlib_main_t * vm, session_rules_table_t * srt, - ip46_address_t * lcl_ip, u16 lcl_port, - ip46_address_t * rmt_ip, u16 rmt_port, - u8 is_ip4) +session_rules_table_show_rule_ (vlib_main_t *vm, u32 srtg_handle, u32 proto, + ip46_address_t *lcl_ip, u16 lcl_port, + ip46_address_t *rmt_ip, u16 rmt_port, + u8 is_ip4) { + session_rules_table_t *srt = srtg_handle_to_srt (srtg_handle, proto); mma_rules_table_16_t *srt4; mma_rules_table_40_t *srt6; mma_rule_16_t *sr4; @@ -599,9 +685,10 @@ session_rules_table_show_rule (vlib_main_t * vm, session_rules_table_t * srt, } void -session_rules_table_cli_dump (vlib_main_t * vm, session_rules_table_t * srt, - u8 fib_proto) +session_rules_table_cli_dump_ (vlib_main_t *vm, u32 srtg_handle, u32 proto, + u8 fib_proto) { + session_rules_table_t *srt = srtg_handle_to_srt (srtg_handle, proto); if (fib_proto == FIB_PROTOCOL_IP4) { mma_rules_table_16_t *srt4; @@ -628,6 +715,108 @@ session_rules_table_cli_dump (vlib_main_t * vm, session_rules_table_t * srt, } } +static const session_rt_engine_vft_t session_rules_table_vft = { + .backend_engine = RT_BACKEND_ENGINE_RULE_TABLE, + .table_lookup4 = session_rules_table_lookup4_, + .table_lookup6 = session_rules_table_lookup6_, + .table_cli_dump = session_rules_table_cli_dump_, + .table_show_rule = session_rules_table_show_rule_, + .table_add_del = session_rules_table_add_del_, + .table_init = session_rules_table_init_, + .table_free = session_rules_table_free_, +}; + +static void +session_rules_table_app_namespace_walk_cb (app_namespace_t *app_ns, void *ctx) +{ + u32 fib_index, table_index; + session_table_t *st; + + log_debug ("disable app_ns %s", app_ns->ns_id); + st = session_table_get (app_ns->local_table_index); + if (st) + session_rules_table_free (st, FIB_PROTOCOL_MAX); + + fib_index = app_namespace_get_fib_index (app_ns, FIB_PROTOCOL_IP4); + table_index = session_lookup_get_index_for_fib (FIB_PROTOCOL_IP4, fib_index); + st = session_table_get (table_index); + if (st) + session_rules_table_free (st, FIB_PROTOCOL_IP4); + + fib_index = app_namespace_get_fib_index (app_ns, FIB_PROTOCOL_IP6); + table_index = session_lookup_get_index_for_fib (FIB_PROTOCOL_IP6, fib_index); + st = session_table_get (table_index); + if (st) + session_rules_table_free (st, FIB_PROTOCOL_IP6); +} + +clib_error_t * +session_rules_table_enable_disable (int enable) +{ + clib_error_t *error; + + if (enable) + error = session_rule_table_register_engine (&session_rules_table_vft); + else + { + app_namespace_walk (session_rules_table_app_namespace_walk_cb, 0); + error = session_rule_table_deregister_engine (&session_rules_table_vft); + } + + return error; +} + +clib_error_t * +session_rt_backend_enable_disable (session_rt_engine_type_t rt_engine_type) +{ + session_main_t *smm = &session_main; + clib_error_t *error = 0; + + if (rt_engine_type < RT_BACKEND_ENGINE_DISABLE || + rt_engine_type > RT_BACKEND_ENGINE_SDL) + return clib_error_return (0, "invalid rt-backend %d", rt_engine_type); + + if (rt_engine_type == RT_BACKEND_ENGINE_SDL) + error = session_sdl_enable_disable (1); + else if (rt_engine_type == RT_BACKEND_ENGINE_RULE_TABLE) + error = session_rules_table_enable_disable (1); + else if (rt_engine_type == RT_BACKEND_ENGINE_DISABLE) + { + if (session_sdl_is_enabled ()) + error = session_sdl_enable_disable (0); + else if (session_rule_table_is_enabled ()) + error = session_rules_table_enable_disable (0); + } + + if (!error) + smm->rt_engine_type = rt_engine_type; + return error; +} + +clib_error_t * +session_rule_table_register_engine (const session_rt_engine_vft_t *vft) +{ + if (session_rt_engine_vft == vft) + return 0; + if (session_rt_engine_vft) + return clib_error_return (0, "session rule engine is already registered"); + + session_rt_engine_vft = vft; + return 0; +} + +clib_error_t * +session_rule_table_deregister_engine (const session_rt_engine_vft_t *vft) +{ + if (session_rt_engine_vft == vft) + session_rt_engine_vft = 0; + else + return clib_error_return ( + 0, "session rule engine is not registered to this engine"); + + return 0; +} + /* * fd.io coding-style-patch-verification: ON * diff --git a/src/vnet/session/session_rules_table.h b/src/vnet/session/session_rules_table.h index 010d50a6398..a61438bb9fd 100644 --- a/src/vnet/session/session_rules_table.h +++ b/src/vnet/session/session_rules_table.h @@ -22,6 +22,10 @@ #include <vnet/session/transport.h> #include <vnet/session/mma_16.h> #include <vnet/session/mma_40.h> +#include <vnet/session/session_lookup.h> +#include <vnet/session/session_table.h> + +#define SESSION_SRTG_HANDLE_INVALID ~0 typedef CLIB_PACKED (struct { @@ -58,29 +62,36 @@ typedef CLIB_PACKED (struct #define SESSION_RULES_TABLE_ACTION_DROP (MMA_TABLE_INVALID_INDEX - 1) #define SESSION_RULES_TABLE_ACTION_ALLOW (MMA_TABLE_INVALID_INDEX - 2) -typedef struct _session_rules_table_add_del_args -{ - fib_prefix_t lcl; - fib_prefix_t rmt; - u16 lcl_port; - u16 rmt_port; - u32 action_index; - u8 *tag; - u8 is_add; -} session_rule_table_add_del_args_t; - typedef struct _rule_tag { u8 *tag; } session_rule_tag_t; +typedef struct session_sdl_block +{ + u32 ip_table_id; + u32 ip6_table_id; + u32 ip_fib_index; + u32 ip6_fib_index; +} session_sdl_block_t; + typedef struct _session_rules_table_t { - /** - * Per fib proto session rules tables - */ - mma_rules_table_16_t session_rules_tables_16; - mma_rules_table_40_t session_rules_tables_40; + union + { + /** + * Per fib proto session rules tables + */ + struct + { + mma_rules_table_16_t session_rules_tables_16; + mma_rules_table_40_t session_rules_tables_40; + }; + /** + * sdl table + */ + struct session_sdl_block sdl_block; + }; /** * Hash table that maps tags to rules */ @@ -95,28 +106,163 @@ typedef struct _session_rules_table_t uword *tags_by_rules; } session_rules_table_t; -u32 session_rules_table_lookup4 (session_rules_table_t * srt, - ip4_address_t * lcl_ip, - ip4_address_t * rmt_ip, u16 lcl_port, - u16 rmt_port); -u32 session_rules_table_lookup6 (session_rules_table_t * srt, - ip6_address_t * lcl_ip, - ip6_address_t * rmt_ip, u16 lcl_port, - u16 rmt_port); -void session_rules_table_cli_dump (vlib_main_t * vm, - session_rules_table_t * srt, u8 fib_proto); -void session_rules_table_show_rule (vlib_main_t * vm, - session_rules_table_t * srt, - ip46_address_t * lcl_ip, u16 lcl_port, - ip46_address_t * rmt_ip, u16 rmt_port, - u8 is_ip4); +typedef struct _session_rules_table_group_t +{ + session_rules_table_t *session_rules; +} session_rules_table_group_t; + session_error_t -session_rules_table_add_del (session_rules_table_t *srt, - session_rule_table_add_del_args_t *args); +session_rules_table_add_del_ (u32 srtg_handle, u32 proto, + session_rule_table_add_del_args_t *args); u8 *session_rules_table_rule_tag (session_rules_table_t * srt, u32 ri, u8 is_ip4); -void session_rules_table_init (session_rules_table_t * srt); -void session_rules_table_free (session_rules_table_t *srt); +void session_rules_table_init_ (struct _session_lookup_table *st, + u8 fib_proto); +void session_rules_table_free_ (struct _session_lookup_table *st, + u8 fib_proto); + +typedef u32 (*rules_table_lookup4) (u32 srtg_handle, u32 proto, + ip4_address_t *lcl_ip, + ip4_address_t *rmt_ip, u16 lcl_port, + u16 rmt_port); +typedef u32 (*rules_table_lookup6) (u32 srtg_handle, u32 proto, + ip6_address_t *lcl_ip, + ip6_address_t *rmt_ip, u16 lcl_port, + u16 rmt_port); +typedef void (*rules_table_cli_dump) (vlib_main_t *vm, u32 srtg_handle, + u32 proto, u8 fib_proto); +typedef void (*rules_table_show_rule) (vlib_main_t *vm, u32 srtg_handle, + u32 proto, ip46_address_t *lcl_ip, + u16 lcl_port, ip46_address_t *rmt_ip, + u16 rmt_port, u8 is_ip4); +typedef session_error_t (*rules_table_add_del) ( + u32 srtg_handle, u32 proto, session_rule_table_add_del_args_t *args); +typedef void (*rules_table_init) (struct _session_lookup_table *st, + u8 fib_proto); +typedef void (*rules_table_free) (struct _session_lookup_table *st, + u8 fib_proto); + +#define foreach_session_rt_engine_vft_method_name \ + _ (lookup4) \ + _ (lookup6) \ + _ (cli_dump) \ + _ (show_rule) \ + _ (add_del) \ + _ (init) \ + _ (free) + +#define _(name) rules_table_##name table_##name; +typedef struct session_rt_engine_vft +{ + u32 backend_engine; + foreach_session_rt_engine_vft_method_name +} session_rt_engine_vft_t; +#undef _ + +extern u8 *format_session_rule_tag (u8 *s, va_list *args); +extern u8 *session_rules_table_rule_tag (session_rules_table_t *srt, u32 ri, + u8 is_ip4); +extern u32 session_rules_table_rule_for_tag (session_rules_table_t *srt, + u8 *tag); +extern void session_rules_table_add_tag (session_rules_table_t *srt, u8 *tag, + u32 rule_index, u8 is_ip4); +extern void session_rules_table_del_tag (session_rules_table_t *srt, u8 *tag, + u8 is_ip4); + +extern const session_rt_engine_vft_t *session_rt_engine_vft; +extern clib_error_t *session_rules_table_enable_disable (int enable); +extern clib_error_t * +session_rt_backend_enable_disable (session_rt_engine_type_t rt_engine_type); + +static_always_inline void +session_rules_table_init (struct _session_lookup_table *st, u8 fib_proto) +{ + if (!session_rt_engine_vft) + return; + if (st->srtg_handle != SESSION_SRTG_HANDLE_INVALID) + return; + session_rt_engine_vft->table_init (st, fib_proto); +} + +static_always_inline void +session_rules_table_free (struct _session_lookup_table *st, u8 fib_proto) +{ + if (!session_rt_engine_vft) + return; + if (st->srtg_handle == SESSION_SRTG_HANDLE_INVALID) + return; + session_rt_engine_vft->table_free (st, fib_proto); +} + +static_always_inline void +session_rules_table_show_rule (vlib_main_t *vm, u32 srtg_handle, u32 proto, + ip46_address_t *lcl_ip, u16 lcl_port, + ip46_address_t *rmt_ip, u16 rmt_port, u8 is_ip4) +{ + if (!session_rt_engine_vft) + return; + if (srtg_handle == SESSION_SRTG_HANDLE_INVALID) + return; + session_rt_engine_vft->table_show_rule (vm, srtg_handle, proto, lcl_ip, + lcl_port, rmt_ip, rmt_port, is_ip4); +} + +static_always_inline u32 +session_rules_table_lookup6 (u32 srtg_handle, u32 proto, ip6_address_t *lcl_ip, + ip6_address_t *rmt_ip, u16 lcl_port, u16 rmt_port) +{ + if (!session_rt_engine_vft) + return SESSION_RULES_TABLE_ACTION_ALLOW; + if (srtg_handle == SESSION_SRTG_HANDLE_INVALID) + return SESSION_RULES_TABLE_ACTION_ALLOW; + return session_rt_engine_vft->table_lookup6 (srtg_handle, proto, lcl_ip, + rmt_ip, lcl_port, rmt_port); +} + +static_always_inline void +session_rules_table_cli_dump (vlib_main_t *vm, u32 srtg_handle, u32 proto, + u8 fib_proto) +{ + if (!session_rt_engine_vft) + return; + if (srtg_handle == SESSION_SRTG_HANDLE_INVALID) + return; + session_rt_engine_vft->table_cli_dump (vm, srtg_handle, proto, fib_proto); +} + +static_always_inline u32 +session_rules_table_lookup4 (u32 srtg_handle, u32 proto, ip4_address_t *lcl_ip, + ip4_address_t *rmt_ip, u16 lcl_port, u16 rmt_port) +{ + if (!session_rt_engine_vft) + return SESSION_RULES_TABLE_ACTION_ALLOW; + if (srtg_handle == SESSION_SRTG_HANDLE_INVALID) + return SESSION_RULES_TABLE_ACTION_ALLOW; + return session_rt_engine_vft->table_lookup4 (srtg_handle, proto, lcl_ip, + rmt_ip, lcl_port, rmt_port); +} + +static_always_inline session_error_t +session_rules_table_add_del (u32 srtg_handle, u32 proto, + session_rule_table_add_del_args_t *args) +{ + if (!session_rt_engine_vft) + return SESSION_E_NOSUPPORT; + if (srtg_handle == SESSION_SRTG_HANDLE_INVALID) + return SESSION_E_NOSUPPORT; + return session_rt_engine_vft->table_add_del (srtg_handle, proto, args); +} + +clib_error_t * +session_rule_table_register_engine (const session_rt_engine_vft_t *vft); +clib_error_t * +session_rule_table_deregister_engine (const session_rt_engine_vft_t *vft); + +extern session_rules_table_t *srtg_handle_to_srt (u32 srtg_handle, u32 proto); +extern session_rules_table_group_t *srtg_instance_alloc (session_table_t *st, + u32 n_proto); +extern void srtg_instance_free (session_table_t *st); + #endif /* SRC_VNET_SESSION_SESSION_RULES_TABLE_H_ */ /* * fd.io coding-style-patch-verification: ON diff --git a/src/vnet/session/session_sdl.c b/src/vnet/session/session_sdl.c new file mode 100644 index 00000000000..45ab705fb62 --- /dev/null +++ b/src/vnet/session/session_sdl.c @@ -0,0 +1,768 @@ +/* + * Copyright (c) 2024 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <vnet/session/session.h> +#include <vnet/ip/ip4_forward.h> +#include <vnet/ip/ip6_forward.h> +#include <vnet/session/session_rules_table.h> +#include <vnet/session/session_sdl.h> + +VLIB_REGISTER_LOG_CLASS (session_sdl_log, static) = { .class_name = "session", + .subclass_name = "sdl" }; + +#define log_debug(fmt, ...) \ + vlib_log_debug (session_sdl_log.class, "%s: " fmt, __func__, __VA_ARGS__) +#define log_warn(fmt, ...) \ + vlib_log_warn (session_sdl_log.class, fmt, __VA_ARGS__) +#define log_err(fmt, ...) \ + vlib_log_err (session_sdl_log.class, fmt, __VA_ARGS__) + +static fib_source_t sdl_fib_src; +static dpo_type_t sdl_dpo_type; + +const static char *const *const session_sdl_dpo_nodes[DPO_PROTO_NUM] = { + [DPO_PROTO_IP4] = (const char *const[]){ "ip4-drop", 0 }, + [DPO_PROTO_IP6] = (const char *const[]){ "ip6-drop", 0 }, +}; + +static fib_route_path_t * +session_sdl_fib_create_route_paths (u32 fib_index, dpo_proto_t dpo_proto) +{ + fib_route_path_t *paths = 0; + fib_route_path_t path = { + .frp_proto = dpo_proto, + .frp_flags = FIB_ROUTE_PATH_EXCLUSIVE, + .frp_fib_index = fib_index, + .frp_sw_if_index = ~0, + .frp_weight = 1, + }; + vec_add1 (paths, path); + return paths; +} + +static void +session_sdl_dpo_lock (dpo_id_t *dpo) +{ +} + +static void +session_sdl_dpo_unlock (dpo_id_t *dpo) +{ +} + +static u8 * +format_session_sdl_dpo (u8 *s, va_list *va) +{ + index_t index = va_arg (*va, index_t); + + return format (s, "sdl: [index: %u, deny]", index); +} + +static const dpo_vft_t session_sdl_dpo_vft = { + .dv_lock = session_sdl_dpo_lock, + .dv_unlock = session_sdl_dpo_unlock, + .dv_format = format_session_sdl_dpo, +}; + +static u32 +session_sdl_lookup6 (u32 srtg_handle, u32 proto, ip6_address_t *lcl_ip, + ip6_address_t *rmt_ip, u16 lcl_port, u16 rmt_port) +{ + session_rules_table_t *srt = srtg_handle_to_srt (srtg_handle, 0); + session_sdl_block_t *sdlb = &srt->sdl_block; + index_t lbi; + const dpo_id_t *dpo; + + if (sdlb->ip6_fib_index == ~0) + return SESSION_TABLE_INVALID_INDEX; + lbi = ip6_fib_table_fwding_lookup (sdlb->ip6_fib_index, lcl_ip); + dpo = load_balance_get_fwd_bucket (load_balance_get (lbi), 0); + if (dpo->dpoi_type != sdl_dpo_type) + return SESSION_TABLE_INVALID_INDEX; + return (dpo->dpoi_index); +} + +static u32 +session_sdl_lookup4 (u32 srtg_handle, u32 proto, ip4_address_t *lcl_ip, + ip4_address_t *rmt_ip, u16 lcl_port, u16 rmt_port) +{ + session_rules_table_t *srt = srtg_handle_to_srt (srtg_handle, 0); + session_sdl_block_t *sdlb = &srt->sdl_block; + index_t lbi; + const dpo_id_t *dpo; + + if (sdlb->ip_fib_index == ~0) + return SESSION_TABLE_INVALID_INDEX; + lbi = ip4_fib_forwarding_lookup (sdlb->ip_fib_index, lcl_ip); + dpo = load_balance_get_fwd_bucket (load_balance_get (lbi), 0); + if (dpo->dpoi_type != sdl_dpo_type) + return SESSION_TABLE_INVALID_INDEX; + return (dpo->dpoi_index); +} + +typedef struct session_sdl4_fib_show_walk_ctx_t_ +{ + fib_node_index_t *ifsw_indicies; +} session_sdl4_fib_show_walk_ctx_t; + +static fib_table_walk_rc_t +session_sdl4_fib_show_walk_cb (fib_node_index_t fei, void *arg) +{ + session_sdl4_fib_show_walk_ctx_t *ctx = arg; + + vec_add1 (ctx->ifsw_indicies, fei); + + return (FIB_TABLE_WALK_CONTINUE); +} + +typedef struct session_sdl6_fib_show_ctx_t_ +{ + fib_node_index_t *entries; +} session_sdl6_fib_show_ctx_t; + +static fib_table_walk_rc_t +session_sdl6_fib_table_show_walk (fib_node_index_t fei, void *arg) +{ + session_sdl6_fib_show_ctx_t *ctx = arg; + + vec_add1 (ctx->entries, fei); + + return (FIB_TABLE_WALK_CONTINUE); +} + +static void +session_sdl_fib_table_show (u32 fei, ip46_address_t *lcl_ip, u16 fp_len, + u32 action_index, u32 fp_proto, u8 *tag, + void *args) +{ + vlib_main_t *vm = args; + u32 type = (fp_proto == FIB_PROTOCOL_IP4) ? IP46_TYPE_IP4 : IP46_TYPE_IP6; + + vlib_cli_output (vm, "[%d] rule: %U/%d action: %d tag %U", fei, + format_ip46_address, lcl_ip, type, fp_len, action_index, + format_session_rule_tag, tag); +} + +static void +session_sdl_cli_dump (vlib_main_t *vm, u32 srtg_handle, u32 proto, + u8 fib_proto) +{ + session_rules_table_t *srt = srtg_handle_to_srt (srtg_handle, 0); + session_sdl_block_t *sdlb = &srt->sdl_block; + + if (fib_proto == FIB_PROTOCOL_IP4) + { + vlib_cli_output (vm, "IP4 rules, fib index %d", sdlb->ip_fib_index); + session_sdl_table_walk4 (srtg_handle, session_sdl_fib_table_show, vm); + } + else if (fib_proto == FIB_PROTOCOL_IP6) + { + vlib_cli_output (vm, "IP6 rules, fib index %d", sdlb->ip6_fib_index); + session_sdl_table_walk6 (srtg_handle, session_sdl_fib_table_show, vm); + } +} + +static void +session_sdl4_fib_table_show_one (session_rules_table_t *srt, u32 fib_index, + vlib_main_t *vm, ip4_address_t *address, + u32 mask_len) +{ + ip4_fib_t *fib; + fib_node_index_t fei; + + fib = ip4_fib_get (fib_index); + fei = ip4_fib_table_lookup (fib, address, mask_len); + if (fei != FIB_NODE_INDEX_INVALID && fib_entry_is_sourced (fei, sdl_fib_src)) + { + u8 *tag = session_rules_table_rule_tag (srt, fei, 1); + fib_entry_t *fib_entry = fib_entry_get (fei); + fib_prefix_t pfx = fib_entry->fe_prefix; + index_t lbi = ip4_fib_forwarding_lookup (fib_index, &pfx.fp_addr.ip4); + const dpo_id_t *dpo = + load_balance_get_fwd_bucket (load_balance_get (lbi), 0); + + session_sdl_fib_table_show (fei, &pfx.fp_addr, pfx.fp_len, + dpo->dpoi_index, FIB_PROTOCOL_IP4, tag, vm); + } +} + +static void +session_sdl6_fib_table_show_one (session_rules_table_t *srt, u32 fib_index, + vlib_main_t *vm, ip6_address_t *address, + u32 mask_len) +{ + fib_node_index_t fei; + + fei = ip6_fib_table_lookup (fib_index, address, mask_len); + if (fei != FIB_NODE_INDEX_INVALID && fib_entry_is_sourced (fei, sdl_fib_src)) + { + u8 *tag = session_rules_table_rule_tag (srt, fei, 0); + fib_entry_t *fib_entry = fib_entry_get (fei); + fib_prefix_t pfx = fib_entry->fe_prefix; + index_t lbi = ip6_fib_table_fwding_lookup (fib_index, &pfx.fp_addr.ip6); + const dpo_id_t *dpo = + load_balance_get_fwd_bucket (load_balance_get (lbi), 0); + + session_sdl_fib_table_show (fei, &pfx.fp_addr, pfx.fp_len, + dpo->dpoi_index, FIB_PROTOCOL_IP6, tag, vm); + } +} + +static void +session_sdl_show_rule (vlib_main_t *vm, u32 srtg_handle, u32 proto, + ip46_address_t *lcl_ip, u16 lcl_port, + ip46_address_t *rmt_ip, u16 rmt_port, u8 is_ip4) +{ + session_rules_table_t *srt = srtg_handle_to_srt (srtg_handle, 0); + session_sdl_block_t *sdlb; + + sdlb = &srt->sdl_block; + if (is_ip4) + session_sdl4_fib_table_show_one (srt, sdlb->ip_fib_index, vm, &lcl_ip->ip4, + 32); + else + session_sdl6_fib_table_show_one (srt, sdlb->ip6_fib_index, vm, + &lcl_ip->ip6, 128); +} + +static void +session_sdl_table_init (session_table_t *st, u8 fib_proto) +{ + session_rules_table_t *srt; + session_sdl_block_t *sdlb; + u8 all = fib_proto > FIB_PROTOCOL_IP6 ? 1 : 0; + char name[80]; + app_namespace_t *app_ns = app_namespace_get (st->appns_index); + session_rules_table_group_t *srtg; + + /* Don't support local table */ + if (st->is_local == 1) + return; + + srtg = srtg_instance_alloc (st, 0); + srt = srtg->session_rules; + sdlb = &srt->sdl_block; + + if (fib_proto == FIB_PROTOCOL_IP4 || all) + { + snprintf (name, sizeof (name), "sdl4 %s", app_ns->ns_id); + sdlb->ip_table_id = ip_table_get_unused_id (FIB_PROTOCOL_IP4); + sdlb->ip_fib_index = fib_table_find_or_create_and_lock_w_name ( + FIB_PROTOCOL_IP4, sdlb->ip_table_id, sdl_fib_src, (const u8 *) name); + } + + if (fib_proto == FIB_PROTOCOL_IP6 || all) + { + snprintf (name, sizeof (name), "sdl6 %s", app_ns->ns_id); + sdlb->ip6_table_id = ip_table_get_unused_id (FIB_PROTOCOL_IP6); + sdlb->ip6_fib_index = fib_table_find_or_create_and_lock_w_name ( + FIB_PROTOCOL_IP6, sdlb->ip6_table_id, sdl_fib_src, (const u8 *) name); + } + + srt->rules_by_tag = hash_create_vec (0, sizeof (u8), sizeof (uword)); + srt->tags_by_rules = hash_create (0, sizeof (uword)); +} + +static void +session_sdl_table_free (session_table_t *st, u8 fib_proto) +{ + session_rules_table_t *srt = srtg_handle_to_srt (st->srtg_handle, 0); + session_sdl_block_t *sdlb; + u8 all = fib_proto > FIB_PROTOCOL_IP6 ? 1 : 0; + + ASSERT (st->is_local == 0); + sdlb = &srt->sdl_block; + if ((fib_proto == FIB_PROTOCOL_IP4 || all) && (sdlb->ip_fib_index != ~0)) + { + fib_table_flush (sdlb->ip_fib_index, FIB_PROTOCOL_IP4, sdl_fib_src); + fib_table_unlock (sdlb->ip_fib_index, FIB_PROTOCOL_IP4, sdl_fib_src); + } + if ((fib_proto == FIB_PROTOCOL_IP6 || all) && (sdlb->ip6_fib_index != ~0)) + { + fib_table_flush (sdlb->ip6_fib_index, FIB_PROTOCOL_IP6, sdl_fib_src); + fib_table_unlock (sdlb->ip6_fib_index, FIB_PROTOCOL_IP6, sdl_fib_src); + } + + hash_free (srt->tags_by_rules); + hash_free (srt->rules_by_tag); + + srtg_instance_free (st); +} + +static session_error_t +session_sdl_add_del (u32 srtg_handle, u32 proto, + session_rule_table_add_del_args_t *args) +{ + session_rules_table_t *srt = srtg_handle_to_srt (srtg_handle, 0); + session_sdl_block_t *sdlb = &srt->sdl_block; + u32 fib_index; + dpo_proto_t dpo_proto; + fib_route_path_t *paths = 0; + fib_prefix_t pfx = args->lcl; + session_error_t err = SESSION_E_NONE; + fib_node_index_t fei; + int is_ip4; + + if (!(args->lcl_port == 0 && args->rmt_port == 0 && + args->rmt.fp_addr.ip4.as_u32 == 0)) + return SESSION_E_NOSUPPORT; + + fei = session_rules_table_rule_for_tag (srt, args->tag); + if (args->is_add && fei != SESSION_RULES_TABLE_INVALID_INDEX) + return SESSION_E_INVALID; + + if (args->lcl.fp_proto == FIB_PROTOCOL_IP4) + { + fib_index = sdlb->ip_fib_index; + dpo_proto = DPO_PROTO_IP4; + is_ip4 = 1; + } + else + { + fib_index = sdlb->ip6_fib_index; + dpo_proto = DPO_PROTO_IP6; + is_ip4 = 0; + } + + paths = session_sdl_fib_create_route_paths (fib_index, dpo_proto); + if (args->is_add) + { + fei = fib_table_lookup_exact_match (fib_index, &pfx); + if (fei != FIB_NODE_INDEX_INVALID) + { + err = SESSION_E_IPINUSE; + goto done; + } + dpo_set (&paths->dpo, sdl_dpo_type, dpo_proto, args->action_index); + fei = fib_table_entry_path_add2 (fib_index, &pfx, sdl_fib_src, + FIB_ENTRY_FLAG_EXCLUSIVE, paths); + session_rules_table_add_tag (srt, args->tag, fei, is_ip4); + dpo_reset (&paths->dpo); + } + else + { + if (fei == SESSION_RULES_TABLE_INVALID_INDEX) + { + fei = fib_table_lookup_exact_match (fib_index, &pfx); + + if (fei == FIB_NODE_INDEX_INVALID) + { + err = SESSION_E_NOROUTE; + goto done; + } + } + + if (!fib_entry_is_sourced (fei, sdl_fib_src)) + { + err = SESSION_E_NOROUTE; + goto done; + } + + fib_entry_t *fib_entry = fib_entry_get (fei); + pfx = fib_entry->fe_prefix; + fib_table_entry_special_remove (fib_index, &pfx, sdl_fib_src); + session_rules_table_del_tag (srt, args->tag, is_ip4); + } +done: + vec_free (paths); + + return err; +} + +static const session_rt_engine_vft_t session_sdl_vft = { + .backend_engine = RT_BACKEND_ENGINE_SDL, + .table_lookup4 = session_sdl_lookup4, + .table_lookup6 = session_sdl_lookup6, + .table_cli_dump = session_sdl_cli_dump, + .table_show_rule = session_sdl_show_rule, + .table_add_del = session_sdl_add_del, + .table_init = session_sdl_table_init, + .table_free = session_sdl_table_free, +}; + +static void +session_sdl_fib_init (void) +{ + static u32 session_fib_inited = 0; + + if (session_fib_inited) + return; + session_fib_inited = 1; + sdl_fib_src = fib_source_allocate ("session sdl", FIB_SOURCE_PRIORITY_LOW, + FIB_SOURCE_BH_SIMPLE); + sdl_dpo_type = + dpo_register_new_type (&session_sdl_dpo_vft, session_sdl_dpo_nodes); +} + +static void +session_sdl_app_namespace_walk_cb (app_namespace_t *app_ns, void *ctx) +{ + u32 fib_index, table_index; + session_table_t *st; + + log_debug ("disable app_ns %s", app_ns->ns_id); + + fib_index = app_namespace_get_fib_index (app_ns, FIB_PROTOCOL_IP4); + table_index = session_lookup_get_index_for_fib (FIB_PROTOCOL_IP4, fib_index); + st = session_table_get (table_index); + if (st) + session_rules_table_free (st, FIB_PROTOCOL_IP4); + + fib_index = app_namespace_get_fib_index (app_ns, FIB_PROTOCOL_IP6); + table_index = session_lookup_get_index_for_fib (FIB_PROTOCOL_IP6, fib_index); + st = session_table_get (table_index); + if (st) + session_rules_table_free (st, FIB_PROTOCOL_IP6); +} + +clib_error_t * +session_sdl_enable_disable (int enable) +{ + clib_error_t *error = 0; + + if (enable) + { + error = session_rule_table_register_engine (&session_sdl_vft); + if (error) + { + log_err ("error in enabling sdl: %U", format_clib_error, error); + return error; + } + session_sdl_fib_init (); + } + else + { + app_namespace_walk (session_sdl_app_namespace_walk_cb, 0); + + error = session_rule_table_deregister_engine (&session_sdl_vft); + if (error) + log_err ("error in disabling sdl: %U", format_clib_error, error); + } + + return error; +} + +/* + * Source Deny List + */ +static clib_error_t * +session_sdl_command_fn (vlib_main_t *vm, unformat_input_t *input, + vlib_cli_command_t *cmd) +{ + u32 appns_index; + app_namespace_t *app_ns; + u32 lcl_plen = 0, action = 0; + clib_error_t *error = 0; + ip46_address_t lcl_ip; + u8 conn_set = 0; + u8 fib_proto = -1, is_add = 1, *ns_id = 0; + u8 *tag = 0, tag_only = 0; + int rv; + session_rule_add_del_args_t args; + + session_cli_return_if_not_enabled (); + + if (session_sdl_is_enabled () == 0) + return clib_error_return (0, "session sdl engine is not enabled"); + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "del")) + is_add = 0; + else if (unformat (input, "add")) + ; + else if (unformat (input, "appns %_%v%_", &ns_id)) + ; + else if (unformat (input, "%U/%d", unformat_ip4_address, &lcl_ip.ip4, + &lcl_plen)) + { + fib_proto = FIB_PROTOCOL_IP4; + conn_set = 1; + } + else if (unformat (input, "%U/%d", unformat_ip6_address, &lcl_ip.ip6, + &lcl_plen)) + { + fib_proto = FIB_PROTOCOL_IP6; + conn_set = 1; + } + else if (unformat (input, "action %d", &action)) + ; + else if (unformat (input, "tag %_%v%_", &tag)) + ; + else + { + error = clib_error_return (0, "unknown input `%U'", + format_unformat_error, input); + goto done; + } + } + + if (ns_id) + { + app_ns = app_namespace_get_from_id (ns_id); + if (!app_ns) + { + vlib_cli_output (vm, "namespace %v does not exist", ns_id); + goto done; + } + } + else + { + app_ns = app_namespace_get_default (); + } + appns_index = app_namespace_index (app_ns); + + if (is_add && !conn_set && action == 0) + { + vlib_cli_output (vm, "connection and action must be set for add"); + goto done; + } + if (!is_add && !tag && !conn_set) + { + vlib_cli_output (vm, "connection or tag must be set for delete"); + goto done; + } + if (vec_len (tag) > SESSION_RULE_TAG_MAX_LEN) + { + vlib_cli_output (vm, "tag too long (max u64)"); + goto done; + } + + /* Delete with only tag entered. Try v4 first and then v6 if failed */ + if ((is_add == 0) && (fib_proto == (u8) ~0)) + { + fib_proto = FIB_PROTOCOL_IP4; + tag_only = 1; + } + + memset (&args, 0, sizeof (args)); + args.transport_proto = TRANSPORT_PROTO_TCP; + args.table_args.lcl.fp_addr = lcl_ip; + args.table_args.lcl.fp_len = lcl_plen; + args.table_args.lcl.fp_proto = fib_proto; + args.table_args.rmt.fp_proto = fib_proto; + args.table_args.action_index = action; + args.table_args.is_add = is_add; + args.table_args.tag = tag; + args.appns_index = appns_index; + args.scope = SESSION_RULE_SCOPE_GLOBAL; + + if ((rv = vnet_session_rule_add_del (&args))) + { + /* Try tag only delete on v6 */ + if (rv && tag_only) + { + args.table_args.rmt.fp_proto = FIB_PROTOCOL_IP6; + args.table_args.lcl.fp_proto = FIB_PROTOCOL_IP6; + if ((rv = vnet_session_rule_add_del (&args))) + { + error = clib_error_return (0, "sdl add del returned %u", rv); + } + } + else + { + error = clib_error_return (0, "sdl add del returned %u", rv); + } + } + +done: + vec_free (ns_id); + vec_free (tag); + return error; +} + +VLIB_CLI_COMMAND (session_sdl_command, static) = { + .path = "session sdl", + .short_help = "session sdl [add|del] [appns <ns_id>] <lcl-ip/plen> action " + "<action> [tag <tag>]", + .function = session_sdl_command_fn, + .is_mp_safe = 1, +}; + +static clib_error_t * +show_session_sdl_command_fn (vlib_main_t *vm, unformat_input_t *input, + vlib_cli_command_t *cmd) +{ + u32 fib_index; + ip46_address_t lcl_ip; + u8 show_one = 0; + app_namespace_t *app_ns; + session_table_t *st; + u8 *ns_id = 0, fib_proto = FIB_PROTOCOL_IP4; + + session_cli_return_if_not_enabled (); + + clib_memset (&lcl_ip, 0, sizeof (lcl_ip)); + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "appns %_%s%_", &ns_id)) + ; + else if (unformat (input, "%U", unformat_ip4_address, &lcl_ip.ip4)) + { + fib_proto = FIB_PROTOCOL_IP4; + show_one = 1; + } + else if (unformat (input, "%U", unformat_ip6_address, &lcl_ip.ip6)) + { + fib_proto = FIB_PROTOCOL_IP6; + show_one = 1; + } + else + { + vec_free (ns_id); + return clib_error_return (0, "unknown input `%U'", + format_unformat_error, input); + } + } + + if (ns_id) + { + app_ns = app_namespace_get_from_id (ns_id); + if (!app_ns) + { + vlib_cli_output (vm, "appns %v doesn't exist", ns_id); + goto done; + } + } + else + { + app_ns = app_namespace_get_default (); + } + + if (session_sdl_is_enabled () == 0) + { + vlib_cli_output (vm, "session sdl engine is not enabled"); + goto done; + } + + if (show_one) + { + fib_index = app_namespace_get_fib_index (app_ns, fib_proto); + st = session_table_get_for_fib_index (fib_proto, fib_index); + if (st && (st->srtg_handle != SESSION_SRTG_HANDLE_INVALID)) + session_rules_table_show_rule (vm, st->srtg_handle, 0, &lcl_ip, 0, 0, + 0, (fib_proto == FIB_PROTOCOL_IP4)); + goto done; + } + + /* 2 separate session tables for global entries, 1 for ip4 and 1 for ip6 */ + fib_index = app_namespace_get_fib_index (app_ns, FIB_PROTOCOL_IP4); + st = session_table_get_for_fib_index (FIB_PROTOCOL_IP4, fib_index); + if (st && (st->srtg_handle != SESSION_SRTG_HANDLE_INVALID)) + session_rules_table_cli_dump (vm, st->srtg_handle, 0, FIB_PROTOCOL_IP4); + + fib_index = app_namespace_get_fib_index (app_ns, FIB_PROTOCOL_IP6); + st = session_table_get_for_fib_index (FIB_PROTOCOL_IP6, fib_index); + if (st && (st->srtg_handle != SESSION_SRTG_HANDLE_INVALID)) + session_rules_table_cli_dump (vm, st->srtg_handle, 0, FIB_PROTOCOL_IP6); +done: + vec_free (ns_id); + return 0; +} + +void +session_sdl_table_walk4 (u32 srtg_handle, session_sdl_table_walk_fn_t fn, + void *args) +{ + ip4_fib_t *fib; + session_sdl4_fib_show_walk_ctx_t ctx = { + .ifsw_indicies = NULL, + }; + fib_node_index_t *fei; + session_rules_table_t *srt = srtg_handle_to_srt (srtg_handle, 0); + session_sdl_block_t *sdlb = &srt->sdl_block; + u32 fib_index = sdlb->ip_fib_index; + + if (fib_index == ~0) + return; + fib = ip4_fib_get (fib_index); + ip4_fib_table_walk (fib, session_sdl4_fib_show_walk_cb, &ctx); + vec_sort_with_function (ctx.ifsw_indicies, fib_entry_cmp_for_sort); + + vec_foreach (fei, ctx.ifsw_indicies) + { + if (*fei != FIB_NODE_INDEX_INVALID && + fib_entry_is_sourced (*fei, sdl_fib_src)) + { + u8 *tag = session_rules_table_rule_tag (srt, *fei, 1); + fib_entry_t *fib_entry = fib_entry_get (*fei); + fib_prefix_t pfx = fib_entry->fe_prefix; + index_t lbi = + ip4_fib_forwarding_lookup (fib_index, &pfx.fp_addr.ip4); + const dpo_id_t *dpo = + load_balance_get_fwd_bucket (load_balance_get (lbi), 0); + + fn (*fei, &pfx.fp_addr, pfx.fp_len, dpo->dpoi_index, + FIB_PROTOCOL_IP4, tag, args); + } + } + + vec_free (ctx.ifsw_indicies); +} + +void +session_sdl_table_walk6 (u32 srtg_handle, session_sdl_table_walk_fn_t fn, + void *args) +{ + ip6_fib_t *fib; + fib_node_index_t *fei; + session_sdl6_fib_show_ctx_t ctx = { + .entries = NULL, + }; + session_rules_table_t *srt = srtg_handle_to_srt (srtg_handle, 0); + session_sdl_block_t *sdlb = &srt->sdl_block; + u32 fib_index = sdlb->ip6_fib_index; + + if (fib_index == ~0) + return; + fib = ip6_fib_get (fib_index); + ip6_fib_table_walk (fib->index, session_sdl6_fib_table_show_walk, &ctx); + vec_sort_with_function (ctx.entries, fib_entry_cmp_for_sort); + + vec_foreach (fei, ctx.entries) + { + if (*fei != FIB_NODE_INDEX_INVALID && + fib_entry_is_sourced (*fei, sdl_fib_src)) + { + u8 *tag = session_rules_table_rule_tag (srt, *fei, 0); + fib_entry_t *fib_entry = fib_entry_get (*fei); + fib_prefix_t pfx = fib_entry->fe_prefix; + index_t lbi = + ip6_fib_table_fwding_lookup (fib_index, &pfx.fp_addr.ip6); + const dpo_id_t *dpo = + load_balance_get_fwd_bucket (load_balance_get (lbi), 0); + + fn (*fei, &pfx.fp_addr, pfx.fp_len, dpo->dpoi_index, + FIB_PROTOCOL_IP6, tag, args); + } + } + + vec_free (ctx.entries); +} + +VLIB_CLI_COMMAND (show_session_sdl_command, static) = { + .path = "show session sdl", + .short_help = "show session sdl [appns <id> <lcl-ip>]", + .function = show_session_sdl_command_fn, + .is_mp_safe = 1, +}; + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/src/vnet/session/session_sdl.h b/src/vnet/session/session_sdl.h new file mode 100644 index 00000000000..8d8b5b2d29e --- /dev/null +++ b/src/vnet/session/session_sdl.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2024 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SRC_VNET_SESSION_SESSION_SDL_H_ +#define SRC_VNET_SESSION_SESSION_SDL_H_ + +clib_error_t *session_sdl_enable_disable (int enable); + +typedef void (*session_sdl_table_walk_fn_t) (u32 fei, ip46_address_t *lcl_ip, + u16 fp_len, u32 action_index, + u32 fb_proto, u8 *tag, void *ctx); +void session_sdl_table_walk4 (u32 srtg_handle, session_sdl_table_walk_fn_t fn, + void *args); +void session_sdl_table_walk6 (u32 srtg_handle, session_sdl_table_walk_fn_t fn, + void *args); + +#endif /* SRC_VNET_SESSION_SESSION_SDL_H_ */ +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/src/vnet/session/session_table.c b/src/vnet/session/session_table.c index dbbe771979c..5dafe0e633c 100644 --- a/src/vnet/session/session_table.c +++ b/src/vnet/session/session_table.c @@ -15,6 +15,7 @@ #include <vnet/session/session_table.h> #include <vnet/session/session.h> +#include <vnet/session/session_rules_table.h> /** * Pool of session tables @@ -64,12 +65,8 @@ void session_table_free (session_table_t *slt, u8 fib_proto) { u8 all = fib_proto > FIB_PROTOCOL_IP6 ? 1 : 0; - int i; - for (i = 0; i < TRANSPORT_N_PROTOS; i++) - session_rules_table_free (&slt->session_rules[i]); - - vec_free (slt->session_rules); + session_rules_table_free (slt, fib_proto); if (fib_proto == FIB_PROTOCOL_IP4 || all) { @@ -92,10 +89,9 @@ session_table_free (session_table_t *slt, u8 fib_proto) * otherwise it uses defaults above. */ void -session_table_init (session_table_t * slt, u8 fib_proto) +session_table_init (session_table_t *slt, u8 fib_proto) { u8 all = fib_proto > FIB_PROTOCOL_IP6 ? 1 : 0; - int i; #define _(af,table,parm,value) \ u32 configured_##af##_##table##_table_##parm = value; @@ -109,6 +105,7 @@ session_table_init (session_table_t * slt, u8 fib_proto) foreach_hash_table_parameter; #undef _ + slt->srtg_handle = SESSION_SRTG_HANDLE_INVALID; if (fib_proto == FIB_PROTOCOL_IP4 || all) { clib_bihash_init2_args_16_8_t _a, *a = &_a; @@ -153,10 +150,6 @@ session_table_init (session_table_t * slt, u8 fib_proto) a->instantiate_immediately = 1; clib_bihash_init2_48_8 (a); } - - vec_validate (slt->session_rules, TRANSPORT_N_PROTOS - 1); - for (i = 0; i < TRANSPORT_N_PROTOS; i++) - session_rules_table_init (&slt->session_rules[i]); } typedef struct _ip4_session_table_walk_ctx_t diff --git a/src/vnet/session/session_table.h b/src/vnet/session/session_table.h index bcbb6ec3037..aae4a1c2af5 100644 --- a/src/vnet/session/session_table.h +++ b/src/vnet/session/session_table.h @@ -18,7 +18,6 @@ #include <vppinfra/bihash_16_8.h> #include <vppinfra/bihash_48_8.h> -#include <vnet/session/session_rules_table.h> typedef struct _session_lookup_table { @@ -37,7 +36,7 @@ typedef struct _session_lookup_table /** * Per fib proto and transport proto session rules tables */ - session_rules_table_t *session_rules; + u32 srtg_handle; /** Flag that indicates if table has local scope */ u8 is_local; diff --git a/src/vnet/session/session_test.c b/src/vnet/session/session_test.c index 770e7263024..1c865b877b5 100644 --- a/src/vnet/session/session_test.c +++ b/src/vnet/session/session_test.c @@ -271,6 +271,12 @@ api_session_enable_disable (vat_main_t *vat) } static int +api_session_enable_disable_v2 (vat_main_t *vat) +{ + return -1; +} + +static int api_app_worker_add_del (vat_main_t *vat) { return -1; @@ -354,6 +360,23 @@ api_session_sapi_enable_disable (vat_main_t *vat) return -1; } +static int +api_session_sdl_add_del (vat_main_t *vam) +{ + return -1; +} + +static void +vl_api_session_sdl_details_t_handler (vl_api_session_rules_details_t *mp) +{ +} + +static int +api_session_sdl_dump (vat_main_t *vam) +{ + return -1; +} + #include <vnet/session/session.api_test.c> /* diff --git a/test/asf/test_session_sdl.py b/test/asf/test_session_sdl.py new file mode 100644 index 00000000000..15d696350bc --- /dev/null +++ b/test/asf/test_session_sdl.py @@ -0,0 +1,297 @@ +#!/usr/bin/env python3 + +import unittest + +from framework import VppTestCase +from asfframework import VppTestRunner, tag_fixme_vpp_workers +from ipaddress import IPv4Network, IPv6Network + +from vpp_ip_route import ( + VppIpRoute, + VppRoutePath, + VppIpTable, +) + +from vpp_papi import VppEnum + + +from vpp_session_sdl import VppSessionSdl +from vpp_session_sdl import SessionSdl + + +@tag_fixme_vpp_workers +class TestSessionSDL(VppTestCase): + """Session SDL Test Case""" + + @classmethod + def setUpClass(cls): + super(TestSessionSDL, cls).setUpClass() + + @classmethod + def tearDownClass(cls): + super(TestSessionSDL, cls).tearDownClass() + + def setUp(self): + super(TestSessionSDL, self).setUp() + self.create_loopback_interfaces(2) + + table_id = 0 + + for i in self.lo_interfaces: + i.admin_up() + + if table_id != 0: + tbl = VppIpTable(self, table_id) + tbl.add_vpp_config() + tbl = VppIpTable(self, table_id, is_ip6=1) + tbl.add_vpp_config() + + i.set_table_ip4(table_id) + i.set_table_ip6(table_id) + i.config_ip4() + i.config_ip6() + table_id += 1 + + def tearDown(self): + for i in self.lo_interfaces: + i.unconfig_ip4() + i.set_table_ip4(0) + i.unconfig_ip6() + i.set_table_ip6(0) + i.admin_down() + self.loop0.remove_vpp_config() + self.loop1.remove_vpp_config() + super(TestSessionSDL, self).tearDown() + + def create_rule(self, lcl, action_index, tag): + return SessionSdl(lcl=lcl, action_index=action_index, tag=tag) + + def apply_rules(self, rules, is_add, appns_index): + r = VppSessionSdl(self, rules, is_add=is_add, appns_index=appns_index) + r.add_vpp_config() + + def test_session_sdl_ip4(self): + """Session SDL IP4 test""" + + self.vapi.session_enable_disable_v2( + rt_engine_type=VppEnum.vl_api_rt_backend_engine_t.RT_BACKEND_ENGINE_API_SDL + ) + + # Configure namespaces + self.vapi.app_namespace_add_del_v4( + namespace_id="0", sw_if_index=self.loop0.sw_if_index + ) + self.vapi.app_namespace_add_del_v4( + namespace_id="1", sw_if_index=self.loop1.sw_if_index + ) + + # Add inter-table routes + uri = "tcp://" + self.loop0.local_ip4 + "/1234" + server_cmd = "test echo server appns 0 fifo-size 4k " + "uri " + uri + client_cmd = ( + "test echo client bytes 100000 appns 1 " + + "fifo-size 4k " + + "syn-timeout 2 uri " + + uri + ) + ip_t01 = VppIpRoute( + self, + self.loop1.local_ip4, + 32, + [VppRoutePath("0.0.0.0", 0xFFFFFFFF, nh_table_id=1)], + ) + ip_t10 = VppIpRoute( + self, + self.loop0.local_ip4, + 32, + [VppRoutePath("0.0.0.0", 0xFFFFFFFF, nh_table_id=0)], + table_id=1, + ) + ip_t01.add_vpp_config() + ip_t10.add_vpp_config() + + # Start builtin server for ip4 + self.logger.info(self.vapi.cli(server_cmd)) + + # Add session filter to block loop0 + rules = [] + rules.append( + self.create_rule(lcl=self.loop0.local_ip4 + "/32", action_index=0, tag="") + ) + self.apply_rules(rules, is_add=1, appns_index=0) + + filter = self.vapi.session_sdl_dump() + self.assertEqual(filter[0].lcl, IPv4Network(self.loop0.local_ip4 + "/32")) + + # irrelevant rules - add 64k entries in one API call + rules = [] + for i in range(255): + for j in range(255): + prefix = "10.1.{0}.{1}/32".format(i, j) + rules.append(self.create_rule(lcl=prefix, action_index=0, tag="")) + self.apply_rules(rules, is_add=1, appns_index=0) + + error = self.vapi.cli_return_response(server_cmd) + # Expecting an error because loop0 is blocked + self.assertEqual(-1, error.retval) + + # Remove the session filter + rules = [] + rules.append( + self.create_rule(lcl=self.loop0.local_ip4 + "/32", action_index=0, tag="") + ) + self.apply_rules(rules, is_add=0, appns_index=0) + + # Not expecting an error + self.logger.info(self.vapi.cli(client_cmd)) + + # Add a session filter not matching loop0 + rules = [] + rules.append(self.create_rule(lcl="172.100.1.0/24", action_index=0, tag="")) + self.apply_rules(rules, is_add=1, appns_index=0) + + # Not expecting an error + self.logger.info(self.vapi.cli(client_cmd)) + + self.logger.info(self.vapi.cli(server_cmd + " stop")) + + self.vapi.app_namespace_add_del_v4( + is_add=0, namespace_id="0", sw_if_index=self.loop0.sw_if_index + ) + self.vapi.app_namespace_add_del_v4( + is_add=0, namespace_id="1", sw_if_index=self.loop1.sw_if_index + ) + # Delete inter-table routes + ip_t01.remove_vpp_config() + ip_t10.remove_vpp_config() + self.vapi.session_enable_disable_v2( + rt_engine_type=VppEnum.vl_api_rt_backend_engine_t.RT_BACKEND_ENGINE_API_DISABLE + ) + + def test_session_sdl_ip6(self): + """Session SDL IP6 test""" + + self.vapi.session_enable_disable_v2( + rt_engine_type=VppEnum.vl_api_rt_backend_engine_t.RT_BACKEND_ENGINE_API_SDL + ) + + # Configure namespaces + self.vapi.app_namespace_add_del_v4( + namespace_id="0", sw_if_index=self.loop0.sw_if_index + ) + self.vapi.app_namespace_add_del_v4( + namespace_id="1", sw_if_index=self.loop1.sw_if_index + ) + + # IP6 Test + # Add inter-table routes + uri = "tcp://" + self.loop0.local_ip6 + "/1235" + client_cmd = ( + "test echo client bytes 100000 appns 1 " + + "fifo-size 4k " + + "syn-timeout 2 uri " + + uri + ) + server_cmd = "test echo server appns 0 fifo-size 4k " + "uri " + uri + + ip_t01 = VppIpRoute( + self, + self.loop1.local_ip6, + 128, + [VppRoutePath("0::0", 0xFFFFFFFF, nh_table_id=1)], + ) + ip_t10 = VppIpRoute( + self, + self.loop0.local_ip6, + 128, + [VppRoutePath("0::0", 0xFFFFFFFF, nh_table_id=0)], + table_id=1, + ) + ip_t01.add_vpp_config() + ip_t10.add_vpp_config() + + # Start builtin server for ip6 + self.logger.info(self.vapi.cli(server_cmd)) + + # case 1: No filter + + # Not expecting an error + self.logger.info(self.vapi.cli(client_cmd)) + + # case 2: filter to block + # Add session filter to block loop0 + rules = [] + rules.append( + self.create_rule(lcl=self.loop0.local_ip6 + "/128", action_index=0, tag="") + ) + self.apply_rules(rules, is_add=1, appns_index=0) + filter = self.vapi.session_sdl_dump() + self.assertEqual(filter[0].lcl, IPv6Network(self.loop0.local_ip6 + "/128")) + + error = self.vapi.cli_return_response(client_cmd) + # Expecting an error because loop0 is blocked + self.assertEqual(-1, error.retval) + + # case 3: remove to block + # Add session filter to block loop0 + rules = [] + rules.append( + self.create_rule(lcl=self.loop0.local_ip6 + "/128", action_index=0, tag="") + ) + self.apply_rules(rules, is_add=0, appns_index=0) + # Not expecting an error + self.logger.info(self.vapi.cli(client_cmd)) + + # stop the server + self.logger.info(self.vapi.cli(server_cmd + " stop")) + + self.vapi.app_namespace_add_del_v4( + is_add=0, namespace_id="0", sw_if_index=self.loop0.sw_if_index + ) + self.vapi.app_namespace_add_del_v4( + is_add=0, namespace_id="1", sw_if_index=self.loop1.sw_if_index + ) + # Delete inter-table routes + ip_t01.remove_vpp_config() + ip_t10.remove_vpp_config() + self.vapi.session_enable_disable_v2( + rt_engine_type=VppEnum.vl_api_rt_backend_engine_t.RT_BACKEND_ENGINE_API_DISABLE + ) + + def test_session_enable_disable(self): + """Session SDL enable/disable test""" + + for i in range(10): + # Enable sdl + self.vapi.session_enable_disable_v2( + rt_engine_type=VppEnum.vl_api_rt_backend_engine_t.RT_BACKEND_ENGINE_API_SDL + ) + + # Disable + self.vapi.session_enable_disable_v2( + rt_engine_type=VppEnum.vl_api_rt_backend_engine_t.RT_BACKEND_ENGINE_API_DISABLE + ) + + # Enable rule-table + self.vapi.session_enable_disable_v2( + rt_engine_type=VppEnum.vl_api_rt_backend_engine_t.RT_BACKEND_ENGINE_API_RULE_TABLE + ) + + # Disable + self.vapi.session_enable_disable_v2( + rt_engine_type=VppEnum.vl_api_rt_backend_engine_t.RT_BACKEND_ENGINE_API_DISABLE + ) + + # Enable sdl + self.vapi.session_enable_disable_v2( + rt_engine_type=VppEnum.vl_api_rt_backend_engine_t.RT_BACKEND_ENGINE_API_SDL + ) + + # Disable + self.vapi.session_enable_disable_v2( + rt_engine_type=VppEnum.vl_api_rt_backend_engine_t.RT_BACKEND_ENGINE_API_DISABLE + ) + + +if __name__ == "__main__": + unittest.main(testRunner=VppTestRunner) diff --git a/test/asf/vpp_session_sdl.py b/test/asf/vpp_session_sdl.py new file mode 100644 index 00000000000..b10c11d1e15 --- /dev/null +++ b/test/asf/vpp_session_sdl.py @@ -0,0 +1,75 @@ +from ipaddress import IPv4Network + +from vpp_object import VppObject +from vpp_papi import VppEnum +from vpp_ip import INVALID_INDEX +from vpp_papi_provider import UnexpectedApiReturnValueError + + +class SessionSdl: + """Session SDL""" + + def __init__( + self, + lcl, + action_index, + tag, + ): + + self.action_index = action_index + self.lcl = lcl + self.tag = tag + + def encode(self): + return { + "lcl": self.lcl, + "action_index": self.action_index, + "tag": self.tag, + } + + +class VppSessionSdl(VppObject): + """VPP Session SDL""" + + def __init__(self, test, rules, is_add, appns_index): + self._test = test + self._rules = rules + self.is_add = is_add + self.appns_index = appns_index + + @property + def rules(self): + return self._rules + + @property + def count(self): + return len(self._rules) + + def encode_rules(self): + rules = [] + for rule in self._rules: + rules.append(rule.encode()) + return rules + + def add_vpp_config(self, expect_error=False): + try: + reply = self._test.vapi.session_sdl_add_del( + is_add=self.is_add, + appns_index=self.appns_index, + count=self.count, + r=self.encode_rules(), + ) + self._test.registry.register(self, self._test.logger) + if expect_error: + self._test.fail("Unexpected api reply") + return self + except UnexpectedApiReturnValueError: + if not expect_error: + self._test.fail("Unexpected api reply") + return None + + def query_vpp_config(self): + pass + + def remove_vpp_config(self, expect_error=False): + pass |