diff options
Diffstat (limited to 'src/vnet')
-rw-r--r-- | src/vnet/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/vnet/session/application_namespace.c | 11 | ||||
-rw-r--r-- | src/vnet/session/application_namespace.h | 4 | ||||
-rw-r--r-- | src/vnet/session/session.api | 60 | ||||
-rw-r--r-- | src/vnet/session/session.c | 48 | ||||
-rw-r--r-- | src/vnet/session/session.h | 50 | ||||
-rw-r--r-- | src/vnet/session/session_api.c | 249 | ||||
-rw-r--r-- | src/vnet/session/session_cli.c | 65 | ||||
-rw-r--r-- | src/vnet/session/session_lookup.c | 272 | ||||
-rw-r--r-- | src/vnet/session/session_lookup.h | 15 | ||||
-rw-r--r-- | src/vnet/session/session_rules_table.c | 313 | ||||
-rw-r--r-- | src/vnet/session/session_rules_table.h | 216 | ||||
-rw-r--r-- | src/vnet/session/session_sdl.c | 768 | ||||
-rw-r--r-- | src/vnet/session/session_sdl.h | 36 | ||||
-rw-r--r-- | src/vnet/session/session_table.c | 15 | ||||
-rw-r--r-- | src/vnet/session/session_table.h | 3 | ||||
-rw-r--r-- | src/vnet/session/session_test.c | 23 |
17 files changed, 1886 insertions, 263 deletions
diff --git a/src/vnet/CMakeLists.txt b/src/vnet/CMakeLists.txt index 1af2d40eff1..6262e803057 100644 --- a/src/vnet/CMakeLists.txt +++ b/src/vnet/CMakeLists.txt @@ -1012,6 +1012,7 @@ list(APPEND VNET_SOURCES session/application_namespace.c session/segment_manager.c session/session_api.c + session/session_sdl.c ) list(APPEND VNET_HEADERS diff --git a/src/vnet/session/application_namespace.c b/src/vnet/session/application_namespace.c index dbc6a6be80f..8b06331d803 100644 --- a/src/vnet/session/application_namespace.c +++ b/src/vnet/session/application_namespace.c @@ -34,6 +34,17 @@ static app_namespace_t *app_namespace_pool; static u8 app_sapi_enabled; +void +app_namespace_walk (app_namespace_walk_fn_t fn, void *ctx) +{ + app_namespace_t *app_ns; + + pool_foreach (app_ns, app_namespace_pool) + { + fn (app_ns, ctx); + } +} + app_namespace_t * app_namespace_get (u32 index) { diff --git a/src/vnet/session/application_namespace.h b/src/vnet/session/application_namespace.h index 261325cbe0e..b441e3c48f2 100644 --- a/src/vnet/session/application_namespace.h +++ b/src/vnet/session/application_namespace.h @@ -15,6 +15,7 @@ #include <vppinfra/socket.h> #include <vnet/vnet.h> +#include <vnet/session/session_types.h> #include <vnet/session/session_table.h> #ifndef SRC_VNET_SESSION_APPLICATION_NAMESPACE_H_ @@ -87,6 +88,9 @@ vnet_app_namespace_add_del (vnet_app_namespace_add_del_args_t *a); u32 app_namespace_get_fib_index (app_namespace_t * app_ns, u8 fib_proto); session_table_t *app_namespace_get_local_table (app_namespace_t * app_ns); +typedef void (*app_namespace_walk_fn_t) (app_namespace_t *app_ns, void *ctx); +extern void app_namespace_walk (app_namespace_walk_fn_t fn, void *ctx); + always_inline app_namespace_t * app_namespace_get_default (void) { diff --git a/src/vnet/session/session.api b/src/vnet/session/session.api index 6affae4112d..26346eaa466 100644 --- a/src/vnet/session/session.api +++ b/src/vnet/session/session.api @@ -13,12 +13,19 @@ * limitations under the License. */ -option version = "4.0.0"; +option version = "4.0.1"; import "vnet/interface_types.api"; import "vnet/ip/ip_types.api"; +typedef sdl_rule +{ + vl_api_prefix_t lcl; + u32 action_index; + string tag[64]; +}; + enum transport_proto : u8 { TRANSPORT_PROTO_API_TCP, @@ -28,6 +35,14 @@ enum transport_proto : u8 TRANSPORT_PROTO_API_QUIC, }; +enum rt_backend_engine : u8 +{ + RT_BACKEND_ENGINE_API_DISABLE = 0, + RT_BACKEND_ENGINE_API_RULE_TABLE, + RT_BACKEND_ENGINE_API_NONE, + RT_BACKEND_ENGINE_API_SDL, +}; + /** \brief Application attach to session layer @param client_index - opaque cookie to identify the sender @param context - sender context, to match reply w/ request @@ -166,11 +181,18 @@ define app_worker_add_del_reply @param is_enable - disable session layer if 0, enable otherwise */ autoreply define session_enable_disable { + option deprecated; u32 client_index; u32 context; bool is_enable [default=true]; }; +autoreply define session_enable_disable_v2 { + u32 client_index; + u32 context; + vl_api_rt_backend_engine_t rt_engine_type; +}; + /** \brief enable/disable session layer socket api @param client_index - opaque cookie to identify the sender client to vpp direction only @@ -417,6 +439,42 @@ define session_rules_details string tag[64]; }; +autoreply define session_sdl_add_del { + u32 client_index; + u32 context; + u32 appns_index; + bool is_add; + u32 count; + vl_api_sdl_rule_t r[count]; +}; + +/** \brief Dump session sdl + @param client_index - opaque cookie to identify the sender + @param context - sender context, to match reply w/ request + */ +define session_sdl_dump +{ + u32 client_index; + u32 context; +}; + +/** \brief Session sdl details + @param context - sender context, to match reply w/ request + @param lcl - local prefix + @param action_index - the only action defined now is forward to + application with index action_index + @param appns_index - application namespace where rule is to be applied to + @param tag - tag + */ +define session_sdl_details +{ + u32 context; + vl_api_prefix_t lcl; + u32 action_index; + u32 appns_index; + string tag[64]; +}; + /* * Local Variables: * eval: (c-set-style "gnu") diff --git a/src/vnet/session/session.c b/src/vnet/session/session.c index c1becf2c5ea..ac02281cf5c 100644 --- a/src/vnet/session/session.c +++ b/src/vnet/session/session.c @@ -24,6 +24,7 @@ #include <vnet/fib/ip4_fib.h> #include <vlib/stats/stats.h> #include <vlib/dma/dma.h> +#include <vnet/session/session_rules_table.h> session_main_t session_main; @@ -1996,7 +1997,8 @@ session_stats_collector_init (void) } static clib_error_t * -session_manager_main_enable (vlib_main_t * vm) +session_manager_main_enable (vlib_main_t *vm, + session_rt_engine_type_t rt_engine_type) { session_main_t *smm = &session_main; vlib_thread_main_t *vtm = vlib_get_thread_main (); @@ -2004,6 +2006,9 @@ session_manager_main_enable (vlib_main_t * vm) session_worker_t *wrk; int i; + if (session_rt_backend_enable_disable (rt_engine_type)) + return clib_error_return (0, "error on enable backend engine"); + /* We only initialize once and do not de-initialized on disable */ if (smm->is_initialized) goto done; @@ -2082,9 +2087,11 @@ done: } static void -session_manager_main_disable (vlib_main_t * vm) +session_manager_main_disable (vlib_main_t *vm, + session_rt_engine_type_t rt_engine_type) { transport_enable_disable (vm, 0 /* is_en */ ); + session_rt_backend_enable_disable (rt_engine_type); } /* in this new callback, cookie hint the index */ @@ -2221,22 +2228,24 @@ session_node_enable_disable (u8 is_en) } clib_error_t * -vnet_session_enable_disable (vlib_main_t * vm, u8 is_en) +vnet_session_enable_disable (vlib_main_t *vm, + session_enable_disable_args_t *args) { clib_error_t *error = 0; - if (is_en) + + if (args->is_en) { if (session_main.is_enabled) return 0; - error = session_manager_main_enable (vm); - session_node_enable_disable (is_en); + error = session_manager_main_enable (vm, args->rt_engine_type); + session_node_enable_disable (1); } else { session_main.is_enabled = 0; - session_manager_main_disable (vm); - session_node_enable_disable (is_en); + session_manager_main_disable (vm, args->rt_engine_type); + session_node_enable_disable (0); } return error; @@ -2263,10 +2272,15 @@ static clib_error_t * session_main_loop_init (vlib_main_t * vm) { session_main_t *smm = &session_main; + if (smm->session_enable_asap) { + session_enable_disable_args_t args = { .is_en = 1, + .rt_engine_type = + smm->rt_engine_type }; + vlib_worker_thread_barrier_sync (vm); - vnet_session_enable_disable (vm, 1 /* is_en */ ); + vnet_session_enable_disable (vm, &args); vlib_worker_thread_barrier_release (vm); } return 0; @@ -2356,8 +2370,22 @@ session_config_fn (vlib_main_t * vm, unformat_input_t * input) smm->port_allocator_min_src_port = tmp; else if (unformat (input, "max-src-port %d", &tmp)) smm->port_allocator_max_src_port = tmp; + else if (unformat (input, "enable rt-backend rule-table")) + { + smm->rt_engine_type = RT_BACKEND_ENGINE_RULE_TABLE; + smm->session_enable_asap = 1; + } + else if (unformat (input, "enable rt-backend sdl")) + { + smm->rt_engine_type = RT_BACKEND_ENGINE_SDL; + smm->session_enable_asap = 1; + } else if (unformat (input, "enable")) - smm->session_enable_asap = 1; + { + /* enable session without rt-backend */ + smm->rt_engine_type = RT_BACKEND_ENGINE_NONE; + smm->session_enable_asap = 1; + } else if (unformat (input, "use-app-socket-api")) (void) appns_sapi_enable_disable (1 /* is_enable */); else if (unformat (input, "poll-main")) diff --git a/src/vnet/session/session.h b/src/vnet/session/session.h index 67a182573e4..24150fbbcd1 100644 --- a/src/vnet/session/session.h +++ b/src/vnet/session/session.h @@ -184,6 +184,19 @@ typedef void (*nat44_original_dst_lookup_fn) ( u16 i2o_dst_port, ip_protocol_t proto, u32 *original_dst, u16 *original_dst_port); +#define foreach_rt_engine \ + _ (DISABLE, "disable") \ + _ (RULE_TABLE, "enable with rt-backend rule table") \ + _ (NONE, "enable without rt-backend") \ + _ (SDL, "enable with rt-backend sdl") + +typedef enum +{ +#define _(v, s) RT_BACKEND_ENGINE_##v, + foreach_rt_engine +#undef _ +} session_rt_engine_type_t; + typedef struct session_main_ { /** Worker contexts */ @@ -235,6 +248,9 @@ typedef struct session_main_ /** Enable session manager at startup */ u8 session_enable_asap; + /** Session engine type */ + session_rt_engine_type_t rt_engine_type; + /** Poll session node in main thread */ u8 poll_main; @@ -292,6 +308,12 @@ typedef enum session_q_process_evt_ SESSION_Q_PROCESS_STOP } session_q_process_evt_t; +typedef struct _session_enable_disable_args_t +{ + session_rt_engine_type_t rt_engine_type; + u8 is_en; +} session_enable_disable_args_t; + #define TRANSPORT_PROTO_INVALID (session_main.last_transport_proto_type + 1) #define TRANSPORT_N_PROTOS (session_main.last_transport_proto_type + 1) @@ -812,7 +834,9 @@ session_wrk_update_time (session_worker_t *wrk, f64 now) void session_wrk_enable_adaptive_mode (session_worker_t *wrk); fifo_segment_t *session_main_get_wrk_mqs_segment (void); void session_node_enable_disable (u8 is_en); -clib_error_t *vnet_session_enable_disable (vlib_main_t * vm, u8 is_en); +clib_error_t * +vnet_session_enable_disable (vlib_main_t *vm, + session_enable_disable_args_t *args); void session_wrk_handle_evts_main_rpc (void *); void session_wrk_program_app_wrk_evts (session_worker_t *wrk, u32 app_wrk_index); @@ -921,6 +945,30 @@ pool_program_safe_realloc (void **p, u32 elt_size, u32 align) } \ while (0) +always_inline u8 +session_is_enabled_without_rt_backend (void) +{ + session_main_t *smm = vnet_get_session_main (); + + return (smm->rt_engine_type == RT_BACKEND_ENGINE_NONE); +} + +always_inline u8 +session_sdl_is_enabled (void) +{ + session_main_t *smm = vnet_get_session_main (); + + return (smm->rt_engine_type == RT_BACKEND_ENGINE_SDL); +} + +always_inline u8 +session_rule_table_is_enabled (void) +{ + session_main_t *smm = vnet_get_session_main (); + + return (smm->rt_engine_type == RT_BACKEND_ENGINE_RULE_TABLE); +} + #endif /* __included_session_h__ */ /* diff --git a/src/vnet/session/session_api.c b/src/vnet/session/session_api.c index 8bb38398e3f..a729baaae29 100644 --- a/src/vnet/session/session_api.c +++ b/src/vnet/session/session_api.c @@ -18,9 +18,10 @@ #include <vnet/session/application.h> #include <vnet/session/application_interface.h> #include <vnet/session/application_local.h> -#include <vnet/session/session_rules_table.h> -#include <vnet/session/session_table.h> #include <vnet/session/session.h> +#include <vnet/session/session_table.h> +#include <vnet/session/session_rules_table.h> +#include <vnet/session/session_sdl.h> #include <vnet/ip/ip_types_api.h> #include <vnet/format_fns.h> @@ -30,6 +31,105 @@ #define REPLY_MSG_ID_BASE session_main.msg_id_base #include <vlibapi/api_helper_macros.h> +VLIB_REGISTER_LOG_CLASS (session_api_log, static) = { .class_name = "session", + .subclass_name = "api" }; + +#define log_debug(fmt, ...) \ + vlib_log_debug (session_api_log.class, "%s: " fmt, __func__, __VA_ARGS__) +#define log_warn(fmt, ...) \ + vlib_log_warn (session_api_log.class, fmt, __VA_ARGS__) +#define log_err(fmt, ...) \ + vlib_log_err (session_api_log.class, fmt, __VA_ARGS__) + +static int +verify_message_len (void *mp, u64 expected_len, char *where) +{ + u32 supplied_len = vl_msg_api_get_msg_length (mp); + + if (supplied_len < expected_len) + { + log_err ("%s: Supplied message length %d is less than expected %d", + where, supplied_len, expected_len); + return 0; + } + else + { + return 1; + } +} + +static void +vl_api_session_sdl_add_del_t_handler (vl_api_session_sdl_add_del_t *mp) +{ + vl_api_session_sdl_add_del_reply_t *rmp; + session_rule_add_del_args_t args; + session_rule_table_add_del_args_t *table_args = &args.table_args; + int rv = 0; + u32 count = clib_net_to_host_u32 (mp->count); + u64 expected_len = sizeof (*mp) + count * sizeof (mp->r[0]); + + if ((session_main.is_enabled == 0) || (session_sdl_is_enabled () == 0)) + { + rv = VNET_API_ERROR_FEATURE_DISABLED; + goto done; + } + + if (!verify_message_len (mp, expected_len, "session_sdl_add_del")) + { + rv = VNET_API_ERROR_INVALID_VALUE; + goto done; + } + + clib_memset (&args, 0, sizeof (args)); + table_args->is_add = mp->is_add; + args.scope = SESSION_RULE_SCOPE_GLOBAL; + args.appns_index = clib_net_to_host_u32 (mp->appns_index); + for (int i = 0; i < count; i++) + { + mp->r[i].tag[sizeof (mp->r[i].tag) - 1] = 0; + table_args->tag = format (0, "%s", mp->r[i].tag); + ip_prefix_decode (&mp->r[i].lcl, &table_args->lcl); + /* + * Need to set fp_proto for vnet_session_rule_add_del to find the + * correct table + */ + table_args->rmt.fp_proto = table_args->lcl.fp_proto; + table_args->action_index = clib_net_to_host_u32 (mp->r[i].action_index); + + rv = vnet_session_rule_add_del (&args); + vec_free (table_args->tag); + if (rv) + { + log_err ("session_sdl add del returned on %U @index %d: %U", + format_ip46_address, &table_args->lcl.fp_addr, + IP46_TYPE_ANY, i, format_session_error, rv); + + /* roll back */ + table_args->is_add = !mp->is_add; + for (int j = i - 1; j >= 0; j--) + { + mp->r[j].tag[sizeof (mp->r[j].tag) - 1] = 0; + table_args->tag = format (0, "%s", mp->r[j].tag); + ip_prefix_decode (&mp->r[j].lcl, &table_args->lcl); + table_args->rmt.fp_proto = table_args->lcl.fp_proto; + table_args->action_index = + clib_net_to_host_u32 (mp->r[j].action_index); + int rv2 = vnet_session_rule_add_del (&args); + vec_free (table_args->tag); + if (rv2) + log_err ("rollback session_sdl add del returned on %U " + "@index %d: %U", + format_ip46_address, &table_args->lcl.fp_addr, + IP46_TYPE_ANY, j, format_session_error, rv2); + } + break; + } + } + +done: + REPLY_MACRO (VL_API_SESSION_SDL_ADD_DEL_REPLY); +} + static transport_proto_t api_session_transport_proto_decode (const vl_api_transport_proto_t * api_tp) { @@ -520,12 +620,54 @@ vl_api_session_enable_disable_t_handler (vl_api_session_enable_disable_t * mp) vl_api_session_enable_disable_reply_t *rmp; vlib_main_t *vm = vlib_get_main (); int rv = 0; + session_enable_disable_args_t args; + + args.is_en = mp->is_enable; + if (mp->is_enable) + args.rt_engine_type = RT_BACKEND_ENGINE_RULE_TABLE; + else + args.rt_engine_type = RT_BACKEND_ENGINE_DISABLE; - vnet_session_enable_disable (vm, mp->is_enable); + if (vnet_session_enable_disable (vm, &args)) + rv = VNET_API_ERROR_INVALID_ARGUMENT; REPLY_MACRO (VL_API_SESSION_ENABLE_DISABLE_REPLY); } static void +vl_api_session_enable_disable_v2_t_handler ( + vl_api_session_enable_disable_v2_t *mp) +{ + vl_api_session_enable_disable_v2_reply_t *rmp; + vlib_main_t *vm = vlib_get_main (); + int rv = 0; + session_enable_disable_args_t args; + + STATIC_ASSERT ((session_rt_engine_type_t) RT_BACKEND_ENGINE_API_DISABLE == + RT_BACKEND_ENGINE_DISABLE, + "API value mismatch"); + STATIC_ASSERT ((session_rt_engine_type_t) RT_BACKEND_ENGINE_API_NONE == + RT_BACKEND_ENGINE_NONE, + "API value mismatch"); + STATIC_ASSERT ((session_rt_engine_type_t) RT_BACKEND_ENGINE_API_RULE_TABLE == + RT_BACKEND_ENGINE_RULE_TABLE, + "API value mismatch"); + STATIC_ASSERT ((session_rt_engine_type_t) RT_BACKEND_ENGINE_API_SDL == + RT_BACKEND_ENGINE_SDL, + "API value mismatch"); + + args.rt_engine_type = (session_rt_engine_type_t) mp->rt_engine_type; + if (args.rt_engine_type == RT_BACKEND_ENGINE_DISABLE) + args.is_en = 0; + else + args.is_en = 1; + + if (vnet_session_enable_disable (vm, &args)) + rv = VNET_API_ERROR_INVALID_VALUE; + + REPLY_MACRO (VL_API_SESSION_ENABLE_DISABLE_V2_REPLY); +} + +static void vl_api_session_sapi_enable_disable_t_handler ( vl_api_session_sapi_enable_disable_t *mp) { @@ -1131,14 +1273,89 @@ vl_api_session_rules_dump_t_handler (vl_api_session_rules_dump_t * mp) return; session_table_foreach (st, ({ - for (tp = 0; tp < TRANSPORT_N_PROTOS; tp++) - { - send_session_rules_table_details (&st->session_rules[tp], - st->active_fib_proto, tp, - st->is_local, st->appns_index, reg, - mp->context); - } - })); + if (st->srtg_handle != SESSION_SRTG_HANDLE_INVALID) + for (tp = 0; tp < TRANSPORT_N_PROTOS; tp++) + { + session_rules_table_t *srt = + srtg_handle_to_srt (st->srtg_handle, tp); + send_session_rules_table_details ( + srt, st->active_fib_proto, tp, st->is_local, + st->appns_index, reg, mp->context); + } + })); +} + +typedef struct session_sdl_table_walk_ctx_ +{ + vl_api_registration_t *reg; + u32 mp_context; + u32 appns_index; +} session_sdl_table_walk_ctx; + +static void +send_session_sdl_details (u32 fei, ip46_address_t *lcl_ip, u16 fp_len, + u32 action_index, u32 fp_proto, u8 *tag, void *args) +{ + session_sdl_table_walk_ctx *ctx = args; + vl_api_registration_t *reg = ctx->reg; + u32 appns_index = ctx->appns_index; + u32 context = ctx->mp_context; + vl_api_session_sdl_details_t *rmp = 0; + fib_prefix_t lcl; + + rmp = vl_msg_api_alloc (sizeof (*rmp)); + clib_memset (rmp, 0, sizeof (*rmp)); + rmp->_vl_msg_id = ntohs (REPLY_MSG_ID_BASE + VL_API_SESSION_SDL_DETAILS); + rmp->context = context; + + clib_memset (&lcl, 0, sizeof (lcl)); + if (fp_proto == FIB_PROTOCOL_IP4) + ip_set (&lcl.fp_addr, &lcl_ip->ip4, 1); + else + ip_set (&lcl.fp_addr, &lcl_ip->ip6, 0); + lcl.fp_len = fp_len; + lcl.fp_proto = fp_proto, + + ip_prefix_encode (&lcl, &rmp->lcl); + rmp->action_index = clib_host_to_net_u32 (action_index); + rmp->appns_index = clib_host_to_net_u32 (appns_index); + if (tag) + { + clib_memcpy_fast (rmp->tag, tag, vec_len (tag)); + rmp->tag[vec_len (tag)] = 0; + } + + vl_api_send_msg (reg, (u8 *) rmp); +} + +static void +vl_api_session_sdl_dump_t_handler (vl_api_session_rules_dump_t *mp) +{ + vl_api_registration_t *reg; + session_table_t *st; + session_sdl_table_walk_ctx ctx; + + reg = vl_api_client_index_to_registration (mp->client_index); + if (!reg) + return; + + ctx.reg = reg; + ctx.mp_context = mp->context; + + session_table_foreach ( + st, ({ + if (st->srtg_handle != SESSION_SRTG_HANDLE_INVALID) + { + ctx.appns_index = st->appns_index; + + if (st->active_fib_proto == FIB_PROTOCOL_IP4) + session_sdl_table_walk4 (st->srtg_handle, send_session_sdl_details, + &ctx); + else + session_sdl_table_walk6 (st->srtg_handle, send_session_sdl_details, + &ctx); + } + })); } static void @@ -1836,11 +2053,21 @@ appns_sapi_add_ns_socket (app_namespace_t * app_ns) static clib_error_t * session_api_hookup (vlib_main_t *vm) { + api_main_t *am = vlibapi_get_main (); + /* * Set up the (msg_name, crc, message-id) table */ REPLY_MSG_ID_BASE = setup_message_id_table (); + vl_api_set_msg_thread_safe ( + am, REPLY_MSG_ID_BASE + VL_API_SESSION_SDL_ADD_DEL, 1); + vl_api_set_msg_thread_safe ( + am, REPLY_MSG_ID_BASE + VL_API_SESSION_SDL_ADD_DEL_REPLY, 1); + vl_api_set_msg_thread_safe (am, REPLY_MSG_ID_BASE + VL_API_SESSION_SDL_DUMP, + 1); + vl_api_set_msg_thread_safe ( + am, REPLY_MSG_ID_BASE + VL_API_SESSION_SDL_DETAILS, 1); return 0; } diff --git a/src/vnet/session/session_cli.c b/src/vnet/session/session_cli.c index 569a77bccc1..76ecfeae243 100644 --- a/src/vnet/session/session_cli.c +++ b/src/vnet/session/session_cli.c @@ -482,6 +482,25 @@ session_cli_print_session_states (vlib_main_t * vm) #undef _ } +static u8 * +format_rt_backend (u8 *s, va_list *args) +{ + u32 i = va_arg (*args, u32); + u8 *t = 0; + + switch (i) + { +#define _(v, s) \ + case RT_BACKEND_ENGINE_##v: \ + t = (u8 *) s; \ + break; + foreach_rt_engine +#undef _ + default : return format (s, "unknown"); + } + return format (s, "%s", t); +} + static clib_error_t * show_session_command_fn (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd) @@ -573,6 +592,11 @@ show_session_command_fn (vlib_main_t * vm, unformat_input_t * input, vlib_cli_output (vm, "%U", format_transport_protos); goto done; } + else if (unformat (input, "rt-backend")) + { + vlib_cli_output (vm, "%U", format_rt_backend, smm->rt_engine_type); + goto done; + } else if (unformat (input, "states")) { session_cli_print_session_states (vm); @@ -654,13 +678,12 @@ done: return error; } -VLIB_CLI_COMMAND (vlib_cli_show_session_command) = -{ +VLIB_CLI_COMMAND (vlib_cli_show_session_command) = { .path = "show session", .short_help = "show session [verbose [n]] [listeners <proto>] " "[<session-id> [elog]] [thread <n> [index <n>] " "[proto <proto>] [state <state>] [range <min> [<max>]] " - "[protos] [states] ", + "[protos] [states] [rt-backend]", .function = show_session_command_fn, }; @@ -829,29 +852,47 @@ static clib_error_t * session_enable_disable_fn (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd) { - u8 is_en = 2; + session_enable_disable_args_t args; + session_main_t *smm = &session_main; while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { if (unformat (input, "enable")) - is_en = 1; + { + args.is_en = 1; + if (unformat (input, "rt-backend")) + if (unformat (input, "sdl")) + args.rt_engine_type = RT_BACKEND_ENGINE_SDL; + else if (unformat (input, "rule-table")) + args.rt_engine_type = RT_BACKEND_ENGINE_RULE_TABLE; + else + return clib_error_return (0, "unknown input `%U'", + format_unformat_error, input); + else + args.rt_engine_type = RT_BACKEND_ENGINE_NONE; + } else if (unformat (input, "disable")) - is_en = 0; + { + args.rt_engine_type = RT_BACKEND_ENGINE_DISABLE; + args.is_en = 0; + } else return clib_error_return (0, "unknown input `%U'", format_unformat_error, input); } - if (is_en > 1) - return clib_error_return (0, "expected enable | disable"); + if (smm->is_enabled && args.is_en) + if (args.rt_engine_type != smm->rt_engine_type) + return clib_error_return ( + 0, "session is already enable. Must disable first"); - return vnet_session_enable_disable (vm, is_en); + return vnet_session_enable_disable (vm, &args); } -VLIB_CLI_COMMAND (session_enable_disable_command, static) = -{ +VLIB_CLI_COMMAND (session_enable_disable_command, static) = { .path = "session", - .short_help = "session [enable|disable]", + .short_help = + "session { enable [ rt-backend sdl | rule-table ] } | { disable }", .function = session_enable_disable_fn, }; diff --git a/src/vnet/session/session_lookup.c b/src/vnet/session/session_lookup.c index 217fe9ad209..0d580ba35c6 100644 --- a/src/vnet/session/session_lookup.c +++ b/src/vnet/session/session_lookup.c @@ -28,6 +28,7 @@ #include <vnet/session/session_lookup.h> #include <vnet/session/session.h> #include <vnet/session/application.h> +#include <vnet/session/session_rules_table.h> static session_lookup_main_t sl_main; @@ -241,7 +242,7 @@ session_table_get_for_connection (transport_connection_t * tc) session_table_get (fib_index_to_table_index[fib_proto][tc->fib_index]); } -static session_table_t * +session_table_t * session_table_get_for_fib_index (u32 fib_proto, u32 fib_index) { if (vec_len (fib_index_to_table_index[fib_proto]) <= fib_index) @@ -478,10 +479,10 @@ session_lookup_rules_table_session4 (session_table_t * st, u8 proto, ip4_address_t * lcl, u16 lcl_port, ip4_address_t * rmt, u16 rmt_port) { - session_rules_table_t *srt = &st->session_rules[proto]; u32 action_index, app_index; - action_index = session_rules_table_lookup4 (srt, lcl, rmt, lcl_port, - rmt_port); + + action_index = session_rules_table_lookup4 (st->srtg_handle, proto, lcl, rmt, + lcl_port, rmt_port); app_index = session_lookup_action_to_handle (action_index); /* Nothing sophisticated for now, action index is app index */ return session_lookup_app_listen_session (app_index, FIB_PROTOCOL_IP4, @@ -494,10 +495,10 @@ session_lookup_rules_table_session6 (session_table_t * st, u8 proto, ip6_address_t * lcl, u16 lcl_port, ip6_address_t * rmt, u16 rmt_port) { - session_rules_table_t *srt = &st->session_rules[proto]; u32 action_index, app_index; - action_index = session_rules_table_lookup6 (srt, lcl, rmt, lcl_port, - rmt_port); + + action_index = session_rules_table_lookup6 (st->srtg_handle, proto, lcl, rmt, + lcl_port, rmt_port); app_index = session_lookup_action_to_handle (action_index); return session_lookup_app_listen_session (app_index, FIB_PROTOCOL_IP6, proto); @@ -517,7 +518,6 @@ u64 session_lookup_endpoint_listener (u32 table_index, session_endpoint_t * sep, u8 use_rules) { - session_rules_table_t *srt; session_table_t *st; u32 ai; int rv; @@ -537,10 +537,12 @@ session_lookup_endpoint_listener (u32 table_index, session_endpoint_t * sep, return kv4.value; if (use_rules) { + if (st->srtg_handle == SESSION_SRTG_HANDLE_INVALID) + return SESSION_INVALID_HANDLE; clib_memset (&lcl4, 0, sizeof (lcl4)); - srt = &st->session_rules[sep->transport_proto]; - ai = session_rules_table_lookup4 (srt, &lcl4, &sep->ip.ip4, 0, - sep->port); + ai = + session_rules_table_lookup4 (st->srtg_handle, sep->transport_proto, + &lcl4, &sep->ip.ip4, 0, sep->port); if (session_lookup_action_index_is_valid (ai)) return session_lookup_action_to_handle (ai); } @@ -558,10 +560,12 @@ session_lookup_endpoint_listener (u32 table_index, session_endpoint_t * sep, if (use_rules) { + if (st->srtg_handle == SESSION_SRTG_HANDLE_INVALID) + return SESSION_INVALID_HANDLE; clib_memset (&lcl6, 0, sizeof (lcl6)); - srt = &st->session_rules[sep->transport_proto]; - ai = session_rules_table_lookup6 (srt, &lcl6, &sep->ip.ip6, 0, - sep->port); + ai = + session_rules_table_lookup6 (st->srtg_handle, sep->transport_proto, + &lcl6, &sep->ip.ip6, 0, sep->port); if (session_lookup_action_index_is_valid (ai)) return session_lookup_action_to_handle (ai); } @@ -588,7 +592,6 @@ session_lookup_endpoint_listener (u32 table_index, session_endpoint_t * sep, u64 session_lookup_local_endpoint (u32 table_index, session_endpoint_t * sep) { - session_rules_table_t *srt; session_table_t *st; u32 ai; int rv; @@ -603,15 +606,18 @@ session_lookup_local_endpoint (u32 table_index, session_endpoint_t * sep) session_kv4_t kv4; ip4_address_t lcl4; - /* - * Check if endpoint has special rules associated - */ - clib_memset (&lcl4, 0, sizeof (lcl4)); - srt = &st->session_rules[sep->transport_proto]; - ai = session_rules_table_lookup4 (srt, &lcl4, &sep->ip.ip4, 0, - sep->port); - if (session_lookup_action_index_is_valid (ai)) - return session_lookup_action_to_handle (ai); + if (st->srtg_handle != SESSION_SRTG_HANDLE_INVALID) + { + /* + * Check if endpoint has special rules associated + */ + clib_memset (&lcl4, 0, sizeof (lcl4)); + ai = + session_rules_table_lookup4 (st->srtg_handle, sep->transport_proto, + &lcl4, &sep->ip.ip4, 0, sep->port); + if (session_lookup_action_index_is_valid (ai)) + return session_lookup_action_to_handle (ai); + } /* * Check if session endpoint is a listener @@ -651,12 +657,15 @@ session_lookup_local_endpoint (u32 table_index, session_endpoint_t * sep) session_kv6_t kv6; ip6_address_t lcl6; - clib_memset (&lcl6, 0, sizeof (lcl6)); - srt = &st->session_rules[sep->transport_proto]; - ai = session_rules_table_lookup6 (srt, &lcl6, &sep->ip.ip6, 0, - sep->port); - if (session_lookup_action_index_is_valid (ai)) - return session_lookup_action_to_handle (ai); + if (st->srtg_handle != SESSION_SRTG_HANDLE_INVALID) + { + clib_memset (&lcl6, 0, sizeof (lcl6)); + ai = + session_rules_table_lookup6 (st->srtg_handle, sep->transport_proto, + &lcl6, &sep->ip.ip6, 0, sep->port); + if (session_lookup_action_index_is_valid (ai)) + return session_lookup_action_to_handle (ai); + } make_v6_listener_kv (&kv6, &sep->ip.ip6, sep->port, sep->transport_proto); @@ -984,22 +993,25 @@ session_lookup_connection_wt4 (u32 fib_index, ip4_address_t * lcl, if (rv == 0) return transport_get_half_open (proto, kv4.value & 0xFFFFFFFF); - /* - * Check the session rules table - */ - action_index = session_rules_table_lookup4 (&st->session_rules[proto], lcl, - rmt, lcl_port, rmt_port); - if (session_lookup_action_index_is_valid (action_index)) + if (st->srtg_handle != SESSION_SRTG_HANDLE_INVALID) { - if (action_index == SESSION_RULES_TABLE_ACTION_DROP) + /* + * Check the session rules table + */ + action_index = session_rules_table_lookup4 (st->srtg_handle, proto, lcl, + rmt, lcl_port, rmt_port); + if (session_lookup_action_index_is_valid (action_index)) { - *result = SESSION_LOOKUP_RESULT_FILTERED; + if (action_index == SESSION_RULES_TABLE_ACTION_DROP) + { + *result = SESSION_LOOKUP_RESULT_FILTERED; + return 0; + } + if ((s = session_lookup_action_to_session (action_index, + FIB_PROTOCOL_IP4, proto))) + return transport_get_listener (proto, s->connection_index); return 0; } - if ((s = session_lookup_action_to_session (action_index, - FIB_PROTOCOL_IP4, proto))) - return transport_get_listener (proto, s->connection_index); - return 0; } /* @@ -1061,19 +1073,22 @@ session_lookup_connection4 (u32 fib_index, ip4_address_t * lcl, if (rv == 0) return transport_get_half_open (proto, kv4.value & 0xFFFFFFFF); - /* - * Check the session rules table - */ - action_index = session_rules_table_lookup4 (&st->session_rules[proto], lcl, - rmt, lcl_port, rmt_port); - if (session_lookup_action_index_is_valid (action_index)) + if (st->srtg_handle != SESSION_SRTG_HANDLE_INVALID) { - if (action_index == SESSION_RULES_TABLE_ACTION_DROP) - return 0; - if ((s = session_lookup_action_to_session (action_index, - FIB_PROTOCOL_IP4, proto))) - return transport_get_listener (proto, s->connection_index); - return 0; + /* + * Check the session rules table + */ + action_index = session_rules_table_lookup4 (st->srtg_handle, proto, lcl, + rmt, lcl_port, rmt_port); + if (session_lookup_action_index_is_valid (action_index)) + { + if (action_index == SESSION_RULES_TABLE_ACTION_DROP) + return 0; + if ((s = session_lookup_action_to_session (action_index, + FIB_PROTOCOL_IP4, proto))) + return transport_get_listener (proto, s->connection_index); + return 0; + } } /* @@ -1119,17 +1134,20 @@ session_lookup_safe4 (u32 fib_index, ip4_address_t * lcl, ip4_address_t * rmt, if (rv == 0) return session_get_from_handle_safe (kv4.value); - /* - * Check the session rules table - */ - action_index = session_rules_table_lookup4 (&st->session_rules[proto], lcl, - rmt, lcl_port, rmt_port); - if (session_lookup_action_index_is_valid (action_index)) + if (st->srtg_handle != SESSION_SRTG_HANDLE_INVALID) { - if (action_index == SESSION_RULES_TABLE_ACTION_DROP) - return 0; - return session_lookup_action_to_session (action_index, FIB_PROTOCOL_IP4, - proto); + /* + * Check the session rules table + */ + action_index = session_rules_table_lookup4 (st->srtg_handle, proto, lcl, + rmt, lcl_port, rmt_port); + if (session_lookup_action_index_is_valid (action_index)) + { + if (action_index == SESSION_RULES_TABLE_ACTION_DROP) + return 0; + return session_lookup_action_to_session (action_index, + FIB_PROTOCOL_IP4, proto); + } } /* @@ -1201,20 +1219,23 @@ session_lookup_connection_wt6 (u32 fib_index, ip6_address_t * lcl, if (rv == 0) return transport_get_half_open (proto, kv6.value & 0xFFFFFFFF); - /* Check the session rules table */ - action_index = session_rules_table_lookup6 (&st->session_rules[proto], lcl, - rmt, lcl_port, rmt_port); - if (session_lookup_action_index_is_valid (action_index)) + if (st->srtg_handle != SESSION_SRTG_HANDLE_INVALID) { - if (action_index == SESSION_RULES_TABLE_ACTION_DROP) + /* Check the session rules table */ + action_index = session_rules_table_lookup6 (st->srtg_handle, proto, lcl, + rmt, lcl_port, rmt_port); + if (session_lookup_action_index_is_valid (action_index)) { - *result = SESSION_LOOKUP_RESULT_FILTERED; + if (action_index == SESSION_RULES_TABLE_ACTION_DROP) + { + *result = SESSION_LOOKUP_RESULT_FILTERED; + return 0; + } + if ((s = session_lookup_action_to_session (action_index, + FIB_PROTOCOL_IP6, proto))) + return transport_get_listener (proto, s->connection_index); return 0; } - if ((s = session_lookup_action_to_session (action_index, - FIB_PROTOCOL_IP6, proto))) - return transport_get_listener (proto, s->connection_index); - return 0; } /* If nothing is found, check if any listener is available */ @@ -1270,17 +1291,20 @@ session_lookup_connection6 (u32 fib_index, ip6_address_t * lcl, if (rv == 0) return transport_get_half_open (proto, kv6.value & 0xFFFFFFFF); - /* Check the session rules table */ - action_index = session_rules_table_lookup6 (&st->session_rules[proto], lcl, - rmt, lcl_port, rmt_port); - if (session_lookup_action_index_is_valid (action_index)) + if (st->srtg_handle != SESSION_SRTG_HANDLE_INVALID) { - if (action_index == SESSION_RULES_TABLE_ACTION_DROP) - return 0; - if ((s = session_lookup_action_to_session (action_index, - FIB_PROTOCOL_IP6, proto))) - return transport_get_listener (proto, s->connection_index); - return 0; + /* Check the session rules table */ + action_index = session_rules_table_lookup6 (st->srtg_handle, proto, lcl, + rmt, lcl_port, rmt_port); + if (session_lookup_action_index_is_valid (action_index)) + { + if (action_index == SESSION_RULES_TABLE_ACTION_DROP) + return 0; + if ((s = session_lookup_action_to_session (action_index, + FIB_PROTOCOL_IP6, proto))) + return transport_get_listener (proto, s->connection_index); + return 0; + } } /* If nothing is found, check if any listener is available */ @@ -1323,15 +1347,18 @@ session_lookup_safe6 (u32 fib_index, ip6_address_t * lcl, ip6_address_t * rmt, if (rv == 0) return session_get_from_handle_safe (kv6.value); - /* Check the session rules table */ - action_index = session_rules_table_lookup6 (&st->session_rules[proto], lcl, - rmt, lcl_port, rmt_port); - if (session_lookup_action_index_is_valid (action_index)) + if (st->srtg_handle != SESSION_SRTG_HANDLE_INVALID) { - if (action_index == SESSION_RULES_TABLE_ACTION_DROP) - return 0; - return session_lookup_action_to_session (action_index, FIB_PROTOCOL_IP6, - proto); + /* Check the session rules table */ + action_index = session_rules_table_lookup6 (st->srtg_handle, proto, lcl, + rmt, lcl_port, rmt_port); + if (session_lookup_action_index_is_valid (action_index)) + { + if (action_index == SESSION_RULES_TABLE_ACTION_DROP) + return 0; + return session_lookup_action_to_session (action_index, + FIB_PROTOCOL_IP6, proto); + } } /* If nothing is found, check if any listener is available */ @@ -1357,7 +1384,6 @@ session_error_t vnet_session_rule_add_del (session_rule_add_del_args_t *args) { app_namespace_t *app_ns = app_namespace_get (args->appns_index); - session_rules_table_t *srt; session_table_t *st; u32 fib_index; u8 fib_proto; @@ -1378,8 +1404,9 @@ vnet_session_rule_add_del (session_rule_add_del_args_t *args) fib_proto = args->table_args.rmt.fp_proto; fib_index = app_namespace_get_fib_index (app_ns, fib_proto); st = session_table_get_for_fib_index (fib_proto, fib_index); - srt = &st->session_rules[args->transport_proto]; - if ((rv = session_rules_table_add_del (srt, &args->table_args))) + session_rules_table_init (st, fib_proto); + if ((rv = session_rules_table_add_del ( + st->srtg_handle, args->transport_proto, &args->table_args))) return rv; } if (args->scope & SESSION_RULE_SCOPE_LOCAL) @@ -1388,8 +1415,9 @@ vnet_session_rule_add_del (session_rule_add_del_args_t *args) args->table_args.lcl.fp_proto = args->table_args.rmt.fp_proto; args->table_args.lcl_port = 0; st = app_namespace_get_local_table (app_ns); - srt = &st->session_rules[args->transport_proto]; - rv = session_rules_table_add_del (srt, &args->table_args); + session_rules_table_init (st, args->table_args.rmt.fp_proto); + rv = session_rules_table_add_del (st->srtg_handle, args->transport_proto, + &args->table_args); } return rv; } @@ -1523,6 +1551,9 @@ session_rule_command_fn (vlib_main_t * vm, unformat_input_t * input, session_cli_return_if_not_enabled (); + if (session_rule_table_is_enabled () == 0) + return clib_error_return (0, "session rule table engine is not enabled"); + clib_memset (&lcl_ip, 0, sizeof (lcl_ip)); clib_memset (&rmt_ip, 0, sizeof (rmt_ip)); while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) @@ -1644,11 +1675,12 @@ session_lookup_dump_rules_table (u32 fib_index, u8 fib_proto, u8 transport_proto) { vlib_main_t *vm = vlib_get_main (); - session_rules_table_t *srt; session_table_t *st; st = session_table_get_for_fib_index (fib_index, fib_proto); - srt = &st->session_rules[transport_proto]; - session_rules_table_cli_dump (vm, srt, fib_proto); + if (st == 0) + return; + session_rules_table_cli_dump (vm, st->srtg_handle, transport_proto, + fib_proto); } void @@ -1656,11 +1688,12 @@ session_lookup_dump_local_rules_table (u32 table_index, u8 fib_proto, u8 transport_proto) { vlib_main_t *vm = vlib_get_main (); - session_rules_table_t *srt; session_table_t *st; st = session_table_get (table_index); - srt = &st->session_rules[transport_proto]; - session_rules_table_cli_dump (vm, srt, fib_proto); + if (st == 0) + return; + session_rules_table_cli_dump (vm, st->srtg_handle, transport_proto, + fib_proto); } static clib_error_t * @@ -1672,7 +1705,6 @@ show_session_rules_command_fn (vlib_main_t * vm, unformat_input_t * input, ip46_address_t lcl_ip, rmt_ip; u8 is_ip4 = 1, show_one = 0; app_namespace_t *app_ns; - session_rules_table_t *srt; session_table_t *st; u8 *ns_id = 0, fib_proto; @@ -1745,11 +1777,18 @@ show_session_rules_command_fn (vlib_main_t * vm, unformat_input_t * input, st = app_namespace_get_local_table (app_ns); } + if (session_rule_table_is_enabled () == 0) + { + vlib_cli_output (vm, "session rule table engine is not enabled"); + goto done; + } + if (show_one) { - srt = &st->session_rules[transport_proto]; - session_rules_table_show_rule (vm, srt, &lcl_ip, lcl_port, &rmt_ip, - rmt_port, is_ip4); + if (st) + session_rules_table_show_rule (vm, st->srtg_handle, transport_proto, + &lcl_ip, lcl_port, &rmt_ip, rmt_port, + is_ip4); goto done; } @@ -1759,9 +1798,10 @@ show_session_rules_command_fn (vlib_main_t * vm, unformat_input_t * input, { if (st) { - srt = &st->session_rules[transport_proto]; - session_rules_table_cli_dump (vm, srt, FIB_PROTOCOL_IP4); - session_rules_table_cli_dump (vm, srt, FIB_PROTOCOL_IP6); + session_rules_table_cli_dump (vm, st->srtg_handle, transport_proto, + FIB_PROTOCOL_IP4); + session_rules_table_cli_dump (vm, st->srtg_handle, transport_proto, + FIB_PROTOCOL_IP6); } } else @@ -1772,18 +1812,14 @@ show_session_rules_command_fn (vlib_main_t * vm, unformat_input_t * input, st = session_table_get_for_fib_index (FIB_PROTOCOL_IP4, app_ns->ip4_fib_index); if (st) - { - srt = &st->session_rules[transport_proto]; - session_rules_table_cli_dump (vm, srt, FIB_PROTOCOL_IP4); - } + session_rules_table_cli_dump (vm, st->srtg_handle, transport_proto, + FIB_PROTOCOL_IP4); st = session_table_get_for_fib_index (FIB_PROTOCOL_IP6, app_ns->ip6_fib_index); if (st) - { - srt = &st->session_rules[transport_proto]; - session_rules_table_cli_dump (vm, srt, FIB_PROTOCOL_IP6); - } + session_rules_table_cli_dump (vm, st->srtg_handle, transport_proto, + FIB_PROTOCOL_IP6); } done: vec_free (ns_id); diff --git a/src/vnet/session/session_lookup.h b/src/vnet/session/session_lookup.h index 95fcca6ff69..9f56af20a87 100644 --- a/src/vnet/session/session_lookup.h +++ b/src/vnet/session/session_lookup.h @@ -19,6 +19,8 @@ #include <vnet/session/session_table.h> #include <vnet/session/session_types.h> #include <vnet/session/application_namespace.h> +#include <vnet/fib/fib_table.h> +#include <vnet/fib/fib_source.h> #define HALF_OPEN_LOOKUP_INVALID_VALUE ((u64)~0) @@ -115,6 +117,17 @@ typedef enum _session_rule_scope SESSION_RULE_SCOPE_LOCAL = 2, } session_rule_scope_e; +typedef struct _session_rules_table_add_del_args +{ + fib_prefix_t lcl; + fib_prefix_t rmt; + u16 lcl_port; + u16 rmt_port; + u32 action_index; + u8 *tag; + u8 is_add; +} session_rule_table_add_del_args_t; + typedef struct _session_rule_add_del_args { /** @@ -140,6 +153,8 @@ session_error_t vnet_session_rule_add_del (session_rule_add_del_args_t *args); void session_lookup_set_tables_appns (app_namespace_t * app_ns); void session_lookup_init (void); +session_table_t *session_table_get_for_fib_index (u32 fib_proto, + u32 fib_index); #endif /* SRC_VNET_SESSION_SESSION_LOOKUP_H_ */ diff --git a/src/vnet/session/session_rules_table.c b/src/vnet/session/session_rules_table.c index d15df48d7b5..acb575b0f7c 100644 --- a/src/vnet/session/session_rules_table.c +++ b/src/vnet/session/session_rules_table.c @@ -17,8 +17,23 @@ #include <vnet/session/mma_template.c> #include <vnet/session/mma_40.h> #include <vnet/session/mma_template.c> -#include <vnet/session/session_rules_table.h> #include <vnet/session/transport.h> +#include <vnet/session/session.h> +#include <vnet/session/session_table.h> +#include <vnet/session/session_rules_table.h> +#include <vnet/session/session_sdl.h> + +VLIB_REGISTER_LOG_CLASS (session_rt_log, static) = { .class_name = "session", + .subclass_name = "rt" }; + +#define log_debug(fmt, ...) \ + vlib_log_debug (session_rt_log.class, "%s: " fmt, __func__, __VA_ARGS__) +#define log_warn(fmt, ...) \ + vlib_log_warn (session_rt_log.class, fmt, __VA_ARGS__) +#define log_err(fmt, ...) vlib_log_err (session_rt_log.class, fmt, __VA_ARGS__) + +static session_rules_table_group_t *srt_instances; +const session_rt_engine_vft_t *session_rt_engine_vft; u32 session_rule_tag_key_index (u32 ri, u8 is_ip4) @@ -119,13 +134,25 @@ fib_pref_normalize (fib_prefix_t * pref) } u8 * +format_session_rule_tag (u8 *s, va_list *args) +{ + static u8 *null_tag = 0; + u8 *tag = va_arg (*args, u8 *); + + if (!null_tag) + null_tag = format (0, "none"); + s = format (s, "%v", (tag != 0) ? tag : null_tag); + return s; +} + +u8 * format_session_rule4 (u8 * s, va_list * args) { session_rules_table_t *srt = va_arg (*args, session_rules_table_t *); mma_rule_16_t *sr = va_arg (*args, mma_rule_16_t *); session_mask_or_match_4_t *mask, *match; mma_rules_table_16_t *srt4; - u8 *tag = 0, *null_tag = format (0, "none"); + u8 *tag = 0; u32 ri; int i; @@ -135,20 +162,18 @@ format_session_rule4 (u8 * s, va_list * args) match = (session_mask_or_match_4_t *) & sr->match; mask = (session_mask_or_match_4_t *) & sr->mask; - s = format (s, "[%d] rule: %U/%d %d %U/%d %d action: %d tag: %v", ri, + s = format (s, "[%d] rule: %U/%d %d %U/%d %d action: %d tag: %U", ri, format_ip4_address, &match->lcl_ip, - ip4_mask_to_preflen (&mask->lcl_ip), - clib_net_to_host_u16 (match->lcl_port), format_ip4_address, - &match->rmt_ip, ip4_mask_to_preflen (&mask->rmt_ip), - clib_net_to_host_u16 (match->rmt_port), sr->action_index, - tag ? tag : null_tag); + ip4_mask_to_preflen (&mask->lcl_ip), match->lcl_port, + format_ip4_address, &match->rmt_ip, + ip4_mask_to_preflen (&mask->rmt_ip), match->rmt_port, + sr->action_index, format_session_rule_tag, tag); if (vec_len (sr->next_indices)) { s = format (s, "\n children: "); for (i = 0; i < vec_len (sr->next_indices); i++) s = format (s, "%d ", sr->next_indices[i]); } - vec_free (null_tag); return s; } @@ -159,7 +184,7 @@ format_session_rule6 (u8 * s, va_list * args) mma_rule_40_t *sr = va_arg (*args, mma_rule_40_t *); session_mask_or_match_6_t *mask, *match; mma_rules_table_40_t *srt6; - u8 *tag = 0, *null_tag = format (0, "none"); + u8 *tag = 0; u32 ri; int i; @@ -169,20 +194,18 @@ format_session_rule6 (u8 * s, va_list * args) match = (session_mask_or_match_6_t *) & sr->match; mask = (session_mask_or_match_6_t *) & sr->mask; - s = format (s, "[%d] rule: %U/%d %d %U/%d %d action: %d tag: %v", ri, + s = format (s, "[%d] rule: %U/%d %d %U/%d %d action: %d tag: %U", ri, format_ip6_address, &match->lcl_ip, - ip6_mask_to_preflen (&mask->lcl_ip), - clib_net_to_host_u16 (match->lcl_port), format_ip6_address, - &match->rmt_ip, ip6_mask_to_preflen (&mask->rmt_ip), - clib_net_to_host_u16 (match->rmt_port), sr->action_index, - tag ? tag : null_tag); + ip6_mask_to_preflen (&mask->lcl_ip), match->lcl_port, + format_ip6_address, &match->rmt_ip, + ip6_mask_to_preflen (&mask->rmt_ip), match->rmt_port, + sr->action_index, format_session_rule_tag, tag); if (vec_len (sr->next_indices)) { s = format (s, "\n children: "); for (i = 0; i < vec_len (sr->next_indices); i++) s = format (s, "%d ", sr->next_indices[i]); } - vec_free (null_tag); return s; } @@ -313,11 +336,10 @@ session_rules_table_alloc_rule_40 (mma_rules_table_40_t * srt, return rule; } -u32 -session_rules_table_lookup_rule4 (session_rules_table_t * srt, - ip4_address_t * lcl_ip, - ip4_address_t * rmt_ip, u16 lcl_port, - u16 rmt_port) +static u32 +session_rules_table_lookup_rule4 (session_rules_table_t *srt, + ip4_address_t *lcl_ip, ip4_address_t *rmt_ip, + u16 lcl_port, u16 rmt_port) { mma_rules_table_16_t *srt4 = &srt->session_rules_tables_16; session_mask_or_match_4_t key = { @@ -326,16 +348,20 @@ session_rules_table_lookup_rule4 (session_rules_table_t * srt, .lcl_port = lcl_port, .rmt_port = rmt_port, }; + + if (srt4->rules == 0) + return SESSION_TABLE_INVALID_INDEX; return mma_rules_table_lookup_rule_16 (srt4, (mma_mask_or_match_16_t *) & key, srt4->root_index); } u32 -session_rules_table_lookup4 (session_rules_table_t * srt, - ip4_address_t * lcl_ip, ip4_address_t * rmt_ip, - u16 lcl_port, u16 rmt_port) +session_rules_table_lookup4_ (u32 srtg_handle, u32 proto, + ip4_address_t *lcl_ip, ip4_address_t *rmt_ip, + u16 lcl_port, u16 rmt_port) { + session_rules_table_t *srt = srtg_handle_to_srt (srtg_handle, proto); mma_rules_table_16_t *srt4 = &srt->session_rules_tables_16; session_mask_or_match_4_t key = { .lcl_ip.as_u32 = lcl_ip->as_u32, @@ -343,21 +369,36 @@ session_rules_table_lookup4 (session_rules_table_t * srt, .lcl_port = lcl_port, .rmt_port = rmt_port, }; + + if (srt4->rules == 0) + return SESSION_TABLE_INVALID_INDEX; return mma_rules_table_lookup_16 (srt4, (mma_mask_or_match_16_t *) & key, srt4->root_index); } -u32 -session_rules_table_lookup_rule6 (session_rules_table_t * srt, - ip6_address_t * lcl_ip, - ip6_address_t * rmt_ip, u16 lcl_port, - u16 rmt_port) +session_rules_table_t * +srtg_handle_to_srt (u32 srtg_handle, u32 proto) +{ + session_rules_table_group_t *srtg = + pool_elt_at_index (srt_instances, srtg_handle); + session_rules_table_t *srt = &srtg->session_rules[proto]; + + return srt; +} + +static u32 +session_rules_table_lookup_rule6 (session_rules_table_t *srt, + ip6_address_t *lcl_ip, ip6_address_t *rmt_ip, + u16 lcl_port, u16 rmt_port) { mma_rules_table_40_t *srt6 = &srt->session_rules_tables_40; session_mask_or_match_6_t key = { .lcl_port = lcl_port, .rmt_port = rmt_port, }; + + if (srt6->rules == 0) + return SESSION_TABLE_INVALID_INDEX; clib_memcpy_fast (&key.lcl_ip, lcl_ip, sizeof (*lcl_ip)); clib_memcpy_fast (&key.rmt_ip, rmt_ip, sizeof (*rmt_ip)); return mma_rules_table_lookup_rule_40 (srt6, @@ -366,15 +407,19 @@ session_rules_table_lookup_rule6 (session_rules_table_t * srt, } u32 -session_rules_table_lookup6 (session_rules_table_t * srt, - ip6_address_t * lcl_ip, ip6_address_t * rmt_ip, - u16 lcl_port, u16 rmt_port) +session_rules_table_lookup6_ (u32 srtg_handle, u32 proto, + ip6_address_t *lcl_ip, ip6_address_t *rmt_ip, + u16 lcl_port, u16 rmt_port) { + session_rules_table_t *srt = srtg_handle_to_srt (srtg_handle, proto); mma_rules_table_40_t *srt6 = &srt->session_rules_tables_40; session_mask_or_match_6_t key = { .lcl_port = lcl_port, .rmt_port = rmt_port, }; + + if (srt6->rules == 0) + return SESSION_TABLE_INVALID_INDEX; clib_memcpy_fast (&key.lcl_ip, lcl_ip, sizeof (*lcl_ip)); clib_memcpy_fast (&key.rmt_ip, rmt_ip, sizeof (*rmt_ip)); return mma_rules_table_lookup_40 (srt6, (mma_mask_or_match_40_t *) & key, @@ -390,9 +435,10 @@ session_rules_table_lookup6 (session_rules_table_t * srt, * @return 0 if success, session_error_t error otherwise */ session_error_t -session_rules_table_add_del (session_rules_table_t *srt, - session_rule_table_add_del_args_t *args) +session_rules_table_add_del_ (u32 srtg_handle, u32 proto, + session_rule_table_add_del_args_t *args) { + session_rules_table_t *srt = srtg_handle_to_srt (srtg_handle, proto); u8 fib_proto = args->rmt.fp_proto, *rt; u32 ri_from_tag, ri; int rv; @@ -515,50 +561,90 @@ session_rules_table_add_del (session_rules_table_t *srt, } void -session_rules_table_free (session_rules_table_t *srt) +session_rules_table_free_ (session_table_t *st, u8 fib_proto) +{ + session_rules_table_group_t *srtg = + pool_elt_at_index (srt_instances, st->srtg_handle); + session_rules_table_t *srt; + + vec_foreach (srt, srtg->session_rules) + { + mma_rules_table_free_16 (&srt->session_rules_tables_16); + mma_rules_table_free_40 (&srt->session_rules_tables_40); + + hash_free (srt->tags_by_rules); + hash_free (srt->rules_by_tag); + } + srtg_instance_free (st); +} + +void +srtg_instance_free (session_table_t *st) { - mma_rules_table_free_16 (&srt->session_rules_tables_16); - mma_rules_table_free_40 (&srt->session_rules_tables_40); + session_rules_table_group_t *srtg = + pool_elt_at_index (srt_instances, st->srtg_handle); - hash_free (srt->tags_by_rules); - hash_free (srt->rules_by_tag); + vec_free (srtg->session_rules); + pool_put (srt_instances, srtg); + st->srtg_handle = SESSION_SRTG_HANDLE_INVALID; +} + +session_rules_table_group_t * +srtg_instance_alloc (session_table_t *st, u32 n_proto) +{ + session_rules_table_group_t *srtg; + + pool_get (srt_instances, srtg); + vec_validate (srtg->session_rules, n_proto); + st->srtg_handle = srtg - srt_instances; + return (srtg); } void -session_rules_table_init (session_rules_table_t * srt) +session_rules_table_init_ (session_table_t *st, u8 fib_proto) { mma_rules_table_16_t *srt4; mma_rules_table_40_t *srt6; mma_rule_16_t *rule4; mma_rule_40_t *rule6; fib_prefix_t null_prefix; + session_rules_table_t *srt; + session_rules_table_group_t *srtg; - clib_memset (&null_prefix, 0, sizeof (null_prefix)); + srtg = srtg_instance_alloc (st, TRANSPORT_N_PROTOS - 1); - srt4 = &srt->session_rules_tables_16; - rule4 = session_rules_table_alloc_rule_16 (srt4, &null_prefix, 0, - &null_prefix, 0); - rule4->action_index = SESSION_RULES_TABLE_INVALID_INDEX; - srt4->root_index = mma_rules_table_rule_index_16 (srt4, rule4); - srt4->rule_cmp_fn = rule_cmp_16; + clib_memset (&null_prefix, 0, sizeof (null_prefix)); + vec_foreach (srt, srtg->session_rules) + { + srt4 = &srt->session_rules_tables_16; - srt6 = &srt->session_rules_tables_40; - rule6 = session_rules_table_alloc_rule_40 (srt6, &null_prefix, 0, - &null_prefix, 0); - rule6->action_index = SESSION_RULES_TABLE_INVALID_INDEX; - srt6->root_index = mma_rules_table_rule_index_40 (srt6, rule6); - srt6->rule_cmp_fn = rule_cmp_40; + ASSERT (srt4->rules == 0); + rule4 = session_rules_table_alloc_rule_16 (srt4, &null_prefix, 0, + &null_prefix, 0); + rule4->action_index = SESSION_RULES_TABLE_INVALID_INDEX; + srt4->root_index = mma_rules_table_rule_index_16 (srt4, rule4); + srt4->rule_cmp_fn = rule_cmp_16; - srt->rules_by_tag = hash_create_vec (0, sizeof (u8), sizeof (uword)); - srt->tags_by_rules = hash_create (0, sizeof (uword)); + srt6 = &srt->session_rules_tables_40; + ASSERT (srt6->rules == 0); + rule6 = session_rules_table_alloc_rule_40 (srt6, &null_prefix, 0, + &null_prefix, 0); + rule6->action_index = SESSION_RULES_TABLE_INVALID_INDEX; + srt6->root_index = mma_rules_table_rule_index_40 (srt6, rule6); + srt6->rule_cmp_fn = rule_cmp_40; + + srt->rules_by_tag = hash_create_vec (0, sizeof (u8), sizeof (uword)); + srt->tags_by_rules = hash_create (0, sizeof (uword)); + } } void -session_rules_table_show_rule (vlib_main_t * vm, session_rules_table_t * srt, - ip46_address_t * lcl_ip, u16 lcl_port, - ip46_address_t * rmt_ip, u16 rmt_port, - u8 is_ip4) +session_rules_table_show_rule_ (vlib_main_t *vm, u32 srtg_handle, u32 proto, + ip46_address_t *lcl_ip, u16 lcl_port, + ip46_address_t *rmt_ip, u16 rmt_port, + u8 is_ip4) { + session_rules_table_t *srt = srtg_handle_to_srt (srtg_handle, proto); mma_rules_table_16_t *srt4; mma_rules_table_40_t *srt6; mma_rule_16_t *sr4; @@ -599,9 +685,10 @@ session_rules_table_show_rule (vlib_main_t * vm, session_rules_table_t * srt, } void -session_rules_table_cli_dump (vlib_main_t * vm, session_rules_table_t * srt, - u8 fib_proto) +session_rules_table_cli_dump_ (vlib_main_t *vm, u32 srtg_handle, u32 proto, + u8 fib_proto) { + session_rules_table_t *srt = srtg_handle_to_srt (srtg_handle, proto); if (fib_proto == FIB_PROTOCOL_IP4) { mma_rules_table_16_t *srt4; @@ -628,6 +715,108 @@ session_rules_table_cli_dump (vlib_main_t * vm, session_rules_table_t * srt, } } +static const session_rt_engine_vft_t session_rules_table_vft = { + .backend_engine = RT_BACKEND_ENGINE_RULE_TABLE, + .table_lookup4 = session_rules_table_lookup4_, + .table_lookup6 = session_rules_table_lookup6_, + .table_cli_dump = session_rules_table_cli_dump_, + .table_show_rule = session_rules_table_show_rule_, + .table_add_del = session_rules_table_add_del_, + .table_init = session_rules_table_init_, + .table_free = session_rules_table_free_, +}; + +static void +session_rules_table_app_namespace_walk_cb (app_namespace_t *app_ns, void *ctx) +{ + u32 fib_index, table_index; + session_table_t *st; + + log_debug ("disable app_ns %s", app_ns->ns_id); + st = session_table_get (app_ns->local_table_index); + if (st) + session_rules_table_free (st, FIB_PROTOCOL_MAX); + + fib_index = app_namespace_get_fib_index (app_ns, FIB_PROTOCOL_IP4); + table_index = session_lookup_get_index_for_fib (FIB_PROTOCOL_IP4, fib_index); + st = session_table_get (table_index); + if (st) + session_rules_table_free (st, FIB_PROTOCOL_IP4); + + fib_index = app_namespace_get_fib_index (app_ns, FIB_PROTOCOL_IP6); + table_index = session_lookup_get_index_for_fib (FIB_PROTOCOL_IP6, fib_index); + st = session_table_get (table_index); + if (st) + session_rules_table_free (st, FIB_PROTOCOL_IP6); +} + +clib_error_t * +session_rules_table_enable_disable (int enable) +{ + clib_error_t *error; + + if (enable) + error = session_rule_table_register_engine (&session_rules_table_vft); + else + { + app_namespace_walk (session_rules_table_app_namespace_walk_cb, 0); + error = session_rule_table_deregister_engine (&session_rules_table_vft); + } + + return error; +} + +clib_error_t * +session_rt_backend_enable_disable (session_rt_engine_type_t rt_engine_type) +{ + session_main_t *smm = &session_main; + clib_error_t *error = 0; + + if (rt_engine_type < RT_BACKEND_ENGINE_DISABLE || + rt_engine_type > RT_BACKEND_ENGINE_SDL) + return clib_error_return (0, "invalid rt-backend %d", rt_engine_type); + + if (rt_engine_type == RT_BACKEND_ENGINE_SDL) + error = session_sdl_enable_disable (1); + else if (rt_engine_type == RT_BACKEND_ENGINE_RULE_TABLE) + error = session_rules_table_enable_disable (1); + else if (rt_engine_type == RT_BACKEND_ENGINE_DISABLE) + { + if (session_sdl_is_enabled ()) + error = session_sdl_enable_disable (0); + else if (session_rule_table_is_enabled ()) + error = session_rules_table_enable_disable (0); + } + + if (!error) + smm->rt_engine_type = rt_engine_type; + return error; +} + +clib_error_t * +session_rule_table_register_engine (const session_rt_engine_vft_t *vft) +{ + if (session_rt_engine_vft == vft) + return 0; + if (session_rt_engine_vft) + return clib_error_return (0, "session rule engine is already registered"); + + session_rt_engine_vft = vft; + return 0; +} + +clib_error_t * +session_rule_table_deregister_engine (const session_rt_engine_vft_t *vft) +{ + if (session_rt_engine_vft == vft) + session_rt_engine_vft = 0; + else + return clib_error_return ( + 0, "session rule engine is not registered to this engine"); + + return 0; +} + /* * fd.io coding-style-patch-verification: ON * diff --git a/src/vnet/session/session_rules_table.h b/src/vnet/session/session_rules_table.h index 010d50a6398..a61438bb9fd 100644 --- a/src/vnet/session/session_rules_table.h +++ b/src/vnet/session/session_rules_table.h @@ -22,6 +22,10 @@ #include <vnet/session/transport.h> #include <vnet/session/mma_16.h> #include <vnet/session/mma_40.h> +#include <vnet/session/session_lookup.h> +#include <vnet/session/session_table.h> + +#define SESSION_SRTG_HANDLE_INVALID ~0 typedef CLIB_PACKED (struct { @@ -58,29 +62,36 @@ typedef CLIB_PACKED (struct #define SESSION_RULES_TABLE_ACTION_DROP (MMA_TABLE_INVALID_INDEX - 1) #define SESSION_RULES_TABLE_ACTION_ALLOW (MMA_TABLE_INVALID_INDEX - 2) -typedef struct _session_rules_table_add_del_args -{ - fib_prefix_t lcl; - fib_prefix_t rmt; - u16 lcl_port; - u16 rmt_port; - u32 action_index; - u8 *tag; - u8 is_add; -} session_rule_table_add_del_args_t; - typedef struct _rule_tag { u8 *tag; } session_rule_tag_t; +typedef struct session_sdl_block +{ + u32 ip_table_id; + u32 ip6_table_id; + u32 ip_fib_index; + u32 ip6_fib_index; +} session_sdl_block_t; + typedef struct _session_rules_table_t { - /** - * Per fib proto session rules tables - */ - mma_rules_table_16_t session_rules_tables_16; - mma_rules_table_40_t session_rules_tables_40; + union + { + /** + * Per fib proto session rules tables + */ + struct + { + mma_rules_table_16_t session_rules_tables_16; + mma_rules_table_40_t session_rules_tables_40; + }; + /** + * sdl table + */ + struct session_sdl_block sdl_block; + }; /** * Hash table that maps tags to rules */ @@ -95,28 +106,163 @@ typedef struct _session_rules_table_t uword *tags_by_rules; } session_rules_table_t; -u32 session_rules_table_lookup4 (session_rules_table_t * srt, - ip4_address_t * lcl_ip, - ip4_address_t * rmt_ip, u16 lcl_port, - u16 rmt_port); -u32 session_rules_table_lookup6 (session_rules_table_t * srt, - ip6_address_t * lcl_ip, - ip6_address_t * rmt_ip, u16 lcl_port, - u16 rmt_port); -void session_rules_table_cli_dump (vlib_main_t * vm, - session_rules_table_t * srt, u8 fib_proto); -void session_rules_table_show_rule (vlib_main_t * vm, - session_rules_table_t * srt, - ip46_address_t * lcl_ip, u16 lcl_port, - ip46_address_t * rmt_ip, u16 rmt_port, - u8 is_ip4); +typedef struct _session_rules_table_group_t +{ + session_rules_table_t *session_rules; +} session_rules_table_group_t; + session_error_t -session_rules_table_add_del (session_rules_table_t *srt, - session_rule_table_add_del_args_t *args); +session_rules_table_add_del_ (u32 srtg_handle, u32 proto, + session_rule_table_add_del_args_t *args); u8 *session_rules_table_rule_tag (session_rules_table_t * srt, u32 ri, u8 is_ip4); -void session_rules_table_init (session_rules_table_t * srt); -void session_rules_table_free (session_rules_table_t *srt); +void session_rules_table_init_ (struct _session_lookup_table *st, + u8 fib_proto); +void session_rules_table_free_ (struct _session_lookup_table *st, + u8 fib_proto); + +typedef u32 (*rules_table_lookup4) (u32 srtg_handle, u32 proto, + ip4_address_t *lcl_ip, + ip4_address_t *rmt_ip, u16 lcl_port, + u16 rmt_port); +typedef u32 (*rules_table_lookup6) (u32 srtg_handle, u32 proto, + ip6_address_t *lcl_ip, + ip6_address_t *rmt_ip, u16 lcl_port, + u16 rmt_port); +typedef void (*rules_table_cli_dump) (vlib_main_t *vm, u32 srtg_handle, + u32 proto, u8 fib_proto); +typedef void (*rules_table_show_rule) (vlib_main_t *vm, u32 srtg_handle, + u32 proto, ip46_address_t *lcl_ip, + u16 lcl_port, ip46_address_t *rmt_ip, + u16 rmt_port, u8 is_ip4); +typedef session_error_t (*rules_table_add_del) ( + u32 srtg_handle, u32 proto, session_rule_table_add_del_args_t *args); +typedef void (*rules_table_init) (struct _session_lookup_table *st, + u8 fib_proto); +typedef void (*rules_table_free) (struct _session_lookup_table *st, + u8 fib_proto); + +#define foreach_session_rt_engine_vft_method_name \ + _ (lookup4) \ + _ (lookup6) \ + _ (cli_dump) \ + _ (show_rule) \ + _ (add_del) \ + _ (init) \ + _ (free) + +#define _(name) rules_table_##name table_##name; +typedef struct session_rt_engine_vft +{ + u32 backend_engine; + foreach_session_rt_engine_vft_method_name +} session_rt_engine_vft_t; +#undef _ + +extern u8 *format_session_rule_tag (u8 *s, va_list *args); +extern u8 *session_rules_table_rule_tag (session_rules_table_t *srt, u32 ri, + u8 is_ip4); +extern u32 session_rules_table_rule_for_tag (session_rules_table_t *srt, + u8 *tag); +extern void session_rules_table_add_tag (session_rules_table_t *srt, u8 *tag, + u32 rule_index, u8 is_ip4); +extern void session_rules_table_del_tag (session_rules_table_t *srt, u8 *tag, + u8 is_ip4); + +extern const session_rt_engine_vft_t *session_rt_engine_vft; +extern clib_error_t *session_rules_table_enable_disable (int enable); +extern clib_error_t * +session_rt_backend_enable_disable (session_rt_engine_type_t rt_engine_type); + +static_always_inline void +session_rules_table_init (struct _session_lookup_table *st, u8 fib_proto) +{ + if (!session_rt_engine_vft) + return; + if (st->srtg_handle != SESSION_SRTG_HANDLE_INVALID) + return; + session_rt_engine_vft->table_init (st, fib_proto); +} + +static_always_inline void +session_rules_table_free (struct _session_lookup_table *st, u8 fib_proto) +{ + if (!session_rt_engine_vft) + return; + if (st->srtg_handle == SESSION_SRTG_HANDLE_INVALID) + return; + session_rt_engine_vft->table_free (st, fib_proto); +} + +static_always_inline void +session_rules_table_show_rule (vlib_main_t *vm, u32 srtg_handle, u32 proto, + ip46_address_t *lcl_ip, u16 lcl_port, + ip46_address_t *rmt_ip, u16 rmt_port, u8 is_ip4) +{ + if (!session_rt_engine_vft) + return; + if (srtg_handle == SESSION_SRTG_HANDLE_INVALID) + return; + session_rt_engine_vft->table_show_rule (vm, srtg_handle, proto, lcl_ip, + lcl_port, rmt_ip, rmt_port, is_ip4); +} + +static_always_inline u32 +session_rules_table_lookup6 (u32 srtg_handle, u32 proto, ip6_address_t *lcl_ip, + ip6_address_t *rmt_ip, u16 lcl_port, u16 rmt_port) +{ + if (!session_rt_engine_vft) + return SESSION_RULES_TABLE_ACTION_ALLOW; + if (srtg_handle == SESSION_SRTG_HANDLE_INVALID) + return SESSION_RULES_TABLE_ACTION_ALLOW; + return session_rt_engine_vft->table_lookup6 (srtg_handle, proto, lcl_ip, + rmt_ip, lcl_port, rmt_port); +} + +static_always_inline void +session_rules_table_cli_dump (vlib_main_t *vm, u32 srtg_handle, u32 proto, + u8 fib_proto) +{ + if (!session_rt_engine_vft) + return; + if (srtg_handle == SESSION_SRTG_HANDLE_INVALID) + return; + session_rt_engine_vft->table_cli_dump (vm, srtg_handle, proto, fib_proto); +} + +static_always_inline u32 +session_rules_table_lookup4 (u32 srtg_handle, u32 proto, ip4_address_t *lcl_ip, + ip4_address_t *rmt_ip, u16 lcl_port, u16 rmt_port) +{ + if (!session_rt_engine_vft) + return SESSION_RULES_TABLE_ACTION_ALLOW; + if (srtg_handle == SESSION_SRTG_HANDLE_INVALID) + return SESSION_RULES_TABLE_ACTION_ALLOW; + return session_rt_engine_vft->table_lookup4 (srtg_handle, proto, lcl_ip, + rmt_ip, lcl_port, rmt_port); +} + +static_always_inline session_error_t +session_rules_table_add_del (u32 srtg_handle, u32 proto, + session_rule_table_add_del_args_t *args) +{ + if (!session_rt_engine_vft) + return SESSION_E_NOSUPPORT; + if (srtg_handle == SESSION_SRTG_HANDLE_INVALID) + return SESSION_E_NOSUPPORT; + return session_rt_engine_vft->table_add_del (srtg_handle, proto, args); +} + +clib_error_t * +session_rule_table_register_engine (const session_rt_engine_vft_t *vft); +clib_error_t * +session_rule_table_deregister_engine (const session_rt_engine_vft_t *vft); + +extern session_rules_table_t *srtg_handle_to_srt (u32 srtg_handle, u32 proto); +extern session_rules_table_group_t *srtg_instance_alloc (session_table_t *st, + u32 n_proto); +extern void srtg_instance_free (session_table_t *st); + #endif /* SRC_VNET_SESSION_SESSION_RULES_TABLE_H_ */ /* * fd.io coding-style-patch-verification: ON diff --git a/src/vnet/session/session_sdl.c b/src/vnet/session/session_sdl.c new file mode 100644 index 00000000000..45ab705fb62 --- /dev/null +++ b/src/vnet/session/session_sdl.c @@ -0,0 +1,768 @@ +/* + * Copyright (c) 2024 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <vnet/session/session.h> +#include <vnet/ip/ip4_forward.h> +#include <vnet/ip/ip6_forward.h> +#include <vnet/session/session_rules_table.h> +#include <vnet/session/session_sdl.h> + +VLIB_REGISTER_LOG_CLASS (session_sdl_log, static) = { .class_name = "session", + .subclass_name = "sdl" }; + +#define log_debug(fmt, ...) \ + vlib_log_debug (session_sdl_log.class, "%s: " fmt, __func__, __VA_ARGS__) +#define log_warn(fmt, ...) \ + vlib_log_warn (session_sdl_log.class, fmt, __VA_ARGS__) +#define log_err(fmt, ...) \ + vlib_log_err (session_sdl_log.class, fmt, __VA_ARGS__) + +static fib_source_t sdl_fib_src; +static dpo_type_t sdl_dpo_type; + +const static char *const *const session_sdl_dpo_nodes[DPO_PROTO_NUM] = { + [DPO_PROTO_IP4] = (const char *const[]){ "ip4-drop", 0 }, + [DPO_PROTO_IP6] = (const char *const[]){ "ip6-drop", 0 }, +}; + +static fib_route_path_t * +session_sdl_fib_create_route_paths (u32 fib_index, dpo_proto_t dpo_proto) +{ + fib_route_path_t *paths = 0; + fib_route_path_t path = { + .frp_proto = dpo_proto, + .frp_flags = FIB_ROUTE_PATH_EXCLUSIVE, + .frp_fib_index = fib_index, + .frp_sw_if_index = ~0, + .frp_weight = 1, + }; + vec_add1 (paths, path); + return paths; +} + +static void +session_sdl_dpo_lock (dpo_id_t *dpo) +{ +} + +static void +session_sdl_dpo_unlock (dpo_id_t *dpo) +{ +} + +static u8 * +format_session_sdl_dpo (u8 *s, va_list *va) +{ + index_t index = va_arg (*va, index_t); + + return format (s, "sdl: [index: %u, deny]", index); +} + +static const dpo_vft_t session_sdl_dpo_vft = { + .dv_lock = session_sdl_dpo_lock, + .dv_unlock = session_sdl_dpo_unlock, + .dv_format = format_session_sdl_dpo, +}; + +static u32 +session_sdl_lookup6 (u32 srtg_handle, u32 proto, ip6_address_t *lcl_ip, + ip6_address_t *rmt_ip, u16 lcl_port, u16 rmt_port) +{ + session_rules_table_t *srt = srtg_handle_to_srt (srtg_handle, 0); + session_sdl_block_t *sdlb = &srt->sdl_block; + index_t lbi; + const dpo_id_t *dpo; + + if (sdlb->ip6_fib_index == ~0) + return SESSION_TABLE_INVALID_INDEX; + lbi = ip6_fib_table_fwding_lookup (sdlb->ip6_fib_index, lcl_ip); + dpo = load_balance_get_fwd_bucket (load_balance_get (lbi), 0); + if (dpo->dpoi_type != sdl_dpo_type) + return SESSION_TABLE_INVALID_INDEX; + return (dpo->dpoi_index); +} + +static u32 +session_sdl_lookup4 (u32 srtg_handle, u32 proto, ip4_address_t *lcl_ip, + ip4_address_t *rmt_ip, u16 lcl_port, u16 rmt_port) +{ + session_rules_table_t *srt = srtg_handle_to_srt (srtg_handle, 0); + session_sdl_block_t *sdlb = &srt->sdl_block; + index_t lbi; + const dpo_id_t *dpo; + + if (sdlb->ip_fib_index == ~0) + return SESSION_TABLE_INVALID_INDEX; + lbi = ip4_fib_forwarding_lookup (sdlb->ip_fib_index, lcl_ip); + dpo = load_balance_get_fwd_bucket (load_balance_get (lbi), 0); + if (dpo->dpoi_type != sdl_dpo_type) + return SESSION_TABLE_INVALID_INDEX; + return (dpo->dpoi_index); +} + +typedef struct session_sdl4_fib_show_walk_ctx_t_ +{ + fib_node_index_t *ifsw_indicies; +} session_sdl4_fib_show_walk_ctx_t; + +static fib_table_walk_rc_t +session_sdl4_fib_show_walk_cb (fib_node_index_t fei, void *arg) +{ + session_sdl4_fib_show_walk_ctx_t *ctx = arg; + + vec_add1 (ctx->ifsw_indicies, fei); + + return (FIB_TABLE_WALK_CONTINUE); +} + +typedef struct session_sdl6_fib_show_ctx_t_ +{ + fib_node_index_t *entries; +} session_sdl6_fib_show_ctx_t; + +static fib_table_walk_rc_t +session_sdl6_fib_table_show_walk (fib_node_index_t fei, void *arg) +{ + session_sdl6_fib_show_ctx_t *ctx = arg; + + vec_add1 (ctx->entries, fei); + + return (FIB_TABLE_WALK_CONTINUE); +} + +static void +session_sdl_fib_table_show (u32 fei, ip46_address_t *lcl_ip, u16 fp_len, + u32 action_index, u32 fp_proto, u8 *tag, + void *args) +{ + vlib_main_t *vm = args; + u32 type = (fp_proto == FIB_PROTOCOL_IP4) ? IP46_TYPE_IP4 : IP46_TYPE_IP6; + + vlib_cli_output (vm, "[%d] rule: %U/%d action: %d tag %U", fei, + format_ip46_address, lcl_ip, type, fp_len, action_index, + format_session_rule_tag, tag); +} + +static void +session_sdl_cli_dump (vlib_main_t *vm, u32 srtg_handle, u32 proto, + u8 fib_proto) +{ + session_rules_table_t *srt = srtg_handle_to_srt (srtg_handle, 0); + session_sdl_block_t *sdlb = &srt->sdl_block; + + if (fib_proto == FIB_PROTOCOL_IP4) + { + vlib_cli_output (vm, "IP4 rules, fib index %d", sdlb->ip_fib_index); + session_sdl_table_walk4 (srtg_handle, session_sdl_fib_table_show, vm); + } + else if (fib_proto == FIB_PROTOCOL_IP6) + { + vlib_cli_output (vm, "IP6 rules, fib index %d", sdlb->ip6_fib_index); + session_sdl_table_walk6 (srtg_handle, session_sdl_fib_table_show, vm); + } +} + +static void +session_sdl4_fib_table_show_one (session_rules_table_t *srt, u32 fib_index, + vlib_main_t *vm, ip4_address_t *address, + u32 mask_len) +{ + ip4_fib_t *fib; + fib_node_index_t fei; + + fib = ip4_fib_get (fib_index); + fei = ip4_fib_table_lookup (fib, address, mask_len); + if (fei != FIB_NODE_INDEX_INVALID && fib_entry_is_sourced (fei, sdl_fib_src)) + { + u8 *tag = session_rules_table_rule_tag (srt, fei, 1); + fib_entry_t *fib_entry = fib_entry_get (fei); + fib_prefix_t pfx = fib_entry->fe_prefix; + index_t lbi = ip4_fib_forwarding_lookup (fib_index, &pfx.fp_addr.ip4); + const dpo_id_t *dpo = + load_balance_get_fwd_bucket (load_balance_get (lbi), 0); + + session_sdl_fib_table_show (fei, &pfx.fp_addr, pfx.fp_len, + dpo->dpoi_index, FIB_PROTOCOL_IP4, tag, vm); + } +} + +static void +session_sdl6_fib_table_show_one (session_rules_table_t *srt, u32 fib_index, + vlib_main_t *vm, ip6_address_t *address, + u32 mask_len) +{ + fib_node_index_t fei; + + fei = ip6_fib_table_lookup (fib_index, address, mask_len); + if (fei != FIB_NODE_INDEX_INVALID && fib_entry_is_sourced (fei, sdl_fib_src)) + { + u8 *tag = session_rules_table_rule_tag (srt, fei, 0); + fib_entry_t *fib_entry = fib_entry_get (fei); + fib_prefix_t pfx = fib_entry->fe_prefix; + index_t lbi = ip6_fib_table_fwding_lookup (fib_index, &pfx.fp_addr.ip6); + const dpo_id_t *dpo = + load_balance_get_fwd_bucket (load_balance_get (lbi), 0); + + session_sdl_fib_table_show (fei, &pfx.fp_addr, pfx.fp_len, + dpo->dpoi_index, FIB_PROTOCOL_IP6, tag, vm); + } +} + +static void +session_sdl_show_rule (vlib_main_t *vm, u32 srtg_handle, u32 proto, + ip46_address_t *lcl_ip, u16 lcl_port, + ip46_address_t *rmt_ip, u16 rmt_port, u8 is_ip4) +{ + session_rules_table_t *srt = srtg_handle_to_srt (srtg_handle, 0); + session_sdl_block_t *sdlb; + + sdlb = &srt->sdl_block; + if (is_ip4) + session_sdl4_fib_table_show_one (srt, sdlb->ip_fib_index, vm, &lcl_ip->ip4, + 32); + else + session_sdl6_fib_table_show_one (srt, sdlb->ip6_fib_index, vm, + &lcl_ip->ip6, 128); +} + +static void +session_sdl_table_init (session_table_t *st, u8 fib_proto) +{ + session_rules_table_t *srt; + session_sdl_block_t *sdlb; + u8 all = fib_proto > FIB_PROTOCOL_IP6 ? 1 : 0; + char name[80]; + app_namespace_t *app_ns = app_namespace_get (st->appns_index); + session_rules_table_group_t *srtg; + + /* Don't support local table */ + if (st->is_local == 1) + return; + + srtg = srtg_instance_alloc (st, 0); + srt = srtg->session_rules; + sdlb = &srt->sdl_block; + + if (fib_proto == FIB_PROTOCOL_IP4 || all) + { + snprintf (name, sizeof (name), "sdl4 %s", app_ns->ns_id); + sdlb->ip_table_id = ip_table_get_unused_id (FIB_PROTOCOL_IP4); + sdlb->ip_fib_index = fib_table_find_or_create_and_lock_w_name ( + FIB_PROTOCOL_IP4, sdlb->ip_table_id, sdl_fib_src, (const u8 *) name); + } + + if (fib_proto == FIB_PROTOCOL_IP6 || all) + { + snprintf (name, sizeof (name), "sdl6 %s", app_ns->ns_id); + sdlb->ip6_table_id = ip_table_get_unused_id (FIB_PROTOCOL_IP6); + sdlb->ip6_fib_index = fib_table_find_or_create_and_lock_w_name ( + FIB_PROTOCOL_IP6, sdlb->ip6_table_id, sdl_fib_src, (const u8 *) name); + } + + srt->rules_by_tag = hash_create_vec (0, sizeof (u8), sizeof (uword)); + srt->tags_by_rules = hash_create (0, sizeof (uword)); +} + +static void +session_sdl_table_free (session_table_t *st, u8 fib_proto) +{ + session_rules_table_t *srt = srtg_handle_to_srt (st->srtg_handle, 0); + session_sdl_block_t *sdlb; + u8 all = fib_proto > FIB_PROTOCOL_IP6 ? 1 : 0; + + ASSERT (st->is_local == 0); + sdlb = &srt->sdl_block; + if ((fib_proto == FIB_PROTOCOL_IP4 || all) && (sdlb->ip_fib_index != ~0)) + { + fib_table_flush (sdlb->ip_fib_index, FIB_PROTOCOL_IP4, sdl_fib_src); + fib_table_unlock (sdlb->ip_fib_index, FIB_PROTOCOL_IP4, sdl_fib_src); + } + if ((fib_proto == FIB_PROTOCOL_IP6 || all) && (sdlb->ip6_fib_index != ~0)) + { + fib_table_flush (sdlb->ip6_fib_index, FIB_PROTOCOL_IP6, sdl_fib_src); + fib_table_unlock (sdlb->ip6_fib_index, FIB_PROTOCOL_IP6, sdl_fib_src); + } + + hash_free (srt->tags_by_rules); + hash_free (srt->rules_by_tag); + + srtg_instance_free (st); +} + +static session_error_t +session_sdl_add_del (u32 srtg_handle, u32 proto, + session_rule_table_add_del_args_t *args) +{ + session_rules_table_t *srt = srtg_handle_to_srt (srtg_handle, 0); + session_sdl_block_t *sdlb = &srt->sdl_block; + u32 fib_index; + dpo_proto_t dpo_proto; + fib_route_path_t *paths = 0; + fib_prefix_t pfx = args->lcl; + session_error_t err = SESSION_E_NONE; + fib_node_index_t fei; + int is_ip4; + + if (!(args->lcl_port == 0 && args->rmt_port == 0 && + args->rmt.fp_addr.ip4.as_u32 == 0)) + return SESSION_E_NOSUPPORT; + + fei = session_rules_table_rule_for_tag (srt, args->tag); + if (args->is_add && fei != SESSION_RULES_TABLE_INVALID_INDEX) + return SESSION_E_INVALID; + + if (args->lcl.fp_proto == FIB_PROTOCOL_IP4) + { + fib_index = sdlb->ip_fib_index; + dpo_proto = DPO_PROTO_IP4; + is_ip4 = 1; + } + else + { + fib_index = sdlb->ip6_fib_index; + dpo_proto = DPO_PROTO_IP6; + is_ip4 = 0; + } + + paths = session_sdl_fib_create_route_paths (fib_index, dpo_proto); + if (args->is_add) + { + fei = fib_table_lookup_exact_match (fib_index, &pfx); + if (fei != FIB_NODE_INDEX_INVALID) + { + err = SESSION_E_IPINUSE; + goto done; + } + dpo_set (&paths->dpo, sdl_dpo_type, dpo_proto, args->action_index); + fei = fib_table_entry_path_add2 (fib_index, &pfx, sdl_fib_src, + FIB_ENTRY_FLAG_EXCLUSIVE, paths); + session_rules_table_add_tag (srt, args->tag, fei, is_ip4); + dpo_reset (&paths->dpo); + } + else + { + if (fei == SESSION_RULES_TABLE_INVALID_INDEX) + { + fei = fib_table_lookup_exact_match (fib_index, &pfx); + + if (fei == FIB_NODE_INDEX_INVALID) + { + err = SESSION_E_NOROUTE; + goto done; + } + } + + if (!fib_entry_is_sourced (fei, sdl_fib_src)) + { + err = SESSION_E_NOROUTE; + goto done; + } + + fib_entry_t *fib_entry = fib_entry_get (fei); + pfx = fib_entry->fe_prefix; + fib_table_entry_special_remove (fib_index, &pfx, sdl_fib_src); + session_rules_table_del_tag (srt, args->tag, is_ip4); + } +done: + vec_free (paths); + + return err; +} + +static const session_rt_engine_vft_t session_sdl_vft = { + .backend_engine = RT_BACKEND_ENGINE_SDL, + .table_lookup4 = session_sdl_lookup4, + .table_lookup6 = session_sdl_lookup6, + .table_cli_dump = session_sdl_cli_dump, + .table_show_rule = session_sdl_show_rule, + .table_add_del = session_sdl_add_del, + .table_init = session_sdl_table_init, + .table_free = session_sdl_table_free, +}; + +static void +session_sdl_fib_init (void) +{ + static u32 session_fib_inited = 0; + + if (session_fib_inited) + return; + session_fib_inited = 1; + sdl_fib_src = fib_source_allocate ("session sdl", FIB_SOURCE_PRIORITY_LOW, + FIB_SOURCE_BH_SIMPLE); + sdl_dpo_type = + dpo_register_new_type (&session_sdl_dpo_vft, session_sdl_dpo_nodes); +} + +static void +session_sdl_app_namespace_walk_cb (app_namespace_t *app_ns, void *ctx) +{ + u32 fib_index, table_index; + session_table_t *st; + + log_debug ("disable app_ns %s", app_ns->ns_id); + + fib_index = app_namespace_get_fib_index (app_ns, FIB_PROTOCOL_IP4); + table_index = session_lookup_get_index_for_fib (FIB_PROTOCOL_IP4, fib_index); + st = session_table_get (table_index); + if (st) + session_rules_table_free (st, FIB_PROTOCOL_IP4); + + fib_index = app_namespace_get_fib_index (app_ns, FIB_PROTOCOL_IP6); + table_index = session_lookup_get_index_for_fib (FIB_PROTOCOL_IP6, fib_index); + st = session_table_get (table_index); + if (st) + session_rules_table_free (st, FIB_PROTOCOL_IP6); +} + +clib_error_t * +session_sdl_enable_disable (int enable) +{ + clib_error_t *error = 0; + + if (enable) + { + error = session_rule_table_register_engine (&session_sdl_vft); + if (error) + { + log_err ("error in enabling sdl: %U", format_clib_error, error); + return error; + } + session_sdl_fib_init (); + } + else + { + app_namespace_walk (session_sdl_app_namespace_walk_cb, 0); + + error = session_rule_table_deregister_engine (&session_sdl_vft); + if (error) + log_err ("error in disabling sdl: %U", format_clib_error, error); + } + + return error; +} + +/* + * Source Deny List + */ +static clib_error_t * +session_sdl_command_fn (vlib_main_t *vm, unformat_input_t *input, + vlib_cli_command_t *cmd) +{ + u32 appns_index; + app_namespace_t *app_ns; + u32 lcl_plen = 0, action = 0; + clib_error_t *error = 0; + ip46_address_t lcl_ip; + u8 conn_set = 0; + u8 fib_proto = -1, is_add = 1, *ns_id = 0; + u8 *tag = 0, tag_only = 0; + int rv; + session_rule_add_del_args_t args; + + session_cli_return_if_not_enabled (); + + if (session_sdl_is_enabled () == 0) + return clib_error_return (0, "session sdl engine is not enabled"); + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "del")) + is_add = 0; + else if (unformat (input, "add")) + ; + else if (unformat (input, "appns %_%v%_", &ns_id)) + ; + else if (unformat (input, "%U/%d", unformat_ip4_address, &lcl_ip.ip4, + &lcl_plen)) + { + fib_proto = FIB_PROTOCOL_IP4; + conn_set = 1; + } + else if (unformat (input, "%U/%d", unformat_ip6_address, &lcl_ip.ip6, + &lcl_plen)) + { + fib_proto = FIB_PROTOCOL_IP6; + conn_set = 1; + } + else if (unformat (input, "action %d", &action)) + ; + else if (unformat (input, "tag %_%v%_", &tag)) + ; + else + { + error = clib_error_return (0, "unknown input `%U'", + format_unformat_error, input); + goto done; + } + } + + if (ns_id) + { + app_ns = app_namespace_get_from_id (ns_id); + if (!app_ns) + { + vlib_cli_output (vm, "namespace %v does not exist", ns_id); + goto done; + } + } + else + { + app_ns = app_namespace_get_default (); + } + appns_index = app_namespace_index (app_ns); + + if (is_add && !conn_set && action == 0) + { + vlib_cli_output (vm, "connection and action must be set for add"); + goto done; + } + if (!is_add && !tag && !conn_set) + { + vlib_cli_output (vm, "connection or tag must be set for delete"); + goto done; + } + if (vec_len (tag) > SESSION_RULE_TAG_MAX_LEN) + { + vlib_cli_output (vm, "tag too long (max u64)"); + goto done; + } + + /* Delete with only tag entered. Try v4 first and then v6 if failed */ + if ((is_add == 0) && (fib_proto == (u8) ~0)) + { + fib_proto = FIB_PROTOCOL_IP4; + tag_only = 1; + } + + memset (&args, 0, sizeof (args)); + args.transport_proto = TRANSPORT_PROTO_TCP; + args.table_args.lcl.fp_addr = lcl_ip; + args.table_args.lcl.fp_len = lcl_plen; + args.table_args.lcl.fp_proto = fib_proto; + args.table_args.rmt.fp_proto = fib_proto; + args.table_args.action_index = action; + args.table_args.is_add = is_add; + args.table_args.tag = tag; + args.appns_index = appns_index; + args.scope = SESSION_RULE_SCOPE_GLOBAL; + + if ((rv = vnet_session_rule_add_del (&args))) + { + /* Try tag only delete on v6 */ + if (rv && tag_only) + { + args.table_args.rmt.fp_proto = FIB_PROTOCOL_IP6; + args.table_args.lcl.fp_proto = FIB_PROTOCOL_IP6; + if ((rv = vnet_session_rule_add_del (&args))) + { + error = clib_error_return (0, "sdl add del returned %u", rv); + } + } + else + { + error = clib_error_return (0, "sdl add del returned %u", rv); + } + } + +done: + vec_free (ns_id); + vec_free (tag); + return error; +} + +VLIB_CLI_COMMAND (session_sdl_command, static) = { + .path = "session sdl", + .short_help = "session sdl [add|del] [appns <ns_id>] <lcl-ip/plen> action " + "<action> [tag <tag>]", + .function = session_sdl_command_fn, + .is_mp_safe = 1, +}; + +static clib_error_t * +show_session_sdl_command_fn (vlib_main_t *vm, unformat_input_t *input, + vlib_cli_command_t *cmd) +{ + u32 fib_index; + ip46_address_t lcl_ip; + u8 show_one = 0; + app_namespace_t *app_ns; + session_table_t *st; + u8 *ns_id = 0, fib_proto = FIB_PROTOCOL_IP4; + + session_cli_return_if_not_enabled (); + + clib_memset (&lcl_ip, 0, sizeof (lcl_ip)); + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "appns %_%s%_", &ns_id)) + ; + else if (unformat (input, "%U", unformat_ip4_address, &lcl_ip.ip4)) + { + fib_proto = FIB_PROTOCOL_IP4; + show_one = 1; + } + else if (unformat (input, "%U", unformat_ip6_address, &lcl_ip.ip6)) + { + fib_proto = FIB_PROTOCOL_IP6; + show_one = 1; + } + else + { + vec_free (ns_id); + return clib_error_return (0, "unknown input `%U'", + format_unformat_error, input); + } + } + + if (ns_id) + { + app_ns = app_namespace_get_from_id (ns_id); + if (!app_ns) + { + vlib_cli_output (vm, "appns %v doesn't exist", ns_id); + goto done; + } + } + else + { + app_ns = app_namespace_get_default (); + } + + if (session_sdl_is_enabled () == 0) + { + vlib_cli_output (vm, "session sdl engine is not enabled"); + goto done; + } + + if (show_one) + { + fib_index = app_namespace_get_fib_index (app_ns, fib_proto); + st = session_table_get_for_fib_index (fib_proto, fib_index); + if (st && (st->srtg_handle != SESSION_SRTG_HANDLE_INVALID)) + session_rules_table_show_rule (vm, st->srtg_handle, 0, &lcl_ip, 0, 0, + 0, (fib_proto == FIB_PROTOCOL_IP4)); + goto done; + } + + /* 2 separate session tables for global entries, 1 for ip4 and 1 for ip6 */ + fib_index = app_namespace_get_fib_index (app_ns, FIB_PROTOCOL_IP4); + st = session_table_get_for_fib_index (FIB_PROTOCOL_IP4, fib_index); + if (st && (st->srtg_handle != SESSION_SRTG_HANDLE_INVALID)) + session_rules_table_cli_dump (vm, st->srtg_handle, 0, FIB_PROTOCOL_IP4); + + fib_index = app_namespace_get_fib_index (app_ns, FIB_PROTOCOL_IP6); + st = session_table_get_for_fib_index (FIB_PROTOCOL_IP6, fib_index); + if (st && (st->srtg_handle != SESSION_SRTG_HANDLE_INVALID)) + session_rules_table_cli_dump (vm, st->srtg_handle, 0, FIB_PROTOCOL_IP6); +done: + vec_free (ns_id); + return 0; +} + +void +session_sdl_table_walk4 (u32 srtg_handle, session_sdl_table_walk_fn_t fn, + void *args) +{ + ip4_fib_t *fib; + session_sdl4_fib_show_walk_ctx_t ctx = { + .ifsw_indicies = NULL, + }; + fib_node_index_t *fei; + session_rules_table_t *srt = srtg_handle_to_srt (srtg_handle, 0); + session_sdl_block_t *sdlb = &srt->sdl_block; + u32 fib_index = sdlb->ip_fib_index; + + if (fib_index == ~0) + return; + fib = ip4_fib_get (fib_index); + ip4_fib_table_walk (fib, session_sdl4_fib_show_walk_cb, &ctx); + vec_sort_with_function (ctx.ifsw_indicies, fib_entry_cmp_for_sort); + + vec_foreach (fei, ctx.ifsw_indicies) + { + if (*fei != FIB_NODE_INDEX_INVALID && + fib_entry_is_sourced (*fei, sdl_fib_src)) + { + u8 *tag = session_rules_table_rule_tag (srt, *fei, 1); + fib_entry_t *fib_entry = fib_entry_get (*fei); + fib_prefix_t pfx = fib_entry->fe_prefix; + index_t lbi = + ip4_fib_forwarding_lookup (fib_index, &pfx.fp_addr.ip4); + const dpo_id_t *dpo = + load_balance_get_fwd_bucket (load_balance_get (lbi), 0); + + fn (*fei, &pfx.fp_addr, pfx.fp_len, dpo->dpoi_index, + FIB_PROTOCOL_IP4, tag, args); + } + } + + vec_free (ctx.ifsw_indicies); +} + +void +session_sdl_table_walk6 (u32 srtg_handle, session_sdl_table_walk_fn_t fn, + void *args) +{ + ip6_fib_t *fib; + fib_node_index_t *fei; + session_sdl6_fib_show_ctx_t ctx = { + .entries = NULL, + }; + session_rules_table_t *srt = srtg_handle_to_srt (srtg_handle, 0); + session_sdl_block_t *sdlb = &srt->sdl_block; + u32 fib_index = sdlb->ip6_fib_index; + + if (fib_index == ~0) + return; + fib = ip6_fib_get (fib_index); + ip6_fib_table_walk (fib->index, session_sdl6_fib_table_show_walk, &ctx); + vec_sort_with_function (ctx.entries, fib_entry_cmp_for_sort); + + vec_foreach (fei, ctx.entries) + { + if (*fei != FIB_NODE_INDEX_INVALID && + fib_entry_is_sourced (*fei, sdl_fib_src)) + { + u8 *tag = session_rules_table_rule_tag (srt, *fei, 0); + fib_entry_t *fib_entry = fib_entry_get (*fei); + fib_prefix_t pfx = fib_entry->fe_prefix; + index_t lbi = + ip6_fib_table_fwding_lookup (fib_index, &pfx.fp_addr.ip6); + const dpo_id_t *dpo = + load_balance_get_fwd_bucket (load_balance_get (lbi), 0); + + fn (*fei, &pfx.fp_addr, pfx.fp_len, dpo->dpoi_index, + FIB_PROTOCOL_IP6, tag, args); + } + } + + vec_free (ctx.entries); +} + +VLIB_CLI_COMMAND (show_session_sdl_command, static) = { + .path = "show session sdl", + .short_help = "show session sdl [appns <id> <lcl-ip>]", + .function = show_session_sdl_command_fn, + .is_mp_safe = 1, +}; + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/src/vnet/session/session_sdl.h b/src/vnet/session/session_sdl.h new file mode 100644 index 00000000000..8d8b5b2d29e --- /dev/null +++ b/src/vnet/session/session_sdl.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2024 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SRC_VNET_SESSION_SESSION_SDL_H_ +#define SRC_VNET_SESSION_SESSION_SDL_H_ + +clib_error_t *session_sdl_enable_disable (int enable); + +typedef void (*session_sdl_table_walk_fn_t) (u32 fei, ip46_address_t *lcl_ip, + u16 fp_len, u32 action_index, + u32 fb_proto, u8 *tag, void *ctx); +void session_sdl_table_walk4 (u32 srtg_handle, session_sdl_table_walk_fn_t fn, + void *args); +void session_sdl_table_walk6 (u32 srtg_handle, session_sdl_table_walk_fn_t fn, + void *args); + +#endif /* SRC_VNET_SESSION_SESSION_SDL_H_ */ +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/src/vnet/session/session_table.c b/src/vnet/session/session_table.c index dbbe771979c..5dafe0e633c 100644 --- a/src/vnet/session/session_table.c +++ b/src/vnet/session/session_table.c @@ -15,6 +15,7 @@ #include <vnet/session/session_table.h> #include <vnet/session/session.h> +#include <vnet/session/session_rules_table.h> /** * Pool of session tables @@ -64,12 +65,8 @@ void session_table_free (session_table_t *slt, u8 fib_proto) { u8 all = fib_proto > FIB_PROTOCOL_IP6 ? 1 : 0; - int i; - for (i = 0; i < TRANSPORT_N_PROTOS; i++) - session_rules_table_free (&slt->session_rules[i]); - - vec_free (slt->session_rules); + session_rules_table_free (slt, fib_proto); if (fib_proto == FIB_PROTOCOL_IP4 || all) { @@ -92,10 +89,9 @@ session_table_free (session_table_t *slt, u8 fib_proto) * otherwise it uses defaults above. */ void -session_table_init (session_table_t * slt, u8 fib_proto) +session_table_init (session_table_t *slt, u8 fib_proto) { u8 all = fib_proto > FIB_PROTOCOL_IP6 ? 1 : 0; - int i; #define _(af,table,parm,value) \ u32 configured_##af##_##table##_table_##parm = value; @@ -109,6 +105,7 @@ session_table_init (session_table_t * slt, u8 fib_proto) foreach_hash_table_parameter; #undef _ + slt->srtg_handle = SESSION_SRTG_HANDLE_INVALID; if (fib_proto == FIB_PROTOCOL_IP4 || all) { clib_bihash_init2_args_16_8_t _a, *a = &_a; @@ -153,10 +150,6 @@ session_table_init (session_table_t * slt, u8 fib_proto) a->instantiate_immediately = 1; clib_bihash_init2_48_8 (a); } - - vec_validate (slt->session_rules, TRANSPORT_N_PROTOS - 1); - for (i = 0; i < TRANSPORT_N_PROTOS; i++) - session_rules_table_init (&slt->session_rules[i]); } typedef struct _ip4_session_table_walk_ctx_t diff --git a/src/vnet/session/session_table.h b/src/vnet/session/session_table.h index bcbb6ec3037..aae4a1c2af5 100644 --- a/src/vnet/session/session_table.h +++ b/src/vnet/session/session_table.h @@ -18,7 +18,6 @@ #include <vppinfra/bihash_16_8.h> #include <vppinfra/bihash_48_8.h> -#include <vnet/session/session_rules_table.h> typedef struct _session_lookup_table { @@ -37,7 +36,7 @@ typedef struct _session_lookup_table /** * Per fib proto and transport proto session rules tables */ - session_rules_table_t *session_rules; + u32 srtg_handle; /** Flag that indicates if table has local scope */ u8 is_local; diff --git a/src/vnet/session/session_test.c b/src/vnet/session/session_test.c index 770e7263024..1c865b877b5 100644 --- a/src/vnet/session/session_test.c +++ b/src/vnet/session/session_test.c @@ -271,6 +271,12 @@ api_session_enable_disable (vat_main_t *vat) } static int +api_session_enable_disable_v2 (vat_main_t *vat) +{ + return -1; +} + +static int api_app_worker_add_del (vat_main_t *vat) { return -1; @@ -354,6 +360,23 @@ api_session_sapi_enable_disable (vat_main_t *vat) return -1; } +static int +api_session_sdl_add_del (vat_main_t *vam) +{ + return -1; +} + +static void +vl_api_session_sdl_details_t_handler (vl_api_session_rules_details_t *mp) +{ +} + +static int +api_session_sdl_dump (vat_main_t *vam) +{ + return -1; +} + #include <vnet/session/session.api_test.c> /* |