From b3605eab5ad6b8acb758caf7ce04c39d91f9e969 Mon Sep 17 00:00:00 2001 From: hedi bouattour Date: Wed, 14 Sep 2022 12:39:23 +0000 Subject: [PATCH 1/1] urpf: add mode for specific fib index lookup this patch adds a mode to urpf in order to perform the lookup in a specified vrf instead of the interface vrf Type: feature Change-Id: Ieb91de6ccdfbf32b6939364f3bebeecd2d57af19 Signed-off-by: hedi bouattour --- src/plugins/urpf/urpf.api | 21 +++++++++ src/plugins/urpf/urpf.c | 111 ++++++++++++++++++++++++++++++++++++++------ src/plugins/urpf/urpf.h | 21 ++++++--- src/plugins/urpf/urpf_api.c | 38 +++++++++++++-- src/plugins/urpf/urpf_dp.h | 22 ++++----- 5 files changed, 175 insertions(+), 38 deletions(-) diff --git a/src/plugins/urpf/urpf.api b/src/plugins/urpf/urpf.api index 944db08cc94..4665743a57a 100644 --- a/src/plugins/urpf/urpf.api +++ b/src/plugins/urpf/urpf.api @@ -50,6 +50,27 @@ autoreply define urpf_update vl_api_interface_index_t sw_if_index; }; +/** + * @brief Enable uRPF on a given interface in a given direction + * @param client_index - opaque cookie to identify the sender + * @param context - sender context, to match reply w/ request + * @param mode - Mode + * @param af - Address Family + * @param sw_if_index - Interface + * @param is_input - Direction. + * @param table-id - Table ID + */ +autoreply define urpf_update_v2 +{ + u32 client_index; + u32 context; + bool is_input[default = true]; + vl_api_urpf_mode_t mode; + vl_api_address_family_t af; + vl_api_interface_index_t sw_if_index; + u32 table_id [default=0xffffffff]; +}; + /* * fd.io coding-style-patch-verification: ON * diff --git a/src/plugins/urpf/urpf.c b/src/plugins/urpf/urpf.c index 6cf7cda8744..3c3b33c769c 100644 --- a/src/plugins/urpf/urpf.c +++ b/src/plugins/urpf/urpf.c @@ -58,7 +58,8 @@ static const char *urpf_feats[N_AF][VLIB_N_DIR][URPF_N_MODES] = /** * Per-af, per-direction, per-interface uRPF configs */ -static urpf_mode_t *urpf_cfgs[N_AF][VLIB_N_DIR]; + +urpf_data_t *urpf_cfgs[N_AF][VLIB_N_DIR]; u8 * format_urpf_mode (u8 * s, va_list * a) @@ -95,34 +96,105 @@ unformat_urpf_mode (unformat_input_t * input, va_list * args) return 0; } -void -urpf_update (urpf_mode_t mode, - u32 sw_if_index, ip_address_family_t af, vlib_dir_t dir) +int +urpf_update (urpf_mode_t mode, u32 sw_if_index, ip_address_family_t af, + vlib_dir_t dir, u32 table_id) { - urpf_mode_t old; + fib_protocol_t proto; + u32 fib_index; + if (table_id != ~0) + { + proto = ip_address_family_to_fib_proto (af); + fib_index = fib_table_find (proto, table_id); + if (fib_index == (~0)) + return VNET_API_ERROR_INVALID_VALUE; + } + else + { + bool is_ip4 = (AF_IP4 == af); + u32 *fib_index_by_sw_if_index = is_ip4 ? + ip4_main.fib_index_by_sw_if_index : + ip6_main.fib_index_by_sw_if_index; - vec_validate_init_empty (urpf_cfgs[af][dir], sw_if_index, URPF_MODE_OFF); + fib_index = fib_index_by_sw_if_index[sw_if_index]; + } + urpf_data_t old; + urpf_mode_t off = URPF_MODE_OFF; + urpf_data_t empty = { .fib_index = 0, .mode = off }; + vec_validate_init_empty (urpf_cfgs[af][dir], sw_if_index, empty); old = urpf_cfgs[af][dir][sw_if_index]; - if (mode != old) + urpf_data_t data = { .fib_index = fib_index, + .mode = mode, + .fib_index_is_custom = (table_id != ~0) }; + urpf_cfgs[af][dir][sw_if_index] = data; + if (data.mode != old.mode || data.fib_index != old.fib_index) { - if (URPF_MODE_OFF != old) + if (URPF_MODE_OFF != old.mode) /* disable what we have */ vnet_feature_enable_disable (urpf_feat_arcs[af][dir], - urpf_feats[af][dir][old], + urpf_feats[af][dir][old.mode], sw_if_index, 0, 0, 0); - if (URPF_MODE_OFF != mode) + if (URPF_MODE_OFF != data.mode) /* enable what's new */ vnet_feature_enable_disable (urpf_feat_arcs[af][dir], - urpf_feats[af][dir][mode], + urpf_feats[af][dir][data.mode], sw_if_index, 1, 0, 0); } /* else - no change to existing config */ + return 0; +} + +static void +urpf_table_bind_v4 (ip4_main_t *im, uword opaque, u32 sw_if_index, + u32 new_fib_index, u32 old_fib_index) +{ + vlib_dir_t dir; + urpf_data_t empty = { .fib_index = 0, .mode = URPF_MODE_OFF }; + FOREACH_VLIB_DIR (dir) + { + vec_validate_init_empty (urpf_cfgs[AF_IP4][dir], sw_if_index, empty); + if (!urpf_cfgs[AF_IP4][dir][sw_if_index].fib_index_is_custom) + { + urpf_cfgs[AF_IP4][dir][sw_if_index].fib_index = new_fib_index; + } + } +} - urpf_cfgs[af][dir][sw_if_index] = mode; +static void +urpf_table_bind_v6 (ip6_main_t *im, uword opaque, u32 sw_if_index, + u32 new_fib_index, u32 old_fib_index) +{ + vlib_dir_t dir; + urpf_data_t empty = { .fib_index = 0, .mode = URPF_MODE_OFF }; + FOREACH_VLIB_DIR (dir) + { + vec_validate_init_empty (urpf_cfgs[AF_IP6][dir], sw_if_index, empty); + if (!urpf_cfgs[AF_IP6][dir][sw_if_index].fib_index_is_custom) + { + urpf_cfgs[AF_IP6][dir][sw_if_index].fib_index = new_fib_index; + } + } } +static clib_error_t * +urpf_init (vlib_main_t *vm) +{ + ip4_table_bind_callback_t cb4 = { + .function = urpf_table_bind_v4, + }; + vec_add1 (ip4_main.table_bind_callbacks, cb4); + + ip6_table_bind_callback_t cb6 = { + .function = urpf_table_bind_v6, + }; + vec_add1 (ip6_main.table_bind_callbacks, cb6); + return (NULL); +} + +VLIB_INIT_FUNCTION (urpf_init); + static clib_error_t * urpf_cli_update (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd) @@ -134,11 +206,13 @@ urpf_cli_update (vlib_main_t * vm, urpf_mode_t mode; u32 sw_if_index; vlib_dir_t dir; + u32 table_id; sw_if_index = ~0; af = AF_IP4; dir = VLIB_RX; mode = URPF_MODE_STRICT; + table_id = ~0; if (!unformat_user (input, unformat_line_input, line_input)) return 0; @@ -150,6 +224,8 @@ urpf_cli_update (vlib_main_t * vm, ; else if (unformat (line_input, "%U", unformat_urpf_mode, &mode)) ; + else if (unformat (line_input, "table %d", &table_id)) + ; else if (unformat (line_input, "%U", unformat_ip_address_family, &af)) ; else if (unformat (line_input, "%U", unformat_vlib_rx_tx, &dir)) @@ -168,7 +244,13 @@ urpf_cli_update (vlib_main_t * vm, goto done; } - urpf_update (mode, sw_if_index, af, dir); + int rv = 0; + rv = urpf_update (mode, sw_if_index, af, dir, table_id); + if (rv) + { + error = clib_error_return (0, "unknown table id"); + goto done; + } done: unformat_free (line_input); @@ -233,7 +315,8 @@ done: VLIB_CLI_COMMAND (set_interface_ip_source_check_command, static) = { .path = "set urpf", .function = urpf_cli_update, - .short_help = "set urpf [ip4|ip6] [rx|tx] [off|strict|loose] ", + .short_help = "set urpf [ip4|ip6] [rx|tx] [off|strict|loose] " + " [table ]", }; /* *INDENT-ON* */ diff --git a/src/plugins/urpf/urpf.h b/src/plugins/urpf/urpf.h index 941cda25f4b..c2ce6b0d452 100644 --- a/src/plugins/urpf/urpf.h +++ b/src/plugins/urpf/urpf.h @@ -18,10 +18,10 @@ #include -#define foreach_urpf_mode \ - _(OFF, "off") \ - _(LOOSE, "loose") \ - _(STRICT, "strict") \ +#define foreach_urpf_mode \ + _ (OFF, "off") \ + _ (LOOSE, "loose") \ + _ (STRICT, "strict") typedef enum urpf_mode_t_ { @@ -34,10 +34,17 @@ typedef enum urpf_mode_t_ extern u8 *format_urpf_mode (u8 * s, va_list * a); -extern void urpf_update (urpf_mode_t mode, - u32 sw_if_index, - ip_address_family_t af, vlib_dir_t dir); +typedef struct +{ + urpf_mode_t mode; + u32 fib_index; + u8 fib_index_is_custom; +} urpf_data_t; + +extern urpf_data_t *urpf_cfgs[N_AF][VLIB_N_DIR]; +extern int urpf_update (urpf_mode_t mode, u32 sw_if_index, + ip_address_family_t af, vlib_dir_t dir, u32 fib_index); #endif diff --git a/src/plugins/urpf/urpf_api.c b/src/plugins/urpf/urpf_api.c index ad060399347..472f0e4a7ff 100644 --- a/src/plugins/urpf/urpf_api.c +++ b/src/plugins/urpf/urpf_api.c @@ -26,6 +26,8 @@ #include #include #include +#include +#include /** * Base message ID fot the plugin @@ -62,7 +64,34 @@ vl_api_urpf_update_t_handler (vl_api_urpf_update_t * mp) VALIDATE_SW_IF_INDEX (mp); rv = urpf_mode_decode (mp->mode, &mode); + if (rv) + goto done; + + rv = ip_address_family_decode (mp->af, &af); + if (rv) + goto done; + + rv = urpf_update (mode, htonl (mp->sw_if_index), af, + (mp->is_input ? VLIB_RX : VLIB_TX), 0); + if (rv) + goto done; + + BAD_SW_IF_INDEX_LABEL; +done: + REPLY_MACRO (VL_API_URPF_UPDATE_REPLY); +} +static void +vl_api_urpf_update_v2_t_handler (vl_api_urpf_update_v2_t *mp) +{ + vl_api_urpf_update_reply_t *rmp; + ip_address_family_t af; + urpf_mode_t mode; + int rv = 0; + + VALIDATE_SW_IF_INDEX (mp); + + rv = urpf_mode_decode (mp->mode, &mode); if (rv) goto done; @@ -71,12 +100,15 @@ vl_api_urpf_update_t_handler (vl_api_urpf_update_t * mp) if (rv) goto done; - urpf_update (mode, htonl (mp->sw_if_index), af, - (mp->is_input ? VLIB_RX : VLIB_TX)); + rv = urpf_update (mode, htonl (mp->sw_if_index), af, + (mp->is_input ? VLIB_RX : VLIB_TX), ntohl (mp->table_id)); + + if (rv) + goto done; BAD_SW_IF_INDEX_LABEL; done: - REPLY_MACRO (VL_API_URPF_UPDATE_REPLY); + REPLY_MACRO (VL_API_URPF_UPDATE_V2_REPLY); } #include diff --git a/src/plugins/urpf/urpf_dp.h b/src/plugins/urpf/urpf_dp.h index bfe1f659171..816d8b70b90 100644 --- a/src/plugins/urpf/urpf_dp.h +++ b/src/plugins/urpf/urpf_dp.h @@ -128,6 +128,11 @@ urpf_inline (vlib_main_t * vm, h1 += vnet_buffer (b[1])->ip.save_rewrite_length; } + fib_index0 = + urpf_cfgs[af][dir][vnet_buffer (b[0])->sw_if_index[dir]].fib_index; + fib_index1 = + urpf_cfgs[af][dir][vnet_buffer (b[1])->sw_if_index[dir]].fib_index; + if (AF_IP4 == af) { const ip4_header_t *ip0, *ip1; @@ -135,11 +140,6 @@ urpf_inline (vlib_main_t * vm, ip0 = (ip4_header_t *) h0; ip1 = (ip4_header_t *) h1; - fib_index0 = ip4_main.fib_index_by_sw_if_index - [vnet_buffer (b[0])->sw_if_index[dir]]; - fib_index1 = ip4_main.fib_index_by_sw_if_index - [vnet_buffer (b[1])->sw_if_index[dir]]; - ip4_fib_forwarding_lookup_x2 (fib_index0, fib_index1, &ip0->src_address, @@ -155,11 +155,6 @@ urpf_inline (vlib_main_t * vm, { const ip6_header_t *ip0, *ip1; - fib_index0 = ip6_main.fib_index_by_sw_if_index - [vnet_buffer (b[0])->sw_if_index[dir]]; - fib_index1 = ip6_main.fib_index_by_sw_if_index - [vnet_buffer (b[1])->sw_if_index[dir]]; - ip0 = (ip6_header_t *) h0; ip1 = (ip6_header_t *) h1; @@ -255,12 +250,13 @@ urpf_inline (vlib_main_t * vm, if (VLIB_TX == dir) h0 += vnet_buffer (b[0])->ip.save_rewrite_length; + fib_index0 = + urpf_cfgs[af][dir][vnet_buffer (b[0])->sw_if_index[dir]].fib_index; + if (AF_IP4 == af) { const ip4_header_t *ip0; - fib_index0 = ip4_main.fib_index_by_sw_if_index - [vnet_buffer (b[0])->sw_if_index[dir]]; ip0 = (ip4_header_t *) h0; lb_index0 = ip4_fib_forwarding_lookup (fib_index0, @@ -275,8 +271,6 @@ urpf_inline (vlib_main_t * vm, const ip6_header_t *ip0; ip0 = (ip6_header_t *) h0; - fib_index0 = ip6_main.fib_index_by_sw_if_index - [vnet_buffer (b[0])->sw_if_index[dir]]; lb_index0 = ip6_fib_table_fwding_lookup (fib_index0, &ip0->src_address); -- 2.16.6