From patchwork Tue Oct 31 07:48:17 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wenjing Qiao X-Patchwork-Id: 133638 X-Patchwork-Delegate: qi.z.zhang@intel.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 211664324D; Tue, 31 Oct 2023 08:53:36 +0100 (CET) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 0CBB64027F; Tue, 31 Oct 2023 08:53:36 +0100 (CET) Received: from mgamail.intel.com (mgamail.intel.com [134.134.136.126]) by mails.dpdk.org (Postfix) with ESMTP id D4E5B400EF for ; Tue, 31 Oct 2023 08:52:31 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1698738752; x=1730274752; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=RxFakPq32AE5cSnFu/m0OJUC6hR4Ahe49J4z3MSTFGY=; b=EryrPT0kkz0xSxBMlsCkHKy3nbDhlzjEPkgf54vvU8QMfRVFGvXl0qBv +v7Q09z94HenP+ueqLqyLWFgJKqnTltNk7bDKJHJS6k05ZuXc+lrdolMi STHPECZFWx9sZlqn0/ZPqw94kW5NHFBLefa4n6RW+lDCkrr+uqHmUPzEw iyFwr6h7YE9HynkLY/w+rGFYmjlQYZES8tDSRYG3kTAAdibW8sMbSOkaT X17uTBmoz7Ua2/LMz1+clKnIg12qyCx8ntZaXZ4AG3EVEDEaCO4xnow2/ AUTuhmbtmLSRhsmkS5c51IjjEJmUTq7lencB+JW3oYK43B2GJBwms/rca A==; X-IronPort-AV: E=McAfee;i="6600,9927,10879"; a="373284982" X-IronPort-AV: E=Sophos;i="6.03,265,1694761200"; d="scan'208";a="373284982" Received: from orsmga006.jf.intel.com ([10.7.209.51]) by orsmga106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 31 Oct 2023 00:52:29 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10879"; a="737000113" X-IronPort-AV: E=Sophos;i="6.03,265,1694761200"; d="scan'208";a="737000113" Received: from dpdk-wenjing-02.sh.intel.com ([10.67.119.3]) by orsmga006.jf.intel.com with ESMTP; 31 Oct 2023 00:52:27 -0700 From: wenjing.qiao@intel.com To: jingjing.wu@intel.com, beilei.xing@intel.com, qi.z.zhang@intel.com Cc: dev@dpdk.org, Wenjing Qiao Subject: [PATCH v3] net/cpfl: support action prog Date: Tue, 31 Oct 2023 07:48:17 +0000 Message-Id: <20231031074816.2391599-1-wenjing.qiao@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231030021325.1393486-1-wenjing.qiao@intel.com> References: <20231030021325.1393486-1-wenjing.qiao@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 Parse JSON file and generate rules that instruct PMD to map an RTE_FLOW_ACTION_TYPE_PROG to a low-level FXP representation, the matching follows below guidelines. Use rte_flow_action_prog->name to match the name of a P4 action type when provided in the JSON file. In cases where the JSON file lacks the P4 action type's name but includes the P4 action type ID, PMD should attempt to convert rte_flow_action_prog->name into a uint32 value and then match it to the P4 action type ID. The same method applies when matching a rte_flow_action_prog_argument to a field of an action type. Here's an example to create a rule that matches an IPV4/TCP header and applies a VXLAN encapsulation which is represented by rte_flow_action_prog: flow create 0 ingress pattern eth src is 00:11:22:33:44:55 dst is 00:01:00:00:03:14 / ipv4 src is 192.168.0.1 dst is 192.168.0.2 / tcp src is 0x1451 dst is 0x157c / end actions prog name vxlan_encap arguments src_addr 0xC0A80002 dst_addr 0xC0A80003 src_mac 0x000100000314 dst_mac 0x000600000314 src_port 0x1234 dst_port 0x4789 vni 0x000050 end / port_representor port_id 0 / end Signed-off-by: Wenjing Qiao --- drivers/net/cpfl/cpfl_flow_engine_fxp.c | 2 + drivers/net/cpfl/cpfl_flow_parser.c | 266 ++++++++++++++++++++++-- drivers/net/cpfl/cpfl_flow_parser.h | 62 +++++- 3 files changed, 306 insertions(+), 24 deletions(-) diff --git a/drivers/net/cpfl/cpfl_flow_engine_fxp.c b/drivers/net/cpfl/cpfl_flow_engine_fxp.c index ddede2f553..6b0830afd0 100644 --- a/drivers/net/cpfl/cpfl_flow_engine_fxp.c +++ b/drivers/net/cpfl/cpfl_flow_engine_fxp.c @@ -373,6 +373,7 @@ cpfl_fxp_parse_action(struct cpfl_itf *itf, break; case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP: case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP: + case RTE_FLOW_ACTION_TYPE_PROG: break; case RTE_FLOW_ACTION_TYPE_VOID: break; @@ -425,6 +426,7 @@ cpfl_is_mod_action(const struct rte_flow_action actions[]) switch (action_type) { case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP: case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP: + case RTE_FLOW_ACTION_TYPE_PROG: return true; default: continue; diff --git a/drivers/net/cpfl/cpfl_flow_parser.c b/drivers/net/cpfl/cpfl_flow_parser.c index 412f7feed0..90034458e1 100644 --- a/drivers/net/cpfl/cpfl_flow_parser.c +++ b/drivers/net/cpfl/cpfl_flow_parser.c @@ -35,6 +35,8 @@ cpfl_get_action_type_by_str(const char *type) return RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP; else if (strcmp(type, "vxlan_decap") == 0) return RTE_FLOW_ACTION_TYPE_VXLAN_DECAP; + else if (strcmp(type, "prog") == 0) + return RTE_FLOW_ACTION_TYPE_PROG; PMD_DRV_LOG(ERR, "Not support this type: %s.", type); return RTE_FLOW_ACTION_TYPE_VOID; @@ -612,6 +614,57 @@ cpfl_flow_js_mr_key(json_t *ob_mr_keys, struct cpfl_flow_js_mr_key *js_mr_key) } encap->protocols[j] = proto_type; } + } else if (js_mr_key->actions[i].type == RTE_FLOW_ACTION_TYPE_PROG) { + int ret; + uint32_t param_size, j; + uint16_t value = 0; + json_t *ob_param, *subobject; + const char *name; + + ret = cpfl_json_t_to_uint32(object, "id", &js_mr_key->actions[i].prog.id); + if (ret < 0) { + PMD_DRV_LOG(ERR, "Can not parse uint32 'id'."); + goto err; + } + if (json_object_get(object, "name")) { + js_mr_key->actions[i].prog.has_name = TRUE; + name = cpfl_json_t_to_string(object, "name"); + if (!name) { + PMD_DRV_LOG(ERR, "Can not parse string 'name'."); + goto err; + } + strncpy(js_mr_key->actions[i].prog.name, name, strlen(name)); + } + + ob_param = json_object_get(object, "parameters"); + param_size = json_array_size(ob_param); + js_mr_key->actions[i].prog.param_size = param_size; + for (j = 0; j < param_size; j++) { + subobject = json_array_get(ob_param, j); + ret = cpfl_json_t_to_uint16(subobject, "index", &value); + if (ret < 0) { + PMD_DRV_LOG(ERR, "Can not parse 'index'."); + goto err; + } + js_mr_key->actions[i].prog.params[j].index = value; + if (json_object_get(subobject, "name")) { + js_mr_key->actions[i].prog.params[j].has_name = TRUE; + name = cpfl_json_t_to_string(subobject, "name"); + if (!name) { + PMD_DRV_LOG(ERR, "Can not parse string 'name'."); + goto err; + } + strncpy(js_mr_key->actions[i].prog.params[j].name, name, + strlen(name)); + } + ret = cpfl_json_t_to_uint16(subobject, "size", &value); + if (ret < 0) { + PMD_DRV_LOG(ERR, "Can not parse 'size'."); + goto err; + } + js_mr_key->actions[i].prog.params[j].size = value; + } + } 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; @@ -634,11 +687,6 @@ cpfl_flow_js_mr_layout(json_t *ob_layouts, struct cpfl_flow_js_mr_action_mod *js 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_t *object; @@ -680,6 +728,79 @@ cpfl_flow_js_mr_layout(json_t *ob_layouts, struct cpfl_flow_js_mr_action_mod *js return -EINVAL; } +static int +cpfl_flow_js_mr_content(json_t *ob_content, struct cpfl_flow_js_mr_action_mod *js_mod) +{ + int ret, len, i; + json_t *ob_field; + + if (!ob_content) + return 0; + + js_mod->is_content = TRUE; + ret = cpfl_json_t_to_uint16(ob_content, "size", &js_mod->content.size); + if (ret < 0) { + PMD_DRV_LOG(ERR, "Can not parse 'size'."); + return -EINVAL; + } + + ob_field = json_object_get(ob_content, "fields"); + len = json_array_size(ob_field); + js_mod->content.field_size = len; + if (len == 0) + return 0; + + for (i = 0; i < len; i++) { + json_t *object; + uint16_t start = 0, width = 0, index = 0; + const char *type; + + object = json_array_get(ob_field, i); + type = cpfl_json_t_to_string(object, "type"); + if (!type) { + PMD_DRV_LOG(ERR, "Can not parse string 'type'."); + goto err; + } + strncpy(js_mod->content.fields[i].type, type, strlen(type)); + ret = cpfl_json_t_to_uint16(object, "start", &start); + if (ret < 0) { + PMD_DRV_LOG(ERR, "Can not parse 'start'."); + goto err; + } + js_mod->content.fields[i].start = start; + ret = cpfl_json_t_to_uint16(object, "width", &width); + if (ret < 0) { + PMD_DRV_LOG(ERR, "Can not parse 'width'."); + goto err; + } + js_mod->content.fields[i].width = width; + if (strcmp(type, "parameter") == 0) { + ret = cpfl_json_t_to_uint16(object, "index", &index); + if (ret < 0) { + PMD_DRV_LOG(ERR, "Can not parse 'index'."); + goto err; + } + js_mod->content.fields[i].index = index; + } else if (strcmp(type, "constant") == 0) { + json_t *ob_value, *subobj; + int value_len, j; + + ob_value = json_object_get(object, "value"); + value_len = json_array_size(ob_value); + for (j = 0; j < value_len; j++) { + subobj = json_array_get(ob_value, j); + js_mod->content.fields[i].value[j] = + (uint8_t)json_integer_value(subobj); + } + } + } + + return 0; + +err: + return -EINVAL; +} + static int cpfl_flow_js_mr_action(json_t *ob_mr_act, struct cpfl_flow_js_mr_action *js_mr_act) { @@ -695,7 +816,7 @@ cpfl_flow_js_mr_action(json_t *ob_mr_act, struct cpfl_flow_js_mr_action *js_mr_a /* mr->action->data */ ob_data = json_object_get(ob_mr_act, "data"); if (strcmp(type, "mod") == 0) { - json_t *ob_layouts; + json_t *ob_layouts, *ob_content; uint16_t profile = 0; int ret; @@ -712,6 +833,12 @@ cpfl_flow_js_mr_action(json_t *ob_mr_act, struct cpfl_flow_js_mr_action *js_mr_a PMD_DRV_LOG(ERR, "Can not parse layout."); return ret; } + ob_content = json_object_get(ob_data, "content"); + ret = cpfl_flow_js_mr_content(ob_content, &js_mr_act->mod); + if (ret < 0) { + PMD_DRV_LOG(ERR, "Can not parse 'content'."); + return ret; + } } else { PMD_DRV_LOG(ERR, "not support this type: %s.", type); return -EINVAL; @@ -862,7 +989,6 @@ cpfl_parser_destroy(struct cpfl_flow_js_parser *parser) struct cpfl_flow_js_mr *mr = &parser->modifications[i]; rte_free(mr->key.actions); - rte_free(mr->action.mod.layout); } rte_free(parser->modifications); rte_free(parser); @@ -1544,6 +1670,39 @@ cpfl_check_actions_vxlan_encap(struct cpfl_flow_mr_key_action_vxlan_encap *encap return 0; } +static int +cpfl_parse_check_prog_action(struct cpfl_flow_js_mr_key_action *key_act, + struct cpfl_flow_mr_key_action_prog *mr_key_prog, + const struct rte_flow_action_prog *prog) +{ + uint32_t k; + bool check_name; + + check_name = key_act->prog.has_name ? strcmp(prog->name, key_act->prog.name) == 0 + : atol(prog->name) == key_act->prog.id; + if (!check_name) { + PMD_DRV_LOG(ERR, "Not support this prog type: %s.", prog->name); + return -EINVAL; + } + if (key_act->prog.param_size != prog->args_num) + return -EINVAL; + for (k = 0; k < key_act->prog.param_size; k++) { + const struct rte_flow_action_prog_argument *arg = &prog->args[k]; + struct cpfl_flow_js_prog_parameter *param = &key_act->prog.params[k]; + + check_name = param->has_name ? strcmp(arg->name, param->name) == 0 + : atoi(arg->name) == param->index; + if (!check_name || arg->size != param->size) + return -EINVAL; + if (param->has_name) { + mr_key_prog->has_name = TRUE; + strncpy(mr_key_prog->name[param->index], param->name, strlen(param->name)); + } + } + + return 0; +} + /* check and parse */ static int cpfl_parse_mr_key_action(struct cpfl_flow_js_mr_key_action *key_acts, int size, @@ -1575,9 +1734,9 @@ cpfl_parse_mr_key_action(struct cpfl_flow_js_mr_key_action *key_acts, int size, } 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; + mr_key_action->mods[i].type = RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP; + mr_key_action->mods[i].encap.action = &actions[j]; + encap = &mr_key_action->mods[i].encap; proto_size = key_act->encap.proto_size; encap->proto_size = proto_size; @@ -1598,8 +1757,22 @@ cpfl_parse_mr_key_action(struct cpfl_flow_js_mr_key_action *key_acts, int size, } if (j >= actions_length) return -EINVAL; - mr_key_action[i].type = RTE_FLOW_ACTION_TYPE_VXLAN_DECAP; + mr_key_action->mods[i].type = RTE_FLOW_ACTION_TYPE_VXLAN_DECAP; j++; + } else if (type == RTE_FLOW_ACTION_TYPE_PROG) { + const struct rte_flow_action_prog *prog; + + while (j < actions_length && + actions[j].type != RTE_FLOW_ACTION_TYPE_PROG) { + j++; + } + if (j >= actions_length) + return -EINVAL; + prog = actions[j].conf; + mr_key_action->prog.prog = prog; + ret = cpfl_parse_check_prog_action(key_act, &mr_key_action->prog, prog); + if (ret < 0) + return -EINVAL; } else { PMD_DRV_LOG(ERR, "Not support this type: %d.", type); return -EPERM; @@ -1612,7 +1785,7 @@ cpfl_parse_mr_key_action(struct cpfl_flow_js_mr_key_action *key_acts, int size, /* 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, + struct cpfl_flow_mr_key_mod *mods, uint8_t *buffer, uint16_t *byte_len) { int i; @@ -1622,7 +1795,7 @@ cpfl_parse_layout(struct cpfl_flow_js_mr_layout *layouts, int layout_size, int index, size, offset; const char *hint; const uint8_t *addr = NULL; - struct cpfl_flow_mr_key_action *temp; + struct cpfl_flow_mr_key_mod *temp; struct cpfl_flow_js_mr_layout *layout; layout = &layouts[i]; @@ -1636,7 +1809,7 @@ cpfl_parse_layout(struct cpfl_flow_js_mr_layout *layouts, int layout_size, continue; } hint = layout->hint; - temp = mr_key_action + index; + temp = mods + 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; @@ -1685,6 +1858,51 @@ cpfl_parse_layout(struct cpfl_flow_js_mr_layout *layouts, int layout_size, return 0; } +static int +cpfl_parse_content(struct cpfl_flow_js_mr_content *content, + struct cpfl_flow_mr_key_action_prog *prog, uint8_t *buffer) +{ + int i, j; + + for (i = 0; i < content->field_size; i++) { + uint16_t start, width, shift_bit; + + start = content->fields[i].start / 8; + width = (content->fields[i].width + 7) / 8; + shift_bit = (8 - content->fields[i].start % 8 - content->fields[i].width % 8) % 8; + + for (j = 0; j < width; j++) { + uint8_t old_value = 0; + + if (strcmp(content->fields[i].type, "parameter") == 0) { + uint32_t k; + uint16_t index = content->fields[i].index; + const struct rte_flow_action_prog *act_prog = prog->prog; + + for (k = 0; k < act_prog->args_num; k++) { + const char *name = act_prog->args[k].name; + + if ((prog->has_name && + strcmp(prog->name[index], name) == 0) || + (!prog->has_name && atoi(name) == index)) { + old_value = act_prog->args[k].value[j]; + break; + } + } + if (k == act_prog->args_num) + return -EINVAL; + } else if (strcmp(content->fields[i].type, "constant") == 0) { + old_value = content->fields[i].value[j]; + } else { + return -EINVAL; + } + memset(buffer + start + j, buffer[start + j] | old_value << shift_bit, 1); + } + } + + return 0; +} + static int cpfl_parse_mr_action(struct cpfl_flow_js_mr_action *action, struct cpfl_flow_mr_key_action *mr_key_action, @@ -1695,6 +1913,18 @@ cpfl_parse_mr_action(struct cpfl_flow_js_mr_action *action, /* mr->action->type */ type = action->type; /* mr->action->data */ + if (action->mod.is_content) { + struct cpfl_flow_js_mr_content *content = &action->mod.content; + + mr_action->type = CPFL_JS_MR_ACTION_TYPE_MOD; + mr_action->mod.byte_len = 0; + mr_action->mod.prof = action->mod.prof; + mr_action->mod.byte_len = content->size; + memset(mr_action->mod.data, 0, sizeof(mr_action->mod.data)); + + return cpfl_parse_content(content, &mr_key_action->prog, mr_action->mod.data); + } + if (type == CPFL_JS_MR_ACTION_TYPE_MOD) { struct cpfl_flow_js_mr_layout *layout; @@ -1706,7 +1936,7 @@ cpfl_parse_mr_action(struct cpfl_flow_js_mr_action *action, 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, + return cpfl_parse_layout(layout, action->mod.layout_size, mr_key_action->mods, mr_action->mod.data, &mr_action->mod.byte_len); } PMD_DRV_LOG(ERR, "Not support this type: %d.", type); @@ -1731,7 +1961,7 @@ cpfl_parse_mod_rules(struct cpfl_flow_js_parser *parser, const struct rte_flow_a struct cpfl_flow_mr_action *mr_action) { int i; - struct cpfl_flow_mr_key_action mr_key_action[CPFL_MOD_KEY_NUM_MAX] = {0}; + struct cpfl_flow_mr_key_action mr_key_action = {0}; for (i = 0; i < parser->mr_size; i++) { int ret; @@ -1740,11 +1970,11 @@ cpfl_parse_mod_rules(struct cpfl_flow_js_parser *parser, const struct rte_flow_a mr = &parser->modifications[i]; if (!mr) return -EINVAL; - ret = cpfl_check_mod_key(mr, actions, mr_key_action); + 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 cpfl_parse_mr_action(&mr->action, &mr_key_action, mr_action); } return -EINVAL; diff --git a/drivers/net/cpfl/cpfl_flow_parser.h b/drivers/net/cpfl/cpfl_flow_parser.h index 962667adc2..c9a9772f13 100644 --- a/drivers/net/cpfl/cpfl_flow_parser.h +++ b/drivers/net/cpfl/cpfl_flow_parser.h @@ -13,6 +13,9 @@ #define CPFL_MAX_SEM_FV_KEY_SIZE 64 #define CPFL_FLOW_JS_PROTO_SIZE 16 #define CPFL_MOD_KEY_NUM_MAX 8 +#define CPFL_PROG_CONTENT_FIELD_NUM_MAX 64 +#define CPFL_PROG_CONSTANT_VALUE_NUM_MAX 8 +#define CPFL_PROG_PARAM_NUM_MAX 10 /* Pattern Rules Storage */ enum cpfl_flow_pr_action_type { @@ -117,11 +120,27 @@ struct cpfl_flow_js_mr_key_action_vxlan_encap { int proto_size; }; +struct cpfl_flow_js_prog_parameter { + bool has_name; + uint16_t index; + char name[CPFL_FLOW_JSON_STR_SIZE_MAX]; + uint16_t size; +}; + +struct cpfl_flow_js_mr_key_action_prog { + bool has_name; + uint32_t id; + char name[CPFL_FLOW_JSON_STR_SIZE_MAX]; + uint32_t param_size; + struct cpfl_flow_js_prog_parameter params[CPFL_PROG_PARAM_NUM_MAX]; +}; + /* 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_action_prog prog; }; }; @@ -137,6 +156,22 @@ struct cpfl_flow_js_mr_layout { uint16_t size; /* bytes of the data to be copied to the memory region */ }; +struct cpfl_flow_js_mr_field { + char type[CPFL_FLOW_JSON_STR_SIZE_MAX]; + uint16_t start; + uint16_t width; + union { + uint16_t index; + uint8_t value[CPFL_PROG_CONSTANT_VALUE_NUM_MAX]; + }; +}; + +struct cpfl_flow_js_mr_content { + uint16_t size; + struct cpfl_flow_js_mr_field fields[CPFL_PROG_CONTENT_FIELD_NUM_MAX]; + int field_size; +}; + /** 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. @@ -144,8 +179,14 @@ struct cpfl_flow_js_mr_layout { struct cpfl_flow_js_mr_action_mod { uint16_t prof; uint16_t byte_len; - struct cpfl_flow_js_mr_layout *layout; - int layout_size; + bool is_content; + union { + struct { + struct cpfl_flow_js_mr_layout layout[CPFL_FLOW_JS_PROTO_SIZE]; + int layout_size; + }; + struct cpfl_flow_js_mr_content content; + }; }; enum cpfl_flow_mr_action_type { @@ -203,11 +244,20 @@ struct cpfl_flow_mr_key_action_vxlan_encap { const struct rte_flow_action *action; }; -struct cpfl_flow_mr_key_action { +struct cpfl_flow_mr_key_action_prog { + const struct rte_flow_action_prog *prog; + bool has_name; + char name[CPFL_PROG_PARAM_NUM_MAX][CPFL_FLOW_JSON_STR_SIZE_MAX]; +}; + +struct cpfl_flow_mr_key_mod { enum rte_flow_action_type type; - union { - struct cpfl_flow_mr_key_action_vxlan_encap encap; - }; + struct cpfl_flow_mr_key_action_vxlan_encap encap; +}; + +struct cpfl_flow_mr_key_action { + struct cpfl_flow_mr_key_mod mods[CPFL_MOD_KEY_NUM_MAX]; + struct cpfl_flow_mr_key_action_prog prog; }; struct cpfl_flow_mr_action_mod {