From patchwork Tue Aug 15 16:50:43 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Zhang, Yuying" X-Patchwork-Id: 131459 X-Patchwork-Delegate: ferruh.yigit@amd.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 692FB425A3; Fri, 15 Sep 2023 10:47:43 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 56AC240697; Fri, 15 Sep 2023 10:47:43 +0200 (CEST) Received: from mgamail.intel.com (mgamail.intel.com [134.134.136.31]) by mails.dpdk.org (Postfix) with ESMTP id D361C4067A for ; Fri, 15 Sep 2023 10:47:41 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1694767662; x=1726303662; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=5teCUJtmaxM5d4VodOBy6olLQXrnSxRrUvwLos/ToA0=; b=JIdwYsMqP8Yjxaj9EBbJ+BeQzjlEBbACDKePrjYvbE7yEZ6RilulbRkc bkSHx+A/mdpDlElca/vDUDIwSnXyG8LHiIpWINADeh4p3MM8V0peNaSp4 GXJ/HDC2fFztzLfVIJhC6O1+8E0gvjXCgIEKYwO/i2zEjIV27oIQuQXAj PsWLpQA527T4M/WhFL0rSpVoQETs/QeHtcGy1IdN4oLCxyp+bxzcLKz9Q dYvFJLBZs+CFhW3fK1Mp5coAUKnFpWcRJLZxfy0OueIJ1UuGtmGc6huZd eZduh1vwtnCVsZA6yDISbqFpDCAtlLAkEjDNKkxiRF2FkrV+cY/x9LAFa A==; X-IronPort-AV: E=McAfee;i="6600,9927,10833"; a="443265001" X-IronPort-AV: E=Sophos;i="6.02,148,1688454000"; d="scan'208";a="443265001" Received: from orsmga007.jf.intel.com ([10.7.209.58]) by orsmga104.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 15 Sep 2023 01:47:26 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10833"; a="738254373" X-IronPort-AV: E=Sophos;i="6.02,148,1688454000"; d="scan'208";a="738254373" Received: from dpdk-pengyuan-mev.sh.intel.com ([10.67.119.128]) by orsmga007.jf.intel.com with ESMTP; 15 Sep 2023 01:47:24 -0700 From: "Zhang, Yuying" To: yuying.zhang@intel.com, dev@dpdk.org, qi.z.zhang@intel.com, beilei.xing@intel.com, jingjing.wu@intel.com Cc: mingxia.liu@intel.com, Wenjing Qiao Subject: [PATCH v4 2/9] net/cpfl: add mod rule parser support for rte flow Date: Tue, 15 Aug 2023 16:50:43 +0000 Message-Id: <20230815165050.86595-3-yuying.zhang@intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230815165050.86595-1-yuying.zhang@intel.com> References: <20230906093407.3635038-1-wenjing.qiao@intel.com> <20230815165050.86595-1-yuying.zhang@intel.com> MIME-Version: 1.0 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org From: Wenjing Qiao Add json parser support for rte flow modification rules. Signed-off-by: Wenjing Qiao --- drivers/net/cpfl/cpfl_flow_parser.c | 534 +++++++++++++++++++++++++++- drivers/net/cpfl/cpfl_flow_parser.h | 100 ++++++ 2 files changed, 633 insertions(+), 1 deletion(-) diff --git a/drivers/net/cpfl/cpfl_flow_parser.c b/drivers/net/cpfl/cpfl_flow_parser.c index 630ce8a227..c33ee1ec27 100644 --- a/drivers/net/cpfl/cpfl_flow_parser.c +++ b/drivers/net/cpfl/cpfl_flow_parser.c @@ -32,6 +32,18 @@ cpfl_get_item_type_by_str(const char *type) return RTE_FLOW_ITEM_TYPE_VOID; } +static enum rte_flow_action_type +cpfl_get_action_type_by_str(const char *type) +{ + if (strcmp(type, "vxlan_encap") == 0) + return RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP; + else if (strcmp(type, "vxlan_decap") == 0) + return RTE_FLOW_ACTION_TYPE_VXLAN_DECAP; + + PMD_DRV_LOG(ERR, "Not support this type: %s.", type); + return RTE_FLOW_ACTION_TYPE_VOID; +} + static const char * cpfl_json_object_to_string(json_object *object, const char *name) { @@ -50,6 +62,25 @@ cpfl_json_object_to_string(json_object *object, const char *name) return json_object_get_string(subobject); } +static int +cpfl_json_object_to_int(json_object *object, const char *name, int *value) +{ + json_object *subobject; + + if (!object) { + PMD_DRV_LOG(ERR, "object doesn't exist."); + return -EINVAL; + } + subobject = json_object_object_get(object, name); + if (!subobject) { + PMD_DRV_LOG(ERR, "%s doesn't exist.", name); + return -EINVAL; + } + *value = json_object_get_int(subobject); + + return 0; +} + static int cpfl_json_object_to_uint16(json_object *object, const char *name, uint16_t *value) { @@ -517,6 +548,228 @@ cpfl_flow_js_pattern_rule(json_object *ob_root, struct cpfl_flow_js_parser *pars return -EINVAL; } +static int +cpfl_flow_js_mr_key(json_object *ob_mr_keys, struct cpfl_flow_js_mr_key *js_mr_key) +{ + int len, i; + + len = json_object_array_length(ob_mr_keys); + if (len == 0) + return 0; + js_mr_key->actions = rte_malloc(NULL, sizeof(struct cpfl_flow_js_mr_key_action) * len, 0); + if (!js_mr_key->actions) { + PMD_DRV_LOG(ERR, "Failed to alloc memory."); + return -ENOMEM; + } + js_mr_key->actions_size = len; + for (i = 0; i < len; i++) { + json_object *object, *ob_data; + const char *type; + enum rte_flow_action_type act_type; + + object = json_object_array_get_idx(ob_mr_keys, i); + /* mr->key->actions->type */ + type = cpfl_json_object_to_string(object, "type"); + if (!type) { + PMD_DRV_LOG(ERR, "Can not parse string 'type'."); + goto err; + } + act_type = cpfl_get_action_type_by_str(type); + if (act_type == RTE_FLOW_ACTION_TYPE_VOID) + goto err; + js_mr_key->actions[i].type = act_type; + /* mr->key->actions->data */ + ob_data = json_object_object_get(object, "data"); + if (js_mr_key->actions[i].type == RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP) { + json_object *ob_protos; + int proto_size, j; + struct cpfl_flow_js_mr_key_action_vxlan_encap *encap; + + ob_protos = json_object_object_get(ob_data, "protocols"); + encap = &js_mr_key->actions[i].encap; + if (!ob_protos) { + encap->proto_size = 0; + continue; + } + proto_size = json_object_array_length(ob_protos); + encap->proto_size = proto_size; + for (j = 0; j < proto_size; j++) { + const char *s; + json_object *subobject; + enum rte_flow_item_type proto_type; + + subobject = json_object_array_get_idx(ob_protos, j); + s = json_object_get_string(subobject); + proto_type = cpfl_get_item_type_by_str(s); + if (proto_type == RTE_FLOW_ITEM_TYPE_VOID) { + PMD_DRV_LOG(ERR, "parse VXLAN_ENCAP failed."); + goto err; + } + encap->protocols[j] = proto_type; + } + } else if (js_mr_key->actions[i].type != RTE_FLOW_ACTION_TYPE_VXLAN_DECAP) { + PMD_DRV_LOG(ERR, "not support this type: %d.", js_mr_key->actions[i].type); + goto err; + } + } + + return 0; + +err: + rte_free(js_mr_key->actions); + return -EINVAL; +} + +static int +cpfl_flow_js_mr_layout(json_object *ob_layouts, struct cpfl_flow_js_mr_action_mod *js_mod) +{ + int len, i; + + len = json_object_array_length(ob_layouts); + js_mod->layout_size = len; + if (len == 0) + return 0; + js_mod->layout = rte_malloc(NULL, sizeof(struct cpfl_flow_js_mr_layout) * len, 0); + if (!js_mod->layout) { + PMD_DRV_LOG(ERR, "Failed to alloc memory."); + return -ENOMEM; + } + + for (i = 0; i < len; i++) { + json_object *object; + int index = 0, size = 0, offset = 0; + int ret; + const char *hint; + + object = json_object_array_get_idx(ob_layouts, i); + ret = cpfl_json_object_to_int(object, "index", &index); + if (ret < 0) { + PMD_DRV_LOG(ERR, "Can not parse 'index'."); + goto err; + } + js_mod->layout[i].index = index; + ret = cpfl_json_object_to_int(object, "size", &size); + if (ret < 0) { + PMD_DRV_LOG(ERR, "Can not parse 'size'."); + goto err; + } + js_mod->layout[i].size = size; + ret = cpfl_json_object_to_int(object, "offset", &offset); + if (ret < 0) { + PMD_DRV_LOG(ERR, "Can not parse 'offset'."); + goto err; + } + js_mod->layout[i].offset = offset; + hint = cpfl_json_object_to_string(object, "hint"); + if (!hint) { + PMD_DRV_LOG(ERR, "Can not parse string 'hint'."); + goto err; + } + memcpy(js_mod->layout[i].hint, hint, strlen(hint)); + } + + return 0; + +err: + rte_free(js_mod->layout); + return -EINVAL; +} + +static int +cpfl_flow_js_mr_action(json_object *ob_mr_act, struct cpfl_flow_js_mr_action *js_mr_act) +{ + json_object *ob_data; + const char *type; + + /* mr->action->type */ + type = cpfl_json_object_to_string(ob_mr_act, "type"); + if (!type) { + PMD_DRV_LOG(ERR, "Can not parse string 'type'."); + return -EINVAL; + } + /* mr->action->data */ + ob_data = json_object_object_get(ob_mr_act, "data"); + if (strcmp(type, "mod") == 0) { + json_object *ob_layouts; + uint16_t profile = 0; + int ret; + + js_mr_act->type = CPFL_JS_MR_ACTION_TYPE_MOD; + ret = cpfl_json_object_to_uint16(ob_data, "profile", &profile); + if (ret < 0) { + PMD_DRV_LOG(ERR, "Can not parse 'profile'."); + return -EINVAL; + } + js_mr_act->mod.prof = profile; + ob_layouts = json_object_object_get(ob_data, "layout"); + ret = cpfl_flow_js_mr_layout(ob_layouts, &js_mr_act->mod); + if (ret < 0) { + PMD_DRV_LOG(ERR, "Can not parse layout."); + return ret; + } + } else { + PMD_DRV_LOG(ERR, "not support this type: %s.", type); + return -EINVAL; + } + + return 0; +} + +/** + * The modifications object array defines a set of rules for the PMD to match rte_flow + * modification actions and translate them into the Modification profile. This object + * is optional. + */ +static int +cpfl_flow_js_mod_rule(json_object *ob_root, struct cpfl_flow_js_parser *parser) +{ + json_object *ob_mrs; + int i, len; + + ob_mrs = json_object_object_get(ob_root, "modifications"); + if (!ob_mrs) { + PMD_DRV_LOG(INFO, "The modifications is optional."); + return 0; + } + len = json_object_array_length(ob_mrs); + if (len == 0) + return 0; + parser->mr_size = len; + parser->modifications = rte_malloc(NULL, sizeof(struct cpfl_flow_js_mr) * len, 0); + if (!parser->modifications) { + PMD_DRV_LOG(ERR, "Failed to alloc memory."); + return -ENOMEM; + } + for (i = 0; i < len; i++) { + int ret; + json_object *object, *ob_mr_key, *ob_mr_action, *ob_mr_key_action; + + object = json_object_array_get_idx(ob_mrs, i); + /* mr->key */ + ob_mr_key = json_object_object_get(object, "key"); + /* mr->key->actions */ + ob_mr_key_action = json_object_object_get(ob_mr_key, "actions"); + ret = cpfl_flow_js_mr_key(ob_mr_key_action, &parser->modifications[i].key); + if (ret < 0) { + PMD_DRV_LOG(ERR, "parse mr_key failed."); + goto err; + } + /* mr->action */ + ob_mr_action = json_object_object_get(object, "action"); + ret = cpfl_flow_js_mr_action(ob_mr_action, &parser->modifications[i].action); + if (ret < 0) { + PMD_DRV_LOG(ERR, "parse mr_action failed."); + goto err; + } + } + + return 0; + +err: + rte_free(parser->modifications); + return -EINVAL; +} + static int cpfl_parser_init(json_object *ob_root, struct cpfl_flow_js_parser *parser) { @@ -527,6 +780,11 @@ cpfl_parser_init(json_object *ob_root, struct cpfl_flow_js_parser *parser) PMD_DRV_LOG(ERR, "parse pattern_rule failed."); return ret; } + ret = cpfl_flow_js_mod_rule(ob_root, parser); + if (ret < 0) { + PMD_DRV_LOG(ERR, "parse mod_rule failed."); + return ret; + } return 0; } @@ -601,6 +859,15 @@ cpfl_parser_destroy(struct cpfl_flow_js_parser *parser) rte_free(pattern->actions); } rte_free(parser->patterns); + for (i = 0; i < parser->mr_size; i++) { + struct cpfl_flow_js_mr *mr = &parser->modifications[i]; + + if (!mr) + continue; + rte_free(mr->key.actions); + rte_free(mr->action.mod.layout); + } + rte_free(parser->modifications); rte_free(parser); return 0; @@ -617,6 +884,17 @@ cpfl_get_items_length(const struct rte_flow_item *items) return length; } +static int +cpfl_get_actions_length(const struct rte_flow_action *actions) +{ + int length = 0; + const struct rte_flow_action *action = actions; + + while ((action + length++)->type != RTE_FLOW_ACTION_TYPE_END) + continue; + return length; +} + static int cpfl_parse_fv_protocol(struct cpfl_flow_js_fv *js_fv, const struct rte_flow_item *items, uint16_t offset, uint8_t *fv) @@ -645,7 +923,7 @@ cpfl_parse_fv_protocol(struct cpfl_flow_js_fv *js_fv, const struct rte_flow_item break; } layer++; - } /* TODO: more type... */ + } } return 0; @@ -1234,6 +1512,260 @@ cpfl_flow_parse_items(struct cpfl_itf *itf, return -EINVAL; } +/* modifications rules */ +static int +cpfl_check_actions_vxlan_encap(struct cpfl_flow_mr_key_action_vxlan_encap *encap, + const struct rte_flow_action *action) +{ + const struct rte_flow_action_vxlan_encap *action_vxlan_encap; + struct rte_flow_item *definition; + int def_length, i, proto_size; + + action_vxlan_encap = (const struct rte_flow_action_vxlan_encap *)action->conf; + definition = action_vxlan_encap->definition; + def_length = cpfl_get_items_length(definition); + proto_size = encap->proto_size; + if (proto_size != def_length - 1) { + PMD_DRV_LOG(DEBUG, "protocols not match."); + return -EINVAL; + } + for (i = 0; i < proto_size; i++) { + enum rte_flow_item_type proto; + + proto = encap->protocols[i]; + if (proto == RTE_FLOW_ITEM_TYPE_VLAN) { + if (definition[i].type != RTE_FLOW_ITEM_TYPE_VOID) { + PMD_DRV_LOG(DEBUG, "protocols not match."); + return -EINVAL; + } + } else if (proto != definition[i].type) { + PMD_DRV_LOG(DEBUG, "protocols not match."); + return -EINVAL; + } + } + + return 0; +} + +/* check and parse */ +static int +cpfl_parse_mr_key_action(struct cpfl_flow_js_mr_key_action *key_acts, int size, + const struct rte_flow_action *actions, + struct cpfl_flow_mr_key_action *mr_key_action) +{ + int actions_length, i; + int j = 0; + int ret; + + actions_length = cpfl_get_actions_length(actions); + if (size > actions_length - 1) + return -EINVAL; + for (i = 0; i < size; i++) { + enum rte_flow_action_type type; + struct cpfl_flow_js_mr_key_action *key_act; + + key_act = &key_acts[i]; + /* mr->key->actions->type */ + type = key_act->type; + /* mr->key->actions->data */ + if (type == RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP) { + int proto_size, k; + struct cpfl_flow_mr_key_action_vxlan_encap *encap; + + while (j < actions_length && + actions[j].type != RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP) { + j++; + } + if (j >= actions_length) + return -EINVAL; + mr_key_action[i].type = RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP; + mr_key_action[i].encap.action = &actions[j]; + encap = &mr_key_action[i].encap; + + proto_size = key_act->encap.proto_size; + encap->proto_size = proto_size; + for (k = 0; k < proto_size; k++) { + enum rte_flow_item_type proto; + + proto = key_act->encap.protocols[k]; + encap->protocols[k] = proto; + } + ret = cpfl_check_actions_vxlan_encap(encap, &actions[j]); + if (ret < 0) + return -EINVAL; + j++; + } else if (type == RTE_FLOW_ACTION_TYPE_VXLAN_DECAP) { + while (j < actions_length && + actions[j].type != RTE_FLOW_ACTION_TYPE_VXLAN_DECAP) { + j++; + } + if (j >= actions_length) + return -EINVAL; + mr_key_action[i].type = RTE_FLOW_ACTION_TYPE_VXLAN_DECAP; + j++; + } else { + PMD_DRV_LOG(ERR, "Not support this type: %d.", type); + return -EPERM; + } + } + + return 0; +} + +/* output: uint8_t *buffer, uint16_t *byte_len */ +static int +cpfl_parse_layout(struct cpfl_flow_js_mr_layout *layouts, int layout_size, + struct cpfl_flow_mr_key_action *mr_key_action, + uint8_t *buffer, uint16_t *byte_len) +{ + int i; + int start = 0; + + for (i = 0; i < layout_size; i++) { + int index, size, offset; + const char *hint; + const uint8_t *addr = NULL; + struct cpfl_flow_mr_key_action *temp; + struct cpfl_flow_js_mr_layout *layout; + + layout = &layouts[i]; + /* index links to the element of the actions array. */ + index = layout->index; + size = layout->size; + offset = layout->offset; + if (index == -1) { + hint = "dummpy"; + start += size; + continue; + } + hint = layout->hint; + temp = mr_key_action + index; + if (temp->type == RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP) { + const struct rte_flow_action_vxlan_encap *action_vxlan_encap; + struct rte_flow_item *definition; + int def_length, k; + + action_vxlan_encap = + (const struct rte_flow_action_vxlan_encap *)temp->encap.action->conf; + definition = action_vxlan_encap->definition; + def_length = cpfl_get_items_length(definition); + for (k = 0; k < def_length - 1; k++) { + if ((strcmp(hint, "eth") == 0 && + definition[k].type == RTE_FLOW_ITEM_TYPE_ETH) || + (strcmp(hint, "ipv4") == 0 && + definition[k].type == RTE_FLOW_ITEM_TYPE_IPV4) || + (strcmp(hint, "udp") == 0 && + definition[k].type == RTE_FLOW_ITEM_TYPE_UDP) || + (strcmp(hint, "tcp") == 0 && + definition[k].type == RTE_FLOW_ITEM_TYPE_TCP) || + (strcmp(hint, "vxlan") == 0 && + definition[k].type == RTE_FLOW_ITEM_TYPE_VXLAN)) { + addr = (const uint8_t *)(definition[k].spec); + if (start > 255) { + *byte_len = 0; + PMD_DRV_LOG(ERR, "byte length is too long: %s", + hint); + return -EINVAL; + } + memcpy(buffer + start, addr + offset, size); + break; + } /* TODO: more hint... */ + } + if (k == def_length - 1) { + *byte_len = 0; + PMD_DRV_LOG(ERR, "can not find corresponding hint: %s", hint); + return -EINVAL; + } + } else { + *byte_len = 0; + PMD_DRV_LOG(ERR, "Not support this type: %d.", temp->type); + return -EINVAL; + } /* else TODO: more type... */ + start += size; + } + *byte_len = start; + + return 0; +} + +static int +cpfl_parse_mr_action(struct cpfl_flow_js_mr_action *action, + struct cpfl_flow_mr_key_action *mr_key_action, + struct cpfl_flow_mr_action *mr_action) +{ + enum cpfl_flow_mr_action_type type; + + /* mr->action->type */ + type = action->type; + /* mr->action->data */ + if (type == CPFL_JS_MR_ACTION_TYPE_MOD) { + struct cpfl_flow_js_mr_layout *layout; + + mr_action->type = CPFL_JS_MR_ACTION_TYPE_MOD; + mr_action->mod.byte_len = 0; + mr_action->mod.prof = action->mod.prof; + layout = action->mod.layout; + if (!layout) + return 0; + memset(mr_action->mod.data, 0, sizeof(mr_action->mod.data)); + + return cpfl_parse_layout(layout, action->mod.layout_size, mr_key_action, + mr_action->mod.data, &mr_action->mod.byte_len); + } + PMD_DRV_LOG(ERR, "Not support this type: %d.", type); + + return -EINVAL; +} + +static int +cpfl_check_mod_key(struct cpfl_flow_js_mr *mr, const struct rte_flow_action *actions, + struct cpfl_flow_mr_key_action *mr_key_action) +{ + int key_action_size; + + /* mr->key->actions */ + key_action_size = mr->key.actions_size; + return cpfl_parse_mr_key_action(mr->key.actions, key_action_size, actions, mr_key_action); +} + +/* output: struct cpfl_flow_mr_action *mr_action */ +static int +cpfl_parse_mod_rules(struct cpfl_flow_js_parser *parser, const struct rte_flow_action *actions, + struct cpfl_flow_mr_action *mr_action) +{ + int i; + struct cpfl_flow_mr_key_action mr_key_action[CPFL_MOD_KEY_NUM_MAX] = {0}; + + for (i = 0; i < parser->mr_size; i++) { + int ret; + struct cpfl_flow_js_mr *mr; + + mr = &parser->modifications[i]; + if (!mr) + return -EINVAL; + ret = cpfl_check_mod_key(mr, actions, mr_key_action); + if (ret < 0) + continue; + /* mr->action */ + return cpfl_parse_mr_action(&mr->action, mr_key_action, mr_action); + } + + return -EINVAL; +} + +int +cpfl_flow_parse_actions(struct cpfl_flow_js_parser *parser, const struct rte_flow_action *actions, + struct cpfl_flow_mr_action *mr_action) +{ + /* modifications rules */ + if (!parser->modifications) { + PMD_DRV_LOG(INFO, "The modifications is optional."); + return 0; + } + + return cpfl_parse_mod_rules(parser, actions, mr_action); +} + bool cpfl_metadata_write_port_id(struct cpfl_itf *itf) { diff --git a/drivers/net/cpfl/cpfl_flow_parser.h b/drivers/net/cpfl/cpfl_flow_parser.h index af64a158a8..2618a9a81f 100644 --- a/drivers/net/cpfl/cpfl_flow_parser.h +++ b/drivers/net/cpfl/cpfl_flow_parser.h @@ -105,9 +105,79 @@ struct cpfl_flow_js_pr { uint16_t actions_size; }; +/* Modification Rules Storage */ +/** + * The vxlan_encap action matches RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP + * and include a sequence of protocol headers defined in field protocols + * of data. + */ +struct cpfl_flow_js_mr_key_action_vxlan_encap { + enum rte_flow_item_type protocols[CPFL_FLOW_JS_PROTO_SIZE]; + int proto_size; +}; + +/* A set of modification rte_flow_action_xxx objects can be defined as a type / data pair. */ +struct cpfl_flow_js_mr_key_action { + enum rte_flow_action_type type; + union { + struct cpfl_flow_js_mr_key_action_vxlan_encap encap; + }; +}; + +struct cpfl_flow_js_mr_key { + struct cpfl_flow_js_mr_key_action *actions; + int actions_size; +}; + +struct cpfl_flow_js_mr_layout { + int index; /* links to the element of the actions array */ + char hint[CPFL_FLOW_JSON_STR_SIZE_MAX]; /* where the data to copy from */ + uint16_t offset; /* the start byte of the data to copy from */ + uint16_t size; /* bytes of the data to be copied to the memory region */ +}; + +/** For mod data, besides the profile ID, a layout array defines a set of hints that helps + * driver composing the MOD memory region when the action need to insert/update some packet + * data from user input. + */ +struct cpfl_flow_js_mr_action_mod { + uint16_t prof; + uint16_t byte_len; + struct cpfl_flow_js_mr_layout *layout; + int layout_size; +}; + +enum cpfl_flow_mr_action_type { + CPFL_JS_MR_ACTION_TYPE_MOD, +}; + +/** Currently, the type can only be mod. + * + * For mod data, besides the profile ID, a layout array defines a set + * of hints that helps driver composing the MOD memory region when the + * action need to insert/update some packet data from user input. + */ +struct cpfl_flow_js_mr_action { + enum cpfl_flow_mr_action_type type; + union { + struct cpfl_flow_js_mr_action_mod mod; + }; +}; + +/** + * This structure defines a set of rules that direct PMD to parse rte_flow modification + * actions. Each rule be described by a pair of key and action + */ +struct cpfl_flow_js_mr { + struct cpfl_flow_js_mr_key key; + struct cpfl_flow_js_mr_action action; +}; + struct cpfl_flow_js_parser { struct cpfl_flow_js_pr *patterns; int pr_size; + struct cpfl_flow_js_mr *modifications; + int mr_size; }; /* Pattern Rules */ @@ -125,6 +195,33 @@ struct cpfl_flow_pr_action { }; }; +/* Modification Rules */ +struct cpfl_flow_mr_key_action_vxlan_encap { + enum rte_flow_item_type protocols[CPFL_FLOW_JS_PROTO_SIZE]; + uint16_t proto_size; + const struct rte_flow_action *action; +}; + +struct cpfl_flow_mr_key_action { + enum rte_flow_action_type type; + union { + struct cpfl_flow_mr_key_action_vxlan_encap encap; + }; +}; + +struct cpfl_flow_mr_action_mod { + uint16_t prof; + uint16_t byte_len; + uint8_t data[256]; +}; + +struct cpfl_flow_mr_action { + enum cpfl_flow_mr_action_type type; + union { + struct cpfl_flow_mr_action_mod mod; + }; +}; + int cpfl_parser_create(struct cpfl_flow_js_parser **parser, const char *filename); int cpfl_parser_destroy(struct cpfl_flow_js_parser *parser); int cpfl_flow_parse_items(struct cpfl_itf *itf, @@ -132,6 +229,9 @@ int cpfl_flow_parse_items(struct cpfl_itf *itf, const struct rte_flow_item *items, const struct rte_flow_attr *attr, struct cpfl_flow_pr_action *pr_action); +int cpfl_flow_parse_actions(struct cpfl_flow_js_parser *parser, + const struct rte_flow_action *actions, + struct cpfl_flow_mr_action *mr_action); bool cpfl_metadata_write_port_id(struct cpfl_itf *itf); bool cpfl_metadata_write_vsi(struct cpfl_itf *itf); bool cpfl_metadata_write_targetvsi(struct cpfl_itf *itf);