flow: Add GTP support

Type: feature

Adding:
	VNET_FLOW_TYPE_IP4_GTPC
	VNET_FLOW_TYPE_IP4_GTPU
	VNET_FLOW_TYPE_IP4_GTPU_IP4
	VNET_FLOW_TYPE_IP4_GTPU_IP6
	VNET_FLOW_TYPE_IP6_GTPC
	VNET_FLOW_TYPE_IP6_GTPU
	VNET_FLOW_TYPE_IP6_GTPU_IP4
	VNET_FLOW_TYPE_IP6_GTPU_IP6
in this patch

Signed-off-by: Chenmin Sun <chenmin.sun@intel.com>
Change-Id: I4ad53895b5ac0771432bb039b8c79e48e3c19f25
This commit is contained in:
Chenmin Sun
2019-10-18 07:35:16 +08:00
committed by Damjan Marion
parent 7c6102b1aa
commit bf85a98fbf
3 changed files with 514 additions and 46 deletions

File diff suppressed because it is too large Load Diff

View File

@ -26,7 +26,15 @@
_(IP4_N_TUPLE, ip4_n_tuple, "ipv4-n-tuple") \
_(IP6_N_TUPLE, ip6_n_tuple, "ipv6-n-tuple") \
_(IP4_VXLAN, ip4_vxlan, "ipv4-vxlan") \
_(IP6_VXLAN, ip6_vxlan, "ipv6-vxlan")
_(IP6_VXLAN, ip6_vxlan, "ipv6-vxlan") \
_(IP4_GTPC, ip4_gtpc, "ipv4-gtpc") \
_(IP4_GTPU, ip4_gtpu, "ipv4-gtpu") \
_(IP4_GTPU_IP4, ip4_gtpu_ip4, "ipv4-gtpu-ipv4") \
_(IP4_GTPU_IP6, ip4_gtpu_ip6, "ipv4-gtpu-ipv6") \
_(IP6_GTPC, ip6_gtpc, "ipv6-gtpc") \
_(IP6_GTPU, ip6_gtpu, "ipv6-gtpu") \
_(IP6_GTPU_IP4, ip6_gtpu_ip4, "ipv6-gtpu-ipv4") \
_(IP6_GTPU_IP6, ip6_gtpu_ip6, "ipv6-gtpu-ipv6")
#define foreach_flow_entry_ip4_n_tuple \
_fe(ip4_address_and_mask_t, src_addr) \
@ -54,6 +62,42 @@
_fe(u16, dst_port) \
_fe(u16, vni)
#define foreach_flow_entry_ip4_gtpc \
foreach_flow_entry_ip4_n_tuple \
_fe(u32, teid)
#define foreach_flow_entry_ip4_gtpu \
foreach_flow_entry_ip4_n_tuple \
_fe(u32, teid)
#define foreach_flow_entry_ip4_gtpu_ip4 \
foreach_flow_entry_ip4_gtpu \
_fe(ip4_address_and_mask_t, inner_src_addr) \
_fe(ip4_address_and_mask_t, inner_dst_addr)
#define foreach_flow_entry_ip4_gtpu_ip6 \
foreach_flow_entry_ip4_gtpu \
_fe(ip6_address_and_mask_t, inner_src_addr) \
_fe(ip6_address_and_mask_t, inner_dst_addr)
#define foreach_flow_entry_ip6_gtpc \
foreach_flow_entry_ip6_n_tuple \
_fe(u32, teid)
#define foreach_flow_entry_ip6_gtpu \
foreach_flow_entry_ip6_n_tuple \
_fe(u32, teid)
#define foreach_flow_entry_ip6_gtpu_ip4 \
foreach_flow_entry_ip6_gtpu \
_fe(ip4_address_and_mask_t, inner_src_addr) \
_fe(ip4_address_and_mask_t, inner_dst_addr)
#define foreach_flow_entry_ip6_gtpu_ip6 \
foreach_flow_entry_ip6_gtpu \
_fe(ip6_address_and_mask_t, inner_src_addr) \
_fe(ip6_address_and_mask_t, inner_dst_addr)
#define foreach_flow_action \
_(0, COUNT, "count") \
_(1, MARK, "mark") \

