LCOV - code coverage report
Current view: top level - app/test-pmd - cmd_flex_item.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 0 201 0.0 %
Date: 2025-03-01 20:23:48 Functions: 0 13 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) 2021 NVIDIA Corporation & Affiliates
       3                 :            :  */
       4                 :            : 
       5                 :            : #include <stddef.h>
       6                 :            : #include <stdint.h>
       7                 :            : #include <stdio.h>
       8                 :            : #include <stdlib.h>
       9                 :            : #include <errno.h>
      10                 :            : #include <string.h>
      11                 :            : 
      12                 :            : #include <rte_common.h>
      13                 :            : #include <rte_ethdev.h>
      14                 :            : #include <cmdline_parse.h>
      15                 :            : #include <cmdline_parse_string.h>
      16                 :            : #include <cmdline_parse_num.h>
      17                 :            : #include <rte_flow.h>
      18                 :            : 
      19                 :            : #include "testpmd.h"
      20                 :            : 
      21                 :            : struct flex_item *flex_items[RTE_MAX_ETHPORTS][FLEX_MAX_PARSERS_NUM];
      22                 :            : struct flex_pattern flex_patterns[FLEX_MAX_PATTERNS_NUM];
      23                 :            : 
      24                 :            : #ifdef RTE_HAS_JANSSON
      25                 :            : 
      26                 :            : static struct flex_item *
      27                 :          0 : flex_parser_fetch(uint16_t port_id, uint16_t flex_id)
      28                 :            : {
      29                 :          0 :         if (port_id >= RTE_MAX_ETHPORTS) {
      30                 :          0 :                 printf("Invalid port_id: %u\n", port_id);
      31                 :          0 :                 return FLEX_PARSER_ERR;
      32                 :            :         }
      33                 :          0 :         if (flex_id >= FLEX_MAX_PARSERS_NUM) {
      34                 :          0 :                 printf("Invalid flex item flex_id: %u\n", flex_id);
      35                 :          0 :                 return FLEX_PARSER_ERR;
      36                 :            :         }
      37                 :          0 :         return flex_items[port_id][flex_id];
      38                 :            : }
      39                 :            : 
      40                 :            : static __rte_always_inline bool
      41                 :            : match_strkey(const char *key, const char *pattern)
      42                 :            : {
      43                 :          0 :         return strncmp(key, pattern, strlen(key)) == 0;
      44                 :            : }
      45                 :            : 
      46                 :            : static int
      47                 :          0 : flex_tunnel_parse(json_t *jtun, enum rte_flow_item_flex_tunnel_mode *tunnel)
      48                 :            : {
      49                 :            :         int tun = -1;
      50                 :            : 
      51                 :          0 :         if (json_is_integer(jtun))
      52                 :          0 :                 tun = (int)json_integer_value(jtun);
      53                 :          0 :         else if (json_is_real(jtun))
      54                 :          0 :                 tun = (int)json_real_value(jtun);
      55                 :          0 :         else if (json_is_string(jtun)) {
      56                 :          0 :                 const char *mode = json_string_value(jtun);
      57                 :            : 
      58                 :          0 :                 if (match_strkey(mode, "FLEX_TUNNEL_MODE_SINGLE"))
      59                 :            :                         tun = FLEX_TUNNEL_MODE_SINGLE;
      60                 :          0 :                 else if (match_strkey(mode, "FLEX_TUNNEL_MODE_OUTER"))
      61                 :            :                         tun = FLEX_TUNNEL_MODE_OUTER;
      62                 :          0 :                 else if (match_strkey(mode, "FLEX_TUNNEL_MODE_INNER"))
      63                 :            :                         tun = FLEX_TUNNEL_MODE_INNER;
      64                 :          0 :                 else if (match_strkey(mode, "FLEX_TUNNEL_MODE_MULTI"))
      65                 :            :                         tun = FLEX_TUNNEL_MODE_MULTI;
      66                 :          0 :                 else if (match_strkey(mode, "FLEX_TUNNEL_MODE_TUNNEL"))
      67                 :            :                         tun = FLEX_TUNNEL_MODE_TUNNEL;
      68                 :            :                 else
      69                 :            :                         return -EINVAL;
      70                 :            :         } else
      71                 :            :                 return -EINVAL;
      72                 :          0 :         *tunnel = (enum rte_flow_item_flex_tunnel_mode)tun;
      73                 :          0 :         return 0;
      74                 :            : }
      75                 :            : 
      76                 :            : static int
      77                 :          0 : flex_field_parse(json_t *jfld, struct rte_flow_item_flex_field *fld)
      78                 :            : {
      79                 :            :         const char *key;
      80                 :            :         json_t *je;
      81                 :            : 
      82                 :            : #define FLEX_FIELD_GET(fm, t) \
      83                 :            : do {                  \
      84                 :            :         if (!strncmp(key, # fm, strlen(# fm))) { \
      85                 :            :                 if (json_is_real(je))   \
      86                 :            :                         fld->fm = (t) json_real_value(je); \
      87                 :            :                 else if (json_is_integer(je))   \
      88                 :            :                         fld->fm = (t) json_integer_value(je); \
      89                 :            :                 else   \
      90                 :            :                         return -EINVAL; \
      91                 :            :         }         \
      92                 :            : } while (0)
      93                 :            : 
      94                 :          0 :         json_object_foreach(jfld, key, je) {
      95                 :          0 :                 FLEX_FIELD_GET(field_size, uint32_t);
      96                 :          0 :                 FLEX_FIELD_GET(field_base, int32_t);
      97                 :          0 :                 FLEX_FIELD_GET(offset_base, uint32_t);
      98                 :          0 :                 FLEX_FIELD_GET(offset_mask, uint32_t);
      99                 :          0 :                 FLEX_FIELD_GET(offset_shift, int32_t);
     100                 :          0 :                 FLEX_FIELD_GET(field_id, uint16_t);
     101                 :          0 :                 if (match_strkey(key, "field_mode")) {
     102                 :            :                         const char *mode;
     103                 :          0 :                         if (!json_is_string(je))
     104                 :            :                                 return -EINVAL;
     105                 :          0 :                         mode = json_string_value(je);
     106                 :          0 :                         if (match_strkey(mode, "FIELD_MODE_DUMMY"))
     107                 :          0 :                                 fld->field_mode = FIELD_MODE_DUMMY;
     108                 :          0 :                         else if (match_strkey(mode, "FIELD_MODE_FIXED"))
     109                 :          0 :                                 fld->field_mode = FIELD_MODE_FIXED;
     110                 :          0 :                         else if (match_strkey(mode, "FIELD_MODE_OFFSET"))
     111                 :          0 :                                 fld->field_mode = FIELD_MODE_OFFSET;
     112                 :          0 :                         else if (match_strkey(mode, "FIELD_MODE_BITMASK"))
     113                 :          0 :                                 fld->field_mode = FIELD_MODE_BITMASK;
     114                 :            :                         else
     115                 :            :                                 return -EINVAL;
     116                 :            :                 }
     117                 :            :         }
     118                 :            :         return 0;
     119                 :            : }
     120                 :            : 
     121                 :            : enum flex_link_type {
     122                 :            :         FLEX_LINK_IN = 0,
     123                 :            :         FLEX_LINK_OUT = 1
     124                 :            : };
     125                 :            : 
     126                 :            : static int
     127                 :          0 : flex_link_item_parse(const char *src, struct rte_flow_item *item)
     128                 :            : {
     129                 :            : #define  FLEX_PARSE_DATA_SIZE 1024
     130                 :            : 
     131                 :            :         int ret;
     132                 :          0 :         uint8_t *ptr, data[FLEX_PARSE_DATA_SIZE] = {0,};
     133                 :            :         char flow_rule[256];
     134                 :            :         struct rte_flow_attr *attr;
     135                 :            :         struct rte_flow_item *pattern;
     136                 :            :         struct rte_flow_action *actions;
     137                 :            : 
     138                 :            :         sprintf(flow_rule,
     139                 :            :                 "flow create 0 pattern %s / end actions drop / end", src);
     140                 :            :         src = flow_rule;
     141                 :          0 :         ret = flow_parse(src, (void *)data, sizeof(data),
     142                 :            :                          &attr, &pattern, &actions);
     143                 :          0 :         if (ret)
     144                 :            :                 return ret;
     145                 :          0 :         item->type = pattern->type;
     146                 :          0 :         if (pattern->spec) {
     147                 :          0 :                 ptr = (void *)(uintptr_t)item->spec;
     148                 :            :                 memcpy(ptr, pattern->spec, FLEX_MAX_FLOW_PATTERN_LENGTH);
     149                 :            :         } else {
     150                 :          0 :                 item->spec = NULL;
     151                 :            :         }
     152                 :          0 :         if (pattern->mask) {
     153                 :          0 :                 ptr = (void *)(uintptr_t)item->mask;
     154                 :            :                 memcpy(ptr, pattern->mask, FLEX_MAX_FLOW_PATTERN_LENGTH);
     155                 :            :         } else {
     156                 :          0 :                 item->mask = NULL;
     157                 :            :         }
     158                 :          0 :         if (pattern->last) {
     159                 :          0 :                 ptr = (void *)(uintptr_t)item->last;
     160                 :            :                 memcpy(ptr, pattern->last, FLEX_MAX_FLOW_PATTERN_LENGTH);
     161                 :            :         } else {
     162                 :          0 :                 item->last = NULL;
     163                 :            :         }
     164                 :            :         return 0;
     165                 :            : }
     166                 :            : 
     167                 :            : static int
     168                 :          0 : flex_link_parse(json_t *jobj, struct rte_flow_item_flex_link *link,
     169                 :            :                 enum flex_link_type link_type)
     170                 :            : {
     171                 :            :         const char *key;
     172                 :            :         json_t *je;
     173                 :            :         int ret;
     174                 :          0 :         json_object_foreach(jobj, key, je) {
     175                 :          0 :                 if (match_strkey(key, "item")) {
     176                 :          0 :                         if (!json_is_string(je))
     177                 :            :                                 return -EINVAL;
     178                 :          0 :                         ret = flex_link_item_parse(json_string_value(je),
     179                 :            :                                                    &link->item);
     180                 :          0 :                         if (ret)
     181                 :            :                                 return -EINVAL;
     182                 :          0 :                         if (link_type == FLEX_LINK_IN) {
     183                 :          0 :                                 if (!link->item.spec || !link->item.mask)
     184                 :            :                                         return -EINVAL;
     185                 :          0 :                                 if (link->item.last)
     186                 :            :                                         return -EINVAL;
     187                 :            :                         }
     188                 :            :                 }
     189                 :          0 :                 if (match_strkey(key, "next")) {
     190                 :          0 :                         if (json_is_integer(je))
     191                 :          0 :                                 link->next = (typeof(link->next))
     192                 :          0 :                                              json_integer_value(je);
     193                 :          0 :                         else if (json_is_real(je))
     194                 :          0 :                                 link->next = (typeof(link->next))
     195                 :          0 :                                              json_real_value(je);
     196                 :            :                         else
     197                 :            :                                 return -EINVAL;
     198                 :            :                 }
     199                 :            :         }
     200                 :            :         return 0;
     201                 :            : }
     202                 :            : 
     203                 :          0 : static int flex_item_config(json_t *jroot,
     204                 :            :                             struct rte_flow_item_flex_conf *flex_conf)
     205                 :            : {
     206                 :            :         const char *key;
     207                 :            :         json_t *jobj = NULL;
     208                 :            :         int ret = 0;
     209                 :            : 
     210                 :          0 :         json_object_foreach(jroot, key, jobj) {
     211                 :          0 :                 if (match_strkey(key, "tunnel")) {
     212                 :          0 :                         ret = flex_tunnel_parse(jobj, &flex_conf->tunnel);
     213                 :          0 :                         if (ret) {
     214                 :            :                                 printf("Can't parse tunnel value\n");
     215                 :          0 :                                 goto out;
     216                 :            :                         }
     217                 :          0 :                 } else if (match_strkey(key, "next_header")) {
     218                 :          0 :                         ret = flex_field_parse(jobj, &flex_conf->next_header);
     219                 :          0 :                         if (ret) {
     220                 :            :                                 printf("Can't parse next_header field\n");
     221                 :          0 :                                 goto out;
     222                 :            :                         }
     223                 :          0 :                 } else if (match_strkey(key, "next_protocol")) {
     224                 :          0 :                         ret = flex_field_parse(jobj,
     225                 :            :                                                &flex_conf->next_protocol);
     226                 :          0 :                         if (ret) {
     227                 :            :                                 printf("Can't parse next_protocol field\n");
     228                 :          0 :                                 goto out;
     229                 :            :                         }
     230                 :          0 :                 } else if (match_strkey(key, "sample_data")) {
     231                 :            :                         json_t *ji;
     232                 :          0 :                         uint32_t i, size = json_array_size(jobj);
     233                 :          0 :                         for (i = 0; i < size; i++) {
     234                 :          0 :                                 ji = json_array_get(jobj, i);
     235                 :          0 :                                 ret = flex_field_parse
     236                 :          0 :                                         (ji, flex_conf->sample_data + i);
     237                 :          0 :                                 if (ret) {
     238                 :            :                                         printf("Can't parse sample_data field(s)\n");
     239                 :          0 :                                         goto out;
     240                 :            :                                 }
     241                 :            :                         }
     242                 :          0 :                         flex_conf->nb_samples = size;
     243                 :          0 :                 } else if (match_strkey(key, "input_link")) {
     244                 :            :                         json_t *ji;
     245                 :          0 :                         uint32_t i, size = json_array_size(jobj);
     246                 :          0 :                         for (i = 0; i < size; i++) {
     247                 :          0 :                                 ji = json_array_get(jobj, i);
     248                 :          0 :                                 ret = flex_link_parse(ji,
     249                 :          0 :                                                       flex_conf->input_link + i,
     250                 :            :                                                       FLEX_LINK_IN);
     251                 :          0 :                                 if (ret) {
     252                 :            :                                         printf("Can't parse input_link(s)\n");
     253                 :          0 :                                         goto out;
     254                 :            :                                 }
     255                 :            :                         }
     256                 :          0 :                         flex_conf->nb_inputs = size;
     257                 :          0 :                 } else if (match_strkey(key, "output_link")) {
     258                 :            :                         json_t *ji;
     259                 :          0 :                         uint32_t i, size = json_array_size(jobj);
     260                 :          0 :                         for (i = 0; i < size; i++) {
     261                 :          0 :                                 ji = json_array_get(jobj, i);
     262                 :          0 :                                 ret = flex_link_parse
     263                 :          0 :                                         (ji, flex_conf->output_link + i,
     264                 :            :                                          FLEX_LINK_OUT);
     265                 :          0 :                                 if (ret) {
     266                 :            :                                         printf("Can't parse output_link(s)\n");
     267                 :          0 :                                         goto out;
     268                 :            :                                 }
     269                 :            :                         }
     270                 :          0 :                         flex_conf->nb_outputs = size;
     271                 :            :                 }
     272                 :            :         }
     273                 :          0 : out:
     274                 :          0 :         return ret;
     275                 :            : }
     276                 :            : 
     277                 :            : static struct flex_item *
     278                 :          0 : flex_item_init(void)
     279                 :            : {
     280                 :            :         size_t base_size, samples_size, links_size, spec_size;
     281                 :            :         struct rte_flow_item_flex_conf *conf;
     282                 :            :         struct flex_item *fp;
     283                 :            :         uint8_t (*pattern)[FLEX_MAX_FLOW_PATTERN_LENGTH];
     284                 :            :         int i;
     285                 :            : 
     286                 :            :         base_size = RTE_ALIGN(sizeof(*conf), sizeof(uintptr_t));
     287                 :            :         samples_size = RTE_ALIGN(FLEX_ITEM_MAX_SAMPLES_NUM *
     288                 :            :                                  sizeof(conf->sample_data[0]),
     289                 :            :                                  sizeof(uintptr_t));
     290                 :            :         links_size = RTE_ALIGN(FLEX_ITEM_MAX_LINKS_NUM *
     291                 :            :                                sizeof(conf->input_link[0]),
     292                 :            :                                sizeof(uintptr_t));
     293                 :            :         /* spec & mask for all input links */
     294                 :            :         spec_size = 2 * FLEX_MAX_FLOW_PATTERN_LENGTH * FLEX_ITEM_MAX_LINKS_NUM;
     295                 :          0 :         fp = calloc(1, base_size + samples_size + 2 * links_size + spec_size);
     296                 :          0 :         if (fp == NULL) {
     297                 :            :                 printf("Can't allocate memory for flex item\n");
     298                 :          0 :                 return NULL;
     299                 :            :         }
     300                 :            :         conf = &fp->flex_conf;
     301                 :          0 :         conf->sample_data = (typeof(conf->sample_data))
     302                 :            :                             ((uint8_t *)fp + base_size);
     303                 :          0 :         conf->input_link = (typeof(conf->input_link))
     304                 :            :                            ((uint8_t *)conf->sample_data + samples_size);
     305                 :          0 :         conf->output_link = (typeof(conf->output_link))
     306                 :            :                             ((uint8_t *)conf->input_link + links_size);
     307                 :          0 :         pattern = (typeof(pattern))((uint8_t *)conf->output_link + links_size);
     308                 :          0 :         for (i = 0; i < FLEX_ITEM_MAX_LINKS_NUM; i++) {
     309                 :          0 :                 struct rte_flow_item_flex_link *in = conf->input_link + i;
     310                 :          0 :                 in->item.spec = pattern++;
     311                 :          0 :                 in->item.mask = pattern++;
     312                 :            :         }
     313                 :            :         return fp;
     314                 :            : }
     315                 :            : 
     316                 :            : static int
     317                 :          0 : flex_item_build_config(struct flex_item *fp, const char *filename)
     318                 :            : {
     319                 :            :         int ret;
     320                 :            :         json_error_t json_error;
     321                 :          0 :         json_t *jroot = json_load_file(filename, 0, &json_error);
     322                 :            : 
     323                 :          0 :         if (!jroot) {
     324                 :            :                 printf("Bad JSON file \"%s\": %s\n", filename, json_error.text);
     325                 :          0 :                 return -1;
     326                 :            :         }
     327                 :          0 :         ret = flex_item_config(jroot, &fp->flex_conf);
     328                 :          0 :         json_decref(jroot);
     329                 :          0 :         return ret;
     330                 :            : }
     331                 :            : 
     332                 :            : void
     333                 :          0 : flex_item_create(portid_t port_id, uint16_t flex_id, const char *filename)
     334                 :            : {
     335                 :            :         struct rte_flow_error flow_error;
     336                 :          0 :         struct flex_item *fp = flex_parser_fetch(port_id, flex_id);
     337                 :            :         int ret;
     338                 :            : 
     339                 :          0 :         if (fp == FLEX_PARSER_ERR) {
     340                 :            :                 printf("Bad parameters: port_id=%u flex_id=%u\n",
     341                 :            :                        port_id, flex_id);
     342                 :          0 :                 return;
     343                 :            :         }
     344                 :          0 :         if (fp) {
     345                 :            :                 printf("port-%u: flex item #%u is already in use\n",
     346                 :            :                        port_id, flex_id);
     347                 :          0 :                 return;
     348                 :            :         }
     349                 :          0 :         fp = flex_item_init();
     350                 :          0 :         if (!fp) {
     351                 :            :                 printf("Could not allocate flex item\n");
     352                 :          0 :                 goto out;
     353                 :            :         }
     354                 :          0 :         ret = flex_item_build_config(fp, filename);
     355                 :          0 :         if (ret)
     356                 :          0 :                 goto out;
     357                 :          0 :         fp->flex_handle = rte_flow_flex_item_create(port_id,
     358                 :          0 :                                                     &fp->flex_conf,
     359                 :            :                                                     &flow_error);
     360                 :          0 :         if (fp->flex_handle) {
     361                 :          0 :                 flex_items[port_id][flex_id] = fp;
     362                 :            :                 printf("port-%u: created flex item #%u\n", port_id, flex_id);
     363                 :            :                 fp = NULL;
     364                 :            :         } else {
     365                 :          0 :                 printf("port-%u: flex item #%u creation failed: %s\n",
     366                 :            :                        port_id, flex_id,
     367                 :          0 :                        flow_error.message ? flow_error.message : "");
     368                 :            :         }
     369                 :          0 : out:
     370                 :          0 :         free(fp);
     371                 :            : }
     372                 :            : 
     373                 :            : void
     374                 :          0 : flex_item_destroy(portid_t port_id, uint16_t flex_id)
     375                 :            : {
     376                 :            :         int ret;
     377                 :            :         struct rte_flow_error error;
     378                 :          0 :         struct flex_item *fp = flex_parser_fetch(port_id, flex_id);
     379                 :          0 :         if (fp == FLEX_PARSER_ERR) {
     380                 :            :                 printf("Bad parameters: port_id=%u flex_id=%u\n",
     381                 :            :                        port_id, flex_id);
     382                 :          0 :                 return;
     383                 :            :         }
     384                 :          0 :         if (!fp)
     385                 :            :                 return;
     386                 :          0 :         ret = rte_flow_flex_item_release(port_id, fp->flex_handle, &error);
     387                 :          0 :         if (!ret) {
     388                 :          0 :                 free(fp);
     389                 :          0 :                 flex_items[port_id][flex_id] = NULL;
     390                 :            :                 printf("port-%u: released flex item #%u\n",
     391                 :            :                        port_id, flex_id);
     392                 :            : 
     393                 :            :         } else {
     394                 :          0 :                 printf("port-%u: cannot release flex item #%u: %s\n",
     395                 :            :                        port_id, flex_id, error.message);
     396                 :            :         }
     397                 :            : }
     398                 :            : 
     399                 :            : #else /* RTE_HAS_JANSSON */
     400                 :            : void flex_item_create(__rte_unused portid_t port_id,
     401                 :            :                       __rte_unused uint16_t flex_id,
     402                 :            :                       __rte_unused const char *filename)
     403                 :            : {
     404                 :            :         printf("cannot create flex item - no JSON library configured\n");
     405                 :            : }
     406                 :            : 
     407                 :            : void
     408                 :            : flex_item_destroy(__rte_unused portid_t port_id, __rte_unused uint16_t flex_id)
     409                 :            : {
     410                 :            : 
     411                 :            : }
     412                 :            : 
     413                 :            : #endif /* RTE_HAS_JANSSON */
     414                 :            : 
     415                 :            : void
     416                 :          0 : port_flex_item_flush(portid_t port_id)
     417                 :            : {
     418                 :            :         uint16_t i;
     419                 :            : 
     420                 :          0 :         for (i = 0; i < FLEX_MAX_PARSERS_NUM; i++) {
     421                 :          0 :                 if (flex_items[port_id][i] != NULL) {
     422                 :          0 :                         flex_item_destroy(port_id, i);
     423                 :          0 :                         flex_items[port_id][i] = NULL;
     424                 :            :                 }
     425                 :            :         }
     426                 :          0 : }
     427                 :            : 
     428                 :            : struct flex_pattern_set {
     429                 :            :         cmdline_fixed_string_t set, flex_pattern;
     430                 :            :         cmdline_fixed_string_t is_spec, mask;
     431                 :            :         cmdline_fixed_string_t spec_data, mask_data;
     432                 :            :         uint16_t id;
     433                 :            : };
     434                 :            : 
     435                 :            : static cmdline_parse_token_string_t flex_pattern_set_token =
     436                 :            :         TOKEN_STRING_INITIALIZER(struct flex_pattern_set, set, "set");
     437                 :            : static cmdline_parse_token_string_t flex_pattern_token =
     438                 :            :         TOKEN_STRING_INITIALIZER(struct flex_pattern_set,
     439                 :            : flex_pattern, "flex_pattern");
     440                 :            : static cmdline_parse_token_string_t flex_pattern_is_token =
     441                 :            :         TOKEN_STRING_INITIALIZER(struct flex_pattern_set,
     442                 :            : is_spec, "is");
     443                 :            : static cmdline_parse_token_string_t flex_pattern_spec_token =
     444                 :            :         TOKEN_STRING_INITIALIZER(struct flex_pattern_set,
     445                 :            : is_spec, "spec");
     446                 :            : static cmdline_parse_token_string_t flex_pattern_mask_token =
     447                 :            :         TOKEN_STRING_INITIALIZER(struct flex_pattern_set, mask, "mask");
     448                 :            : static cmdline_parse_token_string_t flex_pattern_spec_data_token =
     449                 :            :         TOKEN_STRING_INITIALIZER(struct flex_pattern_set, spec_data, NULL);
     450                 :            : static cmdline_parse_token_string_t flex_pattern_mask_data_token =
     451                 :            :         TOKEN_STRING_INITIALIZER(struct flex_pattern_set, mask_data, NULL);
     452                 :            : static cmdline_parse_token_num_t flex_pattern_id_token =
     453                 :            :         TOKEN_NUM_INITIALIZER(struct flex_pattern_set, id, RTE_UINT16);
     454                 :            : 
     455                 :            : /*
     456                 :            :  * flex pattern data - spec or mask is a string representation of byte array
     457                 :            :  * in hexadecimal format. Each byte in data string must have 2 characters:
     458                 :            :  * 0x15 - "15"
     459                 :            :  * 0x1  - "01"
     460                 :            :  * Bytes in data array are in network order.
     461                 :            :  */
     462                 :            : static uint32_t
     463                 :          0 : flex_pattern_data(const char *str, uint8_t *data)
     464                 :            : {
     465                 :          0 :         uint32_t i, len = strlen(str);
     466                 :            :         char b[3], *endptr;
     467                 :            : 
     468                 :          0 :         if (len & 01)
     469                 :            :                 return 0;
     470                 :          0 :         len /= 2;
     471                 :          0 :         if (len >= FLEX_MAX_FLOW_PATTERN_LENGTH)
     472                 :            :                 return 0;
     473                 :          0 :         for (i = 0, b[2] = '\0'; i < len; i++) {
     474                 :          0 :                 b[0] = str[2 * i];
     475                 :          0 :                 b[1] = str[2 * i + 1];
     476                 :          0 :                 data[i] = strtoul(b, &endptr, 16);
     477                 :          0 :                 if (endptr != &b[2])
     478                 :            :                         return 0;
     479                 :            :         }
     480                 :            :         return len;
     481                 :            : }
     482                 :            : 
     483                 :            : static void
     484                 :          0 : flex_pattern_parsed_fn(void *parsed_result,
     485                 :            :                        __rte_unused struct cmdline *cl,
     486                 :            :                        __rte_unused void *data)
     487                 :            : {
     488                 :            :         struct flex_pattern_set *res = parsed_result;
     489                 :            :         struct flex_pattern *fp;
     490                 :            :         bool full_spec;
     491                 :            : 
     492                 :          0 :         if (res->id >= FLEX_MAX_PATTERNS_NUM) {
     493                 :            :                 printf("Bad flex pattern id\n");
     494                 :          0 :                 return;
     495                 :            :         }
     496                 :          0 :         fp = flex_patterns + res->id;
     497                 :          0 :         memset(fp->spec_pattern, 0, sizeof(fp->spec_pattern));
     498                 :          0 :         memset(fp->mask_pattern, 0, sizeof(fp->mask_pattern));
     499                 :          0 :         fp->spec.length = flex_pattern_data(res->spec_data, fp->spec_pattern);
     500                 :          0 :         if (!fp->spec.length) {
     501                 :            :                 printf("Bad flex pattern spec\n");
     502                 :          0 :                 return;
     503                 :            :         }
     504                 :          0 :         full_spec = strncmp(res->is_spec, "spec", strlen("spec")) == 0;
     505                 :          0 :         if (full_spec) {
     506                 :          0 :                 fp->mask.length = flex_pattern_data(res->mask_data,
     507                 :            :                                                     fp->mask_pattern);
     508                 :          0 :                 if (!fp->mask.length) {
     509                 :            :                         printf("Bad flex pattern mask\n");
     510                 :          0 :                         return;
     511                 :            :                 }
     512                 :            :         } else {
     513                 :          0 :                 memset(fp->mask_pattern, 0xFF, fp->spec.length);
     514                 :          0 :                 fp->mask.length = fp->spec.length;
     515                 :            :         }
     516                 :          0 :         if (fp->mask.length != fp->spec.length) {
     517                 :            :                 printf("Spec length do not match mask length\n");
     518                 :          0 :                 return;
     519                 :            :         }
     520                 :          0 :         fp->spec.pattern = fp->spec_pattern;
     521                 :          0 :         fp->mask.pattern = fp->mask_pattern;
     522                 :          0 :         printf("created pattern #%u\n", res->id);
     523                 :            : }
     524                 :            : 
     525                 :            : cmdline_parse_inst_t cmd_set_flex_is_pattern = {
     526                 :            :         .f = flex_pattern_parsed_fn,
     527                 :            :         .data = NULL,
     528                 :            :         .help_str = "set flex_pattern <id> is <spec_data>",
     529                 :            :         .tokens = {
     530                 :            :                 (void *)&flex_pattern_set_token,
     531                 :            :                 (void *)&flex_pattern_token,
     532                 :            :                 (void *)&flex_pattern_id_token,
     533                 :            :                 (void *)&flex_pattern_is_token,
     534                 :            :                 (void *)&flex_pattern_spec_data_token,
     535                 :            :                 NULL,
     536                 :            :         }
     537                 :            : };
     538                 :            : 
     539                 :            : cmdline_parse_inst_t cmd_set_flex_spec_pattern = {
     540                 :            :         .f = flex_pattern_parsed_fn,
     541                 :            :         .data = NULL,
     542                 :            :         .help_str = "set flex_pattern <id> spec <spec_data> mask <mask_data>",
     543                 :            :         .tokens = {
     544                 :            :                 (void *)&flex_pattern_set_token,
     545                 :            :                 (void *)&flex_pattern_token,
     546                 :            :                 (void *)&flex_pattern_id_token,
     547                 :            :                 (void *)&flex_pattern_spec_token,
     548                 :            :                 (void *)&flex_pattern_spec_data_token,
     549                 :            :                 (void *)&flex_pattern_mask_token,
     550                 :            :                 (void *)&flex_pattern_mask_data_token,
     551                 :            :                 NULL,
     552                 :            :         }
     553                 :            : };

Generated by: LCOV version 1.14