diff options
-rw-r--r-- | src/plugins/dpdk/device/flow.c | 169 | ||||
-rw-r--r-- | src/vnet/flow/flow.h | 47 | ||||
-rw-r--r-- | src/vnet/flow/flow_cli.c | 118 |
3 files changed, 305 insertions, 29 deletions
diff --git a/src/plugins/dpdk/device/flow.c b/src/plugins/dpdk/device/flow.c index be453bb9577..635f6f37ebf 100644 --- a/src/plugins/dpdk/device/flow.c +++ b/src/plugins/dpdk/device/flow.c @@ -29,22 +29,30 @@ #define FLOW_IS_ETHERNET_CLASS(f) \ (f->type == VNET_FLOW_TYPE_ETHERNET) -#define FLOW_IS_IPV4_CLASS(f) \ - ((f->type == VNET_FLOW_TYPE_IP4) || \ - (f->type == VNET_FLOW_TYPE_IP4_N_TUPLE) || \ - (f->type == VNET_FLOW_TYPE_IP4_N_TUPLE_TAGGED) || \ - (f->type == VNET_FLOW_TYPE_IP4_VXLAN) || \ - (f->type == VNET_FLOW_TYPE_IP4_GTPC) || \ - (f->type == VNET_FLOW_TYPE_IP4_GTPU) || \ - (f->type == VNET_FLOW_TYPE_IP4_L2TPV3OIP) || \ - (f->type == VNET_FLOW_TYPE_IP4_IPSEC_ESP) || \ - (f->type == VNET_FLOW_TYPE_IP4_IPSEC_AH)) - -#define FLOW_IS_IPV6_CLASS(f) \ - ((f->type == VNET_FLOW_TYPE_IP6) || \ - (f->type == VNET_FLOW_TYPE_IP6_N_TUPLE) || \ - (f->type == VNET_FLOW_TYPE_IP6_N_TUPLE_TAGGED) || \ - (f->type == VNET_FLOW_TYPE_IP6_VXLAN)) +#define FLOW_IS_IPV4_CLASS(f) \ + ((f->type == VNET_FLOW_TYPE_IP4) || \ + (f->type == VNET_FLOW_TYPE_IP4_N_TUPLE) || \ + (f->type == VNET_FLOW_TYPE_IP4_N_TUPLE_TAGGED) || \ + (f->type == VNET_FLOW_TYPE_IP4_VXLAN) || \ + (f->type == VNET_FLOW_TYPE_IP4_GTPC) || \ + (f->type == VNET_FLOW_TYPE_IP4_GTPU) || \ + (f->type == VNET_FLOW_TYPE_IP4_L2TPV3OIP) || \ + (f->type == VNET_FLOW_TYPE_IP4_IPSEC_ESP) || \ + (f->type == VNET_FLOW_TYPE_IP4_IPSEC_AH) || \ + (f->type == VNET_FLOW_TYPE_IP4_IP4) || \ + (f->type == VNET_FLOW_TYPE_IP4_IP6) || \ + (f->type == VNET_FLOW_TYPE_IP4_IP4_N_TUPLE) || \ + (f->type == VNET_FLOW_TYPE_IP4_IP6_N_TUPLE)) + +#define FLOW_IS_IPV6_CLASS(f) \ + ((f->type == VNET_FLOW_TYPE_IP6) || \ + (f->type == VNET_FLOW_TYPE_IP6_N_TUPLE) || \ + (f->type == VNET_FLOW_TYPE_IP6_N_TUPLE_TAGGED) || \ + (f->type == VNET_FLOW_TYPE_IP6_VXLAN) || \ + (f->type == VNET_FLOW_TYPE_IP6_IP4) || \ + (f->type == VNET_FLOW_TYPE_IP6_IP6) || \ + (f->type == VNET_FLOW_TYPE_IP6_IP4_N_TUPLE) || \ + (f->type == VNET_FLOW_TYPE_IP6_IP6_N_TUPLE)) /* check if flow is VLAN sensitive */ #define FLOW_HAS_VLAN_TAG(f) \ @@ -70,6 +78,13 @@ (f->type == VNET_FLOW_TYPE_IP4_GTPC) || \ (f->type == VNET_FLOW_TYPE_IP4_GTPU)) +/* check if flow has a inner TCP/UDP header */ +#define FLOW_HAS_INNER_N_TUPLE(f) \ + ((f->type == VNET_FLOW_TYPE_IP4_IP4_N_TUPLE) || \ + (f->type == VNET_FLOW_TYPE_IP4_IP6_N_TUPLE) || \ + (f->type == VNET_FLOW_TYPE_IP6_IP4_N_TUPLE) || \ + (f->type == VNET_FLOW_TYPE_IP6_IP6_N_TUPLE)) + /* constant structs */ static const struct rte_flow_attr ingress = {.ingress = 1 }; @@ -153,10 +168,10 @@ static int dpdk_flow_add (dpdk_device_t * xd, vnet_flow_t * f, dpdk_flow_entry_t * fe) { struct rte_flow_item_eth eth[2] = { }; - struct rte_flow_item_ipv4 ip4[2] = { }; - struct rte_flow_item_ipv6 ip6[2] = { }; - struct rte_flow_item_udp udp[2] = { }; - struct rte_flow_item_tcp tcp[2] = { }; + struct rte_flow_item_ipv4 ip4[2] = {}, in_ip4[2] = {}; + struct rte_flow_item_ipv6 ip6[2] = {}, in_ip6[2] = {}; + struct rte_flow_item_udp udp[2] = {}, in_UDP[2] = {}; + struct rte_flow_item_tcp tcp[2] = {}, in_TCP[2] = {}; struct rte_flow_item_gtp gtp[2] = { }; struct rte_flow_item_l2tpv3oip l2tp[2] = { }; struct rte_flow_item_esp esp[2] = { }; @@ -472,12 +487,118 @@ dpdk_flow_add (dpdk_device_t * xd, vnet_flow_t * f, dpdk_flow_entry_t * fe) item->mask = raw + 1; } break; + case IP_PROTOCOL_IPV6: + item->type = RTE_FLOW_ITEM_TYPE_IPV6; + +#define fill_inner_ip6_with_outer_ipv(OUTER_IP_VER) \ + if (f->type == VNET_FLOW_TYPE_IP##OUTER_IP_VER##_IP6 || \ + f->type == VNET_FLOW_TYPE_IP##OUTER_IP_VER##_IP6_N_TUPLE) \ + { \ + vnet_flow_ip##OUTER_IP_VER##_ip6_t *ptr = &f->ip##OUTER_IP_VER##_ip6; \ + if ((ptr->in_src_addr.mask.as_u64[0] == 0) && \ + (ptr->in_src_addr.mask.as_u64[1] == 0) && \ + (ptr->in_dst_addr.mask.as_u64[0] == 0) && \ + (ptr->in_dst_addr.mask.as_u64[1] == 0) && (!ptr->in_protocol.mask)) \ + { \ + item->spec = NULL; \ + item->mask = NULL; \ + } \ + else \ + { \ + clib_memcpy (in_ip6[0].hdr.src_addr, &ptr->in_src_addr.addr, \ + ARRAY_LEN (ptr->in_src_addr.addr.as_u8)); \ + clib_memcpy (in_ip6[1].hdr.src_addr, &ptr->in_src_addr.mask, \ + ARRAY_LEN (ptr->in_src_addr.mask.as_u8)); \ + clib_memcpy (in_ip6[0].hdr.dst_addr, &ptr->in_dst_addr.addr, \ + ARRAY_LEN (ptr->in_dst_addr.addr.as_u8)); \ + clib_memcpy (in_ip6[1].hdr.dst_addr, &ptr->in_dst_addr.mask, \ + ARRAY_LEN (ptr->in_dst_addr.mask.as_u8)); \ + item->spec = in_ip6; \ + item->mask = in_ip6 + 1; \ + } \ + } + fill_inner_ip6_with_outer_ipv (6) fill_inner_ip6_with_outer_ipv (4) +#undef fill_inner_ip6_with_outer_ipv + break; + case IP_PROTOCOL_IP_IN_IP: + item->type = RTE_FLOW_ITEM_TYPE_IPV4; +#define fill_inner_ip4_with_outer_ipv(OUTER_IP_VER) \ + if (f->type == VNET_FLOW_TYPE_IP##OUTER_IP_VER##_IP4 || \ + f->type == VNET_FLOW_TYPE_IP##OUTER_IP_VER##_IP4_N_TUPLE) \ + { \ + vnet_flow_ip##OUTER_IP_VER##_ip4_t *ptr = &f->ip##OUTER_IP_VER##_ip4; \ + if ((!ptr->in_src_addr.mask.as_u32) && \ + (!ptr->in_dst_addr.mask.as_u32) && (!ptr->in_protocol.mask)) \ + { \ + item->spec = NULL; \ + item->mask = NULL; \ + } \ + else \ + { \ + in_ip4[0].hdr.src_addr = ptr->in_src_addr.addr.as_u32; \ + in_ip4[1].hdr.src_addr = ptr->in_src_addr.mask.as_u32; \ + in_ip4[0].hdr.dst_addr = ptr->in_dst_addr.addr.as_u32; \ + in_ip4[1].hdr.dst_addr = ptr->in_dst_addr.mask.as_u32; \ + item->spec = in_ip4; \ + item->mask = in_ip4 + 1; \ + } \ + } + fill_inner_ip4_with_outer_ipv (6) fill_inner_ip4_with_outer_ipv (4) +#undef fill_inner_ip4_with_outer_ipv + break; default: rv = VNET_FLOW_ERROR_NOT_SUPPORTED; goto done; } + if (FLOW_HAS_INNER_N_TUPLE (f)) + { + vec_add2 (items, item, 1); + +#define fill_inner_n_tuple_of(proto) \ + item->type = RTE_FLOW_ITEM_TYPE_##proto; \ + if ((ptr->in_src_port.mask == 0) && (ptr->in_dst_port.mask == 0)) \ + { \ + item->spec = NULL; \ + item->mask = NULL; \ + } \ + else \ + { \ + in_##proto[0].hdr.src_port = \ + clib_host_to_net_u16 (ptr->in_src_port.port); \ + in_##proto[1].hdr.src_port = \ + clib_host_to_net_u16 (ptr->in_src_port.mask); \ + in_##proto[0].hdr.dst_port = \ + clib_host_to_net_u16 (ptr->in_dst_port.port); \ + in_##proto[1].hdr.dst_port = \ + clib_host_to_net_u16 (ptr->in_dst_port.mask); \ + item->spec = in_##proto; \ + item->mask = in_##proto + 1; \ + } + +#define fill_inner_n_tuple(OUTER_IP_VER, INNER_IP_VER) \ + if (f->type == \ + VNET_FLOW_TYPE_IP##OUTER_IP_VER##_IP##INNER_IP_VER##_N_TUPLE) \ + { \ + vnet_flow_ip##OUTER_IP_VER##_ip##INNER_IP_VER##_n_tuple_t *ptr = \ + &f->ip##OUTER_IP_VER##_ip##INNER_IP_VER##_n_tuple; \ + switch (ptr->in_protocol.prot) \ + { \ + case IP_PROTOCOL_UDP: \ + fill_inner_n_tuple_of (UDP) break; \ + case IP_PROTOCOL_TCP: \ + fill_inner_n_tuple_of (TCP) break; \ + default: \ + break; \ + } \ + } + fill_inner_n_tuple (6, 4) fill_inner_n_tuple (4, 4) + fill_inner_n_tuple (6, 6) fill_inner_n_tuple (4, 6) +#undef fill_inner_n_tuple +#undef fill_inner_n_tuple_of + } + pattern_end: if ((f->actions & VNET_FLOW_ACTION_RSS) && (f->rss_types & (1ULL << VNET_FLOW_RSS_TYPES_ESP))) @@ -692,6 +813,14 @@ dpdk_flow_ops_fn (vnet_main_t * vnm, vnet_flow_dev_op_t op, u32 dev_instance, case VNET_FLOW_TYPE_IP4_L2TPV3OIP: case VNET_FLOW_TYPE_IP4_IPSEC_ESP: case VNET_FLOW_TYPE_IP4_IPSEC_AH: + case VNET_FLOW_TYPE_IP4_IP4: + case VNET_FLOW_TYPE_IP4_IP4_N_TUPLE: + case VNET_FLOW_TYPE_IP4_IP6: + case VNET_FLOW_TYPE_IP4_IP6_N_TUPLE: + case VNET_FLOW_TYPE_IP6_IP4: + case VNET_FLOW_TYPE_IP6_IP4_N_TUPLE: + case VNET_FLOW_TYPE_IP6_IP6: + case VNET_FLOW_TYPE_IP6_IP6_N_TUPLE: case VNET_FLOW_TYPE_GENERIC: if ((rv = dpdk_flow_add (xd, flow, fe))) goto done; diff --git a/src/vnet/flow/flow.h b/src/vnet/flow/flow.h index 194579b88d8..9069bd1cea5 100644 --- a/src/vnet/flow/flow.h +++ b/src/vnet/flow/flow.h @@ -45,7 +45,16 @@ _ (IP4_GTPC, ip4_gtpc, "ipv4-gtpc") \ _ (IP4_GTPU, ip4_gtpu, "ipv4-gtpu") \ /* generic flow */ \ - _ (GENERIC, generic, "generic") + _ (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) @@ -106,6 +115,42 @@ 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 \ diff --git a/src/vnet/flow/flow_cli.c b/src/vnet/flow/flow_cli.c index 5f44a099f57..bf343b0d550 100644 --- a/src/vnet/flow/flow_cli.c +++ b/src/vnet/flow/flow_cli.c @@ -366,15 +366,16 @@ test_flow (vlib_main_t * vm, unformat_input_t * input, 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; @@ -415,12 +416,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; @@ -432,6 +445,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)) @@ -592,6 +614,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; @@ -600,6 +638,22 @@ 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; @@ -660,6 +714,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; } @@ -693,6 +771,30 @@ 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; } |