X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvnet%2Fspan%2Fspan.c;h=b7292cf1e800d8ea55b45180ee9cb79d0a354563;hb=refs%2Fchanges%2F72%2F8972%2F1;hp=c5b43e343c42d3087c1c9a98057de7df2de50b4a;hpb=13ad1f02922858177915b1cb1450041d2e4d85de;p=vpp.git diff --git a/src/vnet/span/span.c b/src/vnet/span/span.c index c5b43e343c4..b7292cf1e80 100644 --- a/src/vnet/span/span.c +++ b/src/vnet/span/span.c @@ -16,67 +16,114 @@ #include #include #include +#include +#include #include +span_main_t span_main; + +typedef enum +{ + SPAN_DISABLE = 0, + SPAN_RX = 1, + SPAN_TX = 2, + SPAN_BOTH = SPAN_RX | SPAN_TX +} span_state_t; + +static_always_inline u32 +span_dst_set (span_mirror_t * sm, u32 dst_sw_if_index, int enable) +{ + if (dst_sw_if_index == ~0) + { + ASSERT (enable == 0); + clib_bitmap_zero (sm->mirror_ports); + } + else + sm->mirror_ports = + clib_bitmap_set (sm->mirror_ports, dst_sw_if_index, enable); + + u32 last = sm->num_mirror_ports; + sm->num_mirror_ports = clib_bitmap_count_set_bits (sm->mirror_ports); + return last; +} + int span_add_delete_entry (vlib_main_t * vm, - u32 src_sw_if_index, u32 dst_sw_if_index, u8 state) + u32 src_sw_if_index, u32 dst_sw_if_index, u8 state, + span_feat_t sf) { span_main_t *sm = &span_main; - span_interface_t *si; - u32 new_num_rx_mirror_ports, new_num_tx_mirror_ports; - if (state > 3) + if (state > SPAN_BOTH) return VNET_API_ERROR_UNIMPLEMENTED; if ((src_sw_if_index == ~0) || (dst_sw_if_index == ~0 && state > 0) || (src_sw_if_index == dst_sw_if_index)) return VNET_API_ERROR_INVALID_INTERFACE; - vnet_sw_interface_t *sw_if; - - sw_if = vnet_get_sw_interface (vnet_get_main (), src_sw_if_index); - if (sw_if->type == VNET_SW_INTERFACE_TYPE_SUB) - return VNET_API_ERROR_UNIMPLEMENTED; - vec_validate_aligned (sm->interfaces, src_sw_if_index, CLIB_CACHE_LINE_BYTES); - si = vec_elt_at_index (sm->interfaces, src_sw_if_index); - si->rx_mirror_ports = clib_bitmap_set (si->rx_mirror_ports, dst_sw_if_index, - (state & 1) != 0); - si->tx_mirror_ports = clib_bitmap_set (si->tx_mirror_ports, dst_sw_if_index, - (state & 2) != 0); + span_interface_t *si = vec_elt_at_index (sm->interfaces, src_sw_if_index); - new_num_rx_mirror_ports = clib_bitmap_count_set_bits (si->rx_mirror_ports); - new_num_tx_mirror_ports = clib_bitmap_count_set_bits (si->tx_mirror_ports); + int rx = ! !(state & SPAN_RX); + int tx = ! !(state & SPAN_TX); - if (new_num_rx_mirror_ports == 1 && si->num_rx_mirror_ports == 0) - vnet_feature_enable_disable ("device-input", "span-input", - src_sw_if_index, 1, 0, 0); + span_mirror_t *rxm = &si->mirror_rxtx[sf][VLIB_RX]; + span_mirror_t *txm = &si->mirror_rxtx[sf][VLIB_TX]; - if (new_num_rx_mirror_ports == 0 && si->num_rx_mirror_ports == 1) - vnet_feature_enable_disable ("device-input", "span-input", - src_sw_if_index, 0, 0, 0); + u32 last_rx_ports_count = span_dst_set (rxm, dst_sw_if_index, rx); + u32 last_tx_ports_count = span_dst_set (txm, dst_sw_if_index, tx); - if (new_num_rx_mirror_ports == 1 && si->num_rx_mirror_ports == 0) - vnet_feature_enable_disable ("interface-output", "span-output", - src_sw_if_index, 1, 0, 0); + int enable_rx = last_rx_ports_count == 0 && rxm->num_mirror_ports == 1; + int disable_rx = last_rx_ports_count > 0 && rxm->num_mirror_ports == 0; + int enable_tx = last_tx_ports_count == 0 && txm->num_mirror_ports == 1; + int disable_tx = last_tx_ports_count > 0 && txm->num_mirror_ports == 0; - if (new_num_rx_mirror_ports == 0 && si->num_rx_mirror_ports == 1) - vnet_feature_enable_disable ("interface-output", "span-output", - src_sw_if_index, 0, 0, 0); - - si->num_rx_mirror_ports = new_num_rx_mirror_ports; - si->num_tx_mirror_ports = new_num_tx_mirror_ports; + switch (sf) + { + case SPAN_FEAT_DEVICE: + if (enable_rx || disable_rx) + vnet_feature_enable_disable ("device-input", "span-input", + src_sw_if_index, rx, 0, 0); + if (enable_tx || disable_tx) + vnet_feature_enable_disable ("interface-output", "span-output", + src_sw_if_index, tx, 0, 0); + break; + case SPAN_FEAT_L2: + if (enable_rx || disable_rx) + l2input_intf_bitmap_enable (src_sw_if_index, L2INPUT_FEAT_SPAN, rx); + if (enable_tx || disable_tx) + l2output_intf_bitmap_enable (src_sw_if_index, L2OUTPUT_FEAT_SPAN, tx); + break; + default: + return VNET_API_ERROR_UNIMPLEMENTED; + } - if (dst_sw_if_index > sm->max_sw_if_index) + if (dst_sw_if_index != ~0 && dst_sw_if_index > sm->max_sw_if_index) sm->max_sw_if_index = dst_sw_if_index; return 0; } +static uword +unformat_span_state (unformat_input_t * input, va_list * args) +{ + span_state_t *state = va_arg (*args, span_state_t *); + if (unformat (input, "disable")) + *state = SPAN_DISABLE; + else if (unformat (input, "rx")) + *state = SPAN_RX; + else if (unformat (input, "tx")) + *state = SPAN_TX; + else if (unformat (input, "both")) + *state = SPAN_BOTH; + else + return 0; + return 1; +} + static clib_error_t * set_interface_span_command_fn (vlib_main_t * vm, unformat_input_t * input, @@ -85,7 +132,9 @@ set_interface_span_command_fn (vlib_main_t * vm, span_main_t *sm = &span_main; u32 src_sw_if_index = ~0; u32 dst_sw_if_index = ~0; - u8 state = 3; + span_feat_t sf = SPAN_FEAT_DEVICE; + span_state_t state = SPAN_BOTH; + int state_set = 0; while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { @@ -95,20 +144,20 @@ set_interface_span_command_fn (vlib_main_t * vm, else if (unformat (input, "destination %U", unformat_vnet_sw_interface, sm->vnet_main, &dst_sw_if_index)) ; - else if (unformat (input, "disable")) - state = 0; - else if (unformat (input, "rx")) - state = 1; - else if (unformat (input, "tx")) - state = 2; - else if (unformat (input, "both")) - state = 3; + else if (unformat (input, "%U", unformat_span_state, &state)) + { + if (state_set) + return clib_error_return (0, "Multiple mirror states in input"); + state_set = 1; + } + else if (unformat (input, "l2")) + sf = SPAN_FEAT_L2; else - break; + return clib_error_return (0, "Invalid input"); } int rv = - span_add_delete_entry (vm, src_sw_if_index, dst_sw_if_index, state); + span_add_delete_entry (vm, src_sw_if_index, dst_sw_if_index, state, sf); if (rv == VNET_API_ERROR_INVALID_INTERFACE) return clib_error_return (0, "Invalid interface"); return 0; @@ -117,7 +166,7 @@ set_interface_span_command_fn (vlib_main_t * vm, /* *INDENT-OFF* */ VLIB_CLI_COMMAND (set_interface_span_command, static) = { .path = "set interface span", - .short_help = "set interface span [disable | destination [both|rx|tx]]", + .short_help = "set interface span [l2] {disable | destination [both|rx|tx]}", .function = set_interface_span_command_fn, }; /* *INDENT-ON* */ @@ -131,36 +180,54 @@ show_interfaces_span_command_fn (vlib_main_t * vm, span_interface_t *si; vnet_main_t *vnm = &vnet_main; u8 header = 1; - char *states[] = { "none", "rx", "tx", "both" }; + static const char *states[] = { + [SPAN_DISABLE] = "none", + [SPAN_RX] = "rx", + [SPAN_TX] = "tx", + [SPAN_BOTH] = "both" + }; u8 *s = 0; /* *INDENT-OFF* */ vec_foreach (si, sm->interfaces) - if (si->num_rx_mirror_ports || si->num_tx_mirror_ports) + { + span_mirror_t * drxm = &si->mirror_rxtx[SPAN_FEAT_DEVICE][VLIB_RX]; + span_mirror_t * dtxm = &si->mirror_rxtx[SPAN_FEAT_DEVICE][VLIB_TX]; + + span_mirror_t * lrxm = &si->mirror_rxtx[SPAN_FEAT_L2][VLIB_RX]; + span_mirror_t * ltxm = &si->mirror_rxtx[SPAN_FEAT_L2][VLIB_TX]; + + if (drxm->num_mirror_ports || dtxm->num_mirror_ports || + lrxm->num_mirror_ports || ltxm->num_mirror_ports) { - clib_bitmap_t *b; u32 i; - b = clib_bitmap_dup_or (si->rx_mirror_ports, si->tx_mirror_ports); + clib_bitmap_t *d = clib_bitmap_dup_or (drxm->mirror_ports, dtxm->mirror_ports); + clib_bitmap_t *l = clib_bitmap_dup_or (lrxm->mirror_ports, ltxm->mirror_ports); + clib_bitmap_t *b = clib_bitmap_dup_or (d, l); if (header) { - vlib_cli_output (vm, "%-40s %s", "Source interface", - "Mirror interface (direction)"); + vlib_cli_output (vm, "%-20s %-20s %6s %6s", "Source", "Destination", + "Device", "L2"); header = 0; } s = format (s, "%U", format_vnet_sw_if_index_name, vnm, si - sm->interfaces); clib_bitmap_foreach (i, b, ( { - int state; - state = (clib_bitmap_get (si->rx_mirror_ports, i) + - clib_bitmap_get (si->tx_mirror_ports, i) * 2); + int device = (clib_bitmap_get (drxm->mirror_ports, i) + + clib_bitmap_get (dtxm->mirror_ports, i) * 2); + int l2 = (clib_bitmap_get (lrxm->mirror_ports, i) + + clib_bitmap_get (ltxm->mirror_ports, i) * 2); - vlib_cli_output (vm, "%-40v %U (%s)", s, + vlib_cli_output (vm, "%-20v %-20U (%6s) (%6s)", s, format_vnet_sw_if_index_name, vnm, i, - states[state]); + states[device], states[l2]); vec_reset_length (s); })); clib_bitmap_free (b); + clib_bitmap_free (l); + clib_bitmap_free (d); + } } /* *INDENT-ON* */ vec_free (s); @@ -175,19 +242,6 @@ VLIB_CLI_COMMAND (show_interfaces_span_command, static) = { }; /* *INDENT-ON* */ -static clib_error_t * -span_init (vlib_main_t * vm) -{ - span_main_t *sm = &span_main; - - sm->vlib_main = vm; - sm->vnet_main = vnet_get_main (); - - return 0; -} - -VLIB_INIT_FUNCTION (span_init); - /* * fd.io coding-style-patch-verification: ON *