vlib_cli_output (vm, "%-10s: %u", "index", f->index);
vlib_cli_output (vm, "%-10s: %s", "type", flow_type_strings[f->type]);
vlib_cli_output (vm, "%-10s: %U", "match", format_flow, f);
+ if (f->type == VNET_FLOW_TYPE_GENERIC)
+ {
+ vlib_cli_output (vm, "%s: %s", "spec", f->generic.pattern.spec);
+ vlib_cli_output (vm, "%s: %s", "mask", f->generic.pattern.mask);
+ }
/* *INDENT-OFF* */
hash_foreach (hw_if_index, private_data, f->private_data,
({
no_args:
/* *INDENT-OFF* */
- pool_foreach (f, fm->global_flow_pool,
+ pool_foreach (f, fm->global_flow_pool)
{
vlib_cli_output (vm, "%U\n", format_flow, f);
- });
+ if (f->type == VNET_FLOW_TYPE_GENERIC)
+ {
+ vlib_cli_output (vm, "%s: %s", "spec", f->generic.pattern.spec);
+ vlib_cli_output (vm, "%s: %s", "mask", f->generic.pattern.mask);
+ }
+ }
/* *INDENT-ON* */
return 0;
u32 hw_if_index = ~0, flow_index = ~0;
int rv;
u32 teid = 0, session_id = 0, spi = 0;
- u16 vni = 0;
+ u32 vni = 0;
+ u32 queue_start = 0, queue_end = 0;
vnet_flow_type_t type = VNET_FLOW_TYPE_UNKNOWN;
ip4_address_and_mask_t ip4s = { };
ip4_address_and_mask_t ip4d = { };
bool ipsec_esp_set = false, ipsec_ah_set = false;
u8 *rss_type[3] = { };
u8 *type_str = NULL;
+ u8 *spec = NULL;
+ u8 *mask = NULL;
clib_memset (&flow, 0, sizeof (vnet_flow_t));
flow.index = ~0;
action = FLOW_ENABLE;
else if (unformat (line_input, "disable"))
action = FLOW_DISABLE;
+ else if (unformat (line_input, "spec %s", &spec))
+ ;
+ else if (unformat (line_input, "mask %s", &mask))
+ ;
else if (unformat (line_input, "eth-type %U",
unformat_ethernet_type_host_byte_order, ð_type))
flow_class = FLOW_ETHERNET_CLASS;
#undef _
flow.actions |= VNET_FLOW_ACTION_RSS;
}
+ else if (unformat (line_input, "rss queues"))
+ {
+ if (unformat (line_input, "%d to %d", &queue_start, &queue_end))
+ ;
+ else
+ {
+ return clib_error_return (0, "unknown input `%U'",
+ format_unformat_error, line_input);
+ }
+
+ flow.queue_index = queue_start;
+ flow.queue_num = queue_end - queue_start + 1;
+
+ flow.actions |= VNET_FLOW_ACTION_RSS;
+ }
else if (unformat (line_input, "%U", unformat_vnet_hw_interface, vnm,
&hw_if_index))
;
break;
default:
+ if (spec && mask)
+ {
+ type = VNET_FLOW_TYPE_GENERIC;
+ break;
+ }
return clib_error_return (0,
"Please specify a supported flow type");
}
break;
}
}
+ if (type == VNET_FLOW_TYPE_GENERIC)
+ {
+ clib_memcpy (flow.generic.pattern.spec, spec,
+ sizeof (flow.generic.pattern.spec));
+ clib_memcpy (flow.generic.pattern.mask, mask,
+ sizeof (flow.generic.pattern.mask));
+ }
flow.type = type;
rv = vnet_flow_add (vnm, &flow, &flow_index);
/* *INDENT-OFF* */
VLIB_CLI_COMMAND (test_flow_command, static) = {
- .path = "test flow",
- .short_help = "test flow [add|del|enable|disable] [index <id>] "
- "[src-ip <ip-addr/mask>] [dst-ip <ip-addr/mask>] "
- "[ip6-src-ip <ip-addr/mask>] [ip6-dst-ip <ip-addr/mask>] "
- "[src-port <port/mask>] [dst-port <port/mask>] "
- "[proto <ip-proto>] "
- "[gtpc teid <teid>] [gtpu teid <teid>] [vxlan <vni>] "
- "[session id <session>] [spi <spi>]"
- "[next-node <node>] [mark <id>] [buffer-advance <len>] "
- "[redirect-to-queue <queue>] [drop] "
- "[rss function <name>] [rss types <flow type>]",
- .function = test_flow,
+ .path = "test flow",
+ .short_help = "test flow [add|del|enable|disable] [index <id>] "
+ "[src-ip <ip-addr/mask>] [dst-ip <ip-addr/mask>] "
+ "[ip6-src-ip <ip-addr/mask>] [ip6-dst-ip <ip-addr/mask>] "
+ "[src-port <port/mask>] [dst-port <port/mask>] "
+ "[proto <ip-proto>] "
+ "[gtpc teid <teid>] [gtpu teid <teid>] [vxlan <vni>] "
+ "[session id <session>] [spi <spi>]"
+ "[spec <spec string>] [mask <mask string>]"
+ "[next-node <node>] [mark <id>] [buffer-advance <len>] "
+ "[redirect-to-queue <queue>] [drop] "
+ "[rss function <name>] [rss types <flow type>]"
+ "[rss queues <queue_start> to <queue_end>]",
+ .function = test_flow,
};
/* *INDENT-ON* */