LCOV - code coverage report
Current view: top level - app/test-acl - main.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 0 323 0.0 %
Date: 2025-01-02 22:41:34 Functions: 0 23 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright(c) 2010-2014 Intel Corporation
       3                 :            :  */
       4                 :            : 
       5                 :            : #include <rte_string_fns.h>
       6                 :            : #include <rte_acl.h>
       7                 :            : #include <getopt.h>
       8                 :            : #include <string.h>
       9                 :            : 
      10                 :            : #include <rte_cycles.h>
      11                 :            : #include <rte_per_lcore.h>
      12                 :            : #include <rte_lcore.h>
      13                 :            : #include <rte_ip.h>
      14                 :            : 
      15                 :            : #define PRINT_USAGE_START       "%s [EAL options] --\n"
      16                 :            : 
      17                 :            : #define RTE_LOGTYPE_TESTACL     RTE_LOGTYPE_USER1
      18                 :            : 
      19                 :            : #define APP_NAME        "TESTACL"
      20                 :            : 
      21                 :            : #define GET_CB_FIELD(in, fd, base, lim, dlm)    do {            \
      22                 :            :         unsigned long val;                                      \
      23                 :            :         char *end_fld;                                          \
      24                 :            :         errno = 0;                                              \
      25                 :            :         val = strtoul((in), &end_fld, (base));                  \
      26                 :            :         if (errno != 0 || end_fld[0] != (dlm) || val > (lim))   \
      27                 :            :                 return -EINVAL;                               \
      28                 :            :         (fd) = (typeof(fd))val;                                 \
      29                 :            :         (in) = end_fld + 1;                                     \
      30                 :            : } while (0)
      31                 :            : 
      32                 :            : #define OPT_RULE_FILE           "rulesf"
      33                 :            : #define OPT_TRACE_FILE          "tracef"
      34                 :            : #define OPT_RULE_NUM            "rulenum"
      35                 :            : #define OPT_TRACE_NUM           "tracenum"
      36                 :            : #define OPT_TRACE_STEP          "tracestep"
      37                 :            : #define OPT_SEARCH_ALG          "alg"
      38                 :            : #define OPT_BLD_CATEGORIES      "bldcat"
      39                 :            : #define OPT_RUN_CATEGORIES      "runcat"
      40                 :            : #define OPT_MAX_SIZE            "maxsize"
      41                 :            : #define OPT_ITER_NUM            "iter"
      42                 :            : #define OPT_VERBOSE             "verbose"
      43                 :            : #define OPT_IPV6                "ipv6"
      44                 :            : 
      45                 :            : #define TRACE_DEFAULT_NUM       0x10000
      46                 :            : #define TRACE_STEP_MAX          0x1000
      47                 :            : #define TRACE_STEP_DEF          0x100
      48                 :            : 
      49                 :            : #define RULE_NUM                0x10000
      50                 :            : 
      51                 :            : #define COMMENT_LEAD_CHAR       '#'
      52                 :            : 
      53                 :            : enum {
      54                 :            :         DUMP_NONE,
      55                 :            :         DUMP_SEARCH,
      56                 :            :         DUMP_PKT,
      57                 :            :         DUMP_MAX
      58                 :            : };
      59                 :            : 
      60                 :            : enum {
      61                 :            :         IPV6_FRMT_NONE,
      62                 :            :         IPV6_FRMT_U32,
      63                 :            :         IPV6_FRMT_U64,
      64                 :            : };
      65                 :            : 
      66                 :            : struct acl_alg {
      67                 :            :         const char *name;
      68                 :            :         enum rte_acl_classify_alg alg;
      69                 :            : };
      70                 :            : 
      71                 :            : static const struct acl_alg acl_alg[] = {
      72                 :            :         {
      73                 :            :                 .name = "scalar",
      74                 :            :                 .alg = RTE_ACL_CLASSIFY_SCALAR,
      75                 :            :         },
      76                 :            :         {
      77                 :            :                 .name = "sse",
      78                 :            :                 .alg = RTE_ACL_CLASSIFY_SSE,
      79                 :            :         },
      80                 :            :         {
      81                 :            :                 .name = "avx2",
      82                 :            :                 .alg = RTE_ACL_CLASSIFY_AVX2,
      83                 :            :         },
      84                 :            :         {
      85                 :            :                 .name = "neon",
      86                 :            :                 .alg = RTE_ACL_CLASSIFY_NEON,
      87                 :            :         },
      88                 :            :         {
      89                 :            :                 .name = "altivec",
      90                 :            :                 .alg = RTE_ACL_CLASSIFY_ALTIVEC,
      91                 :            :         },
      92                 :            :         {
      93                 :            :                 .name = "avx512x16",
      94                 :            :                 .alg = RTE_ACL_CLASSIFY_AVX512X16,
      95                 :            :         },
      96                 :            :         {
      97                 :            :                 .name = "avx512x32",
      98                 :            :                 .alg = RTE_ACL_CLASSIFY_AVX512X32,
      99                 :            :         },
     100                 :            : };
     101                 :            : 
     102                 :            : static struct {
     103                 :            :         const char         *prgname;
     104                 :            :         const char         *rule_file;
     105                 :            :         const char         *trace_file;
     106                 :            :         size_t              max_size;
     107                 :            :         uint32_t            bld_categories;
     108                 :            :         uint32_t            run_categories;
     109                 :            :         uint32_t            nb_rules;
     110                 :            :         uint32_t            nb_traces;
     111                 :            :         uint32_t            trace_step;
     112                 :            :         uint32_t            trace_sz;
     113                 :            :         uint32_t            iter_num;
     114                 :            :         uint32_t            verbose;
     115                 :            :         uint32_t            ipv6;
     116                 :            :         struct acl_alg      alg;
     117                 :            :         uint32_t            used_traces;
     118                 :            :         void               *traces;
     119                 :            :         struct rte_acl_ctx *acx;
     120                 :            : } config = {
     121                 :            :         .bld_categories = 3,
     122                 :            :         .run_categories = 1,
     123                 :            :         .nb_rules = RULE_NUM,
     124                 :            :         .nb_traces = TRACE_DEFAULT_NUM,
     125                 :            :         .trace_step = TRACE_STEP_DEF,
     126                 :            :         .iter_num = 1,
     127                 :            :         .verbose = DUMP_MAX,
     128                 :            :         .alg = {
     129                 :            :                 .name = "default",
     130                 :            :                 .alg = RTE_ACL_CLASSIFY_DEFAULT,
     131                 :            :         },
     132                 :            :         .ipv6 = IPV6_FRMT_NONE,
     133                 :            : };
     134                 :            : 
     135                 :            : static struct rte_acl_param prm = {
     136                 :            :         .name = APP_NAME,
     137                 :            :         .socket_id = SOCKET_ID_ANY,
     138                 :            : };
     139                 :            : 
     140                 :            : /*
     141                 :            :  * Rule and trace formats definitions.
     142                 :            :  */
     143                 :            : 
     144                 :            : struct ipv4_5tuple {
     145                 :            :         uint8_t  proto;
     146                 :            :         uint32_t ip_src;
     147                 :            :         uint32_t ip_dst;
     148                 :            :         uint16_t port_src;
     149                 :            :         uint16_t port_dst;
     150                 :            : };
     151                 :            : 
     152                 :            : enum {
     153                 :            :         PROTO_FIELD_IPV4,
     154                 :            :         SRC_FIELD_IPV4,
     155                 :            :         DST_FIELD_IPV4,
     156                 :            :         SRCP_FIELD_IPV4,
     157                 :            :         DSTP_FIELD_IPV4,
     158                 :            :         NUM_FIELDS_IPV4
     159                 :            : };
     160                 :            : 
     161                 :            : /*
     162                 :            :  * That effectively defines order of IPV4VLAN classifications:
     163                 :            :  *  - PROTO
     164                 :            :  *  - VLAN (TAG and DOMAIN)
     165                 :            :  *  - SRC IP ADDRESS
     166                 :            :  *  - DST IP ADDRESS
     167                 :            :  *  - PORTS (SRC and DST)
     168                 :            :  */
     169                 :            : enum {
     170                 :            :         RTE_ACL_IPV4VLAN_PROTO,
     171                 :            :         RTE_ACL_IPV4VLAN_VLAN,
     172                 :            :         RTE_ACL_IPV4VLAN_SRC,
     173                 :            :         RTE_ACL_IPV4VLAN_DST,
     174                 :            :         RTE_ACL_IPV4VLAN_PORTS,
     175                 :            :         RTE_ACL_IPV4VLAN_NUM
     176                 :            : };
     177                 :            : 
     178                 :            : struct rte_acl_field_def ipv4_defs[NUM_FIELDS_IPV4] = {
     179                 :            :         {
     180                 :            :                 .type = RTE_ACL_FIELD_TYPE_BITMASK,
     181                 :            :                 .size = sizeof(uint8_t),
     182                 :            :                 .field_index = PROTO_FIELD_IPV4,
     183                 :            :                 .input_index = RTE_ACL_IPV4VLAN_PROTO,
     184                 :            :                 .offset = offsetof(struct ipv4_5tuple, proto),
     185                 :            :         },
     186                 :            :         {
     187                 :            :                 .type = RTE_ACL_FIELD_TYPE_MASK,
     188                 :            :                 .size = sizeof(uint32_t),
     189                 :            :                 .field_index = SRC_FIELD_IPV4,
     190                 :            :                 .input_index = RTE_ACL_IPV4VLAN_SRC,
     191                 :            :                 .offset = offsetof(struct ipv4_5tuple, ip_src),
     192                 :            :         },
     193                 :            :         {
     194                 :            :                 .type = RTE_ACL_FIELD_TYPE_MASK,
     195                 :            :                 .size = sizeof(uint32_t),
     196                 :            :                 .field_index = DST_FIELD_IPV4,
     197                 :            :                 .input_index = RTE_ACL_IPV4VLAN_DST,
     198                 :            :                 .offset = offsetof(struct ipv4_5tuple, ip_dst),
     199                 :            :         },
     200                 :            :         {
     201                 :            :                 .type = RTE_ACL_FIELD_TYPE_RANGE,
     202                 :            :                 .size = sizeof(uint16_t),
     203                 :            :                 .field_index = SRCP_FIELD_IPV4,
     204                 :            :                 .input_index = RTE_ACL_IPV4VLAN_PORTS,
     205                 :            :                 .offset = offsetof(struct ipv4_5tuple, port_src),
     206                 :            :         },
     207                 :            :         {
     208                 :            :                 .type = RTE_ACL_FIELD_TYPE_RANGE,
     209                 :            :                 .size = sizeof(uint16_t),
     210                 :            :                 .field_index = DSTP_FIELD_IPV4,
     211                 :            :                 .input_index = RTE_ACL_IPV4VLAN_PORTS,
     212                 :            :                 .offset = offsetof(struct ipv4_5tuple, port_dst),
     213                 :            :         },
     214                 :            : };
     215                 :            : 
     216                 :            : #define IPV6_ADDR_LEN   16
     217                 :            : #define IPV6_ADDR_U16   (IPV6_ADDR_LEN / sizeof(uint16_t))
     218                 :            : #define IPV6_ADDR_U32   (IPV6_ADDR_LEN / sizeof(uint32_t))
     219                 :            : #define IPV6_ADDR_U64   (IPV6_ADDR_LEN / sizeof(uint64_t))
     220                 :            : 
     221                 :            : struct ipv6_5tuple {
     222                 :            :         uint8_t  proto;
     223                 :            :         uint32_t ip_src[IPV6_ADDR_U32];
     224                 :            :         uint32_t ip_dst[IPV6_ADDR_U32];
     225                 :            :         uint16_t port_src;
     226                 :            :         uint16_t port_dst;
     227                 :            : };
     228                 :            : 
     229                 :            : /* treat IPV6 address as uint32_t[4] (default mode) */
     230                 :            : enum {
     231                 :            :         PROTO_FIELD_IPV6,
     232                 :            :         SRC1_FIELD_IPV6,
     233                 :            :         SRC2_FIELD_IPV6,
     234                 :            :         SRC3_FIELD_IPV6,
     235                 :            :         SRC4_FIELD_IPV6,
     236                 :            :         DST1_FIELD_IPV6,
     237                 :            :         DST2_FIELD_IPV6,
     238                 :            :         DST3_FIELD_IPV6,
     239                 :            :         DST4_FIELD_IPV6,
     240                 :            :         SRCP_FIELD_IPV6,
     241                 :            :         DSTP_FIELD_IPV6,
     242                 :            :         NUM_FIELDS_IPV6
     243                 :            : };
     244                 :            : 
     245                 :            : /* treat IPV6 address as uint64_t[2] (default mode) */
     246                 :            : enum {
     247                 :            :         PROTO_FIELD_IPV6_U64,
     248                 :            :         SRC1_FIELD_IPV6_U64,
     249                 :            :         SRC2_FIELD_IPV6_U64,
     250                 :            :         DST1_FIELD_IPV6_U64,
     251                 :            :         DST2_FIELD_IPV6_U64,
     252                 :            :         SRCP_FIELD_IPV6_U64,
     253                 :            :         DSTP_FIELD_IPV6_U64,
     254                 :            :         NUM_FIELDS_IPV6_U64
     255                 :            : };
     256                 :            : 
     257                 :            : enum {
     258                 :            :         PROTO_INDEX_IPV6_U64 = PROTO_FIELD_IPV6_U64,
     259                 :            :         SRC1_INDEX_IPV6_U64 = SRC1_FIELD_IPV6_U64,
     260                 :            :         SRC2_INDEX_IPV6_U64 = SRC2_FIELD_IPV6_U64 + 1,
     261                 :            :         DST1_INDEX_IPV6_U64 = DST1_FIELD_IPV6_U64 + 2,
     262                 :            :         DST2_INDEX_IPV6_U64 = DST2_FIELD_IPV6_U64 + 3,
     263                 :            :         PRT_INDEX_IPV6_U64 = SRCP_FIELD_IPV6 + 4,
     264                 :            : };
     265                 :            : 
     266                 :            : struct rte_acl_field_def ipv6_defs[NUM_FIELDS_IPV6] = {
     267                 :            :         {
     268                 :            :                 .type = RTE_ACL_FIELD_TYPE_BITMASK,
     269                 :            :                 .size = sizeof(uint8_t),
     270                 :            :                 .field_index = PROTO_FIELD_IPV6,
     271                 :            :                 .input_index = PROTO_FIELD_IPV6,
     272                 :            :                 .offset = offsetof(struct ipv6_5tuple, proto),
     273                 :            :         },
     274                 :            :         {
     275                 :            :                 .type = RTE_ACL_FIELD_TYPE_MASK,
     276                 :            :                 .size = sizeof(uint32_t),
     277                 :            :                 .field_index = SRC1_FIELD_IPV6,
     278                 :            :                 .input_index = SRC1_FIELD_IPV6,
     279                 :            :                 .offset = offsetof(struct ipv6_5tuple, ip_src[0]),
     280                 :            :         },
     281                 :            :         {
     282                 :            :                 .type = RTE_ACL_FIELD_TYPE_MASK,
     283                 :            :                 .size = sizeof(uint32_t),
     284                 :            :                 .field_index = SRC2_FIELD_IPV6,
     285                 :            :                 .input_index = SRC2_FIELD_IPV6,
     286                 :            :                 .offset = offsetof(struct ipv6_5tuple, ip_src[1]),
     287                 :            :         },
     288                 :            :         {
     289                 :            :                 .type = RTE_ACL_FIELD_TYPE_MASK,
     290                 :            :                 .size = sizeof(uint32_t),
     291                 :            :                 .field_index = SRC3_FIELD_IPV6,
     292                 :            :                 .input_index = SRC3_FIELD_IPV6,
     293                 :            :                 .offset = offsetof(struct ipv6_5tuple, ip_src[2]),
     294                 :            :         },
     295                 :            :         {
     296                 :            :                 .type = RTE_ACL_FIELD_TYPE_MASK,
     297                 :            :                 .size = sizeof(uint32_t),
     298                 :            :                 .field_index = SRC4_FIELD_IPV6,
     299                 :            :                 .input_index = SRC4_FIELD_IPV6,
     300                 :            :                 .offset = offsetof(struct ipv6_5tuple, ip_src[3]),
     301                 :            :         },
     302                 :            :         {
     303                 :            :                 .type = RTE_ACL_FIELD_TYPE_MASK,
     304                 :            :                 .size = sizeof(uint32_t),
     305                 :            :                 .field_index = DST1_FIELD_IPV6,
     306                 :            :                 .input_index = DST1_FIELD_IPV6,
     307                 :            :                 .offset = offsetof(struct ipv6_5tuple, ip_dst[0]),
     308                 :            :         },
     309                 :            :         {
     310                 :            :                 .type = RTE_ACL_FIELD_TYPE_MASK,
     311                 :            :                 .size = sizeof(uint32_t),
     312                 :            :                 .field_index = DST2_FIELD_IPV6,
     313                 :            :                 .input_index = DST2_FIELD_IPV6,
     314                 :            :                 .offset = offsetof(struct ipv6_5tuple, ip_dst[1]),
     315                 :            :         },
     316                 :            :         {
     317                 :            :                 .type = RTE_ACL_FIELD_TYPE_MASK,
     318                 :            :                 .size = sizeof(uint32_t),
     319                 :            :                 .field_index = DST3_FIELD_IPV6,
     320                 :            :                 .input_index = DST3_FIELD_IPV6,
     321                 :            :                 .offset = offsetof(struct ipv6_5tuple, ip_dst[2]),
     322                 :            :         },
     323                 :            :         {
     324                 :            :                 .type = RTE_ACL_FIELD_TYPE_MASK,
     325                 :            :                 .size = sizeof(uint32_t),
     326                 :            :                 .field_index = DST4_FIELD_IPV6,
     327                 :            :                 .input_index = DST4_FIELD_IPV6,
     328                 :            :                 .offset = offsetof(struct ipv6_5tuple, ip_dst[3]),
     329                 :            :         },
     330                 :            :         {
     331                 :            :                 .type = RTE_ACL_FIELD_TYPE_RANGE,
     332                 :            :                 .size = sizeof(uint16_t),
     333                 :            :                 .field_index = SRCP_FIELD_IPV6,
     334                 :            :                 .input_index = SRCP_FIELD_IPV6,
     335                 :            :                 .offset = offsetof(struct ipv6_5tuple, port_src),
     336                 :            :         },
     337                 :            :         {
     338                 :            :                 .type = RTE_ACL_FIELD_TYPE_RANGE,
     339                 :            :                 .size = sizeof(uint16_t),
     340                 :            :                 .field_index = DSTP_FIELD_IPV6,
     341                 :            :                 .input_index = SRCP_FIELD_IPV6,
     342                 :            :                 .offset = offsetof(struct ipv6_5tuple, port_dst),
     343                 :            :         },
     344                 :            : };
     345                 :            : 
     346                 :            : struct rte_acl_field_def ipv6_u64_defs[NUM_FIELDS_IPV6_U64] = {
     347                 :            :         {
     348                 :            :                 .type = RTE_ACL_FIELD_TYPE_BITMASK,
     349                 :            :                 .size = sizeof(uint8_t),
     350                 :            :                 .field_index = PROTO_FIELD_IPV6_U64,
     351                 :            :                 .input_index = PROTO_FIELD_IPV6_U64,
     352                 :            :                 .offset = offsetof(struct ipv6_5tuple, proto),
     353                 :            :         },
     354                 :            :         {
     355                 :            :                 .type = RTE_ACL_FIELD_TYPE_MASK,
     356                 :            :                 .size = sizeof(uint64_t),
     357                 :            :                 .field_index = SRC1_FIELD_IPV6_U64,
     358                 :            :                 .input_index = SRC1_INDEX_IPV6_U64,
     359                 :            :                 .offset = offsetof(struct ipv6_5tuple, ip_src[0]),
     360                 :            :         },
     361                 :            :         {
     362                 :            :                 .type = RTE_ACL_FIELD_TYPE_MASK,
     363                 :            :                 .size = sizeof(uint64_t),
     364                 :            :                 .field_index = SRC2_FIELD_IPV6_U64,
     365                 :            :                 .input_index = SRC2_INDEX_IPV6_U64,
     366                 :            :                 .offset = offsetof(struct ipv6_5tuple, ip_src[2]),
     367                 :            :         },
     368                 :            :         {
     369                 :            :                 .type = RTE_ACL_FIELD_TYPE_MASK,
     370                 :            :                 .size = sizeof(uint64_t),
     371                 :            :                 .field_index = DST1_FIELD_IPV6_U64,
     372                 :            :                 .input_index = DST1_INDEX_IPV6_U64,
     373                 :            :                 .offset = offsetof(struct ipv6_5tuple, ip_dst[0]),
     374                 :            :         },
     375                 :            :         {
     376                 :            :                 .type = RTE_ACL_FIELD_TYPE_MASK,
     377                 :            :                 .size = sizeof(uint64_t),
     378                 :            :                 .field_index = DST2_FIELD_IPV6_U64,
     379                 :            :                 .input_index = DST2_INDEX_IPV6_U64,
     380                 :            :                 .offset = offsetof(struct ipv6_5tuple, ip_dst[2]),
     381                 :            :         },
     382                 :            :         {
     383                 :            :                 .type = RTE_ACL_FIELD_TYPE_RANGE,
     384                 :            :                 .size = sizeof(uint16_t),
     385                 :            :                 .field_index = SRCP_FIELD_IPV6_U64,
     386                 :            :                 .input_index = PRT_INDEX_IPV6_U64,
     387                 :            :                 .offset = offsetof(struct ipv6_5tuple, port_src),
     388                 :            :         },
     389                 :            :         {
     390                 :            :                 .type = RTE_ACL_FIELD_TYPE_RANGE,
     391                 :            :                 .size = sizeof(uint16_t),
     392                 :            :                 .field_index = DSTP_FIELD_IPV6_U64,
     393                 :            :                 .input_index = PRT_INDEX_IPV6_U64,
     394                 :            :                 .offset = offsetof(struct ipv6_5tuple, port_dst),
     395                 :            :         },
     396                 :            : };
     397                 :            : 
     398                 :            : enum {
     399                 :            :         CB_FLD_SRC_ADDR,
     400                 :            :         CB_FLD_DST_ADDR,
     401                 :            :         CB_FLD_SRC_PORT_LOW,
     402                 :            :         CB_FLD_SRC_PORT_DLM,
     403                 :            :         CB_FLD_SRC_PORT_HIGH,
     404                 :            :         CB_FLD_DST_PORT_LOW,
     405                 :            :         CB_FLD_DST_PORT_DLM,
     406                 :            :         CB_FLD_DST_PORT_HIGH,
     407                 :            :         CB_FLD_PROTO,
     408                 :            :         CB_FLD_NUM,
     409                 :            : };
     410                 :            : 
     411                 :            : enum {
     412                 :            :         CB_TRC_SRC_ADDR,
     413                 :            :         CB_TRC_DST_ADDR,
     414                 :            :         CB_TRC_SRC_PORT,
     415                 :            :         CB_TRC_DST_PORT,
     416                 :            :         CB_TRC_PROTO,
     417                 :            :         CB_TRC_NUM,
     418                 :            : };
     419                 :            : 
     420                 :            : RTE_ACL_RULE_DEF(acl_rule, RTE_ACL_MAX_FIELDS);
     421                 :            : 
     422                 :            : static const char cb_port_delim[] = ":";
     423                 :            : 
     424                 :            : static char line[LINE_MAX];
     425                 :            : 
     426                 :            : #define dump_verbose(lvl, fh, fmt, ...) do { \
     427                 :            :         if ((lvl) <= (int32_t)config.verbose)        \
     428                 :            :                 fprintf(fh, fmt, ##__VA_ARGS__);         \
     429                 :            : } while (0)
     430                 :            : 
     431                 :            : 
     432                 :            : /*
     433                 :            :  * Parse ClassBench input trace (test vectors and expected results) file.
     434                 :            :  * Expected format:
     435                 :            :  * <src_ipv4_addr> <space> <dst_ipv4_addr> <space> \
     436                 :            :  * <src_port> <space> <dst_port> <space> <proto>
     437                 :            :  */
     438                 :            : static int
     439                 :          0 : parse_cb_ipv4_trace(char *str, struct ipv4_5tuple *v)
     440                 :            : {
     441                 :            :         int i;
     442                 :            :         char *s, *sp, *in[CB_TRC_NUM];
     443                 :            :         static const char *dlm = " \t\n";
     444                 :            : 
     445                 :            :         s = str;
     446                 :          0 :         for (i = 0; i != RTE_DIM(in); i++) {
     447                 :          0 :                 in[i] = strtok_r(s, dlm, &sp);
     448                 :          0 :                 if (in[i] == NULL)
     449                 :            :                         return -EINVAL;
     450                 :            :                 s = NULL;
     451                 :            :         }
     452                 :            : 
     453                 :          0 :         GET_CB_FIELD(in[CB_TRC_SRC_ADDR], v->ip_src, 0, UINT32_MAX, 0);
     454                 :          0 :         GET_CB_FIELD(in[CB_TRC_DST_ADDR], v->ip_dst, 0, UINT32_MAX, 0);
     455                 :          0 :         GET_CB_FIELD(in[CB_TRC_SRC_PORT], v->port_src, 0, UINT16_MAX, 0);
     456                 :          0 :         GET_CB_FIELD(in[CB_TRC_DST_PORT], v->port_dst, 0, UINT16_MAX, 0);
     457                 :          0 :         GET_CB_FIELD(in[CB_TRC_PROTO], v->proto, 0, UINT8_MAX, 0);
     458                 :            : 
     459                 :            :         /* convert to network byte order. */
     460                 :          0 :         v->ip_src = rte_cpu_to_be_32(v->ip_src);
     461                 :          0 :         v->ip_dst = rte_cpu_to_be_32(v->ip_dst);
     462                 :          0 :         v->port_src = rte_cpu_to_be_16(v->port_src);
     463                 :          0 :         v->port_dst = rte_cpu_to_be_16(v->port_dst);
     464                 :            : 
     465                 :          0 :         return 0;
     466                 :            : }
     467                 :            : 
     468                 :            : static int
     469                 :            : parse_cb_ipv6_addr_trace(const char *in, uint32_t v[IPV6_ADDR_U32])
     470                 :            : {
     471                 :          0 :         if (inet_pton(AF_INET6, in, v) != 1)
     472                 :            :                 return -EINVAL;
     473                 :            : 
     474                 :            :         return 0;
     475                 :            : }
     476                 :            : 
     477                 :            : /*
     478                 :            :  * Parse ClassBench input trace (test vectors and expected results) file.
     479                 :            :  * Expected format:
     480                 :            :  * <src_ipv6_addr> <space> <dst_ipv6_addr> <space> \
     481                 :            :  * <src_port> <space> <dst_port> <space> <proto>
     482                 :            :  */
     483                 :            : static int
     484                 :          0 : parse_cb_ipv6_trace(char *str, struct ipv6_5tuple *v)
     485                 :            : {
     486                 :            :         int32_t i, rc;
     487                 :            :         char *s, *sp, *in[CB_TRC_NUM];
     488                 :            :         static const char *dlm = " \t\n";
     489                 :            : 
     490                 :            :         s = str;
     491                 :          0 :         for (i = 0; i != RTE_DIM(in); i++) {
     492                 :          0 :                 in[i] = strtok_r(s, dlm, &sp);
     493                 :          0 :                 if (in[i] == NULL)
     494                 :            :                         return -EINVAL;
     495                 :            :                 s = NULL;
     496                 :            :         }
     497                 :            : 
     498                 :            :         /* get ip6 src address. */
     499                 :          0 :         rc = parse_cb_ipv6_addr_trace(in[CB_TRC_SRC_ADDR], v->ip_src);
     500                 :            :         if (rc != 0)
     501                 :            :                 return rc;
     502                 :            : 
     503                 :            :         /* get ip6 dst address. */
     504                 :          0 :         rc = parse_cb_ipv6_addr_trace(in[CB_TRC_DST_ADDR], v->ip_dst);
     505                 :            :         if (rc != 0)
     506                 :            :                 return rc;
     507                 :            : 
     508                 :          0 :         GET_CB_FIELD(in[CB_TRC_SRC_PORT], v->port_src, 0, UINT16_MAX, 0);
     509                 :          0 :         GET_CB_FIELD(in[CB_TRC_DST_PORT], v->port_dst, 0, UINT16_MAX, 0);
     510                 :          0 :         GET_CB_FIELD(in[CB_TRC_PROTO], v->proto, 0, UINT8_MAX, 0);
     511                 :            : 
     512                 :            :         /* convert to network byte order. */
     513                 :          0 :         v->port_src = rte_cpu_to_be_16(v->port_src);
     514                 :          0 :         v->port_dst = rte_cpu_to_be_16(v->port_dst);
     515                 :            : 
     516                 :          0 :         return 0;
     517                 :            : }
     518                 :            : 
     519                 :            : /* Bypass comment and empty lines */
     520                 :            : static int
     521                 :          0 : skip_line(const char *buf)
     522                 :            : {
     523                 :            :         uint32_t i;
     524                 :            : 
     525                 :          0 :         for (i = 0; isspace(buf[i]) != 0; i++)
     526                 :            :                 ;
     527                 :            : 
     528                 :          0 :         if (buf[i] == 0 || buf[i] == COMMENT_LEAD_CHAR)
     529                 :          0 :                 return 1;
     530                 :            : 
     531                 :            :         return 0;
     532                 :            : }
     533                 :            : 
     534                 :            : static void
     535                 :          0 : tracef_init(void)
     536                 :            : {
     537                 :            :         static const char name[] = APP_NAME;
     538                 :            :         FILE *f;
     539                 :            :         size_t sz;
     540                 :            :         uint32_t i, k, n;
     541                 :            :         struct ipv4_5tuple *v;
     542                 :            :         struct ipv6_5tuple *w;
     543                 :            : 
     544                 :          0 :         sz = config.nb_traces * (config.ipv6 ? sizeof(*w) : sizeof(*v));
     545                 :          0 :         config.traces = rte_zmalloc_socket(name, sz, RTE_CACHE_LINE_SIZE,
     546                 :            :                         SOCKET_ID_ANY);
     547                 :          0 :         if (config.traces == NULL)
     548                 :          0 :                 rte_exit(EXIT_FAILURE, "Cannot allocate %zu bytes for "
     549                 :            :                         "requested %u number of trace records\n",
     550                 :            :                         sz, config.nb_traces);
     551                 :            : 
     552                 :          0 :         f = fopen(config.trace_file, "r");
     553                 :          0 :         if (f == NULL)
     554                 :          0 :                 rte_exit(-EINVAL, "failed to open file: %s\n",
     555                 :            :                         config.trace_file);
     556                 :            : 
     557                 :          0 :         v = config.traces;
     558                 :            :         w = config.traces;
     559                 :            :         k = 0;
     560                 :            :         n = 0;
     561                 :          0 :         for (i = 0; n != config.nb_traces; i++) {
     562                 :            : 
     563                 :          0 :                 if (fgets(line, sizeof(line), f) == NULL)
     564                 :            :                         break;
     565                 :            : 
     566                 :          0 :                 if (skip_line(line) != 0) {
     567                 :          0 :                         k++;
     568                 :          0 :                         continue;
     569                 :            :                 }
     570                 :            : 
     571                 :          0 :                 n = i - k;
     572                 :            : 
     573                 :          0 :                 if (config.ipv6) {
     574                 :          0 :                         if (parse_cb_ipv6_trace(line, w + n) != 0)
     575                 :          0 :                                 rte_exit(EXIT_FAILURE,
     576                 :            :                                         "%s: failed to parse ipv6 trace "
     577                 :            :                                         "record at line %u\n",
     578                 :            :                                         config.trace_file, i + 1);
     579                 :            :                 } else {
     580                 :          0 :                         if (parse_cb_ipv4_trace(line, v + n) != 0)
     581                 :          0 :                                 rte_exit(EXIT_FAILURE,
     582                 :            :                                         "%s: failed to parse ipv4 trace "
     583                 :            :                                         "record at line %u\n",
     584                 :            :                                         config.trace_file, i + 1);
     585                 :            :                 }
     586                 :            :         }
     587                 :            : 
     588                 :          0 :         config.used_traces = i - k;
     589                 :          0 :         fclose(f);
     590                 :          0 : }
     591                 :            : 
     592                 :            : static int
     593                 :          0 : parse_ipv6_u32_net(char *in, struct rte_acl_field field[IPV6_ADDR_U32])
     594                 :            : {
     595                 :            :         char *sa, *sm, *sv;
     596                 :            :         uint32_t i, m, v[IPV6_ADDR_U32];
     597                 :            : 
     598                 :            :         const char *dlm = "/";
     599                 :            :         const uint32_t nbu32 = sizeof(uint32_t) * CHAR_BIT;
     600                 :            : 
     601                 :            :         /* get address. */
     602                 :          0 :         sv = NULL;
     603                 :          0 :         sa = strtok_r(in, dlm, &sv);
     604                 :          0 :         if (sa == NULL)
     605                 :            :                 return -EINVAL;
     606                 :          0 :         sm = strtok_r(NULL, dlm, &sv);
     607                 :          0 :         if (sm == NULL)
     608                 :            :                 return -EINVAL;
     609                 :            : 
     610                 :          0 :         if (inet_pton(AF_INET6, sa, v) != 1)
     611                 :            :                 return -EINVAL;
     612                 :            : 
     613                 :          0 :         v[0] = rte_be_to_cpu_32(v[0]);
     614                 :          0 :         v[1] = rte_be_to_cpu_32(v[1]);
     615                 :          0 :         v[2] = rte_be_to_cpu_32(v[2]);
     616                 :          0 :         v[3] = rte_be_to_cpu_32(v[3]);
     617                 :            : 
     618                 :            :         /* get mask. */
     619                 :          0 :         GET_CB_FIELD(sm, m, 0, CHAR_BIT * sizeof(v), 0);
     620                 :            : 
     621                 :            :         /* put all together. */
     622                 :          0 :         for (i = 0; i != RTE_DIM(v); i++) {
     623                 :          0 :                 if (m >= (i + 1) * nbu32)
     624                 :          0 :                         field[i].mask_range.u32 = nbu32;
     625                 :            :                 else
     626                 :          0 :                         field[i].mask_range.u32 = m > (i * nbu32) ?
     627                 :          0 :                                 m - (i * nbu32) : 0;
     628                 :            : 
     629                 :          0 :                 field[i].value.u32 = v[i];
     630                 :            :         }
     631                 :            : 
     632                 :            :         return 0;
     633                 :            : }
     634                 :            : 
     635                 :            : static int
     636                 :          0 : parse_ipv6_u64_net(char *in, struct rte_acl_field field[IPV6_ADDR_U64])
     637                 :            : {
     638                 :            :         char *sa, *sm, *sv;
     639                 :            :         uint32_t i, m;
     640                 :            :         uint64_t v[IPV6_ADDR_U64];
     641                 :            : 
     642                 :            :         const char *dlm = "/";
     643                 :            :         const uint32_t nbu64 = sizeof(uint64_t) * CHAR_BIT;
     644                 :            : 
     645                 :            :         /* get address. */
     646                 :          0 :         sv = NULL;
     647                 :          0 :         sa = strtok_r(in, dlm, &sv);
     648                 :          0 :         if (sa == NULL)
     649                 :            :                 return -EINVAL;
     650                 :          0 :         sm = strtok_r(NULL, dlm, &sv);
     651                 :          0 :         if (sm == NULL)
     652                 :            :                 return -EINVAL;
     653                 :            : 
     654                 :          0 :         if (inet_pton(AF_INET6, sa, v) != 1)
     655                 :            :                 return -EINVAL;
     656                 :            : 
     657                 :          0 :         v[0] = rte_be_to_cpu_64(v[0]);
     658                 :          0 :         v[1] = rte_be_to_cpu_64(v[1]);
     659                 :            : 
     660                 :            :         /* get mask. */
     661                 :          0 :         GET_CB_FIELD(sm, m, 0, CHAR_BIT * sizeof(v), 0);
     662                 :            : 
     663                 :            :         /* put all together. */
     664                 :          0 :         for (i = 0; i != RTE_DIM(v); i++) {
     665                 :          0 :                 if (m >= (i + 1) * nbu64)
     666                 :          0 :                         field[i].mask_range.u32 = nbu64;
     667                 :            :                 else
     668                 :          0 :                         field[i].mask_range.u32 = m > (i * nbu64) ?
     669                 :          0 :                                 m - (i * nbu64) : 0;
     670                 :            : 
     671                 :          0 :                 field[i].value.u64 = v[i];
     672                 :            :         }
     673                 :            : 
     674                 :            :         return 0;
     675                 :            : }
     676                 :            : 
     677                 :            : static int
     678                 :          0 : parse_cb_ipv6_rule(char *str, struct acl_rule *v, int frmt)
     679                 :            : {
     680                 :            :         int i, rc;
     681                 :            :         uint32_t fidx;
     682                 :            :         const uint32_t *field_map;
     683                 :            :         char *s, *sp, *in[CB_FLD_NUM];
     684                 :            :         int (*parse_ipv6_net)(char *s, struct rte_acl_field f[]);
     685                 :            : 
     686                 :            :         static const char *dlm = " \t\n";
     687                 :            : 
     688                 :            :         static const uint32_t field_map_u32[CB_FLD_NUM] = {
     689                 :            :                 [CB_FLD_SRC_ADDR] = SRC1_FIELD_IPV6,
     690                 :            :                 [CB_FLD_DST_ADDR] = DST1_FIELD_IPV6,
     691                 :            :                 [CB_FLD_SRC_PORT_LOW] = SRCP_FIELD_IPV6,
     692                 :            :                 [CB_FLD_SRC_PORT_HIGH] = SRCP_FIELD_IPV6,
     693                 :            :                 [CB_FLD_DST_PORT_LOW] = DSTP_FIELD_IPV6,
     694                 :            :                 [CB_FLD_DST_PORT_HIGH] = DSTP_FIELD_IPV6,
     695                 :            :                 [CB_FLD_PROTO] = PROTO_FIELD_IPV6,
     696                 :            :         };
     697                 :            : 
     698                 :            :         static const uint32_t field_map_u64[CB_FLD_NUM] = {
     699                 :            :                 [CB_FLD_SRC_ADDR] = SRC1_FIELD_IPV6_U64,
     700                 :            :                 [CB_FLD_DST_ADDR] = DST1_FIELD_IPV6_U64,
     701                 :            :                 [CB_FLD_SRC_PORT_LOW] = SRCP_FIELD_IPV6_U64,
     702                 :            :                 [CB_FLD_SRC_PORT_HIGH] = SRCP_FIELD_IPV6_U64,
     703                 :            :                 [CB_FLD_DST_PORT_LOW] = DSTP_FIELD_IPV6_U64,
     704                 :            :                 [CB_FLD_DST_PORT_HIGH] = DSTP_FIELD_IPV6_U64,
     705                 :            :                 [CB_FLD_PROTO] = PROTO_FIELD_IPV6_U64,
     706                 :            :         };
     707                 :            : 
     708                 :          0 :         if (frmt == IPV6_FRMT_U32) {
     709                 :            :                 field_map = field_map_u32;
     710                 :            :                 parse_ipv6_net = parse_ipv6_u32_net;
     711                 :          0 :         } else if (frmt == IPV6_FRMT_U64) {
     712                 :            :                 field_map = field_map_u64;
     713                 :            :                 parse_ipv6_net = parse_ipv6_u64_net;
     714                 :            :         } else
     715                 :            :                 return -ENOTSUP;
     716                 :            : 
     717                 :            :         /*
     718                 :            :          * Skip leading '@'
     719                 :            :          */
     720                 :          0 :         if (strchr(str, '@') != str)
     721                 :            :                 return -EINVAL;
     722                 :            : 
     723                 :          0 :         s = str + 1;
     724                 :            : 
     725                 :          0 :         for (i = 0; i != RTE_DIM(in); i++) {
     726                 :          0 :                 in[i] = strtok_r(s, dlm, &sp);
     727                 :          0 :                 if (in[i] == NULL)
     728                 :            :                         return -EINVAL;
     729                 :            :                 s = NULL;
     730                 :            :         }
     731                 :            : 
     732                 :            :         fidx = CB_FLD_SRC_ADDR;
     733                 :          0 :         rc = parse_ipv6_net(in[fidx], v->field + field_map[fidx]);
     734                 :          0 :         if (rc != 0) {
     735                 :          0 :                 RTE_LOG(ERR, TESTACL,
     736                 :            :                         "failed to read source address/mask: %s\n", in[fidx]);
     737                 :          0 :                 return rc;
     738                 :            :         }
     739                 :            : 
     740                 :            :         fidx = CB_FLD_DST_ADDR;
     741                 :          0 :         rc = parse_ipv6_net(in[fidx], v->field + field_map[fidx]);
     742                 :          0 :         if (rc != 0) {
     743                 :          0 :                 RTE_LOG(ERR, TESTACL,
     744                 :            :                         "failed to read destination address/mask: %s\n",
     745                 :            :                         in[fidx]);
     746                 :          0 :                 return rc;
     747                 :            :         }
     748                 :            : 
     749                 :            :         /* source port. */
     750                 :            :         fidx = CB_FLD_SRC_PORT_LOW;
     751                 :          0 :         GET_CB_FIELD(in[fidx], v->field[field_map[fidx]].value.u16,
     752                 :            :                 0, UINT16_MAX, 0);
     753                 :            : 
     754                 :            :         fidx = CB_FLD_SRC_PORT_HIGH;
     755                 :          0 :         GET_CB_FIELD(in[fidx], v->field[field_map[fidx]].mask_range.u16,
     756                 :            :                 0, UINT16_MAX, 0);
     757                 :            : 
     758                 :          0 :         if (strncmp(in[CB_FLD_SRC_PORT_DLM], cb_port_delim,
     759                 :            :                         sizeof(cb_port_delim)) != 0)
     760                 :            :                 return -EINVAL;
     761                 :            : 
     762                 :            :         /* destination port. */
     763                 :            :         fidx = CB_FLD_DST_PORT_LOW;
     764                 :          0 :         GET_CB_FIELD(in[fidx], v->field[field_map[fidx]].value.u16,
     765                 :            :                 0, UINT16_MAX, 0);
     766                 :            : 
     767                 :            :         fidx = CB_FLD_DST_PORT_HIGH;
     768                 :          0 :         GET_CB_FIELD(in[fidx], v->field[field_map[fidx]].mask_range.u16,
     769                 :            :                 0, UINT16_MAX, 0);
     770                 :            : 
     771                 :          0 :         if (strncmp(in[CB_FLD_DST_PORT_DLM], cb_port_delim,
     772                 :            :                         sizeof(cb_port_delim)) != 0)
     773                 :            :                 return -EINVAL;
     774                 :            : 
     775                 :            :         fidx = CB_FLD_PROTO;
     776                 :          0 :         GET_CB_FIELD(in[fidx], v->field[field_map[fidx]].value.u8,
     777                 :            :                 0, UINT8_MAX, '/');
     778                 :          0 :         GET_CB_FIELD(in[fidx], v->field[field_map[fidx]].mask_range.u8,
     779                 :            :                 0, UINT8_MAX, 0);
     780                 :            : 
     781                 :          0 :         return 0;
     782                 :            : }
     783                 :            : 
     784                 :            : static int
     785                 :          0 : parse_cb_ipv6_u32_rule(char *str, struct acl_rule *v)
     786                 :            : {
     787                 :          0 :         return parse_cb_ipv6_rule(str, v, IPV6_FRMT_U32);
     788                 :            : }
     789                 :            : 
     790                 :            : static int
     791                 :          0 : parse_cb_ipv6_u64_rule(char *str, struct acl_rule *v)
     792                 :            : {
     793                 :          0 :         return parse_cb_ipv6_rule(str, v, IPV6_FRMT_U64);
     794                 :            : }
     795                 :            : 
     796                 :            : static int
     797                 :          0 : parse_ipv4_net(char *in, uint32_t *addr, uint32_t *mask_len)
     798                 :            : {
     799                 :            :         char *sa, *sm, *sv;
     800                 :            :         uint32_t m, v;
     801                 :            : 
     802                 :            :         const char *dlm = "/";
     803                 :            : 
     804                 :          0 :         sv = NULL;
     805                 :          0 :         sa = strtok_r(in, dlm, &sv);
     806                 :          0 :         if (sa == NULL)
     807                 :            :                 return -EINVAL;
     808                 :          0 :         sm = strtok_r(NULL, dlm, &sv);
     809                 :          0 :         if (sm == NULL)
     810                 :            :                 return -EINVAL;
     811                 :            : 
     812                 :          0 :         if (inet_pton(AF_INET, sa, &v) != 1)
     813                 :            :                 return -EINVAL;
     814                 :            : 
     815                 :          0 :         addr[0] = rte_be_to_cpu_32(v);
     816                 :            : 
     817                 :          0 :         GET_CB_FIELD(sm, m, 0, sizeof(uint32_t) * CHAR_BIT, 0);
     818                 :          0 :         mask_len[0] = m;
     819                 :            : 
     820                 :          0 :         return 0;
     821                 :            : }
     822                 :            : /*
     823                 :            :  * Parse ClassBench rules file.
     824                 :            :  * Expected format:
     825                 :            :  * '@'<src_ipv4_addr>'/'<masklen> <space> \
     826                 :            :  * <dst_ipv4_addr>'/'<masklen> <space> \
     827                 :            :  * <src_port_low> <space> ":" <src_port_high> <space> \
     828                 :            :  * <dst_port_low> <space> ":" <dst_port_high> <space> \
     829                 :            :  * <proto>'/'<mask>
     830                 :            :  */
     831                 :            : static int
     832                 :          0 : parse_cb_ipv4_rule(char *str, struct acl_rule *v)
     833                 :            : {
     834                 :            :         int i, rc;
     835                 :            :         char *s, *sp, *in[CB_FLD_NUM];
     836                 :            :         static const char *dlm = " \t\n";
     837                 :            : 
     838                 :            :         /*
     839                 :            :          * Skip leading '@'
     840                 :            :          */
     841                 :          0 :         if (strchr(str, '@') != str)
     842                 :            :                 return -EINVAL;
     843                 :            : 
     844                 :          0 :         s = str + 1;
     845                 :            : 
     846                 :          0 :         for (i = 0; i != RTE_DIM(in); i++) {
     847                 :          0 :                 in[i] = strtok_r(s, dlm, &sp);
     848                 :          0 :                 if (in[i] == NULL)
     849                 :            :                         return -EINVAL;
     850                 :            :                 s = NULL;
     851                 :            :         }
     852                 :            : 
     853                 :          0 :         rc = parse_ipv4_net(in[CB_FLD_SRC_ADDR],
     854                 :            :                         &v->field[SRC_FIELD_IPV4].value.u32,
     855                 :            :                         &v->field[SRC_FIELD_IPV4].mask_range.u32);
     856                 :          0 :         if (rc != 0) {
     857                 :          0 :                 RTE_LOG(ERR, TESTACL,
     858                 :            :                         "failed to read source address/mask: %s\n",
     859                 :            :                         in[CB_FLD_SRC_ADDR]);
     860                 :          0 :                 return rc;
     861                 :            :         }
     862                 :            : 
     863                 :          0 :         rc = parse_ipv4_net(in[CB_FLD_DST_ADDR],
     864                 :            :                         &v->field[DST_FIELD_IPV4].value.u32,
     865                 :            :                         &v->field[DST_FIELD_IPV4].mask_range.u32);
     866                 :          0 :         if (rc != 0) {
     867                 :          0 :                 RTE_LOG(ERR, TESTACL,
     868                 :            :                         "failed to read destination address/mask: %s\n",
     869                 :            :                         in[CB_FLD_DST_ADDR]);
     870                 :          0 :                 return rc;
     871                 :            :         }
     872                 :            : 
     873                 :            :         /* source port. */
     874                 :          0 :         GET_CB_FIELD(in[CB_FLD_SRC_PORT_LOW],
     875                 :            :                 v->field[SRCP_FIELD_IPV4].value.u16,
     876                 :            :                 0, UINT16_MAX, 0);
     877                 :          0 :         GET_CB_FIELD(in[CB_FLD_SRC_PORT_HIGH],
     878                 :            :                 v->field[SRCP_FIELD_IPV4].mask_range.u16,
     879                 :            :                 0, UINT16_MAX, 0);
     880                 :            : 
     881                 :          0 :         if (strncmp(in[CB_FLD_SRC_PORT_DLM], cb_port_delim,
     882                 :            :                         sizeof(cb_port_delim)) != 0)
     883                 :            :                 return -EINVAL;
     884                 :            : 
     885                 :            :         /* destination port. */
     886                 :          0 :         GET_CB_FIELD(in[CB_FLD_DST_PORT_LOW],
     887                 :            :                 v->field[DSTP_FIELD_IPV4].value.u16,
     888                 :            :                 0, UINT16_MAX, 0);
     889                 :          0 :         GET_CB_FIELD(in[CB_FLD_DST_PORT_HIGH],
     890                 :            :                 v->field[DSTP_FIELD_IPV4].mask_range.u16,
     891                 :            :                 0, UINT16_MAX, 0);
     892                 :            : 
     893                 :          0 :         if (strncmp(in[CB_FLD_DST_PORT_DLM], cb_port_delim,
     894                 :            :                         sizeof(cb_port_delim)) != 0)
     895                 :            :                 return -EINVAL;
     896                 :            : 
     897                 :          0 :         GET_CB_FIELD(in[CB_FLD_PROTO], v->field[PROTO_FIELD_IPV4].value.u8,
     898                 :            :                 0, UINT8_MAX, '/');
     899                 :          0 :         GET_CB_FIELD(in[CB_FLD_PROTO], v->field[PROTO_FIELD_IPV4].mask_range.u8,
     900                 :            :                 0, UINT8_MAX, 0);
     901                 :            : 
     902                 :          0 :         return 0;
     903                 :            : }
     904                 :            : 
     905                 :            : typedef int (*parse_5tuple)(char *text, struct acl_rule *rule);
     906                 :            : 
     907                 :            : static int
     908                 :          0 : add_cb_rules(FILE *f, struct rte_acl_ctx *ctx)
     909                 :            : {
     910                 :            :         int rc;
     911                 :            :         uint32_t i, k, n;
     912                 :            :         struct acl_rule v;
     913                 :            :         parse_5tuple parser;
     914                 :            : 
     915                 :            :         static const parse_5tuple parser_func[] = {
     916                 :            :                 [IPV6_FRMT_NONE] = parse_cb_ipv4_rule,
     917                 :            :                 [IPV6_FRMT_U32] = parse_cb_ipv6_u32_rule,
     918                 :            :                 [IPV6_FRMT_U64] = parse_cb_ipv6_u64_rule,
     919                 :            :         };
     920                 :            : 
     921                 :            :         memset(&v, 0, sizeof(v));
     922                 :          0 :         parser = parser_func[config.ipv6];
     923                 :            : 
     924                 :            :         k = 0;
     925                 :          0 :         for (i = 1; fgets(line, sizeof(line), f) != NULL; i++) {
     926                 :            : 
     927                 :          0 :                 if (skip_line(line) != 0) {
     928                 :          0 :                         k++;
     929                 :          0 :                         continue;
     930                 :            :                 }
     931                 :            : 
     932                 :          0 :                 n = i - k;
     933                 :          0 :                 rc = parser(line, &v);
     934                 :          0 :                 if (rc != 0) {
     935                 :          0 :                         RTE_LOG(ERR, TESTACL, "line %u: parse_cb_ipv4vlan_rule"
     936                 :            :                                 " failed, error code: %d (%s)\n",
     937                 :            :                                 i, rc, strerror(-rc));
     938                 :          0 :                         return rc;
     939                 :            :                 }
     940                 :            : 
     941                 :          0 :                 v.data.category_mask = RTE_LEN2MASK(RTE_ACL_MAX_CATEGORIES,
     942                 :            :                         typeof(v.data.category_mask));
     943                 :          0 :                 v.data.priority = RTE_ACL_MAX_PRIORITY - n;
     944                 :          0 :                 v.data.userdata = n;
     945                 :            : 
     946                 :          0 :                 rc = rte_acl_add_rules(ctx, (struct rte_acl_rule *)&v, 1);
     947                 :          0 :                 if (rc != 0) {
     948                 :          0 :                         RTE_LOG(ERR, TESTACL, "line %u: failed to add rules "
     949                 :            :                                 "into ACL context, error code: %d (%s)\n",
     950                 :            :                                 i, rc, strerror(-rc));
     951                 :          0 :                         return rc;
     952                 :            :                 }
     953                 :            :         }
     954                 :            : 
     955                 :            :         return 0;
     956                 :            : }
     957                 :            : 
     958                 :            : static void
     959                 :          0 : acx_init(void)
     960                 :            : {
     961                 :            :         int ret;
     962                 :            :         FILE *f;
     963                 :            :         struct rte_acl_config cfg;
     964                 :            : 
     965                 :            :         memset(&cfg, 0, sizeof(cfg));
     966                 :            : 
     967                 :            :         /* setup ACL build config. */
     968                 :          0 :         if (config.ipv6 == IPV6_FRMT_U32) {
     969                 :          0 :                 cfg.num_fields = RTE_DIM(ipv6_defs);
     970                 :            :                 memcpy(&cfg.defs, ipv6_defs, sizeof(ipv6_defs));
     971                 :          0 :         } else if (config.ipv6 == IPV6_FRMT_U64) {
     972                 :          0 :                 cfg.num_fields = RTE_DIM(ipv6_u64_defs);
     973                 :            :                 memcpy(&cfg.defs, ipv6_u64_defs, sizeof(ipv6_u64_defs));
     974                 :            :         } else {
     975                 :          0 :                 cfg.num_fields = RTE_DIM(ipv4_defs);
     976                 :            :                 memcpy(&cfg.defs, ipv4_defs, sizeof(ipv4_defs));
     977                 :            :         }
     978                 :          0 :         cfg.num_categories = config.bld_categories;
     979                 :          0 :         cfg.max_size = config.max_size;
     980                 :            : 
     981                 :            :         /* setup ACL creation parameters. */
     982                 :          0 :         prm.rule_size = RTE_ACL_RULE_SZ(cfg.num_fields);
     983                 :          0 :         prm.max_rule_num = config.nb_rules;
     984                 :            : 
     985                 :          0 :         config.acx = rte_acl_create(&prm);
     986                 :          0 :         if (config.acx == NULL)
     987                 :          0 :                 rte_exit(rte_errno, "failed to create ACL context\n");
     988                 :            : 
     989                 :            :         /* set default classify method for this context. */
     990                 :          0 :         if (config.alg.alg != RTE_ACL_CLASSIFY_DEFAULT) {
     991                 :          0 :                 ret = rte_acl_set_ctx_classify(config.acx, config.alg.alg);
     992                 :          0 :                 if (ret != 0)
     993                 :          0 :                         rte_exit(ret, "failed to setup %s method "
     994                 :            :                                 "for ACL context\n", config.alg.name);
     995                 :            :         }
     996                 :            : 
     997                 :            :         /* add ACL rules. */
     998                 :          0 :         f = fopen(config.rule_file, "r");
     999                 :          0 :         if (f == NULL)
    1000                 :          0 :                 rte_exit(-EINVAL, "failed to open file %s\n",
    1001                 :            :                         config.rule_file);
    1002                 :            : 
    1003                 :          0 :         ret = add_cb_rules(f, config.acx);
    1004                 :          0 :         if (ret != 0)
    1005                 :          0 :                 rte_exit(ret, "failed to add rules into ACL context\n");
    1006                 :            : 
    1007                 :          0 :         fclose(f);
    1008                 :            : 
    1009                 :            :         /* perform build. */
    1010                 :          0 :         ret = rte_acl_build(config.acx, &cfg);
    1011                 :            : 
    1012                 :          0 :         dump_verbose(DUMP_NONE, stdout,
    1013                 :            :                 "rte_acl_build(%u) finished with %d\n",
    1014                 :            :                 config.bld_categories, ret);
    1015                 :            : 
    1016                 :          0 :         rte_acl_dump(config.acx);
    1017                 :            : 
    1018                 :          0 :         if (ret != 0)
    1019                 :          0 :                 rte_exit(ret, "failed to build search context\n");
    1020                 :          0 : }
    1021                 :            : 
    1022                 :            : static uint32_t
    1023                 :          0 : search_ip5tuples_once(uint32_t categories, uint32_t step, const char *alg)
    1024                 :          0 : {
    1025                 :            :         int ret;
    1026                 :            :         uint32_t i, j, k, n, r;
    1027                 :          0 :         const uint8_t *data[step], *v;
    1028                 :          0 :         uint32_t results[step * categories];
    1029                 :            : 
    1030                 :          0 :         v = config.traces;
    1031                 :          0 :         for (i = 0; i != config.used_traces; i += n) {
    1032                 :            : 
    1033                 :          0 :                 n = RTE_MIN(step, config.used_traces - i);
    1034                 :            : 
    1035                 :          0 :                 for (j = 0; j != n; j++) {
    1036                 :          0 :                         data[j] = v;
    1037                 :          0 :                         v += config.trace_sz;
    1038                 :            :                 }
    1039                 :            : 
    1040                 :          0 :                 ret = rte_acl_classify(config.acx, data, results,
    1041                 :            :                         n, categories);
    1042                 :            : 
    1043                 :          0 :                 if (ret != 0)
    1044                 :          0 :                         rte_exit(ret, "classify for ipv%c_5tuples returns %d\n",
    1045                 :          0 :                                 config.ipv6 ? '6' : '4', ret);
    1046                 :            : 
    1047                 :          0 :                 for (r = 0, j = 0; j != n; j++) {
    1048                 :          0 :                         for (k = 0; k != categories; k++, r++) {
    1049                 :          0 :                                 dump_verbose(DUMP_PKT, stdout,
    1050                 :            :                                         "ipv%c_5tuple: %u, category: %u, "
    1051                 :            :                                         "result: %u\n",
    1052                 :            :                                         config.ipv6 ? '6' : '4',
    1053                 :            :                                         i + j + 1, k, results[r] - 1);
    1054                 :            :                         }
    1055                 :            : 
    1056                 :            :                 }
    1057                 :            :         }
    1058                 :            : 
    1059                 :          0 :         dump_verbose(DUMP_SEARCH, stdout,
    1060                 :            :                 "%s(%u, %u, %s) returns %u\n", __func__,
    1061                 :            :                 categories, step, alg, i);
    1062                 :          0 :         return i;
    1063                 :            : }
    1064                 :            : 
    1065                 :            : static int
    1066                 :          0 : search_ip5tuples(__rte_unused void *arg)
    1067                 :            : {
    1068                 :            :         uint64_t pkt, start, tm;
    1069                 :            :         uint32_t i, lcore;
    1070                 :            :         long double st;
    1071                 :            : 
    1072                 :            :         lcore = rte_lcore_id();
    1073                 :            :         start = rte_rdtsc_precise();
    1074                 :            :         pkt = 0;
    1075                 :            : 
    1076                 :          0 :         for (i = 0; i != config.iter_num; i++) {
    1077                 :          0 :                 pkt += search_ip5tuples_once(config.run_categories,
    1078                 :            :                         config.trace_step, config.alg.name);
    1079                 :            :         }
    1080                 :            : 
    1081                 :          0 :         tm = rte_rdtsc_precise() - start;
    1082                 :            : 
    1083                 :          0 :         st = (long double)tm / rte_get_timer_hz();
    1084                 :          0 :         dump_verbose(DUMP_NONE, stdout,
    1085                 :            :                 "%s  @lcore %u: %" PRIu32 " iterations, %" PRIu64 " pkts, %"
    1086                 :            :                 PRIu32 " categories, %" PRIu64 " cycles (%.2Lf sec), "
    1087                 :            :                 "%.2Lf cycles/pkt, %.2Lf pkt/sec\n",
    1088                 :            :                 __func__, lcore, i, pkt,
    1089                 :            :                 config.run_categories, tm, st,
    1090                 :            :                 (pkt == 0) ? 0 : (long double)tm / pkt, pkt / st);
    1091                 :            : 
    1092                 :          0 :         return 0;
    1093                 :            : }
    1094                 :            : 
    1095                 :            : static unsigned long
    1096                 :          0 : get_ulong_opt(const char *opt, const char *name, size_t min, size_t max)
    1097                 :            : {
    1098                 :            :         unsigned long val;
    1099                 :            :         char *end;
    1100                 :            : 
    1101                 :          0 :         errno = 0;
    1102                 :          0 :         val = strtoul(opt, &end, 0);
    1103                 :          0 :         if (errno != 0 || end[0] != 0 || val > max || val < min)
    1104                 :          0 :                 rte_exit(-EINVAL, "invalid value: \"%s\" for option: %s\n",
    1105                 :            :                         opt, name);
    1106                 :          0 :         return val;
    1107                 :            : }
    1108                 :            : 
    1109                 :            : static void
    1110                 :          0 : get_alg_opt(const char *opt, const char *name)
    1111                 :            : {
    1112                 :            :         uint32_t i;
    1113                 :            : 
    1114                 :          0 :         for (i = 0; i != RTE_DIM(acl_alg); i++) {
    1115                 :          0 :                 if (strcmp(opt, acl_alg[i].name) == 0) {
    1116                 :          0 :                         config.alg = acl_alg[i];
    1117                 :          0 :                         return;
    1118                 :            :                 }
    1119                 :            :         }
    1120                 :            : 
    1121                 :          0 :         rte_exit(-EINVAL, "invalid value: \"%s\" for option: %s\n",
    1122                 :            :                 opt, name);
    1123                 :            : }
    1124                 :            : 
    1125                 :            : static void
    1126                 :          0 : get_ipv6_opt(const char *opt, const char *name)
    1127                 :            : {
    1128                 :            :         uint32_t i;
    1129                 :            : 
    1130                 :            :         static const struct {
    1131                 :            :                 const char *name;
    1132                 :            :                 uint32_t val;
    1133                 :            :         } ipv6_opt[] = {
    1134                 :            :                 {
    1135                 :            :                         .name = "4B",
    1136                 :            :                         .val = IPV6_FRMT_U32,
    1137                 :            :                 },
    1138                 :            :                 {
    1139                 :            :                         .name = "8B",
    1140                 :            :                         .val = IPV6_FRMT_U64,
    1141                 :            :                 },
    1142                 :            :         };
    1143                 :            : 
    1144                 :          0 :         for (i = 0; i != RTE_DIM(ipv6_opt); i++) {
    1145                 :          0 :                 if (strcmp(opt, ipv6_opt[i].name) == 0) {
    1146                 :          0 :                         config.ipv6 = ipv6_opt[i].val;
    1147                 :          0 :                         return;
    1148                 :            :                 }
    1149                 :            :         }
    1150                 :            : 
    1151                 :          0 :         rte_exit(-EINVAL, "invalid value: \"%s\" for option: %s\n",
    1152                 :            :                 opt, name);
    1153                 :            : }
    1154                 :            : 
    1155                 :            : 
    1156                 :            : static void
    1157                 :          0 : print_usage(const char *prgname)
    1158                 :            : {
    1159                 :            :         uint32_t i, n, rc;
    1160                 :            :         char buf[PATH_MAX];
    1161                 :            : 
    1162                 :            :         n = 0;
    1163                 :          0 :         buf[0] = 0;
    1164                 :            : 
    1165                 :          0 :         for (i = 0; i < RTE_DIM(acl_alg) - 1; i++) {
    1166                 :          0 :                 rc = snprintf(buf + n, sizeof(buf) - n, "%s|",
    1167                 :          0 :                         acl_alg[i].name);
    1168                 :          0 :                 if (rc > sizeof(buf) - n)
    1169                 :            :                         break;
    1170                 :          0 :                 n += rc;
    1171                 :            :         }
    1172                 :            : 
    1173                 :          0 :         strlcpy(buf + n, acl_alg[i].name, sizeof(buf) - n);
    1174                 :            : 
    1175                 :          0 :         fprintf(stdout,
    1176                 :            :                 PRINT_USAGE_START
    1177                 :            :                 "--" OPT_RULE_FILE "=<rules set file>\n"
    1178                 :            :                 "[--" OPT_TRACE_FILE "=<input traces file>]\n"
    1179                 :            :                 "[--" OPT_RULE_NUM
    1180                 :            :                         "=<maximum number of rules for ACL context>]\n"
    1181                 :            :                 "[--" OPT_TRACE_NUM
    1182                 :            :                         "=<number of traces to read binary file in>]\n"
    1183                 :            :                 "[--" OPT_TRACE_STEP
    1184                 :            :                         "=<number of traces to classify per one call>]\n"
    1185                 :            :                 "[--" OPT_BLD_CATEGORIES
    1186                 :            :                         "=<number of categories to build with>]\n"
    1187                 :            :                 "[--" OPT_RUN_CATEGORIES
    1188                 :            :                         "=<number of categories to run with> "
    1189                 :            :                         "should be either 1 or multiple of %zu, "
    1190                 :            :                         "but not greater then %u]\n"
    1191                 :            :                 "[--" OPT_MAX_SIZE
    1192                 :            :                         "=<size limit (in bytes) for runtime ACL structures> "
    1193                 :            :                         "leave 0 for default behaviour]\n"
    1194                 :            :                 "[--" OPT_ITER_NUM "=<number of iterations to perform>]\n"
    1195                 :            :                 "[--" OPT_VERBOSE "=<verbose level>]\n"
    1196                 :            :                 "[--" OPT_SEARCH_ALG "=%s]\n"
    1197                 :            :                 "[--" OPT_IPV6 "(=4B | 8B) <IPv6 rules and trace files>]\n",
    1198                 :            :                 prgname, RTE_ACL_RESULTS_MULTIPLIER,
    1199                 :            :                 (uint32_t)RTE_ACL_MAX_CATEGORIES,
    1200                 :            :                 buf);
    1201                 :          0 : }
    1202                 :            : 
    1203                 :            : static void
    1204                 :          0 : dump_config(FILE *f)
    1205                 :            : {
    1206                 :            :         fprintf(f, "%s:\n", __func__);
    1207                 :          0 :         fprintf(f, "%s:%s\n", OPT_RULE_FILE, config.rule_file);
    1208                 :          0 :         fprintf(f, "%s:%s\n", OPT_TRACE_FILE, config.trace_file);
    1209                 :          0 :         fprintf(f, "%s:%u\n", OPT_RULE_NUM, config.nb_rules);
    1210                 :          0 :         fprintf(f, "%s:%u\n", OPT_TRACE_NUM, config.nb_traces);
    1211                 :          0 :         fprintf(f, "%s:%u\n", OPT_TRACE_STEP, config.trace_step);
    1212                 :          0 :         fprintf(f, "%s:%u\n", OPT_BLD_CATEGORIES, config.bld_categories);
    1213                 :          0 :         fprintf(f, "%s:%u\n", OPT_RUN_CATEGORIES, config.run_categories);
    1214                 :          0 :         fprintf(f, "%s:%zu\n", OPT_MAX_SIZE, config.max_size);
    1215                 :          0 :         fprintf(f, "%s:%u\n", OPT_ITER_NUM, config.iter_num);
    1216                 :          0 :         fprintf(f, "%s:%u\n", OPT_VERBOSE, config.verbose);
    1217                 :          0 :         fprintf(f, "%s:%u(%s)\n", OPT_SEARCH_ALG, config.alg.alg,
    1218                 :            :                 config.alg.name);
    1219                 :          0 :         fprintf(f, "%s:%u\n", OPT_IPV6, config.ipv6);
    1220                 :          0 : }
    1221                 :            : 
    1222                 :            : static void
    1223                 :          0 : check_config(void)
    1224                 :            : {
    1225                 :          0 :         if (config.rule_file == NULL) {
    1226                 :          0 :                 print_usage(config.prgname);
    1227                 :          0 :                 rte_exit(-EINVAL, "mandatory option %s is not specified\n",
    1228                 :            :                         OPT_RULE_FILE);
    1229                 :            :         }
    1230                 :          0 : }
    1231                 :            : 
    1232                 :            : 
    1233                 :            : static void
    1234                 :          0 : get_input_opts(int argc, char **argv)
    1235                 :            : {
    1236                 :            :         static struct option lgopts[] = {
    1237                 :            :                 {OPT_RULE_FILE, 1, 0, 0},
    1238                 :            :                 {OPT_TRACE_FILE, 1, 0, 0},
    1239                 :            :                 {OPT_TRACE_NUM, 1, 0, 0},
    1240                 :            :                 {OPT_RULE_NUM, 1, 0, 0},
    1241                 :            :                 {OPT_MAX_SIZE, 1, 0, 0},
    1242                 :            :                 {OPT_TRACE_STEP, 1, 0, 0},
    1243                 :            :                 {OPT_BLD_CATEGORIES, 1, 0, 0},
    1244                 :            :                 {OPT_RUN_CATEGORIES, 1, 0, 0},
    1245                 :            :                 {OPT_ITER_NUM, 1, 0, 0},
    1246                 :            :                 {OPT_VERBOSE, 1, 0, 0},
    1247                 :            :                 {OPT_SEARCH_ALG, 1, 0, 0},
    1248                 :            :                 {OPT_IPV6, 2, 0, 0},
    1249                 :            :                 {NULL, 0, 0, 0}
    1250                 :            :         };
    1251                 :            : 
    1252                 :            :         int opt, opt_idx;
    1253                 :            : 
    1254                 :          0 :         while ((opt = getopt_long(argc, argv, "", lgopts,  &opt_idx)) != EOF) {
    1255                 :            : 
    1256                 :          0 :                 if (opt != 0) {
    1257                 :          0 :                         print_usage(config.prgname);
    1258                 :          0 :                         rte_exit(-EINVAL, "unknown option: %c", opt);
    1259                 :            :                 }
    1260                 :            : 
    1261                 :          0 :                 if (strcmp(lgopts[opt_idx].name, OPT_RULE_FILE) == 0) {
    1262                 :          0 :                         config.rule_file = optarg;
    1263                 :          0 :                 } else if (strcmp(lgopts[opt_idx].name, OPT_TRACE_FILE) == 0) {
    1264                 :          0 :                         config.trace_file = optarg;
    1265                 :          0 :                 } else if (strcmp(lgopts[opt_idx].name, OPT_RULE_NUM) == 0) {
    1266                 :          0 :                         config.nb_rules = get_ulong_opt(optarg,
    1267                 :            :                                 lgopts[opt_idx].name, 1, RTE_ACL_MAX_INDEX + 1);
    1268                 :          0 :                 } else if (strcmp(lgopts[opt_idx].name, OPT_MAX_SIZE) == 0) {
    1269                 :          0 :                         config.max_size = get_ulong_opt(optarg,
    1270                 :            :                                 lgopts[opt_idx].name, 0, SIZE_MAX);
    1271                 :          0 :                 } else if (strcmp(lgopts[opt_idx].name, OPT_TRACE_NUM) == 0) {
    1272                 :          0 :                         config.nb_traces = get_ulong_opt(optarg,
    1273                 :            :                                 lgopts[opt_idx].name, 1, UINT32_MAX);
    1274                 :          0 :                 } else if (strcmp(lgopts[opt_idx].name, OPT_TRACE_STEP) == 0) {
    1275                 :          0 :                         config.trace_step = get_ulong_opt(optarg,
    1276                 :            :                                 lgopts[opt_idx].name, 1, TRACE_STEP_MAX);
    1277                 :          0 :                 } else if (strcmp(lgopts[opt_idx].name,
    1278                 :            :                                 OPT_BLD_CATEGORIES) == 0) {
    1279                 :          0 :                         config.bld_categories = get_ulong_opt(optarg,
    1280                 :            :                                 lgopts[opt_idx].name, 1,
    1281                 :            :                                 RTE_ACL_MAX_CATEGORIES);
    1282                 :          0 :                 } else if (strcmp(lgopts[opt_idx].name,
    1283                 :            :                                 OPT_RUN_CATEGORIES) == 0) {
    1284                 :          0 :                         config.run_categories = get_ulong_opt(optarg,
    1285                 :            :                                 lgopts[opt_idx].name, 1,
    1286                 :            :                                 RTE_ACL_MAX_CATEGORIES);
    1287                 :          0 :                 } else if (strcmp(lgopts[opt_idx].name, OPT_ITER_NUM) == 0) {
    1288                 :          0 :                         config.iter_num = get_ulong_opt(optarg,
    1289                 :            :                                 lgopts[opt_idx].name, 1, INT32_MAX);
    1290                 :          0 :                 } else if (strcmp(lgopts[opt_idx].name, OPT_VERBOSE) == 0) {
    1291                 :          0 :                         config.verbose = get_ulong_opt(optarg,
    1292                 :            :                                 lgopts[opt_idx].name, DUMP_NONE, DUMP_MAX);
    1293                 :          0 :                 } else if (strcmp(lgopts[opt_idx].name,
    1294                 :            :                                 OPT_SEARCH_ALG) == 0) {
    1295                 :          0 :                         get_alg_opt(optarg, lgopts[opt_idx].name);
    1296                 :          0 :                 } else if (strcmp(lgopts[opt_idx].name, OPT_IPV6) == 0) {
    1297                 :          0 :                         config.ipv6 = IPV6_FRMT_U32;
    1298                 :          0 :                         if (optarg != NULL)
    1299                 :          0 :                                 get_ipv6_opt(optarg, lgopts[opt_idx].name);
    1300                 :            :                 }
    1301                 :            :         }
    1302                 :          0 :         config.trace_sz = config.ipv6 ? sizeof(struct ipv6_5tuple) :
    1303                 :            :                                                 sizeof(struct ipv4_5tuple);
    1304                 :            : 
    1305                 :          0 : }
    1306                 :            : 
    1307                 :            : int
    1308                 :          0 : main(int argc, char **argv)
    1309                 :            : {
    1310                 :            :         int ret;
    1311                 :            :         uint32_t lcore;
    1312                 :            : 
    1313                 :          0 :         ret = rte_eal_init(argc, argv);
    1314                 :          0 :         if (ret < 0)
    1315                 :          0 :                 rte_panic("Cannot init EAL\n");
    1316                 :            : 
    1317                 :          0 :         argc -= ret;
    1318                 :          0 :         argv += ret;
    1319                 :            : 
    1320                 :          0 :         config.prgname = argv[0];
    1321                 :            : 
    1322                 :          0 :         get_input_opts(argc, argv);
    1323                 :          0 :         dump_config(stdout);
    1324                 :          0 :         check_config();
    1325                 :            : 
    1326                 :          0 :         acx_init();
    1327                 :            : 
    1328                 :          0 :         if (config.trace_file != NULL)
    1329                 :          0 :                 tracef_init();
    1330                 :            : 
    1331                 :          0 :         RTE_LCORE_FOREACH_WORKER(lcore)
    1332                 :          0 :                  rte_eal_remote_launch(search_ip5tuples, NULL, lcore);
    1333                 :            : 
    1334                 :          0 :         search_ip5tuples(NULL);
    1335                 :            : 
    1336                 :          0 :         rte_eal_mp_wait_lcore();
    1337                 :            : 
    1338                 :          0 :         rte_acl_free(config.acx);
    1339                 :            :         return 0;
    1340                 :            : }

Generated by: LCOV version 1.14