38 else if (
unformat (input,
"%u", &port))
43 if (port > 0xffff ||
mask > 0xffff)
59 if (pm->
mask == 0xffff)
75 else if (
unformat (input,
"%u", &prot))
80 if (prot > 0XFF ||
mask > 0xFF)
102 int error = va_arg (*args,
int);
105 return format (s,
"no error");
107 #define _(v,n,str) if (error == v) return format (s, #str); 111 return format (s,
"unknown error (%d)", error);
120 #define _(a, b, c) if (actions & (1 << a)) \ 121 t = format (t, "%s%s", t ? " ":"", c); 132 u32 flow_index = va_arg (*args,
u32);
135 return format (s,
"not found");
144 t = format (t,
"%s%U", t ?
", " :
"",
145 format_vnet_hw_if_index_name, vnm, hw_if_index);
162 else if (func == VNET_RSS_FUNC_##f) \ 163 return format (s, n); 167 return format (s,
"unknown");
177 if (type & (1UL<<a)) \ 178 s = format (s, "%s ", c); 209 if (
unformat (line_input,
"index %u", &index))
229 hi = vnet_get_hw_interface (vnm, hw_if_index);
230 dev_class = vnet_get_device_class (vnm, hi->dev_class_index);
231 vlib_cli_output (vm,
"interface %U\n",
232 format_vnet_hw_if_index_name, vnm, hw_if_index);
233 if (dev_class->format_flow)
234 vlib_cli_output (vm,
" %U\n", dev_class->format_flow,
235 hi->dev_instance, f->index, private_data);
254 .path =
"show flow entry",
255 .short_help =
"show flow entry [index <index>]",
280 .path =
"show flow ranges",
281 .short_help =
"show flow ranges",
294 u32 hw_if_index = ~0;
310 if (hw_if_index == ~0)
315 if (dev_class->format_flow == 0)
324 .path =
"show flow interface",
325 .short_help =
"show flow interface <interface name>",
344 }
action = FLOW_UNKNOWN_ACTION;
351 } flow_class = FLOW_UNKNOWN_CLASS;
353 u32 hw_if_index = ~0, flow_index = ~0;
366 bool tcp_udp_port_set =
false;
367 bool gtpc_set =
false;
368 bool gtpu_set =
false;
369 bool vni_set =
false;
370 bool l2tpv3oip_set =
false;
371 bool ipsec_esp_set =
false, ipsec_ah_set =
false;
372 u8 *rss_type[3] = { };
386 else if (
unformat (line_input,
"del"))
388 else if (
unformat (line_input,
"enable"))
389 action = FLOW_ENABLE;
390 else if (
unformat (line_input,
"disable"))
391 action = FLOW_DISABLE;
392 else if (
unformat (line_input,
"eth-type %U",
394 flow_class = FLOW_ETHERNET_CLASS;
395 else if (
unformat (line_input,
"src-ip %U",
397 flow_class = FLOW_IPV4_CLASS;
398 else if (
unformat (line_input,
"dst-ip %U",
400 flow_class = FLOW_IPV4_CLASS;
401 else if (
unformat (line_input,
"ip6-src-ip %U",
403 flow_class = FLOW_IPV6_CLASS;
404 else if (
unformat (line_input,
"ip6-dst-ip %U",
406 flow_class = FLOW_IPV6_CLASS;
409 tcp_udp_port_set =
true;
412 tcp_udp_port_set =
true;
418 else if (
unformat (line_input,
"gtpc teid %u", &teid))
420 else if (
unformat (line_input,
"gtpu teid %u", &teid))
422 else if (
unformat (line_input,
"vxlan vni %u", &vni))
426 if (protocol.
prot == IP_PROTOCOL_L2TP)
427 l2tpv3oip_set =
true;
431 if (protocol.
prot == IP_PROTOCOL_IPSEC_ESP)
432 ipsec_esp_set =
true;
433 else if (protocol.
prot == IP_PROTOCOL_IPSEC_AH)
436 else if (
unformat (line_input,
"index %u", &flow_index))
440 flow.
actions |= VNET_FLOW_ACTION_REDIRECT_TO_NODE;
442 flow.
actions |= VNET_FLOW_ACTION_MARK;
443 else if (
unformat (line_input,
"buffer-advance %d",
445 flow.
actions |= VNET_FLOW_ACTION_BUFFER_ADVANCE;
446 else if (
unformat (line_input,
"redirect-to-queue %d",
448 flow.
actions |= VNET_FLOW_ACTION_REDIRECT_TO_QUEUE;
449 else if (
unformat (line_input,
"drop"))
450 flow.
actions |= VNET_FLOW_ACTION_DROP;
451 else if (
unformat (line_input,
"rss function"))
457 else if (unformat (line_input, s)) \ 458 flow.rss_fun = VNET_RSS_FUNC_##f; 468 flow.
actions |= VNET_FLOW_ACTION_RSS;
470 else if (
unformat (line_input,
"rss types"))
477 if (
unformat (line_input,
"%s use %s and %s",
478 &rss_type[0], &rss_type[1], &rss_type[2]))
481 (line_input,
"%s use %s", &rss_type[0], &rss_type[1]))
483 else if (
unformat (line_input,
"%s", &rss_type[0]))
488 else if (!clib_strcmp(c, (const char *)type_str)) \ 489 flow.rss_types |= (1ULL<<a); 491 #define check_rss_types(_str) \ 496 foreach_flow_rss_types \ 499 return clib_error_return (0, "parse error: '%U'", \ 500 format_unformat_error, line_input); \ 507 flow.
actions |= VNET_FLOW_ACTION_RSS;
519 if (hw_if_index == ~0 && (action == FLOW_ENABLE || action == FLOW_DISABLE))
522 if (flow_index == ~0 && (action == FLOW_ENABLE || action == FLOW_DISABLE ||
535 case FLOW_ETHERNET_CLASS:
536 type = VNET_FLOW_TYPE_ETHERNET;
539 case FLOW_IPV4_CLASS:
542 type = VNET_FLOW_TYPE_IP4_GTPC;
543 protocol.
prot = IP_PROTOCOL_UDP;
547 type = VNET_FLOW_TYPE_IP4_GTPU;
548 protocol.
prot = IP_PROTOCOL_UDP;
552 type = VNET_FLOW_TYPE_IP4_VXLAN;
553 protocol.
prot = IP_PROTOCOL_UDP;
555 else if (l2tpv3oip_set)
556 type = VNET_FLOW_TYPE_IP4_L2TPV3OIP;
557 else if (ipsec_esp_set)
558 type = VNET_FLOW_TYPE_IP4_IPSEC_ESP;
559 else if (ipsec_ah_set)
560 type = VNET_FLOW_TYPE_IP4_IPSEC_AH;
561 else if (tcp_udp_port_set)
562 type = VNET_FLOW_TYPE_IP4_N_TUPLE;
564 type = VNET_FLOW_TYPE_IP4;
566 case FLOW_IPV6_CLASS:
567 if (tcp_udp_port_set)
568 type = VNET_FLOW_TYPE_IP6_N_TUPLE;
570 type = VNET_FLOW_TYPE_IP6_VXLAN;
572 type = VNET_FLOW_TYPE_IP6;
577 "Please specify a supported flow type");
581 if (flow_class == FLOW_ETHERNET_CLASS)
583 flow.ethernet.eth_hdr.
type = eth_type;
585 else if (flow_class == FLOW_IPV4_CLASS)
587 vnet_flow_ip4_t *ip4_ptr = &flow.ip4;
593 ip4_ptr->protocol.prot = protocol.
prot;
599 if (type == VNET_FLOW_TYPE_IP4)
600 ip4_ptr->protocol.mask = protocol.
mask;
602 switch (protocol.
prot)
605 case IP_PROTOCOL_TCP:
606 case IP_PROTOCOL_UDP:
607 flow.ip4_n_tuple.src_port = sport;
608 flow.ip4_n_tuple.dst_port = dport;
610 if (type == VNET_FLOW_TYPE_IP4_GTPC)
611 flow.ip4_gtpc.teid =
teid;
612 else if (type == VNET_FLOW_TYPE_IP4_GTPU)
613 flow.ip4_gtpu.teid =
teid;
614 else if (type == VNET_FLOW_TYPE_IP4_VXLAN)
615 flow.ip4_vxlan.vni =
vni;
617 case IP_PROTOCOL_L2TP:
620 case IP_PROTOCOL_IPSEC_ESP:
621 flow.ip4_ipsec_esp.spi =
spi;
623 case IP_PROTOCOL_IPSEC_AH:
624 flow.ip4_ipsec_esp.spi =
spi;
630 else if (flow_class == FLOW_IPV6_CLASS)
632 vnet_flow_ip6_t *ip6_ptr = &flow.ip6;
639 ip6_ptr->protocol.prot = protocol.
prot;
645 if (type == VNET_FLOW_TYPE_IP6)
646 ip6_ptr->protocol.mask = protocol.
mask;
648 switch (protocol.
prot)
651 case IP_PROTOCOL_TCP:
652 case IP_PROTOCOL_UDP:
653 flow.ip6_n_tuple.src_port = sport;
654 flow.ip6_n_tuple.dst_port = dport;
656 if (type == VNET_FLOW_TYPE_IP6_VXLAN)
657 flow.ip6_vxlan.vni =
vni;
693 .short_help =
"test flow [add|del|enable|disable] [index <id>] " 694 "[src-ip <ip-addr/mask>] [dst-ip <ip-addr/mask>] " 695 "[ip6-src-ip <ip-addr/mask>] [ip6-dst-ip <ip-addr/mask>] " 696 "[src-port <port/mask>] [dst-port <port/mask>] " 697 "[proto <ip-proto>] " 698 "[gtpc teid <teid>] [gtpu teid <teid>] [vxlan <vni>] " 699 "[session id <session>] [spi <spi>]" 700 "[next-node <node>] [mark <id>] [buffer-advance <len>] " 701 "[redirect-to-queue <queue>] [drop] " 702 "[rss function <name>] [rss types <flow type>]",
710 char *
type = va_arg (*args,
char *);
711 void *ptr = va_arg (*args,
void *);
713 if (strncmp (type,
"u8", 2) == 0)
714 return format (s,
"%d", *(
u8 *) ptr);
716 if (strncmp (type,
"u16", 3) == 0)
719 if (strncmp (type,
"u32", 3) == 0)
722 if (strncmp (type,
"ethernet_header_t", 13) == 0)
725 memset (&m, 0,
sizeof (m));
732 if (strncmp (type,
"ip4_address_t", 13) == 0)
735 if (strncmp (type,
"ip4_address_and_mask_t", 13) == 0)
738 if (strncmp (type,
"ip6_address_t", 13) == 0)
741 if (strncmp (type,
"ip6_address_and_mask_t", 13) == 0)
744 if (strncmp (type,
"ip_prot_and_mask_t", 13) == 0)
747 if (strncmp (type,
"ip_port_and_mask_t", 18) == 0)
750 s =
format (s,
"unknown type '%s'", type);
754 #define _fe(a,b) s2 = format (s2, "%s%s %U", s2 ? ", ":"", #b, \ 755 format_flow_match_element, #a, &f->b); 757 u8 * format_flow_match_##b (u8 * s, va_list * args) \ 759 vnet_flow_##b##_t *f = __builtin_va_arg (*args, vnet_flow_##b##_t *); \ 761 foreach_flow_entry_##b \ 762 s = format (s, "%v", s2);; \ 775 if (f->type == VNET_FLOW_TYPE_##a) \ 776 return format (s, "%U", format_flow_match_##b, &f->b); 791 s =
format (s,
"flow-index %u type %s active %u",
799 if (f->
actions & VNET_FLOW_ACTION_DROP)
800 t =
format (t,
"%sdrop", t ?
", " :
"");
802 if (f->
actions & VNET_FLOW_ACTION_MARK)
805 if (f->
actions & VNET_FLOW_ACTION_REDIRECT_TO_QUEUE)
809 if (f->
actions & VNET_FLOW_ACTION_REDIRECT_TO_NODE)
810 t =
format (t,
"%snext-node %U", t ?
", " :
"",
813 if (f->
actions & VNET_FLOW_ACTION_BUFFER_ADVANCE)
816 if (f->
actions & VNET_FLOW_ACTION_RSS)
818 t =
format (t,
"%srss function %U", t ?
", " :
"",
820 t =
format (t,
"%srss types %U", t ?
", " :
"",
unformat_function_t unformat_vnet_hw_interface
vnet_rss_function_t rss_fun
format_function_t format_vlib_node_name
vnet_main_t * vnet_get_main(void)
#define foreach_rss_function
#define pool_foreach(VAR, POOL)
Iterate through pool.
u8 * format_flow_actions(u8 *s, va_list *args)
vl_api_ip_proto_t protocol
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
static vnet_hw_interface_t * vnet_get_hw_interface(vnet_main_t *vnm, u32 hw_if_index)
static clib_error_t * test_flow(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd_arg)
vnet_flow_t * global_flow_pool
u8 * format_flow_error(u8 *s, va_list *args)
struct _vnet_device_class vnet_device_class_t
int vnet_flow_disable(vnet_main_t *vnm, u32 flow_index, u32 hw_if_index)
static clib_error_t * show_flow_entry(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd_arg)
#define clib_memcpy(d, s, n)
static vnet_device_class_t * vnet_get_device_class(vnet_main_t *vnm, u32 dev_class_index)
static format_function_t format_flow
description fragment has unexpected format
#define hash_foreach(key_var, value_var, h, body)
static u8 * format_flow_match_element(u8 *s, va_list *args)
#define clib_error_return(e, args...)
vnet_flow_main_t flow_main
vnet_flow_range_t * ranges
vl_api_fib_path_type_t type
int vnet_flow_del(vnet_main_t *vnm, u32 flow_index)
static clib_error_t * show_flow_ranges(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd_arg)
u8 * format_rss_function(u8 *s, va_list *args)
u8 * format_rss_types(u8 *s, va_list *args)
vnet_flow_t * vnet_get_flow(u32 flow_index)
#define foreach_flow_rss_types
uword unformat_ip_protocol_and_mask(unformat_input_t *input, va_list *args)
u8 * format_ip_port_and_mask(u8 *s, va_list *args)
#define vec_free(V)
Free vector's memory (no header).
u8 * format_flow_enabled_hw(u8 *s, va_list *args)
#define check_rss_types(_str)
u8 * format_ip_protocol_and_mask(u8 *s, va_list *args)
#define VLIB_CLI_COMMAND(x,...)
static const char * flow_type_strings[]
static uword hash_elts(void *v)
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
u8 * format_ethernet_header(u8 *s, va_list *args)
uword unformat_ip_port_and_mask(unformat_input_t *input, va_list *args)
static foreach_flow_type u8 * format_flow_match(u8 *s, va_list *args)
int vnet_flow_add(vnet_main_t *vnm, vnet_flow_t *flow, u32 *flow_index)
static vlib_main_t * vlib_get_main(void)
static clib_error_t * show_flow_interface(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd_arg)
uword unformat_ethernet_type_host_byte_order(unformat_input_t *input, va_list *args)
vl_api_mac_event_action_t action
vl_api_flow_action_t actions
int vnet_flow_enable(vnet_main_t *vnm, u32 flow_index, u32 hw_if_index)
unformat_function_t unformat_vlib_node
#define vec_foreach(var, vec)
Vector iterator.