summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorXinyao Cai <xinyao.cai@intel.com>2023-02-28 14:44:58 +0800
committerDamjan Marion <dmarion@0xa5.net>2023-03-06 16:46:17 +0000
commit99d3a405431dadca2cb5138183603946b6d64408 (patch)
treee1894cae223d9f5c63953cf1a54d2293da04e9b6
parenta20afdc845f4e901f7d3e6974e59a0dc2e8bf427 (diff)
flow dpdk: introduce IP in IP support for flow
This patch introduces IP in IP packet support for flow cli and dpdk plugin. Specifically, the following IP in IP packet types are supported: MAC-IPv4-IPv4-TCP/UDP/None, MAC-IPv4-IPv6-TCP/UDP/None, MAC-IPv6-IPv4-TCP/UDP/None, MAC-IPv6-IPv6-TCP/UDP/None, IP in IP flow rules can be created by using the following new keywords in vppctl: in-src-ip, in-dst-ip : to provide information for inner IPv4 header in-ip6-src-ip, in-ip6-dst-ip: to provide information for inner IPv6 header in-proto : to specify inner transport layer protocol type (TCP or UDP) in-src-port, in-dst-port : to provide information for inner TCP/UDP header An example to create flow rule for MAC-IPv6-IPv6-TCP: test flow add index 0 ip6-src-ip any ip6-dst-ip any in-ip6-src-ip any in-ip6-dst-ip any in-proto tcp in-src-port 1234 in-dst-port any rss function default Another example to create flow rule for MAC-IPv6-IPv6: test flow add index 0 ip6-src-ip any in-ip6-src-ip any rss function default Type: feature Signed-off-by: Xinyao Cai <xinyao.cai@intel.com> Change-Id: I6a1ca36d47eb65b9cb5a4b8d874b2a7f017c35cd
-rw-r--r--src/plugins/dpdk/device/flow.c169
-rw-r--r--src/vnet/flow/flow.h47
-rw-r--r--src/vnet/flow/flow_cli.c118
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;
}