LCOV - code coverage report
Current view: top level - drivers/net/cpfl - cpfl_flow_parser.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 0 1004 0.0 %
Date: 2025-01-02 22:41:34 Functions: 0 48 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 641 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright(c) 2023 Intel Corporation
       3                 :            :  */
       4                 :            : 
       5                 :            : #include <arpa/inet.h>
       6                 :            : 
       7                 :            : #include "cpfl_flow_parser.h"
       8                 :            : 
       9                 :            : static enum rte_flow_item_type
      10                 :          0 : cpfl_get_item_type_by_str(const char *type)
      11                 :            : {
      12         [ #  # ]:          0 :         if (strcmp(type, "eth") == 0)
      13                 :            :                 return RTE_FLOW_ITEM_TYPE_ETH;
      14         [ #  # ]:          0 :         else if (strcmp(type, "ipv4") == 0)
      15                 :            :                 return RTE_FLOW_ITEM_TYPE_IPV4;
      16         [ #  # ]:          0 :         else if (strcmp(type, "tcp") == 0)
      17                 :            :                 return RTE_FLOW_ITEM_TYPE_TCP;
      18         [ #  # ]:          0 :         else if (strcmp(type, "udp") == 0)
      19                 :            :                 return RTE_FLOW_ITEM_TYPE_UDP;
      20         [ #  # ]:          0 :         else if (strcmp(type, "vxlan") == 0)
      21                 :            :                 return RTE_FLOW_ITEM_TYPE_VXLAN;
      22         [ #  # ]:          0 :         else if (strcmp(type, "icmp") == 0)
      23                 :            :                 return RTE_FLOW_ITEM_TYPE_ICMP;
      24         [ #  # ]:          0 :         else if (strcmp(type, "vlan") == 0)
      25                 :            :                 return RTE_FLOW_ITEM_TYPE_VLAN;
      26                 :            : 
      27                 :          0 :         PMD_DRV_LOG(ERR, "Not support this type: %s.", type);
      28                 :          0 :         return RTE_FLOW_ITEM_TYPE_VOID;
      29                 :            : }
      30                 :            : 
      31                 :            : static enum rte_flow_action_type
      32                 :          0 : cpfl_get_action_type_by_str(const char *type)
      33                 :            : {
      34         [ #  # ]:          0 :         if (strcmp(type, "vxlan_encap") == 0)
      35                 :            :                 return RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP;
      36         [ #  # ]:          0 :         else if (strcmp(type, "vxlan_decap") == 0)
      37                 :            :                 return RTE_FLOW_ACTION_TYPE_VXLAN_DECAP;
      38         [ #  # ]:          0 :         else if (strcmp(type, "prog") == 0)
      39                 :            :                 return RTE_FLOW_ACTION_TYPE_PROG;
      40                 :            : 
      41                 :          0 :         PMD_DRV_LOG(ERR, "Not support this type: %s.", type);
      42                 :          0 :         return RTE_FLOW_ACTION_TYPE_VOID;
      43                 :            : }
      44                 :            : 
      45                 :            : static const char *
      46                 :          0 : cpfl_json_t_to_string(json_t *object, const char *name)
      47                 :            : {
      48                 :            :         json_t *subobject;
      49                 :            : 
      50         [ #  # ]:          0 :         if (!object) {
      51                 :          0 :                 PMD_DRV_LOG(ERR, "object doesn't exist.");
      52                 :          0 :                 return NULL;
      53                 :            :         }
      54                 :          0 :         subobject = json_object_get(object, name);
      55         [ #  # ]:          0 :         if (!subobject) {
      56                 :          0 :                 PMD_DRV_LOG(ERR, "%s doesn't exist.", name);
      57                 :          0 :                 return NULL;
      58                 :            :         }
      59                 :            : 
      60                 :          0 :         return json_string_value(subobject);
      61                 :            : }
      62                 :            : 
      63                 :            : static int
      64                 :          0 : cpfl_json_t_to_int(json_t *object, const char *name, int *value)
      65                 :            : {
      66                 :            :         json_t *subobject;
      67                 :            : 
      68         [ #  # ]:          0 :         if (!object) {
      69                 :          0 :                 PMD_DRV_LOG(ERR, "object doesn't exist.");
      70                 :          0 :                 return -EINVAL;
      71                 :            :         }
      72                 :          0 :         subobject = json_object_get(object, name);
      73         [ #  # ]:          0 :         if (!subobject) {
      74                 :          0 :                 PMD_DRV_LOG(ERR, "%s doesn't exist.", name);
      75                 :          0 :                 return -EINVAL;
      76                 :            :         }
      77         [ #  # ]:          0 :         if (!json_is_integer(subobject)) {
      78                 :          0 :                 PMD_DRV_LOG(ERR, "%s is not an integer.", name);
      79                 :          0 :                 return -EINVAL;
      80                 :            :         }
      81                 :          0 :         *value = (int)json_integer_value(subobject);
      82                 :            : 
      83                 :          0 :         return 0;
      84                 :            : }
      85                 :            : 
      86                 :            : static int
      87                 :          0 : cpfl_json_t_to_uint16(json_t *object, const char *name, uint16_t *value)
      88                 :            : {
      89                 :            :         json_t *subobject;
      90                 :            : 
      91         [ #  # ]:          0 :         if (!object) {
      92                 :          0 :                 PMD_DRV_LOG(ERR, "object doesn't exist.");
      93                 :          0 :                 return -EINVAL;
      94                 :            :         }
      95                 :          0 :         subobject = json_object_get(object, name);
      96         [ #  # ]:          0 :         if (!subobject) {
      97                 :          0 :                 PMD_DRV_LOG(ERR, "%s doesn't exist.", name);
      98                 :          0 :                 return -EINVAL;
      99                 :            :         }
     100         [ #  # ]:          0 :         if (!json_is_integer(subobject)) {
     101                 :          0 :                 PMD_DRV_LOG(ERR, "%s is not an integer.", name);
     102                 :          0 :                 return -EINVAL;
     103                 :            :         }
     104                 :          0 :         *value = (uint16_t)json_integer_value(subobject);
     105                 :            : 
     106                 :          0 :         return 0;
     107                 :            : }
     108                 :            : 
     109                 :            : static int
     110                 :          0 : cpfl_json_t_to_uint32(json_t *object, const char *name, uint32_t *value)
     111                 :            : {
     112                 :            :         json_t *subobject;
     113                 :            : 
     114         [ #  # ]:          0 :         if (!object) {
     115                 :          0 :                 PMD_DRV_LOG(ERR, "object doesn't exist.");
     116                 :          0 :                 return -EINVAL;
     117                 :            :         }
     118                 :          0 :         subobject = json_object_get(object, name);
     119         [ #  # ]:          0 :         if (!subobject) {
     120                 :          0 :                 PMD_DRV_LOG(ERR, "%s doesn't exist.", name);
     121                 :          0 :                 return -EINVAL;
     122                 :            :         }
     123         [ #  # ]:          0 :         if (!json_is_integer(subobject)) {
     124                 :          0 :                 PMD_DRV_LOG(ERR, "%s is not an integer.", name);
     125                 :          0 :                 return -EINVAL;
     126                 :            :         }
     127                 :          0 :         *value = (uint32_t)json_integer_value(subobject);
     128                 :            : 
     129                 :          0 :         return 0;
     130                 :            : }
     131                 :            : 
     132                 :            : static int
     133                 :          0 : cpfl_flow_js_pattern_key_attr(json_t *ob_pr_key_attrs, struct cpfl_flow_js_pr *js_pr)
     134                 :            : {
     135                 :            :         int i, len;
     136                 :            :         struct cpfl_flow_js_pr_key_attr *attr;
     137                 :            : 
     138                 :          0 :         len = json_array_size(ob_pr_key_attrs);
     139                 :          0 :         js_pr->key.attributes = rte_malloc(NULL, sizeof(struct cpfl_flow_js_pr_key_attr), 0);
     140         [ #  # ]:          0 :         if (!js_pr->key.attributes) {
     141                 :          0 :                 PMD_DRV_LOG(ERR, "Failed to alloc memory.");
     142                 :          0 :                 return -ENOMEM;
     143                 :            :         }
     144                 :          0 :         js_pr->key.attr_size = len;
     145                 :            :         attr = js_pr->key.attributes;
     146         [ #  # ]:          0 :         for (i = 0; i < len; i++) {
     147                 :            :                 json_t *object;
     148                 :            :                 const char *name;
     149                 :          0 :                 uint16_t value = 0;
     150                 :            :                 int ret;
     151                 :            : 
     152                 :          0 :                 object = json_array_get(ob_pr_key_attrs, i);
     153                 :          0 :                 name = cpfl_json_t_to_string(object, "Name");
     154         [ #  # ]:          0 :                 if (!name) {
     155                 :          0 :                         PMD_DRV_LOG(ERR, "Can not parse string 'Name'.");
     156                 :          0 :                         goto err;
     157                 :            :                 }
     158                 :          0 :                 ret = cpfl_json_t_to_uint16(object, "Value", &value);
     159         [ #  # ]:          0 :                 if (ret < 0) {
     160                 :          0 :                         PMD_DRV_LOG(ERR, "Can not parse 'value'.");
     161                 :          0 :                         goto err;
     162                 :            :                 }
     163         [ #  # ]:          0 :                 if (strcmp(name, "ingress") == 0) {
     164                 :          0 :                         attr->ingress = value;
     165         [ #  # ]:          0 :                 } else if (strcmp(name, "egress") == 0) {
     166                 :          0 :                         attr->egress = value;
     167                 :            :                 } else {
     168                 :            :                         /* TODO: more... */
     169                 :          0 :                         PMD_DRV_LOG(ERR, "Not support attr name: %s.", name);
     170                 :          0 :                         goto err;
     171                 :            :                 }
     172                 :            :         }
     173                 :            : 
     174                 :            :         return 0;
     175                 :            : err:
     176                 :          0 :         rte_free(js_pr->key.attributes);
     177                 :          0 :         return -EINVAL;
     178                 :            : }
     179                 :            : 
     180                 :            : static int
     181                 :          0 : cpfl_flow_js_pattern_key_proto_field(json_t *ob_fields,
     182                 :            :                                      struct cpfl_flow_js_pr_key_proto *js_field)
     183                 :            : {
     184                 :            :         int len, i;
     185                 :            : 
     186         [ #  # ]:          0 :         if (!ob_fields)
     187                 :            :                 return 0;
     188                 :          0 :         len = json_array_size(ob_fields);
     189         [ #  # ]:          0 :         if (len == 0)
     190                 :            :                 return 0;
     191                 :          0 :         js_field->fields_size = len;
     192                 :          0 :         js_field->fields =
     193                 :          0 :             rte_malloc(NULL, sizeof(struct cpfl_flow_js_pr_key_proto_field) * len, 0);
     194         [ #  # ]:          0 :         if (!js_field->fields) {
     195                 :          0 :                 PMD_DRV_LOG(ERR, "Failed to alloc memory.");
     196                 :          0 :                 return -ENOMEM;
     197                 :            :         }
     198         [ #  # ]:          0 :         for (i = 0; i < len; i++) {
     199                 :            :                 json_t *object;
     200                 :            :                 const char *name, *mask;
     201                 :          0 :                 uint32_t mask_32b = 0;
     202                 :            :                 int ret;
     203                 :            : 
     204                 :          0 :                 object = json_array_get(ob_fields, i);
     205                 :          0 :                 name = cpfl_json_t_to_string(object, "name");
     206         [ #  # ]:          0 :                 if (!name) {
     207                 :          0 :                         PMD_DRV_LOG(ERR, "Can not parse string 'name'.");
     208                 :          0 :                         goto err;
     209                 :            :                 }
     210         [ #  # ]:          0 :                 if (strlen(name) > CPFL_JS_STR_SIZE - 1) {
     211                 :          0 :                         PMD_DRV_LOG(ERR, "The 'name' is too long.");
     212                 :          0 :                         goto err;
     213                 :            :                 }
     214         [ #  # ]:          0 :                 strncpy(js_field->fields[i].name, name, CPFL_JS_STR_SIZE - 1);
     215                 :            : 
     216         [ #  # ]:          0 :                 if (js_field->type == RTE_FLOW_ITEM_TYPE_ETH ||
     217                 :            :                     js_field->type == RTE_FLOW_ITEM_TYPE_IPV4) {
     218                 :            :                         /* Added a check for parsing mask value of the next_proto_id field. */
     219         [ #  # ]:          0 :                         if (strcmp(name, "next_proto_id") == 0) {
     220                 :          0 :                                 ret = cpfl_json_t_to_uint32(object, "mask", &mask_32b);
     221         [ #  # ]:          0 :                                 if (ret < 0) {
     222                 :          0 :                                         PMD_DRV_LOG(ERR, "Cannot parse uint32 'mask'.");
     223                 :          0 :                                         goto err;
     224                 :            :                                 }
     225                 :          0 :                                 js_field->fields[i].mask_32b = mask_32b;
     226                 :            :                         } else {
     227                 :          0 :                                 mask = cpfl_json_t_to_string(object, "mask");
     228         [ #  # ]:          0 :                                 if (!mask) {
     229                 :          0 :                                         PMD_DRV_LOG(ERR, "Can not parse string 'mask'.");
     230                 :          0 :                                         goto err;
     231                 :            :                                 }
     232         [ #  # ]:          0 :                                 if (rte_strscpy(js_field->fields[i].mask,
     233                 :            :                                                 mask, CPFL_JS_STR_SIZE) < 0) {
     234                 :          0 :                                         PMD_DRV_LOG(ERR, "The 'mask' is too long.");
     235                 :          0 :                                         goto err;
     236                 :            :                                 }
     237                 :            :                         }
     238                 :            : 
     239                 :            :                 } else {
     240                 :          0 :                         ret = cpfl_json_t_to_uint32(object, "mask", &mask_32b);
     241         [ #  # ]:          0 :                         if (ret < 0) {
     242                 :          0 :                                 PMD_DRV_LOG(ERR, "Can not parse uint32 'mask'.");
     243                 :          0 :                                 goto err;
     244                 :            :                         }
     245                 :          0 :                         js_field->fields[i].mask_32b = mask_32b;
     246                 :            :                 }
     247                 :            :         }
     248                 :            : 
     249                 :            :         return 0;
     250                 :            : 
     251                 :            : err:
     252                 :          0 :         rte_free(js_field->fields);
     253                 :          0 :         return -EINVAL;
     254                 :            : }
     255                 :            : 
     256                 :            : static int
     257                 :          0 : cpfl_flow_js_pattern_key_proto(json_t *ob_pr_key_protos, struct cpfl_flow_js_pr *js_pr)
     258                 :            : {
     259                 :            :         int len, i, ret;
     260                 :            : 
     261                 :          0 :         len = json_array_size(ob_pr_key_protos);
     262         [ #  # ]:          0 :         if (len == 0)
     263                 :            :                 return 0;
     264                 :          0 :         js_pr->key.proto_size = len;
     265                 :          0 :         js_pr->key.protocols = rte_malloc(NULL, sizeof(struct cpfl_flow_js_pr_key_proto) * len, 0);
     266         [ #  # ]:          0 :         if (!js_pr->key.protocols) {
     267                 :          0 :                 PMD_DRV_LOG(ERR, "Failed to alloc memory.");
     268                 :          0 :                 return -ENOMEM;
     269                 :            :         }
     270                 :            : 
     271         [ #  # ]:          0 :         for (i = 0; i < len; i++) {
     272                 :            :                 json_t *object, *ob_fields;
     273                 :            :                 const char *type;
     274                 :            :                 enum rte_flow_item_type item_type;
     275                 :            : 
     276                 :          0 :                 object = json_array_get(ob_pr_key_protos, i);
     277                 :            :                 /* pr->key->proto->type */
     278                 :          0 :                 type = cpfl_json_t_to_string(object, "type");
     279         [ #  # ]:          0 :                 if (!type) {
     280                 :          0 :                         PMD_DRV_LOG(ERR, "Can not parse string 'type'.");
     281                 :          0 :                         goto err;
     282                 :            :                 }
     283                 :          0 :                 item_type = cpfl_get_item_type_by_str(type);
     284         [ #  # ]:          0 :                 if (item_type == RTE_FLOW_ITEM_TYPE_VOID)
     285                 :          0 :                         goto err;
     286                 :          0 :                 js_pr->key.protocols[i].type = item_type;
     287                 :            :                 /* pr->key->proto->fields */
     288                 :          0 :                 ob_fields = json_object_get(object, "fields");
     289                 :          0 :                 ret = cpfl_flow_js_pattern_key_proto_field(ob_fields,
     290                 :          0 :                                                            &js_pr->key.protocols[i]);
     291         [ #  # ]:          0 :                 if (ret < 0)
     292                 :          0 :                         goto err;
     293                 :            :         }
     294                 :            : 
     295                 :            :         return 0;
     296                 :            : 
     297                 :          0 : err:
     298                 :          0 :         rte_free(js_pr->key.protocols);
     299                 :          0 :         return -EINVAL;
     300                 :            : }
     301                 :            : 
     302                 :            : static int
     303                 :          0 : cpfl_flow_js_pattern_act_fv_proto(json_t *ob_value, struct cpfl_flow_js_fv *js_fv)
     304                 :            : {
     305                 :          0 :         uint16_t layer = 0, offset = 0, mask = 0;
     306                 :            :         const char *header;
     307                 :            :         enum rte_flow_item_type type;
     308                 :            :         int ret;
     309                 :            : 
     310                 :          0 :         ret = cpfl_json_t_to_uint16(ob_value, "layer", &layer);
     311         [ #  # ]:          0 :         if (ret < 0) {
     312                 :          0 :                 PMD_DRV_LOG(ERR, "Can not parse 'value'.");
     313                 :          0 :                 return -EINVAL;
     314                 :            :         }
     315                 :            : 
     316                 :          0 :         header = cpfl_json_t_to_string(ob_value, "header");
     317         [ #  # ]:          0 :         if (!header) {
     318                 :          0 :                 PMD_DRV_LOG(ERR, "Can not parse string 'header'.");
     319                 :          0 :                 return -EINVAL;
     320                 :            :         }
     321                 :          0 :         ret = cpfl_json_t_to_uint16(ob_value, "offset", &offset);
     322         [ #  # ]:          0 :         if (ret < 0) {
     323                 :          0 :                 PMD_DRV_LOG(ERR, "Can not parse 'offset'.");
     324                 :          0 :                 return -EINVAL;
     325                 :            :         }
     326                 :          0 :         ret = cpfl_json_t_to_uint16(ob_value, "mask", &mask);
     327         [ #  # ]:          0 :         if (ret < 0) {
     328                 :          0 :                 PMD_DRV_LOG(ERR, "Can not parse 'mask'.");
     329                 :          0 :                 return -EINVAL;
     330                 :            :         }
     331                 :          0 :         type = cpfl_get_item_type_by_str(header);
     332         [ #  # ]:          0 :         if (type == RTE_FLOW_ITEM_TYPE_VOID)
     333                 :            :                 return -EINVAL;
     334                 :          0 :         js_fv->proto.layer = layer;
     335                 :          0 :         js_fv->proto.offset = offset;
     336                 :          0 :         js_fv->proto.mask = mask;
     337                 :          0 :         js_fv->proto.header = type;
     338                 :            : 
     339                 :          0 :         return 0;
     340                 :            : }
     341                 :            : 
     342                 :            : static int
     343                 :          0 : cpfl_flow_js_pattern_act_fv_metadata(json_t *ob_value, struct cpfl_flow_js_fv *js_fv)
     344                 :            : {
     345                 :            :         int ret;
     346                 :            : 
     347                 :          0 :         ret = cpfl_json_t_to_uint16(ob_value, "type", &js_fv->meta.type);
     348         [ #  # ]:          0 :         if (ret < 0) {
     349                 :          0 :                 PMD_DRV_LOG(ERR, "Can not parse 'size'.");
     350                 :          0 :                 return ret;
     351                 :            :         }
     352                 :          0 :         ret = cpfl_json_t_to_uint16(ob_value, "offset", &js_fv->meta.offset);
     353         [ #  # ]:          0 :         if (ret < 0) {
     354                 :          0 :                 PMD_DRV_LOG(ERR, "Can not parse 'size'.");
     355                 :          0 :                 return ret;
     356                 :            :         }
     357                 :          0 :         ret = cpfl_json_t_to_uint16(ob_value, "mask", &js_fv->meta.mask);
     358         [ #  # ]:          0 :         if (ret < 0) {
     359                 :          0 :                 PMD_DRV_LOG(ERR, "Can not parse 'size'.");
     360                 :          0 :                 return ret;
     361                 :            :         }
     362                 :            : 
     363                 :            :         return 0;
     364                 :            : }
     365                 :            : 
     366                 :            : static int
     367                 :          0 : cpfl_flow_js_pattern_act_fv(json_t *ob_fvs, struct cpfl_flow_js_pr_action *js_act)
     368                 :            : {
     369                 :            :         int len, i;
     370                 :            : 
     371                 :          0 :         len = json_array_size(ob_fvs);
     372         [ #  # ]:          0 :         if (len == 0)
     373                 :            :                 return 0;
     374                 :          0 :         js_act->sem.fv = rte_malloc(NULL, sizeof(struct cpfl_flow_js_fv) * len, 0);
     375         [ #  # ]:          0 :         if (!js_act->sem.fv) {
     376                 :          0 :                 PMD_DRV_LOG(ERR, "Failed to alloc memory.");
     377                 :          0 :                 return -ENOMEM;
     378                 :            :         }
     379                 :          0 :         js_act->sem.fv_size = len;
     380         [ #  # ]:          0 :         for (i = 0; i < len; i++) {
     381                 :            :                 struct cpfl_flow_js_fv *js_fv;
     382                 :            :                 json_t *object, *ob_value;
     383                 :          0 :                 uint16_t offset = 0;
     384                 :            :                 const char *type;
     385                 :            :                 int ret;
     386                 :            : 
     387                 :          0 :                 js_fv = &js_act->sem.fv[i];
     388                 :          0 :                 object = json_array_get(ob_fvs, i);
     389                 :          0 :                 ret = cpfl_json_t_to_uint16(object, "offset", &offset);
     390         [ #  # ]:          0 :                 if (ret < 0) {
     391                 :          0 :                         PMD_DRV_LOG(ERR, "Can not parse 'offset'.");
     392                 :          0 :                         goto err;
     393                 :            :                 }
     394                 :          0 :                 js_fv->offset = offset;
     395                 :            : 
     396                 :          0 :                 type = cpfl_json_t_to_string(object, "type");
     397         [ #  # ]:          0 :                 if (!type) {
     398                 :          0 :                         PMD_DRV_LOG(ERR, "Can not parse string 'type'.");
     399                 :          0 :                         goto err;
     400                 :            :                 }
     401                 :          0 :                 ob_value = json_object_get(object, "value");
     402         [ #  # ]:          0 :                 if (strcmp(type, "immediate") == 0) {
     403                 :          0 :                         js_fv->type = CPFL_FV_TYPE_IMMEDIATE;
     404                 :          0 :                         js_fv->immediate = json_integer_value(ob_value);
     405         [ #  # ]:          0 :                 } else if (strcmp(type, "metadata") == 0) {
     406                 :          0 :                         js_fv->type = CPFL_FV_TYPE_METADATA;
     407                 :          0 :                         cpfl_flow_js_pattern_act_fv_metadata(ob_value, js_fv);
     408         [ #  # ]:          0 :                 } else if (strcmp(type, "protocol") == 0) {
     409                 :          0 :                         js_fv->type = CPFL_FV_TYPE_PROTOCOL;
     410                 :          0 :                         cpfl_flow_js_pattern_act_fv_proto(ob_value, js_fv);
     411                 :            :                 } else {
     412                 :          0 :                         PMD_DRV_LOG(ERR, "Not support this type: %s.", type);
     413                 :          0 :                         goto err;
     414                 :            :                 }
     415                 :            :         }
     416                 :            : 
     417                 :            :         return 0;
     418                 :            : 
     419                 :            : err:
     420                 :          0 :         rte_free(js_act->sem.fv);
     421                 :          0 :         return -EINVAL;
     422                 :            : }
     423                 :            : 
     424                 :            : static int
     425                 :          0 : cpfl_flow_js_pattern_per_act(json_t *ob_per_act, struct cpfl_flow_js_pr_action *js_act)
     426                 :            : {
     427                 :            :         const char *type;
     428                 :            :         int ret;
     429                 :            : 
     430                 :            :         /* pr->actions->type */
     431                 :          0 :         type = cpfl_json_t_to_string(ob_per_act, "type");
     432         [ #  # ]:          0 :         if (!type) {
     433                 :          0 :                 PMD_DRV_LOG(ERR, "Can not parse string 'type'.");
     434                 :          0 :                 return -EINVAL;
     435                 :            :         }
     436                 :            :         /* pr->actions->data */
     437         [ #  # ]:          0 :         if (strcmp(type, "sem") == 0) {
     438                 :            :                 json_t *ob_fvs, *ob_sem;
     439                 :            : 
     440                 :          0 :                 js_act->type = CPFL_JS_PR_ACTION_TYPE_SEM;
     441                 :          0 :                 ob_sem = json_object_get(ob_per_act, "data");
     442                 :          0 :                 ret = cpfl_json_t_to_uint16(ob_sem, "profile", &js_act->sem.prof);
     443         [ #  # ]:          0 :                 if (ret < 0) {
     444                 :          0 :                         PMD_DRV_LOG(ERR, "Can not parse 'profile'.");
     445                 :          0 :                         return -EINVAL;
     446                 :            :                 }
     447                 :          0 :                 ret = cpfl_json_t_to_uint16(ob_sem, "subprofile", &js_act->sem.subprof);
     448         [ #  # ]:          0 :                 if (ret < 0) {
     449                 :          0 :                         PMD_DRV_LOG(ERR, "Can not parse 'subprofile'.");
     450                 :          0 :                         return -EINVAL;
     451                 :            :                 }
     452                 :          0 :                 ret = cpfl_json_t_to_uint16(ob_sem, "keysize", &js_act->sem.keysize);
     453         [ #  # ]:          0 :                 if (ret < 0) {
     454                 :          0 :                         PMD_DRV_LOG(ERR, "Can not parse 'keysize'.");
     455                 :          0 :                         return -EINVAL;
     456                 :            :                 }
     457                 :          0 :                 ob_fvs = json_object_get(ob_sem, "fieldvectors");
     458                 :          0 :                 ret = cpfl_flow_js_pattern_act_fv(ob_fvs, js_act);
     459                 :            :                 if (ret < 0)
     460                 :            :                         return ret;
     461                 :            :         } else {
     462                 :          0 :                 PMD_DRV_LOG(ERR, "Not support this type: %s.", type);
     463                 :          0 :                 return -EINVAL;
     464                 :            :         }
     465                 :            : 
     466                 :            :         return 0;
     467                 :            : }
     468                 :            : 
     469                 :            : static int
     470                 :          0 : cpfl_flow_js_pattern_act(json_t *ob_pr_acts, struct cpfl_flow_js_pr *js_pr)
     471                 :            : {
     472                 :            :         int i, len, ret;
     473                 :            : 
     474                 :          0 :         len = json_array_size(ob_pr_acts);
     475         [ #  # ]:          0 :         if (len == 0)
     476                 :            :                 return 0;
     477                 :          0 :         js_pr->actions = rte_malloc(NULL, sizeof(struct cpfl_flow_js_pr_action) * len, 0);
     478         [ #  # ]:          0 :         if (!js_pr->actions) {
     479                 :          0 :                 PMD_DRV_LOG(ERR, "Failed to alloc memory.");
     480                 :          0 :                 return -ENOMEM;
     481                 :            :         }
     482                 :          0 :         js_pr->actions_size = len;
     483         [ #  # ]:          0 :         for (i = 0; i < len; i++) {
     484                 :            :                 struct cpfl_flow_js_pr_action *js_act;
     485                 :            :                 json_t *object;
     486                 :            : 
     487                 :          0 :                 object = json_array_get(ob_pr_acts, i);
     488                 :          0 :                 js_act = &js_pr->actions[i];
     489                 :          0 :                 ret = cpfl_flow_js_pattern_per_act(object, js_act);
     490         [ #  # ]:          0 :                 if (ret < 0) {
     491                 :          0 :                         rte_free(js_pr->actions);
     492                 :          0 :                         PMD_DRV_LOG(ERR, "Can not parse pattern action.");
     493                 :          0 :                         return -EINVAL;
     494                 :            :                 }
     495                 :            :         }
     496                 :            : 
     497                 :            :         return 0;
     498                 :            : }
     499                 :            : 
     500                 :            : /**
     501                 :            :  * The patterns object array defines a set of rules directing the PMD to match sequences of
     502                 :            :  * rte_flow protocol headers and translate them into profile/field vectors for each pipeline
     503                 :            :  * stage. This object is mandatory.
     504                 :            :  */
     505                 :            : static int
     506                 :          0 : cpfl_flow_js_pattern_rule(json_t *ob_root, struct cpfl_flow_js_parser *parser)
     507                 :            : {
     508                 :            :         json_t *ob_prs;
     509                 :            :         int i, len;
     510                 :            : 
     511                 :            :         /* Pattern Rules */
     512                 :          0 :         ob_prs = json_object_get(ob_root, "patterns");
     513         [ #  # ]:          0 :         if (!ob_prs) {
     514                 :          0 :                 PMD_DRV_LOG(ERR, "The patterns is mandatory.");
     515                 :          0 :                 return -EINVAL;
     516                 :            :         }
     517                 :            : 
     518                 :          0 :         len = json_array_size(ob_prs);
     519         [ #  # ]:          0 :         if (len == 0)
     520                 :            :                 return 0;
     521                 :          0 :         parser->patterns = rte_malloc(NULL, sizeof(struct cpfl_flow_js_pr) * len, 0);
     522         [ #  # ]:          0 :         if (!parser->patterns) {
     523                 :          0 :                 PMD_DRV_LOG(ERR, "Failed to alloc memory.");
     524                 :          0 :                 return -ENOMEM;
     525                 :            :         }
     526                 :          0 :         parser->pr_size = len;
     527         [ #  # ]:          0 :         for (i = 0; i < len; i++) {
     528                 :            :                 json_t *object;
     529                 :            :                 json_t *ob_pr_actions;
     530                 :            :                 json_t *ob_pr_key;
     531                 :            :                 json_t *ob_pr_key_protos;
     532                 :            :                 json_t *ob_pr_key_attrs;
     533                 :            :                 int ret;
     534                 :            : 
     535                 :          0 :                 object = json_array_get(ob_prs, i);
     536                 :            :                 /* pr->key */
     537                 :          0 :                 ob_pr_key = json_object_get(object, "key");
     538                 :            :                 /* pr->key->protocols */
     539                 :          0 :                 ob_pr_key_protos = json_object_get(ob_pr_key, "protocols");
     540                 :          0 :                 ret = cpfl_flow_js_pattern_key_proto(ob_pr_key_protos, &parser->patterns[i]);
     541         [ #  # ]:          0 :                 if (ret < 0) {
     542                 :          0 :                         PMD_DRV_LOG(ERR, "Can not parse key->protocols.");
     543                 :          0 :                         goto err;
     544                 :            :                 }
     545                 :            :                 /* pr->key->attributes */
     546                 :          0 :                 ob_pr_key_attrs = json_object_get(ob_pr_key, "attributes");
     547                 :          0 :                 ret = cpfl_flow_js_pattern_key_attr(ob_pr_key_attrs, &parser->patterns[i]);
     548         [ #  # ]:          0 :                 if (ret < 0) {
     549                 :          0 :                         PMD_DRV_LOG(ERR, "Can not parse key->attributes.");
     550                 :          0 :                         goto err;
     551                 :            :                 }
     552                 :            :                 /* pr->actions */
     553                 :          0 :                 ob_pr_actions = json_object_get(object, "actions");
     554                 :          0 :                 ret = cpfl_flow_js_pattern_act(ob_pr_actions, &parser->patterns[i]);
     555         [ #  # ]:          0 :                 if (ret < 0) {
     556                 :          0 :                         PMD_DRV_LOG(ERR, "Can not parse pattern action.");
     557                 :          0 :                         goto err;
     558                 :            :                 }
     559                 :            :         }
     560                 :            : 
     561                 :            :         return 0;
     562                 :            : 
     563                 :          0 : err:
     564                 :          0 :         rte_free(parser->patterns);
     565                 :          0 :         return -EINVAL;
     566                 :            : }
     567                 :            : 
     568                 :            : static int
     569                 :          0 : cpfl_flow_js_mr_key(json_t *ob_mr_keys, struct cpfl_flow_js_mr_key *js_mr_key)
     570                 :            : {
     571                 :            :         int len, i;
     572                 :            : 
     573                 :          0 :         len = json_array_size(ob_mr_keys);
     574         [ #  # ]:          0 :         if (len == 0)
     575                 :            :                 return 0;
     576                 :          0 :         js_mr_key->actions = rte_malloc(NULL, sizeof(struct cpfl_flow_js_mr_key_action) * len, 0);
     577         [ #  # ]:          0 :         if (!js_mr_key->actions) {
     578                 :          0 :                 PMD_DRV_LOG(ERR, "Failed to alloc memory.");
     579                 :          0 :                 return -ENOMEM;
     580                 :            :         }
     581                 :          0 :         js_mr_key->actions_size = len;
     582         [ #  # ]:          0 :         for (i = 0; i < len; i++) {
     583                 :            :                 json_t *object, *ob_data;
     584                 :            :                 const char *type;
     585                 :            :                 enum rte_flow_action_type act_type;
     586                 :            : 
     587                 :          0 :                 object = json_array_get(ob_mr_keys, i);
     588                 :            :                 /* mr->key->actions->type */
     589                 :          0 :                 type = cpfl_json_t_to_string(object, "type");
     590         [ #  # ]:          0 :                 if (!type) {
     591                 :          0 :                         PMD_DRV_LOG(ERR, "Can not parse string 'type'.");
     592                 :          0 :                         goto err;
     593                 :            :                 }
     594                 :          0 :                 act_type = cpfl_get_action_type_by_str(type);
     595         [ #  # ]:          0 :                 if (act_type == RTE_FLOW_ACTION_TYPE_VOID)
     596                 :          0 :                         goto err;
     597                 :          0 :                 js_mr_key->actions[i].type = act_type;
     598                 :            :                 /* mr->key->actions->data */
     599                 :          0 :                 ob_data = json_object_get(object, "data");
     600         [ #  # ]:          0 :                 if (js_mr_key->actions[i].type == RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP) {
     601                 :            :                         json_t *ob_protos;
     602                 :            :                         int proto_size, j;
     603                 :            :                         struct cpfl_flow_js_mr_key_action_vxlan_encap *encap;
     604                 :            : 
     605                 :          0 :                         ob_protos = json_object_get(ob_data, "protocols");
     606                 :          0 :                         encap = &js_mr_key->actions[i].encap;
     607         [ #  # ]:          0 :                         if (!ob_protos) {
     608                 :          0 :                                 encap->proto_size = 0;
     609                 :          0 :                                 continue;
     610                 :            :                         }
     611                 :          0 :                         proto_size = json_array_size(ob_protos);
     612                 :          0 :                         encap->proto_size = proto_size;
     613         [ #  # ]:          0 :                         for (j = 0; j < proto_size; j++) {
     614                 :            :                                 const char *s;
     615                 :            :                                 json_t *subobject;
     616                 :            :                                 enum rte_flow_item_type proto_type;
     617                 :            : 
     618                 :          0 :                                 subobject = json_array_get(ob_protos, j);
     619                 :          0 :                                 s = json_string_value(subobject);
     620                 :          0 :                                 proto_type = cpfl_get_item_type_by_str(s);
     621         [ #  # ]:          0 :                                 if (proto_type == RTE_FLOW_ITEM_TYPE_VOID) {
     622                 :          0 :                                         PMD_DRV_LOG(ERR, "parse VXLAN_ENCAP failed.");
     623                 :          0 :                                         goto err;
     624                 :            :                                 }
     625                 :          0 :                                 encap->protocols[j] = proto_type;
     626                 :            :                         }
     627         [ #  # ]:          0 :                 } else if (js_mr_key->actions[i].type == RTE_FLOW_ACTION_TYPE_PROG) {
     628                 :            :                         int ret;
     629                 :            :                         uint32_t param_size, j;
     630                 :          0 :                         uint16_t value = 0;
     631                 :            :                         json_t *ob_param, *subobject;
     632                 :            :                         const char *name;
     633                 :            : 
     634                 :          0 :                         ret = cpfl_json_t_to_uint32(object, "id", &js_mr_key->actions[i].prog.id);
     635         [ #  # ]:          0 :                         if (ret < 0) {
     636                 :          0 :                                 PMD_DRV_LOG(ERR, "Can not parse uint32 'id'.");
     637                 :          0 :                                 goto err;
     638                 :            :                         }
     639         [ #  # ]:          0 :                         if (json_object_get(object, "name")) {
     640                 :          0 :                                 js_mr_key->actions[i].prog.has_name = TRUE;
     641                 :          0 :                                 name = cpfl_json_t_to_string(object, "name");
     642         [ #  # ]:          0 :                                 if (!name) {
     643                 :          0 :                                         PMD_DRV_LOG(ERR, "Can not parse string 'name'.");
     644                 :          0 :                                         goto err;
     645                 :            :                                 }
     646         [ #  # ]:          0 :                                 if (strlen(name) > CPFL_JS_STR_SIZE - 1) {
     647                 :          0 :                                         PMD_DRV_LOG(ERR, "The 'name' is too long.");
     648                 :          0 :                                         goto err;
     649                 :            :                                 }
     650                 :          0 :                                 strncpy(js_mr_key->actions[i].prog.name, name,
     651                 :            :                                         CPFL_JS_STR_SIZE - 1);
     652                 :            :                         }
     653                 :            : 
     654                 :          0 :                         ob_param = json_object_get(object, "parameters");
     655                 :          0 :                         param_size = json_array_size(ob_param);
     656                 :          0 :                         js_mr_key->actions[i].prog.param_size = param_size;
     657         [ #  # ]:          0 :                         for (j = 0; j < param_size; j++) {
     658                 :          0 :                                 subobject = json_array_get(ob_param, j);
     659                 :          0 :                                 ret = cpfl_json_t_to_uint16(subobject, "index", &value);
     660         [ #  # ]:          0 :                                 if (ret < 0) {
     661                 :          0 :                                         PMD_DRV_LOG(ERR, "Can not parse 'index'.");
     662                 :          0 :                                         goto err;
     663                 :            :                                 }
     664                 :          0 :                                 js_mr_key->actions[i].prog.params[j].index = value;
     665         [ #  # ]:          0 :                                 if (json_object_get(subobject, "name")) {
     666                 :          0 :                                         js_mr_key->actions[i].prog.params[j].has_name = TRUE;
     667                 :          0 :                                         name = cpfl_json_t_to_string(subobject, "name");
     668         [ #  # ]:          0 :                                         if (!name) {
     669                 :          0 :                                                 PMD_DRV_LOG(ERR, "Can not parse string 'name'.");
     670                 :          0 :                                                 goto err;
     671                 :            :                                         }
     672         [ #  # ]:          0 :                                         if (strlen(name) > CPFL_JS_STR_SIZE - 1) {
     673                 :          0 :                                                 PMD_DRV_LOG(ERR, "The 'name' is too long.");
     674                 :          0 :                                                 goto err;
     675                 :            :                                         }
     676                 :          0 :                                         strncpy(js_mr_key->actions[i].prog.params[j].name, name,
     677                 :            :                                                 CPFL_JS_STR_SIZE - 1);
     678                 :            :                                 }
     679                 :          0 :                                 ret = cpfl_json_t_to_uint16(subobject, "size", &value);
     680         [ #  # ]:          0 :                                 if (ret < 0) {
     681                 :          0 :                                         PMD_DRV_LOG(ERR, "Can not parse 'size'.");
     682                 :          0 :                                         goto err;
     683                 :            :                                 }
     684                 :          0 :                                 js_mr_key->actions[i].prog.params[j].size = value;
     685                 :            :                         }
     686                 :            : 
     687         [ #  # ]:          0 :                 } else if (js_mr_key->actions[i].type != RTE_FLOW_ACTION_TYPE_VXLAN_DECAP) {
     688                 :          0 :                         PMD_DRV_LOG(ERR, "not support this type: %d.", js_mr_key->actions[i].type);
     689                 :          0 :                         goto err;
     690                 :            :                 }
     691                 :            :         }
     692                 :            : 
     693                 :            :         return 0;
     694                 :            : 
     695                 :          0 : err:
     696                 :          0 :         rte_free(js_mr_key->actions);
     697                 :          0 :         return -EINVAL;
     698                 :            : }
     699                 :            : 
     700                 :            : static int
     701                 :          0 : cpfl_flow_js_mr_layout(json_t *ob_layouts, struct cpfl_flow_js_mr_action_mod *js_mod)
     702                 :            : {
     703                 :            :         int len, i;
     704                 :            : 
     705                 :          0 :         len = json_array_size(ob_layouts);
     706                 :          0 :         js_mod->layout_size = len;
     707         [ #  # ]:          0 :         if (len == 0)
     708                 :            :                 return 0;
     709                 :            : 
     710         [ #  # ]:          0 :         for (i = 0; i < len; i++) {
     711                 :            :                 json_t *object;
     712                 :          0 :                 int index = 0, size = 0, offset = 0;
     713                 :            :                 int ret;
     714                 :            :                 const char *hint;
     715                 :            : 
     716                 :          0 :                 object = json_array_get(ob_layouts, i);
     717                 :          0 :                 ret = cpfl_json_t_to_int(object, "index", &index);
     718         [ #  # ]:          0 :                 if (ret < 0) {
     719                 :          0 :                         PMD_DRV_LOG(ERR, "Can not parse 'index'.");
     720                 :          0 :                         goto err;
     721                 :            :                 }
     722                 :          0 :                 js_mod->layout[i].index = index;
     723                 :          0 :                 ret = cpfl_json_t_to_int(object, "size", &size);
     724         [ #  # ]:          0 :                 if (ret < 0) {
     725                 :          0 :                         PMD_DRV_LOG(ERR, "Can not parse 'size'.");
     726                 :          0 :                         goto err;
     727                 :            :                 }
     728                 :          0 :                 js_mod->layout[i].size = size;
     729                 :          0 :                 ret = cpfl_json_t_to_int(object, "offset", &offset);
     730         [ #  # ]:          0 :                 if (ret < 0) {
     731                 :          0 :                         PMD_DRV_LOG(ERR, "Can not parse 'offset'.");
     732                 :          0 :                         goto err;
     733                 :            :                 }
     734                 :          0 :                 js_mod->layout[i].offset = offset;
     735                 :          0 :                 hint = cpfl_json_t_to_string(object, "hint");
     736         [ #  # ]:          0 :                 if (!hint) {
     737                 :          0 :                         PMD_DRV_LOG(ERR, "Can not parse string 'hint'.");
     738                 :          0 :                         goto err;
     739                 :            :                 }
     740         [ #  # ]:          0 :                 if (strlen(hint) > CPFL_JS_STR_SIZE - 1) {
     741                 :          0 :                         PMD_DRV_LOG(ERR, "The 'hint' is too long.");
     742                 :          0 :                         goto err;
     743                 :            :                 }
     744                 :          0 :                 strncpy(js_mod->layout[i].hint, hint, CPFL_JS_STR_SIZE - 1);
     745                 :            :         }
     746                 :            : 
     747                 :            :         return 0;
     748                 :            : 
     749                 :            : err:
     750                 :          0 :         return -EINVAL;
     751                 :            : }
     752                 :            : 
     753                 :            : static int
     754                 :          0 : cpfl_flow_js_mr_content(json_t *ob_content, struct cpfl_flow_js_mr_action_mod *js_mod)
     755                 :            : {
     756                 :            :         int ret, len, i;
     757                 :            :         json_t *ob_field;
     758                 :            : 
     759         [ #  # ]:          0 :         if (!ob_content)
     760                 :            :                 return 0;
     761                 :            : 
     762                 :          0 :         js_mod->is_content = TRUE;
     763                 :          0 :         ret = cpfl_json_t_to_uint16(ob_content, "size", &js_mod->content.size);
     764         [ #  # ]:          0 :         if (ret < 0) {
     765                 :          0 :                 PMD_DRV_LOG(ERR, "Can not parse 'size'.");
     766                 :          0 :                 return -EINVAL;
     767                 :            :         }
     768                 :            : 
     769                 :          0 :         ob_field = json_object_get(ob_content, "fields");
     770                 :          0 :         len = json_array_size(ob_field);
     771                 :          0 :         js_mod->content.field_size = len;
     772         [ #  # ]:          0 :         if (len == 0)
     773                 :            :                 return 0;
     774                 :            : 
     775         [ #  # ]:          0 :         for (i = 0; i < len; i++) {
     776                 :            :                 json_t *object;
     777                 :          0 :                 uint16_t start = 0, width = 0, index = 0;
     778                 :            :                 const char *type;
     779                 :            : 
     780                 :          0 :                 object = json_array_get(ob_field, i);
     781                 :          0 :                 type = cpfl_json_t_to_string(object, "type");
     782         [ #  # ]:          0 :                 if (!type) {
     783                 :          0 :                         PMD_DRV_LOG(ERR, "Can not parse string 'type'.");
     784                 :          0 :                         goto err;
     785                 :            :                 }
     786         [ #  # ]:          0 :                 if (strlen(type) > CPFL_JS_STR_SIZE - 1) {
     787                 :          0 :                         PMD_DRV_LOG(ERR, "The 'type' is too long.");
     788                 :          0 :                         goto err;
     789                 :            :                 }
     790                 :          0 :                 strncpy(js_mod->content.fields[i].type, type, CPFL_JS_STR_SIZE - 1);
     791                 :          0 :                 ret = cpfl_json_t_to_uint16(object, "start", &start);
     792         [ #  # ]:          0 :                 if (ret < 0) {
     793                 :          0 :                         PMD_DRV_LOG(ERR, "Can not parse 'start'.");
     794                 :          0 :                         goto err;
     795                 :            :                 }
     796                 :          0 :                 js_mod->content.fields[i].start = start;
     797                 :          0 :                 ret = cpfl_json_t_to_uint16(object, "width", &width);
     798         [ #  # ]:          0 :                 if (ret < 0) {
     799                 :          0 :                         PMD_DRV_LOG(ERR, "Can not parse 'width'.");
     800                 :          0 :                         goto err;
     801                 :            :                 }
     802                 :          0 :                 js_mod->content.fields[i].width = width;
     803         [ #  # ]:          0 :                 if (strcmp(type, "parameter") == 0) {
     804                 :          0 :                         ret = cpfl_json_t_to_uint16(object, "index", &index);
     805         [ #  # ]:          0 :                         if (ret < 0) {
     806                 :          0 :                                 PMD_DRV_LOG(ERR, "Can not parse 'index'.");
     807                 :          0 :                                 goto err;
     808                 :            :                         }
     809                 :          0 :                         js_mod->content.fields[i].index = index;
     810         [ #  # ]:          0 :                 } else if (strcmp(type, "constant") == 0) {
     811                 :            :                         json_t *ob_value, *subobj;
     812                 :            :                         int value_len, j;
     813                 :            : 
     814                 :          0 :                         ob_value = json_object_get(object, "value");
     815                 :          0 :                         value_len = json_array_size(ob_value);
     816         [ #  # ]:          0 :                         for (j = 0; j < value_len; j++) {
     817                 :          0 :                                 subobj = json_array_get(ob_value, j);
     818                 :          0 :                                 js_mod->content.fields[i].value[j] =
     819                 :          0 :                                     (uint8_t)json_integer_value(subobj);
     820                 :            :                         }
     821                 :            :                 }
     822                 :            :         }
     823                 :            : 
     824                 :            :         return 0;
     825                 :            : 
     826                 :            : err:
     827                 :          0 :         return -EINVAL;
     828                 :            : }
     829                 :            : 
     830                 :            : static int
     831                 :          0 : cpfl_flow_js_mr_action(json_t *ob_mr_act, struct cpfl_flow_js_mr_action *js_mr_act)
     832                 :            : {
     833                 :            :         json_t *ob_data;
     834                 :            :         const char *type;
     835                 :            : 
     836                 :            :         /* mr->action->type */
     837                 :          0 :         type = cpfl_json_t_to_string(ob_mr_act, "type");
     838         [ #  # ]:          0 :         if (!type) {
     839                 :          0 :                 PMD_DRV_LOG(ERR, "Can not parse string 'type'.");
     840                 :          0 :                 return -EINVAL;
     841                 :            :         }
     842                 :            :         /* mr->action->data */
     843                 :          0 :         ob_data = json_object_get(ob_mr_act, "data");
     844         [ #  # ]:          0 :         if (strcmp(type, "mod") == 0) {
     845                 :            :                 json_t *ob_layouts, *ob_content;
     846                 :          0 :                 uint16_t profile = 0;
     847                 :            :                 int ret;
     848                 :            : 
     849                 :          0 :                 js_mr_act->type = CPFL_JS_MR_ACTION_TYPE_MOD;
     850                 :          0 :                 ret = cpfl_json_t_to_uint16(ob_data, "profile", &profile);
     851         [ #  # ]:          0 :                 if (ret < 0) {
     852                 :          0 :                         PMD_DRV_LOG(ERR, "Can not parse 'profile'.");
     853                 :          0 :                         return -EINVAL;
     854                 :            :                 }
     855                 :          0 :                 js_mr_act->mod.prof = profile;
     856                 :          0 :                 ob_layouts = json_object_get(ob_data, "layout");
     857                 :          0 :                 ret = cpfl_flow_js_mr_layout(ob_layouts, &js_mr_act->mod);
     858         [ #  # ]:          0 :                 if (ret < 0) {
     859                 :          0 :                         PMD_DRV_LOG(ERR, "Can not parse layout.");
     860                 :          0 :                         return ret;
     861                 :            :                 }
     862                 :          0 :                 ob_content = json_object_get(ob_data, "content");
     863                 :          0 :                 ret = cpfl_flow_js_mr_content(ob_content, &js_mr_act->mod);
     864         [ #  # ]:          0 :                 if (ret < 0) {
     865                 :          0 :                         PMD_DRV_LOG(ERR, "Can not parse 'content'.");
     866                 :          0 :                         return ret;
     867                 :            :                 }
     868                 :            :         } else  {
     869                 :          0 :                 PMD_DRV_LOG(ERR, "not support this type: %s.", type);
     870                 :          0 :                 return -EINVAL;
     871                 :            :         }
     872                 :            : 
     873                 :          0 :         return 0;
     874                 :            : }
     875                 :            : 
     876                 :            : /**
     877                 :            :  * The modifications object array defines a set of rules for the PMD to match rte_flow
     878                 :            :  * modification actions and translate them into the Modification profile. This object
     879                 :            :  * is optional.
     880                 :            :  */
     881                 :            : static int
     882                 :          0 : cpfl_flow_js_mod_rule(json_t *ob_root, struct cpfl_flow_js_parser *parser)
     883                 :            : {
     884                 :            :         json_t *ob_mrs;
     885                 :            :         int i, len;
     886                 :            : 
     887                 :          0 :         ob_mrs = json_object_get(ob_root, "modifications");
     888         [ #  # ]:          0 :         if (!ob_mrs) {
     889                 :          0 :                 PMD_DRV_LOG(INFO, "The modifications is optional.");
     890                 :          0 :                 return 0;
     891                 :            :         }
     892                 :          0 :         len = json_array_size(ob_mrs);
     893         [ #  # ]:          0 :         if (len == 0)
     894                 :            :                 return 0;
     895                 :          0 :         parser->mr_size = len;
     896                 :          0 :         parser->modifications = rte_malloc(NULL, sizeof(struct cpfl_flow_js_mr) * len, 0);
     897         [ #  # ]:          0 :         if (!parser->modifications) {
     898                 :          0 :                 PMD_DRV_LOG(ERR, "Failed to alloc memory.");
     899                 :          0 :                 return -ENOMEM;
     900                 :            :         }
     901         [ #  # ]:          0 :         for (i = 0; i < len; i++) {
     902                 :            :                 int ret;
     903                 :            :                 json_t *object, *ob_mr_key, *ob_mr_action, *ob_mr_key_action;
     904                 :            : 
     905                 :          0 :                 object = json_array_get(ob_mrs, i);
     906                 :            :                 /* mr->key */
     907                 :          0 :                 ob_mr_key = json_object_get(object, "key");
     908                 :            :                 /* mr->key->actions */
     909                 :          0 :                 ob_mr_key_action = json_object_get(ob_mr_key, "actions");
     910                 :          0 :                 ret = cpfl_flow_js_mr_key(ob_mr_key_action, &parser->modifications[i].key);
     911         [ #  # ]:          0 :                 if (ret < 0) {
     912                 :          0 :                         PMD_DRV_LOG(ERR, "parse mr_key failed.");
     913                 :          0 :                         goto err;
     914                 :            :                 }
     915                 :            :                 /* mr->action */
     916                 :          0 :                 ob_mr_action = json_object_get(object, "action");
     917                 :          0 :                 ret = cpfl_flow_js_mr_action(ob_mr_action, &parser->modifications[i].action);
     918         [ #  # ]:          0 :                 if (ret < 0) {
     919                 :          0 :                         PMD_DRV_LOG(ERR, "parse mr_action failed.");
     920                 :          0 :                         goto err;
     921                 :            :                 }
     922                 :            :         }
     923                 :            : 
     924                 :            :         return 0;
     925                 :            : 
     926                 :          0 : err:
     927                 :          0 :         rte_free(parser->modifications);
     928                 :          0 :         return -EINVAL;
     929                 :            : }
     930                 :            : 
     931                 :            : static int
     932                 :          0 : cpfl_parser_init(json_t *ob_root, struct cpfl_flow_js_parser *parser)
     933                 :            : {
     934                 :            :         int ret = 0;
     935                 :            : 
     936                 :          0 :         ret = cpfl_flow_js_pattern_rule(ob_root, parser);
     937         [ #  # ]:          0 :         if (ret < 0) {
     938                 :          0 :                 PMD_DRV_LOG(ERR, "parse pattern_rule failed.");
     939                 :          0 :                 return ret;
     940                 :            :         }
     941                 :          0 :         ret = cpfl_flow_js_mod_rule(ob_root, parser);
     942         [ #  # ]:          0 :         if (ret < 0) {
     943                 :          0 :                 PMD_DRV_LOG(ERR, "parse mod_rule failed.");
     944                 :          0 :                 return ret;
     945                 :            :         }
     946                 :            : 
     947                 :            :         return 0;
     948                 :            : }
     949                 :            : 
     950                 :            : int
     951                 :          0 : cpfl_parser_create(struct cpfl_flow_js_parser **flow_parser, const char *filename)
     952                 :            : {
     953                 :            :         struct cpfl_flow_js_parser *parser;
     954                 :            :         json_error_t json_error;
     955                 :            :         json_t *root;
     956                 :            :         int ret;
     957                 :            : 
     958                 :          0 :         parser = rte_zmalloc("flow_parser", sizeof(struct cpfl_flow_js_parser), 0);
     959         [ #  # ]:          0 :         if (!parser) {
     960                 :          0 :                 PMD_DRV_LOG(ERR, "Not enough memory to create flow parser.");
     961                 :          0 :                 return -ENOMEM;
     962                 :            :         }
     963                 :          0 :         root = json_load_file(filename, 0, &json_error);
     964         [ #  # ]:          0 :         if (!root) {
     965                 :          0 :                 PMD_DRV_LOG(ERR, "Bad JSON file \"%s\": %s", filename, json_error.text);
     966                 :          0 :                 goto free_parser;
     967                 :            :         }
     968                 :          0 :         ret = cpfl_parser_init(root, parser);
     969         [ #  # ]:          0 :         if (ret < 0) {
     970                 :          0 :                 PMD_DRV_LOG(ERR, "parser init failed.");
     971                 :          0 :                 goto free_parser;
     972                 :            :         }
     973                 :          0 :         *flow_parser = parser;
     974                 :          0 :         json_decref(root);
     975                 :            : 
     976                 :          0 :         return 0;
     977                 :          0 : free_parser:
     978                 :          0 :         rte_free(parser);
     979                 :          0 :         return -EINVAL;
     980                 :            : }
     981                 :            : 
     982                 :            : static void
     983                 :            : cpfl_parser_free_pr_action(struct cpfl_flow_js_pr_action *pr_act)
     984                 :            : {
     985                 :          0 :         if (pr_act->type == CPFL_JS_PR_ACTION_TYPE_SEM)
     986                 :          0 :                 rte_free(pr_act->sem.fv);
     987                 :            : }
     988                 :            : 
     989                 :            : int
     990                 :          0 : cpfl_parser_destroy(struct cpfl_flow_js_parser *parser)
     991                 :            : {
     992                 :            :         int i, j;
     993                 :            : 
     994         [ #  # ]:          0 :         if (!parser)
     995                 :            :                 return 0;
     996                 :            : 
     997         [ #  # ]:          0 :         for (i = 0; i < parser->pr_size; i++) {
     998                 :          0 :                 struct cpfl_flow_js_pr *pattern = &parser->patterns[i];
     999                 :            : 
    1000         [ #  # ]:          0 :                 for (j = 0; j < pattern->key.proto_size; j++)
    1001                 :          0 :                         rte_free(pattern->key.protocols[j].fields);
    1002                 :          0 :                 rte_free(pattern->key.protocols);
    1003                 :          0 :                 rte_free(pattern->key.attributes);
    1004                 :            : 
    1005         [ #  # ]:          0 :                 for (j = 0; j < pattern->actions_size; j++) {
    1006                 :            :                         struct cpfl_flow_js_pr_action *pr_act;
    1007                 :            : 
    1008         [ #  # ]:          0 :                         pr_act = &pattern->actions[j];
    1009                 :            :                         cpfl_parser_free_pr_action(pr_act);
    1010                 :            :                 }
    1011                 :          0 :                 rte_free(pattern->actions);
    1012                 :            :         }
    1013                 :          0 :         rte_free(parser->patterns);
    1014         [ #  # ]:          0 :         for (i = 0; i < parser->mr_size; i++) {
    1015                 :          0 :                 struct cpfl_flow_js_mr *mr = &parser->modifications[i];
    1016                 :            : 
    1017                 :          0 :                 rte_free(mr->key.actions);
    1018                 :            :         }
    1019                 :          0 :         rte_free(parser->modifications);
    1020                 :          0 :         rte_free(parser);
    1021                 :            : 
    1022                 :          0 :         return 0;
    1023                 :            : }
    1024                 :            : 
    1025                 :            : static int
    1026                 :            : cpfl_get_items_length(const struct rte_flow_item *items)
    1027                 :          0 : {
    1028                 :            :         int length = 0;
    1029                 :            :         const struct rte_flow_item *item = items;
    1030                 :            : 
    1031   [ #  #  #  #  :          0 :         while ((item + length++)->type != RTE_FLOW_ITEM_TYPE_END)
             #  #  #  # ]
    1032                 :          0 :                 continue;
    1033                 :            :         return length;
    1034                 :            : }
    1035                 :            : 
    1036                 :            : static int
    1037                 :            : cpfl_get_actions_length(const struct rte_flow_action *actions)
    1038                 :          0 : {
    1039                 :            :         int length = 0;
    1040                 :            :         const struct rte_flow_action *action = actions;
    1041                 :            : 
    1042         [ #  # ]:          0 :         while ((action + length++)->type != RTE_FLOW_ACTION_TYPE_END)
    1043                 :          0 :                 continue;
    1044                 :            :         return length;
    1045                 :            : }
    1046                 :            : 
    1047                 :            : static int
    1048                 :          0 : cpfl_parse_fv_protocol(struct cpfl_flow_js_fv *js_fv, const struct rte_flow_item *items,
    1049                 :            :                        uint16_t offset, uint8_t *fv)
    1050                 :            : {
    1051                 :            :         uint16_t v_layer, v_offset, v_mask;
    1052                 :            :         enum rte_flow_item_type v_header;
    1053                 :            :         int j, layer, length;
    1054                 :            :         uint16_t temp_fv;
    1055                 :            : 
    1056                 :            :         length = cpfl_get_items_length(items);
    1057                 :          0 :         v_layer = js_fv->proto.layer;
    1058                 :          0 :         v_header = js_fv->proto.header;
    1059                 :          0 :         v_offset = js_fv->proto.offset;
    1060                 :          0 :         v_mask = js_fv->proto.mask;
    1061                 :            :         layer = 0;
    1062         [ #  # ]:          0 :         for (j = 0; j < length - 1; j++) {
    1063         [ #  # ]:          0 :                 if (items[j].type == v_header) {
    1064         [ #  # ]:          0 :                         if (layer == v_layer) {
    1065                 :            :                                 /* copy out 16 bits from offset */
    1066                 :            :                                 const uint8_t *pointer;
    1067                 :            : 
    1068                 :          0 :                                 pointer = &(((const uint8_t *)(items[j].spec))[v_offset]);
    1069                 :          0 :                                 temp_fv = ntohs((*((const uint16_t *)pointer)) & v_mask);
    1070                 :          0 :                                 fv[2 * offset] = (uint8_t)(temp_fv >> 8);
    1071                 :          0 :                                 fv[2 * offset + 1] = (uint8_t)(temp_fv & 0x00ff);
    1072                 :          0 :                                 break;
    1073                 :            :                         }
    1074                 :          0 :                         layer++;
    1075                 :            :                 }
    1076                 :            :         }
    1077                 :            : 
    1078                 :          0 :         return 0;
    1079                 :            : }
    1080                 :            : 
    1081                 :            : static int
    1082                 :          0 : cpfl_parse_fieldvectors(struct cpfl_itf *itf, struct cpfl_flow_js_fv *js_fvs, int size,
    1083                 :            :                         uint8_t *fv, const struct rte_flow_item *items)
    1084                 :            : {
    1085                 :            :         int i, ret;
    1086                 :            : 
    1087         [ #  # ]:          0 :         for (i = 0; i < size; i++) {
    1088                 :            :                 uint16_t offset, temp_fv, value_int;
    1089                 :            :                 enum cpfl_flow_js_fv_type type;
    1090                 :            :                 struct cpfl_flow_js_fv *js_fv;
    1091                 :            : 
    1092                 :          0 :                 js_fv = &js_fvs[i];
    1093                 :          0 :                 offset = js_fv->offset;
    1094                 :          0 :                 type = js_fv->type;
    1095         [ #  # ]:          0 :                 if (type == CPFL_FV_TYPE_IMMEDIATE) {
    1096                 :          0 :                         value_int = js_fv->immediate;
    1097                 :          0 :                         temp_fv = (value_int << 8) & 0xff00;
    1098                 :          0 :                         fv[2 * offset] = (uint8_t)(temp_fv >> 8);
    1099                 :          0 :                         fv[2 * offset + 1] = (uint8_t)(temp_fv & 0x00ff);
    1100         [ #  # ]:          0 :                 } else if (type == CPFL_FV_TYPE_METADATA) {
    1101                 :            :                         uint16_t type, v_offset, mask;
    1102                 :            : 
    1103                 :          0 :                         type = js_fv->meta.type;
    1104                 :          0 :                         v_offset = js_fv->meta.offset;
    1105                 :          0 :                         mask = js_fv->meta.mask;
    1106                 :          0 :                         temp_fv = cpfl_metadata_read16(&itf->adapter->meta, type, v_offset) & mask;
    1107                 :          0 :                         fv[2 * offset] = (uint8_t)(temp_fv & 0x00ff);
    1108                 :          0 :                         fv[2 * offset + 1] = (uint8_t)(temp_fv >> 8);
    1109         [ #  # ]:          0 :                 } else if (type == CPFL_FV_TYPE_PROTOCOL) {
    1110                 :          0 :                         ret = cpfl_parse_fv_protocol(js_fv, items, offset, fv);
    1111         [ #  # ]:          0 :                         if (ret)
    1112                 :          0 :                                 return ret;
    1113                 :            :                 } else {
    1114                 :          0 :                         PMD_DRV_LOG(DEBUG, "not support this type: %d.", type);
    1115                 :          0 :                         return -EINVAL;
    1116                 :            :                 }
    1117                 :            :         }
    1118                 :            : 
    1119                 :            :         return 0;
    1120                 :            : }
    1121                 :            : 
    1122                 :            : static int
    1123                 :          0 : cpfl_parse_pr_actions(struct cpfl_itf *itf,
    1124                 :            :                       struct cpfl_flow_js_pr_action *actions,
    1125                 :            :                       int size,
    1126                 :            :                       const struct rte_flow_item *items,
    1127                 :            :                       const struct rte_flow_attr *attr,
    1128                 :            :                       struct cpfl_flow_pr_action *pr_action)
    1129                 :            : {
    1130                 :            :         int i, ret;
    1131                 :            : 
    1132         [ #  # ]:          0 :         for (i = 0; i < size; i++) {
    1133                 :            :                 struct cpfl_flow_js_pr_action *pr_act;
    1134                 :            :                 enum cpfl_flow_pr_action_type type;
    1135                 :            : 
    1136                 :          0 :                 pr_act = &actions[i];
    1137                 :            :                 /* pr->actions->type */
    1138                 :          0 :                 type = pr_act->type;
    1139                 :            :                 /* pr->actions->data */
    1140   [ #  #  #  # ]:          0 :                 if (attr->group == 1  && type == CPFL_JS_PR_ACTION_TYPE_SEM) {
    1141                 :            :                         struct cpfl_flow_js_pr_action_sem *sem = &pr_act->sem;
    1142                 :            : 
    1143                 :          0 :                         pr_action->type = CPFL_JS_PR_ACTION_TYPE_SEM;
    1144                 :          0 :                         pr_action->sem.prof = sem->prof;
    1145                 :          0 :                         pr_action->sem.subprof = sem->subprof;
    1146                 :          0 :                         pr_action->sem.keysize = sem->keysize;
    1147                 :          0 :                         memset(pr_action->sem.cpfl_flow_pr_fv, 0,
    1148                 :            :                                sizeof(pr_action->sem.cpfl_flow_pr_fv));
    1149                 :          0 :                         ret = cpfl_parse_fieldvectors(itf, sem->fv, sem->fv_size,
    1150                 :            :                                                       pr_action->sem.cpfl_flow_pr_fv, items);
    1151                 :          0 :                         return ret;
    1152         [ #  # ]:          0 :                 } else if (attr->group > 4 || attr->group == 0) {
    1153                 :            :                         return -EPERM;
    1154                 :            :                 }
    1155                 :            :         }
    1156                 :            : 
    1157                 :            :         return 0;
    1158                 :            : }
    1159                 :            : 
    1160                 :            : static int
    1161                 :          0 : cpfl_check_eth_mask(const char *mask, struct rte_ether_addr addr)
    1162                 :            : {
    1163                 :            :         int i, ret;
    1164                 :            :         struct rte_ether_addr mask_bytes;
    1165                 :            : 
    1166                 :          0 :         ret = rte_ether_unformat_addr(mask, &mask_bytes);
    1167         [ #  # ]:          0 :         if (ret < 0) {
    1168                 :          0 :                 PMD_DRV_LOG(ERR, "translate mac address from string to rte_ether_addr failed.");
    1169                 :          0 :                 return -EINVAL;
    1170                 :            :         }
    1171                 :            :         /* validate eth mask addr if match */
    1172         [ #  # ]:          0 :         for (i = 0; i < RTE_ETHER_ADDR_LEN; i++) {
    1173         [ #  # ]:          0 :                 if (mask_bytes.addr_bytes[i] != addr.addr_bytes[i])
    1174                 :            :                         return -EINVAL;
    1175                 :            :         }
    1176                 :            : 
    1177                 :            :         return 0;
    1178                 :            : }
    1179                 :            : 
    1180                 :            : static int
    1181                 :            : cpfl_check_ipv4_mask(const char *mask, rte_be32_t addr)
    1182                 :            : {
    1183                 :            :         uint32_t out_addr;
    1184                 :            : 
    1185                 :            :         /* 0: success; -EINVAL: invalid; -ENOTSUP: fail */
    1186                 :          0 :         int ret = inet_pton(AF_INET, mask, &out_addr);
    1187                 :            : 
    1188   [ #  #  #  # ]:          0 :         if (ret < 0)
    1189                 :            :                 return -EINVAL;
    1190                 :            :         /* validate ipv4 mask addr if match */
    1191   [ #  #  #  # ]:          0 :         if (out_addr != addr)
    1192                 :            :                 return -EINVAL;
    1193                 :            : 
    1194                 :            :         return 0;
    1195                 :            : }
    1196                 :            : 
    1197                 :            : static int
    1198                 :          0 : cpfl_check_eth(struct cpfl_flow_js_pr_key_proto *proto, const struct rte_flow_item_eth *eth_mask)
    1199                 :            : {
    1200                 :            :         int field_size, j;
    1201                 :            :         int flag_dst_addr, flag_src_addr, flag_ether_type;
    1202                 :            :         struct cpfl_flow_js_pr_key_proto_field *field;
    1203                 :            : 
    1204         [ #  # ]:          0 :         if (!proto)
    1205                 :            :                 return 0;
    1206                 :          0 :         field_size = proto->fields_size;
    1207         [ #  # ]:          0 :         if (field_size != 0 && !eth_mask)
    1208                 :            :                 return -EINVAL;
    1209                 :            : 
    1210         [ #  # ]:          0 :         if (field_size == 0 && eth_mask)
    1211                 :            :                 return -EINVAL;
    1212                 :            : 
    1213         [ #  # ]:          0 :         if (field_size == 0 && !eth_mask)
    1214                 :            :                 return 0;
    1215                 :            : 
    1216                 :            :         flag_dst_addr = false;
    1217                 :            :         flag_src_addr = false;
    1218                 :            :         flag_ether_type = false;
    1219         [ #  # ]:          0 :         for (j = 0; j < field_size; j++) {
    1220                 :            :                 const char *name, *s_mask;
    1221                 :            : 
    1222                 :          0 :                 field = &proto->fields[j];
    1223                 :            :                 /* match: rte_flow_item_eth.dst, more see Field Mapping
    1224                 :            :                  */
    1225                 :          0 :                 name = field->name;
    1226                 :            :                 /* match: rte_flow_item->mask */
    1227         [ #  # ]:          0 :                 if (strcmp(name, "src_addr") == 0) {
    1228                 :          0 :                         s_mask = field->mask;
    1229         [ #  # ]:          0 :                         if (cpfl_check_eth_mask(s_mask, eth_mask->src) < 0)
    1230                 :            :                                 return -EINVAL;
    1231                 :            :                         flag_src_addr = true;
    1232         [ #  # ]:          0 :                 } else if (strcmp(name, "dst_addr") == 0) {
    1233                 :          0 :                         s_mask = field->mask;
    1234         [ #  # ]:          0 :                         if (cpfl_check_eth_mask(s_mask, eth_mask->dst) < 0)
    1235                 :            :                                 return -EINVAL;
    1236                 :            :                         flag_dst_addr = true;
    1237         [ #  # ]:          0 :                 } else if (strcmp(name, "ether_type") == 0) {
    1238                 :          0 :                         uint16_t mask = (uint16_t)field->mask_32b;
    1239                 :            : 
    1240         [ #  # ]:          0 :                         if (mask != eth_mask->type)
    1241                 :            :                                 return -EINVAL;
    1242                 :            :                         flag_ether_type = true;
    1243                 :            :                 } else {
    1244                 :            :                         /* TODO: more type... */
    1245                 :          0 :                         PMD_DRV_LOG(ERR, "not support this name.");
    1246                 :          0 :                         return -EINVAL;
    1247                 :            :                 }
    1248                 :            :         }
    1249         [ #  # ]:          0 :         if (!flag_src_addr) {
    1250         [ #  # ]:          0 :                 if (strcmp((const char *)eth_mask->src.addr_bytes, "\x00\x00\x00\x00\x00\x00") != 0)
    1251                 :            :                         return -EINVAL;
    1252                 :            :         }
    1253         [ #  # ]:          0 :         if (!flag_dst_addr) {
    1254         [ #  # ]:          0 :                 if (strcmp((const char *)eth_mask->dst.addr_bytes, "\x00\x00\x00\x00\x00\x00") != 0)
    1255                 :            :                         return -EINVAL;
    1256                 :            :         }
    1257         [ #  # ]:          0 :         if (!flag_ether_type) {
    1258         [ #  # ]:          0 :                 if (eth_mask->hdr.ether_type != (rte_be16_t)0)
    1259                 :          0 :                         return -EINVAL;
    1260                 :            :         }
    1261                 :            : 
    1262                 :            :         return 0;
    1263                 :            : }
    1264                 :            : 
    1265                 :            : static int
    1266                 :          0 : cpfl_check_ipv4(struct cpfl_flow_js_pr_key_proto *proto, const struct rte_flow_item_ipv4 *ipv4_mask)
    1267                 :            : {
    1268                 :            :         int field_size, j;
    1269                 :            :         int flag_next_proto_id, flag_src_addr, flag_dst_addr;
    1270                 :            :         struct cpfl_flow_js_pr_key_proto_field *field;
    1271                 :            : 
    1272         [ #  # ]:          0 :         if (!proto)
    1273                 :            :                 return 0;
    1274                 :            : 
    1275                 :          0 :         field_size = proto->fields_size;
    1276         [ #  # ]:          0 :         if (field_size != 0 && !ipv4_mask)
    1277                 :            :                 return -EINVAL;
    1278                 :            : 
    1279         [ #  # ]:          0 :         if (field_size == 0 && ipv4_mask)
    1280                 :            :                 return -EINVAL;
    1281                 :            : 
    1282         [ #  # ]:          0 :         if (field_size == 0 && !ipv4_mask)
    1283                 :            :                 return 0;
    1284                 :            : 
    1285                 :            :         flag_dst_addr = false;
    1286                 :            :         flag_src_addr = false;
    1287                 :            :         flag_next_proto_id = false;
    1288         [ #  # ]:          0 :         for (j = 0; j < field_size; j++) {
    1289                 :            :                 const char *name;
    1290                 :            : 
    1291                 :          0 :                 field = &proto->fields[j];
    1292                 :          0 :                 name = field->name;
    1293         [ #  # ]:          0 :                 if (strcmp(name, "src_addr") == 0) {
    1294                 :            :                         const char *mask;
    1295                 :            : 
    1296                 :          0 :                         mask = field->mask;
    1297                 :          0 :                         if (cpfl_check_ipv4_mask(mask, ipv4_mask->hdr.src_addr) < 0)
    1298                 :          0 :                                 return -EINVAL;
    1299                 :            :                         flag_src_addr = true;
    1300         [ #  # ]:          0 :                 } else if (strcmp(name, "dst_addr") == 0) {
    1301                 :            :                         const char *mask;
    1302                 :            : 
    1303                 :          0 :                         mask = field->mask;
    1304                 :          0 :                         if (cpfl_check_ipv4_mask(mask, ipv4_mask->hdr.dst_addr) < 0)
    1305                 :          0 :                                 return -EINVAL;
    1306                 :            :                         flag_dst_addr = true;
    1307         [ #  # ]:          0 :                 } else if (strcmp(name, "next_proto_id") == 0) {
    1308                 :            :                         uint8_t mask;
    1309                 :            : 
    1310                 :          0 :                         mask = (uint8_t)field->mask_32b;
    1311         [ #  # ]:          0 :                         if (mask != ipv4_mask->hdr.next_proto_id)
    1312                 :            :                                 return -EINVAL;
    1313                 :            :                         flag_next_proto_id = true;
    1314                 :            :                 } else {
    1315                 :          0 :                         PMD_DRV_LOG(ERR, "not support this name.");
    1316                 :          0 :                         return -EINVAL;
    1317                 :            :                 }
    1318                 :            :         }
    1319         [ #  # ]:          0 :         if (!flag_src_addr) {
    1320         [ #  # ]:          0 :                 if (ipv4_mask->hdr.src_addr != (rte_be32_t)0)
    1321                 :            :                         return -EINVAL;
    1322                 :            :         }
    1323         [ #  # ]:          0 :         if (!flag_dst_addr) {
    1324         [ #  # ]:          0 :                 if (ipv4_mask->hdr.dst_addr != (rte_be32_t)0)
    1325                 :            :                         return -EINVAL;
    1326                 :            :         }
    1327         [ #  # ]:          0 :         if (!flag_next_proto_id) {
    1328         [ #  # ]:          0 :                 if (ipv4_mask->hdr.next_proto_id != (uint8_t)0)
    1329                 :          0 :                         return -EINVAL;
    1330                 :            :         }
    1331                 :            : 
    1332                 :            :         return 0;
    1333                 :            : }
    1334                 :            : 
    1335                 :            : static int
    1336                 :          0 : cpfl_check_tcp(struct cpfl_flow_js_pr_key_proto *proto, const struct rte_flow_item_tcp *tcp_mask)
    1337                 :            : {
    1338                 :            :         int field_size, j;
    1339                 :            :         int flag_src_port, flag_dst_port;
    1340                 :            :         struct cpfl_flow_js_pr_key_proto_field *field;
    1341                 :            : 
    1342         [ #  # ]:          0 :         if (!proto)
    1343                 :            :                 return 0;
    1344                 :            : 
    1345                 :          0 :         field_size = proto->fields_size;
    1346         [ #  # ]:          0 :         if (field_size != 0 && !tcp_mask)
    1347                 :            :                 return -EINVAL;
    1348                 :            : 
    1349         [ #  # ]:          0 :         if (field_size == 0 && tcp_mask)
    1350                 :            :                 return -EINVAL;
    1351                 :            : 
    1352         [ #  # ]:          0 :         if (field_size == 0 && !tcp_mask)
    1353                 :            :                 return 0;
    1354                 :            : 
    1355                 :            :         flag_src_port = false;
    1356                 :            :         flag_dst_port = false;
    1357         [ #  # ]:          0 :         for (j = 0; j < field_size; j++) {
    1358                 :            :                 const char *name;
    1359                 :            :                 uint16_t mask;
    1360                 :            : 
    1361                 :          0 :                 field = &proto->fields[j];
    1362                 :          0 :                 name = field->name;
    1363                 :          0 :                 mask = (uint16_t)field->mask_32b;
    1364         [ #  # ]:          0 :                 if (strcmp(name, "src_port") == 0) {
    1365         [ #  # ]:          0 :                         if (tcp_mask->hdr.src_port != mask)
    1366                 :            :                                 return -EINVAL;
    1367                 :            :                         flag_src_port = true;
    1368         [ #  # ]:          0 :                 } else if (strcmp(name, "dst_port") == 0) {
    1369         [ #  # ]:          0 :                         if (tcp_mask->hdr.dst_port != mask)
    1370                 :            :                                 return -EINVAL;
    1371                 :            :                         flag_dst_port = true;
    1372                 :            :                 } else {
    1373                 :          0 :                         PMD_DRV_LOG(ERR, "not support this name.");
    1374                 :          0 :                         return -EINVAL;
    1375                 :            :                 }
    1376                 :            :         }
    1377         [ #  # ]:          0 :         if (!flag_src_port) {
    1378         [ #  # ]:          0 :                 if (tcp_mask->hdr.src_port != (rte_be16_t)0)
    1379                 :            :                         return -EINVAL;
    1380                 :            :         }
    1381         [ #  # ]:          0 :         if (!flag_dst_port) {
    1382         [ #  # ]:          0 :                 if (tcp_mask->hdr.dst_port != (rte_be16_t)0)
    1383                 :          0 :                         return -EINVAL;
    1384                 :            :         }
    1385                 :            : 
    1386                 :            :         return 0;
    1387                 :            : }
    1388                 :            : 
    1389                 :            : static int
    1390                 :          0 : cpfl_check_udp(struct cpfl_flow_js_pr_key_proto *proto, const struct rte_flow_item_udp *udp_mask)
    1391                 :            : {
    1392                 :            :         int field_size, j;
    1393                 :            :         bool flag_src_port, flag_dst_port;
    1394                 :            :         struct cpfl_flow_js_pr_key_proto_field *field;
    1395                 :            : 
    1396         [ #  # ]:          0 :         if (!proto)
    1397                 :            :                 return 0;
    1398                 :          0 :         field_size = proto->fields_size;
    1399         [ #  # ]:          0 :         if (field_size != 0 && !udp_mask)
    1400                 :            :                 return -EINVAL;
    1401         [ #  # ]:          0 :         if (field_size == 0 && udp_mask)
    1402                 :            :                 return -EINVAL;
    1403         [ #  # ]:          0 :         if (field_size == 0 && !udp_mask)
    1404                 :            :                 return 0;
    1405                 :            :         flag_src_port = false;
    1406                 :            :         flag_dst_port = false;
    1407         [ #  # ]:          0 :         for (j = 0; j < field_size; j++) {
    1408                 :            :                 const char *name;
    1409                 :            :                 uint16_t mask;
    1410                 :            : 
    1411                 :          0 :                 field = &proto->fields[j];
    1412                 :            :                 /* match: rte_flow_item_eth.dst */
    1413                 :          0 :                 name = field->name; /* match: rte_flow_item->mask */
    1414                 :          0 :                 mask = (uint16_t)field->mask_32b;
    1415         [ #  # ]:          0 :                 if (strcmp(name, "src_port") == 0) {
    1416         [ #  # ]:          0 :                         if (udp_mask->hdr.src_port != mask)
    1417                 :            :                                 return -EINVAL;
    1418                 :            :                         flag_src_port = true;
    1419         [ #  # ]:          0 :                 } else if (strcmp(name, "dst_port") == 0) {
    1420         [ #  # ]:          0 :                         if (udp_mask->hdr.dst_port != mask)
    1421                 :            :                                 return -EINVAL;
    1422                 :            :                         flag_dst_port = true;
    1423                 :            :                 } else {
    1424                 :          0 :                         PMD_DRV_LOG(ERR, "not support this name: %s.", name);
    1425                 :          0 :                         return -EINVAL;
    1426                 :            :                 }
    1427                 :            :         }
    1428         [ #  # ]:          0 :         if (!flag_src_port) {
    1429         [ #  # ]:          0 :                 if (udp_mask->hdr.src_port != (rte_be16_t)0)
    1430                 :            :                         return -EINVAL;
    1431                 :            :         }
    1432         [ #  # ]:          0 :         if (!flag_dst_port) {
    1433         [ #  # ]:          0 :                 if (udp_mask->hdr.dst_port != (rte_be16_t)0)
    1434                 :          0 :                         return -EINVAL;
    1435                 :            :         }
    1436                 :            : 
    1437                 :            :         return 0;
    1438                 :            : }
    1439                 :            : 
    1440                 :            : static int
    1441                 :          0 : cpfl_check_vxlan(struct cpfl_flow_js_pr_key_proto *proto,
    1442                 :            :                  const struct rte_flow_item_vxlan *vxlan_mask)
    1443                 :            : {
    1444                 :            :         int field_size, j;
    1445                 :            :         struct cpfl_flow_js_pr_key_proto_field *field;
    1446                 :            : 
    1447         [ #  # ]:          0 :         if (!proto)
    1448                 :            :                 return 0;
    1449                 :          0 :         field_size = proto->fields_size;
    1450         [ #  # ]:          0 :         if (field_size != 0 && !vxlan_mask)
    1451                 :            :                 return -EINVAL;
    1452         [ #  # ]:          0 :         if (field_size == 0 && vxlan_mask)
    1453                 :            :                 return -EINVAL;
    1454         [ #  # ]:          0 :         if (field_size == 0 && !vxlan_mask)
    1455                 :            :                 return 0;
    1456         [ #  # ]:          0 :         for (j = 0; j < field_size; j++) {
    1457                 :            :                 const char *name;
    1458                 :            :                 int64_t mask;
    1459                 :            : 
    1460                 :          0 :                 field = &proto->fields[j];
    1461                 :          0 :                 name = field->name;
    1462                 :            :                 /* match: rte_flow_item->mask */
    1463                 :          0 :                 mask = (int64_t)field->mask_32b;
    1464         [ #  # ]:          0 :                 if (strcmp(name, "vx_vni") == 0) {
    1465         [ #  # ]:          0 :                         if ((int64_t)RTE_BE32(vxlan_mask->hdr.vx_vni) != mask)
    1466                 :            :                                 return -EINVAL;
    1467                 :            :                 } else {
    1468                 :          0 :                         PMD_DRV_LOG(ERR, "not support this name.");
    1469                 :          0 :                         return -EINVAL;
    1470                 :            :                 }
    1471                 :            :         }
    1472                 :            : 
    1473                 :            :         return 0;
    1474                 :            : }
    1475                 :            : 
    1476                 :            : static int
    1477                 :            : cpfl_check_icmp(struct cpfl_flow_js_pr_key_proto *proto, const struct rte_flow_item_icmp *icmp_mask)
    1478                 :            : {
    1479                 :            :         int field_size;
    1480                 :            : 
    1481                 :            :         if (!proto)
    1482                 :            :                 return 0;
    1483                 :          0 :         field_size = proto->fields_size;
    1484                 :          0 :         if ((field_size != 0 && !icmp_mask) || (field_size == 0 && icmp_mask))
    1485                 :            :                 return -EINVAL;
    1486                 :            : 
    1487                 :            :         return 0;
    1488                 :            : }
    1489                 :            : 
    1490                 :            : static int
    1491                 :          0 : cpfl_check_pattern_key_proto(struct cpfl_flow_js_pr_key_proto *protocols,
    1492                 :            :                              int proto_size,
    1493                 :            :                              const struct rte_flow_item *items)
    1494                 :            : {
    1495                 :            :         int i, length;
    1496                 :            :         int j = 0;
    1497                 :            : 
    1498                 :            :         length = cpfl_get_items_length(items);
    1499         [ #  # ]:          0 :         if (proto_size > length - 1)
    1500                 :            :                 return -EINVAL;
    1501         [ #  # ]:          0 :         for (i = 0; i < proto_size; i++) {
    1502                 :            :                 struct cpfl_flow_js_pr_key_proto *key_proto;
    1503                 :            :                 enum rte_flow_item_type type;
    1504                 :            : 
    1505                 :          0 :                 key_proto = &protocols[i];
    1506                 :            :                 /* pr->key->proto->type */
    1507                 :          0 :                 type = key_proto->type;
    1508                 :            :                 /* pr->key->proto->fields */
    1509   [ #  #  #  #  :          0 :                 switch (type) {
                #  #  # ]
    1510                 :          0 :                 case RTE_FLOW_ITEM_TYPE_ETH:
    1511         [ #  # ]:          0 :                         if (items[j++].type == RTE_FLOW_ITEM_TYPE_ETH) {
    1512                 :            :                                 const struct rte_flow_item_eth *eth_mask;
    1513                 :            :                                 int ret;
    1514                 :            : 
    1515                 :          0 :                                 eth_mask = (const struct rte_flow_item_eth *)items[i].mask;
    1516                 :          0 :                                 ret = cpfl_check_eth(key_proto, eth_mask);
    1517         [ #  # ]:          0 :                                 if (ret < 0)
    1518                 :          0 :                                         return ret;
    1519                 :            :                         } else {
    1520                 :            :                                 return -EINVAL;
    1521                 :            :                         }
    1522                 :            :                         break;
    1523                 :          0 :                 case RTE_FLOW_ITEM_TYPE_IPV4:
    1524         [ #  # ]:          0 :                         if (items[j++].type == RTE_FLOW_ITEM_TYPE_IPV4) {
    1525                 :            :                                 const struct rte_flow_item_ipv4 *ipv4_mask;
    1526                 :            :                                 int ret;
    1527                 :            : 
    1528                 :          0 :                                 ipv4_mask = (const struct rte_flow_item_ipv4 *)items[i].mask;
    1529                 :          0 :                                 ret = cpfl_check_ipv4(key_proto, ipv4_mask);
    1530         [ #  # ]:          0 :                                 if (ret < 0)
    1531                 :          0 :                                         return ret;
    1532                 :            :                         } else {
    1533                 :            :                                 return -EINVAL;
    1534                 :            :                         }
    1535                 :            :                         break;
    1536                 :          0 :                 case RTE_FLOW_ITEM_TYPE_TCP:
    1537         [ #  # ]:          0 :                         if (items[j++].type == RTE_FLOW_ITEM_TYPE_TCP) {
    1538                 :            :                                 const struct rte_flow_item_tcp *tcp_mask;
    1539                 :            :                                 int ret;
    1540                 :            : 
    1541                 :          0 :                                 tcp_mask = (const struct rte_flow_item_tcp *)items[i].mask;
    1542                 :          0 :                                 ret = cpfl_check_tcp(key_proto, tcp_mask);
    1543         [ #  # ]:          0 :                                 if (ret < 0)
    1544                 :          0 :                                         return ret;
    1545                 :            :                         } else {
    1546                 :            :                                 return -EINVAL;
    1547                 :            :                         }
    1548                 :            :                         break;
    1549                 :          0 :                 case RTE_FLOW_ITEM_TYPE_UDP:
    1550         [ #  # ]:          0 :                         if (items[j++].type == RTE_FLOW_ITEM_TYPE_UDP) {
    1551                 :            :                                 const struct rte_flow_item_udp *udp_mask;
    1552                 :            :                                 int ret;
    1553                 :            : 
    1554                 :          0 :                                 udp_mask = (const struct rte_flow_item_udp *)items[i].mask;
    1555                 :          0 :                                 ret = cpfl_check_udp(key_proto, udp_mask);
    1556         [ #  # ]:          0 :                                 if (ret < 0)
    1557                 :          0 :                                         return ret;
    1558                 :            :                         } else {
    1559                 :            :                                 return -EINVAL;
    1560                 :            :                         }
    1561                 :            :                         break;
    1562                 :          0 :                 case RTE_FLOW_ITEM_TYPE_VXLAN:
    1563         [ #  # ]:          0 :                         if (items[j++].type == RTE_FLOW_ITEM_TYPE_VXLAN) {
    1564                 :            :                                 const struct rte_flow_item_vxlan *vxlan_mask;
    1565                 :            :                                 int ret;
    1566                 :            : 
    1567                 :          0 :                                 vxlan_mask = (const struct rte_flow_item_vxlan *)items[i].mask;
    1568                 :          0 :                                 ret = cpfl_check_vxlan(key_proto, vxlan_mask);
    1569         [ #  # ]:          0 :                                 if (ret < 0)
    1570                 :          0 :                                         return ret;
    1571                 :            :                         } else {
    1572                 :            :                                 return -EINVAL;
    1573                 :            :                         }
    1574                 :            :                         break;
    1575                 :          0 :                 case RTE_FLOW_ITEM_TYPE_ICMP:
    1576         [ #  # ]:          0 :                         if (items[j++].type == RTE_FLOW_ITEM_TYPE_ICMP) {
    1577                 :            :                                 const struct rte_flow_item_icmp *icmp_mask;
    1578                 :            :                                 int ret;
    1579                 :            : 
    1580         [ #  # ]:          0 :                                 icmp_mask = (const struct rte_flow_item_icmp *)items[i].mask;
    1581                 :            :                                 ret = cpfl_check_icmp(key_proto, icmp_mask);
    1582                 :            :                                 if (ret < 0)
    1583                 :            :                                         return ret;
    1584                 :            :                         } else {
    1585                 :            :                                 return -EINVAL;
    1586                 :            :                         }
    1587                 :            :                         break;
    1588                 :          0 :                 default:
    1589                 :          0 :                         PMD_DRV_LOG(ERR, "Not support this type: %d.", type);
    1590                 :          0 :                         return -EPERM;
    1591                 :            :                 }
    1592                 :            :         }
    1593         [ #  # ]:          0 :         if (items[j].type != RTE_FLOW_ITEM_TYPE_END)
    1594                 :          0 :                 return -EINVAL;
    1595                 :            : 
    1596                 :            :         return 0;
    1597                 :            : }
    1598                 :            : 
    1599                 :            : static int
    1600                 :          0 : cpfl_check_pattern_key_attr(struct cpfl_flow_js_pr_key_attr *key_attr,
    1601                 :            :                             const struct rte_flow_attr *attr)
    1602                 :            : {
    1603         [ #  # ]:          0 :         if (key_attr->ingress != attr->ingress) {
    1604                 :          0 :                 PMD_DRV_LOG(DEBUG, "ingress not match.");
    1605                 :          0 :                 return -EINVAL;
    1606                 :            :         }
    1607         [ #  # ]:          0 :         if (key_attr->egress != attr->egress) {
    1608                 :          0 :                 PMD_DRV_LOG(DEBUG, "egress not match.");
    1609                 :          0 :                 return -EINVAL;
    1610                 :            :         }
    1611                 :            : 
    1612                 :            :         return 0;
    1613                 :            : }
    1614                 :            : 
    1615                 :            : static int
    1616                 :          0 : cpfl_check_pattern_key(struct cpfl_flow_js_pr *pattern,
    1617                 :            :                        const struct rte_flow_item *items,
    1618                 :            :                        const struct rte_flow_attr *attr)
    1619                 :            : {
    1620                 :            :         int ret;
    1621                 :            : 
    1622                 :            :         /* pr->key */
    1623                 :            :         /* pr->key->protocols */
    1624                 :          0 :         ret = cpfl_check_pattern_key_proto(pattern->key.protocols,
    1625                 :          0 :                                            pattern->key.proto_size, items);
    1626         [ #  # ]:          0 :         if (ret < 0)
    1627                 :            :                 return -EINVAL;
    1628                 :            :         /* pr->key->attributes */
    1629                 :          0 :         ret = cpfl_check_pattern_key_attr(pattern->key.attributes, attr);
    1630         [ #  # ]:          0 :         if (ret < 0)
    1631                 :          0 :                 return -EINVAL;
    1632                 :            : 
    1633                 :            :         return 0;
    1634                 :            : }
    1635                 :            : 
    1636                 :            : /* output: struct cpfl_flow_pr_action* pr_action */
    1637                 :            : int
    1638                 :          0 : cpfl_flow_parse_items(struct cpfl_itf *itf,
    1639                 :            :                       struct cpfl_flow_js_parser *parser,
    1640                 :            :                       const struct rte_flow_item *items,
    1641                 :            :                       const struct rte_flow_attr *attr,
    1642                 :            :                       struct cpfl_flow_pr_action *pr_action)
    1643                 :            : {
    1644                 :            :         int i, size;
    1645                 :            :         struct cpfl_flow_js_pr *pattern;
    1646                 :            : 
    1647                 :          0 :         size = parser->pr_size;
    1648         [ #  # ]:          0 :         for (i = 0; i < size; i++) {
    1649                 :            :                 int ret;
    1650                 :            : 
    1651                 :          0 :                 pattern = &parser->patterns[i];
    1652                 :          0 :                 ret = cpfl_check_pattern_key(pattern, items, attr);
    1653         [ #  # ]:          0 :                 if (ret < 0)
    1654                 :            :                         continue;
    1655                 :            :                 /* pr->actions */
    1656                 :          0 :                 ret = cpfl_parse_pr_actions(itf, pattern->actions, pattern->actions_size,
    1657                 :            :                                             items, attr, pr_action);
    1658                 :          0 :                 return ret;
    1659                 :            :         }
    1660                 :            : 
    1661                 :            :         return -EINVAL;
    1662                 :            : }
    1663                 :            : 
    1664                 :            : /* modifications rules */
    1665                 :            : static int
    1666                 :          0 : cpfl_check_actions_vxlan_encap(struct cpfl_flow_mr_key_action_vxlan_encap *encap,
    1667                 :            :                                const struct rte_flow_action *action)
    1668                 :            : {
    1669                 :            :         const struct rte_flow_action_vxlan_encap *action_vxlan_encap;
    1670                 :            :         struct rte_flow_item *definition;
    1671                 :            :         int def_length, i, proto_size;
    1672                 :            : 
    1673                 :          0 :         action_vxlan_encap = (const struct rte_flow_action_vxlan_encap *)action->conf;
    1674                 :          0 :         definition = action_vxlan_encap->definition;
    1675                 :            :         def_length = cpfl_get_items_length(definition);
    1676                 :          0 :         proto_size = encap->proto_size;
    1677         [ #  # ]:          0 :         if (proto_size != def_length - 1) {
    1678                 :          0 :                 PMD_DRV_LOG(DEBUG, "protocols not match.");
    1679                 :          0 :                 return -EINVAL;
    1680                 :            :         }
    1681         [ #  # ]:          0 :         for (i = 0; i < proto_size; i++) {
    1682                 :            :                 enum rte_flow_item_type proto;
    1683                 :            : 
    1684                 :          0 :                 proto = encap->protocols[i];
    1685         [ #  # ]:          0 :                 if (proto == RTE_FLOW_ITEM_TYPE_VLAN) {
    1686         [ #  # ]:          0 :                         if (definition[i].type != RTE_FLOW_ITEM_TYPE_VOID) {
    1687                 :          0 :                                 PMD_DRV_LOG(DEBUG, "protocols not match.");
    1688                 :          0 :                                 return -EINVAL;
    1689                 :            :                         }
    1690         [ #  # ]:          0 :                 } else if (proto != definition[i].type) {
    1691                 :          0 :                         PMD_DRV_LOG(DEBUG, "protocols not match.");
    1692                 :          0 :                         return -EINVAL;
    1693                 :            :                 }
    1694                 :            :         }
    1695                 :            : 
    1696                 :            :         return 0;
    1697                 :            : }
    1698                 :            : 
    1699                 :            : static int
    1700                 :          0 : cpfl_parse_check_prog_action(struct cpfl_flow_js_mr_key_action *key_act,
    1701                 :            :                              struct cpfl_flow_mr_key_action_prog *mr_key_prog,
    1702                 :            :                              const struct rte_flow_action_prog *prog)
    1703                 :            : {
    1704                 :            :         uint32_t k;
    1705                 :            :         bool check_name;
    1706                 :            : 
    1707                 :          0 :         check_name = key_act->prog.has_name ? strcmp(prog->name, key_act->prog.name) == 0
    1708         [ #  # ]:          0 :                                             : (uint32_t)atol(prog->name) == key_act->prog.id;
    1709         [ #  # ]:          0 :         if (!check_name) {
    1710                 :          0 :                 PMD_DRV_LOG(ERR, "Not support this prog type: %s.", prog->name);
    1711                 :          0 :                 return -EINVAL;
    1712                 :            :         }
    1713         [ #  # ]:          0 :         if (key_act->prog.param_size != prog->args_num)
    1714                 :            :                 return -EINVAL;
    1715         [ #  # ]:          0 :         for (k = 0; k < key_act->prog.param_size; k++) {
    1716                 :          0 :                 const struct rte_flow_action_prog_argument *arg = &prog->args[k];
    1717                 :            :                 struct cpfl_flow_js_prog_parameter *param = &key_act->prog.params[k];
    1718                 :            : 
    1719                 :          0 :                 check_name = param->has_name ? strcmp(arg->name, param->name) == 0
    1720         [ #  # ]:          0 :                                              : atoi(arg->name) == param->index;
    1721   [ #  #  #  # ]:          0 :                 if (!check_name || arg->size != param->size)
    1722                 :            :                         return -EINVAL;
    1723         [ #  # ]:          0 :                 if (param->has_name) {
    1724                 :          0 :                         mr_key_prog->has_name = TRUE;
    1725                 :          0 :                         strncpy(mr_key_prog->name[param->index], param->name,
    1726                 :            :                                 CPFL_JS_STR_SIZE - 1);
    1727                 :            :                 }
    1728                 :            :         }
    1729                 :            : 
    1730                 :            :         return 0;
    1731                 :            : }
    1732                 :            : 
    1733                 :            : /* check and parse */
    1734                 :            : static int
    1735                 :          0 : cpfl_parse_mr_key_action(struct cpfl_flow_js_mr_key_action *key_acts, int size,
    1736                 :            :                          const struct rte_flow_action *actions,
    1737                 :            :                          struct cpfl_flow_mr_key_action *mr_key_action)
    1738                 :            : {
    1739                 :            :         int actions_length, i;
    1740                 :            :         int j = 0;
    1741                 :            :         int ret;
    1742                 :            : 
    1743                 :            :         actions_length = cpfl_get_actions_length(actions);
    1744         [ #  # ]:          0 :         if (size > actions_length - 1)
    1745                 :            :                 return -EINVAL;
    1746         [ #  # ]:          0 :         for (i = 0; i < size; i++) {
    1747                 :            :                 enum rte_flow_action_type type;
    1748                 :            :                 struct cpfl_flow_js_mr_key_action *key_act;
    1749                 :            : 
    1750                 :          0 :                 key_act = &key_acts[i];
    1751                 :            :                 /* mr->key->actions->type */
    1752                 :          0 :                 type = key_act->type;
    1753                 :            :                 /* mr->key->actions->data */
    1754         [ #  # ]:          0 :                 if (type == RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP) {
    1755                 :            :                         int proto_size, k;
    1756                 :            :                         struct cpfl_flow_mr_key_action_vxlan_encap *encap;
    1757                 :            : 
    1758         [ #  # ]:          0 :                         while (j < actions_length &&
    1759         [ #  # ]:          0 :                                actions[j].type != RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP) {
    1760                 :          0 :                                 j++;
    1761                 :            :                         }
    1762         [ #  # ]:          0 :                         if (j >= actions_length)
    1763                 :            :                                 return -EINVAL;
    1764                 :          0 :                         mr_key_action->mods[i].type = RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP;
    1765                 :          0 :                         mr_key_action->mods[i].encap.action = &actions[j];
    1766                 :          0 :                         encap = &mr_key_action->mods[i].encap;
    1767                 :            : 
    1768                 :          0 :                         proto_size = key_act->encap.proto_size;
    1769                 :          0 :                         encap->proto_size = proto_size;
    1770         [ #  # ]:          0 :                         for (k = 0; k < proto_size; k++) {
    1771                 :            :                                 enum rte_flow_item_type proto;
    1772                 :            : 
    1773                 :          0 :                                 proto = key_act->encap.protocols[k];
    1774                 :          0 :                                 encap->protocols[k] = proto;
    1775                 :            :                         }
    1776                 :          0 :                         ret = cpfl_check_actions_vxlan_encap(encap, &actions[j]);
    1777         [ #  # ]:          0 :                         if (ret < 0)
    1778                 :            :                                 return -EINVAL;
    1779                 :          0 :                         j++;
    1780         [ #  # ]:          0 :                 } else if (type == RTE_FLOW_ACTION_TYPE_VXLAN_DECAP) {
    1781         [ #  # ]:          0 :                         while (j < actions_length &&
    1782         [ #  # ]:          0 :                                actions[j].type != RTE_FLOW_ACTION_TYPE_VXLAN_DECAP) {
    1783                 :          0 :                                 j++;
    1784                 :            :                         }
    1785         [ #  # ]:          0 :                         if (j >= actions_length)
    1786                 :            :                                 return -EINVAL;
    1787                 :          0 :                         mr_key_action->mods[i].type = RTE_FLOW_ACTION_TYPE_VXLAN_DECAP;
    1788                 :          0 :                         j++;
    1789         [ #  # ]:          0 :                 } else if (type == RTE_FLOW_ACTION_TYPE_PROG) {
    1790                 :            :                         const struct rte_flow_action_prog *prog;
    1791                 :            : 
    1792         [ #  # ]:          0 :                         while (j < actions_length &&
    1793         [ #  # ]:          0 :                                actions[j].type != RTE_FLOW_ACTION_TYPE_PROG) {
    1794                 :          0 :                                 j++;
    1795                 :            :                         }
    1796         [ #  # ]:          0 :                         if (j >= actions_length)
    1797                 :            :                                 return -EINVAL;
    1798                 :          0 :                         prog = actions[j].conf;
    1799                 :          0 :                         mr_key_action->prog.prog = prog;
    1800                 :          0 :                         ret = cpfl_parse_check_prog_action(key_act, &mr_key_action->prog, prog);
    1801         [ #  # ]:          0 :                         if (ret < 0)
    1802                 :            :                                 return -EINVAL;
    1803                 :            :                 } else {
    1804                 :          0 :                         PMD_DRV_LOG(ERR, "Not support this type: %d.", type);
    1805                 :          0 :                         return -EPERM;
    1806                 :            :                 }
    1807                 :            :         }
    1808                 :            : 
    1809                 :            :         return 0;
    1810                 :            : }
    1811                 :            : 
    1812                 :            : /* output: uint8_t *buffer, uint16_t *byte_len */
    1813                 :            : static int
    1814                 :          0 : cpfl_parse_layout(struct cpfl_flow_js_mr_layout *layouts, int layout_size,
    1815                 :            :                   struct cpfl_flow_mr_key_mod *mods,
    1816                 :            :                   uint8_t *buffer, uint16_t *byte_len)
    1817                 :            : {
    1818                 :            :         int i;
    1819                 :            :         int start = 0;
    1820                 :            : 
    1821         [ #  # ]:          0 :         for (i = 0; i < layout_size; i++) {
    1822                 :            :                 int index, size, offset;
    1823                 :            :                 const char *hint;
    1824                 :            :                 const uint8_t *addr = NULL;
    1825                 :            :                 struct cpfl_flow_mr_key_mod *temp;
    1826                 :            :                 struct cpfl_flow_js_mr_layout *layout;
    1827                 :            : 
    1828                 :          0 :                 layout = &layouts[i];
    1829                 :            :                 /* index links to the element of the actions array. */
    1830                 :          0 :                 index = layout->index;
    1831                 :          0 :                 size = layout->size;
    1832                 :          0 :                 offset = layout->offset;
    1833         [ #  # ]:          0 :                 if (index == -1) {
    1834                 :            :                         hint = "dummpy";
    1835                 :          0 :                         start += size;
    1836                 :          0 :                         continue;
    1837                 :            :                 }
    1838                 :          0 :                 hint = layout->hint;
    1839                 :          0 :                 temp = mods + index;
    1840         [ #  # ]:          0 :                 if (temp->type == RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP) {
    1841                 :            :                         const struct rte_flow_action_vxlan_encap *action_vxlan_encap;
    1842                 :            :                         struct rte_flow_item *definition;
    1843                 :            :                         int def_length, k;
    1844                 :            : 
    1845                 :          0 :                         action_vxlan_encap =
    1846                 :          0 :                             (const struct rte_flow_action_vxlan_encap *)temp->encap.action->conf;
    1847                 :          0 :                         definition = action_vxlan_encap->definition;
    1848                 :            :                         def_length = cpfl_get_items_length(definition);
    1849         [ #  # ]:          0 :                         for (k = 0; k < def_length - 1; k++) {
    1850         [ #  # ]:          0 :                                 if ((strcmp(hint, "eth") == 0 &&
    1851         [ #  # ]:          0 :                                      definition[k].type == RTE_FLOW_ITEM_TYPE_ETH) ||
    1852         [ #  # ]:          0 :                                     (strcmp(hint, "ipv4") == 0 &&
    1853         [ #  # ]:          0 :                                      definition[k].type == RTE_FLOW_ITEM_TYPE_IPV4) ||
    1854         [ #  # ]:          0 :                                     (strcmp(hint, "udp") == 0 &&
    1855         [ #  # ]:          0 :                                      definition[k].type == RTE_FLOW_ITEM_TYPE_UDP) ||
    1856         [ #  # ]:          0 :                                     (strcmp(hint, "tcp") == 0 &&
    1857         [ #  # ]:          0 :                                      definition[k].type == RTE_FLOW_ITEM_TYPE_TCP) ||
    1858         [ #  # ]:          0 :                                     (strcmp(hint, "vxlan") == 0 &&
    1859         [ #  # ]:          0 :                                      definition[k].type == RTE_FLOW_ITEM_TYPE_VXLAN)) {
    1860                 :          0 :                                         addr = (const uint8_t *)(definition[k].spec);
    1861         [ #  # ]:          0 :                                         if (start > 255) {
    1862                 :          0 :                                                 *byte_len = 0;
    1863                 :          0 :                                                 PMD_DRV_LOG(ERR, "byte length is too long: %s",
    1864                 :            :                                                             hint);
    1865                 :          0 :                                                 return -EINVAL;
    1866                 :            :                                         }
    1867                 :          0 :                                         memcpy(buffer + start, addr + offset, size);
    1868                 :            :                                         break;
    1869                 :            :                                 } /* TODO: more hint... */
    1870                 :            :                         }
    1871         [ #  # ]:          0 :                         if (k == def_length - 1) {
    1872                 :          0 :                                 *byte_len = 0;
    1873                 :          0 :                                 PMD_DRV_LOG(ERR, "can not find corresponding hint: %s", hint);
    1874                 :          0 :                                 return -EINVAL;
    1875                 :            :                         }
    1876                 :            :                 } else {
    1877                 :          0 :                         *byte_len = 0;
    1878                 :          0 :                         PMD_DRV_LOG(ERR, "Not support this type: %d.", temp->type);
    1879                 :          0 :                         return -EINVAL;
    1880                 :            :                 } /* else TODO: more type... */
    1881                 :          0 :                 start += size;
    1882                 :            :         }
    1883                 :          0 :         *byte_len = start;
    1884                 :            : 
    1885                 :          0 :         return 0;
    1886                 :            : }
    1887                 :            : 
    1888                 :            : static int
    1889                 :          0 : cpfl_parse_content(struct cpfl_flow_js_mr_content *content,
    1890                 :            :                    struct cpfl_flow_mr_key_action_prog *prog, uint8_t *buffer)
    1891                 :            : {
    1892                 :            :         int i, j;
    1893                 :            : 
    1894         [ #  # ]:          0 :         for (i = 0; i < content->field_size; i++) {
    1895                 :            :                 uint16_t start, width, shift_bit;
    1896                 :            : 
    1897                 :          0 :                 start = content->fields[i].start / 8;
    1898                 :          0 :                 width = (content->fields[i].width + 7) / 8;
    1899                 :          0 :                 shift_bit = (8 - content->fields[i].start % 8 - content->fields[i].width % 8) % 8;
    1900                 :            : 
    1901         [ #  # ]:          0 :                 for (j = 0; j < width; j++) {
    1902                 :            :                         uint8_t old_value = 0;
    1903                 :            : 
    1904         [ #  # ]:          0 :                         if (strcmp(content->fields[i].type, "parameter") == 0) {
    1905                 :            :                                 uint32_t k;
    1906                 :          0 :                                 uint16_t index = content->fields[i].index;
    1907                 :          0 :                                 const struct rte_flow_action_prog *act_prog = prog->prog;
    1908                 :            : 
    1909         [ #  # ]:          0 :                                 for (k = 0; k < act_prog->args_num; k++) {
    1910                 :          0 :                                         const char *name = act_prog->args[k].name;
    1911                 :            : 
    1912         [ #  # ]:          0 :                                         if ((prog->has_name &&
    1913   [ #  #  #  # ]:          0 :                                              strcmp(prog->name[index], name) == 0) ||
    1914         [ #  # ]:          0 :                                             (!prog->has_name && atoi(name) == index)) {
    1915                 :          0 :                                                 old_value = act_prog->args[k].value[j];
    1916                 :          0 :                                                 break;
    1917                 :            :                                         }
    1918                 :            :                                 }
    1919         [ #  # ]:          0 :                                 if (k == act_prog->args_num)
    1920                 :            :                                         return -EINVAL;
    1921         [ #  # ]:          0 :                         } else if (strcmp(content->fields[i].type, "constant") == 0) {
    1922                 :          0 :                                 old_value = content->fields[i].value[j];
    1923                 :            :                         } else {
    1924                 :            :                                 return -EINVAL;
    1925                 :            :                         }
    1926                 :          0 :                         memset(buffer + start + j, buffer[start + j] | old_value << shift_bit, 1);
    1927                 :            :                 }
    1928                 :            :         }
    1929                 :            : 
    1930                 :            :         return 0;
    1931                 :            : }
    1932                 :            : 
    1933                 :            : static int
    1934                 :          0 : cpfl_parse_mr_action(struct cpfl_flow_js_mr_action *action,
    1935                 :            :                      struct cpfl_flow_mr_key_action *mr_key_action,
    1936                 :            :                      struct cpfl_flow_mr_action *mr_action)
    1937                 :            : {
    1938                 :            :         enum cpfl_flow_mr_action_type type;
    1939                 :            : 
    1940                 :            :         /* mr->action->type */
    1941                 :          0 :         type = action->type;
    1942                 :            :         /* mr->action->data */
    1943         [ #  # ]:          0 :         if (action->mod.is_content) {
    1944                 :          0 :                 struct cpfl_flow_js_mr_content *content = &action->mod.content;
    1945                 :            : 
    1946                 :          0 :                 mr_action->type = CPFL_JS_MR_ACTION_TYPE_MOD;
    1947                 :            :                 mr_action->mod.byte_len = 0;
    1948                 :          0 :                 mr_action->mod.prof = action->mod.prof;
    1949                 :          0 :                 mr_action->mod.byte_len = content->size;
    1950                 :          0 :                 memset(mr_action->mod.data, 0, sizeof(mr_action->mod.data));
    1951                 :            : 
    1952                 :          0 :                 return cpfl_parse_content(content, &mr_key_action->prog, mr_action->mod.data);
    1953                 :            :         }
    1954                 :            : 
    1955         [ #  # ]:          0 :         if (type == CPFL_JS_MR_ACTION_TYPE_MOD) {
    1956                 :            :                 struct cpfl_flow_js_mr_layout *layout;
    1957                 :            : 
    1958                 :          0 :                 mr_action->type = CPFL_JS_MR_ACTION_TYPE_MOD;
    1959                 :          0 :                 mr_action->mod.byte_len = 0;
    1960                 :          0 :                 mr_action->mod.prof = action->mod.prof;
    1961                 :          0 :                 layout = action->mod.layout;
    1962                 :            :                 if (!layout)
    1963                 :            :                         return 0;
    1964                 :          0 :                 memset(mr_action->mod.data, 0, sizeof(mr_action->mod.data));
    1965                 :            : 
    1966                 :          0 :                 return cpfl_parse_layout(layout, action->mod.layout_size, mr_key_action->mods,
    1967                 :            :                                          mr_action->mod.data, &mr_action->mod.byte_len);
    1968                 :            :         }
    1969                 :          0 :         PMD_DRV_LOG(ERR, "Not support this type: %d.", type);
    1970                 :            : 
    1971                 :          0 :         return -EINVAL;
    1972                 :            : }
    1973                 :            : 
    1974                 :            : static int
    1975                 :            : cpfl_check_mod_key(struct cpfl_flow_js_mr *mr, const struct rte_flow_action *actions,
    1976                 :            :                    struct cpfl_flow_mr_key_action *mr_key_action)
    1977                 :            : {
    1978                 :            :         int key_action_size;
    1979                 :            : 
    1980                 :            :         /* mr->key->actions */
    1981                 :          0 :         key_action_size = mr->key.actions_size;
    1982                 :          0 :         return cpfl_parse_mr_key_action(mr->key.actions, key_action_size, actions, mr_key_action);
    1983                 :            : }
    1984                 :            : 
    1985                 :            : /* output: struct cpfl_flow_mr_action *mr_action */
    1986                 :            : static int
    1987                 :          0 : cpfl_parse_mod_rules(struct cpfl_flow_js_parser *parser, const struct rte_flow_action *actions,
    1988                 :            :                      struct cpfl_flow_mr_action *mr_action)
    1989                 :            : {
    1990                 :            :         int i;
    1991                 :          0 :         struct cpfl_flow_mr_key_action mr_key_action = {0};
    1992                 :            : 
    1993         [ #  # ]:          0 :         for (i = 0; i < parser->mr_size; i++) {
    1994                 :            :                 int ret;
    1995                 :            :                 struct cpfl_flow_js_mr *mr;
    1996                 :            : 
    1997                 :          0 :                 mr = &parser->modifications[i];
    1998         [ #  # ]:          0 :                 if (!mr)
    1999                 :            :                         return -EINVAL;
    2000                 :            :                 ret = cpfl_check_mod_key(mr, actions, &mr_key_action);
    2001         [ #  # ]:          0 :                 if (ret < 0)
    2002                 :            :                         continue;
    2003                 :            :                 /* mr->action */
    2004                 :          0 :                 return cpfl_parse_mr_action(&mr->action, &mr_key_action, mr_action);
    2005                 :            :         }
    2006                 :            : 
    2007                 :            :         return -EINVAL;
    2008                 :            : }
    2009                 :            : 
    2010                 :            : int
    2011                 :          0 : cpfl_flow_parse_actions(struct cpfl_flow_js_parser *parser, const struct rte_flow_action *actions,
    2012                 :            :                         struct cpfl_flow_mr_action *mr_action)
    2013                 :            : {
    2014                 :            :         /* modifications rules */
    2015         [ #  # ]:          0 :         if (!parser->modifications) {
    2016                 :          0 :                 PMD_DRV_LOG(INFO, "The modifications is optional.");
    2017                 :          0 :                 return 0;
    2018                 :            :         }
    2019                 :            : 
    2020                 :          0 :         return cpfl_parse_mod_rules(parser, actions, mr_action);
    2021                 :            : }
    2022                 :            : 
    2023                 :            : bool
    2024         [ #  # ]:          0 : cpfl_metadata_write_port_id(struct cpfl_itf *itf)
    2025                 :            : {
    2026                 :            :         uint16_t dev_id;
    2027                 :            :         const int type = 0;
    2028                 :            :         const int offset = 5;
    2029                 :            : 
    2030                 :            :         dev_id = cpfl_get_port_id(itf);
    2031         [ #  # ]:          0 :         if (dev_id == CPFL_INVALID_HW_ID) {
    2032                 :          0 :                 PMD_DRV_LOG(ERR, "fail to get hw ID");
    2033                 :          0 :                 return false;
    2034                 :            :         }
    2035                 :          0 :         cpfl_metadata_write16(&itf->adapter->meta, type, offset, dev_id << 3);
    2036                 :            : 
    2037                 :          0 :         return true;
    2038                 :            : }
    2039                 :            : 
    2040                 :            : bool
    2041                 :          0 : cpfl_metadata_write_targetvsi(struct cpfl_itf *itf)
    2042                 :            : {
    2043                 :            :         uint16_t dev_id;
    2044                 :            :         const int type = 6;
    2045                 :            :         const int offset = 2;
    2046                 :            : 
    2047                 :          0 :         dev_id = cpfl_get_vsi_id(itf);
    2048         [ #  # ]:          0 :         if (dev_id == CPFL_INVALID_HW_ID) {
    2049                 :          0 :                 PMD_DRV_LOG(ERR, "fail to get hw ID");
    2050                 :          0 :                 return false;
    2051                 :            :         }
    2052                 :          0 :         cpfl_metadata_write16(&itf->adapter->meta, type, offset, dev_id << 1);
    2053                 :            : 
    2054                 :          0 :         return true;
    2055                 :            : }
    2056                 :            : 
    2057                 :            : bool
    2058                 :          0 : cpfl_metadata_write_sourcevsi(struct cpfl_itf *itf)
    2059                 :            : {
    2060                 :            :         uint16_t dev_id;
    2061                 :            :         const int type = 6;
    2062                 :            :         const int offset = 0;
    2063                 :            : 
    2064                 :          0 :         dev_id = cpfl_get_vsi_id(itf);
    2065         [ #  # ]:          0 :         if (dev_id == CPFL_INVALID_HW_ID) {
    2066                 :          0 :                 PMD_DRV_LOG(ERR, "fail to get hw ID");
    2067                 :          0 :                 return false;
    2068                 :            :         }
    2069                 :          0 :         cpfl_metadata_write16(&itf->adapter->meta, type, offset, dev_id);
    2070                 :            : 
    2071                 :          0 :         return true;
    2072                 :            : }
    2073                 :            : 
    2074                 :          0 : bool cpfl_metadata_write_vsi(struct cpfl_itf *itf)
    2075                 :            : {
    2076                 :            :         uint16_t dev_id;
    2077                 :            :         const int type = 0;
    2078                 :            :         const int offset = 24;
    2079                 :            : 
    2080                 :          0 :         dev_id = cpfl_get_vsi_id(itf);
    2081         [ #  # ]:          0 :         if (dev_id == CPFL_INVALID_HW_ID) {
    2082                 :          0 :                 PMD_DRV_LOG(ERR, "fail to get hw ID");
    2083                 :          0 :                 return false;
    2084                 :            :         }
    2085                 :          0 :         cpfl_metadata_write16(&itf->adapter->meta, type, offset, dev_id);
    2086                 :            : 
    2087                 :          0 :         return true;
    2088                 :            : }

Generated by: LCOV version 1.14