diff options
Diffstat (limited to 'src/vnet/flow')
-rw-r--r-- | src/vnet/flow/FEATURE.yaml | 4 | ||||
-rw-r--r-- | src/vnet/flow/flow.api | 31 | ||||
-rw-r--r-- | src/vnet/flow/flow.c | 2 | ||||
-rw-r--r-- | src/vnet/flow/flow.h | 101 | ||||
-rw-r--r-- | src/vnet/flow/flow_api.c | 97 | ||||
-rw-r--r-- | src/vnet/flow/flow_cli.c | 204 | ||||
-rw-r--r-- | src/vnet/flow/flow_types.api | 109 |
7 files changed, 485 insertions, 63 deletions
diff --git a/src/vnet/flow/FEATURE.yaml b/src/vnet/flow/FEATURE.yaml index a26571c35e8..8633f4febdd 100644 --- a/src/vnet/flow/FEATURE.yaml +++ b/src/vnet/flow/FEATURE.yaml @@ -16,13 +16,15 @@ features: - FLOW_TYPE_IP4_VXLAN, - FLOW_TYPE_IP6_VXLAN, - FLOW_TYPE_IP4_GTPC, - - FLOW_TYPE_IP4_GTPU + - FLOW_TYPE_IP4_GTPU, + - FLOW_TYPE_GENERIC - The below flow actions can be specified for the flows: - FLOW_ACTION_COUNT, - FLOW_ACTION_MARK, - FLOW_ACTION_BUFFER_ADVANCE, - FLOW_ACTION_REDIRECT_TO_NODE, - FLOW_ACTION_REDIRECT_TO_QUEUE, + - FLOW_ACTION_RSS, - FLOW_ACTION_DROP description: "Flow infrastructure to provide hardware offload capabilities" state: development diff --git a/src/vnet/flow/flow.api b/src/vnet/flow/flow.api index 7bb21cdcd72..1e807b539d5 100644 --- a/src/vnet/flow/flow.api +++ b/src/vnet/flow/flow.api @@ -13,7 +13,7 @@ * limitations under the License. */ -option version = "0.0.2"; +option version = "1.0.3"; import "vnet/interface_types.api"; import "vnet/ip/ip_types.api"; @@ -26,12 +26,27 @@ import "vnet/flow/flow_types.api"; */ define flow_add { + option deprecated; + u32 client_index; u32 context; vl_api_flow_rule_t flow; option vat_help = "test flow add [src-ip <ip-addr/mask>] [dst-ip <ip-addr/mask>] [src-port <port/mask>] [dst-port <port/mask>] [proto <ip-proto>]"; }; +/** \brief flow add request v2 + @param client_index - opaque cookie to identify the sender + @param context - sender context, to match reply w/ request + @param flow - flow rule v2 +*/ +define flow_add_v2 +{ + u32 client_index; + u32 context; + vl_api_flow_rule_v2_t flow; + option vat_help = "test flow add [src-ip <ip-addr/mask>] [dst-ip <ip-addr/mask>] [src-port <port/mask>] [dst-port <port/mask>] [proto <ip-proto>] [spec <spec-string>] [mask <mask-string>]"; +}; + /** \brief reply for adding flow @param context - sender context, to match reply w/ request @param retval - return code @@ -39,6 +54,20 @@ define flow_add */ define flow_add_reply { + option deprecated; + + u32 context; + i32 retval; + u32 flow_index; +}; + +/** \brief reply for adding flow v2 + @param context - sender context, to match reply w/ request + @param retval - return code + @param flow_index - flow index, can be used for flow del/enable/disable +*/ +define flow_add_v2_reply +{ u32 context; i32 retval; u32 flow_index; diff --git a/src/vnet/flow/flow.c b/src/vnet/flow/flow.c index 9b6a376af3e..eda15356958 100644 --- a/src/vnet/flow/flow.c +++ b/src/vnet/flow/flow.c @@ -74,12 +74,10 @@ vnet_flow_del (vnet_main_t * vnm, u32 flow_index) if (f == 0) return VNET_FLOW_ERROR_NO_SUCH_ENTRY; - /* *INDENT-OFF* */ hash_foreach (hw_if_index, private_data, f->private_data, ({ vnet_flow_disable (vnm, flow_index, hw_if_index); })); - /* *INDENT-ON* */ hash_free (f->private_data); clib_memset (f, 0, sizeof (*f)); diff --git a/src/vnet/flow/flow.h b/src/vnet/flow/flow.h index 76c1df8a22f..ada822257e3 100644 --- a/src/vnet/flow/flow.h +++ b/src/vnet/flow/flow.h @@ -18,31 +18,43 @@ #include <vppinfra/clib.h> #include <vppinfra/pcap.h> +#include <vnet/vnet.h> #include <vnet/l3_types.h> #include <vnet/ip/ip4_packet.h> #include <vnet/ip/ip6_packet.h> #include <vnet/ethernet/packet.h> -#define foreach_flow_type \ - /* l2 flow*/ \ - _(ETHERNET, ethernet, "ethernet") \ - /* l3 IP flow */ \ - _(IP4, ip4, "ipv4") \ - _(IP6, ip6, "ipv6") \ - /* IP tunnel flow */ \ - _(IP4_L2TPV3OIP, ip4_l2tpv3oip, "ipv4-l2tpv3oip") \ - _(IP4_IPSEC_ESP, ip4_ipsec_esp, "ipv4-ipsec-esp") \ - _(IP4_IPSEC_AH, ip4_ipsec_ah, "ipv4-ipsec-ah") \ - /* l4 flow*/ \ - _(IP4_N_TUPLE, ip4_n_tuple, "ipv4-n-tuple") \ - _(IP6_N_TUPLE, ip6_n_tuple, "ipv6-n-tuple") \ - _(IP4_N_TUPLE_TAGGED, ip4_n_tuple_tagged, "ipv4-n-tuple-tagged") \ - _(IP6_N_TUPLE_TAGGED, ip6_n_tuple_tagged, "ipv6-n-tuple-tagged") \ - /* L4 tunnel flow*/ \ - _(IP4_VXLAN, ip4_vxlan, "ipv4-vxlan") \ - _(IP6_VXLAN, ip6_vxlan, "ipv6-vxlan") \ - _(IP4_GTPC, ip4_gtpc, "ipv4-gtpc") \ - _(IP4_GTPU, ip4_gtpu, "ipv4-gtpu") +#define foreach_flow_type \ + /* l2 flow*/ \ + _ (ETHERNET, ethernet, "ethernet") \ + /* l3 IP flow */ \ + _ (IP4, ip4, "ipv4") \ + _ (IP6, ip6, "ipv6") \ + /* IP tunnel flow */ \ + _ (IP4_L2TPV3OIP, ip4_l2tpv3oip, "ipv4-l2tpv3oip") \ + _ (IP4_IPSEC_ESP, ip4_ipsec_esp, "ipv4-ipsec-esp") \ + _ (IP4_IPSEC_AH, ip4_ipsec_ah, "ipv4-ipsec-ah") \ + /* l4 flow*/ \ + _ (IP4_N_TUPLE, ip4_n_tuple, "ipv4-n-tuple") \ + _ (IP6_N_TUPLE, ip6_n_tuple, "ipv6-n-tuple") \ + _ (IP4_N_TUPLE_TAGGED, ip4_n_tuple_tagged, "ipv4-n-tuple-tagged") \ + _ (IP6_N_TUPLE_TAGGED, ip6_n_tuple_tagged, "ipv6-n-tuple-tagged") \ + /* L4 tunnel flow*/ \ + _ (IP4_VXLAN, ip4_vxlan, "ipv4-vxlan") \ + _ (IP6_VXLAN, ip6_vxlan, "ipv6-vxlan") \ + _ (IP4_GTPC, ip4_gtpc, "ipv4-gtpc") \ + _ (IP4_GTPU, ip4_gtpu, "ipv4-gtpu") \ + /* generic flow */ \ + _ (GENERIC, generic, "generic") \ + /* IP in IP */ \ + _ (IP6_IP6, ip6_ip6, "ipv6-ipv6") \ + _ (IP6_IP4, ip6_ip4, "ipv6-ipv4") \ + _ (IP4_IP6, ip4_ip6, "ipv4-ipv6") \ + _ (IP4_IP4, ip4_ip4, "ipv4-ipv4") \ + _ (IP6_IP6_N_TUPLE, ip6_ip6_n_tuple, "ipv6-ipv6-n-tuple") \ + _ (IP6_IP4_N_TUPLE, ip6_ip4_n_tuple, "ipv6-ipv4-n-tuple") \ + _ (IP4_IP6_N_TUPLE, ip4_ip6_n_tuple, "ipv4-ipv6-n-tuple") \ + _ (IP4_IP4_N_TUPLE, ip4_ip4_n_tuple, "ipv4-ipv4-n-tuple") #define foreach_flow_entry_ethernet \ _fe(ethernet_header_t, eth_hdr) @@ -103,6 +115,44 @@ foreach_flow_entry_ip4_n_tuple \ _fe(u32, teid) +#define foreach_flow_entry_ip6_ip6 \ + foreach_flow_entry_ip6 _fe (ip6_address_and_mask_t, in_src_addr) \ + _fe (ip6_address_and_mask_t, in_dst_addr) \ + _fe (ip_prot_and_mask_t, in_protocol) + +#define foreach_flow_entry_ip6_ip6_n_tuple \ + foreach_flow_entry_ip6_ip6 _fe (ip_port_and_mask_t, in_src_port) \ + _fe (ip_port_and_mask_t, in_dst_port) + +#define foreach_flow_entry_ip6_ip4 \ + foreach_flow_entry_ip6 _fe (ip4_address_and_mask_t, in_src_addr) \ + _fe (ip4_address_and_mask_t, in_dst_addr) \ + _fe (ip_prot_and_mask_t, in_protocol) + +#define foreach_flow_entry_ip6_ip4_n_tuple \ + foreach_flow_entry_ip6_ip4 _fe (ip_port_and_mask_t, in_src_port) \ + _fe (ip_port_and_mask_t, in_dst_port) + +#define foreach_flow_entry_ip4_ip6 \ + foreach_flow_entry_ip4 _fe (ip6_address_and_mask_t, in_src_addr) \ + _fe (ip6_address_and_mask_t, in_dst_addr) \ + _fe (ip_prot_and_mask_t, in_protocol) + +#define foreach_flow_entry_ip4_ip6_n_tuple \ + foreach_flow_entry_ip4_ip6 _fe (ip_port_and_mask_t, in_src_port) \ + _fe (ip_port_and_mask_t, in_dst_port) + +#define foreach_flow_entry_ip4_ip4 \ + foreach_flow_entry_ip4 _fe (ip4_address_and_mask_t, in_src_addr) \ + _fe (ip4_address_and_mask_t, in_dst_addr) \ + _fe (ip_prot_and_mask_t, in_protocol) + +#define foreach_flow_entry_ip4_ip4_n_tuple \ + foreach_flow_entry_ip4_ip4 _fe (ip_port_and_mask_t, in_src_port) \ + _fe (ip_port_and_mask_t, in_dst_port) + +#define foreach_flow_entry_generic _fe (generic_pattern_t, pattern) + #define foreach_flow_action \ _(0, COUNT, "count") \ _(1, MARK, "mark") \ @@ -150,6 +200,7 @@ typedef enum _ (19, NVGRE, "nvgre") \ _ (20, GTPU, "gtpu") \ _ (21, ESP, "esp") \ + _ (22, L2TPV3, "l2tpv3") \ _ (60, L4_DST_ONLY, "l4-dst-only") \ _ (61, L4_SRC_ONLY, "l4-src-only") \ _ (62, L3_DST_ONLY, "l3-dst-only") \ @@ -189,6 +240,12 @@ typedef struct u8 mask; } ip_prot_and_mask_t; +typedef struct +{ + u8 spec[1024]; + u8 mask[1024]; +} generic_pattern_t; + typedef enum { VNET_FLOW_TYPE_UNKNOWN, @@ -241,6 +298,10 @@ typedef struct /* queue for VNET_FLOW_ACTION_REDIRECT_TO_QUEUE */ u32 redirect_queue; + /* start queue index and queue numbers for RSS queue group */ + u32 queue_index; + u32 queue_num; + /* buffer offset for VNET_FLOW_ACTION_BUFFER_ADVANCE */ i32 buffer_advance; diff --git a/src/vnet/flow/flow_api.c b/src/vnet/flow/flow_api.c index 6f08f0314a4..bfe97ec2978 100644 --- a/src/vnet/flow/flow_api.c +++ b/src/vnet/flow/flow_api.c @@ -215,6 +215,16 @@ ipv4_gtpc_flow_convert (vl_api_flow_ip4_gtpc_t * vl_api_flow, f->teid = ntohl (vl_api_flow->teid); } +static inline void +generic_flow_convert (vl_api_flow_generic_t *vl_api_flow, + vnet_flow_generic_t *f) +{ + clib_memcpy (f->pattern.spec, vl_api_flow->pattern.spec, + sizeof (vl_api_flow->pattern.spec)); + clib_memcpy (f->pattern.mask, vl_api_flow->pattern.mask, + sizeof (vl_api_flow->pattern.mask)); +} + static void vl_api_flow_add_t_handler (vl_api_flow_add_t * mp) { @@ -289,12 +299,95 @@ vl_api_flow_add_t_handler (vl_api_flow_add_t * mp) rv = vnet_flow_add (vnm, &flow, &flow_index); out: - /* *INDENT-OFF* */ REPLY_MACRO2(VL_API_FLOW_ADD_REPLY, ({ rmp->flow_index = ntohl (flow_index); })); - /* *INDENT-ON* */ +} + +static void +vl_api_flow_add_v2_t_handler (vl_api_flow_add_v2_t *mp) +{ + vl_api_flow_add_v2_reply_t *rmp; + int rv = 0; + vnet_flow_t flow; + u32 flow_index = ~0; + vl_api_flow_rule_v2_t *f = &mp->flow; + + vnet_main_t *vnm = vnet_get_main (); + + flow.type = ntohl (f->type); + flow.actions = ntohl (f->actions); + flow.mark_flow_id = ntohl (f->mark_flow_id); + flow.redirect_node_index = ntohl (f->redirect_node_index); + flow.redirect_device_input_next_index = + ntohl (f->redirect_device_input_next_index); + flow.redirect_queue = ntohl (f->redirect_queue); + flow.buffer_advance = ntohl (f->buffer_advance); + flow.queue_index = ntohl (f->queue_index); + flow.queue_num = ntohl (f->queue_num); + flow.rss_types = clib_net_to_host_u64 (f->rss_types); + flow.rss_fun = ntohl (f->rss_fun); + + switch (flow.type) + { + case VNET_FLOW_TYPE_IP4: + ipv4_flow_convert (&f->flow.ip4, &flow.ip4); + break; + case VNET_FLOW_TYPE_IP6: + ipv6_flow_convert (&f->flow.ip6, &flow.ip6); + break; + case VNET_FLOW_TYPE_IP4_N_TUPLE: + ipv4_n_tuple_flow_convert (&f->flow.ip4_n_tuple, &flow.ip4_n_tuple); + break; + case VNET_FLOW_TYPE_IP6_N_TUPLE: + ipv6_n_tuple_flow_convert (&f->flow.ip6_n_tuple, &flow.ip6_n_tuple); + break; + case VNET_FLOW_TYPE_IP4_N_TUPLE_TAGGED: + ipv4_n_tuple_tagged_flow_convert (&f->flow.ip4_n_tuple_tagged, + &flow.ip4_n_tuple_tagged); + break; + case VNET_FLOW_TYPE_IP6_N_TUPLE_TAGGED: + ipv6_n_tuple_tagged_flow_convert (&f->flow.ip6_n_tuple_tagged, + &flow.ip6_n_tuple_tagged); + break; + case VNET_FLOW_TYPE_IP4_L2TPV3OIP: + ipv4_l2tpv3oip_flow_convert (&f->flow.ip4_l2tpv3oip, + &flow.ip4_l2tpv3oip); + break; + case VNET_FLOW_TYPE_IP4_IPSEC_ESP: + ipv4_ipsec_esp_flow_convert (&f->flow.ip4_ipsec_esp, + &flow.ip4_ipsec_esp); + break; + case VNET_FLOW_TYPE_IP4_IPSEC_AH: + ipv4_ipsec_ah_flow_convert (&f->flow.ip4_ipsec_ah, &flow.ip4_ipsec_ah); + break; + case VNET_FLOW_TYPE_IP4_VXLAN: + ipv4_vxlan_flow_convert (&f->flow.ip4_vxlan, &flow.ip4_vxlan); + break; + case VNET_FLOW_TYPE_IP6_VXLAN: + ipv6_vxlan_flow_convert (&f->flow.ip6_vxlan, &flow.ip6_vxlan); + break; + case VNET_FLOW_TYPE_IP4_GTPU: + ipv4_gtpu_flow_convert (&f->flow.ip4_gtpu, &flow.ip4_gtpu); + break; + case VNET_FLOW_TYPE_IP4_GTPC: + ipv4_gtpc_flow_convert (&f->flow.ip4_gtpc, &flow.ip4_gtpc); + break; + case VNET_FLOW_TYPE_GENERIC: + generic_flow_convert (&f->flow.generic, &flow.generic); + break; + default: + rv = VNET_FLOW_ERROR_NOT_SUPPORTED; + goto out; + break; + } + + rv = vnet_flow_add (vnm, &flow, &flow_index); + +out: + REPLY_MACRO2 (VL_API_FLOW_ADD_V2_REPLY, + ({ rmp->flow_index = ntohl (flow_index); })); } static void diff --git a/src/vnet/flow/flow_cli.c b/src/vnet/flow/flow_cli.c index e2a3141c551..e4b73717241 100644 --- a/src/vnet/flow/flow_cli.c +++ b/src/vnet/flow/flow_cli.c @@ -138,13 +138,11 @@ format_flow_enabled_hw (u8 * s, va_list * args) u32 hw_if_index; uword private_data; vnet_main_t *vnm = vnet_get_main (); - /* *INDENT-OFF* */ hash_foreach (hw_if_index, private_data, f->private_data, ({ t = format (t, "%s%U", t ? ", " : "", format_vnet_hw_if_index_name, vnm, hw_if_index); })); - /* *INDENT-ON* */ s = format (s, "%v", t); vec_free (t); return s; @@ -223,7 +221,11 @@ show_flow_entry (vlib_main_t * vm, unformat_input_t * input, 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); - /* *INDENT-OFF* */ + 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); + } hash_foreach (hw_if_index, private_data, f->private_data, ({ hi = vnet_get_hw_interface (vnm, hw_if_index); @@ -234,28 +236,28 @@ show_flow_entry (vlib_main_t * vm, unformat_input_t * input, vlib_cli_output (vm, " %U\n", dev_class->format_flow, hi->dev_instance, f->index, private_data); })); - /* *INDENT-ON* */ return 0; } no_args: - /* *INDENT-OFF* */ 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; } -/* *INDENT-OFF* */ VLIB_CLI_COMMAND (show_flow_entry_command, static) = { .path = "show flow entry", .short_help = "show flow entry [index <index>]", .function = show_flow_entry, }; -/* *INDENT-ON* */ static clib_error_t * show_flow_ranges (vlib_main_t * vm, unformat_input_t * input, @@ -266,22 +268,18 @@ show_flow_ranges (vlib_main_t * vm, unformat_input_t * input, vlib_cli_output (vm, "%8s %8s %s", "Start", "Count", "Owner"); - /* *INDENT-OFF* */ vec_foreach (r, fm->ranges) { vlib_cli_output (vm, "%8u %8u %s", r->start, r->count, r->owner); }; - /* *INDENT-ON* */ return 0; } -/* *INDENT-OFF* */ VLIB_CLI_COMMAND (show_flow_ranges_command, static) = { .path = "show flow ranges", .short_help = "show flow ranges", .function = show_flow_ranges, }; -/* *INDENT-ON* */ static clib_error_t * show_flow_interface (vlib_main_t * vm, unformat_input_t * input, @@ -319,13 +317,11 @@ show_flow_interface (vlib_main_t * vm, unformat_input_t * input, return 0; } -/* *INDENT-OFF* */ VLIB_CLI_COMMAND (show_flow_interface_command, static) = { .path = "show flow interface", .short_help = "show flow interface <interface name>", .function = show_flow_interface, }; -/* *INDENT-ON* */ static clib_error_t * test_flow (vlib_main_t * vm, unformat_input_t * input, @@ -354,16 +350,18 @@ test_flow (vlib_main_t * vm, unformat_input_t * input, int rv; u32 teid = 0, session_id = 0, spi = 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 = { }; - ip6_address_and_mask_t ip6s = { }; - ip6_address_and_mask_t ip6d = { }; - ip_port_and_mask_t sport = { }; - ip_port_and_mask_t dport = { }; - ip_prot_and_mask_t protocol = { }; + ip4_address_and_mask_t ip4s = {}, in_ip4s = {}; + ip4_address_and_mask_t ip4d = {}, in_ip4d = {}; + ip6_address_and_mask_t ip6s = {}, in_ip6s = {}; + ip6_address_and_mask_t ip6d = {}, in_ip6d = {}; + ip_port_and_mask_t sport = {}, in_sport = {}; + ip_port_and_mask_t dport = {}, in_dport = {}; + ip_prot_and_mask_t protocol = {}, in_proto = {}; u16 eth_type; - bool tcp_udp_port_set = false; + bool inner_ip4_set = false, inner_ip6_set = false; + bool tcp_udp_port_set = false, inner_port_set = false; bool gtpc_set = false; bool gtpu_set = false; bool vni_set = false; @@ -371,6 +369,8 @@ test_flow (vlib_main_t * vm, unformat_input_t * input, 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; @@ -389,6 +389,10 @@ test_flow (vlib_main_t * vm, unformat_input_t * input, 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; @@ -398,12 +402,24 @@ test_flow (vlib_main_t * vm, unformat_input_t * input, else if (unformat (line_input, "dst-ip %U", unformat_ip4_address_and_mask, &ip4d)) flow_class = FLOW_IPV4_CLASS; + else if (unformat (line_input, "in-src-ip %U", + unformat_ip4_address_and_mask, &in_ip4s)) + inner_ip4_set = true; + else if (unformat (line_input, "in-dst-ip %U", + unformat_ip4_address_and_mask, &in_ip4d)) + inner_ip4_set = true; else if (unformat (line_input, "ip6-src-ip %U", unformat_ip6_address_and_mask, &ip6s)) flow_class = FLOW_IPV6_CLASS; else if (unformat (line_input, "ip6-dst-ip %U", unformat_ip6_address_and_mask, &ip6d)) flow_class = FLOW_IPV6_CLASS; + else if (unformat (line_input, "in-ip6-src-ip %U", + unformat_ip6_address_and_mask, &in_ip6s)) + inner_ip6_set = true; + else if (unformat (line_input, "in-ip6-dst-ip %U", + unformat_ip6_address_and_mask, &in_ip6d)) + inner_ip6_set = true; else if (unformat (line_input, "src-port %U", unformat_ip_port_and_mask, &sport)) tcp_udp_port_set = true; @@ -415,6 +431,15 @@ test_flow (vlib_main_t * vm, unformat_input_t * input, (line_input, "proto %U", unformat_ip_protocol_and_mask, &protocol)) ; + else if (unformat (line_input, "in-src-port %U", + unformat_ip_port_and_mask, &in_sport)) + inner_port_set = true; + else if (unformat (line_input, "in-dst-port %U", + unformat_ip_port_and_mask, &in_dport)) + inner_port_set = true; + else if (unformat (line_input, "in-proto %U", + unformat_ip_protocol_and_mask, &in_proto)) + ; else if (unformat (line_input, "gtpc teid %u", &teid)) gtpc_set = true; else if (unformat (line_input, "gtpu teid %u", &teid)) @@ -506,6 +531,21 @@ test_flow (vlib_main_t * vm, unformat_input_t * input, #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)) ; @@ -560,6 +600,22 @@ test_flow (vlib_main_t * vm, unformat_input_t * input, type = VNET_FLOW_TYPE_IP4_IPSEC_AH; else if (tcp_udp_port_set) type = VNET_FLOW_TYPE_IP4_N_TUPLE; + else if (inner_ip4_set) + { + if (inner_port_set) + type = VNET_FLOW_TYPE_IP4_IP4_N_TUPLE; + else + type = VNET_FLOW_TYPE_IP4_IP4; + protocol.prot = IP_PROTOCOL_IP_IN_IP; + } + else if (inner_ip6_set) + { + if (inner_port_set) + type = VNET_FLOW_TYPE_IP4_IP6_N_TUPLE; + else + type = VNET_FLOW_TYPE_IP4_IP6; + protocol.prot = IP_PROTOCOL_IPV6; + } else type = VNET_FLOW_TYPE_IP4; break; @@ -568,11 +624,32 @@ test_flow (vlib_main_t * vm, unformat_input_t * input, type = VNET_FLOW_TYPE_IP6_N_TUPLE; else if (vni_set) type = VNET_FLOW_TYPE_IP6_VXLAN; + else if (inner_ip4_set) + { + if (inner_port_set) + type = VNET_FLOW_TYPE_IP6_IP4_N_TUPLE; + else + type = VNET_FLOW_TYPE_IP6_IP4; + protocol.prot = IP_PROTOCOL_IP_IN_IP; + } + else if (inner_ip6_set) + { + if (inner_port_set) + type = VNET_FLOW_TYPE_IP6_IP6_N_TUPLE; + else + type = VNET_FLOW_TYPE_IP6_IP6; + protocol.prot = IP_PROTOCOL_IPV6; + } else type = VNET_FLOW_TYPE_IP6; break; default: + if (spec && mask) + { + type = VNET_FLOW_TYPE_GENERIC; + break; + } return clib_error_return (0, "Please specify a supported flow type"); } @@ -623,6 +700,30 @@ test_flow (vlib_main_t * vm, unformat_input_t * input, case IP_PROTOCOL_IPSEC_AH: flow.ip4_ipsec_esp.spi = spi; break; + case IP_PROTOCOL_IP_IN_IP: + clib_memcpy (&flow.ip4_ip4.in_src_addr, &in_ip4s, + sizeof (ip4_address_and_mask_t)); + clib_memcpy (&flow.ip4_ip4.in_dst_addr, &in_ip4d, + sizeof (ip4_address_and_mask_t)); + if (type == VNET_FLOW_TYPE_IP4_IP4_N_TUPLE) + { + flow.ip4_ip4.in_protocol.prot = in_proto.prot; + flow.ip4_ip4_n_tuple.in_src_port = in_sport; + flow.ip4_ip4_n_tuple.in_dst_port = in_dport; + } + break; + case IP_PROTOCOL_IPV6: + clib_memcpy (&flow.ip4_ip6.in_src_addr, &in_ip6s, + sizeof (ip6_address_and_mask_t)); + clib_memcpy (&flow.ip4_ip6.in_dst_addr, &in_ip6d, + sizeof (ip6_address_and_mask_t)); + if (type == VNET_FLOW_TYPE_IP4_IP6_N_TUPLE) + { + flow.ip4_ip6.in_protocol.prot = in_proto.prot; + flow.ip4_ip6_n_tuple.in_src_port = in_sport; + flow.ip4_ip6_n_tuple.in_dst_port = in_dport; + } + break; default: break; } @@ -656,10 +757,41 @@ test_flow (vlib_main_t * vm, unformat_input_t * input, if (type == VNET_FLOW_TYPE_IP6_VXLAN) flow.ip6_vxlan.vni = vni; break; + case IP_PROTOCOL_IP_IN_IP: + clib_memcpy (&flow.ip6_ip4.in_src_addr, &in_ip4s, + sizeof (ip4_address_and_mask_t)); + clib_memcpy (&flow.ip6_ip4.in_dst_addr, &in_ip4d, + sizeof (ip4_address_and_mask_t)); + if (type == VNET_FLOW_TYPE_IP6_IP4_N_TUPLE) + { + flow.ip6_ip4.in_protocol.prot = in_proto.prot; + flow.ip6_ip4_n_tuple.in_src_port = in_sport; + flow.ip6_ip4_n_tuple.in_dst_port = in_dport; + } + break; + case IP_PROTOCOL_IPV6: + clib_memcpy (&flow.ip6_ip6.in_src_addr, &in_ip6s, + sizeof (ip6_address_and_mask_t)); + clib_memcpy (&flow.ip6_ip6.in_dst_addr, &in_ip6d, + sizeof (ip6_address_and_mask_t)); + if (type == VNET_FLOW_TYPE_IP6_IP6_N_TUPLE) + { + flow.ip6_ip6.in_protocol.prot = in_proto.prot; + flow.ip6_ip6_n_tuple.in_src_port = in_sport; + flow.ip6_ip6_n_tuple.in_dst_port = in_dport; + } + break; default: 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); @@ -687,22 +819,22 @@ test_flow (vlib_main_t * vm, unformat_input_t * input, return 0; } -/* *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* */ static u8 * format_flow_match_element (u8 * s, va_list * args) diff --git a/src/vnet/flow/flow_types.api b/src/vnet/flow/flow_types.api index 86f7ce128cb..1696001d975 100644 --- a/src/vnet/flow/flow_types.api +++ b/src/vnet/flow/flow_types.api @@ -14,7 +14,7 @@ * limitations under the License. */ -option version = "0.0.3"; +option version = "0.0.4"; import "vnet/ethernet/ethernet_types.api"; import "vnet/ip/ip_types.api"; @@ -36,6 +36,25 @@ enum flow_type FLOW_TYPE_IP4_GTPU, }; +enum flow_type_v2 +{ + FLOW_TYPE_ETHERNET_V2 = 1, + FLOW_TYPE_IP4_V2, + FLOW_TYPE_IP6_V2, + FLOW_TYPE_IP4_L2TPV3OIP_V2, + FLOW_TYPE_IP4_IPSEC_ESP_V2, + FLOW_TYPE_IP4_IPSEC_AH_V2, + FLOW_TYPE_IP4_N_TUPLE_V2, + FLOW_TYPE_IP6_N_TUPLE_V2, + FLOW_TYPE_IP4_N_TUPLE_TAGGED_V2, + FLOW_TYPE_IP6_N_TUPLE_TAGGED_V2, + FLOW_TYPE_IP4_VXLAN_V2, + FLOW_TYPE_IP6_VXLAN_V2, + FLOW_TYPE_IP4_GTPC_V2, + FLOW_TYPE_IP4_GTPU_V2, + FLOW_TYPE_GENERIC_V2, +}; + enum flow_action { FLOW_ACTION_COUNT = 1, @@ -46,6 +65,31 @@ enum flow_action FLOW_ACTION_DROP = 64, }; +enum flow_action_v2 +{ + FLOW_ACTION_COUNT_V2 = 1, + FLOW_ACTION_MARK_V2 = 2, + FLOW_ACTION_BUFFER_ADVANCE_V2 = 4, + FLOW_ACTION_REDIRECT_TO_NODE_V2 = 8, + FLOW_ACTION_REDIRECT_TO_QUEUE_V2 = 16, + FLOW_ACTION_RSS_V2 = 32, + FLOW_ACTION_DROP_V2 = 64, +}; + +enum rss_function +{ + RSS_FUNC_DEFAULT, + RSS_FUNC_TOEPLITZ, + RSS_FUNC_SIMPLE_XOR, + RSS_FUNC_SYMMETRIC_TOEPLITZ, +}; + +typedef generic_pattern +{ + u8 spec[1024]; + u8 mask[1024]; +}; + typedef ip_port_and_mask { u16 port; @@ -193,6 +237,12 @@ typedef flow_ip4_gtpu u32 teid; }; +typedef flow_generic +{ + i32 foo; + vl_api_generic_pattern_t pattern; +}; + union flow { vl_api_flow_ethernet_t ethernet; @@ -211,6 +261,25 @@ union flow vl_api_flow_ip4_gtpu_t ip4_gtpu; }; +union flow_v2 +{ + vl_api_flow_ethernet_t ethernet; + vl_api_flow_ip4_t ip4; + vl_api_flow_ip6_t ip6; + vl_api_flow_ip4_l2tpv3oip_t ip4_l2tpv3oip; + vl_api_flow_ip4_ipsec_esp_t ip4_ipsec_esp; + vl_api_flow_ip4_ipsec_ah_t ip4_ipsec_ah; + vl_api_flow_ip4_n_tuple_t ip4_n_tuple; + vl_api_flow_ip6_n_tuple_t ip6_n_tuple; + vl_api_flow_ip4_n_tuple_tagged_t ip4_n_tuple_tagged; + vl_api_flow_ip6_n_tuple_tagged_t ip6_n_tuple_tagged; + vl_api_flow_ip4_vxlan_t ip4_vxlan; + vl_api_flow_ip6_vxlan_t ip6_vxlan; + vl_api_flow_ip4_gtpc_t ip4_gtpc; + vl_api_flow_ip4_gtpu_t ip4_gtpu; + vl_api_flow_generic_t generic; +}; + /* main flow struct */ typedef flow_rule { @@ -240,3 +309,41 @@ typedef flow_rule vl_api_flow_t flow; }; +/* main flow struct */ +typedef flow_rule_v2 +{ + /* flow type */ + vl_api_flow_type_v2_t type; + + /* flow index */ + u32 index; + + /* bitmap of flow actions (FLOW_ACTION_*) */ + vl_api_flow_action_v2_t actions; + + /* flow id for VNET_FLOW_ACTION_MARK */ + u32 mark_flow_id; + + /* node index and next index for FLOW_ACTION_REDIRECT_TO_NODE */ + u32 redirect_node_index; + u32 redirect_device_input_next_index; + + /* queue for FLOW_ACTION_REDIRECT_TO_QUEUE */ + u32 redirect_queue; + + /* start queue index and queue numbers for RSS queue group with FLOW_ACTION_RSS */ + u32 queue_index; + u32 queue_num; + + /* buffer offset for FLOW_ACTION_BUFFER_ADVANCE */ + i32 buffer_advance; + + /* RSS types, including IPv4/IPv6/TCP/UDP... */ + u64 rss_types; + + /* RSS functions, including IPv4/IPv6/TCP/UDP... */ + vl_api_rss_function_t rss_fun; + + /* flow enum */ + vl_api_flow_v2_t flow; +}; |