xref: /f-stack/dpdk/app/test/test_flow_classify.c (revision 0c6bd470)
14418919fSjohnjiang /* SPDX-License-Identifier: BSD-3-Clause
24418919fSjohnjiang  * Copyright(c) 2017 Intel Corporation
34418919fSjohnjiang  */
44418919fSjohnjiang 
54418919fSjohnjiang #include <string.h>
64418919fSjohnjiang #include <errno.h>
74418919fSjohnjiang 
84418919fSjohnjiang #include "test.h"
94418919fSjohnjiang 
104418919fSjohnjiang #include <rte_string_fns.h>
114418919fSjohnjiang #include <rte_mbuf.h>
124418919fSjohnjiang #include <rte_byteorder.h>
134418919fSjohnjiang #include <rte_ip.h>
144418919fSjohnjiang #include <rte_acl.h>
154418919fSjohnjiang #include <rte_common.h>
164418919fSjohnjiang #include <rte_table_acl.h>
174418919fSjohnjiang #include <rte_flow.h>
184418919fSjohnjiang #include <rte_flow_classify.h>
194418919fSjohnjiang 
204418919fSjohnjiang #include "packet_burst_generator.h"
214418919fSjohnjiang #include "test_flow_classify.h"
224418919fSjohnjiang 
234418919fSjohnjiang 
244418919fSjohnjiang #define FLOW_CLASSIFY_MAX_RULE_NUM 100
254418919fSjohnjiang #define MAX_PKT_BURST              32
26*0c6bd470Sfengbojiang #define NB_SOCKETS                 4
274418919fSjohnjiang #define MEMPOOL_CACHE_SIZE         256
284418919fSjohnjiang #define MBUF_SIZE                  512
294418919fSjohnjiang #define NB_MBUF                    512
304418919fSjohnjiang 
314418919fSjohnjiang /* test UDP, TCP and SCTP packets */
324418919fSjohnjiang static struct rte_mempool *mbufpool[NB_SOCKETS];
334418919fSjohnjiang static struct rte_mbuf *bufs[MAX_PKT_BURST];
344418919fSjohnjiang 
354418919fSjohnjiang static struct rte_acl_field_def ipv4_defs[NUM_FIELDS_IPV4] = {
364418919fSjohnjiang 	/* first input field - always one byte long. */
374418919fSjohnjiang 	{
384418919fSjohnjiang 		.type = RTE_ACL_FIELD_TYPE_BITMASK,
394418919fSjohnjiang 		.size = sizeof(uint8_t),
404418919fSjohnjiang 		.field_index = PROTO_FIELD_IPV4,
414418919fSjohnjiang 		.input_index = PROTO_INPUT_IPV4,
424418919fSjohnjiang 		.offset = sizeof(struct rte_ether_hdr) +
434418919fSjohnjiang 			offsetof(struct rte_ipv4_hdr, next_proto_id),
444418919fSjohnjiang 	},
454418919fSjohnjiang 	/* next input field (IPv4 source address) - 4 consecutive bytes. */
464418919fSjohnjiang 	{
474418919fSjohnjiang 		/* rte_flow uses a bit mask for IPv4 addresses */
484418919fSjohnjiang 		.type = RTE_ACL_FIELD_TYPE_BITMASK,
494418919fSjohnjiang 		.size = sizeof(uint32_t),
504418919fSjohnjiang 		.field_index = SRC_FIELD_IPV4,
514418919fSjohnjiang 		.input_index = SRC_INPUT_IPV4,
524418919fSjohnjiang 		.offset = sizeof(struct rte_ether_hdr) +
534418919fSjohnjiang 			offsetof(struct rte_ipv4_hdr, src_addr),
544418919fSjohnjiang 	},
554418919fSjohnjiang 	/* next input field (IPv4 destination address) - 4 consecutive bytes. */
564418919fSjohnjiang 	{
574418919fSjohnjiang 		/* rte_flow uses a bit mask for IPv4 addresses */
584418919fSjohnjiang 		.type = RTE_ACL_FIELD_TYPE_BITMASK,
594418919fSjohnjiang 		.size = sizeof(uint32_t),
604418919fSjohnjiang 		.field_index = DST_FIELD_IPV4,
614418919fSjohnjiang 		.input_index = DST_INPUT_IPV4,
624418919fSjohnjiang 		.offset = sizeof(struct rte_ether_hdr) +
634418919fSjohnjiang 			offsetof(struct rte_ipv4_hdr, dst_addr),
644418919fSjohnjiang 	},
654418919fSjohnjiang 	/*
664418919fSjohnjiang 	 * Next 2 fields (src & dst ports) form 4 consecutive bytes.
674418919fSjohnjiang 	 * They share the same input index.
684418919fSjohnjiang 	 */
694418919fSjohnjiang 	{
704418919fSjohnjiang 		/* rte_flow uses a bit mask for protocol ports */
714418919fSjohnjiang 		.type = RTE_ACL_FIELD_TYPE_BITMASK,
724418919fSjohnjiang 		.size = sizeof(uint16_t),
734418919fSjohnjiang 		.field_index = SRCP_FIELD_IPV4,
744418919fSjohnjiang 		.input_index = SRCP_DESTP_INPUT_IPV4,
754418919fSjohnjiang 		.offset = sizeof(struct rte_ether_hdr) +
764418919fSjohnjiang 			sizeof(struct rte_ipv4_hdr) +
774418919fSjohnjiang 			offsetof(struct rte_tcp_hdr, src_port),
784418919fSjohnjiang 	},
794418919fSjohnjiang 	{
804418919fSjohnjiang 		/* rte_flow uses a bit mask for protocol ports */
814418919fSjohnjiang 		.type = RTE_ACL_FIELD_TYPE_BITMASK,
824418919fSjohnjiang 		.size = sizeof(uint16_t),
834418919fSjohnjiang 		.field_index = DSTP_FIELD_IPV4,
844418919fSjohnjiang 		.input_index = SRCP_DESTP_INPUT_IPV4,
854418919fSjohnjiang 		.offset = sizeof(struct rte_ether_hdr) +
864418919fSjohnjiang 			sizeof(struct rte_ipv4_hdr) +
874418919fSjohnjiang 			offsetof(struct rte_tcp_hdr, dst_port),
884418919fSjohnjiang 	},
894418919fSjohnjiang };
904418919fSjohnjiang 
914418919fSjohnjiang /* parameters for rte_flow_classify_validate and rte_flow_classify_create */
924418919fSjohnjiang 
934418919fSjohnjiang /* test UDP pattern:
944418919fSjohnjiang  * "eth / ipv4 src spec 2.2.2.3 src mask 255.255.255.00 dst spec 2.2.2.7
954418919fSjohnjiang  *  dst mask 255.255.255.00 / udp src is 32 dst is 33 / end"
964418919fSjohnjiang  */
974418919fSjohnjiang static struct rte_flow_item_ipv4 ipv4_udp_spec_1 = {
984418919fSjohnjiang 	{ 0, 0, 0, 0, 0, 0, IPPROTO_UDP, 0,
994418919fSjohnjiang 	  RTE_IPV4(2, 2, 2, 3), RTE_IPV4(2, 2, 2, 7)}
1004418919fSjohnjiang };
1014418919fSjohnjiang static const struct rte_flow_item_ipv4 ipv4_mask_24 = {
1024418919fSjohnjiang 	.hdr = {
1034418919fSjohnjiang 		.next_proto_id = 0xff,
1044418919fSjohnjiang 		.src_addr = 0xffffff00,
1054418919fSjohnjiang 		.dst_addr = 0xffffff00,
1064418919fSjohnjiang 	},
1074418919fSjohnjiang };
1084418919fSjohnjiang static struct rte_flow_item_udp udp_spec_1 = {
1094418919fSjohnjiang 	{ 32, 33, 0, 0 }
1104418919fSjohnjiang };
1114418919fSjohnjiang 
1124418919fSjohnjiang static struct rte_flow_item  eth_item = { RTE_FLOW_ITEM_TYPE_ETH,
1134418919fSjohnjiang 	0, 0, 0 };
1144418919fSjohnjiang static struct rte_flow_item  eth_item_bad = { -1, 0, 0, 0 };
1154418919fSjohnjiang 
1164418919fSjohnjiang static struct rte_flow_item  ipv4_udp_item_1 = { RTE_FLOW_ITEM_TYPE_IPV4,
1174418919fSjohnjiang 	&ipv4_udp_spec_1, 0, &ipv4_mask_24};
1184418919fSjohnjiang static struct rte_flow_item  ipv4_udp_item_bad = { RTE_FLOW_ITEM_TYPE_IPV4,
1194418919fSjohnjiang 	NULL, 0, NULL};
1204418919fSjohnjiang 
1214418919fSjohnjiang static struct rte_flow_item  udp_item_1 = { RTE_FLOW_ITEM_TYPE_UDP,
1224418919fSjohnjiang 	&udp_spec_1, 0, &rte_flow_item_udp_mask};
1234418919fSjohnjiang static struct rte_flow_item  udp_item_bad = { RTE_FLOW_ITEM_TYPE_UDP,
1244418919fSjohnjiang 	NULL, 0, NULL};
1254418919fSjohnjiang 
1264418919fSjohnjiang static struct rte_flow_item  end_item = { RTE_FLOW_ITEM_TYPE_END,
1274418919fSjohnjiang 	0, 0, 0 };
1284418919fSjohnjiang 
1294418919fSjohnjiang /* test TCP pattern:
1304418919fSjohnjiang  * "eth / ipv4 src spec 1.2.3.4 src mask 255.255.255.00 dst spec 5.6.7.8
1314418919fSjohnjiang  *  dst mask 255.255.255.00 / tcp src is 16 dst is 17 / end"
1324418919fSjohnjiang  */
1334418919fSjohnjiang static struct rte_flow_item_ipv4 ipv4_tcp_spec_1 = {
1344418919fSjohnjiang 	{ 0, 0, 0, 0, 0, 0, IPPROTO_TCP, 0,
1354418919fSjohnjiang 	  RTE_IPV4(1, 2, 3, 4), RTE_IPV4(5, 6, 7, 8)}
1364418919fSjohnjiang };
1374418919fSjohnjiang 
1384418919fSjohnjiang static struct rte_flow_item_tcp tcp_spec_1 = {
1394418919fSjohnjiang 	{ 16, 17, 0, 0, 0, 0, 0, 0, 0}
1404418919fSjohnjiang };
1414418919fSjohnjiang 
1424418919fSjohnjiang static struct rte_flow_item  ipv4_tcp_item_1 = { RTE_FLOW_ITEM_TYPE_IPV4,
1434418919fSjohnjiang 	&ipv4_tcp_spec_1, 0, &ipv4_mask_24};
1444418919fSjohnjiang 
1454418919fSjohnjiang static struct rte_flow_item  tcp_item_1 = { RTE_FLOW_ITEM_TYPE_TCP,
1464418919fSjohnjiang 	&tcp_spec_1, 0, &rte_flow_item_tcp_mask};
1474418919fSjohnjiang 
1484418919fSjohnjiang /* test SCTP pattern:
1494418919fSjohnjiang  * "eth / ipv4 src spec 1.2.3.4 src mask 255.255.255.00 dst spec 5.6.7.8
1504418919fSjohnjiang  *  dst mask 255.255.255.00 / sctp src is 16 dst is 17/ end"
1514418919fSjohnjiang  */
1524418919fSjohnjiang static struct rte_flow_item_ipv4 ipv4_sctp_spec_1 = {
1534418919fSjohnjiang 	{ 0, 0, 0, 0, 0, 0, IPPROTO_SCTP, 0, RTE_IPV4(11, 12, 13, 14),
1544418919fSjohnjiang 	RTE_IPV4(15, 16, 17, 18)}
1554418919fSjohnjiang };
1564418919fSjohnjiang 
1574418919fSjohnjiang static struct rte_flow_item_sctp sctp_spec_1 = {
1584418919fSjohnjiang 	{ 10, 11, 0, 0}
1594418919fSjohnjiang };
1604418919fSjohnjiang 
1614418919fSjohnjiang static struct rte_flow_item  ipv4_sctp_item_1 = { RTE_FLOW_ITEM_TYPE_IPV4,
1624418919fSjohnjiang 	&ipv4_sctp_spec_1, 0, &ipv4_mask_24};
1634418919fSjohnjiang 
1644418919fSjohnjiang static struct rte_flow_item  sctp_item_1 = { RTE_FLOW_ITEM_TYPE_SCTP,
1654418919fSjohnjiang 	&sctp_spec_1, 0, &rte_flow_item_sctp_mask};
1664418919fSjohnjiang 
1674418919fSjohnjiang 
1684418919fSjohnjiang /* test actions:
1694418919fSjohnjiang  * "actions count / end"
1704418919fSjohnjiang  */
1714418919fSjohnjiang static struct rte_flow_query_count count = {
1724418919fSjohnjiang 	.reset = 1,
1734418919fSjohnjiang 	.hits_set = 1,
1744418919fSjohnjiang 	.bytes_set = 1,
1754418919fSjohnjiang 	.hits = 0,
1764418919fSjohnjiang 	.bytes = 0,
1774418919fSjohnjiang };
1784418919fSjohnjiang static struct rte_flow_action count_action = { RTE_FLOW_ACTION_TYPE_COUNT,
1794418919fSjohnjiang 	&count};
1804418919fSjohnjiang static struct rte_flow_action count_action_bad = { -1, 0};
1814418919fSjohnjiang 
1824418919fSjohnjiang static struct rte_flow_action end_action = { RTE_FLOW_ACTION_TYPE_END, 0};
1834418919fSjohnjiang 
1844418919fSjohnjiang static struct rte_flow_action actions[2];
1854418919fSjohnjiang 
1864418919fSjohnjiang /* test attributes */
1874418919fSjohnjiang static struct rte_flow_attr attr;
1884418919fSjohnjiang 
1894418919fSjohnjiang /* test error */
1904418919fSjohnjiang static struct rte_flow_error error;
1914418919fSjohnjiang 
1924418919fSjohnjiang /* test pattern */
1934418919fSjohnjiang static struct rte_flow_item  pattern[4];
1944418919fSjohnjiang 
1954418919fSjohnjiang /* flow classify data for UDP burst */
1964418919fSjohnjiang static struct rte_flow_classify_ipv4_5tuple_stats udp_ntuple_stats;
1974418919fSjohnjiang static struct rte_flow_classify_stats udp_classify_stats = {
1984418919fSjohnjiang 		.stats = (void *)&udp_ntuple_stats
1994418919fSjohnjiang };
2004418919fSjohnjiang 
2014418919fSjohnjiang /* flow classify data for TCP burst */
2024418919fSjohnjiang static struct rte_flow_classify_ipv4_5tuple_stats tcp_ntuple_stats;
2034418919fSjohnjiang static struct rte_flow_classify_stats tcp_classify_stats = {
2044418919fSjohnjiang 		.stats = (void *)&tcp_ntuple_stats
2054418919fSjohnjiang };
2064418919fSjohnjiang 
2074418919fSjohnjiang /* flow classify data for SCTP burst */
2084418919fSjohnjiang static struct rte_flow_classify_ipv4_5tuple_stats sctp_ntuple_stats;
2094418919fSjohnjiang static struct rte_flow_classify_stats sctp_classify_stats = {
2104418919fSjohnjiang 		.stats = (void *)&sctp_ntuple_stats
2114418919fSjohnjiang };
2124418919fSjohnjiang 
2134418919fSjohnjiang struct flow_classifier_acl *cls;
2144418919fSjohnjiang 
2154418919fSjohnjiang struct flow_classifier_acl {
2164418919fSjohnjiang 	struct rte_flow_classifier *cls;
2174418919fSjohnjiang } __rte_cache_aligned;
2184418919fSjohnjiang 
2194418919fSjohnjiang /*
2204418919fSjohnjiang  * test functions by passing invalid or
2214418919fSjohnjiang  * non-workable parameters.
2224418919fSjohnjiang  */
2234418919fSjohnjiang static int
test_invalid_parameters(void)2244418919fSjohnjiang test_invalid_parameters(void)
2254418919fSjohnjiang {
2264418919fSjohnjiang 	struct rte_flow_classify_rule *rule;
2274418919fSjohnjiang 	int ret;
2284418919fSjohnjiang 
2294418919fSjohnjiang 	ret = rte_flow_classify_validate(NULL, NULL, NULL, NULL, NULL);
2304418919fSjohnjiang 	if (!ret) {
2314418919fSjohnjiang 		printf("Line %i: rte_flow_classify_validate",
2324418919fSjohnjiang 			__LINE__);
2334418919fSjohnjiang 		printf(" with NULL param should have failed!\n");
2344418919fSjohnjiang 		return -1;
2354418919fSjohnjiang 	}
2364418919fSjohnjiang 
2374418919fSjohnjiang 	rule = rte_flow_classify_table_entry_add(NULL, NULL, NULL, NULL,
2384418919fSjohnjiang 			NULL, NULL);
2394418919fSjohnjiang 	if (rule) {
2404418919fSjohnjiang 		printf("Line %i: flow_classifier_table_entry_add", __LINE__);
2414418919fSjohnjiang 		printf(" with NULL param should have failed!\n");
2424418919fSjohnjiang 		return -1;
2434418919fSjohnjiang 	}
2444418919fSjohnjiang 
2454418919fSjohnjiang 	ret = rte_flow_classify_table_entry_delete(NULL, NULL);
2464418919fSjohnjiang 	if (!ret) {
2474418919fSjohnjiang 		printf("Line %i: rte_flow_classify_table_entry_delete",
2484418919fSjohnjiang 			__LINE__);
2494418919fSjohnjiang 		printf(" with NULL param should have failed!\n");
2504418919fSjohnjiang 		return -1;
2514418919fSjohnjiang 	}
2524418919fSjohnjiang 
2534418919fSjohnjiang 	ret = rte_flow_classifier_query(NULL, NULL, 0, NULL, NULL);
2544418919fSjohnjiang 	if (!ret) {
2554418919fSjohnjiang 		printf("Line %i: flow_classifier_query", __LINE__);
2564418919fSjohnjiang 		printf(" with NULL param should have failed!\n");
2574418919fSjohnjiang 		return -1;
2584418919fSjohnjiang 	}
2594418919fSjohnjiang 
2604418919fSjohnjiang 	rule = rte_flow_classify_table_entry_add(NULL, NULL, NULL, NULL,
2614418919fSjohnjiang 		NULL, &error);
2624418919fSjohnjiang 	if (rule) {
2634418919fSjohnjiang 		printf("Line %i: flow_classify_table_entry_add ", __LINE__);
2644418919fSjohnjiang 		printf("with NULL param should have failed!\n");
2654418919fSjohnjiang 		return -1;
2664418919fSjohnjiang 	}
2674418919fSjohnjiang 
2684418919fSjohnjiang 	ret = rte_flow_classify_table_entry_delete(NULL, NULL);
2694418919fSjohnjiang 	if (!ret) {
2704418919fSjohnjiang 		printf("Line %i: rte_flow_classify_table_entry_delete",
2714418919fSjohnjiang 			__LINE__);
2724418919fSjohnjiang 		printf("with NULL param should have failed!\n");
2734418919fSjohnjiang 		return -1;
2744418919fSjohnjiang 	}
2754418919fSjohnjiang 
2764418919fSjohnjiang 	ret = rte_flow_classifier_query(NULL, NULL, 0, NULL, NULL);
2774418919fSjohnjiang 	if (!ret) {
2784418919fSjohnjiang 		printf("Line %i: flow_classifier_query", __LINE__);
2794418919fSjohnjiang 		printf(" with NULL param should have failed!\n");
2804418919fSjohnjiang 		return -1;
2814418919fSjohnjiang 	}
2824418919fSjohnjiang 	return 0;
2834418919fSjohnjiang }
2844418919fSjohnjiang 
2854418919fSjohnjiang static int
test_valid_parameters(void)2864418919fSjohnjiang test_valid_parameters(void)
2874418919fSjohnjiang {
2884418919fSjohnjiang 	struct rte_flow_classify_rule *rule;
2894418919fSjohnjiang 	int ret;
2904418919fSjohnjiang 	int key_found;
2914418919fSjohnjiang 
2924418919fSjohnjiang 	/*
2934418919fSjohnjiang 	 * set up parameters for rte_flow_classify_validate,
2944418919fSjohnjiang 	 * rte_flow_classify_table_entry_add and
2954418919fSjohnjiang 	 * rte_flow_classify_table_entry_delete
2964418919fSjohnjiang 	 */
2974418919fSjohnjiang 
2984418919fSjohnjiang 	attr.ingress = 1;
2994418919fSjohnjiang 	attr.priority = 1;
3004418919fSjohnjiang 	pattern[0] = eth_item;
3014418919fSjohnjiang 	pattern[1] = ipv4_udp_item_1;
3024418919fSjohnjiang 	pattern[2] = udp_item_1;
3034418919fSjohnjiang 	pattern[3] = end_item;
3044418919fSjohnjiang 	actions[0] = count_action;
3054418919fSjohnjiang 	actions[1] = end_action;
3064418919fSjohnjiang 
3074418919fSjohnjiang 	ret = rte_flow_classify_validate(cls->cls, &attr, pattern,
3084418919fSjohnjiang 			actions, &error);
3094418919fSjohnjiang 	if (ret) {
3104418919fSjohnjiang 		printf("Line %i: rte_flow_classify_validate",
3114418919fSjohnjiang 			__LINE__);
3124418919fSjohnjiang 		printf(" should not have failed!\n");
3134418919fSjohnjiang 		return -1;
3144418919fSjohnjiang 	}
3154418919fSjohnjiang 	rule = rte_flow_classify_table_entry_add(cls->cls, &attr, pattern,
3164418919fSjohnjiang 			actions, &key_found, &error);
3174418919fSjohnjiang 
3184418919fSjohnjiang 	if (!rule) {
3194418919fSjohnjiang 		printf("Line %i: flow_classify_table_entry_add", __LINE__);
3204418919fSjohnjiang 		printf(" should not have failed!\n");
3214418919fSjohnjiang 		return -1;
3224418919fSjohnjiang 	}
3234418919fSjohnjiang 
3244418919fSjohnjiang 	ret = rte_flow_classify_table_entry_delete(cls->cls, rule);
3254418919fSjohnjiang 	if (ret) {
3264418919fSjohnjiang 		printf("Line %i: rte_flow_classify_table_entry_delete",
3274418919fSjohnjiang 			__LINE__);
3284418919fSjohnjiang 		printf(" should not have failed!\n");
3294418919fSjohnjiang 		return -1;
3304418919fSjohnjiang 	}
3314418919fSjohnjiang 	return 0;
3324418919fSjohnjiang }
3334418919fSjohnjiang 
3344418919fSjohnjiang static int
test_invalid_patterns(void)3354418919fSjohnjiang test_invalid_patterns(void)
3364418919fSjohnjiang {
3374418919fSjohnjiang 	struct rte_flow_classify_rule *rule;
3384418919fSjohnjiang 	int ret;
3394418919fSjohnjiang 	int key_found;
3404418919fSjohnjiang 
3414418919fSjohnjiang 	/*
3424418919fSjohnjiang 	 * set up parameters for rte_flow_classify_validate,
3434418919fSjohnjiang 	 * rte_flow_classify_table_entry_add and
3444418919fSjohnjiang 	 * rte_flow_classify_table_entry_delete
3454418919fSjohnjiang 	 */
3464418919fSjohnjiang 
3474418919fSjohnjiang 	attr.ingress = 1;
3484418919fSjohnjiang 	attr.priority = 1;
3494418919fSjohnjiang 	pattern[0] = eth_item_bad;
3504418919fSjohnjiang 	pattern[1] = ipv4_udp_item_1;
3514418919fSjohnjiang 	pattern[2] = udp_item_1;
3524418919fSjohnjiang 	pattern[3] = end_item;
3534418919fSjohnjiang 	actions[0] = count_action;
3544418919fSjohnjiang 	actions[1] = end_action;
3554418919fSjohnjiang 
3564418919fSjohnjiang 	pattern[0] = eth_item;
3574418919fSjohnjiang 	pattern[1] = ipv4_udp_item_bad;
3584418919fSjohnjiang 
3594418919fSjohnjiang 	ret = rte_flow_classify_validate(cls->cls, &attr, pattern,
3604418919fSjohnjiang 			actions, &error);
3614418919fSjohnjiang 	if (!ret) {
3624418919fSjohnjiang 		printf("Line %i: rte_flow_classify_validate", __LINE__);
3634418919fSjohnjiang 		printf(" should have failed!\n");
3644418919fSjohnjiang 		return -1;
3654418919fSjohnjiang 	}
3664418919fSjohnjiang 
3674418919fSjohnjiang 	rule = rte_flow_classify_table_entry_add(cls->cls, &attr, pattern,
3684418919fSjohnjiang 			actions, &key_found, &error);
3694418919fSjohnjiang 	if (rule) {
3704418919fSjohnjiang 		printf("Line %i: flow_classify_table_entry_add", __LINE__);
3714418919fSjohnjiang 		printf(" should have failed!\n");
3724418919fSjohnjiang 		return -1;
3734418919fSjohnjiang 	}
3744418919fSjohnjiang 
3754418919fSjohnjiang 	ret = rte_flow_classify_table_entry_delete(cls->cls, rule);
3764418919fSjohnjiang 	if (!ret) {
3774418919fSjohnjiang 		printf("Line %i: rte_flow_classify_table_entry_delete",
3784418919fSjohnjiang 			__LINE__);
3794418919fSjohnjiang 		printf(" should have failed!\n");
3804418919fSjohnjiang 		return -1;
3814418919fSjohnjiang 	}
3824418919fSjohnjiang 
3834418919fSjohnjiang 	pattern[1] = ipv4_udp_item_1;
3844418919fSjohnjiang 	pattern[2] = udp_item_bad;
3854418919fSjohnjiang 	pattern[3] = end_item;
3864418919fSjohnjiang 
3874418919fSjohnjiang 	ret = rte_flow_classify_validate(cls->cls, &attr, pattern,
3884418919fSjohnjiang 			actions, &error);
3894418919fSjohnjiang 	if (!ret) {
3904418919fSjohnjiang 		printf("Line %i: rte_flow_classify_validate", __LINE__);
3914418919fSjohnjiang 		printf(" should have failed!\n");
3924418919fSjohnjiang 		return -1;
3934418919fSjohnjiang 	}
3944418919fSjohnjiang 
3954418919fSjohnjiang 	rule = rte_flow_classify_table_entry_add(cls->cls, &attr, pattern,
3964418919fSjohnjiang 			actions, &key_found, &error);
3974418919fSjohnjiang 	if (rule) {
3984418919fSjohnjiang 		printf("Line %i: flow_classify_table_entry_add", __LINE__);
3994418919fSjohnjiang 		printf(" should have failed!\n");
4004418919fSjohnjiang 		return -1;
4014418919fSjohnjiang 	}
4024418919fSjohnjiang 
4034418919fSjohnjiang 	ret = rte_flow_classify_table_entry_delete(cls->cls, rule);
4044418919fSjohnjiang 	if (!ret) {
4054418919fSjohnjiang 		printf("Line %i: rte_flow_classify_table_entry_delete",
4064418919fSjohnjiang 			__LINE__);
4074418919fSjohnjiang 		printf(" should have failed!\n");
4084418919fSjohnjiang 		return -1;
4094418919fSjohnjiang 	}
4104418919fSjohnjiang 	return 0;
4114418919fSjohnjiang }
4124418919fSjohnjiang 
4134418919fSjohnjiang static int
test_invalid_actions(void)4144418919fSjohnjiang test_invalid_actions(void)
4154418919fSjohnjiang {
4164418919fSjohnjiang 	struct rte_flow_classify_rule *rule;
4174418919fSjohnjiang 	int ret;
4184418919fSjohnjiang 	int key_found;
4194418919fSjohnjiang 
4204418919fSjohnjiang 	/*
4214418919fSjohnjiang 	 * set up parameters for rte_flow_classify_validate,
4224418919fSjohnjiang 	 * rte_flow_classify_table_entry_add and
4234418919fSjohnjiang 	 * rte_flow_classify_table_entry_delete
4244418919fSjohnjiang 	 */
4254418919fSjohnjiang 
4264418919fSjohnjiang 	attr.ingress = 1;
4274418919fSjohnjiang 	attr.priority = 1;
4284418919fSjohnjiang 	pattern[0] = eth_item;
4294418919fSjohnjiang 	pattern[1] = ipv4_udp_item_1;
4304418919fSjohnjiang 	pattern[2] = udp_item_1;
4314418919fSjohnjiang 	pattern[3] = end_item;
4324418919fSjohnjiang 	actions[0] = count_action_bad;
4334418919fSjohnjiang 	actions[1] = end_action;
4344418919fSjohnjiang 
4354418919fSjohnjiang 	ret = rte_flow_classify_validate(cls->cls, &attr, pattern,
4364418919fSjohnjiang 			actions, &error);
4374418919fSjohnjiang 	if (!ret) {
4384418919fSjohnjiang 		printf("Line %i: rte_flow_classify_validate", __LINE__);
4394418919fSjohnjiang 		printf(" should have failed!\n");
4404418919fSjohnjiang 		return -1;
4414418919fSjohnjiang 	}
4424418919fSjohnjiang 
4434418919fSjohnjiang 	rule = rte_flow_classify_table_entry_add(cls->cls, &attr, pattern,
4444418919fSjohnjiang 			actions, &key_found, &error);
4454418919fSjohnjiang 	if (rule) {
4464418919fSjohnjiang 		printf("Line %i: flow_classify_table_entry_add", __LINE__);
4474418919fSjohnjiang 		printf(" should have failed!\n");
4484418919fSjohnjiang 		return -1;
4494418919fSjohnjiang 	}
4504418919fSjohnjiang 
4514418919fSjohnjiang 	ret = rte_flow_classify_table_entry_delete(cls->cls, rule);
4524418919fSjohnjiang 	if (!ret) {
4534418919fSjohnjiang 		printf("Line %i: rte_flow_classify_table_entry_delete",
4544418919fSjohnjiang 			__LINE__);
4554418919fSjohnjiang 		printf(" should have failed!\n");
4564418919fSjohnjiang 		return -1;
4574418919fSjohnjiang 	}
4584418919fSjohnjiang 
4594418919fSjohnjiang 	return 0;
4604418919fSjohnjiang }
4614418919fSjohnjiang 
4624418919fSjohnjiang static int
init_ipv4_udp_traffic(struct rte_mempool * mp,struct rte_mbuf ** pkts_burst,uint32_t burst_size)4634418919fSjohnjiang init_ipv4_udp_traffic(struct rte_mempool *mp,
4644418919fSjohnjiang 	     struct rte_mbuf **pkts_burst, uint32_t burst_size)
4654418919fSjohnjiang {
4664418919fSjohnjiang 	struct rte_ether_hdr pkt_eth_hdr;
4674418919fSjohnjiang 	struct rte_ipv4_hdr pkt_ipv4_hdr;
4684418919fSjohnjiang 	struct rte_udp_hdr pkt_udp_hdr;
4694418919fSjohnjiang 	uint32_t src_addr = IPV4_ADDR(2, 2, 2, 3);
4704418919fSjohnjiang 	uint32_t dst_addr = IPV4_ADDR(2, 2, 2, 7);
4714418919fSjohnjiang 	uint16_t src_port = 32;
4724418919fSjohnjiang 	uint16_t dst_port = 33;
4734418919fSjohnjiang 	uint16_t pktlen;
4744418919fSjohnjiang 
4754418919fSjohnjiang 	static uint8_t src_mac[] = { 0x00, 0xFF, 0xAA, 0xFF, 0xAA, 0xFF };
4764418919fSjohnjiang 	static uint8_t dst_mac[] = { 0x00, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA };
4774418919fSjohnjiang 
4784418919fSjohnjiang 	printf("Set up IPv4 UDP traffic\n");
4794418919fSjohnjiang 	initialize_eth_header(&pkt_eth_hdr,
4804418919fSjohnjiang 		(struct rte_ether_addr *)src_mac,
4814418919fSjohnjiang 		(struct rte_ether_addr *)dst_mac, RTE_ETHER_TYPE_IPV4, 0, 0);
4824418919fSjohnjiang 	pktlen = (uint16_t)(sizeof(struct rte_ether_hdr));
4834418919fSjohnjiang 	printf("ETH  pktlen %u\n", pktlen);
4844418919fSjohnjiang 
4854418919fSjohnjiang 	pktlen = initialize_ipv4_header(&pkt_ipv4_hdr, src_addr, dst_addr,
4864418919fSjohnjiang 					pktlen);
4874418919fSjohnjiang 	printf("ETH + IPv4 pktlen %u\n", pktlen);
4884418919fSjohnjiang 
4894418919fSjohnjiang 	pktlen = initialize_udp_header(&pkt_udp_hdr, src_port, dst_port,
4904418919fSjohnjiang 					pktlen);
4914418919fSjohnjiang 	printf("ETH + IPv4 + UDP pktlen %u\n\n", pktlen);
4924418919fSjohnjiang 
4934418919fSjohnjiang 	return generate_packet_burst(mp, pkts_burst, &pkt_eth_hdr,
4944418919fSjohnjiang 				     0, &pkt_ipv4_hdr, 1,
4954418919fSjohnjiang 				     &pkt_udp_hdr, burst_size,
4964418919fSjohnjiang 				     PACKET_BURST_GEN_PKT_LEN, 1);
4974418919fSjohnjiang }
4984418919fSjohnjiang 
4994418919fSjohnjiang static int
init_ipv4_tcp_traffic(struct rte_mempool * mp,struct rte_mbuf ** pkts_burst,uint32_t burst_size)5004418919fSjohnjiang init_ipv4_tcp_traffic(struct rte_mempool *mp,
5014418919fSjohnjiang 	     struct rte_mbuf **pkts_burst, uint32_t burst_size)
5024418919fSjohnjiang {
5034418919fSjohnjiang 	struct rte_ether_hdr pkt_eth_hdr;
5044418919fSjohnjiang 	struct rte_ipv4_hdr pkt_ipv4_hdr;
5054418919fSjohnjiang 	struct rte_tcp_hdr pkt_tcp_hdr;
5064418919fSjohnjiang 	uint32_t src_addr = IPV4_ADDR(1, 2, 3, 4);
5074418919fSjohnjiang 	uint32_t dst_addr = IPV4_ADDR(5, 6, 7, 8);
5084418919fSjohnjiang 	uint16_t src_port = 16;
5094418919fSjohnjiang 	uint16_t dst_port = 17;
5104418919fSjohnjiang 	uint16_t pktlen;
5114418919fSjohnjiang 
5124418919fSjohnjiang 	static uint8_t src_mac[] = { 0x00, 0xFF, 0xAA, 0xFF, 0xAA, 0xFF };
5134418919fSjohnjiang 	static uint8_t dst_mac[] = { 0x00, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA };
5144418919fSjohnjiang 
5154418919fSjohnjiang 	printf("Set up IPv4 TCP traffic\n");
5164418919fSjohnjiang 	initialize_eth_header(&pkt_eth_hdr,
5174418919fSjohnjiang 		(struct rte_ether_addr *)src_mac,
5184418919fSjohnjiang 		(struct rte_ether_addr *)dst_mac, RTE_ETHER_TYPE_IPV4, 0, 0);
5194418919fSjohnjiang 	pktlen = (uint16_t)(sizeof(struct rte_ether_hdr));
5204418919fSjohnjiang 	printf("ETH  pktlen %u\n", pktlen);
5214418919fSjohnjiang 
5224418919fSjohnjiang 	pktlen = initialize_ipv4_header_proto(&pkt_ipv4_hdr, src_addr,
5234418919fSjohnjiang 					dst_addr, pktlen, IPPROTO_TCP);
5244418919fSjohnjiang 	printf("ETH + IPv4 pktlen %u\n", pktlen);
5254418919fSjohnjiang 
5264418919fSjohnjiang 	pktlen = initialize_tcp_header(&pkt_tcp_hdr, src_port, dst_port,
5274418919fSjohnjiang 					pktlen);
5284418919fSjohnjiang 	printf("ETH + IPv4 + TCP pktlen %u\n\n", pktlen);
5294418919fSjohnjiang 
5304418919fSjohnjiang 	return generate_packet_burst_proto(mp, pkts_burst, &pkt_eth_hdr,
5314418919fSjohnjiang 					0, &pkt_ipv4_hdr, 1, IPPROTO_TCP,
5324418919fSjohnjiang 					&pkt_tcp_hdr, burst_size,
5334418919fSjohnjiang 					PACKET_BURST_GEN_PKT_LEN, 1);
5344418919fSjohnjiang }
5354418919fSjohnjiang 
5364418919fSjohnjiang static int
init_ipv4_sctp_traffic(struct rte_mempool * mp,struct rte_mbuf ** pkts_burst,uint32_t burst_size)5374418919fSjohnjiang init_ipv4_sctp_traffic(struct rte_mempool *mp,
5384418919fSjohnjiang 	     struct rte_mbuf **pkts_burst, uint32_t burst_size)
5394418919fSjohnjiang {
5404418919fSjohnjiang 	struct rte_ether_hdr pkt_eth_hdr;
5414418919fSjohnjiang 	struct rte_ipv4_hdr pkt_ipv4_hdr;
5424418919fSjohnjiang 	struct rte_sctp_hdr pkt_sctp_hdr;
5434418919fSjohnjiang 	uint32_t src_addr = IPV4_ADDR(11, 12, 13, 14);
5444418919fSjohnjiang 	uint32_t dst_addr = IPV4_ADDR(15, 16, 17, 18);
5454418919fSjohnjiang 	uint16_t src_port = 10;
5464418919fSjohnjiang 	uint16_t dst_port = 11;
5474418919fSjohnjiang 	uint16_t pktlen;
5484418919fSjohnjiang 
5494418919fSjohnjiang 	static uint8_t src_mac[] = { 0x00, 0xFF, 0xAA, 0xFF, 0xAA, 0xFF };
5504418919fSjohnjiang 	static uint8_t dst_mac[] = { 0x00, 0xAA, 0xFF, 0xAA, 0xFF, 0xAA };
5514418919fSjohnjiang 
5524418919fSjohnjiang 	printf("Set up IPv4 SCTP traffic\n");
5534418919fSjohnjiang 	initialize_eth_header(&pkt_eth_hdr,
5544418919fSjohnjiang 		(struct rte_ether_addr *)src_mac,
5554418919fSjohnjiang 		(struct rte_ether_addr *)dst_mac, RTE_ETHER_TYPE_IPV4, 0, 0);
5564418919fSjohnjiang 	pktlen = (uint16_t)(sizeof(struct rte_ether_hdr));
5574418919fSjohnjiang 	printf("ETH  pktlen %u\n", pktlen);
5584418919fSjohnjiang 
5594418919fSjohnjiang 	pktlen = initialize_ipv4_header_proto(&pkt_ipv4_hdr, src_addr,
5604418919fSjohnjiang 					dst_addr, pktlen, IPPROTO_SCTP);
5614418919fSjohnjiang 	printf("ETH + IPv4 pktlen %u\n", pktlen);
5624418919fSjohnjiang 
5634418919fSjohnjiang 	pktlen = initialize_sctp_header(&pkt_sctp_hdr, src_port, dst_port,
5644418919fSjohnjiang 					pktlen);
5654418919fSjohnjiang 	printf("ETH + IPv4 + SCTP pktlen %u\n\n", pktlen);
5664418919fSjohnjiang 
5674418919fSjohnjiang 	return generate_packet_burst_proto(mp, pkts_burst, &pkt_eth_hdr,
5684418919fSjohnjiang 					0, &pkt_ipv4_hdr, 1, IPPROTO_SCTP,
5694418919fSjohnjiang 					&pkt_sctp_hdr, burst_size,
5704418919fSjohnjiang 					PACKET_BURST_GEN_PKT_LEN, 1);
5714418919fSjohnjiang }
5724418919fSjohnjiang 
5734418919fSjohnjiang static int
init_mbufpool(void)5744418919fSjohnjiang init_mbufpool(void)
5754418919fSjohnjiang {
5764418919fSjohnjiang 	int socketid;
5774418919fSjohnjiang 	int ret = 0;
5784418919fSjohnjiang 	unsigned int lcore_id;
5794418919fSjohnjiang 	char s[64];
5804418919fSjohnjiang 
5814418919fSjohnjiang 	for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
5824418919fSjohnjiang 		if (rte_lcore_is_enabled(lcore_id) == 0)
5834418919fSjohnjiang 			continue;
5844418919fSjohnjiang 
5854418919fSjohnjiang 		socketid = rte_lcore_to_socket_id(lcore_id);
5864418919fSjohnjiang 		if (socketid >= NB_SOCKETS) {
5874418919fSjohnjiang 			printf(
5884418919fSjohnjiang 				"Socket %d of lcore %u is out of range %d\n",
5894418919fSjohnjiang 				socketid, lcore_id, NB_SOCKETS);
5904418919fSjohnjiang 			ret = -1;
5914418919fSjohnjiang 			break;
5924418919fSjohnjiang 		}
5934418919fSjohnjiang 		if (mbufpool[socketid] == NULL) {
5944418919fSjohnjiang 			snprintf(s, sizeof(s), "mbuf_pool_%d", socketid);
5954418919fSjohnjiang 			mbufpool[socketid] =
5964418919fSjohnjiang 				rte_pktmbuf_pool_create(s, NB_MBUF,
5974418919fSjohnjiang 					MEMPOOL_CACHE_SIZE, 0, MBUF_SIZE,
5984418919fSjohnjiang 					socketid);
5994418919fSjohnjiang 			if (mbufpool[socketid]) {
6004418919fSjohnjiang 				printf("Allocated mbuf pool on socket %d\n",
6014418919fSjohnjiang 					socketid);
6024418919fSjohnjiang 			} else {
6034418919fSjohnjiang 				printf("Cannot init mbuf pool on socket %d\n",
6044418919fSjohnjiang 					socketid);
6054418919fSjohnjiang 				ret = -ENOMEM;
6064418919fSjohnjiang 				break;
6074418919fSjohnjiang 			}
6084418919fSjohnjiang 		}
6094418919fSjohnjiang 	}
6104418919fSjohnjiang 	return ret;
6114418919fSjohnjiang }
6124418919fSjohnjiang 
6134418919fSjohnjiang static int
test_query_udp(void)6144418919fSjohnjiang test_query_udp(void)
6154418919fSjohnjiang {
6164418919fSjohnjiang 	struct rte_flow_error error;
6174418919fSjohnjiang 	struct rte_flow_classify_rule *rule;
6184418919fSjohnjiang 	int ret;
6194418919fSjohnjiang 	int i;
6204418919fSjohnjiang 	int key_found;
6214418919fSjohnjiang 
6224418919fSjohnjiang 	ret = init_ipv4_udp_traffic(mbufpool[0], bufs, MAX_PKT_BURST);
6234418919fSjohnjiang 	if (ret != MAX_PKT_BURST) {
6244418919fSjohnjiang 		printf("Line %i: init_udp_ipv4_traffic has failed!\n",
6254418919fSjohnjiang 				__LINE__);
6264418919fSjohnjiang 		return -1;
6274418919fSjohnjiang 	}
6284418919fSjohnjiang 
6294418919fSjohnjiang 	for (i = 0; i < MAX_PKT_BURST; i++)
6304418919fSjohnjiang 		bufs[i]->packet_type = RTE_PTYPE_L3_IPV4;
6314418919fSjohnjiang 
6324418919fSjohnjiang 	/*
6334418919fSjohnjiang 	 * set up parameters for rte_flow_classify_validate,
6344418919fSjohnjiang 	 * rte_flow_classify_table_entry_add and
6354418919fSjohnjiang 	 * rte_flow_classify_table_entry_delete
6364418919fSjohnjiang 	 */
6374418919fSjohnjiang 
6384418919fSjohnjiang 	attr.ingress = 1;
6394418919fSjohnjiang 	attr.priority = 1;
6404418919fSjohnjiang 	pattern[0] = eth_item;
6414418919fSjohnjiang 	pattern[1] = ipv4_udp_item_1;
6424418919fSjohnjiang 	pattern[2] = udp_item_1;
6434418919fSjohnjiang 	pattern[3] = end_item;
6444418919fSjohnjiang 	actions[0] = count_action;
6454418919fSjohnjiang 	actions[1] = end_action;
6464418919fSjohnjiang 
6474418919fSjohnjiang 	ret = rte_flow_classify_validate(cls->cls, &attr, pattern,
6484418919fSjohnjiang 			actions, &error);
6494418919fSjohnjiang 	if (ret) {
6504418919fSjohnjiang 		printf("Line %i: rte_flow_classify_validate", __LINE__);
6514418919fSjohnjiang 		printf(" should not have failed!\n");
6524418919fSjohnjiang 		return -1;
6534418919fSjohnjiang 	}
6544418919fSjohnjiang 
6554418919fSjohnjiang 	rule = rte_flow_classify_table_entry_add(cls->cls, &attr, pattern,
6564418919fSjohnjiang 			actions, &key_found, &error);
6574418919fSjohnjiang 	if (!rule) {
6584418919fSjohnjiang 		printf("Line %i: flow_classify_table_entry_add", __LINE__);
6594418919fSjohnjiang 		printf(" should not have failed!\n");
6604418919fSjohnjiang 		return -1;
6614418919fSjohnjiang 	}
6624418919fSjohnjiang 
6634418919fSjohnjiang 	ret = rte_flow_classifier_query(cls->cls, bufs, MAX_PKT_BURST,
6644418919fSjohnjiang 			rule, &udp_classify_stats);
6654418919fSjohnjiang 	if (ret) {
6664418919fSjohnjiang 		printf("Line %i: flow_classifier_query", __LINE__);
6674418919fSjohnjiang 		printf(" should not have failed!\n");
6684418919fSjohnjiang 		return -1;
6694418919fSjohnjiang 	}
6704418919fSjohnjiang 
6714418919fSjohnjiang 	ret = rte_flow_classify_table_entry_delete(cls->cls, rule);
6724418919fSjohnjiang 	if (ret) {
6734418919fSjohnjiang 		printf("Line %i: rte_flow_classify_table_entry_delete",
6744418919fSjohnjiang 			__LINE__);
6754418919fSjohnjiang 		printf(" should not have failed!\n");
6764418919fSjohnjiang 		return -1;
6774418919fSjohnjiang 	}
6784418919fSjohnjiang 	return 0;
6794418919fSjohnjiang }
6804418919fSjohnjiang 
6814418919fSjohnjiang static int
test_query_tcp(void)6824418919fSjohnjiang test_query_tcp(void)
6834418919fSjohnjiang {
6844418919fSjohnjiang 	struct rte_flow_classify_rule *rule;
6854418919fSjohnjiang 	int ret;
6864418919fSjohnjiang 	int i;
6874418919fSjohnjiang 	int key_found;
6884418919fSjohnjiang 
6894418919fSjohnjiang 	ret = init_ipv4_tcp_traffic(mbufpool[0], bufs, MAX_PKT_BURST);
6904418919fSjohnjiang 	if (ret != MAX_PKT_BURST) {
6914418919fSjohnjiang 		printf("Line %i: init_ipv4_tcp_traffic has failed!\n",
6924418919fSjohnjiang 				__LINE__);
6934418919fSjohnjiang 		return -1;
6944418919fSjohnjiang 	}
6954418919fSjohnjiang 
6964418919fSjohnjiang 	for (i = 0; i < MAX_PKT_BURST; i++)
6974418919fSjohnjiang 		bufs[i]->packet_type = RTE_PTYPE_L3_IPV4;
6984418919fSjohnjiang 
6994418919fSjohnjiang 	/*
7004418919fSjohnjiang 	 * set up parameters for rte_flow_classify_validate,
7014418919fSjohnjiang 	 * rte_flow_classify_table_entry_add and
7024418919fSjohnjiang 	 * rte_flow_classify_table_entry_delete
7034418919fSjohnjiang 	 */
7044418919fSjohnjiang 
7054418919fSjohnjiang 	attr.ingress = 1;
7064418919fSjohnjiang 	attr.priority = 1;
7074418919fSjohnjiang 	pattern[0] = eth_item;
7084418919fSjohnjiang 	pattern[1] = ipv4_tcp_item_1;
7094418919fSjohnjiang 	pattern[2] = tcp_item_1;
7104418919fSjohnjiang 	pattern[3] = end_item;
7114418919fSjohnjiang 	actions[0] = count_action;
7124418919fSjohnjiang 	actions[1] = end_action;
7134418919fSjohnjiang 
7144418919fSjohnjiang 	ret = rte_flow_classify_validate(cls->cls, &attr, pattern,
7154418919fSjohnjiang 			actions, &error);
7164418919fSjohnjiang 	if (ret) {
7174418919fSjohnjiang 		printf("Line %i: flow_classifier_query", __LINE__);
7184418919fSjohnjiang 		printf(" should not have failed!\n");
7194418919fSjohnjiang 		return -1;
7204418919fSjohnjiang 	}
7214418919fSjohnjiang 
7224418919fSjohnjiang 	rule = rte_flow_classify_table_entry_add(cls->cls, &attr, pattern,
7234418919fSjohnjiang 			actions, &key_found, &error);
7244418919fSjohnjiang 	if (!rule) {
7254418919fSjohnjiang 		printf("Line %i: flow_classify_table_entry_add", __LINE__);
7264418919fSjohnjiang 		printf(" should not have failed!\n");
7274418919fSjohnjiang 		return -1;
7284418919fSjohnjiang 	}
7294418919fSjohnjiang 
7304418919fSjohnjiang 	ret = rte_flow_classifier_query(cls->cls, bufs, MAX_PKT_BURST,
7314418919fSjohnjiang 			rule, &tcp_classify_stats);
7324418919fSjohnjiang 	if (ret) {
7334418919fSjohnjiang 		printf("Line %i: flow_classifier_query", __LINE__);
7344418919fSjohnjiang 		printf(" should not have failed!\n");
7354418919fSjohnjiang 		return -1;
7364418919fSjohnjiang 	}
7374418919fSjohnjiang 
7384418919fSjohnjiang 	ret = rte_flow_classify_table_entry_delete(cls->cls, rule);
7394418919fSjohnjiang 	if (ret) {
7404418919fSjohnjiang 		printf("Line %i: rte_flow_classify_table_entry_delete",
7414418919fSjohnjiang 			__LINE__);
7424418919fSjohnjiang 		printf(" should not have failed!\n");
7434418919fSjohnjiang 		return -1;
7444418919fSjohnjiang 	}
7454418919fSjohnjiang 	return 0;
7464418919fSjohnjiang }
7474418919fSjohnjiang 
7484418919fSjohnjiang static int
test_query_sctp(void)7494418919fSjohnjiang test_query_sctp(void)
7504418919fSjohnjiang {
7514418919fSjohnjiang 	struct rte_flow_classify_rule *rule;
7524418919fSjohnjiang 	int ret;
7534418919fSjohnjiang 	int i;
7544418919fSjohnjiang 	int key_found;
7554418919fSjohnjiang 
7564418919fSjohnjiang 	ret = init_ipv4_sctp_traffic(mbufpool[0], bufs, MAX_PKT_BURST);
7574418919fSjohnjiang 	if (ret != MAX_PKT_BURST) {
7584418919fSjohnjiang 		printf("Line %i: init_ipv4_tcp_traffic has failed!\n",
7594418919fSjohnjiang 			__LINE__);
7604418919fSjohnjiang 		return -1;
7614418919fSjohnjiang 	}
7624418919fSjohnjiang 
7634418919fSjohnjiang 	for (i = 0; i < MAX_PKT_BURST; i++)
7644418919fSjohnjiang 		bufs[i]->packet_type = RTE_PTYPE_L3_IPV4;
7654418919fSjohnjiang 
7664418919fSjohnjiang 	/*
7674418919fSjohnjiang 	 * set up parameters rte_flow_classify_validate,
7684418919fSjohnjiang 	 * rte_flow_classify_table_entry_add and
7694418919fSjohnjiang 	 * rte_flow_classify_table_entry_delete
7704418919fSjohnjiang 	 */
7714418919fSjohnjiang 
7724418919fSjohnjiang 	attr.ingress = 1;
7734418919fSjohnjiang 	attr.priority = 1;
7744418919fSjohnjiang 	pattern[0] = eth_item;
7754418919fSjohnjiang 	pattern[1] = ipv4_sctp_item_1;
7764418919fSjohnjiang 	pattern[2] = sctp_item_1;
7774418919fSjohnjiang 	pattern[3] = end_item;
7784418919fSjohnjiang 	actions[0] = count_action;
7794418919fSjohnjiang 	actions[1] = end_action;
7804418919fSjohnjiang 
7814418919fSjohnjiang 	ret = rte_flow_classify_validate(cls->cls, &attr, pattern,
7824418919fSjohnjiang 			actions, &error);
7834418919fSjohnjiang 	if (ret) {
7844418919fSjohnjiang 		printf("Line %i: flow_classifier_query", __LINE__);
7854418919fSjohnjiang 		printf(" should not have failed!\n");
7864418919fSjohnjiang 		return -1;
7874418919fSjohnjiang 	}
7884418919fSjohnjiang 
7894418919fSjohnjiang 	rule = rte_flow_classify_table_entry_add(cls->cls, &attr, pattern,
7904418919fSjohnjiang 			actions, &key_found, &error);
7914418919fSjohnjiang 	if (!rule) {
7924418919fSjohnjiang 		printf("Line %i: flow_classify_table_entry_add", __LINE__);
7934418919fSjohnjiang 		printf(" should not have failed!\n");
7944418919fSjohnjiang 		return -1;
7954418919fSjohnjiang 	}
7964418919fSjohnjiang 
7974418919fSjohnjiang 	ret = rte_flow_classifier_query(cls->cls, bufs, MAX_PKT_BURST,
7984418919fSjohnjiang 			rule, &sctp_classify_stats);
7994418919fSjohnjiang 	if (ret) {
8004418919fSjohnjiang 		printf("Line %i: flow_classifier_query", __LINE__);
8014418919fSjohnjiang 		printf(" should not have failed!\n");
8024418919fSjohnjiang 		return -1;
8034418919fSjohnjiang 	}
8044418919fSjohnjiang 
8054418919fSjohnjiang 	ret = rte_flow_classify_table_entry_delete(cls->cls, rule);
8064418919fSjohnjiang 	if (ret) {
8074418919fSjohnjiang 		printf("Line %i: rte_flow_classify_table_entry_delete",
8084418919fSjohnjiang 			__LINE__);
8094418919fSjohnjiang 		printf(" should not have failed!\n");
8104418919fSjohnjiang 		return -1;
8114418919fSjohnjiang 	}
8124418919fSjohnjiang 	return 0;
8134418919fSjohnjiang }
8144418919fSjohnjiang 
8154418919fSjohnjiang static int
test_flow_classify(void)8164418919fSjohnjiang test_flow_classify(void)
8174418919fSjohnjiang {
8184418919fSjohnjiang 	struct rte_table_acl_params table_acl_params;
8194418919fSjohnjiang 	struct rte_flow_classify_table_params cls_table_params;
8204418919fSjohnjiang 	struct rte_flow_classifier_params cls_params;
8214418919fSjohnjiang 	int ret;
8224418919fSjohnjiang 	uint32_t size;
8234418919fSjohnjiang 
8244418919fSjohnjiang 	/* Memory allocation */
8254418919fSjohnjiang 	size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct flow_classifier_acl));
8264418919fSjohnjiang 	cls = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE);
8274418919fSjohnjiang 
8284418919fSjohnjiang 	cls_params.name = "flow_classifier";
8294418919fSjohnjiang 	cls_params.socket_id = 0;
8304418919fSjohnjiang 	cls->cls = rte_flow_classifier_create(&cls_params);
8314418919fSjohnjiang 
8324418919fSjohnjiang 	/* initialise ACL table params */
8334418919fSjohnjiang 	table_acl_params.n_rule_fields = RTE_DIM(ipv4_defs);
8344418919fSjohnjiang 	table_acl_params.name = "table_acl_ipv4_5tuple";
8354418919fSjohnjiang 	table_acl_params.n_rules = FLOW_CLASSIFY_MAX_RULE_NUM;
8364418919fSjohnjiang 	memcpy(table_acl_params.field_format, ipv4_defs, sizeof(ipv4_defs));
8374418919fSjohnjiang 
8384418919fSjohnjiang 	/* initialise table create params */
8394418919fSjohnjiang 	cls_table_params.ops = &rte_table_acl_ops;
8404418919fSjohnjiang 	cls_table_params.arg_create = &table_acl_params;
8414418919fSjohnjiang 	cls_table_params.type = RTE_FLOW_CLASSIFY_TABLE_ACL_IP4_5TUPLE;
8424418919fSjohnjiang 
8434418919fSjohnjiang 	ret = rte_flow_classify_table_create(cls->cls, &cls_table_params);
8444418919fSjohnjiang 	if (ret) {
8454418919fSjohnjiang 		printf("Line %i: f_create has failed!\n", __LINE__);
8464418919fSjohnjiang 		rte_flow_classifier_free(cls->cls);
8474418919fSjohnjiang 		rte_free(cls);
8484418919fSjohnjiang 		return TEST_FAILED;
8494418919fSjohnjiang 	}
8504418919fSjohnjiang 	printf("Created table_acl for for IPv4 five tuple packets\n");
8514418919fSjohnjiang 
8524418919fSjohnjiang 	ret = init_mbufpool();
8534418919fSjohnjiang 	if (ret) {
8544418919fSjohnjiang 		printf("Line %i: init_mbufpool has failed!\n", __LINE__);
8554418919fSjohnjiang 		return TEST_FAILED;
8564418919fSjohnjiang 	}
8574418919fSjohnjiang 
8584418919fSjohnjiang 	if (test_invalid_parameters() < 0)
8594418919fSjohnjiang 		return TEST_FAILED;
8604418919fSjohnjiang 	if (test_valid_parameters() < 0)
8614418919fSjohnjiang 		return TEST_FAILED;
8624418919fSjohnjiang 	if (test_invalid_patterns() < 0)
8634418919fSjohnjiang 		return TEST_FAILED;
8644418919fSjohnjiang 	if (test_invalid_actions() < 0)
8654418919fSjohnjiang 		return TEST_FAILED;
8664418919fSjohnjiang 	if (test_query_udp() < 0)
8674418919fSjohnjiang 		return TEST_FAILED;
8684418919fSjohnjiang 	if (test_query_tcp() < 0)
8694418919fSjohnjiang 		return TEST_FAILED;
8704418919fSjohnjiang 	if (test_query_sctp() < 0)
8714418919fSjohnjiang 		return TEST_FAILED;
8724418919fSjohnjiang 
8734418919fSjohnjiang 	return TEST_SUCCESS;
8744418919fSjohnjiang }
8754418919fSjohnjiang 
8764418919fSjohnjiang REGISTER_TEST_COMMAND(flow_classify_autotest, test_flow_classify);
877