X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvnet%2Fl2%2Fl2_bd.c;h=7e6ea60b440667946a45d9cd151afcb2616c765c;hb=fbc633f5542be4b0b85963f7dcba9ab143c61d62;hp=4dd359ed0b7f3f7b76cbdfe80a6953f370690e93;hpb=e26c81fc80d1ce9a8746ebf4009149849b04f60f;p=vpp.git diff --git a/src/vnet/l2/l2_bd.c b/src/vnet/l2/l2_bd.c index 4dd359ed0b7..7e6ea60b440 100644 --- a/src/vnet/l2/l2_bd.c +++ b/src/vnet/l2/l2_bd.c @@ -52,7 +52,8 @@ bd_validate (l2_bridge_domain_t * bd_config) { if (bd_is_valid (bd_config)) return; - bd_config->feature_bitmap = ~(L2INPUT_FEAT_ARP_TERM | L2INPUT_FEAT_UU_FWD); + bd_config->feature_bitmap = + ~(L2INPUT_FEAT_ARP_TERM | L2INPUT_FEAT_UU_FWD | L2INPUT_FEAT_ARP_UFWD); bd_config->bvi_sw_if_index = ~0; bd_config->uu_fwd_sw_if_index = ~0; bd_config->members = 0; @@ -87,6 +88,9 @@ bd_add_bd_index (bd_main_t * bdm, u32 bd_id) vec_validate (l2input_main.bd_configs, rv); l2input_main.bd_configs[rv].bd_id = bd_id; + l2input_main.bd_configs[rv].learn_limit = + l2learn_main.bd_default_learn_limit; + l2input_main.bd_configs[rv].learn_count = 0; return rv; } @@ -123,6 +127,8 @@ bd_delete (bd_main_t * bdm, u32 bd_index) /* clear BD config for reuse: bd_id to -1 and clear feature_bitmap */ bd->bd_id = ~0; bd->feature_bitmap = 0; + bd->learn_limit = 0; + bd->learn_count = ~0; /* free BD tag */ vec_free (bd->bd_tag); @@ -228,7 +234,7 @@ l2bd_init (vlib_main_t * vm) bd_main_t *bdm = &bd_main; bdm->bd_index_by_bd_id = hash_create (0, sizeof (uword)); /* - * create a dummy bd with bd_id of 0 and bd_index of 0 with feature set + * create a placeholder bd with bd_id of 0 and bd_index of 0 with feature set * to packet drop only. Thus, packets received from any L2 interface with * uninitialized bd_index of 0 can be dropped safely. */ @@ -242,6 +248,43 @@ l2bd_init (vlib_main_t * vm) VLIB_INIT_FUNCTION (l2bd_init); +l2_bridge_domain_t * +bd_get (u32 bd_index) +{ + if (bd_index < vec_len (l2input_main.bd_configs)) + return (vec_elt_at_index (l2input_main.bd_configs, bd_index)); + return (NULL); +} + +u32 +bd_input_walk (u32 bd_index, bd_input_walk_fn_t fn, void *data) +{ + l2_flood_member_t *member; + l2_bridge_domain_t *bd; + u32 sw_if_index; + + sw_if_index = ~0; + bd = bd_get (bd_index); + + ASSERT (bd); + + vec_foreach (member, bd->members) + { + if (WALK_STOP == fn (bd_index, member->sw_if_index)) + { + sw_if_index = member->sw_if_index; + break; + } + } + + return (sw_if_index); +} + +static void +b2_input_recache (u32 bd_index) +{ + bd_input_walk (bd_index, l2input_recache, NULL); +} /** Set the learn/forward/flood flags for the bridge domain. @@ -275,6 +318,10 @@ bd_set_flags (vlib_main_t * vm, u32 bd_index, bd_flags_t flags, u32 enable) { feature_bitmap |= L2INPUT_FEAT_ARP_TERM; } + if (flags & L2_ARP_UFWD) + { + feature_bitmap |= L2INPUT_FEAT_ARP_UFWD; + } if (enable) { @@ -285,6 +332,8 @@ bd_set_flags (vlib_main_t * vm, u32 bd_index, bd_flags_t flags, u32 enable) bd_config->feature_bitmap &= ~feature_bitmap; } + b2_input_recache (bd_index); + return bd_config->feature_bitmap; } @@ -300,6 +349,7 @@ bd_set_mac_age (vlib_main_t * vm, u32 bd_index, u8 age) vec_validate (l2input_main.bd_configs, bd_index); bd_config = vec_elt_at_index (l2input_main.bd_configs, bd_index); bd_config->mac_age = age; + b2_input_recache (bd_index); /* check if there is at least one bd with mac aging enabled */ vec_foreach (bd_config, l2input_main.bd_configs) @@ -311,9 +361,20 @@ bd_set_mac_age (vlib_main_t * vm, u32 bd_index, u8 age) } /** - Set the tag for the bridge domain. + Set learn limit for the bridge domain. */ +void +bd_set_learn_limit (vlib_main_t *vm, u32 bd_index, u32 learn_limit) +{ + l2_bridge_domain_t *bd_config; + vec_validate (l2input_main.bd_configs, bd_index); + bd_config = vec_elt_at_index (l2input_main.bd_configs, bd_index); + bd_config->learn_limit = learn_limit; +} +/** + Set the tag for the bridge domain. +*/ static void bd_set_bd_tag (vlib_main_t * vm, u32 bd_index, u8 * bd_tag) { @@ -401,6 +462,34 @@ VLIB_CLI_COMMAND (bd_learn_cli, static) = { }; /* *INDENT-ON* */ +static clib_error_t * +bd_default_learn_limit (vlib_main_t *vm, unformat_input_t *input, + vlib_cli_command_t *cmd) +{ + l2learn_main_t *l2m = &l2learn_main; + clib_error_t *error = 0; + u32 learn_limit; + + if (!unformat (input, "%d", &learn_limit)) + { + error = clib_error_return ( + 0, "expecting per bridge-domain max entry number got`%U'", + format_unformat_error, input); + goto done; + } + + l2m->bd_default_learn_limit = learn_limit; + +done: + return error; +} + +VLIB_CLI_COMMAND (bd_default_learn_limit_cli, static) = { + .path = "set bridge-domain default-learn-limit", + .short_help = "set bridge-domain default-learn-limit ", + .function = bd_default_learn_limit, +}; + /** Set bridge-domain forward enable/disable. The CLI format is: @@ -596,6 +685,71 @@ VLIB_CLI_COMMAND (bd_uu_flood_cli, static) = { }; /* *INDENT-ON* */ +/** + Set bridge-domain arp-unicast forward enable/disable. + The CLI format is: + set bridge-domain arp-ufwd [disable] +*/ +static clib_error_t * +bd_arp_ufwd (vlib_main_t * vm, + unformat_input_t * input, vlib_cli_command_t * cmd) +{ + bd_main_t *bdm = &bd_main; + clib_error_t *error = 0; + u32 bd_index, bd_id; + u32 enable; + uword *p; + + if (!unformat (input, "%d", &bd_id)) + { + error = clib_error_return (0, "expecting bridge-domain id but got `%U'", + format_unformat_error, input); + goto done; + } + + if (bd_id == 0) + return clib_error_return (0, + "No operations on the default bridge domain are supported"); + + p = hash_get (bdm->bd_index_by_bd_id, bd_id); + + if (p == 0) + return clib_error_return (0, "No such bridge domain %d", bd_id); + + bd_index = p[0]; + + enable = 1; + if (unformat (input, "disable")) + { + enable = 0; + } + + /* set the bridge domain flag */ + bd_set_flags (vm, bd_index, L2_ARP_UFWD, enable); + +done: + return error; +} + +/*? + * Layer 2 arp-unicast forwarding can be enabled and disabled on each + * bridge-domain. It is disabled by default. + * + * @cliexpar + * Example of how to enable arp-unicast forwarding (where 200 is the + * bridge-domain-id): + * @cliexcmd{set bridge-domain arp-ufwd 200} + * Example of how to disable arp-unicast forwarding (where 200 is the bridge-domain-id): + * @cliexcmd{set bridge-domain arp-ufwd 200 disable} +?*/ +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (bd_arp_ufwd_cli, static) = { + .path = "set bridge-domain arp-ufwd", + .short_help = "set bridge-domain arp-ufwd [disable]", + .function = bd_arp_ufwd, +}; +/* *INDENT-ON* */ + /** Set bridge-domain arp term enable/disable. The CLI format is: @@ -708,6 +862,55 @@ VLIB_CLI_COMMAND (bd_mac_age_cli, static) = { }; /* *INDENT-ON* */ +static clib_error_t * +bd_learn_limit (vlib_main_t *vm, unformat_input_t *input, + vlib_cli_command_t *cmd) +{ + bd_main_t *bdm = &bd_main; + clib_error_t *error = 0; + u32 bd_index, bd_id; + u32 learn_limit; + uword *p; + + if (!unformat (input, "%d", &bd_id)) + { + error = clib_error_return (0, "expecting bridge-domain id but got `%U'", + format_unformat_error, input); + goto done; + } + + if (bd_id == 0) + return clib_error_return ( + 0, "No operations on the default bridge domain are supported"); + + p = hash_get (bdm->bd_index_by_bd_id, bd_id); + + if (p == 0) + return clib_error_return (0, "No such bridge domain %d", bd_id); + + bd_index = p[0]; + + if (!unformat (input, "%u", &learn_limit)) + { + error = clib_error_return ( + 0, "expecting maxium number of learned entries but got `%U'", + format_unformat_error, input); + goto done; + } + + bd_set_learn_limit (vm, bd_index, learn_limit); + +done: + return error; +} + +VLIB_CLI_COMMAND (bd_learn_limit_cli, static) = { + .path = "set bridge-domain learn-limit", + .short_help = + "set bridge-domain learn-limit ", + .function = bd_learn_limit, +}; + /*? * Modify whether or not an existing bridge-domain should terminate and respond * to ARP Requests. ARP Termination is disabled by default. @@ -924,41 +1127,6 @@ VLIB_CLI_COMMAND (bd_arp_entry_cli, static) = { }; /* *INDENT-ON* */ -static u8 * -format_vtr (u8 * s, va_list * args) -{ - u32 vtr_op = va_arg (*args, u32); - u32 dot1q = va_arg (*args, u32); - u32 tag1 = va_arg (*args, u32); - u32 tag2 = va_arg (*args, u32); - switch (vtr_op) - { - case L2_VTR_DISABLED: - return format (s, "none"); - case L2_VTR_PUSH_1: - return format (s, "push-1 %s %d", dot1q ? "dot1q" : "dot1ad", tag1); - case L2_VTR_PUSH_2: - return format (s, "push-2 %s %d %d", dot1q ? "dot1q" : "dot1ad", tag1, - tag2); - case L2_VTR_POP_1: - return format (s, "pop-1"); - case L2_VTR_POP_2: - return format (s, "pop-2"); - case L2_VTR_TRANSLATE_1_1: - return format (s, "trans-1-1 %s %d", dot1q ? "dot1q" : "dot1ad", tag1); - case L2_VTR_TRANSLATE_1_2: - return format (s, "trans-1-2 %s %d %d", dot1q ? "dot1q" : "dot1ad", - tag1, tag2); - case L2_VTR_TRANSLATE_2_1: - return format (s, "trans-2-1 %s %d", dot1q ? "dot1q" : "dot1ad", tag1); - case L2_VTR_TRANSLATE_2_2: - return format (s, "trans-2-2 %s %d %d", dot1q ? "dot1q" : "dot1ad", - tag1, tag2); - default: - return format (s, "none"); - } -} - static u8 * format_uu_cfg (u8 * s, va_list * args) { @@ -1046,30 +1214,35 @@ bd_show (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd) { printed = 1; vlib_cli_output (vm, - "%=8s %=7s %=4s %=9s %=9s %=9s %=11s %=9s %=9s %=11s", - "BD-ID", "Index", "BSN", "Age(min)", - "Learning", "U-Forwrd", "UU-Flood", - "Flooding", "ARP-Term", "BVI-Intf"); + "%=8s %=7s %=4s %=9s %=9s %=9s %=11s %=9s %=9s " + "%=9s %=8s %=8s %=11s", + "BD-ID", "Index", "BSN", "Age(min)", "Learning", + "U-Forwrd", "UU-Flood", "Flooding", "ARP-Term", + "arp-ufwd", "Learn-count", "Learn-limit", + "BVI-Intf"); } if (bd_config->mac_age) as = format (as, "%d", bd_config->mac_age); else as = format (as, "off"); - vlib_cli_output (vm, - "%=8d %=7d %=4d %=9v %=9s %=9s %=11U %=9s %=9s %=11U", - bd_config->bd_id, bd_index, bd_config->seq_num, as, - bd_config->feature_bitmap & L2INPUT_FEAT_LEARN ? - "on" : "off", - bd_config->feature_bitmap & L2INPUT_FEAT_FWD ? - "on" : "off", - format_uu_cfg, bd_config, - bd_config->feature_bitmap & L2INPUT_FEAT_FLOOD ? - "on" : "off", - bd_config->feature_bitmap & L2INPUT_FEAT_ARP_TERM ? - "on" : "off", - format_vnet_sw_if_index_name_with_NA, - vnm, bd_config->bvi_sw_if_index); + vlib_cli_output ( + vm, + "%=8d %=7d %=4d %=9v %=9s %=9s %=11U %=9s %=9s %=9s %=8d %=8d " + "%=11U", + bd_config->bd_id, bd_index, bd_config->seq_num, as, + bd_config->feature_bitmap & L2INPUT_FEAT_LEARN ? "on" : "off", + bd_config->feature_bitmap & L2INPUT_FEAT_FWD ? "on" : "off", + format_uu_cfg, bd_config, + bd_config->feature_bitmap & L2INPUT_FEAT_FLOOD ? "on" : "off", + bd_config->feature_bitmap & L2INPUT_FEAT_ARP_TERM ? "on" : "off", + bd_config->feature_bitmap & L2INPUT_FEAT_ARP_UFWD ? "on" : "off", + bd_config->learn_count, bd_config->learn_limit, + format_vnet_sw_if_index_name_with_NA, vnm, + bd_config->bvi_sw_if_index); + if (detail) + vlib_cli_output (vm, "%U", format_l2_input_feature_bitmap, + bd_config->feature_bitmap); vec_reset_length (as); if (detail || intf) @@ -1080,7 +1253,7 @@ bd_show (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd) { l2_flood_member_t *member = vec_elt_at_index (bd_config->members, i); - u8 swif_seq_num = *l2fib_swif_seq_num (member->sw_if_index); + u8 swif_seq_num = l2_input_seq_num (member->sw_if_index); u32 vtr_opr, dot1q, tag1, tag2; if (i == 0) { @@ -1188,9 +1361,13 @@ int bd_add_del (l2_bridge_domain_add_del_args_t * a) { bd_main_t *bdm = &bd_main; + l2fib_main_t *fm = &l2fib_main; vlib_main_t *vm = bdm->vlib_main; int rv = 0; + if (fm->mac_table_initialized == 0) + l2fib_table_init (); + u32 bd_index = bd_find_index (bdm, a->bd_id); if (a->is_add) { @@ -1226,6 +1403,11 @@ bd_add_del (l2_bridge_domain_add_del_args_t * a) else disable_flags |= L2_ARP_TERM; + if (a->arp_ufwd) + enable_flags |= L2_ARP_UFWD; + else + disable_flags |= L2_ARP_UFWD; + if (enable_flags) bd_set_flags (vm, bd_index, enable_flags, 1 /* enable */ ); @@ -1237,6 +1419,8 @@ bd_add_del (l2_bridge_domain_add_del_args_t * a) if (a->bd_tag) bd_set_bd_tag (vm, bd_index, a->bd_tag); + bd_set_learn_limit (vm, bd_index, l2learn_main.bd_default_learn_limit); + vec_elt_at_index (l2input_main.bd_configs, bd_index)->learn_count = 0; } else { @@ -1267,7 +1451,8 @@ bd_add_del_command_fn (vlib_main_t * vm, unformat_input_t * input, clib_error_t *error = 0; u8 is_add = 1; u32 bd_id = ~0; - u32 flood = 1, forward = 1, learn = 1, uu_flood = 1, arp_term = 0; + u32 flood = 1, forward = 1, learn = 1, uu_flood = 1, arp_term = + 0, arp_ufwd = 0; u32 mac_age = 0; u8 *bd_tag = NULL; l2_bridge_domain_add_del_args_t _a, *a = &_a; @@ -1291,6 +1476,8 @@ bd_add_del_command_fn (vlib_main_t * vm, unformat_input_t * input, ; else if (unformat (line_input, "arp-term %d", &arp_term)) ; + else if (unformat (line_input, "arp-ufwd %d", &arp_ufwd)) + ; else if (unformat (line_input, "mac-age %d", &mac_age)) ; else if (unformat (line_input, "bd-tag %s", &bd_tag)) @@ -1335,6 +1522,7 @@ bd_add_del_command_fn (vlib_main_t * vm, unformat_input_t * input, a->forward = (u8) forward; a->learn = (u8) learn; a->arp_term = (u8) arp_term; + a->arp_ufwd = (u8) arp_ufwd; a->mac_age = (u8) mac_age; a->bd_tag = bd_tag; @@ -1404,7 +1592,7 @@ VLIB_CLI_COMMAND (bd_create_cli, static) = { .path = "create bridge-domain", .short_help = "create bridge-domain " " [learn <0|1>] [forward <0|1>] [uu-flood <0|1>] [flood <0|1>] [arp-term <0|1>]" - " [mac-age ] [bd-tag ] [del]", + " [arp-ufwd <0|1>] [mac-age ] [bd-tag ] [del]", .function = bd_add_del_command_fn, }; /* *INDENT-ON* */