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 <hedibouattour2010@gmail.com>
This commit is contained in:
committed by
Neale Ranns
parent
9260b8861e
commit
b3605eab5a
@@ -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
|
||||
*
|
||||
|
||||
@@ -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 */
|
||||
|
||||
urpf_cfgs[af][dir][sw_if_index] = mode;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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] <INTERFACE>",
|
||||
.short_help = "set urpf [ip4|ip6] [rx|tx] [off|strict|loose] "
|
||||
"<INTERFACE> [table <table>]",
|
||||
};
|
||||
/* *INDENT-ON* */
|
||||
|
||||
|
||||
@@ -18,10 +18,10 @@
|
||||
|
||||
#include <vnet/ip/ip_types.h>
|
||||
|
||||
#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
|
||||
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
#include <vnet/format_fns.h>
|
||||
#include <urpf/urpf.api_enum.h>
|
||||
#include <urpf/urpf.api_types.h>
|
||||
#include <vnet/fib/fib_table.h>
|
||||
#include <vnet/ip/ip_types.h>
|
||||
|
||||
/**
|
||||
* 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 <urpf/urpf.api.c>
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user