View File

@ -274,9 +274,26 @@ test_flow (vlib_main_t * vm, unformat_input_t * input,
FLOW_ENABLE,
FLOW_DISABLE
} action = FLOW_UNKNOWN_ACTION;
u32 hw_if_index = ~0, tmp, flow_index = ~0;
u32 hw_if_index = ~0, flow_index = ~0;
int rv;
u8 prot;
u32 prot = 0, teid = 0;
vnet_flow_type_t type = VNET_FLOW_TYPE_IP4_N_TUPLE;
bool is_gtpc_set = false;
bool is_gtpu_set = false;
vnet_flow_type_t outer_type = VNET_FLOW_TYPE_UNKNOWN;
vnet_flow_type_t inner_type = VNET_FLOW_TYPE_UNKNOWN;
bool outer_ip4_set = false, inner_ip4_set = false;
bool outer_ip6_set = false, inner_ip6_set = false;
ip4_address_and_mask_t ip4s = { };
ip4_address_and_mask_t ip4d = { };
ip4_address_and_mask_t inner_ip4s = { };
ip4_address_and_mask_t inner_ip4d = { };
ip6_address_and_mask_t ip6s = { };
ip6_address_and_mask_t ip6d = { };
ip6_address_and_mask_t inner_ip6s = { };
ip6_address_and_mask_t inner_ip6d = { };
ip_port_and_mask_t sport = { };
ip_port_and_mask_t dport = { };
clib_memset (&flow, 0, sizeof (vnet_flow_t));
flow.index = ~0;
@ -296,23 +313,44 @@ test_flow (vlib_main_t * vm, unformat_input_t * input,
else if (unformat (line_input, "disable"))
action = FLOW_DISABLE;
else if (unformat (line_input, "src-ip %U",
unformat_ip4_address_and_mask,
&flow.ip4_n_tuple.src_addr))
;
unformat_ip4_address_and_mask, &ip4s))
outer_ip4_set = true;
else if (unformat (line_input, "dst-ip %U",
unformat_ip4_address_and_mask,
&flow.ip4_n_tuple.dst_addr))
;
unformat_ip4_address_and_mask, &ip4d))
outer_ip4_set = true;
else if (unformat (line_input, "ip6-src-ip %U",
unformat_ip6_address_and_mask, &ip6s))
outer_ip6_set = true;
else if (unformat (line_input, "ip6-dst-ip %U",
unformat_ip6_address_and_mask, &ip6d))
outer_ip6_set = true;
else if (unformat (line_input, "inner-src-ip %U",
unformat_ip4_address_and_mask, &inner_ip4s))
inner_ip4_set = true;
else if (unformat (line_input, "inner-dst-ip %U",
unformat_ip4_address_and_mask, &inner_ip4d))
inner_ip4_set = true;
else if (unformat (line_input, "inner-ip6-src-ip %U",
unformat_ip6_address_and_mask, &inner_ip6s))
inner_ip6_set = true;
else if (unformat (line_input, "inner-ip6-dst-ip %U",
unformat_ip6_address_and_mask, &inner_ip6d))
inner_ip6_set = true;
else if (unformat (line_input, "src-port %U", unformat_ip_port_and_mask,
&flow.ip4_n_tuple.src_port))
&sport))
;
else if (unformat (line_input, "dst-port %U", unformat_ip_port_and_mask,
&flow.ip4_n_tuple.dst_port))
&dport))
;
else if (unformat (line_input, "proto %U", unformat_ip_protocol, &prot))
flow.ip4_n_tuple.protocol = prot;
else if (unformat (line_input, "proto %u", &tmp))
flow.ip4_n_tuple.protocol = tmp;
;
else if (unformat (line_input, "proto %u", &prot))
;
else if (unformat (line_input, "gtpc teid %u", &teid))
is_gtpc_set = true;
else if (unformat (line_input, "gtpu teid %u", &teid))
is_gtpu_set = true;
else if (unformat (line_input, "index %u", &flow_index))
;
else if (unformat (line_input, "next-node %U", unformat_vlib_node, vm,
@ -348,13 +386,167 @@ test_flow (vlib_main_t * vm, unformat_input_t * input,
switch (action)
{
case FLOW_ADD:
if (flow.ip4_n_tuple.protocol == (ip_protocol_t) ~ 0)
return clib_error_return (0, "Please specify ip protocol");
if (flow.actions == 0)
return clib_error_return (0, "Please specify at least one action");
flow.type = VNET_FLOW_TYPE_IP4_N_TUPLE;
/* Adjust the flow type */
if (outer_ip4_set == true)
outer_type = VNET_FLOW_TYPE_IP4_N_TUPLE;
else if (outer_ip6_set == true)
outer_type = VNET_FLOW_TYPE_IP6_N_TUPLE;
if (inner_ip4_set == true)
inner_type = VNET_FLOW_TYPE_IP4_N_TUPLE;
else if (inner_ip6_set == true)
inner_type = VNET_FLOW_TYPE_IP6_N_TUPLE;
if (outer_type == VNET_FLOW_TYPE_UNKNOWN)
return clib_error_return (0, "Please specify a supported flow type");
if (outer_type == VNET_FLOW_TYPE_IP4_N_TUPLE)
{
type = VNET_FLOW_TYPE_IP4_N_TUPLE;
if (inner_type == VNET_FLOW_TYPE_UNKNOWN)
{
if (is_gtpc_set)
type = VNET_FLOW_TYPE_IP4_GTPC;
else if (is_gtpu_set)
type = VNET_FLOW_TYPE_IP4_GTPU;
}
else if (inner_type == VNET_FLOW_TYPE_IP4_N_TUPLE)
{
if (is_gtpu_set)
type = VNET_FLOW_TYPE_IP4_GTPU_IP4;
}
else if (inner_type == VNET_FLOW_TYPE_IP6_N_TUPLE)
{
if (is_gtpu_set)
type = VNET_FLOW_TYPE_IP4_GTPU_IP6;
}
}
else if (outer_type == VNET_FLOW_TYPE_IP6_N_TUPLE)
{
type = VNET_FLOW_TYPE_IP6_N_TUPLE;
if (inner_type == VNET_FLOW_TYPE_UNKNOWN)
{
if (is_gtpc_set)
type = VNET_FLOW_TYPE_IP6_GTPC;
else if (is_gtpu_set)
type = VNET_FLOW_TYPE_IP6_GTPU;
}
else if (inner_type == VNET_FLOW_TYPE_IP4_N_TUPLE)
{
if (is_gtpu_set)
type = VNET_FLOW_TYPE_IP6_GTPU_IP4;
}
else if (inner_type == VNET_FLOW_TYPE_IP6_N_TUPLE)
{
if (is_gtpu_set)
type = VNET_FLOW_TYPE_IP6_GTPU_IP6;
}
}
//assign specific field values per flow type
switch (type)
{
case VNET_FLOW_TYPE_IP4_N_TUPLE:
case VNET_FLOW_TYPE_IP4_GTPC:
case VNET_FLOW_TYPE_IP4_GTPU:
case VNET_FLOW_TYPE_IP4_GTPU_IP4:
case VNET_FLOW_TYPE_IP4_GTPU_IP6:
clib_memcpy (&flow.ip4_n_tuple.src_addr, &ip4s,
sizeof (ip4_address_and_mask_t));
clib_memcpy (&flow.ip4_n_tuple.dst_addr, &ip4d,
sizeof (ip4_address_and_mask_t));
clib_memcpy (&flow.ip4_n_tuple.src_port, &sport,
sizeof (ip_port_and_mask_t));
clib_memcpy (&flow.ip4_n_tuple.dst_port, &dport,
sizeof (ip_port_and_mask_t));
flow.ip4_n_tuple.protocol = prot;
if (type == VNET_FLOW_TYPE_IP4_GTPC)
flow.ip4_gtpc.teid = teid;
else if (type == VNET_FLOW_TYPE_IP4_GTPU)
flow.ip4_gtpu.teid = teid;
else if (type == VNET_FLOW_TYPE_IP4_GTPU_IP4)
{
flow.ip4_gtpu_ip4.teid = teid;
clib_memcpy (&flow.ip4_gtpu_ip4.inner_src_addr, &inner_ip4s,
sizeof (ip4_address_and_mask_t));
clib_memcpy (&flow.ip4_gtpu_ip4.inner_dst_addr, &inner_ip4d,
sizeof (ip4_address_and_mask_t));
}
else if (type == VNET_FLOW_TYPE_IP4_GTPU_IP6)
{
flow.ip4_gtpu_ip6.teid = teid;
clib_memcpy (&flow.ip4_gtpu_ip6.inner_src_addr, &inner_ip6s,
sizeof (ip6_address_and_mask_t));
clib_memcpy (&flow.ip4_gtpu_ip6.inner_dst_addr, &inner_ip6d,
sizeof (ip6_address_and_mask_t));
}
if (flow.ip4_n_tuple.protocol == (ip_protocol_t) ~ 0)
return clib_error_return (0, "Please specify ip protocol");
if ((type != VNET_FLOW_TYPE_IP4_N_TUPLE) &&
(flow.ip4_n_tuple.protocol != IP_PROTOCOL_UDP))
return clib_error_return (0,
"For GTP related flow, ip protocol must be UDP");
break;
case VNET_FLOW_TYPE_IP6_N_TUPLE:
case VNET_FLOW_TYPE_IP6_GTPC:
case VNET_FLOW_TYPE_IP6_GTPU:
case VNET_FLOW_TYPE_IP6_GTPU_IP4:
case VNET_FLOW_TYPE_IP6_GTPU_IP6:
clib_memcpy (&flow.ip6_n_tuple.src_addr, &ip6s,
sizeof (ip6_address_and_mask_t));
clib_memcpy (&flow.ip6_n_tuple.dst_addr, &ip6d,
sizeof (ip6_address_and_mask_t));
clib_memcpy (&flow.ip6_n_tuple.src_port, &sport,
sizeof (ip_port_and_mask_t));
clib_memcpy (&flow.ip6_n_tuple.dst_port, &dport,
sizeof (ip_port_and_mask_t));
flow.ip6_n_tuple.protocol = prot;
if (type == VNET_FLOW_TYPE_IP6_GTPC)
flow.ip6_gtpc.teid = teid;
else if (type == VNET_FLOW_TYPE_IP6_GTPU)
flow.ip6_gtpu.teid = teid;
else if (type == VNET_FLOW_TYPE_IP6_GTPU_IP4)
{
flow.ip6_gtpu_ip4.teid = teid;
clib_memcpy (&flow.ip6_gtpu_ip4.inner_src_addr, &inner_ip4s,
sizeof (ip4_address_and_mask_t));
clib_memcpy (&flow.ip6_gtpu_ip4.inner_dst_addr, &inner_ip4d,
sizeof (ip4_address_and_mask_t));
}
else if (type == VNET_FLOW_TYPE_IP6_GTPU_IP6)
{
flow.ip6_gtpu_ip6.teid = teid;
clib_memcpy (&flow.ip6_gtpu_ip6.inner_src_addr, &inner_ip6s,
sizeof (ip6_address_and_mask_t));
clib_memcpy (&flow.ip6_gtpu_ip6.inner_dst_addr, &inner_ip6d,
sizeof (ip6_address_and_mask_t));
}
if (flow.ip6_n_tuple.protocol == (ip_protocol_t) ~ 0)
return clib_error_return (0, "Please specify ip protocol");
if ((type != VNET_FLOW_TYPE_IP4_N_TUPLE) &&
(flow.ip6_n_tuple.protocol != IP_PROTOCOL_UDP))
return clib_error_return (0,
"For GTP related flow, ip protocol must be UDP");
break;
default:
break;
}
flow.type = type;
rv = vnet_flow_add (vnm, &flow, &flow_index);
if (!rv)
printf ("flow %u added\n", flow_index);
break;
case FLOW_DEL:
rv = vnet_flow_del (vnm, flow_index);