X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvnet%2Fl2%2Fl2_input.c;h=f60dd189e0af59dda5355675bd6718bbadbdd527;hb=57938f63cc6743193c76d4fa89ad3250a5f76b56;hp=a104ec9eebb2813302b544871e6adbc384ee4c91;hpb=7cd468a3d7dee7d6c92f69a0bb7061ae208ec727;p=vpp.git diff --git a/src/vnet/l2/l2_input.c b/src/vnet/l2/l2_input.c index a104ec9eebb..f60dd189e0a 100644 --- a/src/vnet/l2/l2_input.c +++ b/src/vnet/l2/l2_input.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -59,6 +60,29 @@ l2input_get_feat_names (void) return l2input_feat_names; } +u8 * +format_l2_input_features (u8 * s, va_list * args) +{ + static char *display_names[] = { +#define _(sym,name) #sym, + foreach_l2input_feat +#undef _ + }; + u32 feature_bitmap = va_arg (*args, u32); + + if (feature_bitmap == 0) + { + s = format (s, " none configured"); + return s; + } + + feature_bitmap &= ~L2INPUT_FEAT_DROP; /* Not a feature */ + int i; + for (i = L2INPUT_N_FEAT; i >= 0; i--) + if (feature_bitmap & (1 << i)) + s = format (s, "%10s (%s)\n", display_names[i], l2input_feat_names[i]); + return s; +} typedef struct { @@ -114,10 +138,7 @@ typedef enum static_always_inline void -classify_and_dispatch (vlib_main_t * vm, - vlib_node_runtime_t * node, - u32 cpu_index, - l2input_main_t * msm, vlib_buffer_t * b0, u32 * next0) +classify_and_dispatch (l2input_main_t * msm, vlib_buffer_t * b0, u32 * next0) { /* * Load L2 input feature struct @@ -186,12 +207,7 @@ classify_and_dispatch (vlib_main_t * vm, } - if (config->xconnect) - { - /* Set the output interface */ - vnet_buffer (b0)->sw_if_index[VLIB_TX] = config->output_sw_if_index; - } - else + if (config->bridge) { /* Do bridge-domain processing */ bd_index0 = config->bd_index; @@ -201,6 +217,16 @@ classify_and_dispatch (vlib_main_t * vm, /* Get config for the bridge domain interface */ bd_config = vec_elt_at_index (msm->bd_configs, bd_index0); + /* Save bridge domain and interface seq_num */ + /* *INDENT-OFF* */ + l2fib_seq_num_t sn = { + .swif = *l2fib_swif_seq_num(sw_if_index0), + .bd = bd_config->seq_num, + }; + /* *INDENT-ON* */ + vnet_buffer (b0)->l2.l2fib_sn = sn.as_u16;; + vnet_buffer (b0)->l2.bd_age = bd_config->mac_age; + /* * Process bridge domain feature enables. * To perform learning/flooding/forwarding, the corresponding bit @@ -210,6 +236,13 @@ classify_and_dispatch (vlib_main_t * vm, */ feat_mask = feat_mask & bd_config->feature_bitmap; } + else if (config->xconnect) + { + /* Set the output interface */ + vnet_buffer (b0)->sw_if_index[VLIB_TX] = config->output_sw_if_index; + } + else + feat_mask = L2INPUT_FEAT_DROP; /* mask out features from bitmap using packet type and bd config */ feature_bitmap = config->feature_bitmap & feat_mask; @@ -222,15 +255,14 @@ classify_and_dispatch (vlib_main_t * vm, feature_bitmap); } - -static uword -l2input_node_fn (vlib_main_t * vm, - vlib_node_runtime_t * node, vlib_frame_t * frame) +static_always_inline uword +l2input_node_inline (vlib_main_t * vm, + vlib_node_runtime_t * node, vlib_frame_t * frame, + int do_trace) { u32 n_left_from, *from, *to_next; l2input_next_t next_index; l2input_main_t *msm = &l2input_main; - u32 cpu_index = os_get_cpu_number (); from = vlib_frame_vector_args (frame); n_left_from = frame->n_vectors; /* number of packets to process */ @@ -294,7 +326,7 @@ l2input_node_fn (vlib_main_t * vm, b2 = vlib_get_buffer (vm, bi2); b3 = vlib_get_buffer (vm, bi3); - if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE))) + if (do_trace) { /* RX interface handles */ sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX]; @@ -343,10 +375,10 @@ l2input_node_fn (vlib_main_t * vm, vlib_node_increment_counter (vm, l2input_node.index, L2INPUT_ERROR_L2INPUT, 4); - classify_and_dispatch (vm, node, cpu_index, msm, b0, &next0); - classify_and_dispatch (vm, node, cpu_index, msm, b1, &next1); - classify_and_dispatch (vm, node, cpu_index, msm, b2, &next2); - classify_and_dispatch (vm, node, cpu_index, msm, b3, &next3); + classify_and_dispatch (msm, b0, &next0); + classify_and_dispatch (msm, b1, &next1); + classify_and_dispatch (msm, b2, &next2); + classify_and_dispatch (msm, b3, &next3); /* verify speculative enqueues, maybe switch current next frame */ /* if next0==next1==next_index then nothing special needs to be done */ @@ -373,8 +405,7 @@ l2input_node_fn (vlib_main_t * vm, b0 = vlib_get_buffer (vm, bi0); - if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE) - && (b0->flags & VLIB_BUFFER_IS_TRACED))) + if (do_trace && PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED)) { ethernet_header_t *h0 = vlib_buffer_get_current (b0); l2input_trace_t *t = vlib_add_trace (vm, node, b0, sizeof (*t)); @@ -387,7 +418,7 @@ l2input_node_fn (vlib_main_t * vm, vlib_node_increment_counter (vm, l2input_node.index, L2INPUT_ERROR_L2INPUT, 1); - classify_and_dispatch (vm, node, cpu_index, msm, b0, &next0); + classify_and_dispatch (msm, b0, &next0); /* verify speculative enqueue, maybe switch current next frame */ vlib_validate_buffer_enqueue_x1 (vm, node, next_index, @@ -401,6 +432,14 @@ l2input_node_fn (vlib_main_t * vm, return frame->n_vectors; } +static uword +l2input_node_fn (vlib_main_t * vm, + vlib_node_runtime_t * node, vlib_frame_t * frame) +{ + if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE))) + return l2input_node_inline (vm, node, frame, 1 /* do_trace */ ); + return l2input_node_inline (vm, node, frame, 0 /* do_trace */ ); +} /* *INDENT-OFF* */ VLIB_REGISTER_NODE (l2input_node) = { @@ -467,20 +506,12 @@ l2input_intf_config (u32 sw_if_index) u32 l2input_intf_bitmap_enable (u32 sw_if_index, u32 feature_bitmap, u32 enable) { - l2input_main_t *mp = &l2input_main; - l2_input_config_t *config; - - vec_validate (mp->configs, sw_if_index); - config = vec_elt_at_index (mp->configs, sw_if_index); + l2_input_config_t *config = l2input_intf_config (sw_if_index); if (enable) - { - config->feature_bitmap |= feature_bitmap; - } + config->feature_bitmap |= feature_bitmap; else - { - config->feature_bitmap &= ~feature_bitmap; - } + config->feature_bitmap &= ~feature_bitmap; return config->feature_bitmap; } @@ -488,9 +519,7 @@ l2input_intf_bitmap_enable (u32 sw_if_index, u32 feature_bitmap, u32 enable) u32 l2input_set_bridge_features (u32 bd_index, u32 feat_mask, u32 feat_value) { - 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); + l2_bridge_domain_t *bd_config = l2input_bd_config (bd_index);; bd_validate (bd_config); bd_config->feature_bitmap = (bd_config->feature_bitmap & ~feat_mask) | feat_value; @@ -506,10 +535,13 @@ l2input_set_bridge_features (u32 bd_index, u32 feat_mask, u32 feat_value) */ u32 -set_int_l2_mode (vlib_main_t * vm, vnet_main_t * vnet_main, u32 mode, u32 sw_if_index, u32 bd_index, /* for bridged interface */ - u32 bvi, /* the bridged interface is the BVI */ - u32 shg, /* the bridged interface's split horizon group */ - u32 xc_sw_if_index) /* peer interface for xconnect */ +set_int_l2_mode (vlib_main_t * vm, vnet_main_t * vnet_main, /* */ + u32 mode, /* One of L2 modes or back to L3 mode */ + u32 sw_if_index, /* sw interface index */ + u32 bd_index, /* for bridged interface */ + u32 bvi, /* the bridged interface is the BVI */ + u32 shg, /* the bridged interface split horizon group */ + u32 xc_sw_if_index) /* peer interface for xconnect */ { l2input_main_t *mp = &l2input_main; l2output_main_t *l2om = &l2output_main; @@ -518,8 +550,6 @@ set_int_l2_mode (vlib_main_t * vm, vnet_main_t * vnet_main, u32 mode, u32 sw_if_ l2_output_config_t *out_config; l2_input_config_t *config; l2_bridge_domain_t *bd_config; - l2_flood_member_t member; - u64 mac; i32 l2_if_adjust = 0; u32 slot; @@ -541,8 +571,7 @@ set_int_l2_mode (vlib_main_t * vm, vnet_main_t * vnet_main, u32 mode, u32 sw_if_ config->bvi = 0; /* delete the l2fib entry for the bvi interface */ - mac = *((u64 *) hi->hw_address); - l2fib_del_entry (mac, config->bd_index); + l2fib_del_entry (hi->hw_address, config->bd_index); /* Make loop output node send packet back to ethernet-input node */ slot = @@ -551,6 +580,12 @@ set_int_l2_mode (vlib_main_t * vm, vnet_main_t * vnet_main, u32 mode, u32 sw_if_ VNET_SIMULATED_ETHERNET_TX_NEXT_ETHERNET_INPUT); ASSERT (slot == VNET_SIMULATED_ETHERNET_TX_NEXT_ETHERNET_INPUT); } + + /* Clear MACs learned on the interface */ + if ((config->feature_bitmap & L2INPUT_FEAT_LEARN) || + (bd_config->feature_bitmap & L2INPUT_FEAT_LEARN)) + l2fib_flush_int_mac (vm, sw_if_index); + l2_if_adjust--; } else if (config->xconnect) @@ -558,13 +593,9 @@ set_int_l2_mode (vlib_main_t * vm, vnet_main_t * vnet_main, u32 mode, u32 sw_if_ l2_if_adjust--; } - /* - * Directs the l2 output path to work out the interface - * output next-arc itself. Needed when recycling a sw_if_index. - */ - vec_validate_init_empty (l2om->next_nodes.output_node_index_vec, - sw_if_index, ~0); - l2om->next_nodes.output_node_index_vec[sw_if_index] = ~0; + /* Make sure vector is big enough */ + vec_validate_init_empty (l2om->output_node_index_vec, sw_if_index, + L2OUTPUT_NEXT_DROP); /* Initialize the l2-input configuration for the interface */ if (mode == MODE_L3) @@ -577,31 +608,19 @@ set_int_l2_mode (vlib_main_t * vm, vnet_main_t * vnet_main, u32 mode, u32 sw_if_ config->bd_index = 0; config->feature_bitmap = L2INPUT_FEAT_DROP; + /* Clear L2 output config */ + out_config = l2output_intf_config (sw_if_index); + memset (out_config, 0, sizeof (l2_output_config_t)); + /* Make sure any L2-output packet to this interface now in L3 mode is * dropped. This may happen if L2 FIB MAC entry is stale */ - l2om->next_nodes.output_node_index_vec[sw_if_index] = - L2OUTPUT_NEXT_BAD_INTF; - } - else if (mode == MODE_L2_CLASSIFY) - { - config->xconnect = 1; - config->bridge = 0; - config->output_sw_if_index = xc_sw_if_index; - - /* Make sure last-chance drop is configured */ - config->feature_bitmap |= - L2INPUT_FEAT_DROP | L2INPUT_FEAT_INPUT_CLASSIFY; - - /* Make sure bridging features are disabled */ - config->feature_bitmap &= - ~(L2INPUT_FEAT_LEARN | L2INPUT_FEAT_FWD | L2INPUT_FEAT_FLOOD); - shg = 0; /* not used in xconnect */ - - /* Insure all packets go to ethernet-input */ - ethernet_set_rx_redirect (vnet_main, hi, 1); + l2om->output_node_index_vec[sw_if_index] = L2OUTPUT_NEXT_BAD_INTF; } else { + /* Add or update l2-output node next-arc and output_node_index_vec table + * for the interface */ + l2output_create_output_node_mapping (vm, vnet_main, sw_if_index); if (mode == MODE_L2_BRIDGE) { @@ -618,6 +637,7 @@ set_int_l2_mode (vlib_main_t * vm, vnet_main_t * vnet_main, u32 mode, u32 sw_if_ config->xconnect = 0; config->bridge = 1; config->bd_index = bd_index; + *l2fib_valid_swif_seq_num (sw_if_index) += 1; /* * Enable forwarding, flooding, learning and ARP termination by default @@ -633,8 +653,7 @@ set_int_l2_mode (vlib_main_t * vm, vnet_main_t * vnet_main, u32 mode, u32 sw_if_ config->feature_bitmap &= ~L2INPUT_FEAT_XCONNECT; /* Set up bridge domain */ - vec_validate (mp->bd_configs, bd_index); - bd_config = vec_elt_at_index (mp->bd_configs, bd_index); + bd_config = l2input_bd_config (bd_index); bd_validate (bd_config); /* TODO: think: add l2fib entry even for non-bvi interface? */ @@ -651,8 +670,7 @@ set_int_l2_mode (vlib_main_t * vm, vnet_main_t * vnet_main, u32 mode, u32 sw_if_ config->bvi = 1; /* create the l2fib entry for the bvi interface */ - mac = *((u64 *) hi->hw_address); - l2fib_add_entry (mac, bd_index, sw_if_index, 1, 0, 1); /* static + bvi */ + l2fib_add_fwd_entry (hi->hw_address, bd_index, sw_if_index, 1, 1); /* static + bvi */ /* Disable learning by default. no use since l2fib entry is static. */ config->feature_bitmap &= ~L2INPUT_FEAT_LEARN; @@ -666,13 +684,15 @@ set_int_l2_mode (vlib_main_t * vm, vnet_main_t * vnet_main, u32 mode, u32 sw_if_ } /* Add interface to bridge-domain flood vector */ - member.sw_if_index = sw_if_index; - member.flags = bvi ? L2_FLOOD_MEMBER_BVI : L2_FLOOD_MEMBER_NORMAL; - member.shg = shg; + l2_flood_member_t member = { + .sw_if_index = sw_if_index, + .flags = bvi ? L2_FLOOD_MEMBER_BVI : L2_FLOOD_MEMBER_NORMAL, + .shg = shg, + }; bd_add_member (bd_config, &member); } - else + else if (mode == MODE_L2_XC) { config->xconnect = 1; config->bridge = 0; @@ -688,11 +708,30 @@ set_int_l2_mode (vlib_main_t * vm, vnet_main_t * vnet_main, u32 mode, u32 sw_if_ config->feature_bitmap |= L2INPUT_FEAT_XCONNECT; shg = 0; /* not used in xconnect */ } + else if (mode == MODE_L2_CLASSIFY) + { + config->xconnect = 1; + config->bridge = 0; + config->output_sw_if_index = xc_sw_if_index; + + /* Make sure last-chance drop is configured */ + config->feature_bitmap |= + L2INPUT_FEAT_DROP | L2INPUT_FEAT_INPUT_CLASSIFY; + + /* Make sure bridging features are disabled */ + config->feature_bitmap &= + ~(L2INPUT_FEAT_LEARN | L2INPUT_FEAT_FWD | L2INPUT_FEAT_FLOOD); + shg = 0; /* not used in xconnect */ + + /* Insure all packets go to ethernet-input */ + ethernet_set_rx_redirect (vnet_main, hi, 1); + } - /* set up split-horizon group */ + /* set up split-horizon group and set output feature bit */ config->shg = shg; out_config = l2output_intf_config (sw_if_index); out_config->shg = shg; + out_config->feature_bitmap |= L2OUTPUT_FEAT_OUTPUT; /* * Test: remove this when non-IP features can be configured. @@ -769,6 +808,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 */ @@ -968,10 +1013,8 @@ show_int_mode (vlib_main_t * vm, char *mode; u8 *args; vnet_interface_main_t *im = &vnm->interface_main; - vnet_sw_interface_t *si, *sis = 0; - l2input_main_t *mp = &l2input_main; - l2_input_config_t *config; + vnet_sw_interface_t *si, *sis = 0; while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { u32 sw_if_index; @@ -989,7 +1032,6 @@ show_int_mode (vlib_main_t * vm, format_unformat_error, input); goto done; } - } if (vec_len (sis) == 0) /* Get all interfaces */ @@ -1004,8 +1046,7 @@ show_int_mode (vlib_main_t * vm, vec_foreach (si, sis) { - vec_validate (mp->configs, si->sw_if_index); - config = vec_elt_at_index (mp->configs, si->sw_if_index); + l2_input_config_t *config = l2input_intf_config (si->sw_if_index); if (config->bridge) { u32 bd_id;