From c4b5d10115d4370488ac14eb0ba7295b049a0615 Mon Sep 17 00:00:00 2001 From: Steven Luong Date: Tue, 30 Jul 2024 13:44:01 -0700 Subject: session: add Source Deny List With this feature, session enable is now modified to have 3 modes of operation session enable -- only enable session session enable rt-backend sdl -- enable session with sdl session enable rt-backend rule-table -- enable session with rule-table session rule tables are now created on demand, upon adding first rule to the rule table. refactor session table to remove depenency from sesssion rules table. Now session rules table APIs take srtg_handle and transport proto instead of srt pointer. Type: feature Change-Id: Idde6a9b2f46b29bb931f9039636562575572aa14 Signed-off-by: Steven Luong --- src/vnet/CMakeLists.txt | 1 + src/vnet/session/application_namespace.c | 11 + src/vnet/session/application_namespace.h | 4 + src/vnet/session/session.api | 60 ++- src/vnet/session/session.c | 48 +- src/vnet/session/session.h | 50 +- src/vnet/session/session_api.c | 249 +++++++++- src/vnet/session/session_cli.c | 65 ++- src/vnet/session/session_lookup.c | 272 ++++++----- src/vnet/session/session_lookup.h | 15 + src/vnet/session/session_rules_table.c | 313 ++++++++++--- src/vnet/session/session_rules_table.h | 216 +++++++-- src/vnet/session/session_sdl.c | 768 +++++++++++++++++++++++++++++++ src/vnet/session/session_sdl.h | 36 ++ src/vnet/session/session_table.c | 15 +- src/vnet/session/session_table.h | 3 +- src/vnet/session/session_test.c | 23 + 17 files changed, 1886 insertions(+), 263 deletions(-) create mode 100644 src/vnet/session/session_sdl.c create mode 100644 src/vnet/session/session_sdl.h (limited to 'src/vnet') 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 #include +#include #include #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 #include #include +#include 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 #include #include -#include -#include #include +#include +#include +#include #include #include @@ -30,6 +31,105 @@ #define REPLY_MSG_ID_BASE session_main.msg_id_base #include +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,11 +620,53 @@ 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 ] " "[ [elog]] [thread [index ] " "[proto ] [state ] [range []] " - "[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 #include #include +#include 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 #include #include +#include +#include #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 #include #include -#include #include +#include +#include +#include +#include + +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) @@ -118,6 +133,18 @@ fib_pref_normalize (fib_prefix_t * pref) ip6_address_normalize (&pref->fp_addr.ip6, pref->fp_len); } +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) { @@ -125,7 +152,7 @@ format_session_rule4 (u8 * s, va_list * args) 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 #include #include +#include +#include + +#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 +#include +#include +#include +#include + +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 ] action " + " [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 ]", + .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 #include +#include /** * 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 #include -#include 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 @@ -270,6 +270,12 @@ api_session_enable_disable (vat_main_t *vat) return -1; } +static int +api_session_enable_disable_v2 (vat_main_t *vat) +{ + return -1; +} + static int api_app_worker_add_del (vat_main_t *vat) { @@ -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 /* -- cgit 1.2.3-korg