xref: /f-stack/dpdk/app/test/test_acl.c (revision 2d9fd380)
14418919fSjohnjiang /* SPDX-License-Identifier: BSD-3-Clause
24418919fSjohnjiang  * Copyright(c) 2010-2014 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 
174418919fSjohnjiang #include "test_acl.h"
184418919fSjohnjiang 
194418919fSjohnjiang #define	BIT_SIZEOF(x) (sizeof(x) * CHAR_BIT)
204418919fSjohnjiang 
214418919fSjohnjiang #define LEN RTE_ACL_MAX_CATEGORIES
224418919fSjohnjiang 
234418919fSjohnjiang RTE_ACL_RULE_DEF(acl_ipv4vlan_rule, RTE_ACL_IPV4VLAN_NUM_FIELDS);
244418919fSjohnjiang 
254418919fSjohnjiang struct rte_acl_param acl_param = {
264418919fSjohnjiang 	.name = "acl_ctx",
274418919fSjohnjiang 	.socket_id = SOCKET_ID_ANY,
284418919fSjohnjiang 	.rule_size = RTE_ACL_IPV4VLAN_RULE_SZ,
294418919fSjohnjiang 	.max_rule_num = 0x30000,
304418919fSjohnjiang };
314418919fSjohnjiang 
324418919fSjohnjiang struct rte_acl_ipv4vlan_rule acl_rule = {
334418919fSjohnjiang 		.data = { .priority = 1, .category_mask = 0xff },
344418919fSjohnjiang 		.src_port_low = 0,
354418919fSjohnjiang 		.src_port_high = UINT16_MAX,
364418919fSjohnjiang 		.dst_port_low = 0,
374418919fSjohnjiang 		.dst_port_high = UINT16_MAX,
384418919fSjohnjiang };
394418919fSjohnjiang 
404418919fSjohnjiang const uint32_t ipv4_7tuple_layout[RTE_ACL_IPV4VLAN_NUM] = {
414418919fSjohnjiang 	offsetof(struct ipv4_7tuple, proto),
424418919fSjohnjiang 	offsetof(struct ipv4_7tuple, vlan),
434418919fSjohnjiang 	offsetof(struct ipv4_7tuple, ip_src),
444418919fSjohnjiang 	offsetof(struct ipv4_7tuple, ip_dst),
454418919fSjohnjiang 	offsetof(struct ipv4_7tuple, port_src),
464418919fSjohnjiang };
474418919fSjohnjiang 
484418919fSjohnjiang 
494418919fSjohnjiang /* byteswap to cpu or network order */
504418919fSjohnjiang static void
bswap_test_data(struct ipv4_7tuple * data,int len,int to_be)514418919fSjohnjiang bswap_test_data(struct ipv4_7tuple *data, int len, int to_be)
524418919fSjohnjiang {
534418919fSjohnjiang 	int i;
544418919fSjohnjiang 
554418919fSjohnjiang 	for (i = 0; i < len; i++) {
564418919fSjohnjiang 
574418919fSjohnjiang 		if (to_be) {
584418919fSjohnjiang 			/* swap all bytes so that they are in network order */
594418919fSjohnjiang 			data[i].ip_dst = rte_cpu_to_be_32(data[i].ip_dst);
604418919fSjohnjiang 			data[i].ip_src = rte_cpu_to_be_32(data[i].ip_src);
614418919fSjohnjiang 			data[i].port_dst = rte_cpu_to_be_16(data[i].port_dst);
624418919fSjohnjiang 			data[i].port_src = rte_cpu_to_be_16(data[i].port_src);
634418919fSjohnjiang 			data[i].vlan = rte_cpu_to_be_16(data[i].vlan);
644418919fSjohnjiang 			data[i].domain = rte_cpu_to_be_16(data[i].domain);
654418919fSjohnjiang 		} else {
664418919fSjohnjiang 			data[i].ip_dst = rte_be_to_cpu_32(data[i].ip_dst);
674418919fSjohnjiang 			data[i].ip_src = rte_be_to_cpu_32(data[i].ip_src);
684418919fSjohnjiang 			data[i].port_dst = rte_be_to_cpu_16(data[i].port_dst);
694418919fSjohnjiang 			data[i].port_src = rte_be_to_cpu_16(data[i].port_src);
704418919fSjohnjiang 			data[i].vlan = rte_be_to_cpu_16(data[i].vlan);
714418919fSjohnjiang 			data[i].domain = rte_be_to_cpu_16(data[i].domain);
724418919fSjohnjiang 		}
734418919fSjohnjiang 	}
744418919fSjohnjiang }
754418919fSjohnjiang 
764418919fSjohnjiang static int
acl_ipv4vlan_check_rule(const struct rte_acl_ipv4vlan_rule * rule)774418919fSjohnjiang acl_ipv4vlan_check_rule(const struct rte_acl_ipv4vlan_rule *rule)
784418919fSjohnjiang {
794418919fSjohnjiang 	if (rule->src_port_low > rule->src_port_high ||
804418919fSjohnjiang 			rule->dst_port_low > rule->dst_port_high ||
814418919fSjohnjiang 			rule->src_mask_len > BIT_SIZEOF(rule->src_addr) ||
824418919fSjohnjiang 			rule->dst_mask_len > BIT_SIZEOF(rule->dst_addr))
834418919fSjohnjiang 		return -EINVAL;
844418919fSjohnjiang 	return 0;
854418919fSjohnjiang }
864418919fSjohnjiang 
874418919fSjohnjiang static void
acl_ipv4vlan_convert_rule(const struct rte_acl_ipv4vlan_rule * ri,struct acl_ipv4vlan_rule * ro)884418919fSjohnjiang acl_ipv4vlan_convert_rule(const struct rte_acl_ipv4vlan_rule *ri,
894418919fSjohnjiang 	struct acl_ipv4vlan_rule *ro)
904418919fSjohnjiang {
914418919fSjohnjiang 	ro->data = ri->data;
924418919fSjohnjiang 
934418919fSjohnjiang 	ro->field[RTE_ACL_IPV4VLAN_PROTO_FIELD].value.u8 = ri->proto;
944418919fSjohnjiang 	ro->field[RTE_ACL_IPV4VLAN_VLAN1_FIELD].value.u16 = ri->vlan;
954418919fSjohnjiang 	ro->field[RTE_ACL_IPV4VLAN_VLAN2_FIELD].value.u16 = ri->domain;
964418919fSjohnjiang 	ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD].value.u32 = ri->src_addr;
974418919fSjohnjiang 	ro->field[RTE_ACL_IPV4VLAN_DST_FIELD].value.u32 = ri->dst_addr;
984418919fSjohnjiang 	ro->field[RTE_ACL_IPV4VLAN_SRCP_FIELD].value.u16 = ri->src_port_low;
994418919fSjohnjiang 	ro->field[RTE_ACL_IPV4VLAN_DSTP_FIELD].value.u16 = ri->dst_port_low;
1004418919fSjohnjiang 
1014418919fSjohnjiang 	ro->field[RTE_ACL_IPV4VLAN_PROTO_FIELD].mask_range.u8 = ri->proto_mask;
1024418919fSjohnjiang 	ro->field[RTE_ACL_IPV4VLAN_VLAN1_FIELD].mask_range.u16 = ri->vlan_mask;
1034418919fSjohnjiang 	ro->field[RTE_ACL_IPV4VLAN_VLAN2_FIELD].mask_range.u16 =
1044418919fSjohnjiang 		ri->domain_mask;
1054418919fSjohnjiang 	ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD].mask_range.u32 =
1064418919fSjohnjiang 		ri->src_mask_len;
1074418919fSjohnjiang 	ro->field[RTE_ACL_IPV4VLAN_DST_FIELD].mask_range.u32 = ri->dst_mask_len;
1084418919fSjohnjiang 	ro->field[RTE_ACL_IPV4VLAN_SRCP_FIELD].mask_range.u16 =
1094418919fSjohnjiang 		ri->src_port_high;
1104418919fSjohnjiang 	ro->field[RTE_ACL_IPV4VLAN_DSTP_FIELD].mask_range.u16 =
1114418919fSjohnjiang 		ri->dst_port_high;
1124418919fSjohnjiang }
1134418919fSjohnjiang 
1144418919fSjohnjiang /*
1154418919fSjohnjiang  * Add ipv4vlan rules to an existing ACL context.
1164418919fSjohnjiang  * This function is not multi-thread safe.
1174418919fSjohnjiang  *
1184418919fSjohnjiang  * @param ctx
1194418919fSjohnjiang  *   ACL context to add patterns to.
1204418919fSjohnjiang  * @param rules
1214418919fSjohnjiang  *   Array of rules to add to the ACL context.
1224418919fSjohnjiang  *   Note that all fields in rte_acl_ipv4vlan_rule structures are expected
1234418919fSjohnjiang  *   to be in host byte order.
1244418919fSjohnjiang  * @param num
1254418919fSjohnjiang  *   Number of elements in the input array of rules.
1264418919fSjohnjiang  * @return
1274418919fSjohnjiang  *   - -ENOMEM if there is no space in the ACL context for these rules.
1284418919fSjohnjiang  *   - -EINVAL if the parameters are invalid.
1294418919fSjohnjiang  *   - Zero if operation completed successfully.
1304418919fSjohnjiang  */
1314418919fSjohnjiang static int
rte_acl_ipv4vlan_add_rules(struct rte_acl_ctx * ctx,const struct rte_acl_ipv4vlan_rule * rules,uint32_t num)1324418919fSjohnjiang rte_acl_ipv4vlan_add_rules(struct rte_acl_ctx *ctx,
1334418919fSjohnjiang 	const struct rte_acl_ipv4vlan_rule *rules,
1344418919fSjohnjiang 	uint32_t num)
1354418919fSjohnjiang {
1364418919fSjohnjiang 	int32_t rc;
1374418919fSjohnjiang 	uint32_t i;
1384418919fSjohnjiang 	struct acl_ipv4vlan_rule rv;
1394418919fSjohnjiang 
1404418919fSjohnjiang 	if (ctx == NULL || rules == NULL)
1414418919fSjohnjiang 		return -EINVAL;
1424418919fSjohnjiang 
1434418919fSjohnjiang 	/* check input rules. */
1444418919fSjohnjiang 	for (i = 0; i != num; i++) {
1454418919fSjohnjiang 		rc = acl_ipv4vlan_check_rule(rules + i);
1464418919fSjohnjiang 		if (rc != 0) {
1474418919fSjohnjiang 			RTE_LOG(ERR, ACL, "%s: rule #%u is invalid\n",
1484418919fSjohnjiang 				__func__, i + 1);
1494418919fSjohnjiang 			return rc;
1504418919fSjohnjiang 		}
1514418919fSjohnjiang 	}
1524418919fSjohnjiang 
1534418919fSjohnjiang 	/* perform conversion to the internal format and add to the context. */
1544418919fSjohnjiang 	for (i = 0, rc = 0; i != num && rc == 0; i++) {
1554418919fSjohnjiang 		acl_ipv4vlan_convert_rule(rules + i, &rv);
1564418919fSjohnjiang 		rc = rte_acl_add_rules(ctx, (struct rte_acl_rule *)&rv, 1);
1574418919fSjohnjiang 	}
1584418919fSjohnjiang 
1594418919fSjohnjiang 	return rc;
1604418919fSjohnjiang }
1614418919fSjohnjiang 
1624418919fSjohnjiang static void
acl_ipv4vlan_config(struct rte_acl_config * cfg,const uint32_t layout[RTE_ACL_IPV4VLAN_NUM],uint32_t num_categories)1634418919fSjohnjiang acl_ipv4vlan_config(struct rte_acl_config *cfg,
1644418919fSjohnjiang 	const uint32_t layout[RTE_ACL_IPV4VLAN_NUM],
1654418919fSjohnjiang 	uint32_t num_categories)
1664418919fSjohnjiang {
1674418919fSjohnjiang 	static const struct rte_acl_field_def
1684418919fSjohnjiang 		ipv4_defs[RTE_ACL_IPV4VLAN_NUM_FIELDS] = {
1694418919fSjohnjiang 		{
1704418919fSjohnjiang 			.type = RTE_ACL_FIELD_TYPE_BITMASK,
1714418919fSjohnjiang 			.size = sizeof(uint8_t),
1724418919fSjohnjiang 			.field_index = RTE_ACL_IPV4VLAN_PROTO_FIELD,
1734418919fSjohnjiang 			.input_index = RTE_ACL_IPV4VLAN_PROTO,
1744418919fSjohnjiang 		},
1754418919fSjohnjiang 		{
1764418919fSjohnjiang 			.type = RTE_ACL_FIELD_TYPE_BITMASK,
1774418919fSjohnjiang 			.size = sizeof(uint16_t),
1784418919fSjohnjiang 			.field_index = RTE_ACL_IPV4VLAN_VLAN1_FIELD,
1794418919fSjohnjiang 			.input_index = RTE_ACL_IPV4VLAN_VLAN,
1804418919fSjohnjiang 		},
1814418919fSjohnjiang 		{
1824418919fSjohnjiang 			.type = RTE_ACL_FIELD_TYPE_BITMASK,
1834418919fSjohnjiang 			.size = sizeof(uint16_t),
1844418919fSjohnjiang 			.field_index = RTE_ACL_IPV4VLAN_VLAN2_FIELD,
1854418919fSjohnjiang 			.input_index = RTE_ACL_IPV4VLAN_VLAN,
1864418919fSjohnjiang 		},
1874418919fSjohnjiang 		{
1884418919fSjohnjiang 			.type = RTE_ACL_FIELD_TYPE_MASK,
1894418919fSjohnjiang 			.size = sizeof(uint32_t),
1904418919fSjohnjiang 			.field_index = RTE_ACL_IPV4VLAN_SRC_FIELD,
1914418919fSjohnjiang 			.input_index = RTE_ACL_IPV4VLAN_SRC,
1924418919fSjohnjiang 		},
1934418919fSjohnjiang 		{
1944418919fSjohnjiang 			.type = RTE_ACL_FIELD_TYPE_MASK,
1954418919fSjohnjiang 			.size = sizeof(uint32_t),
1964418919fSjohnjiang 			.field_index = RTE_ACL_IPV4VLAN_DST_FIELD,
1974418919fSjohnjiang 			.input_index = RTE_ACL_IPV4VLAN_DST,
1984418919fSjohnjiang 		},
1994418919fSjohnjiang 		{
2004418919fSjohnjiang 			.type = RTE_ACL_FIELD_TYPE_RANGE,
2014418919fSjohnjiang 			.size = sizeof(uint16_t),
2024418919fSjohnjiang 			.field_index = RTE_ACL_IPV4VLAN_SRCP_FIELD,
2034418919fSjohnjiang 			.input_index = RTE_ACL_IPV4VLAN_PORTS,
2044418919fSjohnjiang 		},
2054418919fSjohnjiang 		{
2064418919fSjohnjiang 			.type = RTE_ACL_FIELD_TYPE_RANGE,
2074418919fSjohnjiang 			.size = sizeof(uint16_t),
2084418919fSjohnjiang 			.field_index = RTE_ACL_IPV4VLAN_DSTP_FIELD,
2094418919fSjohnjiang 			.input_index = RTE_ACL_IPV4VLAN_PORTS,
2104418919fSjohnjiang 		},
2114418919fSjohnjiang 	};
2124418919fSjohnjiang 
2134418919fSjohnjiang 	memcpy(&cfg->defs, ipv4_defs, sizeof(ipv4_defs));
2144418919fSjohnjiang 	cfg->num_fields = RTE_DIM(ipv4_defs);
2154418919fSjohnjiang 
2164418919fSjohnjiang 	cfg->defs[RTE_ACL_IPV4VLAN_PROTO_FIELD].offset =
2174418919fSjohnjiang 		layout[RTE_ACL_IPV4VLAN_PROTO];
2184418919fSjohnjiang 	cfg->defs[RTE_ACL_IPV4VLAN_VLAN1_FIELD].offset =
2194418919fSjohnjiang 		layout[RTE_ACL_IPV4VLAN_VLAN];
2204418919fSjohnjiang 	cfg->defs[RTE_ACL_IPV4VLAN_VLAN2_FIELD].offset =
2214418919fSjohnjiang 		layout[RTE_ACL_IPV4VLAN_VLAN] +
2224418919fSjohnjiang 		cfg->defs[RTE_ACL_IPV4VLAN_VLAN1_FIELD].size;
2234418919fSjohnjiang 	cfg->defs[RTE_ACL_IPV4VLAN_SRC_FIELD].offset =
2244418919fSjohnjiang 		layout[RTE_ACL_IPV4VLAN_SRC];
2254418919fSjohnjiang 	cfg->defs[RTE_ACL_IPV4VLAN_DST_FIELD].offset =
2264418919fSjohnjiang 		layout[RTE_ACL_IPV4VLAN_DST];
2274418919fSjohnjiang 	cfg->defs[RTE_ACL_IPV4VLAN_SRCP_FIELD].offset =
2284418919fSjohnjiang 		layout[RTE_ACL_IPV4VLAN_PORTS];
2294418919fSjohnjiang 	cfg->defs[RTE_ACL_IPV4VLAN_DSTP_FIELD].offset =
2304418919fSjohnjiang 		layout[RTE_ACL_IPV4VLAN_PORTS] +
2314418919fSjohnjiang 		cfg->defs[RTE_ACL_IPV4VLAN_SRCP_FIELD].size;
2324418919fSjohnjiang 
2334418919fSjohnjiang 	cfg->num_categories = num_categories;
2344418919fSjohnjiang }
2354418919fSjohnjiang 
2364418919fSjohnjiang /*
2374418919fSjohnjiang  * Analyze set of ipv4vlan rules and build required internal
2384418919fSjohnjiang  * run-time structures.
2394418919fSjohnjiang  * This function is not multi-thread safe.
2404418919fSjohnjiang  *
2414418919fSjohnjiang  * @param ctx
2424418919fSjohnjiang  *   ACL context to build.
2434418919fSjohnjiang  * @param layout
2444418919fSjohnjiang  *   Layout of input data to search through.
2454418919fSjohnjiang  * @param num_categories
2464418919fSjohnjiang  *   Maximum number of categories to use in that build.
2474418919fSjohnjiang  * @return
2484418919fSjohnjiang  *   - -ENOMEM if couldn't allocate enough memory.
2494418919fSjohnjiang  *   - -EINVAL if the parameters are invalid.
2504418919fSjohnjiang  *   - Negative error code if operation failed.
2514418919fSjohnjiang  *   - Zero if operation completed successfully.
2524418919fSjohnjiang  */
2534418919fSjohnjiang static int
rte_acl_ipv4vlan_build(struct rte_acl_ctx * ctx,const uint32_t layout[RTE_ACL_IPV4VLAN_NUM],uint32_t num_categories)2544418919fSjohnjiang rte_acl_ipv4vlan_build(struct rte_acl_ctx *ctx,
2554418919fSjohnjiang 	const uint32_t layout[RTE_ACL_IPV4VLAN_NUM],
2564418919fSjohnjiang 	uint32_t num_categories)
2574418919fSjohnjiang {
2584418919fSjohnjiang 	struct rte_acl_config cfg;
2594418919fSjohnjiang 
2604418919fSjohnjiang 	if (ctx == NULL || layout == NULL)
2614418919fSjohnjiang 		return -EINVAL;
2624418919fSjohnjiang 
2634418919fSjohnjiang 	memset(&cfg, 0, sizeof(cfg));
2644418919fSjohnjiang 	acl_ipv4vlan_config(&cfg, layout, num_categories);
2654418919fSjohnjiang 	return rte_acl_build(ctx, &cfg);
2664418919fSjohnjiang }
2674418919fSjohnjiang 
2684418919fSjohnjiang /*
269*2d9fd380Sjfb8856606  * Test ACL lookup (selected alg).
2704418919fSjohnjiang  */
2714418919fSjohnjiang static int
test_classify_alg(struct rte_acl_ctx * acx,struct ipv4_7tuple test_data[],const uint8_t * data[],size_t dim,enum rte_acl_classify_alg alg)272*2d9fd380Sjfb8856606 test_classify_alg(struct rte_acl_ctx *acx, struct ipv4_7tuple test_data[],
273*2d9fd380Sjfb8856606 	const uint8_t *data[], size_t dim, enum rte_acl_classify_alg alg)
2744418919fSjohnjiang {
275*2d9fd380Sjfb8856606 	int32_t ret;
276*2d9fd380Sjfb8856606 	uint32_t i, result, count;
277*2d9fd380Sjfb8856606 	uint32_t results[dim * RTE_ACL_MAX_CATEGORIES];
2784418919fSjohnjiang 
279*2d9fd380Sjfb8856606 	/* set given classify alg, skip test if alg is not supported */
280*2d9fd380Sjfb8856606 	ret = rte_acl_set_ctx_classify(acx, alg);
281*2d9fd380Sjfb8856606 	if (ret != 0)
282*2d9fd380Sjfb8856606 		return (ret == -ENOTSUP) ? 0 : ret;
2834418919fSjohnjiang 
2844418919fSjohnjiang 	/**
2854418919fSjohnjiang 	 * these will run quite a few times, it's necessary to test code paths
2864418919fSjohnjiang 	 * from num=0 to num>8
2874418919fSjohnjiang 	 */
288*2d9fd380Sjfb8856606 	for (count = 0; count <= dim; count++) {
2894418919fSjohnjiang 		ret = rte_acl_classify(acx, data, results,
2904418919fSjohnjiang 				count, RTE_ACL_MAX_CATEGORIES);
2914418919fSjohnjiang 		if (ret != 0) {
292*2d9fd380Sjfb8856606 			printf("Line %i: classify(alg=%d) failed!\n",
293*2d9fd380Sjfb8856606 				__LINE__, alg);
294*2d9fd380Sjfb8856606 			return ret;
2954418919fSjohnjiang 		}
2964418919fSjohnjiang 
2974418919fSjohnjiang 		/* check if we allow everything we should allow */
298*2d9fd380Sjfb8856606 		for (i = 0; i < count; i++) {
2994418919fSjohnjiang 			result =
3004418919fSjohnjiang 				results[i * RTE_ACL_MAX_CATEGORIES + ACL_ALLOW];
301*2d9fd380Sjfb8856606 			if (result != test_data[i].allow) {
3024418919fSjohnjiang 				printf("Line %i: Error in allow results at %i "
3034418919fSjohnjiang 					"(expected %"PRIu32" got %"PRIu32")!\n",
304*2d9fd380Sjfb8856606 					__LINE__, i, test_data[i].allow,
3054418919fSjohnjiang 					result);
306*2d9fd380Sjfb8856606 				return -EINVAL;
3074418919fSjohnjiang 			}
3084418919fSjohnjiang 		}
3094418919fSjohnjiang 
3104418919fSjohnjiang 		/* check if we deny everything we should deny */
311*2d9fd380Sjfb8856606 		for (i = 0; i < count; i++) {
3124418919fSjohnjiang 			result = results[i * RTE_ACL_MAX_CATEGORIES + ACL_DENY];
313*2d9fd380Sjfb8856606 			if (result != test_data[i].deny) {
3144418919fSjohnjiang 				printf("Line %i: Error in deny results at %i "
3154418919fSjohnjiang 					"(expected %"PRIu32" got %"PRIu32")!\n",
316*2d9fd380Sjfb8856606 					__LINE__, i, test_data[i].deny,
3174418919fSjohnjiang 					result);
318*2d9fd380Sjfb8856606 				return -EINVAL;
3194418919fSjohnjiang 			}
3204418919fSjohnjiang 		}
3214418919fSjohnjiang 	}
3224418919fSjohnjiang 
323*2d9fd380Sjfb8856606 	/* restore default classify alg */
324*2d9fd380Sjfb8856606 	return rte_acl_set_ctx_classify(acx, RTE_ACL_CLASSIFY_DEFAULT);
3254418919fSjohnjiang }
3264418919fSjohnjiang 
327*2d9fd380Sjfb8856606 /*
328*2d9fd380Sjfb8856606  * Test ACL lookup (all possible methods).
329*2d9fd380Sjfb8856606  */
330*2d9fd380Sjfb8856606 static int
test_classify_run(struct rte_acl_ctx * acx,struct ipv4_7tuple test_data[],size_t dim)331*2d9fd380Sjfb8856606 test_classify_run(struct rte_acl_ctx *acx, struct ipv4_7tuple test_data[],
332*2d9fd380Sjfb8856606 	size_t dim)
333*2d9fd380Sjfb8856606 {
334*2d9fd380Sjfb8856606 	int32_t ret;
335*2d9fd380Sjfb8856606 	uint32_t i;
336*2d9fd380Sjfb8856606 	const uint8_t *data[dim];
3374418919fSjohnjiang 
338*2d9fd380Sjfb8856606 	static const enum rte_acl_classify_alg alg[] = {
339*2d9fd380Sjfb8856606 		RTE_ACL_CLASSIFY_SCALAR,
340*2d9fd380Sjfb8856606 		RTE_ACL_CLASSIFY_SSE,
341*2d9fd380Sjfb8856606 		RTE_ACL_CLASSIFY_AVX2,
342*2d9fd380Sjfb8856606 		RTE_ACL_CLASSIFY_NEON,
343*2d9fd380Sjfb8856606 		RTE_ACL_CLASSIFY_ALTIVEC,
344*2d9fd380Sjfb8856606 		RTE_ACL_CLASSIFY_AVX512X16,
345*2d9fd380Sjfb8856606 		RTE_ACL_CLASSIFY_AVX512X32,
346*2d9fd380Sjfb8856606 	};
347*2d9fd380Sjfb8856606 
348*2d9fd380Sjfb8856606 	/* swap all bytes in the data to network order */
349*2d9fd380Sjfb8856606 	bswap_test_data(test_data, dim, 1);
350*2d9fd380Sjfb8856606 
351*2d9fd380Sjfb8856606 	/* store pointers to test data */
352*2d9fd380Sjfb8856606 	for (i = 0; i < dim; i++)
353*2d9fd380Sjfb8856606 		data[i] = (uint8_t *)&test_data[i];
3544418919fSjohnjiang 
3554418919fSjohnjiang 	ret = 0;
356*2d9fd380Sjfb8856606 	for (i = 0; i != RTE_DIM(alg); i++) {
357*2d9fd380Sjfb8856606 		ret = test_classify_alg(acx, test_data, data, dim, alg[i]);
358*2d9fd380Sjfb8856606 		if (ret < 0) {
359*2d9fd380Sjfb8856606 			printf("Line %i: %s() for alg=%d failed, errno=%d\n",
360*2d9fd380Sjfb8856606 				__LINE__, __func__, alg[i], -ret);
361*2d9fd380Sjfb8856606 			break;
362*2d9fd380Sjfb8856606 		}
363*2d9fd380Sjfb8856606 	}
3644418919fSjohnjiang 
3654418919fSjohnjiang 	/* swap data back to cpu order so that next time tests don't fail */
366*2d9fd380Sjfb8856606 	bswap_test_data(test_data, dim, 0);
3674418919fSjohnjiang 	return ret;
3684418919fSjohnjiang }
3694418919fSjohnjiang 
3704418919fSjohnjiang static int
test_classify_buid(struct rte_acl_ctx * acx,const struct rte_acl_ipv4vlan_rule * rules,uint32_t num)3714418919fSjohnjiang test_classify_buid(struct rte_acl_ctx *acx,
3724418919fSjohnjiang 	const struct rte_acl_ipv4vlan_rule *rules, uint32_t num)
3734418919fSjohnjiang {
3744418919fSjohnjiang 	int ret;
3754418919fSjohnjiang 
3764418919fSjohnjiang 	/* add rules to the context */
3774418919fSjohnjiang 	ret = rte_acl_ipv4vlan_add_rules(acx, rules, num);
3784418919fSjohnjiang 	if (ret != 0) {
3794418919fSjohnjiang 		printf("Line %i: Adding rules to ACL context failed!\n",
3804418919fSjohnjiang 			__LINE__);
3814418919fSjohnjiang 		return ret;
3824418919fSjohnjiang 	}
3834418919fSjohnjiang 
3844418919fSjohnjiang 	/* try building the context */
3854418919fSjohnjiang 	ret = rte_acl_ipv4vlan_build(acx, ipv4_7tuple_layout,
3864418919fSjohnjiang 		RTE_ACL_MAX_CATEGORIES);
3874418919fSjohnjiang 	if (ret != 0) {
3884418919fSjohnjiang 		printf("Line %i: Building ACL context failed!\n", __LINE__);
3894418919fSjohnjiang 		return ret;
3904418919fSjohnjiang 	}
3914418919fSjohnjiang 
3924418919fSjohnjiang 	return 0;
3934418919fSjohnjiang }
3944418919fSjohnjiang 
3954418919fSjohnjiang #define	TEST_CLASSIFY_ITER	4
3964418919fSjohnjiang 
3974418919fSjohnjiang /*
3984418919fSjohnjiang  * Test scalar and SSE ACL lookup.
3994418919fSjohnjiang  */
4004418919fSjohnjiang static int
test_classify(void)4014418919fSjohnjiang test_classify(void)
4024418919fSjohnjiang {
4034418919fSjohnjiang 	struct rte_acl_ctx *acx;
4044418919fSjohnjiang 	int i, ret;
4054418919fSjohnjiang 
4064418919fSjohnjiang 	acx = rte_acl_create(&acl_param);
4074418919fSjohnjiang 	if (acx == NULL) {
4084418919fSjohnjiang 		printf("Line %i: Error creating ACL context!\n", __LINE__);
4094418919fSjohnjiang 		return -1;
4104418919fSjohnjiang 	}
4114418919fSjohnjiang 
4124418919fSjohnjiang 	ret = 0;
4134418919fSjohnjiang 	for (i = 0; i != TEST_CLASSIFY_ITER; i++) {
4144418919fSjohnjiang 
4154418919fSjohnjiang 		if ((i & 1) == 0)
4164418919fSjohnjiang 			rte_acl_reset(acx);
4174418919fSjohnjiang 		else
4184418919fSjohnjiang 			rte_acl_reset_rules(acx);
4194418919fSjohnjiang 
4204418919fSjohnjiang 		ret = test_classify_buid(acx, acl_test_rules,
4214418919fSjohnjiang 			RTE_DIM(acl_test_rules));
4224418919fSjohnjiang 		if (ret != 0) {
4234418919fSjohnjiang 			printf("Line %i, iter: %d: "
4244418919fSjohnjiang 				"Adding rules to ACL context failed!\n",
4254418919fSjohnjiang 				__LINE__, i);
4264418919fSjohnjiang 			break;
4274418919fSjohnjiang 		}
4284418919fSjohnjiang 
429*2d9fd380Sjfb8856606 		ret = test_classify_run(acx, acl_test_data,
430*2d9fd380Sjfb8856606 			RTE_DIM(acl_test_data));
4314418919fSjohnjiang 		if (ret != 0) {
4324418919fSjohnjiang 			printf("Line %i, iter: %d: %s failed!\n",
4334418919fSjohnjiang 				__LINE__, i, __func__);
4344418919fSjohnjiang 			break;
4354418919fSjohnjiang 		}
4364418919fSjohnjiang 
4374418919fSjohnjiang 		/* reset rules and make sure that classify still works ok. */
4384418919fSjohnjiang 		rte_acl_reset_rules(acx);
439*2d9fd380Sjfb8856606 		ret = test_classify_run(acx, acl_test_data,
440*2d9fd380Sjfb8856606 			RTE_DIM(acl_test_data));
4414418919fSjohnjiang 		if (ret != 0) {
4424418919fSjohnjiang 			printf("Line %i, iter: %d: %s failed!\n",
4434418919fSjohnjiang 				__LINE__, i, __func__);
4444418919fSjohnjiang 			break;
4454418919fSjohnjiang 		}
4464418919fSjohnjiang 	}
4474418919fSjohnjiang 
4484418919fSjohnjiang 	rte_acl_free(acx);
4494418919fSjohnjiang 	return ret;
4504418919fSjohnjiang }
4514418919fSjohnjiang 
4524418919fSjohnjiang static int
test_build_ports_range(void)4534418919fSjohnjiang test_build_ports_range(void)
4544418919fSjohnjiang {
4554418919fSjohnjiang 	static const struct rte_acl_ipv4vlan_rule test_rules[] = {
4564418919fSjohnjiang 		{
4574418919fSjohnjiang 			/* match all packets. */
4584418919fSjohnjiang 			.data = {
4594418919fSjohnjiang 				.userdata = 1,
4604418919fSjohnjiang 				.category_mask = ACL_ALLOW_MASK,
4614418919fSjohnjiang 				.priority = 101,
4624418919fSjohnjiang 			},
4634418919fSjohnjiang 			.src_port_low = 0,
4644418919fSjohnjiang 			.src_port_high = UINT16_MAX,
4654418919fSjohnjiang 			.dst_port_low = 0,
4664418919fSjohnjiang 			.dst_port_high = UINT16_MAX,
4674418919fSjohnjiang 		},
4684418919fSjohnjiang 		{
4694418919fSjohnjiang 			/* match all packets with dst ports [54-65280]. */
4704418919fSjohnjiang 			.data = {
4714418919fSjohnjiang 				.userdata = 2,
4724418919fSjohnjiang 				.category_mask = ACL_ALLOW_MASK,
4734418919fSjohnjiang 				.priority = 102,
4744418919fSjohnjiang 			},
4754418919fSjohnjiang 			.src_port_low = 0,
4764418919fSjohnjiang 			.src_port_high = UINT16_MAX,
4774418919fSjohnjiang 			.dst_port_low = 54,
4784418919fSjohnjiang 			.dst_port_high = 65280,
4794418919fSjohnjiang 		},
4804418919fSjohnjiang 		{
4814418919fSjohnjiang 			/* match all packets with dst ports [0-52]. */
4824418919fSjohnjiang 			.data = {
4834418919fSjohnjiang 				.userdata = 3,
4844418919fSjohnjiang 				.category_mask = ACL_ALLOW_MASK,
4854418919fSjohnjiang 				.priority = 103,
4864418919fSjohnjiang 			},
4874418919fSjohnjiang 			.src_port_low = 0,
4884418919fSjohnjiang 			.src_port_high = UINT16_MAX,
4894418919fSjohnjiang 			.dst_port_low = 0,
4904418919fSjohnjiang 			.dst_port_high = 52,
4914418919fSjohnjiang 		},
4924418919fSjohnjiang 		{
4934418919fSjohnjiang 			/* match all packets with dst ports [53]. */
4944418919fSjohnjiang 			.data = {
4954418919fSjohnjiang 				.userdata = 4,
4964418919fSjohnjiang 				.category_mask = ACL_ALLOW_MASK,
4974418919fSjohnjiang 				.priority = 99,
4984418919fSjohnjiang 			},
4994418919fSjohnjiang 			.src_port_low = 0,
5004418919fSjohnjiang 			.src_port_high = UINT16_MAX,
5014418919fSjohnjiang 			.dst_port_low = 53,
5024418919fSjohnjiang 			.dst_port_high = 53,
5034418919fSjohnjiang 		},
5044418919fSjohnjiang 		{
5054418919fSjohnjiang 			/* match all packets with dst ports [65279-65535]. */
5064418919fSjohnjiang 			.data = {
5074418919fSjohnjiang 				.userdata = 5,
5084418919fSjohnjiang 				.category_mask = ACL_ALLOW_MASK,
5094418919fSjohnjiang 				.priority = 98,
5104418919fSjohnjiang 			},
5114418919fSjohnjiang 			.src_port_low = 0,
5124418919fSjohnjiang 			.src_port_high = UINT16_MAX,
5134418919fSjohnjiang 			.dst_port_low = 65279,
5144418919fSjohnjiang 			.dst_port_high = UINT16_MAX,
5154418919fSjohnjiang 		},
5164418919fSjohnjiang 	};
5174418919fSjohnjiang 
5184418919fSjohnjiang 	static struct ipv4_7tuple test_data[] = {
5194418919fSjohnjiang 		{
5204418919fSjohnjiang 			.proto = 6,
5214418919fSjohnjiang 			.ip_src = RTE_IPV4(10, 1, 1, 1),
5224418919fSjohnjiang 			.ip_dst = RTE_IPV4(192, 168, 0, 33),
5234418919fSjohnjiang 			.port_dst = 53,
5244418919fSjohnjiang 			.allow = 1,
5254418919fSjohnjiang 		},
5264418919fSjohnjiang 		{
5274418919fSjohnjiang 			.proto = 6,
5284418919fSjohnjiang 			.ip_src = RTE_IPV4(127, 84, 33, 1),
5294418919fSjohnjiang 			.ip_dst = RTE_IPV4(1, 2, 3, 4),
5304418919fSjohnjiang 			.port_dst = 65281,
5314418919fSjohnjiang 			.allow = 1,
5324418919fSjohnjiang 		},
5334418919fSjohnjiang 	};
5344418919fSjohnjiang 
5354418919fSjohnjiang 	struct rte_acl_ctx *acx;
5364418919fSjohnjiang 	int32_t ret, i, j;
5374418919fSjohnjiang 	uint32_t results[RTE_DIM(test_data)];
5384418919fSjohnjiang 	const uint8_t *data[RTE_DIM(test_data)];
5394418919fSjohnjiang 
5404418919fSjohnjiang 	acx = rte_acl_create(&acl_param);
5414418919fSjohnjiang 	if (acx == NULL) {
5424418919fSjohnjiang 		printf("Line %i: Error creating ACL context!\n", __LINE__);
5434418919fSjohnjiang 		return -1;
5444418919fSjohnjiang 	}
5454418919fSjohnjiang 
5464418919fSjohnjiang 	/* swap all bytes in the data to network order */
5474418919fSjohnjiang 	bswap_test_data(test_data, RTE_DIM(test_data), 1);
5484418919fSjohnjiang 
5494418919fSjohnjiang 	/* store pointers to test data */
5504418919fSjohnjiang 	for (i = 0; i != RTE_DIM(test_data); i++)
5514418919fSjohnjiang 		data[i] = (uint8_t *)&test_data[i];
5524418919fSjohnjiang 
5534418919fSjohnjiang 	for (i = 0; i != RTE_DIM(test_rules); i++) {
5544418919fSjohnjiang 		rte_acl_reset(acx);
5554418919fSjohnjiang 		ret = test_classify_buid(acx, test_rules, i + 1);
5564418919fSjohnjiang 		if (ret != 0) {
5574418919fSjohnjiang 			printf("Line %i, iter: %d: "
5584418919fSjohnjiang 				"Adding rules to ACL context failed!\n",
5594418919fSjohnjiang 				__LINE__, i);
5604418919fSjohnjiang 			break;
5614418919fSjohnjiang 		}
5624418919fSjohnjiang 		ret = rte_acl_classify(acx, data, results,
5634418919fSjohnjiang 			RTE_DIM(data), 1);
5644418919fSjohnjiang 		if (ret != 0) {
5654418919fSjohnjiang 			printf("Line %i, iter: %d: classify failed!\n",
5664418919fSjohnjiang 				__LINE__, i);
5674418919fSjohnjiang 			break;
5684418919fSjohnjiang 		}
5694418919fSjohnjiang 
5704418919fSjohnjiang 		/* check results */
5714418919fSjohnjiang 		for (j = 0; j != RTE_DIM(results); j++) {
5724418919fSjohnjiang 			if (results[j] != test_data[j].allow) {
5734418919fSjohnjiang 				printf("Line %i: Error in allow results at %i "
5744418919fSjohnjiang 					"(expected %"PRIu32" got %"PRIu32")!\n",
5754418919fSjohnjiang 					__LINE__, j, test_data[j].allow,
5764418919fSjohnjiang 					results[j]);
5774418919fSjohnjiang 				ret = -EINVAL;
5784418919fSjohnjiang 			}
5794418919fSjohnjiang 		}
5804418919fSjohnjiang 	}
5814418919fSjohnjiang 
5824418919fSjohnjiang 	bswap_test_data(test_data, RTE_DIM(test_data), 0);
5834418919fSjohnjiang 
5844418919fSjohnjiang 	rte_acl_free(acx);
5854418919fSjohnjiang 	return ret;
5864418919fSjohnjiang }
5874418919fSjohnjiang 
5884418919fSjohnjiang static void
convert_rule(const struct rte_acl_ipv4vlan_rule * ri,struct acl_ipv4vlan_rule * ro)5894418919fSjohnjiang convert_rule(const struct rte_acl_ipv4vlan_rule *ri,
5904418919fSjohnjiang 	struct acl_ipv4vlan_rule *ro)
5914418919fSjohnjiang {
5924418919fSjohnjiang 	ro->data = ri->data;
5934418919fSjohnjiang 
5944418919fSjohnjiang 	ro->field[RTE_ACL_IPV4VLAN_PROTO_FIELD].value.u8 = ri->proto;
5954418919fSjohnjiang 	ro->field[RTE_ACL_IPV4VLAN_VLAN1_FIELD].value.u16 = ri->vlan;
5964418919fSjohnjiang 	ro->field[RTE_ACL_IPV4VLAN_VLAN2_FIELD].value.u16 = ri->domain;
5974418919fSjohnjiang 	ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD].value.u32 = ri->src_addr;
5984418919fSjohnjiang 	ro->field[RTE_ACL_IPV4VLAN_DST_FIELD].value.u32 = ri->dst_addr;
5994418919fSjohnjiang 	ro->field[RTE_ACL_IPV4VLAN_SRCP_FIELD].value.u16 = ri->src_port_low;
6004418919fSjohnjiang 	ro->field[RTE_ACL_IPV4VLAN_DSTP_FIELD].value.u16 = ri->dst_port_low;
6014418919fSjohnjiang 
6024418919fSjohnjiang 	ro->field[RTE_ACL_IPV4VLAN_PROTO_FIELD].mask_range.u8 = ri->proto_mask;
6034418919fSjohnjiang 	ro->field[RTE_ACL_IPV4VLAN_VLAN1_FIELD].mask_range.u16 = ri->vlan_mask;
6044418919fSjohnjiang 	ro->field[RTE_ACL_IPV4VLAN_VLAN2_FIELD].mask_range.u16 =
6054418919fSjohnjiang 		ri->domain_mask;
6064418919fSjohnjiang 	ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD].mask_range.u32 =
6074418919fSjohnjiang 		ri->src_mask_len;
6084418919fSjohnjiang 	ro->field[RTE_ACL_IPV4VLAN_DST_FIELD].mask_range.u32 = ri->dst_mask_len;
6094418919fSjohnjiang 	ro->field[RTE_ACL_IPV4VLAN_SRCP_FIELD].mask_range.u16 =
6104418919fSjohnjiang 		ri->src_port_high;
6114418919fSjohnjiang 	ro->field[RTE_ACL_IPV4VLAN_DSTP_FIELD].mask_range.u16 =
6124418919fSjohnjiang 		ri->dst_port_high;
6134418919fSjohnjiang }
6144418919fSjohnjiang 
6154418919fSjohnjiang /*
6164418919fSjohnjiang  * Convert IPV4 source and destination from RTE_ACL_FIELD_TYPE_MASK to
6174418919fSjohnjiang  * RTE_ACL_FIELD_TYPE_BITMASK.
6184418919fSjohnjiang  */
6194418919fSjohnjiang static void
convert_rule_1(const struct rte_acl_ipv4vlan_rule * ri,struct acl_ipv4vlan_rule * ro)6204418919fSjohnjiang convert_rule_1(const struct rte_acl_ipv4vlan_rule *ri,
6214418919fSjohnjiang 	struct acl_ipv4vlan_rule *ro)
6224418919fSjohnjiang {
6234418919fSjohnjiang 	uint32_t v;
6244418919fSjohnjiang 
6254418919fSjohnjiang 	convert_rule(ri, ro);
6264418919fSjohnjiang 	v = ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD].mask_range.u32;
6274418919fSjohnjiang 	ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD].mask_range.u32 =
6284418919fSjohnjiang 		RTE_ACL_MASKLEN_TO_BITMASK(v, sizeof(v));
6294418919fSjohnjiang 	v = ro->field[RTE_ACL_IPV4VLAN_DST_FIELD].mask_range.u32;
6304418919fSjohnjiang 	ro->field[RTE_ACL_IPV4VLAN_DST_FIELD].mask_range.u32 =
6314418919fSjohnjiang 		RTE_ACL_MASKLEN_TO_BITMASK(v, sizeof(v));
6324418919fSjohnjiang }
6334418919fSjohnjiang 
6344418919fSjohnjiang /*
6354418919fSjohnjiang  * Convert IPV4 source and destination from RTE_ACL_FIELD_TYPE_MASK to
6364418919fSjohnjiang  * RTE_ACL_FIELD_TYPE_RANGE.
6374418919fSjohnjiang  */
6384418919fSjohnjiang static void
convert_rule_2(const struct rte_acl_ipv4vlan_rule * ri,struct acl_ipv4vlan_rule * ro)6394418919fSjohnjiang convert_rule_2(const struct rte_acl_ipv4vlan_rule *ri,
6404418919fSjohnjiang 	struct acl_ipv4vlan_rule *ro)
6414418919fSjohnjiang {
6424418919fSjohnjiang 	uint32_t hi, lo, mask;
6434418919fSjohnjiang 
6444418919fSjohnjiang 	convert_rule(ri, ro);
6454418919fSjohnjiang 
6464418919fSjohnjiang 	mask = ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD].mask_range.u32;
6474418919fSjohnjiang 	mask = RTE_ACL_MASKLEN_TO_BITMASK(mask, sizeof(mask));
6484418919fSjohnjiang 	lo = ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD].value.u32 & mask;
6494418919fSjohnjiang 	hi = lo + ~mask;
6504418919fSjohnjiang 	ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD].value.u32 = lo;
6514418919fSjohnjiang 	ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD].mask_range.u32 = hi;
6524418919fSjohnjiang 
6534418919fSjohnjiang 	mask = ro->field[RTE_ACL_IPV4VLAN_DST_FIELD].mask_range.u32;
6544418919fSjohnjiang 	mask = RTE_ACL_MASKLEN_TO_BITMASK(mask, sizeof(mask));
6554418919fSjohnjiang 	lo = ro->field[RTE_ACL_IPV4VLAN_DST_FIELD].value.u32 & mask;
6564418919fSjohnjiang 	hi = lo + ~mask;
6574418919fSjohnjiang 	ro->field[RTE_ACL_IPV4VLAN_DST_FIELD].value.u32 = lo;
6584418919fSjohnjiang 	ro->field[RTE_ACL_IPV4VLAN_DST_FIELD].mask_range.u32 = hi;
6594418919fSjohnjiang }
6604418919fSjohnjiang 
6614418919fSjohnjiang /*
6624418919fSjohnjiang  * Convert rte_acl_ipv4vlan_rule: swap VLAN and PORTS rule fields.
6634418919fSjohnjiang  */
6644418919fSjohnjiang static void
convert_rule_3(const struct rte_acl_ipv4vlan_rule * ri,struct acl_ipv4vlan_rule * ro)6654418919fSjohnjiang convert_rule_3(const struct rte_acl_ipv4vlan_rule *ri,
6664418919fSjohnjiang 	struct acl_ipv4vlan_rule *ro)
6674418919fSjohnjiang {
6684418919fSjohnjiang 	struct rte_acl_field t1, t2;
6694418919fSjohnjiang 
6704418919fSjohnjiang 	convert_rule(ri, ro);
6714418919fSjohnjiang 
6724418919fSjohnjiang 	t1 = ro->field[RTE_ACL_IPV4VLAN_VLAN1_FIELD];
6734418919fSjohnjiang 	t2 = ro->field[RTE_ACL_IPV4VLAN_VLAN2_FIELD];
6744418919fSjohnjiang 
6754418919fSjohnjiang 	ro->field[RTE_ACL_IPV4VLAN_VLAN1_FIELD] =
6764418919fSjohnjiang 		ro->field[RTE_ACL_IPV4VLAN_SRCP_FIELD];
6774418919fSjohnjiang 	ro->field[RTE_ACL_IPV4VLAN_VLAN2_FIELD] =
6784418919fSjohnjiang 		ro->field[RTE_ACL_IPV4VLAN_DSTP_FIELD];
6794418919fSjohnjiang 
6804418919fSjohnjiang 	ro->field[RTE_ACL_IPV4VLAN_SRCP_FIELD] = t1;
6814418919fSjohnjiang 	ro->field[RTE_ACL_IPV4VLAN_DSTP_FIELD] = t2;
6824418919fSjohnjiang }
6834418919fSjohnjiang 
6844418919fSjohnjiang /*
6854418919fSjohnjiang  * Convert rte_acl_ipv4vlan_rule: swap SRC and DST IPv4 address rules.
6864418919fSjohnjiang  */
6874418919fSjohnjiang static void
convert_rule_4(const struct rte_acl_ipv4vlan_rule * ri,struct acl_ipv4vlan_rule * ro)6884418919fSjohnjiang convert_rule_4(const struct rte_acl_ipv4vlan_rule *ri,
6894418919fSjohnjiang 	struct acl_ipv4vlan_rule *ro)
6904418919fSjohnjiang {
6914418919fSjohnjiang 	struct rte_acl_field t;
6924418919fSjohnjiang 
6934418919fSjohnjiang 	convert_rule(ri, ro);
6944418919fSjohnjiang 
6954418919fSjohnjiang 	t = ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD];
6964418919fSjohnjiang 	ro->field[RTE_ACL_IPV4VLAN_SRC_FIELD] =
6974418919fSjohnjiang 		ro->field[RTE_ACL_IPV4VLAN_DST_FIELD];
6984418919fSjohnjiang 
6994418919fSjohnjiang 	ro->field[RTE_ACL_IPV4VLAN_DST_FIELD] = t;
7004418919fSjohnjiang }
7014418919fSjohnjiang 
7024418919fSjohnjiang static void
ipv4vlan_config(struct rte_acl_config * cfg,const uint32_t layout[RTE_ACL_IPV4VLAN_NUM],uint32_t num_categories)7034418919fSjohnjiang ipv4vlan_config(struct rte_acl_config *cfg,
7044418919fSjohnjiang 	const uint32_t layout[RTE_ACL_IPV4VLAN_NUM],
7054418919fSjohnjiang 	uint32_t num_categories)
7064418919fSjohnjiang {
7074418919fSjohnjiang 	static const struct rte_acl_field_def
7084418919fSjohnjiang 		ipv4_defs[RTE_ACL_IPV4VLAN_NUM_FIELDS] = {
7094418919fSjohnjiang 		{
7104418919fSjohnjiang 			.type = RTE_ACL_FIELD_TYPE_BITMASK,
7114418919fSjohnjiang 			.size = sizeof(uint8_t),
7124418919fSjohnjiang 			.field_index = RTE_ACL_IPV4VLAN_PROTO_FIELD,
7134418919fSjohnjiang 			.input_index = RTE_ACL_IPV4VLAN_PROTO,
7144418919fSjohnjiang 		},
7154418919fSjohnjiang 		{
7164418919fSjohnjiang 			.type = RTE_ACL_FIELD_TYPE_BITMASK,
7174418919fSjohnjiang 			.size = sizeof(uint16_t),
7184418919fSjohnjiang 			.field_index = RTE_ACL_IPV4VLAN_VLAN1_FIELD,
7194418919fSjohnjiang 			.input_index = RTE_ACL_IPV4VLAN_VLAN,
7204418919fSjohnjiang 		},
7214418919fSjohnjiang 		{
7224418919fSjohnjiang 			.type = RTE_ACL_FIELD_TYPE_BITMASK,
7234418919fSjohnjiang 			.size = sizeof(uint16_t),
7244418919fSjohnjiang 			.field_index = RTE_ACL_IPV4VLAN_VLAN2_FIELD,
7254418919fSjohnjiang 			.input_index = RTE_ACL_IPV4VLAN_VLAN,
7264418919fSjohnjiang 		},
7274418919fSjohnjiang 		{
7284418919fSjohnjiang 			.type = RTE_ACL_FIELD_TYPE_MASK,
7294418919fSjohnjiang 			.size = sizeof(uint32_t),
7304418919fSjohnjiang 			.field_index = RTE_ACL_IPV4VLAN_SRC_FIELD,
7314418919fSjohnjiang 			.input_index = RTE_ACL_IPV4VLAN_SRC,
7324418919fSjohnjiang 		},
7334418919fSjohnjiang 		{
7344418919fSjohnjiang 			.type = RTE_ACL_FIELD_TYPE_MASK,
7354418919fSjohnjiang 			.size = sizeof(uint32_t),
7364418919fSjohnjiang 			.field_index = RTE_ACL_IPV4VLAN_DST_FIELD,
7374418919fSjohnjiang 			.input_index = RTE_ACL_IPV4VLAN_DST,
7384418919fSjohnjiang 		},
7394418919fSjohnjiang 		{
7404418919fSjohnjiang 			.type = RTE_ACL_FIELD_TYPE_RANGE,
7414418919fSjohnjiang 			.size = sizeof(uint16_t),
7424418919fSjohnjiang 			.field_index = RTE_ACL_IPV4VLAN_SRCP_FIELD,
7434418919fSjohnjiang 			.input_index = RTE_ACL_IPV4VLAN_PORTS,
7444418919fSjohnjiang 		},
7454418919fSjohnjiang 		{
7464418919fSjohnjiang 			.type = RTE_ACL_FIELD_TYPE_RANGE,
7474418919fSjohnjiang 			.size = sizeof(uint16_t),
7484418919fSjohnjiang 			.field_index = RTE_ACL_IPV4VLAN_DSTP_FIELD,
7494418919fSjohnjiang 			.input_index = RTE_ACL_IPV4VLAN_PORTS,
7504418919fSjohnjiang 		},
7514418919fSjohnjiang 	};
7524418919fSjohnjiang 
7534418919fSjohnjiang 	memcpy(&cfg->defs, ipv4_defs, sizeof(ipv4_defs));
7544418919fSjohnjiang 	cfg->num_fields = RTE_DIM(ipv4_defs);
7554418919fSjohnjiang 
7564418919fSjohnjiang 	cfg->defs[RTE_ACL_IPV4VLAN_PROTO_FIELD].offset =
7574418919fSjohnjiang 		layout[RTE_ACL_IPV4VLAN_PROTO];
7584418919fSjohnjiang 	cfg->defs[RTE_ACL_IPV4VLAN_VLAN1_FIELD].offset =
7594418919fSjohnjiang 		layout[RTE_ACL_IPV4VLAN_VLAN];
7604418919fSjohnjiang 	cfg->defs[RTE_ACL_IPV4VLAN_VLAN2_FIELD].offset =
7614418919fSjohnjiang 		layout[RTE_ACL_IPV4VLAN_VLAN] +
7624418919fSjohnjiang 		cfg->defs[RTE_ACL_IPV4VLAN_VLAN1_FIELD].size;
7634418919fSjohnjiang 	cfg->defs[RTE_ACL_IPV4VLAN_SRC_FIELD].offset =
7644418919fSjohnjiang 		layout[RTE_ACL_IPV4VLAN_SRC];
7654418919fSjohnjiang 	cfg->defs[RTE_ACL_IPV4VLAN_DST_FIELD].offset =
7664418919fSjohnjiang 		layout[RTE_ACL_IPV4VLAN_DST];
7674418919fSjohnjiang 	cfg->defs[RTE_ACL_IPV4VLAN_SRCP_FIELD].offset =
7684418919fSjohnjiang 		layout[RTE_ACL_IPV4VLAN_PORTS];
7694418919fSjohnjiang 	cfg->defs[RTE_ACL_IPV4VLAN_DSTP_FIELD].offset =
7704418919fSjohnjiang 		layout[RTE_ACL_IPV4VLAN_PORTS] +
7714418919fSjohnjiang 		cfg->defs[RTE_ACL_IPV4VLAN_SRCP_FIELD].size;
7724418919fSjohnjiang 
7734418919fSjohnjiang 	cfg->num_categories = num_categories;
7744418919fSjohnjiang }
7754418919fSjohnjiang 
7764418919fSjohnjiang static int
convert_rules(struct rte_acl_ctx * acx,void (* convert)(const struct rte_acl_ipv4vlan_rule *,struct acl_ipv4vlan_rule *),const struct rte_acl_ipv4vlan_rule * rules,uint32_t num)7774418919fSjohnjiang convert_rules(struct rte_acl_ctx *acx,
7784418919fSjohnjiang 	void (*convert)(const struct rte_acl_ipv4vlan_rule *,
7794418919fSjohnjiang 	struct acl_ipv4vlan_rule *),
7804418919fSjohnjiang 	const struct rte_acl_ipv4vlan_rule *rules, uint32_t num)
7814418919fSjohnjiang {
7824418919fSjohnjiang 	int32_t rc;
7834418919fSjohnjiang 	uint32_t i;
7844418919fSjohnjiang 	struct acl_ipv4vlan_rule r;
7854418919fSjohnjiang 
7864418919fSjohnjiang 	for (i = 0; i != num; i++) {
7874418919fSjohnjiang 		convert(rules + i, &r);
7884418919fSjohnjiang 		rc = rte_acl_add_rules(acx, (struct rte_acl_rule *)&r, 1);
7894418919fSjohnjiang 		if (rc != 0) {
7904418919fSjohnjiang 			printf("Line %i: Adding rule %u to ACL context "
7914418919fSjohnjiang 				"failed with error code: %d\n",
7924418919fSjohnjiang 			__LINE__, i, rc);
7934418919fSjohnjiang 			return rc;
7944418919fSjohnjiang 		}
7954418919fSjohnjiang 	}
7964418919fSjohnjiang 
7974418919fSjohnjiang 	return 0;
7984418919fSjohnjiang }
7994418919fSjohnjiang 
8004418919fSjohnjiang static void
convert_config(struct rte_acl_config * cfg)8014418919fSjohnjiang convert_config(struct rte_acl_config *cfg)
8024418919fSjohnjiang {
8034418919fSjohnjiang 	ipv4vlan_config(cfg, ipv4_7tuple_layout, RTE_ACL_MAX_CATEGORIES);
8044418919fSjohnjiang }
8054418919fSjohnjiang 
8064418919fSjohnjiang /*
8074418919fSjohnjiang  * Convert rte_acl_ipv4vlan_rule to use RTE_ACL_FIELD_TYPE_BITMASK.
8084418919fSjohnjiang  */
8094418919fSjohnjiang static void
convert_config_1(struct rte_acl_config * cfg)8104418919fSjohnjiang convert_config_1(struct rte_acl_config *cfg)
8114418919fSjohnjiang {
8124418919fSjohnjiang 	ipv4vlan_config(cfg, ipv4_7tuple_layout, RTE_ACL_MAX_CATEGORIES);
8134418919fSjohnjiang 	cfg->defs[RTE_ACL_IPV4VLAN_SRC_FIELD].type = RTE_ACL_FIELD_TYPE_BITMASK;
8144418919fSjohnjiang 	cfg->defs[RTE_ACL_IPV4VLAN_DST_FIELD].type = RTE_ACL_FIELD_TYPE_BITMASK;
8154418919fSjohnjiang }
8164418919fSjohnjiang 
8174418919fSjohnjiang /*
8184418919fSjohnjiang  * Convert rte_acl_ipv4vlan_rule to use RTE_ACL_FIELD_TYPE_RANGE.
8194418919fSjohnjiang  */
8204418919fSjohnjiang static void
convert_config_2(struct rte_acl_config * cfg)8214418919fSjohnjiang convert_config_2(struct rte_acl_config *cfg)
8224418919fSjohnjiang {
8234418919fSjohnjiang 	ipv4vlan_config(cfg, ipv4_7tuple_layout, RTE_ACL_MAX_CATEGORIES);
8244418919fSjohnjiang 	cfg->defs[RTE_ACL_IPV4VLAN_SRC_FIELD].type = RTE_ACL_FIELD_TYPE_RANGE;
8254418919fSjohnjiang 	cfg->defs[RTE_ACL_IPV4VLAN_DST_FIELD].type = RTE_ACL_FIELD_TYPE_RANGE;
8264418919fSjohnjiang }
8274418919fSjohnjiang 
8284418919fSjohnjiang /*
8294418919fSjohnjiang  * Convert rte_acl_ipv4vlan_rule: swap VLAN and PORTS rule definitions.
8304418919fSjohnjiang  */
8314418919fSjohnjiang static void
convert_config_3(struct rte_acl_config * cfg)8324418919fSjohnjiang convert_config_3(struct rte_acl_config *cfg)
8334418919fSjohnjiang {
8344418919fSjohnjiang 	struct rte_acl_field_def t1, t2;
8354418919fSjohnjiang 
8364418919fSjohnjiang 	ipv4vlan_config(cfg, ipv4_7tuple_layout, RTE_ACL_MAX_CATEGORIES);
8374418919fSjohnjiang 
8384418919fSjohnjiang 	t1 = cfg->defs[RTE_ACL_IPV4VLAN_VLAN1_FIELD];
8394418919fSjohnjiang 	t2 = cfg->defs[RTE_ACL_IPV4VLAN_VLAN2_FIELD];
8404418919fSjohnjiang 
8414418919fSjohnjiang 	/* swap VLAN1 and SRCP rule definition. */
8424418919fSjohnjiang 	cfg->defs[RTE_ACL_IPV4VLAN_VLAN1_FIELD] =
8434418919fSjohnjiang 		cfg->defs[RTE_ACL_IPV4VLAN_SRCP_FIELD];
8444418919fSjohnjiang 	cfg->defs[RTE_ACL_IPV4VLAN_VLAN1_FIELD].field_index = t1.field_index;
8454418919fSjohnjiang 	cfg->defs[RTE_ACL_IPV4VLAN_VLAN1_FIELD].input_index = t1.input_index;
8464418919fSjohnjiang 
8474418919fSjohnjiang 	/* swap VLAN2 and DSTP rule definition. */
8484418919fSjohnjiang 	cfg->defs[RTE_ACL_IPV4VLAN_VLAN2_FIELD] =
8494418919fSjohnjiang 		cfg->defs[RTE_ACL_IPV4VLAN_DSTP_FIELD];
8504418919fSjohnjiang 	cfg->defs[RTE_ACL_IPV4VLAN_VLAN2_FIELD].field_index = t2.field_index;
8514418919fSjohnjiang 	cfg->defs[RTE_ACL_IPV4VLAN_VLAN2_FIELD].input_index = t2.input_index;
8524418919fSjohnjiang 
8534418919fSjohnjiang 	cfg->defs[RTE_ACL_IPV4VLAN_SRCP_FIELD].type = t1.type;
8544418919fSjohnjiang 	cfg->defs[RTE_ACL_IPV4VLAN_SRCP_FIELD].size = t1.size;
8554418919fSjohnjiang 	cfg->defs[RTE_ACL_IPV4VLAN_SRCP_FIELD].offset = t1.offset;
8564418919fSjohnjiang 
8574418919fSjohnjiang 	cfg->defs[RTE_ACL_IPV4VLAN_DSTP_FIELD].type = t2.type;
8584418919fSjohnjiang 	cfg->defs[RTE_ACL_IPV4VLAN_DSTP_FIELD].size = t2.size;
8594418919fSjohnjiang 	cfg->defs[RTE_ACL_IPV4VLAN_DSTP_FIELD].offset = t2.offset;
8604418919fSjohnjiang }
8614418919fSjohnjiang 
8624418919fSjohnjiang /*
8634418919fSjohnjiang  * Convert rte_acl_ipv4vlan_rule: swap SRC and DST ip address rule definitions.
8644418919fSjohnjiang  */
8654418919fSjohnjiang static void
convert_config_4(struct rte_acl_config * cfg)8664418919fSjohnjiang convert_config_4(struct rte_acl_config *cfg)
8674418919fSjohnjiang {
8684418919fSjohnjiang 	struct rte_acl_field_def t;
8694418919fSjohnjiang 
8704418919fSjohnjiang 	ipv4vlan_config(cfg, ipv4_7tuple_layout, RTE_ACL_MAX_CATEGORIES);
8714418919fSjohnjiang 
8724418919fSjohnjiang 	t = cfg->defs[RTE_ACL_IPV4VLAN_SRC_FIELD];
8734418919fSjohnjiang 
8744418919fSjohnjiang 	cfg->defs[RTE_ACL_IPV4VLAN_SRC_FIELD] =
8754418919fSjohnjiang 		cfg->defs[RTE_ACL_IPV4VLAN_DST_FIELD];
8764418919fSjohnjiang 	cfg->defs[RTE_ACL_IPV4VLAN_SRC_FIELD].field_index = t.field_index;
8774418919fSjohnjiang 	cfg->defs[RTE_ACL_IPV4VLAN_SRC_FIELD].input_index = t.input_index;
8784418919fSjohnjiang 
8794418919fSjohnjiang 	cfg->defs[RTE_ACL_IPV4VLAN_DST_FIELD].type = t.type;
8804418919fSjohnjiang 	cfg->defs[RTE_ACL_IPV4VLAN_DST_FIELD].size = t.size;
8814418919fSjohnjiang 	cfg->defs[RTE_ACL_IPV4VLAN_DST_FIELD].offset = t.offset;
8824418919fSjohnjiang }
8834418919fSjohnjiang 
8844418919fSjohnjiang 
8854418919fSjohnjiang static int
build_convert_rules(struct rte_acl_ctx * acx,void (* config)(struct rte_acl_config *),size_t max_size)8864418919fSjohnjiang build_convert_rules(struct rte_acl_ctx *acx,
8874418919fSjohnjiang 	void (*config)(struct rte_acl_config *),
8884418919fSjohnjiang 	size_t max_size)
8894418919fSjohnjiang {
8904418919fSjohnjiang 	struct rte_acl_config cfg;
8914418919fSjohnjiang 
8924418919fSjohnjiang 	memset(&cfg, 0, sizeof(cfg));
8934418919fSjohnjiang 	config(&cfg);
8944418919fSjohnjiang 	cfg.max_size = max_size;
8954418919fSjohnjiang 	return rte_acl_build(acx, &cfg);
8964418919fSjohnjiang }
8974418919fSjohnjiang 
8984418919fSjohnjiang static int
test_convert_rules(const char * desc,void (* config)(struct rte_acl_config *),void (* convert)(const struct rte_acl_ipv4vlan_rule *,struct acl_ipv4vlan_rule *))8994418919fSjohnjiang test_convert_rules(const char *desc,
9004418919fSjohnjiang 	void (*config)(struct rte_acl_config *),
9014418919fSjohnjiang 	void (*convert)(const struct rte_acl_ipv4vlan_rule *,
9024418919fSjohnjiang 	struct acl_ipv4vlan_rule *))
9034418919fSjohnjiang {
9044418919fSjohnjiang 	struct rte_acl_ctx *acx;
9054418919fSjohnjiang 	int32_t rc;
9064418919fSjohnjiang 	uint32_t i;
9074418919fSjohnjiang 	static const size_t mem_sizes[] = {0, -1};
9084418919fSjohnjiang 
9094418919fSjohnjiang 	printf("running %s(%s)\n", __func__, desc);
9104418919fSjohnjiang 
9114418919fSjohnjiang 	acx = rte_acl_create(&acl_param);
9124418919fSjohnjiang 	if (acx == NULL) {
9134418919fSjohnjiang 		printf("Line %i: Error creating ACL context!\n", __LINE__);
9144418919fSjohnjiang 		return -1;
9154418919fSjohnjiang 	}
9164418919fSjohnjiang 
9174418919fSjohnjiang 	rc = convert_rules(acx, convert, acl_test_rules,
9184418919fSjohnjiang 		RTE_DIM(acl_test_rules));
9194418919fSjohnjiang 	if (rc != 0)
9204418919fSjohnjiang 		printf("Line %i: Error converting ACL rules!\n", __LINE__);
9214418919fSjohnjiang 
9224418919fSjohnjiang 	for (i = 0; rc == 0 && i != RTE_DIM(mem_sizes); i++) {
9234418919fSjohnjiang 
9244418919fSjohnjiang 		rc = build_convert_rules(acx, config, mem_sizes[i]);
9254418919fSjohnjiang 		if (rc != 0) {
9264418919fSjohnjiang 			printf("Line %i: Error @ build_convert_rules(%zu)!\n",
9274418919fSjohnjiang 				__LINE__, mem_sizes[i]);
9284418919fSjohnjiang 			break;
9294418919fSjohnjiang 		}
9304418919fSjohnjiang 
931*2d9fd380Sjfb8856606 		rc = test_classify_run(acx, acl_test_data,
932*2d9fd380Sjfb8856606 			RTE_DIM(acl_test_data));
9334418919fSjohnjiang 		if (rc != 0)
9344418919fSjohnjiang 			printf("%s failed at line %i, max_size=%zu\n",
9354418919fSjohnjiang 				__func__, __LINE__, mem_sizes[i]);
9364418919fSjohnjiang 	}
9374418919fSjohnjiang 
9384418919fSjohnjiang 	rte_acl_free(acx);
9394418919fSjohnjiang 	return rc;
9404418919fSjohnjiang }
9414418919fSjohnjiang 
9424418919fSjohnjiang static int
test_convert(void)9434418919fSjohnjiang test_convert(void)
9444418919fSjohnjiang {
9454418919fSjohnjiang 	static const struct {
9464418919fSjohnjiang 		const char *desc;
9474418919fSjohnjiang 		void (*config)(struct rte_acl_config *);
9484418919fSjohnjiang 		void (*convert)(const struct rte_acl_ipv4vlan_rule *,
9494418919fSjohnjiang 			struct acl_ipv4vlan_rule *);
9504418919fSjohnjiang 	} convert_param[] = {
9514418919fSjohnjiang 		{
9524418919fSjohnjiang 			"acl_ipv4vlan_tuple",
9534418919fSjohnjiang 			convert_config,
9544418919fSjohnjiang 			convert_rule,
9554418919fSjohnjiang 		},
9564418919fSjohnjiang 		{
9574418919fSjohnjiang 			"acl_ipv4vlan_tuple, RTE_ACL_FIELD_TYPE_BITMASK type "
9584418919fSjohnjiang 			"for IPv4",
9594418919fSjohnjiang 			convert_config_1,
9604418919fSjohnjiang 			convert_rule_1,
9614418919fSjohnjiang 		},
9624418919fSjohnjiang 		{
9634418919fSjohnjiang 			"acl_ipv4vlan_tuple, RTE_ACL_FIELD_TYPE_RANGE type "
9644418919fSjohnjiang 			"for IPv4",
9654418919fSjohnjiang 			convert_config_2,
9664418919fSjohnjiang 			convert_rule_2,
9674418919fSjohnjiang 		},
9684418919fSjohnjiang 		{
9694418919fSjohnjiang 			"acl_ipv4vlan_tuple: swap VLAN and PORTs order",
9704418919fSjohnjiang 			convert_config_3,
9714418919fSjohnjiang 			convert_rule_3,
9724418919fSjohnjiang 		},
9734418919fSjohnjiang 		{
9744418919fSjohnjiang 			"acl_ipv4vlan_tuple: swap SRC and DST IPv4 order",
9754418919fSjohnjiang 			convert_config_4,
9764418919fSjohnjiang 			convert_rule_4,
9774418919fSjohnjiang 		},
9784418919fSjohnjiang 	};
9794418919fSjohnjiang 
9804418919fSjohnjiang 	uint32_t i;
9814418919fSjohnjiang 	int32_t rc;
9824418919fSjohnjiang 
9834418919fSjohnjiang 	for (i = 0; i != RTE_DIM(convert_param); i++) {
9844418919fSjohnjiang 		rc = test_convert_rules(convert_param[i].desc,
9854418919fSjohnjiang 			convert_param[i].config,
9864418919fSjohnjiang 			convert_param[i].convert);
9874418919fSjohnjiang 		if (rc != 0) {
9884418919fSjohnjiang 			printf("%s for test-case: %s failed, error code: %d;\n",
9894418919fSjohnjiang 				__func__, convert_param[i].desc, rc);
9904418919fSjohnjiang 			return rc;
9914418919fSjohnjiang 		}
9924418919fSjohnjiang 	}
9934418919fSjohnjiang 
9944418919fSjohnjiang 	return 0;
9954418919fSjohnjiang }
9964418919fSjohnjiang 
9974418919fSjohnjiang /*
9984418919fSjohnjiang  * Test wrong layout behavior
9994418919fSjohnjiang  * This test supplies the ACL context with invalid layout, which results in
10004418919fSjohnjiang  * ACL matching the wrong stuff. However, it should match the wrong stuff
10014418919fSjohnjiang  * the right way. We switch around source and destination addresses,
10024418919fSjohnjiang  * source and destination ports, and protocol will point to first byte of
10034418919fSjohnjiang  * destination port.
10044418919fSjohnjiang  */
10054418919fSjohnjiang static int
test_invalid_layout(void)10064418919fSjohnjiang test_invalid_layout(void)
10074418919fSjohnjiang {
10084418919fSjohnjiang 	struct rte_acl_ctx *acx;
10094418919fSjohnjiang 	int ret, i;
10104418919fSjohnjiang 
10114418919fSjohnjiang 	uint32_t results[RTE_DIM(invalid_layout_data)];
10124418919fSjohnjiang 	const uint8_t *data[RTE_DIM(invalid_layout_data)];
10134418919fSjohnjiang 
10144418919fSjohnjiang 	const uint32_t layout[RTE_ACL_IPV4VLAN_NUM] = {
10154418919fSjohnjiang 			/* proto points to destination port's first byte */
10164418919fSjohnjiang 			offsetof(struct ipv4_7tuple, port_dst),
10174418919fSjohnjiang 
10184418919fSjohnjiang 			0, /* VLAN not used */
10194418919fSjohnjiang 
10204418919fSjohnjiang 			/* src and dst addresses are swapped */
10214418919fSjohnjiang 			offsetof(struct ipv4_7tuple, ip_dst),
10224418919fSjohnjiang 			offsetof(struct ipv4_7tuple, ip_src),
10234418919fSjohnjiang 
10244418919fSjohnjiang 			/*
10254418919fSjohnjiang 			 * we can't swap ports here, so we will swap
10264418919fSjohnjiang 			 * them in the data
10274418919fSjohnjiang 			 */
10284418919fSjohnjiang 			offsetof(struct ipv4_7tuple, port_src),
10294418919fSjohnjiang 	};
10304418919fSjohnjiang 
10314418919fSjohnjiang 	acx = rte_acl_create(&acl_param);
10324418919fSjohnjiang 	if (acx == NULL) {
10334418919fSjohnjiang 		printf("Line %i: Error creating ACL context!\n", __LINE__);
10344418919fSjohnjiang 		return -1;
10354418919fSjohnjiang 	}
10364418919fSjohnjiang 
10374418919fSjohnjiang 	/* putting a lot of rules into the context results in greater
10384418919fSjohnjiang 	 * coverage numbers. it doesn't matter if they are identical */
10394418919fSjohnjiang 	for (i = 0; i < 1000; i++) {
10404418919fSjohnjiang 		/* add rules to the context */
10414418919fSjohnjiang 		ret = rte_acl_ipv4vlan_add_rules(acx, invalid_layout_rules,
10424418919fSjohnjiang 				RTE_DIM(invalid_layout_rules));
10434418919fSjohnjiang 		if (ret != 0) {
10444418919fSjohnjiang 			printf("Line %i: Adding rules to ACL context failed!\n",
10454418919fSjohnjiang 				__LINE__);
10464418919fSjohnjiang 			rte_acl_free(acx);
10474418919fSjohnjiang 			return -1;
10484418919fSjohnjiang 		}
10494418919fSjohnjiang 	}
10504418919fSjohnjiang 
10514418919fSjohnjiang 	/* try building the context */
10524418919fSjohnjiang 	ret = rte_acl_ipv4vlan_build(acx, layout, 1);
10534418919fSjohnjiang 	if (ret != 0) {
10544418919fSjohnjiang 		printf("Line %i: Building ACL context failed!\n", __LINE__);
10554418919fSjohnjiang 		rte_acl_free(acx);
10564418919fSjohnjiang 		return -1;
10574418919fSjohnjiang 	}
10584418919fSjohnjiang 
10594418919fSjohnjiang 	/* swap all bytes in the data to network order */
10604418919fSjohnjiang 	bswap_test_data(invalid_layout_data, RTE_DIM(invalid_layout_data), 1);
10614418919fSjohnjiang 
10624418919fSjohnjiang 	/* prepare data */
10634418919fSjohnjiang 	for (i = 0; i < (int) RTE_DIM(invalid_layout_data); i++) {
10644418919fSjohnjiang 		data[i] = (uint8_t *)&invalid_layout_data[i];
10654418919fSjohnjiang 	}
10664418919fSjohnjiang 
10674418919fSjohnjiang 	/* classify tuples */
10684418919fSjohnjiang 	ret = rte_acl_classify_alg(acx, data, results,
10694418919fSjohnjiang 			RTE_DIM(results), 1, RTE_ACL_CLASSIFY_SCALAR);
10704418919fSjohnjiang 	if (ret != 0) {
10714418919fSjohnjiang 		printf("Line %i: SSE classify failed!\n", __LINE__);
10724418919fSjohnjiang 		rte_acl_free(acx);
10734418919fSjohnjiang 		return -1;
10744418919fSjohnjiang 	}
10754418919fSjohnjiang 
10764418919fSjohnjiang 	for (i = 0; i < (int) RTE_DIM(results); i++) {
10774418919fSjohnjiang 		if (results[i] != invalid_layout_data[i].allow) {
10784418919fSjohnjiang 			printf("Line %i: Wrong results at %i "
10794418919fSjohnjiang 				"(result=%u, should be %u)!\n",
10804418919fSjohnjiang 				__LINE__, i, results[i],
10814418919fSjohnjiang 				invalid_layout_data[i].allow);
10824418919fSjohnjiang 			goto err;
10834418919fSjohnjiang 		}
10844418919fSjohnjiang 	}
10854418919fSjohnjiang 
10864418919fSjohnjiang 	/* classify tuples (scalar) */
10874418919fSjohnjiang 	ret = rte_acl_classify_alg(acx, data, results, RTE_DIM(results), 1,
10884418919fSjohnjiang 		RTE_ACL_CLASSIFY_SCALAR);
10894418919fSjohnjiang 
10904418919fSjohnjiang 	if (ret != 0) {
10914418919fSjohnjiang 		printf("Line %i: Scalar classify failed!\n", __LINE__);
10924418919fSjohnjiang 		rte_acl_free(acx);
10934418919fSjohnjiang 		return -1;
10944418919fSjohnjiang 	}
10954418919fSjohnjiang 
10964418919fSjohnjiang 	for (i = 0; i < (int) RTE_DIM(results); i++) {
10974418919fSjohnjiang 		if (results[i] != invalid_layout_data[i].allow) {
10984418919fSjohnjiang 			printf("Line %i: Wrong results at %i "
10994418919fSjohnjiang 				"(result=%u, should be %u)!\n",
11004418919fSjohnjiang 				__LINE__, i, results[i],
11014418919fSjohnjiang 				invalid_layout_data[i].allow);
11024418919fSjohnjiang 			goto err;
11034418919fSjohnjiang 		}
11044418919fSjohnjiang 	}
11054418919fSjohnjiang 
11064418919fSjohnjiang 	rte_acl_free(acx);
11074418919fSjohnjiang 
11084418919fSjohnjiang 	/* swap data back to cpu order so that next time tests don't fail */
11094418919fSjohnjiang 	bswap_test_data(invalid_layout_data, RTE_DIM(invalid_layout_data), 0);
11104418919fSjohnjiang 
11114418919fSjohnjiang 	return 0;
11124418919fSjohnjiang err:
11134418919fSjohnjiang 
11144418919fSjohnjiang 	/* swap data back to cpu order so that next time tests don't fail */
11154418919fSjohnjiang 	bswap_test_data(invalid_layout_data, RTE_DIM(invalid_layout_data), 0);
11164418919fSjohnjiang 
11174418919fSjohnjiang 	rte_acl_free(acx);
11184418919fSjohnjiang 
11194418919fSjohnjiang 	return -1;
11204418919fSjohnjiang }
11214418919fSjohnjiang 
11224418919fSjohnjiang /*
11234418919fSjohnjiang  * Test creating and finding ACL contexts, and adding rules
11244418919fSjohnjiang  */
11254418919fSjohnjiang static int
test_create_find_add(void)11264418919fSjohnjiang test_create_find_add(void)
11274418919fSjohnjiang {
11284418919fSjohnjiang 	struct rte_acl_param param;
11294418919fSjohnjiang 	struct rte_acl_ctx *acx, *acx2, *tmp;
11304418919fSjohnjiang 	struct rte_acl_ipv4vlan_rule rules[LEN];
11314418919fSjohnjiang 
11324418919fSjohnjiang 	const uint32_t layout[RTE_ACL_IPV4VLAN_NUM] = {0};
11334418919fSjohnjiang 
11344418919fSjohnjiang 	const char *acx_name = "acx";
11354418919fSjohnjiang 	const char *acx2_name = "acx2";
11364418919fSjohnjiang 	int i, ret;
11374418919fSjohnjiang 
11384418919fSjohnjiang 	/* create two contexts */
11394418919fSjohnjiang 	memcpy(&param, &acl_param, sizeof(param));
11404418919fSjohnjiang 	param.max_rule_num = 2;
11414418919fSjohnjiang 
11424418919fSjohnjiang 	param.name = acx_name;
11434418919fSjohnjiang 	acx = rte_acl_create(&param);
11444418919fSjohnjiang 	if (acx == NULL) {
11454418919fSjohnjiang 		printf("Line %i: Error creating %s!\n", __LINE__, acx_name);
11464418919fSjohnjiang 		return -1;
11474418919fSjohnjiang 	}
11484418919fSjohnjiang 
11494418919fSjohnjiang 	param.name = acx2_name;
11504418919fSjohnjiang 	acx2 = rte_acl_create(&param);
11514418919fSjohnjiang 	if (acx2 == NULL || acx2 == acx) {
11524418919fSjohnjiang 		printf("Line %i: Error creating %s!\n", __LINE__, acx2_name);
11534418919fSjohnjiang 		rte_acl_free(acx);
11544418919fSjohnjiang 		return -1;
11554418919fSjohnjiang 	}
11564418919fSjohnjiang 
11574418919fSjohnjiang 	/* try to create third one, with an existing name */
11584418919fSjohnjiang 	param.name = acx_name;
11594418919fSjohnjiang 	tmp = rte_acl_create(&param);
11604418919fSjohnjiang 	if (tmp != acx) {
11614418919fSjohnjiang 		printf("Line %i: Creating context with existing name "
11624418919fSjohnjiang 			"test failed!\n",
11634418919fSjohnjiang 			__LINE__);
11644418919fSjohnjiang 		if (tmp)
11654418919fSjohnjiang 			rte_acl_free(tmp);
11664418919fSjohnjiang 		goto err;
11674418919fSjohnjiang 	}
11684418919fSjohnjiang 
11694418919fSjohnjiang 	param.name = acx2_name;
11704418919fSjohnjiang 	tmp = rte_acl_create(&param);
11714418919fSjohnjiang 	if (tmp != acx2) {
11724418919fSjohnjiang 		printf("Line %i: Creating context with existing "
11734418919fSjohnjiang 			"name test 2 failed!\n",
11744418919fSjohnjiang 			__LINE__);
11754418919fSjohnjiang 		if (tmp)
11764418919fSjohnjiang 			rte_acl_free(tmp);
11774418919fSjohnjiang 		goto err;
11784418919fSjohnjiang 	}
11794418919fSjohnjiang 
11804418919fSjohnjiang 	/* try to find existing ACL contexts */
11814418919fSjohnjiang 	tmp = rte_acl_find_existing(acx_name);
11824418919fSjohnjiang 	if (tmp != acx) {
11834418919fSjohnjiang 		printf("Line %i: Finding %s failed!\n", __LINE__, acx_name);
11844418919fSjohnjiang 		if (tmp)
11854418919fSjohnjiang 			rte_acl_free(tmp);
11864418919fSjohnjiang 		goto err;
11874418919fSjohnjiang 	}
11884418919fSjohnjiang 
11894418919fSjohnjiang 	tmp = rte_acl_find_existing(acx2_name);
11904418919fSjohnjiang 	if (tmp != acx2) {
11914418919fSjohnjiang 		printf("Line %i: Finding %s failed!\n", __LINE__, acx2_name);
11924418919fSjohnjiang 		if (tmp)
11934418919fSjohnjiang 			rte_acl_free(tmp);
11944418919fSjohnjiang 		goto err;
11954418919fSjohnjiang 	}
11964418919fSjohnjiang 
11974418919fSjohnjiang 	/* try to find non-existing context */
11984418919fSjohnjiang 	tmp = rte_acl_find_existing("invalid");
11994418919fSjohnjiang 	if (tmp != NULL) {
12004418919fSjohnjiang 		printf("Line %i: Non-existent ACL context found!\n", __LINE__);
12014418919fSjohnjiang 		goto err;
12024418919fSjohnjiang 	}
12034418919fSjohnjiang 
12044418919fSjohnjiang 	/* free context */
12054418919fSjohnjiang 	rte_acl_free(acx);
12064418919fSjohnjiang 
12074418919fSjohnjiang 
12084418919fSjohnjiang 	/* create valid (but severely limited) acx */
12094418919fSjohnjiang 	memcpy(&param, &acl_param, sizeof(param));
12104418919fSjohnjiang 	param.max_rule_num = LEN;
12114418919fSjohnjiang 
12124418919fSjohnjiang 	acx = rte_acl_create(&param);
12134418919fSjohnjiang 	if (acx == NULL) {
12144418919fSjohnjiang 		printf("Line %i: Error creating %s!\n", __LINE__, param.name);
12154418919fSjohnjiang 		goto err;
12164418919fSjohnjiang 	}
12174418919fSjohnjiang 
12184418919fSjohnjiang 	/* create dummy acl */
12194418919fSjohnjiang 	for (i = 0; i < LEN; i++) {
12204418919fSjohnjiang 		memcpy(&rules[i], &acl_rule,
12214418919fSjohnjiang 			sizeof(struct rte_acl_ipv4vlan_rule));
12224418919fSjohnjiang 		/* skip zero */
12234418919fSjohnjiang 		rules[i].data.userdata = i + 1;
12244418919fSjohnjiang 		/* one rule per category */
12254418919fSjohnjiang 		rules[i].data.category_mask = 1 << i;
12264418919fSjohnjiang 	}
12274418919fSjohnjiang 
12284418919fSjohnjiang 	/* try filling up the context */
12294418919fSjohnjiang 	ret = rte_acl_ipv4vlan_add_rules(acx, rules, LEN);
12304418919fSjohnjiang 	if (ret != 0) {
12314418919fSjohnjiang 		printf("Line %i: Adding %i rules to ACL context failed!\n",
12324418919fSjohnjiang 				__LINE__, LEN);
12334418919fSjohnjiang 		goto err;
12344418919fSjohnjiang 	}
12354418919fSjohnjiang 
12364418919fSjohnjiang 	/* try adding to a (supposedly) full context */
12374418919fSjohnjiang 	ret = rte_acl_ipv4vlan_add_rules(acx, rules, 1);
12384418919fSjohnjiang 	if (ret == 0) {
12394418919fSjohnjiang 		printf("Line %i: Adding rules to full ACL context should"
12404418919fSjohnjiang 				"have failed!\n", __LINE__);
12414418919fSjohnjiang 		goto err;
12424418919fSjohnjiang 	}
12434418919fSjohnjiang 
12444418919fSjohnjiang 	/* try building the context */
12454418919fSjohnjiang 	ret = rte_acl_ipv4vlan_build(acx, layout, RTE_ACL_MAX_CATEGORIES);
12464418919fSjohnjiang 	if (ret != 0) {
12474418919fSjohnjiang 		printf("Line %i: Building ACL context failed!\n", __LINE__);
12484418919fSjohnjiang 		goto err;
12494418919fSjohnjiang 	}
12504418919fSjohnjiang 
12514418919fSjohnjiang 	rte_acl_free(acx);
12524418919fSjohnjiang 	rte_acl_free(acx2);
12534418919fSjohnjiang 
12544418919fSjohnjiang 	return 0;
12554418919fSjohnjiang err:
12564418919fSjohnjiang 	rte_acl_free(acx);
12574418919fSjohnjiang 	rte_acl_free(acx2);
12584418919fSjohnjiang 	return -1;
12594418919fSjohnjiang }
12604418919fSjohnjiang 
12614418919fSjohnjiang /*
12624418919fSjohnjiang  * test various invalid rules
12634418919fSjohnjiang  */
12644418919fSjohnjiang static int
test_invalid_rules(void)12654418919fSjohnjiang test_invalid_rules(void)
12664418919fSjohnjiang {
12674418919fSjohnjiang 	struct rte_acl_ctx *acx;
12684418919fSjohnjiang 	int ret;
12694418919fSjohnjiang 
12704418919fSjohnjiang 	struct rte_acl_ipv4vlan_rule rule;
12714418919fSjohnjiang 
12724418919fSjohnjiang 	acx = rte_acl_create(&acl_param);
12734418919fSjohnjiang 	if (acx == NULL) {
12744418919fSjohnjiang 		printf("Line %i: Error creating ACL context!\n", __LINE__);
12754418919fSjohnjiang 		return -1;
12764418919fSjohnjiang 	}
12774418919fSjohnjiang 
12784418919fSjohnjiang 	/* test inverted high/low source and destination ports.
12794418919fSjohnjiang 	 * originally, there was a problem with memory consumption when using
12804418919fSjohnjiang 	 * such rules.
12814418919fSjohnjiang 	 */
12824418919fSjohnjiang 	/* create dummy acl */
12834418919fSjohnjiang 	memcpy(&rule, &acl_rule, sizeof(struct rte_acl_ipv4vlan_rule));
12844418919fSjohnjiang 	rule.data.userdata = 1;
12854418919fSjohnjiang 	rule.dst_port_low = 0xfff0;
12864418919fSjohnjiang 	rule.dst_port_high = 0x0010;
12874418919fSjohnjiang 
12884418919fSjohnjiang 	/* add rules to context and try to build it */
12894418919fSjohnjiang 	ret = rte_acl_ipv4vlan_add_rules(acx, &rule, 1);
12904418919fSjohnjiang 	if (ret == 0) {
12914418919fSjohnjiang 		printf("Line %i: Adding rules to ACL context "
12924418919fSjohnjiang 				"should have failed!\n", __LINE__);
12934418919fSjohnjiang 		goto err;
12944418919fSjohnjiang 	}
12954418919fSjohnjiang 
12964418919fSjohnjiang 	rule.dst_port_low = 0x0;
12974418919fSjohnjiang 	rule.dst_port_high = 0xffff;
12984418919fSjohnjiang 	rule.src_port_low = 0xfff0;
12994418919fSjohnjiang 	rule.src_port_high = 0x0010;
13004418919fSjohnjiang 
13014418919fSjohnjiang 	/* add rules to context and try to build it */
13024418919fSjohnjiang 	ret = rte_acl_ipv4vlan_add_rules(acx, &rule, 1);
13034418919fSjohnjiang 	if (ret == 0) {
13044418919fSjohnjiang 		printf("Line %i: Adding rules to ACL context "
13054418919fSjohnjiang 				"should have failed!\n", __LINE__);
13064418919fSjohnjiang 		goto err;
13074418919fSjohnjiang 	}
13084418919fSjohnjiang 
13094418919fSjohnjiang 	rule.dst_port_low = 0x0;
13104418919fSjohnjiang 	rule.dst_port_high = 0xffff;
13114418919fSjohnjiang 	rule.src_port_low = 0x0;
13124418919fSjohnjiang 	rule.src_port_high = 0xffff;
13134418919fSjohnjiang 
13144418919fSjohnjiang 	rule.dst_mask_len = 33;
13154418919fSjohnjiang 
13164418919fSjohnjiang 	/* add rules to context and try to build it */
13174418919fSjohnjiang 	ret = rte_acl_ipv4vlan_add_rules(acx, &rule, 1);
13184418919fSjohnjiang 	if (ret == 0) {
13194418919fSjohnjiang 		printf("Line %i: Adding rules to ACL context "
13204418919fSjohnjiang 				"should have failed!\n", __LINE__);
13214418919fSjohnjiang 		goto err;
13224418919fSjohnjiang 	}
13234418919fSjohnjiang 
13244418919fSjohnjiang 	rule.dst_mask_len = 0;
13254418919fSjohnjiang 	rule.src_mask_len = 33;
13264418919fSjohnjiang 
13274418919fSjohnjiang 	/* add rules to context and try to build it */
13284418919fSjohnjiang 	ret = rte_acl_ipv4vlan_add_rules(acx, &rule, 1);
13294418919fSjohnjiang 	if (ret == 0) {
13304418919fSjohnjiang 		printf("Line %i: Adding rules to ACL context "
13314418919fSjohnjiang 				"should have failed!\n", __LINE__);
13324418919fSjohnjiang 		goto err;
13334418919fSjohnjiang 	}
13344418919fSjohnjiang 
13354418919fSjohnjiang 	rte_acl_free(acx);
13364418919fSjohnjiang 
13374418919fSjohnjiang 	return 0;
13384418919fSjohnjiang 
13394418919fSjohnjiang err:
13404418919fSjohnjiang 	rte_acl_free(acx);
13414418919fSjohnjiang 
13424418919fSjohnjiang 	return -1;
13434418919fSjohnjiang }
13444418919fSjohnjiang 
13454418919fSjohnjiang /*
13464418919fSjohnjiang  * test functions by passing invalid or
13474418919fSjohnjiang  * non-workable parameters.
13484418919fSjohnjiang  *
13494418919fSjohnjiang  * we do very limited testing of classify functions here
13504418919fSjohnjiang  * because those are performance-critical and
13514418919fSjohnjiang  * thus don't do much parameter checking.
13524418919fSjohnjiang  */
13534418919fSjohnjiang static int
test_invalid_parameters(void)13544418919fSjohnjiang test_invalid_parameters(void)
13554418919fSjohnjiang {
13564418919fSjohnjiang 	struct rte_acl_param param;
13574418919fSjohnjiang 	struct rte_acl_ctx *acx;
13584418919fSjohnjiang 	struct rte_acl_ipv4vlan_rule rule;
13594418919fSjohnjiang 	int result;
13604418919fSjohnjiang 
13614418919fSjohnjiang 	uint32_t layout[RTE_ACL_IPV4VLAN_NUM] = {0};
13624418919fSjohnjiang 
13634418919fSjohnjiang 
13644418919fSjohnjiang 	/**
13654418919fSjohnjiang 	 * rte_ac_create()
13664418919fSjohnjiang 	 */
13674418919fSjohnjiang 
13684418919fSjohnjiang 	/* NULL param */
13694418919fSjohnjiang 	acx = rte_acl_create(NULL);
13704418919fSjohnjiang 	if (acx != NULL) {
13714418919fSjohnjiang 		printf("Line %i: ACL context creation with NULL param "
13724418919fSjohnjiang 				"should have failed!\n", __LINE__);
13734418919fSjohnjiang 		rte_acl_free(acx);
13744418919fSjohnjiang 		return -1;
13754418919fSjohnjiang 	}
13764418919fSjohnjiang 
13774418919fSjohnjiang 	/* zero rule size */
13784418919fSjohnjiang 	memcpy(&param, &acl_param, sizeof(param));
13794418919fSjohnjiang 	param.rule_size = 0;
13804418919fSjohnjiang 
13814418919fSjohnjiang 	acx = rte_acl_create(&param);
13824418919fSjohnjiang 	if (acx == NULL) {
13834418919fSjohnjiang 		printf("Line %i: ACL context creation with zero rule len "
13844418919fSjohnjiang 				"failed!\n", __LINE__);
13854418919fSjohnjiang 		return -1;
13864418919fSjohnjiang 	} else
13874418919fSjohnjiang 		rte_acl_free(acx);
13884418919fSjohnjiang 
13894418919fSjohnjiang 	/* zero max rule num */
13904418919fSjohnjiang 	memcpy(&param, &acl_param, sizeof(param));
13914418919fSjohnjiang 	param.max_rule_num = 0;
13924418919fSjohnjiang 
13934418919fSjohnjiang 	acx = rte_acl_create(&param);
13944418919fSjohnjiang 	if (acx == NULL) {
13954418919fSjohnjiang 		printf("Line %i: ACL context creation with zero rule num "
13964418919fSjohnjiang 				"failed!\n", __LINE__);
13974418919fSjohnjiang 		return -1;
13984418919fSjohnjiang 	} else
13994418919fSjohnjiang 		rte_acl_free(acx);
14004418919fSjohnjiang 
14010c6bd470Sfengbojiang 	if (rte_eal_has_hugepages()) {
14024418919fSjohnjiang 		/* invalid NUMA node */
14034418919fSjohnjiang 		memcpy(&param, &acl_param, sizeof(param));
14044418919fSjohnjiang 		param.socket_id = RTE_MAX_NUMA_NODES + 1;
14054418919fSjohnjiang 
14064418919fSjohnjiang 		acx = rte_acl_create(&param);
14074418919fSjohnjiang 		if (acx != NULL) {
14080c6bd470Sfengbojiang 			printf("Line %i: ACL context creation with invalid "
14090c6bd470Sfengbojiang 					"NUMA should have failed!\n", __LINE__);
14104418919fSjohnjiang 			rte_acl_free(acx);
14114418919fSjohnjiang 			return -1;
14124418919fSjohnjiang 		}
14130c6bd470Sfengbojiang 	}
14144418919fSjohnjiang 
14154418919fSjohnjiang 	/* NULL name */
14164418919fSjohnjiang 	memcpy(&param, &acl_param, sizeof(param));
14174418919fSjohnjiang 	param.name = NULL;
14184418919fSjohnjiang 
14194418919fSjohnjiang 	acx = rte_acl_create(&param);
14204418919fSjohnjiang 	if (acx != NULL) {
14214418919fSjohnjiang 		printf("Line %i: ACL context creation with NULL name "
14224418919fSjohnjiang 				"should have failed!\n", __LINE__);
14234418919fSjohnjiang 		rte_acl_free(acx);
14244418919fSjohnjiang 		return -1;
14254418919fSjohnjiang 	}
14264418919fSjohnjiang 
14274418919fSjohnjiang 	/**
14284418919fSjohnjiang 	 * rte_acl_find_existing
14294418919fSjohnjiang 	 */
14304418919fSjohnjiang 
14314418919fSjohnjiang 	acx = rte_acl_find_existing(NULL);
14324418919fSjohnjiang 	if (acx != NULL) {
14334418919fSjohnjiang 		printf("Line %i: NULL ACL context found!\n", __LINE__);
14344418919fSjohnjiang 		rte_acl_free(acx);
14354418919fSjohnjiang 		return -1;
14364418919fSjohnjiang 	}
14374418919fSjohnjiang 
14384418919fSjohnjiang 	/**
14394418919fSjohnjiang 	 * rte_acl_ipv4vlan_add_rules
14404418919fSjohnjiang 	 */
14414418919fSjohnjiang 
14424418919fSjohnjiang 	/* initialize everything */
14434418919fSjohnjiang 	memcpy(&param, &acl_param, sizeof(param));
14444418919fSjohnjiang 	acx = rte_acl_create(&param);
14454418919fSjohnjiang 	if (acx == NULL) {
14464418919fSjohnjiang 		printf("Line %i: ACL context creation failed!\n", __LINE__);
14474418919fSjohnjiang 		return -1;
14484418919fSjohnjiang 	}
14494418919fSjohnjiang 
14504418919fSjohnjiang 	memcpy(&rule, &acl_rule, sizeof(rule));
14514418919fSjohnjiang 
14524418919fSjohnjiang 	/* NULL context */
14534418919fSjohnjiang 	result = rte_acl_ipv4vlan_add_rules(NULL, &rule, 1);
14544418919fSjohnjiang 	if (result == 0) {
14554418919fSjohnjiang 		printf("Line %i: Adding rules with NULL ACL context "
14564418919fSjohnjiang 				"should have failed!\n", __LINE__);
14574418919fSjohnjiang 		rte_acl_free(acx);
14584418919fSjohnjiang 		return -1;
14594418919fSjohnjiang 	}
14604418919fSjohnjiang 
14614418919fSjohnjiang 	/* NULL rule */
14624418919fSjohnjiang 	result = rte_acl_ipv4vlan_add_rules(acx, NULL, 1);
14634418919fSjohnjiang 	if (result == 0) {
14644418919fSjohnjiang 		printf("Line %i: Adding NULL rule to ACL context "
14654418919fSjohnjiang 				"should have failed!\n", __LINE__);
14664418919fSjohnjiang 		rte_acl_free(acx);
14674418919fSjohnjiang 		return -1;
14684418919fSjohnjiang 	}
14694418919fSjohnjiang 
14704418919fSjohnjiang 	/* zero count (should succeed) */
14714418919fSjohnjiang 	result = rte_acl_ipv4vlan_add_rules(acx, &rule, 0);
14724418919fSjohnjiang 	if (result != 0) {
14734418919fSjohnjiang 		printf("Line %i: Adding 0 rules to ACL context failed!\n",
14744418919fSjohnjiang 			__LINE__);
14754418919fSjohnjiang 		rte_acl_free(acx);
14764418919fSjohnjiang 		return -1;
14774418919fSjohnjiang 	}
14784418919fSjohnjiang 
14794418919fSjohnjiang 	/* free ACL context */
14804418919fSjohnjiang 	rte_acl_free(acx);
14814418919fSjohnjiang 
14824418919fSjohnjiang 
14834418919fSjohnjiang 	/**
14844418919fSjohnjiang 	 * rte_acl_ipv4vlan_build
14854418919fSjohnjiang 	 */
14864418919fSjohnjiang 
14874418919fSjohnjiang 	/* reinitialize context */
14884418919fSjohnjiang 	memcpy(&param, &acl_param, sizeof(param));
14894418919fSjohnjiang 	acx = rte_acl_create(&param);
14904418919fSjohnjiang 	if (acx == NULL) {
14914418919fSjohnjiang 		printf("Line %i: ACL context creation failed!\n", __LINE__);
14924418919fSjohnjiang 		return -1;
14934418919fSjohnjiang 	}
14944418919fSjohnjiang 
14954418919fSjohnjiang 	/* NULL context */
14964418919fSjohnjiang 	result = rte_acl_ipv4vlan_build(NULL, layout, 1);
14974418919fSjohnjiang 	if (result == 0) {
14984418919fSjohnjiang 		printf("Line %i: Building with NULL context "
14994418919fSjohnjiang 				"should have failed!\n", __LINE__);
15004418919fSjohnjiang 		rte_acl_free(acx);
15014418919fSjohnjiang 		return -1;
15024418919fSjohnjiang 	}
15034418919fSjohnjiang 
15044418919fSjohnjiang 	/* NULL layout */
15054418919fSjohnjiang 	result = rte_acl_ipv4vlan_build(acx, NULL, 1);
15064418919fSjohnjiang 	if (result == 0) {
15074418919fSjohnjiang 		printf("Line %i: Building with NULL layout "
15084418919fSjohnjiang 				"should have failed!\n", __LINE__);
15094418919fSjohnjiang 		rte_acl_free(acx);
15104418919fSjohnjiang 		return -1;
15114418919fSjohnjiang 	}
15124418919fSjohnjiang 
15134418919fSjohnjiang 	/* zero categories (should not fail) */
15144418919fSjohnjiang 	result = rte_acl_ipv4vlan_build(acx, layout, 0);
15154418919fSjohnjiang 	if (result == 0) {
15164418919fSjohnjiang 		printf("Line %i: Building with 0 categories should fail!\n",
15174418919fSjohnjiang 			__LINE__);
15184418919fSjohnjiang 		rte_acl_free(acx);
15194418919fSjohnjiang 		return -1;
15204418919fSjohnjiang 	}
15214418919fSjohnjiang 
15224418919fSjohnjiang 	/* SSE classify test */
15234418919fSjohnjiang 
15244418919fSjohnjiang 	/* cover zero categories in classify (should not fail) */
15254418919fSjohnjiang 	result = rte_acl_classify(acx, NULL, NULL, 0, 0);
15264418919fSjohnjiang 	if (result != 0) {
15274418919fSjohnjiang 		printf("Line %i: SSE classify with zero categories "
15284418919fSjohnjiang 				"failed!\n", __LINE__);
15294418919fSjohnjiang 		rte_acl_free(acx);
15304418919fSjohnjiang 		return -1;
15314418919fSjohnjiang 	}
15324418919fSjohnjiang 
15334418919fSjohnjiang 	/* cover invalid but positive categories in classify */
15344418919fSjohnjiang 	result = rte_acl_classify(acx, NULL, NULL, 0, 3);
15354418919fSjohnjiang 	if (result == 0) {
15364418919fSjohnjiang 		printf("Line %i: SSE classify with 3 categories "
15374418919fSjohnjiang 				"should have failed!\n", __LINE__);
15384418919fSjohnjiang 		rte_acl_free(acx);
15394418919fSjohnjiang 		return -1;
15404418919fSjohnjiang 	}
15414418919fSjohnjiang 
15424418919fSjohnjiang 	/* scalar classify test */
15434418919fSjohnjiang 
15444418919fSjohnjiang 	/* cover zero categories in classify (should not fail) */
15454418919fSjohnjiang 	result = rte_acl_classify_alg(acx, NULL, NULL, 0, 0,
15464418919fSjohnjiang 		RTE_ACL_CLASSIFY_SCALAR);
15474418919fSjohnjiang 	if (result != 0) {
15484418919fSjohnjiang 		printf("Line %i: Scalar classify with zero categories "
15494418919fSjohnjiang 				"failed!\n", __LINE__);
15504418919fSjohnjiang 		rte_acl_free(acx);
15514418919fSjohnjiang 		return -1;
15524418919fSjohnjiang 	}
15534418919fSjohnjiang 
15544418919fSjohnjiang 	/* cover invalid but positive categories in classify */
15554418919fSjohnjiang 	result = rte_acl_classify(acx, NULL, NULL, 0, 3);
15564418919fSjohnjiang 	if (result == 0) {
15574418919fSjohnjiang 		printf("Line %i: Scalar classify with 3 categories "
15584418919fSjohnjiang 				"should have failed!\n", __LINE__);
15594418919fSjohnjiang 		rte_acl_free(acx);
15604418919fSjohnjiang 		return -1;
15614418919fSjohnjiang 	}
15624418919fSjohnjiang 
15634418919fSjohnjiang 	/* free ACL context */
15644418919fSjohnjiang 	rte_acl_free(acx);
15654418919fSjohnjiang 
15664418919fSjohnjiang 
15674418919fSjohnjiang 	/**
15684418919fSjohnjiang 	 * make sure void functions don't crash with NULL parameters
15694418919fSjohnjiang 	 */
15704418919fSjohnjiang 
15714418919fSjohnjiang 	rte_acl_free(NULL);
15724418919fSjohnjiang 
15734418919fSjohnjiang 	rte_acl_dump(NULL);
15744418919fSjohnjiang 
15754418919fSjohnjiang 	return 0;
15764418919fSjohnjiang }
15774418919fSjohnjiang 
15784418919fSjohnjiang /**
15794418919fSjohnjiang  * Various tests that don't test much but improve coverage
15804418919fSjohnjiang  */
15814418919fSjohnjiang static int
test_misc(void)15824418919fSjohnjiang test_misc(void)
15834418919fSjohnjiang {
15844418919fSjohnjiang 	struct rte_acl_param param;
15854418919fSjohnjiang 	struct rte_acl_ctx *acx;
15864418919fSjohnjiang 
15874418919fSjohnjiang 	/* create context */
15884418919fSjohnjiang 	memcpy(&param, &acl_param, sizeof(param));
15894418919fSjohnjiang 
15904418919fSjohnjiang 	acx = rte_acl_create(&param);
15914418919fSjohnjiang 	if (acx == NULL) {
15924418919fSjohnjiang 		printf("Line %i: Error creating ACL context!\n", __LINE__);
15934418919fSjohnjiang 		return -1;
15944418919fSjohnjiang 	}
15954418919fSjohnjiang 
15964418919fSjohnjiang 	/* dump context with rules - useful for coverage */
15974418919fSjohnjiang 	rte_acl_list_dump();
15984418919fSjohnjiang 
15994418919fSjohnjiang 	rte_acl_dump(acx);
16004418919fSjohnjiang 
16014418919fSjohnjiang 	rte_acl_free(acx);
16024418919fSjohnjiang 
16034418919fSjohnjiang 	return 0;
16044418919fSjohnjiang }
16054418919fSjohnjiang 
1606*2d9fd380Sjfb8856606 static uint32_t
get_u32_range_max(void)1607*2d9fd380Sjfb8856606 get_u32_range_max(void)
1608*2d9fd380Sjfb8856606 {
1609*2d9fd380Sjfb8856606 	uint32_t i, max;
1610*2d9fd380Sjfb8856606 
1611*2d9fd380Sjfb8856606 	max = 0;
1612*2d9fd380Sjfb8856606 	for (i = 0; i != RTE_DIM(acl_u32_range_test_rules); i++)
1613*2d9fd380Sjfb8856606 		max = RTE_MAX(max, acl_u32_range_test_rules[i].src_mask_len);
1614*2d9fd380Sjfb8856606 	return max;
1615*2d9fd380Sjfb8856606 }
1616*2d9fd380Sjfb8856606 
1617*2d9fd380Sjfb8856606 static uint32_t
get_u32_range_min(void)1618*2d9fd380Sjfb8856606 get_u32_range_min(void)
1619*2d9fd380Sjfb8856606 {
1620*2d9fd380Sjfb8856606 	uint32_t i, min;
1621*2d9fd380Sjfb8856606 
1622*2d9fd380Sjfb8856606 	min = UINT32_MAX;
1623*2d9fd380Sjfb8856606 	for (i = 0; i != RTE_DIM(acl_u32_range_test_rules); i++)
1624*2d9fd380Sjfb8856606 		min = RTE_MIN(min, acl_u32_range_test_rules[i].src_addr);
1625*2d9fd380Sjfb8856606 	return min;
1626*2d9fd380Sjfb8856606 }
1627*2d9fd380Sjfb8856606 
1628*2d9fd380Sjfb8856606 static const struct rte_acl_ipv4vlan_rule *
find_u32_range_rule(uint32_t val)1629*2d9fd380Sjfb8856606 find_u32_range_rule(uint32_t val)
1630*2d9fd380Sjfb8856606 {
1631*2d9fd380Sjfb8856606 	uint32_t i;
1632*2d9fd380Sjfb8856606 
1633*2d9fd380Sjfb8856606 	for (i = 0; i != RTE_DIM(acl_u32_range_test_rules); i++) {
1634*2d9fd380Sjfb8856606 		if (val >= acl_u32_range_test_rules[i].src_addr &&
1635*2d9fd380Sjfb8856606 				val <= acl_u32_range_test_rules[i].src_mask_len)
1636*2d9fd380Sjfb8856606 			return acl_u32_range_test_rules + i;
1637*2d9fd380Sjfb8856606 	}
1638*2d9fd380Sjfb8856606 	return NULL;
1639*2d9fd380Sjfb8856606 }
1640*2d9fd380Sjfb8856606 
1641*2d9fd380Sjfb8856606 static void
fill_u32_range_data(struct ipv4_7tuple tdata[],uint32_t start,uint32_t num)1642*2d9fd380Sjfb8856606 fill_u32_range_data(struct ipv4_7tuple tdata[], uint32_t start, uint32_t num)
1643*2d9fd380Sjfb8856606 {
1644*2d9fd380Sjfb8856606 	uint32_t i;
1645*2d9fd380Sjfb8856606 	const struct rte_acl_ipv4vlan_rule *r;
1646*2d9fd380Sjfb8856606 
1647*2d9fd380Sjfb8856606 	for (i = 0; i != num; i++) {
1648*2d9fd380Sjfb8856606 		tdata[i].ip_src = start + i;
1649*2d9fd380Sjfb8856606 		r = find_u32_range_rule(start + i);
1650*2d9fd380Sjfb8856606 		if (r != NULL)
1651*2d9fd380Sjfb8856606 			tdata[i].allow = r->data.userdata;
1652*2d9fd380Sjfb8856606 	}
1653*2d9fd380Sjfb8856606 }
1654*2d9fd380Sjfb8856606 
1655*2d9fd380Sjfb8856606 static int
test_u32_range(void)1656*2d9fd380Sjfb8856606 test_u32_range(void)
1657*2d9fd380Sjfb8856606 {
1658*2d9fd380Sjfb8856606 	int32_t rc;
1659*2d9fd380Sjfb8856606 	uint32_t i, k, max, min;
1660*2d9fd380Sjfb8856606 	struct rte_acl_ctx *acx;
1661*2d9fd380Sjfb8856606 	struct acl_ipv4vlan_rule r;
1662*2d9fd380Sjfb8856606 	struct ipv4_7tuple test_data[64];
1663*2d9fd380Sjfb8856606 
1664*2d9fd380Sjfb8856606 	acx = rte_acl_create(&acl_param);
1665*2d9fd380Sjfb8856606 	if (acx == NULL) {
1666*2d9fd380Sjfb8856606 		printf("%s#%i: Error creating ACL context!\n",
1667*2d9fd380Sjfb8856606 			__func__, __LINE__);
1668*2d9fd380Sjfb8856606 		return -1;
1669*2d9fd380Sjfb8856606 	}
1670*2d9fd380Sjfb8856606 
1671*2d9fd380Sjfb8856606 	for (i = 0; i != RTE_DIM(acl_u32_range_test_rules); i++) {
1672*2d9fd380Sjfb8856606 		convert_rule(&acl_u32_range_test_rules[i], &r);
1673*2d9fd380Sjfb8856606 		rc = rte_acl_add_rules(acx, (struct rte_acl_rule *)&r, 1);
1674*2d9fd380Sjfb8856606 		if (rc != 0) {
1675*2d9fd380Sjfb8856606 			printf("%s#%i: Adding rule to ACL context "
1676*2d9fd380Sjfb8856606 				"failed with error code: %d\n",
1677*2d9fd380Sjfb8856606 				__func__, __LINE__, rc);
1678*2d9fd380Sjfb8856606 			rte_acl_free(acx);
1679*2d9fd380Sjfb8856606 			return rc;
1680*2d9fd380Sjfb8856606 		}
1681*2d9fd380Sjfb8856606 	}
1682*2d9fd380Sjfb8856606 
1683*2d9fd380Sjfb8856606 	rc = build_convert_rules(acx, convert_config_2, 0);
1684*2d9fd380Sjfb8856606 	if (rc != 0) {
1685*2d9fd380Sjfb8856606 		printf("%s#%i Error @ build_convert_rules!\n",
1686*2d9fd380Sjfb8856606 			__func__, __LINE__);
1687*2d9fd380Sjfb8856606 		rte_acl_free(acx);
1688*2d9fd380Sjfb8856606 		return rc;
1689*2d9fd380Sjfb8856606 	}
1690*2d9fd380Sjfb8856606 
1691*2d9fd380Sjfb8856606 	max = get_u32_range_max();
1692*2d9fd380Sjfb8856606 	min = get_u32_range_min();
1693*2d9fd380Sjfb8856606 
1694*2d9fd380Sjfb8856606 	max = RTE_MAX(max, max + 1);
1695*2d9fd380Sjfb8856606 	min = RTE_MIN(min, min - 1);
1696*2d9fd380Sjfb8856606 
1697*2d9fd380Sjfb8856606 	printf("%s#%d starting range test from %u to %u\n",
1698*2d9fd380Sjfb8856606 		__func__, __LINE__, min, max);
1699*2d9fd380Sjfb8856606 
1700*2d9fd380Sjfb8856606 	for (i = min; i <= max; i += k) {
1701*2d9fd380Sjfb8856606 
1702*2d9fd380Sjfb8856606 		k = RTE_MIN(max - i + 1, RTE_DIM(test_data));
1703*2d9fd380Sjfb8856606 
1704*2d9fd380Sjfb8856606 		memset(test_data, 0, sizeof(test_data));
1705*2d9fd380Sjfb8856606 		fill_u32_range_data(test_data, i, k);
1706*2d9fd380Sjfb8856606 
1707*2d9fd380Sjfb8856606 		rc = test_classify_run(acx, test_data, k);
1708*2d9fd380Sjfb8856606 		if (rc != 0) {
1709*2d9fd380Sjfb8856606 			printf("%s#%d failed at [%u, %u) interval\n",
1710*2d9fd380Sjfb8856606 				__func__, __LINE__, i, i + k);
1711*2d9fd380Sjfb8856606 			break;
1712*2d9fd380Sjfb8856606 		}
1713*2d9fd380Sjfb8856606 	}
1714*2d9fd380Sjfb8856606 
1715*2d9fd380Sjfb8856606 	rte_acl_free(acx);
1716*2d9fd380Sjfb8856606 	return rc;
1717*2d9fd380Sjfb8856606 }
1718*2d9fd380Sjfb8856606 
17194418919fSjohnjiang static int
test_acl(void)17204418919fSjohnjiang test_acl(void)
17214418919fSjohnjiang {
17224418919fSjohnjiang 	if (test_invalid_parameters() < 0)
17234418919fSjohnjiang 		return -1;
17244418919fSjohnjiang 	if (test_invalid_rules() < 0)
17254418919fSjohnjiang 		return -1;
17264418919fSjohnjiang 	if (test_create_find_add() < 0)
17274418919fSjohnjiang 		return -1;
17284418919fSjohnjiang 	if (test_invalid_layout() < 0)
17294418919fSjohnjiang 		return -1;
17304418919fSjohnjiang 	if (test_misc() < 0)
17314418919fSjohnjiang 		return -1;
17324418919fSjohnjiang 	if (test_classify() < 0)
17334418919fSjohnjiang 		return -1;
17344418919fSjohnjiang 	if (test_build_ports_range() < 0)
17354418919fSjohnjiang 		return -1;
17364418919fSjohnjiang 	if (test_convert() < 0)
17374418919fSjohnjiang 		return -1;
1738*2d9fd380Sjfb8856606 	if (test_u32_range() < 0)
1739*2d9fd380Sjfb8856606 		return -1;
17404418919fSjohnjiang 
17414418919fSjohnjiang 	return 0;
17424418919fSjohnjiang }
17434418919fSjohnjiang 
17444418919fSjohnjiang REGISTER_TEST_COMMAND(acl_autotest, test_acl);
1745