diff options
author | Florin Coras <fcoras@cisco.com> | 2017-10-17 00:03:13 -0700 |
---|---|---|
committer | Dave Barach <openvpp@barachs.net> | 2017-10-28 19:56:39 +0000 |
commit | 1c7104514cd40d2377caca36cf40c13b791bc5aa (patch) | |
tree | 2b95bb11dd8658e826ad8cb3fe4d399adbab7e01 /src/vnet/session/session_test.c | |
parent | ae5a02f8235b9a243df09b42e932ae5f238e366b (diff) |
session: rules tables
This introduces 5-tuple lookup tables that may be used to implement
custom session layer actions at connection establishment time (session
layer perspective).
The rules table build mask-match-action lookup trees that for a given
5-tuple key return the action for the first longest match. If rules
overlap, ordering is established by tuple longest match with the
following descending priority: remote ip, local ip, remote port, local
port.
At this time, the only match action supported is to forward packets to
the application identified by the action.
Change-Id: Icbade6fac720fa3979820d50cd7d6137f8b635c3
Signed-off-by: Florin Coras <fcoras@cisco.com>
Diffstat (limited to 'src/vnet/session/session_test.c')
-rw-r--r-- | src/vnet/session/session_test.c | 462 |
1 files changed, 462 insertions, 0 deletions
diff --git a/src/vnet/session/session_test.c b/src/vnet/session/session_test.c index 986837cbf24..bdd4f052adc 100644 --- a/src/vnet/session/session_test.c +++ b/src/vnet/session/session_test.c @@ -17,6 +17,7 @@ #include <vnet/session/application_interface.h> #include <vnet/session/application.h> #include <vnet/session/session.h> +#include <vnet/session/session_rules_table.h> #define SESSION_TEST_I(_cond, _comment, _args...) \ ({ \ @@ -438,6 +439,463 @@ session_test_namespace (vlib_main_t * vm, unformat_input_t * input) return 0; } +static int +session_test_rule_table (vlib_main_t * vm, unformat_input_t * input) +{ + session_rules_table_t _srt, *srt = &_srt; + u16 lcl_port = 1234, rmt_port = 4321; + u32 action_index = 1, res; + ip4_address_t lcl_lkup, rmt_lkup; + clib_error_t *error; + int verbose = 0; + + 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; + } + } + + memset (srt, 0, sizeof (*srt)); + session_rules_table_init (srt); + + ip4_address_t lcl_ip = { + .as_u32 = clib_host_to_net_u32 (0x01020304), + }; + ip4_address_t rmt_ip = { + .as_u32 = clib_host_to_net_u32 (0x05060708), + }; + ip4_address_t lcl_ip2 = { + .as_u32 = clib_host_to_net_u32 (0x02020202), + }; + ip4_address_t rmt_ip2 = { + .as_u32 = clib_host_to_net_u32 (0x06060606), + }; + ip4_address_t lcl_ip3 = { + .as_u32 = clib_host_to_net_u32 (0x03030303), + }; + ip4_address_t rmt_ip3 = { + .as_u32 = clib_host_to_net_u32 (0x07070707), + }; + 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 = 16, + .fp_proto = FIB_PROTOCOL_IP4, + }; + + 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, + }; + error = session_rules_table_add_del (srt, &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, 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); + + /* + * Add 1.2.3.4/24 1234 5.6.7.8/16 4321 and 1.2.3.4/24 1234 5.6.7.8/24 4321 + */ + 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); + 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); + SESSION_TEST ((error == 0), "Add 1.2.3.4/24 1234 5.6.7.8/24 4321 action %d", + action_index - 1); + + /* + * Add 2.2.2.2/24 1234 6.6.6.6/16 4321 and 3.3.3.3/24 1234 7.7.7.7/16 4321 + */ + args.lcl.fp_addr.ip4 = lcl_ip2; + args.lcl.fp_len = 24; + 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); + 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); + SESSION_TEST ((error == 0), "Add 3.3.3.3/24 1234 7.7.7.7/16 4321 action %d", + action_index - 1); + + /* + * Add again 3.3.3.3/24 1234 7.7.7.7/16 4321 + */ + 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); + SESSION_TEST ((error == 0), "overwrite 3.3.3.3/24 1234 7.7.7.7/16 4321 " + "action %d", action_index - 1); + + /* + * 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, 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, 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, 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); + + /* + * Add 1.2.3.4/24 * 5.6.7.8/24 * + * Lookup 1.2.3.4 1234 5.6.7.8 4321 and 1.2.3.4 1235 5.6.7.8 4321 + */ + args.lcl.fp_addr.ip4 = lcl_ip; + args.rmt.fp_addr.ip4 = rmt_ip; + args.lcl.fp_len = 24; + args.rmt.fp_len = 24; + args.lcl_port = 0; + args.rmt_port = 0; + args.action_index = action_index++; + error = session_rules_table_add_del (srt, &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, 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, 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); + + /* + * Del 1.2.3.4/24 * 5.6.7.8/24 * + * Add 1.2.3.4/16 * 5.6.7.8/16 * and 1.2.3.4/24 1235 5.6.7.8/24 4321 + * Lookup 1.2.3.4 1234 5.6.7.8 4321, 1.2.3.4 1235 5.6.7.8 4321 and + * 1.2.3.4 1235 5.6.7.8 4322 + */ + args.is_add = 0; + error = session_rules_table_add_del (srt, &args); + SESSION_TEST ((error == 0), "Del 1.2.3.4/24 * 5.6.7.8/24 *"); + + args.lcl.fp_addr.ip4 = lcl_ip; + args.rmt.fp_addr.ip4 = rmt_ip; + args.lcl.fp_len = 16; + args.rmt.fp_len = 16; + args.lcl_port = 0; + args.rmt_port = 0; + args.action_index = action_index++; + args.is_add = 1; + error = session_rules_table_add_del (srt, &args); + SESSION_TEST ((error == 0), "Add 1.2.3.4/16 * 5.6.7.8/16 * action %d", + action_index - 1); + + args.lcl.fp_addr.ip4 = lcl_ip; + args.rmt.fp_addr.ip4 = rmt_ip; + args.lcl.fp_len = 24; + args.rmt.fp_len = 24; + args.lcl_port = lcl_port + 1; + args.rmt_port = rmt_port; + args.action_index = action_index++; + args.is_add = 1; + error = session_rules_table_add_del (srt, &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, + TRANSPORT_PROTO_TCP); + + res = + session_rules_table_lookup4 (srt, 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, 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, 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); + + /* + * Delete 1.2.0.0/16 1234 5.6.0.0/16 4321 and 1.2.0.0/16 * 5.6.0.0/16 * + * Lookup 1.2.3.4 1234 5.6.7.8 4321 + */ + args.lcl_port = 1234; + args.rmt_port = 4321; + args.lcl.fp_len = 16; + args.rmt.fp_len = 16; + args.is_add = 0; + error = session_rules_table_add_del (srt, &args); + SESSION_TEST ((error == 0), "Del 1.2.0.0/16 1234 5.6.0.0/16 4321"); + res = + session_rules_table_lookup4 (srt, 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); + + args.lcl_port = 0; + args.rmt_port = 0; + args.is_add = 0; + error = session_rules_table_add_del (srt, &args); + SESSION_TEST ((error == 0), "Del 1.2.0.0/16 * 5.6.0.0/16 *"); + res = + session_rules_table_lookup4 (srt, 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); + + /* + * Delete 1.2.3.4/24 1234 5.6.7.5/24 + */ + args.lcl.fp_addr.ip4 = lcl_ip; + args.rmt.fp_addr.ip4 = rmt_ip; + args.lcl.fp_len = 24; + args.rmt.fp_len = 24; + args.lcl_port = 1234; + args.rmt_port = 4321; + args.is_add = 0; + error = session_rules_table_add_del (srt, &args); + SESSION_TEST ((error == 0), "Del 1.2.3.4/24 1234 5.6.7.5/24"); + res = + session_rules_table_lookup4 (srt, TRANSPORT_PROTO_TCP, &lcl_ip, &rmt_ip, + lcl_port, rmt_port); + SESSION_TEST ((res == 2), "Action should be 2: %d", res); + + return 0; +} + +static int +session_test_rules (vlib_main_t * vm, unformat_input_t * input) +{ + session_endpoint_t server_sep = SESSION_ENDPOINT_NULL; + u64 options[SESSION_OPTIONS_N_OPTIONS]; + u16 lcl_port = 1234, rmt_port = 4321; + u32 server_index, app_index; + u32 dummy_server_api_index = ~0; + transport_connection_t *tc; + u32 dummy_port = 1111; + clib_error_t *error = 0; + u8 segment_name[128]; + stream_session_t *listener, *s; + app_namespace_t *default_ns = app_namespace_get_default (); + u32 local_ns_index = default_ns->local_table_index; + + server_sep.is_ip4 = 1; + server_sep.port = dummy_port; + memset (options, 0, sizeof (options)); + + vnet_app_attach_args_t attach_args = { + .api_client_index = ~0, + .options = options, + .namespace_id = 0, + .session_cb_vft = &dummy_session_cbs, + .segment_name = segment_name, + }; + + vnet_bind_args_t bind_args = { + .sep = server_sep, + .app_index = 0, + }; + + /* + * Attach server with global and local default scope + */ + options[APP_OPTIONS_FLAGS] = APP_OPTIONS_FLAGS_BUILTIN_APP; + options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_ACCEPT_REDIRECT; + options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_GLOBAL_SCOPE; + options[APP_OPTIONS_FLAGS] |= APP_OPTIONS_FLAGS_USE_LOCAL_SCOPE; + attach_args.namespace_id = 0; + attach_args.api_client_index = dummy_server_api_index; + error = vnet_application_attach (&attach_args); + SESSION_TEST ((error == 0), "server attached"); + server_index = attach_args.app_index; + + bind_args.app_index = server_index; + error = vnet_bind (&bind_args); + SESSION_TEST ((error == 0), "server bound to %U/%d", format_ip46_address, + &server_sep.ip, 1, server_sep.port); + listener = listen_session_get_from_handle (bind_args.handle); + ip4_address_t lcl_ip = { + .as_u32 = clib_host_to_net_u32 (0x01020304), + }; + ip4_address_t rmt_ip = { + .as_u32 = clib_host_to_net_u32 (0x05060708), + }; + 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 = 16, + .fp_proto = FIB_PROTOCOL_IP4, + }; + + tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4, + &rmt_pref.fp_addr.ip4, lcl_port, + rmt_port, TRANSPORT_PROTO_TCP, 0); + SESSION_TEST ((tc == 0), "optimized lookup should not work (port)"); + + /* + * Add 1.2.3.4/16 1234 5.6.7.8/16 4321 action server_index + */ + session_rule_add_del_args_t args = { + .table_args.lcl = lcl_pref, + .table_args.rmt = rmt_pref, + .table_args.lcl_port = lcl_port, + .table_args.rmt_port = rmt_port, + .table_args.action_index = server_index, + .table_args.is_add = 1, + .appns_index = 0, + }; + error = vnet_session_rule_add_del (&args); + SESSION_TEST ((error == 0), "Add 1.2.3.4/16 1234 5.6.7.8/16 4321 action %d", + args.table_args.action_index); + + tc = session_lookup_connection4 (0, &lcl_pref.fp_addr.ip4, + &rmt_pref.fp_addr.ip4, lcl_port, rmt_port, + TRANSPORT_PROTO_TCP); + SESSION_TEST ((tc->c_index == listener->connection_index), + "optimized lookup should return the listener"); + tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4, + &rmt_pref.fp_addr.ip4, lcl_port, + rmt_port, TRANSPORT_PROTO_TCP, 0); + SESSION_TEST ((tc->c_index == listener->connection_index), + "lookup should return the listener"); + s = session_lookup_safe4 (0, &lcl_pref.fp_addr.ip4, &rmt_pref.fp_addr.ip4, + lcl_port, rmt_port, TRANSPORT_PROTO_TCP); + SESSION_TEST ((s->connection_index == listener->connection_index), + "safe lookup should return the listener"); + session_endpoint_t sep = { + .ip = rmt_pref.fp_addr, + .is_ip4 = 1, + .port = rmt_port, + .transport_proto = TRANSPORT_PROTO_TCP, + }; + app_index = session_lookup_local_session_endpoint (local_ns_index, &sep); + SESSION_TEST ((app_index != server_index), "local session endpoint lookup " + "should not work (global scope)"); + + tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4, + &rmt_pref.fp_addr.ip4, lcl_port + 1, + rmt_port, TRANSPORT_PROTO_TCP, 0); + SESSION_TEST ((tc == 0), + "optimized lookup for wrong lcl port + 1 should not" " work"); + + /* + * Add 1.2.3.4/16 * 5.6.7.8/16 4321 + */ + args.table_args.lcl_port = 0; + args.scope = SESSION_RULE_SCOPE_LOCAL | SESSION_RULE_SCOPE_GLOBAL; + error = vnet_session_rule_add_del (&args); + SESSION_TEST ((error == 0), "Add 1.2.3.4/16 * 5.6.7.8/16 4321 action %d", + args.table_args.action_index); + tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4, + &rmt_pref.fp_addr.ip4, lcl_port + 1, + rmt_port, TRANSPORT_PROTO_TCP, 0); + SESSION_TEST ((tc->c_index == listener->connection_index), + "optimized lookup for lcl port + 1 should work"); + app_index = session_lookup_local_session_endpoint (local_ns_index, &sep); + SESSION_TEST ((app_index != server_index), "local session endpoint lookup " + "should not work (constrained lcl ip)"); + + /* + * Add local scope rule for 0/0 * 5.6.7.8/16 4321 action server_index + */ + args.table_args.lcl.fp_len = 0; + error = vnet_session_rule_add_del (&args); + SESSION_TEST ((error == 0), "Add * * 5.6.7.8/16 4321 action %d", + args.table_args.action_index); + app_index = session_lookup_local_session_endpoint (local_ns_index, &sep); + SESSION_TEST ((app_index == server_index), "local session endpoint lookup " + "should work"); + + /* + * Delete 0/0 * 5.6.7.8/16 4321, 1.2.3.4/16 * 5.6.7.8/16 4321 and + * 1.2.3.4/16 1234 5.6.7.8/16 4321 + */ + args.table_args.is_add = 0; + error = vnet_session_rule_add_del (&args); + SESSION_TEST ((error == 0), "Del 0/0 * 5.6.7.8/16 4321"); + app_index = session_lookup_local_session_endpoint (local_ns_index, &sep); + SESSION_TEST ((app_index != server_index), "local session endpoint lookup " + "should not work (removed)"); + + args.table_args.is_add = 0; + args.table_args.lcl = lcl_pref; + error = vnet_session_rule_add_del (&args); + SESSION_TEST ((error == 0), "Del 1.2.3.4/16 * 5.6.7.8/16 4321"); + tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4, + &rmt_pref.fp_addr.ip4, lcl_port + 1, + rmt_port, TRANSPORT_PROTO_TCP, 0); + SESSION_TEST ((tc == 0), "optimized lookup for lcl port + 1 should not " + "work (del)"); + + args.table_args.is_add = 0; + args.table_args.lcl_port = 1234; + error = vnet_session_rule_add_del (&args); + SESSION_TEST ((error == 0), "Del 1.2.3.4/16 1234 5.6.7.8/16 4321"); + tc = session_lookup_connection_wt4 (0, &lcl_pref.fp_addr.ip4, + &rmt_pref.fp_addr.ip4, lcl_port, + rmt_port, TRANSPORT_PROTO_TCP, 0); + SESSION_TEST ((tc == 0), "optimized lookup should not work (del)"); + return 0; +} + static clib_error_t * session_test (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd_arg) @@ -452,6 +910,10 @@ session_test (vlib_main_t * vm, { res = session_test_namespace (vm, input); } + else if (unformat (input, "rules-table")) + res = session_test_rule_table (vm, input); + else if (unformat (input, "rules")) + res = session_test_rules (vm, input); else break; } |