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(¶m, &acl_param, sizeof(param));
11404418919fSjohnjiang param.max_rule_num = 2;
11414418919fSjohnjiang
11424418919fSjohnjiang param.name = acx_name;
11434418919fSjohnjiang acx = rte_acl_create(¶m);
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(¶m);
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(¶m);
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(¶m);
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(¶m, &acl_param, sizeof(param));
12104418919fSjohnjiang param.max_rule_num = LEN;
12114418919fSjohnjiang
12124418919fSjohnjiang acx = rte_acl_create(¶m);
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(¶m, &acl_param, sizeof(param));
13794418919fSjohnjiang param.rule_size = 0;
13804418919fSjohnjiang
13814418919fSjohnjiang acx = rte_acl_create(¶m);
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(¶m, &acl_param, sizeof(param));
13914418919fSjohnjiang param.max_rule_num = 0;
13924418919fSjohnjiang
13934418919fSjohnjiang acx = rte_acl_create(¶m);
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(¶m, &acl_param, sizeof(param));
14044418919fSjohnjiang param.socket_id = RTE_MAX_NUMA_NODES + 1;
14054418919fSjohnjiang
14064418919fSjohnjiang acx = rte_acl_create(¶m);
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(¶m, &acl_param, sizeof(param));
14174418919fSjohnjiang param.name = NULL;
14184418919fSjohnjiang
14194418919fSjohnjiang acx = rte_acl_create(¶m);
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(¶m, &acl_param, sizeof(param));
14444418919fSjohnjiang acx = rte_acl_create(¶m);
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(¶m, &acl_param, sizeof(param));
14894418919fSjohnjiang acx = rte_acl_create(¶m);
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(¶m, &acl_param, sizeof(param));
15894418919fSjohnjiang
15904418919fSjohnjiang acx = rte_acl_create(¶m);
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