summaryrefslogtreecommitdiffstats
path: root/vnet/vnet/span/span.c
diff options
context:
space:
mode:
Diffstat (limited to 'vnet/vnet/span/span.c')
-rw-r--r--vnet/vnet/span/span.c106
1 files changed, 82 insertions, 24 deletions
diff --git a/vnet/vnet/span/span.c b/vnet/vnet/span/span.c
index 52300454427..7b5816c79f2 100644
--- a/vnet/vnet/span/span.c
+++ b/vnet/vnet/span/span.c
@@ -21,22 +21,59 @@
int
span_add_delete_entry (vlib_main_t * vm,
- u32 src_sw_if_index, u32 dst_sw_if_index, u8 is_add)
+ u32 src_sw_if_index, u32 dst_sw_if_index, u8 state)
{
span_main_t *sm = &span_main;
+ span_interface_t *si;
+ u32 new_num_rx_mirror_ports, new_num_tx_mirror_ports;
- if ((src_sw_if_index == ~0) || (dst_sw_if_index == ~0 && is_add)
+ if (state > 3)
+ 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 =
- vnet_get_sw_interface (sm->vnet_main, src_sw_if_index);
+ 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->dst_by_src_sw_if_index, sw->sw_if_index,
+ vec_validate_aligned (sm->interfaces, src_sw_if_index,
CLIB_CACHE_LINE_BYTES);
- sm->dst_by_src_sw_if_index[sw->sw_if_index] = is_add ? dst_sw_if_index : 0;
- vnet_feature_enable_disable ("device-input", "span-input",
- sw->sw_if_index, is_add, 0, 0);
+ 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);
+
+ 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);
+
+ 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);
+
+ 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);
+
+ if (new_num_rx_mirror_ports == 1 && si->num_rx_mirror_ports == 0)
+ vnet_feature_enable_disable ("device-input", "span-output",
+ src_sw_if_index, 1, 0, 0);
+
+ if (new_num_rx_mirror_ports == 0 && si->num_rx_mirror_ports == 1)
+ vnet_feature_enable_disable ("device-input", "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;
+
+ if (dst_sw_if_index > sm->max_sw_if_index)
+ sm->max_sw_if_index = dst_sw_if_index;
+
return 0;
}
@@ -48,7 +85,7 @@ 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 is_add = 1;
+ u8 state = 3;
while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
{
@@ -59,13 +96,19 @@ set_interface_span_command_fn (vlib_main_t * vm,
sm->vnet_main, &dst_sw_if_index))
;
else if (unformat (input, "disable"))
- is_add = 0;
+ state = 0;
+ else if (unformat (input, "rx"))
+ state = 1;
+ else if (unformat (input, "tx"))
+ state = 2;
+ else if (unformat (input, "both"))
+ state = 3;
else
break;
}
int rv =
- span_add_delete_entry (vm, src_sw_if_index, dst_sw_if_index, is_add);
+ span_add_delete_entry (vm, src_sw_if_index, dst_sw_if_index, state);
if (rv == VNET_API_ERROR_INVALID_INTERFACE)
return clib_error_return (0, "Invalid interface");
return 0;
@@ -74,7 +117,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 <if-name> [disable | destination <if-name>]",
+ .short_help = "set interface span <if-name> [disable | destination <if-name> [both|rx|tx]]",
.function = set_interface_span_command_fn,
};
/* *INDENT-ON* */
@@ -84,28 +127,43 @@ show_interfaces_span_command_fn (vlib_main_t * vm,
unformat_input_t * input,
vlib_cli_command_t * cmd)
{
-
span_main_t *sm = &span_main;
+ span_interface_t *si;
vnet_main_t *vnm = &vnet_main;
- u32 src_sw_if_index = 0, *dst_sw_if_index;
u8 header = 1;
+ char *states[] = { "none", "rx", "tx", "both" };
+ u8 *s = 0;
- vec_foreach (dst_sw_if_index, sm->dst_by_src_sw_if_index)
- {
- if (*dst_sw_if_index > 0) // && *dst_sw_if_index != ~0)
+ /* *INDENT-OFF* */
+ vec_foreach (si, sm->interfaces)
+ if (si->num_rx_mirror_ports || si->num_tx_mirror_ports)
{
+ clib_bitmap_t *b;
+ u32 i;
+ b = clib_bitmap_dup_or (si->rx_mirror_ports, si->tx_mirror_ports);
if (header)
{
- vlib_cli_output (vm,
- "SPAN source interface to destination interface table");
+ vlib_cli_output (vm, "%-40s %s", "Source interface",
+ "Mirror interface (direction)");
header = 0;
}
- vlib_cli_output (vm, "%32U => %-32U",
- format_vnet_sw_if_index_name, vnm, src_sw_if_index,
- format_vnet_sw_if_index_name, vnm, *dst_sw_if_index);
+ 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);
+
+ vlib_cli_output (vm, "%-40v %U (%s)", s,
+ format_vnet_sw_if_index_name, vnm, i,
+ states[state]);
+ vec_reset_length (s);
+ }));
+ clib_bitmap_free (b);
}
- src_sw_if_index++;
- }
+ /* *INDENT-ON* */
+ vec_free (s);
return 0;
}