175795fabSBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause 275795fabSBruce Richardson * Copyright(c) 2010-2014 Intel Corporation 375795fabSBruce Richardson */ 475795fabSBruce Richardson 56723c0fcSBruce Richardson #include <rte_string_fns.h> 675795fabSBruce Richardson #include <rte_acl.h> 775795fabSBruce Richardson #include <getopt.h> 875795fabSBruce Richardson #include <string.h> 975795fabSBruce Richardson 1075795fabSBruce Richardson #include <rte_cycles.h> 1175795fabSBruce Richardson #include <rte_per_lcore.h> 1275795fabSBruce Richardson #include <rte_lcore.h> 1375795fabSBruce Richardson #include <rte_ip.h> 1475795fabSBruce Richardson 15a658775cSThomas Monjalon #define PRINT_USAGE_START "%s [EAL options] --\n" 1675795fabSBruce Richardson 1775795fabSBruce Richardson #define RTE_LOGTYPE_TESTACL RTE_LOGTYPE_USER1 1875795fabSBruce Richardson 1975795fabSBruce Richardson #define APP_NAME "TESTACL" 2075795fabSBruce Richardson 2175795fabSBruce Richardson #define GET_CB_FIELD(in, fd, base, lim, dlm) do { \ 2275795fabSBruce Richardson unsigned long val; \ 2375795fabSBruce Richardson char *end_fld; \ 2475795fabSBruce Richardson errno = 0; \ 2575795fabSBruce Richardson val = strtoul((in), &end_fld, (base)); \ 2675795fabSBruce Richardson if (errno != 0 || end_fld[0] != (dlm) || val > (lim)) \ 2775795fabSBruce Richardson return -EINVAL; \ 2875795fabSBruce Richardson (fd) = (typeof(fd))val; \ 2975795fabSBruce Richardson (in) = end_fld + 1; \ 3075795fabSBruce Richardson } while (0) 3175795fabSBruce Richardson 3275795fabSBruce Richardson #define OPT_RULE_FILE "rulesf" 3375795fabSBruce Richardson #define OPT_TRACE_FILE "tracef" 3475795fabSBruce Richardson #define OPT_RULE_NUM "rulenum" 3575795fabSBruce Richardson #define OPT_TRACE_NUM "tracenum" 3675795fabSBruce Richardson #define OPT_TRACE_STEP "tracestep" 3775795fabSBruce Richardson #define OPT_SEARCH_ALG "alg" 3875795fabSBruce Richardson #define OPT_BLD_CATEGORIES "bldcat" 3975795fabSBruce Richardson #define OPT_RUN_CATEGORIES "runcat" 4075795fabSBruce Richardson #define OPT_MAX_SIZE "maxsize" 4175795fabSBruce Richardson #define OPT_ITER_NUM "iter" 4275795fabSBruce Richardson #define OPT_VERBOSE "verbose" 4375795fabSBruce Richardson #define OPT_IPV6 "ipv6" 4475795fabSBruce Richardson 4575795fabSBruce Richardson #define TRACE_DEFAULT_NUM 0x10000 4675795fabSBruce Richardson #define TRACE_STEP_MAX 0x1000 4775795fabSBruce Richardson #define TRACE_STEP_DEF 0x100 4875795fabSBruce Richardson 4975795fabSBruce Richardson #define RULE_NUM 0x10000 5075795fabSBruce Richardson 51ca2183d3SKonstantin Ananyev #define COMMENT_LEAD_CHAR '#' 52ca2183d3SKonstantin Ananyev 5375795fabSBruce Richardson enum { 5475795fabSBruce Richardson DUMP_NONE, 5575795fabSBruce Richardson DUMP_SEARCH, 5675795fabSBruce Richardson DUMP_PKT, 5775795fabSBruce Richardson DUMP_MAX 5875795fabSBruce Richardson }; 5975795fabSBruce Richardson 6060018ef4SKonstantin Ananyev enum { 6160018ef4SKonstantin Ananyev IPV6_FRMT_NONE, 6260018ef4SKonstantin Ananyev IPV6_FRMT_U32, 6360018ef4SKonstantin Ananyev IPV6_FRMT_U64, 6460018ef4SKonstantin Ananyev }; 6560018ef4SKonstantin Ananyev 6675795fabSBruce Richardson struct acl_alg { 6775795fabSBruce Richardson const char *name; 6875795fabSBruce Richardson enum rte_acl_classify_alg alg; 6975795fabSBruce Richardson }; 7075795fabSBruce Richardson 7175795fabSBruce Richardson static const struct acl_alg acl_alg[] = { 7275795fabSBruce Richardson { 7375795fabSBruce Richardson .name = "scalar", 7475795fabSBruce Richardson .alg = RTE_ACL_CLASSIFY_SCALAR, 7575795fabSBruce Richardson }, 7675795fabSBruce Richardson { 7775795fabSBruce Richardson .name = "sse", 7875795fabSBruce Richardson .alg = RTE_ACL_CLASSIFY_SSE, 7975795fabSBruce Richardson }, 8075795fabSBruce Richardson { 8175795fabSBruce Richardson .name = "avx2", 8275795fabSBruce Richardson .alg = RTE_ACL_CLASSIFY_AVX2, 8375795fabSBruce Richardson }, 8475795fabSBruce Richardson { 8575795fabSBruce Richardson .name = "neon", 8675795fabSBruce Richardson .alg = RTE_ACL_CLASSIFY_NEON, 8775795fabSBruce Richardson }, 8875795fabSBruce Richardson { 8975795fabSBruce Richardson .name = "altivec", 9075795fabSBruce Richardson .alg = RTE_ACL_CLASSIFY_ALTIVEC, 9175795fabSBruce Richardson }, 92b64c2295SKonstantin Ananyev { 93b64c2295SKonstantin Ananyev .name = "avx512x16", 94b64c2295SKonstantin Ananyev .alg = RTE_ACL_CLASSIFY_AVX512X16, 95b64c2295SKonstantin Ananyev }, 9645da22e4SKonstantin Ananyev { 9745da22e4SKonstantin Ananyev .name = "avx512x32", 9845da22e4SKonstantin Ananyev .alg = RTE_ACL_CLASSIFY_AVX512X32, 9945da22e4SKonstantin Ananyev }, 10075795fabSBruce Richardson }; 10175795fabSBruce Richardson 10275795fabSBruce Richardson static struct { 10375795fabSBruce Richardson const char *prgname; 10475795fabSBruce Richardson const char *rule_file; 10575795fabSBruce Richardson const char *trace_file; 10675795fabSBruce Richardson size_t max_size; 10775795fabSBruce Richardson uint32_t bld_categories; 10875795fabSBruce Richardson uint32_t run_categories; 10975795fabSBruce Richardson uint32_t nb_rules; 11075795fabSBruce Richardson uint32_t nb_traces; 11175795fabSBruce Richardson uint32_t trace_step; 11275795fabSBruce Richardson uint32_t trace_sz; 11375795fabSBruce Richardson uint32_t iter_num; 11475795fabSBruce Richardson uint32_t verbose; 11575795fabSBruce Richardson uint32_t ipv6; 11675795fabSBruce Richardson struct acl_alg alg; 11775795fabSBruce Richardson uint32_t used_traces; 11875795fabSBruce Richardson void *traces; 11975795fabSBruce Richardson struct rte_acl_ctx *acx; 12075795fabSBruce Richardson } config = { 12175795fabSBruce Richardson .bld_categories = 3, 12275795fabSBruce Richardson .run_categories = 1, 12375795fabSBruce Richardson .nb_rules = RULE_NUM, 12475795fabSBruce Richardson .nb_traces = TRACE_DEFAULT_NUM, 12575795fabSBruce Richardson .trace_step = TRACE_STEP_DEF, 12675795fabSBruce Richardson .iter_num = 1, 12775795fabSBruce Richardson .verbose = DUMP_MAX, 12875795fabSBruce Richardson .alg = { 12975795fabSBruce Richardson .name = "default", 13075795fabSBruce Richardson .alg = RTE_ACL_CLASSIFY_DEFAULT, 13175795fabSBruce Richardson }, 13260018ef4SKonstantin Ananyev .ipv6 = IPV6_FRMT_NONE, 13375795fabSBruce Richardson }; 13475795fabSBruce Richardson 13575795fabSBruce Richardson static struct rte_acl_param prm = { 13675795fabSBruce Richardson .name = APP_NAME, 13775795fabSBruce Richardson .socket_id = SOCKET_ID_ANY, 13875795fabSBruce Richardson }; 13975795fabSBruce Richardson 14075795fabSBruce Richardson /* 14175795fabSBruce Richardson * Rule and trace formats definitions. 14275795fabSBruce Richardson */ 14375795fabSBruce Richardson 14475795fabSBruce Richardson struct ipv4_5tuple { 14575795fabSBruce Richardson uint8_t proto; 14675795fabSBruce Richardson uint32_t ip_src; 14775795fabSBruce Richardson uint32_t ip_dst; 14875795fabSBruce Richardson uint16_t port_src; 14975795fabSBruce Richardson uint16_t port_dst; 15075795fabSBruce Richardson }; 15175795fabSBruce Richardson 15275795fabSBruce Richardson enum { 15375795fabSBruce Richardson PROTO_FIELD_IPV4, 15475795fabSBruce Richardson SRC_FIELD_IPV4, 15575795fabSBruce Richardson DST_FIELD_IPV4, 15675795fabSBruce Richardson SRCP_FIELD_IPV4, 15775795fabSBruce Richardson DSTP_FIELD_IPV4, 15875795fabSBruce Richardson NUM_FIELDS_IPV4 15975795fabSBruce Richardson }; 16075795fabSBruce Richardson 16175795fabSBruce Richardson /* 16275795fabSBruce Richardson * That effectively defines order of IPV4VLAN classifications: 16375795fabSBruce Richardson * - PROTO 16475795fabSBruce Richardson * - VLAN (TAG and DOMAIN) 16575795fabSBruce Richardson * - SRC IP ADDRESS 16675795fabSBruce Richardson * - DST IP ADDRESS 16775795fabSBruce Richardson * - PORTS (SRC and DST) 16875795fabSBruce Richardson */ 16975795fabSBruce Richardson enum { 17075795fabSBruce Richardson RTE_ACL_IPV4VLAN_PROTO, 17175795fabSBruce Richardson RTE_ACL_IPV4VLAN_VLAN, 17275795fabSBruce Richardson RTE_ACL_IPV4VLAN_SRC, 17375795fabSBruce Richardson RTE_ACL_IPV4VLAN_DST, 17475795fabSBruce Richardson RTE_ACL_IPV4VLAN_PORTS, 17575795fabSBruce Richardson RTE_ACL_IPV4VLAN_NUM 17675795fabSBruce Richardson }; 17775795fabSBruce Richardson 17875795fabSBruce Richardson struct rte_acl_field_def ipv4_defs[NUM_FIELDS_IPV4] = { 17975795fabSBruce Richardson { 18075795fabSBruce Richardson .type = RTE_ACL_FIELD_TYPE_BITMASK, 18175795fabSBruce Richardson .size = sizeof(uint8_t), 18275795fabSBruce Richardson .field_index = PROTO_FIELD_IPV4, 18375795fabSBruce Richardson .input_index = RTE_ACL_IPV4VLAN_PROTO, 18475795fabSBruce Richardson .offset = offsetof(struct ipv4_5tuple, proto), 18575795fabSBruce Richardson }, 18675795fabSBruce Richardson { 18775795fabSBruce Richardson .type = RTE_ACL_FIELD_TYPE_MASK, 18875795fabSBruce Richardson .size = sizeof(uint32_t), 18975795fabSBruce Richardson .field_index = SRC_FIELD_IPV4, 19075795fabSBruce Richardson .input_index = RTE_ACL_IPV4VLAN_SRC, 19175795fabSBruce Richardson .offset = offsetof(struct ipv4_5tuple, ip_src), 19275795fabSBruce Richardson }, 19375795fabSBruce Richardson { 19475795fabSBruce Richardson .type = RTE_ACL_FIELD_TYPE_MASK, 19575795fabSBruce Richardson .size = sizeof(uint32_t), 19675795fabSBruce Richardson .field_index = DST_FIELD_IPV4, 19775795fabSBruce Richardson .input_index = RTE_ACL_IPV4VLAN_DST, 19875795fabSBruce Richardson .offset = offsetof(struct ipv4_5tuple, ip_dst), 19975795fabSBruce Richardson }, 20075795fabSBruce Richardson { 20175795fabSBruce Richardson .type = RTE_ACL_FIELD_TYPE_RANGE, 20275795fabSBruce Richardson .size = sizeof(uint16_t), 20375795fabSBruce Richardson .field_index = SRCP_FIELD_IPV4, 20475795fabSBruce Richardson .input_index = RTE_ACL_IPV4VLAN_PORTS, 20575795fabSBruce Richardson .offset = offsetof(struct ipv4_5tuple, port_src), 20675795fabSBruce Richardson }, 20775795fabSBruce Richardson { 20875795fabSBruce Richardson .type = RTE_ACL_FIELD_TYPE_RANGE, 20975795fabSBruce Richardson .size = sizeof(uint16_t), 21075795fabSBruce Richardson .field_index = DSTP_FIELD_IPV4, 21175795fabSBruce Richardson .input_index = RTE_ACL_IPV4VLAN_PORTS, 21275795fabSBruce Richardson .offset = offsetof(struct ipv4_5tuple, port_dst), 21375795fabSBruce Richardson }, 21475795fabSBruce Richardson }; 21575795fabSBruce Richardson 21675795fabSBruce Richardson #define IPV6_ADDR_LEN 16 21775795fabSBruce Richardson #define IPV6_ADDR_U16 (IPV6_ADDR_LEN / sizeof(uint16_t)) 21875795fabSBruce Richardson #define IPV6_ADDR_U32 (IPV6_ADDR_LEN / sizeof(uint32_t)) 21960018ef4SKonstantin Ananyev #define IPV6_ADDR_U64 (IPV6_ADDR_LEN / sizeof(uint64_t)) 22075795fabSBruce Richardson 22175795fabSBruce Richardson struct ipv6_5tuple { 22275795fabSBruce Richardson uint8_t proto; 22375795fabSBruce Richardson uint32_t ip_src[IPV6_ADDR_U32]; 22475795fabSBruce Richardson uint32_t ip_dst[IPV6_ADDR_U32]; 22575795fabSBruce Richardson uint16_t port_src; 22675795fabSBruce Richardson uint16_t port_dst; 22775795fabSBruce Richardson }; 22875795fabSBruce Richardson 22960018ef4SKonstantin Ananyev /* treat IPV6 address as uint32_t[4] (default mode) */ 23075795fabSBruce Richardson enum { 23175795fabSBruce Richardson PROTO_FIELD_IPV6, 23275795fabSBruce Richardson SRC1_FIELD_IPV6, 23375795fabSBruce Richardson SRC2_FIELD_IPV6, 23475795fabSBruce Richardson SRC3_FIELD_IPV6, 23575795fabSBruce Richardson SRC4_FIELD_IPV6, 23675795fabSBruce Richardson DST1_FIELD_IPV6, 23775795fabSBruce Richardson DST2_FIELD_IPV6, 23875795fabSBruce Richardson DST3_FIELD_IPV6, 23975795fabSBruce Richardson DST4_FIELD_IPV6, 24075795fabSBruce Richardson SRCP_FIELD_IPV6, 24175795fabSBruce Richardson DSTP_FIELD_IPV6, 24275795fabSBruce Richardson NUM_FIELDS_IPV6 24375795fabSBruce Richardson }; 24475795fabSBruce Richardson 24560018ef4SKonstantin Ananyev /* treat IPV6 address as uint64_t[2] (default mode) */ 24660018ef4SKonstantin Ananyev enum { 24760018ef4SKonstantin Ananyev PROTO_FIELD_IPV6_U64, 24860018ef4SKonstantin Ananyev SRC1_FIELD_IPV6_U64, 24960018ef4SKonstantin Ananyev SRC2_FIELD_IPV6_U64, 25060018ef4SKonstantin Ananyev DST1_FIELD_IPV6_U64, 25160018ef4SKonstantin Ananyev DST2_FIELD_IPV6_U64, 25260018ef4SKonstantin Ananyev SRCP_FIELD_IPV6_U64, 25360018ef4SKonstantin Ananyev DSTP_FIELD_IPV6_U64, 25460018ef4SKonstantin Ananyev NUM_FIELDS_IPV6_U64 25560018ef4SKonstantin Ananyev }; 25660018ef4SKonstantin Ananyev 25760018ef4SKonstantin Ananyev enum { 25860018ef4SKonstantin Ananyev PROTO_INDEX_IPV6_U64 = PROTO_FIELD_IPV6_U64, 25960018ef4SKonstantin Ananyev SRC1_INDEX_IPV6_U64 = SRC1_FIELD_IPV6_U64, 26060018ef4SKonstantin Ananyev SRC2_INDEX_IPV6_U64 = SRC2_FIELD_IPV6_U64 + 1, 26160018ef4SKonstantin Ananyev DST1_INDEX_IPV6_U64 = DST1_FIELD_IPV6_U64 + 2, 26260018ef4SKonstantin Ananyev DST2_INDEX_IPV6_U64 = DST2_FIELD_IPV6_U64 + 3, 26360018ef4SKonstantin Ananyev PRT_INDEX_IPV6_U64 = SRCP_FIELD_IPV6 + 4, 26460018ef4SKonstantin Ananyev }; 26560018ef4SKonstantin Ananyev 26675795fabSBruce Richardson struct rte_acl_field_def ipv6_defs[NUM_FIELDS_IPV6] = { 26775795fabSBruce Richardson { 26875795fabSBruce Richardson .type = RTE_ACL_FIELD_TYPE_BITMASK, 26975795fabSBruce Richardson .size = sizeof(uint8_t), 27075795fabSBruce Richardson .field_index = PROTO_FIELD_IPV6, 27175795fabSBruce Richardson .input_index = PROTO_FIELD_IPV6, 27275795fabSBruce Richardson .offset = offsetof(struct ipv6_5tuple, proto), 27375795fabSBruce Richardson }, 27475795fabSBruce Richardson { 27575795fabSBruce Richardson .type = RTE_ACL_FIELD_TYPE_MASK, 27675795fabSBruce Richardson .size = sizeof(uint32_t), 27775795fabSBruce Richardson .field_index = SRC1_FIELD_IPV6, 27875795fabSBruce Richardson .input_index = SRC1_FIELD_IPV6, 27975795fabSBruce Richardson .offset = offsetof(struct ipv6_5tuple, ip_src[0]), 28075795fabSBruce Richardson }, 28175795fabSBruce Richardson { 28275795fabSBruce Richardson .type = RTE_ACL_FIELD_TYPE_MASK, 28375795fabSBruce Richardson .size = sizeof(uint32_t), 28475795fabSBruce Richardson .field_index = SRC2_FIELD_IPV6, 28575795fabSBruce Richardson .input_index = SRC2_FIELD_IPV6, 28675795fabSBruce Richardson .offset = offsetof(struct ipv6_5tuple, ip_src[1]), 28775795fabSBruce Richardson }, 28875795fabSBruce Richardson { 28975795fabSBruce Richardson .type = RTE_ACL_FIELD_TYPE_MASK, 29075795fabSBruce Richardson .size = sizeof(uint32_t), 29175795fabSBruce Richardson .field_index = SRC3_FIELD_IPV6, 29275795fabSBruce Richardson .input_index = SRC3_FIELD_IPV6, 29375795fabSBruce Richardson .offset = offsetof(struct ipv6_5tuple, ip_src[2]), 29475795fabSBruce Richardson }, 29575795fabSBruce Richardson { 29675795fabSBruce Richardson .type = RTE_ACL_FIELD_TYPE_MASK, 29775795fabSBruce Richardson .size = sizeof(uint32_t), 29875795fabSBruce Richardson .field_index = SRC4_FIELD_IPV6, 29975795fabSBruce Richardson .input_index = SRC4_FIELD_IPV6, 30075795fabSBruce Richardson .offset = offsetof(struct ipv6_5tuple, ip_src[3]), 30175795fabSBruce Richardson }, 30275795fabSBruce Richardson { 30375795fabSBruce Richardson .type = RTE_ACL_FIELD_TYPE_MASK, 30475795fabSBruce Richardson .size = sizeof(uint32_t), 30575795fabSBruce Richardson .field_index = DST1_FIELD_IPV6, 30675795fabSBruce Richardson .input_index = DST1_FIELD_IPV6, 30775795fabSBruce Richardson .offset = offsetof(struct ipv6_5tuple, ip_dst[0]), 30875795fabSBruce Richardson }, 30975795fabSBruce Richardson { 31075795fabSBruce Richardson .type = RTE_ACL_FIELD_TYPE_MASK, 31175795fabSBruce Richardson .size = sizeof(uint32_t), 31275795fabSBruce Richardson .field_index = DST2_FIELD_IPV6, 31375795fabSBruce Richardson .input_index = DST2_FIELD_IPV6, 31475795fabSBruce Richardson .offset = offsetof(struct ipv6_5tuple, ip_dst[1]), 31575795fabSBruce Richardson }, 31675795fabSBruce Richardson { 31775795fabSBruce Richardson .type = RTE_ACL_FIELD_TYPE_MASK, 31875795fabSBruce Richardson .size = sizeof(uint32_t), 31975795fabSBruce Richardson .field_index = DST3_FIELD_IPV6, 32075795fabSBruce Richardson .input_index = DST3_FIELD_IPV6, 32175795fabSBruce Richardson .offset = offsetof(struct ipv6_5tuple, ip_dst[2]), 32275795fabSBruce Richardson }, 32375795fabSBruce Richardson { 32475795fabSBruce Richardson .type = RTE_ACL_FIELD_TYPE_MASK, 32575795fabSBruce Richardson .size = sizeof(uint32_t), 32675795fabSBruce Richardson .field_index = DST4_FIELD_IPV6, 32775795fabSBruce Richardson .input_index = DST4_FIELD_IPV6, 32875795fabSBruce Richardson .offset = offsetof(struct ipv6_5tuple, ip_dst[3]), 32975795fabSBruce Richardson }, 33075795fabSBruce Richardson { 33175795fabSBruce Richardson .type = RTE_ACL_FIELD_TYPE_RANGE, 33275795fabSBruce Richardson .size = sizeof(uint16_t), 33375795fabSBruce Richardson .field_index = SRCP_FIELD_IPV6, 33475795fabSBruce Richardson .input_index = SRCP_FIELD_IPV6, 33575795fabSBruce Richardson .offset = offsetof(struct ipv6_5tuple, port_src), 33675795fabSBruce Richardson }, 33775795fabSBruce Richardson { 33875795fabSBruce Richardson .type = RTE_ACL_FIELD_TYPE_RANGE, 33975795fabSBruce Richardson .size = sizeof(uint16_t), 34075795fabSBruce Richardson .field_index = DSTP_FIELD_IPV6, 34175795fabSBruce Richardson .input_index = SRCP_FIELD_IPV6, 34275795fabSBruce Richardson .offset = offsetof(struct ipv6_5tuple, port_dst), 34375795fabSBruce Richardson }, 34475795fabSBruce Richardson }; 34575795fabSBruce Richardson 34660018ef4SKonstantin Ananyev struct rte_acl_field_def ipv6_u64_defs[NUM_FIELDS_IPV6_U64] = { 34760018ef4SKonstantin Ananyev { 34860018ef4SKonstantin Ananyev .type = RTE_ACL_FIELD_TYPE_BITMASK, 34960018ef4SKonstantin Ananyev .size = sizeof(uint8_t), 35060018ef4SKonstantin Ananyev .field_index = PROTO_FIELD_IPV6_U64, 35160018ef4SKonstantin Ananyev .input_index = PROTO_FIELD_IPV6_U64, 35260018ef4SKonstantin Ananyev .offset = offsetof(struct ipv6_5tuple, proto), 35360018ef4SKonstantin Ananyev }, 35460018ef4SKonstantin Ananyev { 35560018ef4SKonstantin Ananyev .type = RTE_ACL_FIELD_TYPE_MASK, 35660018ef4SKonstantin Ananyev .size = sizeof(uint64_t), 35760018ef4SKonstantin Ananyev .field_index = SRC1_FIELD_IPV6_U64, 35860018ef4SKonstantin Ananyev .input_index = SRC1_INDEX_IPV6_U64, 35960018ef4SKonstantin Ananyev .offset = offsetof(struct ipv6_5tuple, ip_src[0]), 36060018ef4SKonstantin Ananyev }, 36160018ef4SKonstantin Ananyev { 36260018ef4SKonstantin Ananyev .type = RTE_ACL_FIELD_TYPE_MASK, 36360018ef4SKonstantin Ananyev .size = sizeof(uint64_t), 36460018ef4SKonstantin Ananyev .field_index = SRC2_FIELD_IPV6_U64, 36560018ef4SKonstantin Ananyev .input_index = SRC2_INDEX_IPV6_U64, 36660018ef4SKonstantin Ananyev .offset = offsetof(struct ipv6_5tuple, ip_src[2]), 36760018ef4SKonstantin Ananyev }, 36860018ef4SKonstantin Ananyev { 36960018ef4SKonstantin Ananyev .type = RTE_ACL_FIELD_TYPE_MASK, 37060018ef4SKonstantin Ananyev .size = sizeof(uint64_t), 37160018ef4SKonstantin Ananyev .field_index = DST1_FIELD_IPV6_U64, 37260018ef4SKonstantin Ananyev .input_index = DST1_INDEX_IPV6_U64, 37360018ef4SKonstantin Ananyev .offset = offsetof(struct ipv6_5tuple, ip_dst[0]), 37460018ef4SKonstantin Ananyev }, 37560018ef4SKonstantin Ananyev { 37660018ef4SKonstantin Ananyev .type = RTE_ACL_FIELD_TYPE_MASK, 37760018ef4SKonstantin Ananyev .size = sizeof(uint64_t), 37860018ef4SKonstantin Ananyev .field_index = DST2_FIELD_IPV6_U64, 37960018ef4SKonstantin Ananyev .input_index = DST2_INDEX_IPV6_U64, 38060018ef4SKonstantin Ananyev .offset = offsetof(struct ipv6_5tuple, ip_dst[2]), 38160018ef4SKonstantin Ananyev }, 38260018ef4SKonstantin Ananyev { 38360018ef4SKonstantin Ananyev .type = RTE_ACL_FIELD_TYPE_RANGE, 38460018ef4SKonstantin Ananyev .size = sizeof(uint16_t), 38560018ef4SKonstantin Ananyev .field_index = SRCP_FIELD_IPV6_U64, 38660018ef4SKonstantin Ananyev .input_index = PRT_INDEX_IPV6_U64, 38760018ef4SKonstantin Ananyev .offset = offsetof(struct ipv6_5tuple, port_src), 38860018ef4SKonstantin Ananyev }, 38960018ef4SKonstantin Ananyev { 39060018ef4SKonstantin Ananyev .type = RTE_ACL_FIELD_TYPE_RANGE, 39160018ef4SKonstantin Ananyev .size = sizeof(uint16_t), 39260018ef4SKonstantin Ananyev .field_index = DSTP_FIELD_IPV6_U64, 39360018ef4SKonstantin Ananyev .input_index = PRT_INDEX_IPV6_U64, 39460018ef4SKonstantin Ananyev .offset = offsetof(struct ipv6_5tuple, port_dst), 39560018ef4SKonstantin Ananyev }, 39660018ef4SKonstantin Ananyev }; 39775795fabSBruce Richardson 39875795fabSBruce Richardson enum { 39975795fabSBruce Richardson CB_FLD_SRC_ADDR, 40075795fabSBruce Richardson CB_FLD_DST_ADDR, 40175795fabSBruce Richardson CB_FLD_SRC_PORT_LOW, 40275795fabSBruce Richardson CB_FLD_SRC_PORT_DLM, 40375795fabSBruce Richardson CB_FLD_SRC_PORT_HIGH, 40475795fabSBruce Richardson CB_FLD_DST_PORT_LOW, 40575795fabSBruce Richardson CB_FLD_DST_PORT_DLM, 40675795fabSBruce Richardson CB_FLD_DST_PORT_HIGH, 40775795fabSBruce Richardson CB_FLD_PROTO, 40875795fabSBruce Richardson CB_FLD_NUM, 40975795fabSBruce Richardson }; 41075795fabSBruce Richardson 41175795fabSBruce Richardson enum { 41275795fabSBruce Richardson CB_TRC_SRC_ADDR, 41375795fabSBruce Richardson CB_TRC_DST_ADDR, 41475795fabSBruce Richardson CB_TRC_SRC_PORT, 41575795fabSBruce Richardson CB_TRC_DST_PORT, 41675795fabSBruce Richardson CB_TRC_PROTO, 41775795fabSBruce Richardson CB_TRC_NUM, 41875795fabSBruce Richardson }; 41975795fabSBruce Richardson 42075795fabSBruce Richardson RTE_ACL_RULE_DEF(acl_rule, RTE_ACL_MAX_FIELDS); 42175795fabSBruce Richardson 42275795fabSBruce Richardson static const char cb_port_delim[] = ":"; 42375795fabSBruce Richardson 42475795fabSBruce Richardson static char line[LINE_MAX]; 42575795fabSBruce Richardson 426*f7c9651cSAndre Muezerie #define dump_verbose(lvl, fh, fmt, ...) do { \ 42775795fabSBruce Richardson if ((lvl) <= (int32_t)config.verbose) \ 428*f7c9651cSAndre Muezerie fprintf(fh, fmt, ##__VA_ARGS__); \ 42975795fabSBruce Richardson } while (0) 43075795fabSBruce Richardson 43175795fabSBruce Richardson 43275795fabSBruce Richardson /* 43375795fabSBruce Richardson * Parse ClassBench input trace (test vectors and expected results) file. 43475795fabSBruce Richardson * Expected format: 43575795fabSBruce Richardson * <src_ipv4_addr> <space> <dst_ipv4_addr> <space> \ 43675795fabSBruce Richardson * <src_port> <space> <dst_port> <space> <proto> 43775795fabSBruce Richardson */ 43875795fabSBruce Richardson static int 43975795fabSBruce Richardson parse_cb_ipv4_trace(char *str, struct ipv4_5tuple *v) 44075795fabSBruce Richardson { 44175795fabSBruce Richardson int i; 44275795fabSBruce Richardson char *s, *sp, *in[CB_TRC_NUM]; 44375795fabSBruce Richardson static const char *dlm = " \t\n"; 44475795fabSBruce Richardson 44575795fabSBruce Richardson s = str; 44675795fabSBruce Richardson for (i = 0; i != RTE_DIM(in); i++) { 44775795fabSBruce Richardson in[i] = strtok_r(s, dlm, &sp); 44875795fabSBruce Richardson if (in[i] == NULL) 44975795fabSBruce Richardson return -EINVAL; 45075795fabSBruce Richardson s = NULL; 45175795fabSBruce Richardson } 45275795fabSBruce Richardson 45375795fabSBruce Richardson GET_CB_FIELD(in[CB_TRC_SRC_ADDR], v->ip_src, 0, UINT32_MAX, 0); 45475795fabSBruce Richardson GET_CB_FIELD(in[CB_TRC_DST_ADDR], v->ip_dst, 0, UINT32_MAX, 0); 45575795fabSBruce Richardson GET_CB_FIELD(in[CB_TRC_SRC_PORT], v->port_src, 0, UINT16_MAX, 0); 45675795fabSBruce Richardson GET_CB_FIELD(in[CB_TRC_DST_PORT], v->port_dst, 0, UINT16_MAX, 0); 45775795fabSBruce Richardson GET_CB_FIELD(in[CB_TRC_PROTO], v->proto, 0, UINT8_MAX, 0); 45875795fabSBruce Richardson 45975795fabSBruce Richardson /* convert to network byte order. */ 46075795fabSBruce Richardson v->ip_src = rte_cpu_to_be_32(v->ip_src); 46175795fabSBruce Richardson v->ip_dst = rte_cpu_to_be_32(v->ip_dst); 46275795fabSBruce Richardson v->port_src = rte_cpu_to_be_16(v->port_src); 46375795fabSBruce Richardson v->port_dst = rte_cpu_to_be_16(v->port_dst); 46475795fabSBruce Richardson 46575795fabSBruce Richardson return 0; 46675795fabSBruce Richardson } 46775795fabSBruce Richardson 46875795fabSBruce Richardson static int 46975795fabSBruce Richardson parse_cb_ipv6_addr_trace(const char *in, uint32_t v[IPV6_ADDR_U32]) 47075795fabSBruce Richardson { 47160018ef4SKonstantin Ananyev if (inet_pton(AF_INET6, in, v) != 1) 47260018ef4SKonstantin Ananyev return -EINVAL; 47375795fabSBruce Richardson 47475795fabSBruce Richardson return 0; 47575795fabSBruce Richardson } 47675795fabSBruce Richardson 47775795fabSBruce Richardson /* 47875795fabSBruce Richardson * Parse ClassBench input trace (test vectors and expected results) file. 47975795fabSBruce Richardson * Expected format: 48075795fabSBruce Richardson * <src_ipv6_addr> <space> <dst_ipv6_addr> <space> \ 48175795fabSBruce Richardson * <src_port> <space> <dst_port> <space> <proto> 48275795fabSBruce Richardson */ 48375795fabSBruce Richardson static int 48475795fabSBruce Richardson parse_cb_ipv6_trace(char *str, struct ipv6_5tuple *v) 48575795fabSBruce Richardson { 48675795fabSBruce Richardson int32_t i, rc; 48775795fabSBruce Richardson char *s, *sp, *in[CB_TRC_NUM]; 48875795fabSBruce Richardson static const char *dlm = " \t\n"; 48975795fabSBruce Richardson 49075795fabSBruce Richardson s = str; 49175795fabSBruce Richardson for (i = 0; i != RTE_DIM(in); i++) { 49275795fabSBruce Richardson in[i] = strtok_r(s, dlm, &sp); 49375795fabSBruce Richardson if (in[i] == NULL) 49475795fabSBruce Richardson return -EINVAL; 49575795fabSBruce Richardson s = NULL; 49675795fabSBruce Richardson } 49775795fabSBruce Richardson 49875795fabSBruce Richardson /* get ip6 src address. */ 49975795fabSBruce Richardson rc = parse_cb_ipv6_addr_trace(in[CB_TRC_SRC_ADDR], v->ip_src); 50075795fabSBruce Richardson if (rc != 0) 50175795fabSBruce Richardson return rc; 50275795fabSBruce Richardson 50375795fabSBruce Richardson /* get ip6 dst address. */ 50475795fabSBruce Richardson rc = parse_cb_ipv6_addr_trace(in[CB_TRC_DST_ADDR], v->ip_dst); 50575795fabSBruce Richardson if (rc != 0) 50675795fabSBruce Richardson return rc; 50775795fabSBruce Richardson 50875795fabSBruce Richardson GET_CB_FIELD(in[CB_TRC_SRC_PORT], v->port_src, 0, UINT16_MAX, 0); 50975795fabSBruce Richardson GET_CB_FIELD(in[CB_TRC_DST_PORT], v->port_dst, 0, UINT16_MAX, 0); 51075795fabSBruce Richardson GET_CB_FIELD(in[CB_TRC_PROTO], v->proto, 0, UINT8_MAX, 0); 51175795fabSBruce Richardson 51275795fabSBruce Richardson /* convert to network byte order. */ 51375795fabSBruce Richardson v->port_src = rte_cpu_to_be_16(v->port_src); 51475795fabSBruce Richardson v->port_dst = rte_cpu_to_be_16(v->port_dst); 51575795fabSBruce Richardson 51675795fabSBruce Richardson return 0; 51775795fabSBruce Richardson } 51875795fabSBruce Richardson 519ca2183d3SKonstantin Ananyev /* Bypass comment and empty lines */ 520ca2183d3SKonstantin Ananyev static int 521ca2183d3SKonstantin Ananyev skip_line(const char *buf) 522ca2183d3SKonstantin Ananyev { 523ca2183d3SKonstantin Ananyev uint32_t i; 524ca2183d3SKonstantin Ananyev 525ca2183d3SKonstantin Ananyev for (i = 0; isspace(buf[i]) != 0; i++) 526ca2183d3SKonstantin Ananyev ; 527ca2183d3SKonstantin Ananyev 528ca2183d3SKonstantin Ananyev if (buf[i] == 0 || buf[i] == COMMENT_LEAD_CHAR) 529ca2183d3SKonstantin Ananyev return 1; 530ca2183d3SKonstantin Ananyev 531ca2183d3SKonstantin Ananyev return 0; 532ca2183d3SKonstantin Ananyev } 533ca2183d3SKonstantin Ananyev 53475795fabSBruce Richardson static void 53575795fabSBruce Richardson tracef_init(void) 53675795fabSBruce Richardson { 53775795fabSBruce Richardson static const char name[] = APP_NAME; 53875795fabSBruce Richardson FILE *f; 53975795fabSBruce Richardson size_t sz; 540ca2183d3SKonstantin Ananyev uint32_t i, k, n; 54175795fabSBruce Richardson struct ipv4_5tuple *v; 54275795fabSBruce Richardson struct ipv6_5tuple *w; 54375795fabSBruce Richardson 54475795fabSBruce Richardson sz = config.nb_traces * (config.ipv6 ? sizeof(*w) : sizeof(*v)); 54575795fabSBruce Richardson config.traces = rte_zmalloc_socket(name, sz, RTE_CACHE_LINE_SIZE, 54675795fabSBruce Richardson SOCKET_ID_ANY); 54775795fabSBruce Richardson if (config.traces == NULL) 54875795fabSBruce Richardson rte_exit(EXIT_FAILURE, "Cannot allocate %zu bytes for " 54975795fabSBruce Richardson "requested %u number of trace records\n", 55075795fabSBruce Richardson sz, config.nb_traces); 55175795fabSBruce Richardson 55275795fabSBruce Richardson f = fopen(config.trace_file, "r"); 55375795fabSBruce Richardson if (f == NULL) 55475795fabSBruce Richardson rte_exit(-EINVAL, "failed to open file: %s\n", 55575795fabSBruce Richardson config.trace_file); 55675795fabSBruce Richardson 55775795fabSBruce Richardson v = config.traces; 55875795fabSBruce Richardson w = config.traces; 559ca2183d3SKonstantin Ananyev k = 0; 560ca2183d3SKonstantin Ananyev n = 0; 561ca2183d3SKonstantin Ananyev for (i = 0; n != config.nb_traces; i++) { 56275795fabSBruce Richardson 56375795fabSBruce Richardson if (fgets(line, sizeof(line), f) == NULL) 56475795fabSBruce Richardson break; 56575795fabSBruce Richardson 566ca2183d3SKonstantin Ananyev if (skip_line(line) != 0) { 567ca2183d3SKonstantin Ananyev k++; 568ca2183d3SKonstantin Ananyev continue; 569ca2183d3SKonstantin Ananyev } 570ca2183d3SKonstantin Ananyev 571ca2183d3SKonstantin Ananyev n = i - k; 572ca2183d3SKonstantin Ananyev 57375795fabSBruce Richardson if (config.ipv6) { 57475795fabSBruce Richardson if (parse_cb_ipv6_trace(line, w + n) != 0) 57575795fabSBruce Richardson rte_exit(EXIT_FAILURE, 57675795fabSBruce Richardson "%s: failed to parse ipv6 trace " 57775795fabSBruce Richardson "record at line %u\n", 578ca2183d3SKonstantin Ananyev config.trace_file, i + 1); 57975795fabSBruce Richardson } else { 58075795fabSBruce Richardson if (parse_cb_ipv4_trace(line, v + n) != 0) 58175795fabSBruce Richardson rte_exit(EXIT_FAILURE, 58275795fabSBruce Richardson "%s: failed to parse ipv4 trace " 58375795fabSBruce Richardson "record at line %u\n", 584ca2183d3SKonstantin Ananyev config.trace_file, i + 1); 58575795fabSBruce Richardson } 58675795fabSBruce Richardson } 58775795fabSBruce Richardson 588ca2183d3SKonstantin Ananyev config.used_traces = i - k; 58975795fabSBruce Richardson fclose(f); 59075795fabSBruce Richardson } 59175795fabSBruce Richardson 59275795fabSBruce Richardson static int 59360018ef4SKonstantin Ananyev parse_ipv6_u32_net(char *in, struct rte_acl_field field[IPV6_ADDR_U32]) 59475795fabSBruce Richardson { 59560018ef4SKonstantin Ananyev char *sa, *sm, *sv; 59660018ef4SKonstantin Ananyev uint32_t i, m, v[IPV6_ADDR_U32]; 59760018ef4SKonstantin Ananyev 59860018ef4SKonstantin Ananyev const char *dlm = "/"; 59975795fabSBruce Richardson const uint32_t nbu32 = sizeof(uint32_t) * CHAR_BIT; 60075795fabSBruce Richardson 60175795fabSBruce Richardson /* get address. */ 60260018ef4SKonstantin Ananyev sv = NULL; 60360018ef4SKonstantin Ananyev sa = strtok_r(in, dlm, &sv); 60460018ef4SKonstantin Ananyev if (sa == NULL) 60560018ef4SKonstantin Ananyev return -EINVAL; 60660018ef4SKonstantin Ananyev sm = strtok_r(NULL, dlm, &sv); 60760018ef4SKonstantin Ananyev if (sm == NULL) 60860018ef4SKonstantin Ananyev return -EINVAL; 60960018ef4SKonstantin Ananyev 61060018ef4SKonstantin Ananyev if (inet_pton(AF_INET6, sa, v) != 1) 61160018ef4SKonstantin Ananyev return -EINVAL; 61260018ef4SKonstantin Ananyev 61360018ef4SKonstantin Ananyev v[0] = rte_be_to_cpu_32(v[0]); 61460018ef4SKonstantin Ananyev v[1] = rte_be_to_cpu_32(v[1]); 61560018ef4SKonstantin Ananyev v[2] = rte_be_to_cpu_32(v[2]); 61660018ef4SKonstantin Ananyev v[3] = rte_be_to_cpu_32(v[3]); 61775795fabSBruce Richardson 61875795fabSBruce Richardson /* get mask. */ 61960018ef4SKonstantin Ananyev GET_CB_FIELD(sm, m, 0, CHAR_BIT * sizeof(v), 0); 62075795fabSBruce Richardson 62175795fabSBruce Richardson /* put all together. */ 62275795fabSBruce Richardson for (i = 0; i != RTE_DIM(v); i++) { 62375795fabSBruce Richardson if (m >= (i + 1) * nbu32) 62475795fabSBruce Richardson field[i].mask_range.u32 = nbu32; 62575795fabSBruce Richardson else 62675795fabSBruce Richardson field[i].mask_range.u32 = m > (i * nbu32) ? 62760018ef4SKonstantin Ananyev m - (i * nbu32) : 0; 62875795fabSBruce Richardson 62975795fabSBruce Richardson field[i].value.u32 = v[i]; 63075795fabSBruce Richardson } 63175795fabSBruce Richardson 63275795fabSBruce Richardson return 0; 63375795fabSBruce Richardson } 63475795fabSBruce Richardson 63560018ef4SKonstantin Ananyev static int 63660018ef4SKonstantin Ananyev parse_ipv6_u64_net(char *in, struct rte_acl_field field[IPV6_ADDR_U64]) 63760018ef4SKonstantin Ananyev { 63860018ef4SKonstantin Ananyev char *sa, *sm, *sv; 63960018ef4SKonstantin Ananyev uint32_t i, m; 64060018ef4SKonstantin Ananyev uint64_t v[IPV6_ADDR_U64]; 64160018ef4SKonstantin Ananyev 64260018ef4SKonstantin Ananyev const char *dlm = "/"; 64360018ef4SKonstantin Ananyev const uint32_t nbu64 = sizeof(uint64_t) * CHAR_BIT; 64460018ef4SKonstantin Ananyev 64560018ef4SKonstantin Ananyev /* get address. */ 64660018ef4SKonstantin Ananyev sv = NULL; 64760018ef4SKonstantin Ananyev sa = strtok_r(in, dlm, &sv); 64860018ef4SKonstantin Ananyev if (sa == NULL) 64960018ef4SKonstantin Ananyev return -EINVAL; 65060018ef4SKonstantin Ananyev sm = strtok_r(NULL, dlm, &sv); 65160018ef4SKonstantin Ananyev if (sm == NULL) 65260018ef4SKonstantin Ananyev return -EINVAL; 65360018ef4SKonstantin Ananyev 65460018ef4SKonstantin Ananyev if (inet_pton(AF_INET6, sa, v) != 1) 65560018ef4SKonstantin Ananyev return -EINVAL; 65660018ef4SKonstantin Ananyev 65760018ef4SKonstantin Ananyev v[0] = rte_be_to_cpu_64(v[0]); 65860018ef4SKonstantin Ananyev v[1] = rte_be_to_cpu_64(v[1]); 65960018ef4SKonstantin Ananyev 66060018ef4SKonstantin Ananyev /* get mask. */ 66160018ef4SKonstantin Ananyev GET_CB_FIELD(sm, m, 0, CHAR_BIT * sizeof(v), 0); 66260018ef4SKonstantin Ananyev 66360018ef4SKonstantin Ananyev /* put all together. */ 66460018ef4SKonstantin Ananyev for (i = 0; i != RTE_DIM(v); i++) { 66560018ef4SKonstantin Ananyev if (m >= (i + 1) * nbu64) 66660018ef4SKonstantin Ananyev field[i].mask_range.u32 = nbu64; 66760018ef4SKonstantin Ananyev else 66860018ef4SKonstantin Ananyev field[i].mask_range.u32 = m > (i * nbu64) ? 66960018ef4SKonstantin Ananyev m - (i * nbu64) : 0; 67060018ef4SKonstantin Ananyev 67160018ef4SKonstantin Ananyev field[i].value.u64 = v[i]; 67260018ef4SKonstantin Ananyev } 67360018ef4SKonstantin Ananyev 67460018ef4SKonstantin Ananyev return 0; 67560018ef4SKonstantin Ananyev } 67675795fabSBruce Richardson 67775795fabSBruce Richardson static int 67860018ef4SKonstantin Ananyev parse_cb_ipv6_rule(char *str, struct acl_rule *v, int frmt) 67975795fabSBruce Richardson { 68075795fabSBruce Richardson int i, rc; 68160018ef4SKonstantin Ananyev uint32_t fidx; 68260018ef4SKonstantin Ananyev const uint32_t *field_map; 68375795fabSBruce Richardson char *s, *sp, *in[CB_FLD_NUM]; 68460018ef4SKonstantin Ananyev int (*parse_ipv6_net)(char *s, struct rte_acl_field f[]); 68560018ef4SKonstantin Ananyev 68675795fabSBruce Richardson static const char *dlm = " \t\n"; 68775795fabSBruce Richardson 68860018ef4SKonstantin Ananyev static const uint32_t field_map_u32[CB_FLD_NUM] = { 68960018ef4SKonstantin Ananyev [CB_FLD_SRC_ADDR] = SRC1_FIELD_IPV6, 69060018ef4SKonstantin Ananyev [CB_FLD_DST_ADDR] = DST1_FIELD_IPV6, 69160018ef4SKonstantin Ananyev [CB_FLD_SRC_PORT_LOW] = SRCP_FIELD_IPV6, 69260018ef4SKonstantin Ananyev [CB_FLD_SRC_PORT_HIGH] = SRCP_FIELD_IPV6, 69360018ef4SKonstantin Ananyev [CB_FLD_DST_PORT_LOW] = DSTP_FIELD_IPV6, 69460018ef4SKonstantin Ananyev [CB_FLD_DST_PORT_HIGH] = DSTP_FIELD_IPV6, 69560018ef4SKonstantin Ananyev [CB_FLD_PROTO] = PROTO_FIELD_IPV6, 69660018ef4SKonstantin Ananyev }; 69760018ef4SKonstantin Ananyev 69860018ef4SKonstantin Ananyev static const uint32_t field_map_u64[CB_FLD_NUM] = { 69960018ef4SKonstantin Ananyev [CB_FLD_SRC_ADDR] = SRC1_FIELD_IPV6_U64, 70060018ef4SKonstantin Ananyev [CB_FLD_DST_ADDR] = DST1_FIELD_IPV6_U64, 70160018ef4SKonstantin Ananyev [CB_FLD_SRC_PORT_LOW] = SRCP_FIELD_IPV6_U64, 70260018ef4SKonstantin Ananyev [CB_FLD_SRC_PORT_HIGH] = SRCP_FIELD_IPV6_U64, 70360018ef4SKonstantin Ananyev [CB_FLD_DST_PORT_LOW] = DSTP_FIELD_IPV6_U64, 70460018ef4SKonstantin Ananyev [CB_FLD_DST_PORT_HIGH] = DSTP_FIELD_IPV6_U64, 70560018ef4SKonstantin Ananyev [CB_FLD_PROTO] = PROTO_FIELD_IPV6_U64, 70660018ef4SKonstantin Ananyev }; 70760018ef4SKonstantin Ananyev 70860018ef4SKonstantin Ananyev if (frmt == IPV6_FRMT_U32) { 70960018ef4SKonstantin Ananyev field_map = field_map_u32; 71060018ef4SKonstantin Ananyev parse_ipv6_net = parse_ipv6_u32_net; 71160018ef4SKonstantin Ananyev } else if (frmt == IPV6_FRMT_U64) { 71260018ef4SKonstantin Ananyev field_map = field_map_u64; 71360018ef4SKonstantin Ananyev parse_ipv6_net = parse_ipv6_u64_net; 71460018ef4SKonstantin Ananyev } else 71560018ef4SKonstantin Ananyev return -ENOTSUP; 71660018ef4SKonstantin Ananyev 71775795fabSBruce Richardson /* 71875795fabSBruce Richardson * Skip leading '@' 71975795fabSBruce Richardson */ 72075795fabSBruce Richardson if (strchr(str, '@') != str) 72175795fabSBruce Richardson return -EINVAL; 72275795fabSBruce Richardson 72375795fabSBruce Richardson s = str + 1; 72475795fabSBruce Richardson 72575795fabSBruce Richardson for (i = 0; i != RTE_DIM(in); i++) { 72675795fabSBruce Richardson in[i] = strtok_r(s, dlm, &sp); 72775795fabSBruce Richardson if (in[i] == NULL) 72875795fabSBruce Richardson return -EINVAL; 72975795fabSBruce Richardson s = NULL; 73075795fabSBruce Richardson } 73175795fabSBruce Richardson 73260018ef4SKonstantin Ananyev fidx = CB_FLD_SRC_ADDR; 73360018ef4SKonstantin Ananyev rc = parse_ipv6_net(in[fidx], v->field + field_map[fidx]); 73475795fabSBruce Richardson if (rc != 0) { 73575795fabSBruce Richardson RTE_LOG(ERR, TESTACL, 73660018ef4SKonstantin Ananyev "failed to read source address/mask: %s\n", in[fidx]); 73775795fabSBruce Richardson return rc; 73875795fabSBruce Richardson } 73975795fabSBruce Richardson 74060018ef4SKonstantin Ananyev fidx = CB_FLD_DST_ADDR; 74160018ef4SKonstantin Ananyev rc = parse_ipv6_net(in[fidx], v->field + field_map[fidx]); 74275795fabSBruce Richardson if (rc != 0) { 74375795fabSBruce Richardson RTE_LOG(ERR, TESTACL, 74475795fabSBruce Richardson "failed to read destination address/mask: %s\n", 74560018ef4SKonstantin Ananyev in[fidx]); 74675795fabSBruce Richardson return rc; 74775795fabSBruce Richardson } 74875795fabSBruce Richardson 74975795fabSBruce Richardson /* source port. */ 75060018ef4SKonstantin Ananyev fidx = CB_FLD_SRC_PORT_LOW; 75160018ef4SKonstantin Ananyev GET_CB_FIELD(in[fidx], v->field[field_map[fidx]].value.u16, 75275795fabSBruce Richardson 0, UINT16_MAX, 0); 75360018ef4SKonstantin Ananyev 75460018ef4SKonstantin Ananyev fidx = CB_FLD_SRC_PORT_HIGH; 75560018ef4SKonstantin Ananyev GET_CB_FIELD(in[fidx], v->field[field_map[fidx]].mask_range.u16, 75675795fabSBruce Richardson 0, UINT16_MAX, 0); 75775795fabSBruce Richardson 75875795fabSBruce Richardson if (strncmp(in[CB_FLD_SRC_PORT_DLM], cb_port_delim, 75975795fabSBruce Richardson sizeof(cb_port_delim)) != 0) 76075795fabSBruce Richardson return -EINVAL; 76175795fabSBruce Richardson 76275795fabSBruce Richardson /* destination port. */ 76360018ef4SKonstantin Ananyev fidx = CB_FLD_DST_PORT_LOW; 76460018ef4SKonstantin Ananyev GET_CB_FIELD(in[fidx], v->field[field_map[fidx]].value.u16, 76575795fabSBruce Richardson 0, UINT16_MAX, 0); 76660018ef4SKonstantin Ananyev 76760018ef4SKonstantin Ananyev fidx = CB_FLD_DST_PORT_HIGH; 76860018ef4SKonstantin Ananyev GET_CB_FIELD(in[fidx], v->field[field_map[fidx]].mask_range.u16, 76975795fabSBruce Richardson 0, UINT16_MAX, 0); 77075795fabSBruce Richardson 77175795fabSBruce Richardson if (strncmp(in[CB_FLD_DST_PORT_DLM], cb_port_delim, 77275795fabSBruce Richardson sizeof(cb_port_delim)) != 0) 77375795fabSBruce Richardson return -EINVAL; 77475795fabSBruce Richardson 77560018ef4SKonstantin Ananyev fidx = CB_FLD_PROTO; 77660018ef4SKonstantin Ananyev GET_CB_FIELD(in[fidx], v->field[field_map[fidx]].value.u8, 77775795fabSBruce Richardson 0, UINT8_MAX, '/'); 77860018ef4SKonstantin Ananyev GET_CB_FIELD(in[fidx], v->field[field_map[fidx]].mask_range.u8, 77975795fabSBruce Richardson 0, UINT8_MAX, 0); 78075795fabSBruce Richardson 78175795fabSBruce Richardson return 0; 78275795fabSBruce Richardson } 78375795fabSBruce Richardson 78475795fabSBruce Richardson static int 78560018ef4SKonstantin Ananyev parse_cb_ipv6_u32_rule(char *str, struct acl_rule *v) 78675795fabSBruce Richardson { 78760018ef4SKonstantin Ananyev return parse_cb_ipv6_rule(str, v, IPV6_FRMT_U32); 78860018ef4SKonstantin Ananyev } 78975795fabSBruce Richardson 79060018ef4SKonstantin Ananyev static int 79160018ef4SKonstantin Ananyev parse_cb_ipv6_u64_rule(char *str, struct acl_rule *v) 79260018ef4SKonstantin Ananyev { 79360018ef4SKonstantin Ananyev return parse_cb_ipv6_rule(str, v, IPV6_FRMT_U64); 79460018ef4SKonstantin Ananyev } 79575795fabSBruce Richardson 79660018ef4SKonstantin Ananyev static int 79760018ef4SKonstantin Ananyev parse_ipv4_net(char *in, uint32_t *addr, uint32_t *mask_len) 79860018ef4SKonstantin Ananyev { 79960018ef4SKonstantin Ananyev char *sa, *sm, *sv; 80060018ef4SKonstantin Ananyev uint32_t m, v; 80160018ef4SKonstantin Ananyev 80260018ef4SKonstantin Ananyev const char *dlm = "/"; 80360018ef4SKonstantin Ananyev 80460018ef4SKonstantin Ananyev sv = NULL; 80560018ef4SKonstantin Ananyev sa = strtok_r(in, dlm, &sv); 80660018ef4SKonstantin Ananyev if (sa == NULL) 80760018ef4SKonstantin Ananyev return -EINVAL; 80860018ef4SKonstantin Ananyev sm = strtok_r(NULL, dlm, &sv); 80960018ef4SKonstantin Ananyev if (sm == NULL) 81060018ef4SKonstantin Ananyev return -EINVAL; 81160018ef4SKonstantin Ananyev 81260018ef4SKonstantin Ananyev if (inet_pton(AF_INET, sa, &v) != 1) 81360018ef4SKonstantin Ananyev return -EINVAL; 81460018ef4SKonstantin Ananyev 81560018ef4SKonstantin Ananyev addr[0] = rte_be_to_cpu_32(v); 81660018ef4SKonstantin Ananyev 81760018ef4SKonstantin Ananyev GET_CB_FIELD(sm, m, 0, sizeof(uint32_t) * CHAR_BIT, 0); 81875795fabSBruce Richardson mask_len[0] = m; 81975795fabSBruce Richardson 82075795fabSBruce Richardson return 0; 82175795fabSBruce Richardson } 82275795fabSBruce Richardson /* 82375795fabSBruce Richardson * Parse ClassBench rules file. 82475795fabSBruce Richardson * Expected format: 82575795fabSBruce Richardson * '@'<src_ipv4_addr>'/'<masklen> <space> \ 82675795fabSBruce Richardson * <dst_ipv4_addr>'/'<masklen> <space> \ 82775795fabSBruce Richardson * <src_port_low> <space> ":" <src_port_high> <space> \ 82875795fabSBruce Richardson * <dst_port_low> <space> ":" <dst_port_high> <space> \ 82975795fabSBruce Richardson * <proto>'/'<mask> 83075795fabSBruce Richardson */ 83175795fabSBruce Richardson static int 83275795fabSBruce Richardson parse_cb_ipv4_rule(char *str, struct acl_rule *v) 83375795fabSBruce Richardson { 83475795fabSBruce Richardson int i, rc; 83575795fabSBruce Richardson char *s, *sp, *in[CB_FLD_NUM]; 83675795fabSBruce Richardson static const char *dlm = " \t\n"; 83775795fabSBruce Richardson 83875795fabSBruce Richardson /* 83975795fabSBruce Richardson * Skip leading '@' 84075795fabSBruce Richardson */ 84175795fabSBruce Richardson if (strchr(str, '@') != str) 84275795fabSBruce Richardson return -EINVAL; 84375795fabSBruce Richardson 84475795fabSBruce Richardson s = str + 1; 84575795fabSBruce Richardson 84675795fabSBruce Richardson for (i = 0; i != RTE_DIM(in); i++) { 84775795fabSBruce Richardson in[i] = strtok_r(s, dlm, &sp); 84875795fabSBruce Richardson if (in[i] == NULL) 84975795fabSBruce Richardson return -EINVAL; 85075795fabSBruce Richardson s = NULL; 85175795fabSBruce Richardson } 85275795fabSBruce Richardson 85375795fabSBruce Richardson rc = parse_ipv4_net(in[CB_FLD_SRC_ADDR], 85475795fabSBruce Richardson &v->field[SRC_FIELD_IPV4].value.u32, 85575795fabSBruce Richardson &v->field[SRC_FIELD_IPV4].mask_range.u32); 85675795fabSBruce Richardson if (rc != 0) { 85775795fabSBruce Richardson RTE_LOG(ERR, TESTACL, 85875795fabSBruce Richardson "failed to read source address/mask: %s\n", 85975795fabSBruce Richardson in[CB_FLD_SRC_ADDR]); 86075795fabSBruce Richardson return rc; 86175795fabSBruce Richardson } 86275795fabSBruce Richardson 86375795fabSBruce Richardson rc = parse_ipv4_net(in[CB_FLD_DST_ADDR], 86475795fabSBruce Richardson &v->field[DST_FIELD_IPV4].value.u32, 86575795fabSBruce Richardson &v->field[DST_FIELD_IPV4].mask_range.u32); 86675795fabSBruce Richardson if (rc != 0) { 86775795fabSBruce Richardson RTE_LOG(ERR, TESTACL, 86875795fabSBruce Richardson "failed to read destination address/mask: %s\n", 86975795fabSBruce Richardson in[CB_FLD_DST_ADDR]); 87075795fabSBruce Richardson return rc; 87175795fabSBruce Richardson } 87275795fabSBruce Richardson 87375795fabSBruce Richardson /* source port. */ 87475795fabSBruce Richardson GET_CB_FIELD(in[CB_FLD_SRC_PORT_LOW], 87575795fabSBruce Richardson v->field[SRCP_FIELD_IPV4].value.u16, 87675795fabSBruce Richardson 0, UINT16_MAX, 0); 87775795fabSBruce Richardson GET_CB_FIELD(in[CB_FLD_SRC_PORT_HIGH], 87875795fabSBruce Richardson v->field[SRCP_FIELD_IPV4].mask_range.u16, 87975795fabSBruce Richardson 0, UINT16_MAX, 0); 88075795fabSBruce Richardson 88175795fabSBruce Richardson if (strncmp(in[CB_FLD_SRC_PORT_DLM], cb_port_delim, 88275795fabSBruce Richardson sizeof(cb_port_delim)) != 0) 88375795fabSBruce Richardson return -EINVAL; 88475795fabSBruce Richardson 88575795fabSBruce Richardson /* destination port. */ 88675795fabSBruce Richardson GET_CB_FIELD(in[CB_FLD_DST_PORT_LOW], 88775795fabSBruce Richardson v->field[DSTP_FIELD_IPV4].value.u16, 88875795fabSBruce Richardson 0, UINT16_MAX, 0); 88975795fabSBruce Richardson GET_CB_FIELD(in[CB_FLD_DST_PORT_HIGH], 89075795fabSBruce Richardson v->field[DSTP_FIELD_IPV4].mask_range.u16, 89175795fabSBruce Richardson 0, UINT16_MAX, 0); 89275795fabSBruce Richardson 89375795fabSBruce Richardson if (strncmp(in[CB_FLD_DST_PORT_DLM], cb_port_delim, 89475795fabSBruce Richardson sizeof(cb_port_delim)) != 0) 89575795fabSBruce Richardson return -EINVAL; 89675795fabSBruce Richardson 89775795fabSBruce Richardson GET_CB_FIELD(in[CB_FLD_PROTO], v->field[PROTO_FIELD_IPV4].value.u8, 89875795fabSBruce Richardson 0, UINT8_MAX, '/'); 89975795fabSBruce Richardson GET_CB_FIELD(in[CB_FLD_PROTO], v->field[PROTO_FIELD_IPV4].mask_range.u8, 90075795fabSBruce Richardson 0, UINT8_MAX, 0); 90175795fabSBruce Richardson 90275795fabSBruce Richardson return 0; 90375795fabSBruce Richardson } 90475795fabSBruce Richardson 90575795fabSBruce Richardson typedef int (*parse_5tuple)(char *text, struct acl_rule *rule); 90675795fabSBruce Richardson 90775795fabSBruce Richardson static int 90875795fabSBruce Richardson add_cb_rules(FILE *f, struct rte_acl_ctx *ctx) 90975795fabSBruce Richardson { 91075795fabSBruce Richardson int rc; 911ca2183d3SKonstantin Ananyev uint32_t i, k, n; 91275795fabSBruce Richardson struct acl_rule v; 91375795fabSBruce Richardson parse_5tuple parser; 91475795fabSBruce Richardson 91560018ef4SKonstantin Ananyev static const parse_5tuple parser_func[] = { 91660018ef4SKonstantin Ananyev [IPV6_FRMT_NONE] = parse_cb_ipv4_rule, 91760018ef4SKonstantin Ananyev [IPV6_FRMT_U32] = parse_cb_ipv6_u32_rule, 91860018ef4SKonstantin Ananyev [IPV6_FRMT_U64] = parse_cb_ipv6_u64_rule, 91960018ef4SKonstantin Ananyev }; 92060018ef4SKonstantin Ananyev 92175795fabSBruce Richardson memset(&v, 0, sizeof(v)); 92260018ef4SKonstantin Ananyev parser = parser_func[config.ipv6]; 92375795fabSBruce Richardson 924ca2183d3SKonstantin Ananyev k = 0; 925ca2183d3SKonstantin Ananyev for (i = 1; fgets(line, sizeof(line), f) != NULL; i++) { 92675795fabSBruce Richardson 927ca2183d3SKonstantin Ananyev if (skip_line(line) != 0) { 928ca2183d3SKonstantin Ananyev k++; 929ca2183d3SKonstantin Ananyev continue; 930ca2183d3SKonstantin Ananyev } 931ca2183d3SKonstantin Ananyev 932ca2183d3SKonstantin Ananyev n = i - k; 93375795fabSBruce Richardson rc = parser(line, &v); 93475795fabSBruce Richardson if (rc != 0) { 93575795fabSBruce Richardson RTE_LOG(ERR, TESTACL, "line %u: parse_cb_ipv4vlan_rule" 93675795fabSBruce Richardson " failed, error code: %d (%s)\n", 937ca2183d3SKonstantin Ananyev i, rc, strerror(-rc)); 93875795fabSBruce Richardson return rc; 93975795fabSBruce Richardson } 94075795fabSBruce Richardson 94175795fabSBruce Richardson v.data.category_mask = RTE_LEN2MASK(RTE_ACL_MAX_CATEGORIES, 94275795fabSBruce Richardson typeof(v.data.category_mask)); 94375795fabSBruce Richardson v.data.priority = RTE_ACL_MAX_PRIORITY - n; 94475795fabSBruce Richardson v.data.userdata = n; 94575795fabSBruce Richardson 94675795fabSBruce Richardson rc = rte_acl_add_rules(ctx, (struct rte_acl_rule *)&v, 1); 94775795fabSBruce Richardson if (rc != 0) { 94875795fabSBruce Richardson RTE_LOG(ERR, TESTACL, "line %u: failed to add rules " 94975795fabSBruce Richardson "into ACL context, error code: %d (%s)\n", 950ca2183d3SKonstantin Ananyev i, rc, strerror(-rc)); 95175795fabSBruce Richardson return rc; 95275795fabSBruce Richardson } 95375795fabSBruce Richardson } 95475795fabSBruce Richardson 95575795fabSBruce Richardson return 0; 95675795fabSBruce Richardson } 95775795fabSBruce Richardson 95875795fabSBruce Richardson static void 95975795fabSBruce Richardson acx_init(void) 96075795fabSBruce Richardson { 96175795fabSBruce Richardson int ret; 96275795fabSBruce Richardson FILE *f; 96375795fabSBruce Richardson struct rte_acl_config cfg; 96475795fabSBruce Richardson 96575795fabSBruce Richardson memset(&cfg, 0, sizeof(cfg)); 96675795fabSBruce Richardson 96775795fabSBruce Richardson /* setup ACL build config. */ 96860018ef4SKonstantin Ananyev if (config.ipv6 == IPV6_FRMT_U32) { 96975795fabSBruce Richardson cfg.num_fields = RTE_DIM(ipv6_defs); 97075795fabSBruce Richardson memcpy(&cfg.defs, ipv6_defs, sizeof(ipv6_defs)); 97160018ef4SKonstantin Ananyev } else if (config.ipv6 == IPV6_FRMT_U64) { 97260018ef4SKonstantin Ananyev cfg.num_fields = RTE_DIM(ipv6_u64_defs); 97360018ef4SKonstantin Ananyev memcpy(&cfg.defs, ipv6_u64_defs, sizeof(ipv6_u64_defs)); 97475795fabSBruce Richardson } else { 97575795fabSBruce Richardson cfg.num_fields = RTE_DIM(ipv4_defs); 97675795fabSBruce Richardson memcpy(&cfg.defs, ipv4_defs, sizeof(ipv4_defs)); 97775795fabSBruce Richardson } 97875795fabSBruce Richardson cfg.num_categories = config.bld_categories; 97975795fabSBruce Richardson cfg.max_size = config.max_size; 98075795fabSBruce Richardson 98175795fabSBruce Richardson /* setup ACL creation parameters. */ 98275795fabSBruce Richardson prm.rule_size = RTE_ACL_RULE_SZ(cfg.num_fields); 98375795fabSBruce Richardson prm.max_rule_num = config.nb_rules; 98475795fabSBruce Richardson 98575795fabSBruce Richardson config.acx = rte_acl_create(&prm); 98675795fabSBruce Richardson if (config.acx == NULL) 98775795fabSBruce Richardson rte_exit(rte_errno, "failed to create ACL context\n"); 98875795fabSBruce Richardson 98975795fabSBruce Richardson /* set default classify method for this context. */ 99075795fabSBruce Richardson if (config.alg.alg != RTE_ACL_CLASSIFY_DEFAULT) { 99175795fabSBruce Richardson ret = rte_acl_set_ctx_classify(config.acx, config.alg.alg); 99275795fabSBruce Richardson if (ret != 0) 99375795fabSBruce Richardson rte_exit(ret, "failed to setup %s method " 99475795fabSBruce Richardson "for ACL context\n", config.alg.name); 99575795fabSBruce Richardson } 99675795fabSBruce Richardson 99775795fabSBruce Richardson /* add ACL rules. */ 99875795fabSBruce Richardson f = fopen(config.rule_file, "r"); 99975795fabSBruce Richardson if (f == NULL) 100075795fabSBruce Richardson rte_exit(-EINVAL, "failed to open file %s\n", 100175795fabSBruce Richardson config.rule_file); 100275795fabSBruce Richardson 100375795fabSBruce Richardson ret = add_cb_rules(f, config.acx); 100475795fabSBruce Richardson if (ret != 0) 100575795fabSBruce Richardson rte_exit(ret, "failed to add rules into ACL context\n"); 100675795fabSBruce Richardson 100775795fabSBruce Richardson fclose(f); 100875795fabSBruce Richardson 100975795fabSBruce Richardson /* perform build. */ 101075795fabSBruce Richardson ret = rte_acl_build(config.acx, &cfg); 101175795fabSBruce Richardson 101275795fabSBruce Richardson dump_verbose(DUMP_NONE, stdout, 101375795fabSBruce Richardson "rte_acl_build(%u) finished with %d\n", 101475795fabSBruce Richardson config.bld_categories, ret); 101575795fabSBruce Richardson 101675795fabSBruce Richardson rte_acl_dump(config.acx); 101775795fabSBruce Richardson 101875795fabSBruce Richardson if (ret != 0) 101975795fabSBruce Richardson rte_exit(ret, "failed to build search context\n"); 102075795fabSBruce Richardson } 102175795fabSBruce Richardson 102275795fabSBruce Richardson static uint32_t 102375795fabSBruce Richardson search_ip5tuples_once(uint32_t categories, uint32_t step, const char *alg) 102475795fabSBruce Richardson { 102575795fabSBruce Richardson int ret; 102675795fabSBruce Richardson uint32_t i, j, k, n, r; 102775795fabSBruce Richardson const uint8_t *data[step], *v; 102875795fabSBruce Richardson uint32_t results[step * categories]; 102975795fabSBruce Richardson 103075795fabSBruce Richardson v = config.traces; 103175795fabSBruce Richardson for (i = 0; i != config.used_traces; i += n) { 103275795fabSBruce Richardson 103375795fabSBruce Richardson n = RTE_MIN(step, config.used_traces - i); 103475795fabSBruce Richardson 103575795fabSBruce Richardson for (j = 0; j != n; j++) { 103675795fabSBruce Richardson data[j] = v; 103775795fabSBruce Richardson v += config.trace_sz; 103875795fabSBruce Richardson } 103975795fabSBruce Richardson 104075795fabSBruce Richardson ret = rte_acl_classify(config.acx, data, results, 104175795fabSBruce Richardson n, categories); 104275795fabSBruce Richardson 104375795fabSBruce Richardson if (ret != 0) 104475795fabSBruce Richardson rte_exit(ret, "classify for ipv%c_5tuples returns %d\n", 104575795fabSBruce Richardson config.ipv6 ? '6' : '4', ret); 104675795fabSBruce Richardson 104775795fabSBruce Richardson for (r = 0, j = 0; j != n; j++) { 104875795fabSBruce Richardson for (k = 0; k != categories; k++, r++) { 104975795fabSBruce Richardson dump_verbose(DUMP_PKT, stdout, 105075795fabSBruce Richardson "ipv%c_5tuple: %u, category: %u, " 105175795fabSBruce Richardson "result: %u\n", 105275795fabSBruce Richardson config.ipv6 ? '6' : '4', 105375795fabSBruce Richardson i + j + 1, k, results[r] - 1); 105475795fabSBruce Richardson } 105575795fabSBruce Richardson 105675795fabSBruce Richardson } 105775795fabSBruce Richardson } 105875795fabSBruce Richardson 105975795fabSBruce Richardson dump_verbose(DUMP_SEARCH, stdout, 106075795fabSBruce Richardson "%s(%u, %u, %s) returns %u\n", __func__, 106175795fabSBruce Richardson categories, step, alg, i); 106275795fabSBruce Richardson return i; 106375795fabSBruce Richardson } 106475795fabSBruce Richardson 106575795fabSBruce Richardson static int 1066f2fc83b4SThomas Monjalon search_ip5tuples(__rte_unused void *arg) 106775795fabSBruce Richardson { 106875795fabSBruce Richardson uint64_t pkt, start, tm; 106975795fabSBruce Richardson uint32_t i, lcore; 1070bcb9a016SKonstantin Ananyev long double st; 107175795fabSBruce Richardson 107275795fabSBruce Richardson lcore = rte_lcore_id(); 1073bcb9a016SKonstantin Ananyev start = rte_rdtsc_precise(); 107475795fabSBruce Richardson pkt = 0; 107575795fabSBruce Richardson 107675795fabSBruce Richardson for (i = 0; i != config.iter_num; i++) { 107775795fabSBruce Richardson pkt += search_ip5tuples_once(config.run_categories, 107875795fabSBruce Richardson config.trace_step, config.alg.name); 107975795fabSBruce Richardson } 108075795fabSBruce Richardson 1081bcb9a016SKonstantin Ananyev tm = rte_rdtsc_precise() - start; 1082bcb9a016SKonstantin Ananyev 1083bcb9a016SKonstantin Ananyev st = (long double)tm / rte_get_timer_hz(); 108475795fabSBruce Richardson dump_verbose(DUMP_NONE, stdout, 108575795fabSBruce Richardson "%s @lcore %u: %" PRIu32 " iterations, %" PRIu64 " pkts, %" 1086bcb9a016SKonstantin Ananyev PRIu32 " categories, %" PRIu64 " cycles (%.2Lf sec), " 1087bcb9a016SKonstantin Ananyev "%.2Lf cycles/pkt, %.2Lf pkt/sec\n", 1088bcb9a016SKonstantin Ananyev __func__, lcore, i, pkt, 1089bcb9a016SKonstantin Ananyev config.run_categories, tm, st, 1090bcb9a016SKonstantin Ananyev (pkt == 0) ? 0 : (long double)tm / pkt, pkt / st); 109175795fabSBruce Richardson 109275795fabSBruce Richardson return 0; 109375795fabSBruce Richardson } 109475795fabSBruce Richardson 109575795fabSBruce Richardson static unsigned long 109675795fabSBruce Richardson get_ulong_opt(const char *opt, const char *name, size_t min, size_t max) 109775795fabSBruce Richardson { 109875795fabSBruce Richardson unsigned long val; 109975795fabSBruce Richardson char *end; 110075795fabSBruce Richardson 110175795fabSBruce Richardson errno = 0; 110275795fabSBruce Richardson val = strtoul(opt, &end, 0); 110375795fabSBruce Richardson if (errno != 0 || end[0] != 0 || val > max || val < min) 110475795fabSBruce Richardson rte_exit(-EINVAL, "invalid value: \"%s\" for option: %s\n", 110575795fabSBruce Richardson opt, name); 110675795fabSBruce Richardson return val; 110775795fabSBruce Richardson } 110875795fabSBruce Richardson 110975795fabSBruce Richardson static void 111075795fabSBruce Richardson get_alg_opt(const char *opt, const char *name) 111175795fabSBruce Richardson { 111275795fabSBruce Richardson uint32_t i; 111375795fabSBruce Richardson 111475795fabSBruce Richardson for (i = 0; i != RTE_DIM(acl_alg); i++) { 111575795fabSBruce Richardson if (strcmp(opt, acl_alg[i].name) == 0) { 111675795fabSBruce Richardson config.alg = acl_alg[i]; 111775795fabSBruce Richardson return; 111875795fabSBruce Richardson } 111975795fabSBruce Richardson } 112075795fabSBruce Richardson 112175795fabSBruce Richardson rte_exit(-EINVAL, "invalid value: \"%s\" for option: %s\n", 112275795fabSBruce Richardson opt, name); 112375795fabSBruce Richardson } 112475795fabSBruce Richardson 112575795fabSBruce Richardson static void 112660018ef4SKonstantin Ananyev get_ipv6_opt(const char *opt, const char *name) 112760018ef4SKonstantin Ananyev { 112860018ef4SKonstantin Ananyev uint32_t i; 112960018ef4SKonstantin Ananyev 113060018ef4SKonstantin Ananyev static const struct { 113160018ef4SKonstantin Ananyev const char *name; 113260018ef4SKonstantin Ananyev uint32_t val; 113360018ef4SKonstantin Ananyev } ipv6_opt[] = { 113460018ef4SKonstantin Ananyev { 113560018ef4SKonstantin Ananyev .name = "4B", 113660018ef4SKonstantin Ananyev .val = IPV6_FRMT_U32, 113760018ef4SKonstantin Ananyev }, 113860018ef4SKonstantin Ananyev { 113960018ef4SKonstantin Ananyev .name = "8B", 114060018ef4SKonstantin Ananyev .val = IPV6_FRMT_U64, 114160018ef4SKonstantin Ananyev }, 114260018ef4SKonstantin Ananyev }; 114360018ef4SKonstantin Ananyev 114460018ef4SKonstantin Ananyev for (i = 0; i != RTE_DIM(ipv6_opt); i++) { 114560018ef4SKonstantin Ananyev if (strcmp(opt, ipv6_opt[i].name) == 0) { 114660018ef4SKonstantin Ananyev config.ipv6 = ipv6_opt[i].val; 114760018ef4SKonstantin Ananyev return; 114860018ef4SKonstantin Ananyev } 114960018ef4SKonstantin Ananyev } 115060018ef4SKonstantin Ananyev 115160018ef4SKonstantin Ananyev rte_exit(-EINVAL, "invalid value: \"%s\" for option: %s\n", 115260018ef4SKonstantin Ananyev opt, name); 115360018ef4SKonstantin Ananyev } 115460018ef4SKonstantin Ananyev 115560018ef4SKonstantin Ananyev 115660018ef4SKonstantin Ananyev static void 115775795fabSBruce Richardson print_usage(const char *prgname) 115875795fabSBruce Richardson { 115975795fabSBruce Richardson uint32_t i, n, rc; 116075795fabSBruce Richardson char buf[PATH_MAX]; 116175795fabSBruce Richardson 116275795fabSBruce Richardson n = 0; 116375795fabSBruce Richardson buf[0] = 0; 116475795fabSBruce Richardson 116575795fabSBruce Richardson for (i = 0; i < RTE_DIM(acl_alg) - 1; i++) { 116675795fabSBruce Richardson rc = snprintf(buf + n, sizeof(buf) - n, "%s|", 116775795fabSBruce Richardson acl_alg[i].name); 116875795fabSBruce Richardson if (rc > sizeof(buf) - n) 116975795fabSBruce Richardson break; 117075795fabSBruce Richardson n += rc; 117175795fabSBruce Richardson } 117275795fabSBruce Richardson 11736723c0fcSBruce Richardson strlcpy(buf + n, acl_alg[i].name, sizeof(buf) - n); 117475795fabSBruce Richardson 117575795fabSBruce Richardson fprintf(stdout, 117675795fabSBruce Richardson PRINT_USAGE_START 117775795fabSBruce Richardson "--" OPT_RULE_FILE "=<rules set file>\n" 117875795fabSBruce Richardson "[--" OPT_TRACE_FILE "=<input traces file>]\n" 117975795fabSBruce Richardson "[--" OPT_RULE_NUM 118075795fabSBruce Richardson "=<maximum number of rules for ACL context>]\n" 118175795fabSBruce Richardson "[--" OPT_TRACE_NUM 118275795fabSBruce Richardson "=<number of traces to read binary file in>]\n" 118375795fabSBruce Richardson "[--" OPT_TRACE_STEP 118475795fabSBruce Richardson "=<number of traces to classify per one call>]\n" 118575795fabSBruce Richardson "[--" OPT_BLD_CATEGORIES 118675795fabSBruce Richardson "=<number of categories to build with>]\n" 118775795fabSBruce Richardson "[--" OPT_RUN_CATEGORIES 118875795fabSBruce Richardson "=<number of categories to run with> " 118975795fabSBruce Richardson "should be either 1 or multiple of %zu, " 119075795fabSBruce Richardson "but not greater then %u]\n" 119175795fabSBruce Richardson "[--" OPT_MAX_SIZE 11927be78d02SJosh Soref "=<size limit (in bytes) for runtime ACL structures> " 119375795fabSBruce Richardson "leave 0 for default behaviour]\n" 119475795fabSBruce Richardson "[--" OPT_ITER_NUM "=<number of iterations to perform>]\n" 119575795fabSBruce Richardson "[--" OPT_VERBOSE "=<verbose level>]\n" 119675795fabSBruce Richardson "[--" OPT_SEARCH_ALG "=%s]\n" 119760018ef4SKonstantin Ananyev "[--" OPT_IPV6 "(=4B | 8B) <IPv6 rules and trace files>]\n", 119875795fabSBruce Richardson prgname, RTE_ACL_RESULTS_MULTIPLIER, 119975795fabSBruce Richardson (uint32_t)RTE_ACL_MAX_CATEGORIES, 120075795fabSBruce Richardson buf); 120175795fabSBruce Richardson } 120275795fabSBruce Richardson 120375795fabSBruce Richardson static void 120475795fabSBruce Richardson dump_config(FILE *f) 120575795fabSBruce Richardson { 120675795fabSBruce Richardson fprintf(f, "%s:\n", __func__); 120775795fabSBruce Richardson fprintf(f, "%s:%s\n", OPT_RULE_FILE, config.rule_file); 120875795fabSBruce Richardson fprintf(f, "%s:%s\n", OPT_TRACE_FILE, config.trace_file); 120975795fabSBruce Richardson fprintf(f, "%s:%u\n", OPT_RULE_NUM, config.nb_rules); 121075795fabSBruce Richardson fprintf(f, "%s:%u\n", OPT_TRACE_NUM, config.nb_traces); 121175795fabSBruce Richardson fprintf(f, "%s:%u\n", OPT_TRACE_STEP, config.trace_step); 121275795fabSBruce Richardson fprintf(f, "%s:%u\n", OPT_BLD_CATEGORIES, config.bld_categories); 121375795fabSBruce Richardson fprintf(f, "%s:%u\n", OPT_RUN_CATEGORIES, config.run_categories); 121475795fabSBruce Richardson fprintf(f, "%s:%zu\n", OPT_MAX_SIZE, config.max_size); 121575795fabSBruce Richardson fprintf(f, "%s:%u\n", OPT_ITER_NUM, config.iter_num); 121675795fabSBruce Richardson fprintf(f, "%s:%u\n", OPT_VERBOSE, config.verbose); 121775795fabSBruce Richardson fprintf(f, "%s:%u(%s)\n", OPT_SEARCH_ALG, config.alg.alg, 121875795fabSBruce Richardson config.alg.name); 121975795fabSBruce Richardson fprintf(f, "%s:%u\n", OPT_IPV6, config.ipv6); 122075795fabSBruce Richardson } 122175795fabSBruce Richardson 122275795fabSBruce Richardson static void 122375795fabSBruce Richardson check_config(void) 122475795fabSBruce Richardson { 122575795fabSBruce Richardson if (config.rule_file == NULL) { 122675795fabSBruce Richardson print_usage(config.prgname); 122775795fabSBruce Richardson rte_exit(-EINVAL, "mandatory option %s is not specified\n", 122875795fabSBruce Richardson OPT_RULE_FILE); 122975795fabSBruce Richardson } 123075795fabSBruce Richardson } 123175795fabSBruce Richardson 123275795fabSBruce Richardson 123375795fabSBruce Richardson static void 123475795fabSBruce Richardson get_input_opts(int argc, char **argv) 123575795fabSBruce Richardson { 123675795fabSBruce Richardson static struct option lgopts[] = { 123775795fabSBruce Richardson {OPT_RULE_FILE, 1, 0, 0}, 123875795fabSBruce Richardson {OPT_TRACE_FILE, 1, 0, 0}, 123975795fabSBruce Richardson {OPT_TRACE_NUM, 1, 0, 0}, 124075795fabSBruce Richardson {OPT_RULE_NUM, 1, 0, 0}, 124175795fabSBruce Richardson {OPT_MAX_SIZE, 1, 0, 0}, 124275795fabSBruce Richardson {OPT_TRACE_STEP, 1, 0, 0}, 124375795fabSBruce Richardson {OPT_BLD_CATEGORIES, 1, 0, 0}, 124475795fabSBruce Richardson {OPT_RUN_CATEGORIES, 1, 0, 0}, 124575795fabSBruce Richardson {OPT_ITER_NUM, 1, 0, 0}, 124675795fabSBruce Richardson {OPT_VERBOSE, 1, 0, 0}, 124775795fabSBruce Richardson {OPT_SEARCH_ALG, 1, 0, 0}, 124860018ef4SKonstantin Ananyev {OPT_IPV6, 2, 0, 0}, 124975795fabSBruce Richardson {NULL, 0, 0, 0} 125075795fabSBruce Richardson }; 125175795fabSBruce Richardson 125275795fabSBruce Richardson int opt, opt_idx; 125375795fabSBruce Richardson 125475795fabSBruce Richardson while ((opt = getopt_long(argc, argv, "", lgopts, &opt_idx)) != EOF) { 125575795fabSBruce Richardson 125675795fabSBruce Richardson if (opt != 0) { 125775795fabSBruce Richardson print_usage(config.prgname); 125875795fabSBruce Richardson rte_exit(-EINVAL, "unknown option: %c", opt); 125975795fabSBruce Richardson } 126075795fabSBruce Richardson 126175795fabSBruce Richardson if (strcmp(lgopts[opt_idx].name, OPT_RULE_FILE) == 0) { 126275795fabSBruce Richardson config.rule_file = optarg; 126375795fabSBruce Richardson } else if (strcmp(lgopts[opt_idx].name, OPT_TRACE_FILE) == 0) { 126475795fabSBruce Richardson config.trace_file = optarg; 126575795fabSBruce Richardson } else if (strcmp(lgopts[opt_idx].name, OPT_RULE_NUM) == 0) { 126675795fabSBruce Richardson config.nb_rules = get_ulong_opt(optarg, 126775795fabSBruce Richardson lgopts[opt_idx].name, 1, RTE_ACL_MAX_INDEX + 1); 126875795fabSBruce Richardson } else if (strcmp(lgopts[opt_idx].name, OPT_MAX_SIZE) == 0) { 126975795fabSBruce Richardson config.max_size = get_ulong_opt(optarg, 127075795fabSBruce Richardson lgopts[opt_idx].name, 0, SIZE_MAX); 127175795fabSBruce Richardson } else if (strcmp(lgopts[opt_idx].name, OPT_TRACE_NUM) == 0) { 127275795fabSBruce Richardson config.nb_traces = get_ulong_opt(optarg, 127375795fabSBruce Richardson lgopts[opt_idx].name, 1, UINT32_MAX); 127475795fabSBruce Richardson } else if (strcmp(lgopts[opt_idx].name, OPT_TRACE_STEP) == 0) { 127575795fabSBruce Richardson config.trace_step = get_ulong_opt(optarg, 127675795fabSBruce Richardson lgopts[opt_idx].name, 1, TRACE_STEP_MAX); 127775795fabSBruce Richardson } else if (strcmp(lgopts[opt_idx].name, 127875795fabSBruce Richardson OPT_BLD_CATEGORIES) == 0) { 127975795fabSBruce Richardson config.bld_categories = get_ulong_opt(optarg, 128075795fabSBruce Richardson lgopts[opt_idx].name, 1, 128175795fabSBruce Richardson RTE_ACL_MAX_CATEGORIES); 128275795fabSBruce Richardson } else if (strcmp(lgopts[opt_idx].name, 128375795fabSBruce Richardson OPT_RUN_CATEGORIES) == 0) { 128475795fabSBruce Richardson config.run_categories = get_ulong_opt(optarg, 128575795fabSBruce Richardson lgopts[opt_idx].name, 1, 128675795fabSBruce Richardson RTE_ACL_MAX_CATEGORIES); 128775795fabSBruce Richardson } else if (strcmp(lgopts[opt_idx].name, OPT_ITER_NUM) == 0) { 128875795fabSBruce Richardson config.iter_num = get_ulong_opt(optarg, 128975795fabSBruce Richardson lgopts[opt_idx].name, 1, INT32_MAX); 129075795fabSBruce Richardson } else if (strcmp(lgopts[opt_idx].name, OPT_VERBOSE) == 0) { 129175795fabSBruce Richardson config.verbose = get_ulong_opt(optarg, 129275795fabSBruce Richardson lgopts[opt_idx].name, DUMP_NONE, DUMP_MAX); 129375795fabSBruce Richardson } else if (strcmp(lgopts[opt_idx].name, 129475795fabSBruce Richardson OPT_SEARCH_ALG) == 0) { 129575795fabSBruce Richardson get_alg_opt(optarg, lgopts[opt_idx].name); 129675795fabSBruce Richardson } else if (strcmp(lgopts[opt_idx].name, OPT_IPV6) == 0) { 129760018ef4SKonstantin Ananyev config.ipv6 = IPV6_FRMT_U32; 129860018ef4SKonstantin Ananyev if (optarg != NULL) 129960018ef4SKonstantin Ananyev get_ipv6_opt(optarg, lgopts[opt_idx].name); 130075795fabSBruce Richardson } 130175795fabSBruce Richardson } 130275795fabSBruce Richardson config.trace_sz = config.ipv6 ? sizeof(struct ipv6_5tuple) : 130375795fabSBruce Richardson sizeof(struct ipv4_5tuple); 130475795fabSBruce Richardson 130575795fabSBruce Richardson } 130675795fabSBruce Richardson 130775795fabSBruce Richardson int 130875795fabSBruce Richardson main(int argc, char **argv) 130975795fabSBruce Richardson { 131075795fabSBruce Richardson int ret; 131175795fabSBruce Richardson uint32_t lcore; 131275795fabSBruce Richardson 131375795fabSBruce Richardson ret = rte_eal_init(argc, argv); 131475795fabSBruce Richardson if (ret < 0) 131575795fabSBruce Richardson rte_panic("Cannot init EAL\n"); 131675795fabSBruce Richardson 131775795fabSBruce Richardson argc -= ret; 131875795fabSBruce Richardson argv += ret; 131975795fabSBruce Richardson 132075795fabSBruce Richardson config.prgname = argv[0]; 132175795fabSBruce Richardson 132275795fabSBruce Richardson get_input_opts(argc, argv); 132375795fabSBruce Richardson dump_config(stdout); 132475795fabSBruce Richardson check_config(); 132575795fabSBruce Richardson 132675795fabSBruce Richardson acx_init(); 132775795fabSBruce Richardson 132875795fabSBruce Richardson if (config.trace_file != NULL) 132975795fabSBruce Richardson tracef_init(); 133075795fabSBruce Richardson 1331cb056611SStephen Hemminger RTE_LCORE_FOREACH_WORKER(lcore) 133275795fabSBruce Richardson rte_eal_remote_launch(search_ip5tuples, NULL, lcore); 133375795fabSBruce Richardson 133475795fabSBruce Richardson search_ip5tuples(NULL); 133575795fabSBruce Richardson 133675795fabSBruce Richardson rte_eal_mp_wait_lcore(); 133775795fabSBruce Richardson 133875795fabSBruce Richardson rte_acl_free(config.acx); 133975795fabSBruce Richardson return 0; 134075795fabSBruce Richardson } 1341