From 9793477a28c45e4eb5bba3f2050fe415e57e8ad8 Mon Sep 17 00:00:00 2001 From: John Lo Date: Thu, 18 May 2017 22:26:47 -0400 Subject: [PATCH] Enforce Bridge Domain ID range to match 24-bit VNI range Enforce bridge domain ID range to allow a maximum value of 16M which matches the range of 24-bit VNI used for virtual overlay network ID. Fix "show bridge-domain" output to allow full 16M BD ID range to be displayed using 8-digit spaces. Change-Id: I80d9c76ea7c001bcccd3c19df1f3e55d2970f01c Signed-off-by: John Lo --- src/vlibapi/api_helper_macros.h | 14 ++++++++++++++ src/vnet/api_errno.h | 5 +++-- src/vnet/l2/l2_bd.c | 17 +++++++++++------ src/vnet/l2/l2_bd.h | 4 +++- src/vnet/l2/l2_input.c | 6 ++++++ src/vnet/lisp-gpe/interface.c | 6 ++++++ src/vpp/api/api.c | 2 ++ 7 files changed, 45 insertions(+), 9 deletions(-) diff --git a/src/vlibapi/api_helper_macros.h b/src/vlibapi/api_helper_macros.h index a492c3f40e2..2e29d4d7983 100644 --- a/src/vlibapi/api_helper_macros.h +++ b/src/vlibapi/api_helper_macros.h @@ -155,6 +155,20 @@ bad_tx_sw_if_index: \ ; \ } while (0); +#define VALIDATE_BD_ID(mp) \ + do { u32 __rx_bd_id = ntohl(mp->bd_id); \ + if (__rx_bd_id > L2_BD_ID_MAX) { \ + rv = VNET_API_ERROR_BD_ID_EXCEED_MAX; \ + goto bad_bd_id; \ + } \ +} while(0); + +#define BAD_BD_ID_LABEL \ +do { \ +bad_bd_id: \ + ; \ +} while (0); + #define pub_sub_handler(lca,UCA) \ static void vl_api_want_##lca##_t_handler ( \ vl_api_want_##lca##_t *mp) \ diff --git a/src/vnet/api_errno.h b/src/vnet/api_errno.h index e694fbf1ed4..b22bb3a879f 100644 --- a/src/vnet/api_errno.h +++ b/src/vnet/api_errno.h @@ -110,8 +110,9 @@ _(SVM_SEGMENT_CREATE_FAIL, -117, "svm segment create fail") \ _(APPLICATION_NOT_ATTACHED, -118, "application not attached") \ _(BD_ALREADY_EXISTS, -119, "Bridge domain already exists") \ _(BD_IN_USE, -120, "Bridge domain has member interfaces") \ -_(BD_NOT_MODIFIABLE, -121, "Default bridge domain 0 can be neither deleted nor modified") \ -_(UNSUPPORTED, -122, "Unsupported") +_(BD_NOT_MODIFIABLE, -121, "Bridge domain 0 can't be deleted/modified") \ +_(BD_ID_EXCEED_MAX, -122, "Bridge domain ID exceed 16M limit") \ +_(UNSUPPORTED, -123, "Unsupported") typedef enum { diff --git a/src/vnet/l2/l2_bd.c b/src/vnet/l2/l2_bd.c index 351e6987446..f68b6638618 100644 --- a/src/vnet/l2/l2_bd.c +++ b/src/vnet/l2/l2_bd.c @@ -984,10 +984,10 @@ bd_show (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd) { printed = 1; vlib_cli_output (vm, - "%=5s %=7s %=4s %=9s %=9s %=9s %=9s %=9s %=9s %=9s", - "ID", "Index", "BSN", "Age(min)", "Learning", - "U-Forwrd", "UU-Flood", "Flooding", "ARP-Term", - "BVI-Intf"); + "%=8s %=7s %=4s %=9s %=9s %=9s %=9s %=9s %=9s %=9s", + "BD-ID", "Index", "BSN", "Age(min)", + "Learning", "U-Forwrd", "UU-Flood", "Flooding", + "ARP-Term", "BVI-Intf"); } if (bd_config->mac_age) @@ -995,7 +995,7 @@ bd_show (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd) else as = format (as, "off"); vlib_cli_output (vm, - "%=5d %=7d %=4d %=9v %=9s %=9s %=9s %=9s %=9s %=9U", + "%=8d %=7d %=4d %=9v %=9s %=9s %=9s %=9s %=9s %=9U", bd_config->bd_id, bd_index, bd_config->seq_num, as, bd_config->feature_bitmap & L2INPUT_FEAT_LEARN ? "on" : "off", @@ -1123,6 +1123,8 @@ bd_add_del (l2_bridge_domain_add_del_args_t * a) { if (bd_index != ~0) return VNET_API_ERROR_BD_ALREADY_EXISTS; + if (a->bd_id > L2_BD_ID_MAX) + return VNET_API_ERROR_BD_ID_EXCEED_MAX; bd_index = bd_add_bd_index (bdm, a->bd_id); u32 enable_flags = 0, disable_flags = 0; @@ -1262,11 +1264,14 @@ bd_add_del_command_fn (vlib_main_t * vm, unformat_input_t * input, error = clib_error_return (0, "bridge domain in use - remove members"); goto done; case VNET_API_ERROR_NO_SUCH_ENTRY: - error = clib_error_return (0, "bridge domain id does not exist"); + error = clib_error_return (0, "bridge domain ID does not exist"); goto done; case VNET_API_ERROR_BD_NOT_MODIFIABLE: error = clib_error_return (0, "bridge domain 0 can not be modified"); goto done; + case VNET_API_ERROR_BD_ID_EXCEED_MAX: + error = clib_error_return (0, "bridge domain ID exceed 16M limit"); + goto done; default: error = clib_error_return (0, "bd_add_del returned %d", rv); goto done; diff --git a/src/vnet/l2/l2_bd.h b/src/vnet/l2/l2_bd.h index e502d497e0b..93ed1a8532a 100644 --- a/src/vnet/l2/l2_bd.h +++ b/src/vnet/l2/l2_bd.h @@ -49,7 +49,6 @@ typedef struct u16 spare; } l2_flood_member_t; - /* Per-bridge domain configuration */ typedef struct @@ -91,6 +90,9 @@ typedef struct } l2_bridge_domain_t; +/* Limit Bridge Domain ID to 24 bits to match 24-bit VNI range */ +#define L2_BD_ID_MAX ((1<<24)-1) + typedef struct { u32 bd_id; diff --git a/src/vnet/l2/l2_input.c b/src/vnet/l2/l2_input.c index 41a93f56332..aca23fe03fc 100644 --- a/src/vnet/l2/l2_input.c +++ b/src/vnet/l2/l2_input.c @@ -791,6 +791,12 @@ int_l2_bridge (vlib_main_t * vm, goto done; } + if (bd_id > L2_BD_ID_MAX) + { + error = clib_error_return (0, "bridge domain ID exceed 16M limit", + format_unformat_error, input); + goto done; + } bd_index = bd_find_or_add_bd_index (&bd_main, bd_id); /* optional bvi */ diff --git a/src/vnet/lisp-gpe/interface.c b/src/vnet/lisp-gpe/interface.c index ff750563c53..94703abc4cf 100644 --- a/src/vnet/lisp-gpe/interface.c +++ b/src/vnet/lisp-gpe/interface.c @@ -653,6 +653,12 @@ lisp_gpe_add_l2_iface (lisp_gpe_main_t * lgm, u32 vni, u32 bd_id) uword *hip, *si; u16 bd_index; + if (bd_id > L2_BD_ID_MAX) + { + clib_warning ("bridge domain ID %d exceed 16M limit", bd_id); + return ~0; + } + bd_index = bd_find_or_add_bd_index (&bd_main, bd_id); hip = hash_get (l2_ifaces->hw_if_index_by_dp_table, bd_index); diff --git a/src/vpp/api/api.c b/src/vpp/api/api.c index 16d512259ac..7e4c341e12b 100644 --- a/src/vpp/api/api.c +++ b/src/vpp/api/api.c @@ -419,6 +419,7 @@ static void if (mp->enable) { + VALIDATE_BD_ID (mp); u32 bd_id = ntohl (mp->bd_id); u32 bd_index = bd_find_or_add_bd_index (bdm, bd_id); u32 bvi = mp->bvi; @@ -432,6 +433,7 @@ static void } BAD_RX_SW_IF_INDEX_LABEL; + BAD_BD_ID_LABEL; REPLY_MACRO (VL_API_SW_INTERFACE_SET_L2_BRIDGE_REPLY); } -- 2.16.6