From: Wenjing Qiao <wenjing.q...@intel.com>

To supporting P4-programmed network controller, reuse devargs
"flow_parser" to specify the path of a p4 context JSON configure
file. The cpfl PMD use the JSON configuration file to translate
rte_flow tokens into low level hardware representation.

Note, the p4 context JSON file is generated by the P4 compiler
and is intended to work exclusively with a specific P4 pipeline
configuration, which must be compiled and programmed into the hardware.

Signed-off-by: Wenjing Qiao <wenjing.q...@intel.com>
---
 drivers/net/cpfl/cpfl_ethdev.h          |    9 +-
 drivers/net/cpfl/cpfl_flow.c            |   10 +-
 drivers/net/cpfl/cpfl_flow_engine_fxp.c |    9 +-
 drivers/net/cpfl/cpfl_flow_parser.c     |   60 +-
 drivers/net/cpfl/cpfl_flow_parser.h     |    2 +-
 drivers/net/cpfl/cpfl_tdi_parser.c      | 1721 +++++++++++++++++++++++
 drivers/net/cpfl/cpfl_tdi_parser.h      |  294 ++++
 drivers/net/cpfl/meson.build            |    1 +
 8 files changed, 2084 insertions(+), 22 deletions(-)
 create mode 100644 drivers/net/cpfl/cpfl_tdi_parser.c
 create mode 100644 drivers/net/cpfl/cpfl_tdi_parser.h

diff --git a/drivers/net/cpfl/cpfl_ethdev.h b/drivers/net/cpfl/cpfl_ethdev.h
index 457db6d6be..e580f80f2f 100644
--- a/drivers/net/cpfl/cpfl_ethdev.h
+++ b/drivers/net/cpfl/cpfl_ethdev.h
@@ -185,6 +185,12 @@ struct cpfl_repr {
        bool func_up; /* If the represented function is up */
 };
 
+struct cpfl_flow_parser {
+       struct cpfl_flow_js_parser *fixed_parser;
+       struct cpfl_tdi_program *p4_parser;
+       bool is_p4_parser;
+};
+
 struct cpfl_metadata_chunk {
        int type;
        uint8_t data[CPFL_META_CHUNK_LENGTH];
@@ -218,8 +224,7 @@ struct cpfl_adapter_ext {
 
        rte_spinlock_t repr_lock;
        struct rte_hash *repr_allowlist_hash;
-
-       struct cpfl_flow_js_parser *flow_parser;
+       struct cpfl_flow_parser flow_parser;
        struct rte_bitmap *mod_bm;
        void *mod_bm_mem;
 
diff --git a/drivers/net/cpfl/cpfl_flow.c b/drivers/net/cpfl/cpfl_flow.c
index 3ba6c0f0e7..1c4131da2c 100644
--- a/drivers/net/cpfl/cpfl_flow.c
+++ b/drivers/net/cpfl/cpfl_flow.c
@@ -6,6 +6,7 @@
 
 #include "cpfl_flow.h"
 #include "cpfl_flow_parser.h"
+#include "cpfl_tdi_parser.h"
 
 TAILQ_HEAD(cpfl_flow_engine_list, cpfl_flow_engine);
 
@@ -331,9 +332,14 @@ cpfl_flow_init(struct cpfl_adapter_ext *ad, struct 
cpfl_devargs *devargs)
 void
 cpfl_flow_uninit(struct cpfl_adapter_ext *ad)
 {
-       if (ad->flow_parser == NULL)
+       if (ad->flow_parser.fixed_parser == NULL && ad->flow_parser.p4_parser 
== NULL)
                return;
 
-       cpfl_parser_destroy(ad->flow_parser);
+       if (ad->flow_parser.fixed_parser)
+               cpfl_parser_destroy(ad->flow_parser.fixed_parser);
+
+       if (ad->flow_parser.p4_parser)
+               cpfl_tdi_program_destroy(ad->flow_parser.p4_parser);
+
        cpfl_flow_engine_uninit(ad);
 }
diff --git a/drivers/net/cpfl/cpfl_flow_engine_fxp.c 
b/drivers/net/cpfl/cpfl_flow_engine_fxp.c
index 8a4e1419b4..f269ff97e1 100644
--- a/drivers/net/cpfl/cpfl_flow_engine_fxp.c
+++ b/drivers/net/cpfl/cpfl_flow_engine_fxp.c
@@ -503,20 +503,25 @@ cpfl_fxp_parse_pattern_action(struct rte_eth_dev *dev,
        struct cpfl_rule_info_meta *rim;
        int ret;
 
+       if (adapter->flow_parser.is_p4_parser)
+               return -EINVAL;
+
        ret = cpfl_fxp_get_metadata_port(itf, actions);
        if (!ret) {
                PMD_DRV_LOG(ERR, "Fail to save metadata.");
                return -EINVAL;
        }
 
-       ret = cpfl_flow_parse_items(itf, adapter->flow_parser, pattern, attr, 
&pr_action);
+       ret = cpfl_flow_parse_items(itf, adapter->flow_parser.fixed_parser, 
pattern, attr,
+                                   &pr_action);
        if (ret) {
                PMD_DRV_LOG(ERR, "No Match pattern support.");
                return -EINVAL;
        }
 
        if (cpfl_is_mod_action(actions)) {
-               ret = cpfl_flow_parse_actions(adapter->flow_parser, actions, 
mr_action);
+               ret = cpfl_flow_parse_actions(adapter->flow_parser.fixed_parser,
+                                             actions, mr_action);
                if (ret) {
                        PMD_DRV_LOG(ERR, "action parse fails.");
                        return -EINVAL;
diff --git a/drivers/net/cpfl/cpfl_flow_parser.c 
b/drivers/net/cpfl/cpfl_flow_parser.c
index a8f0488f21..e7f8a8a6cc 100644
--- a/drivers/net/cpfl/cpfl_flow_parser.c
+++ b/drivers/net/cpfl/cpfl_flow_parser.c
@@ -5,6 +5,7 @@
 #include <arpa/inet.h>
 
 #include "cpfl_flow_parser.h"
+#include "cpfl_tdi_parser.h"
 
 static enum rte_flow_item_type
 cpfl_get_item_type_by_str(const char *type)
@@ -938,36 +939,65 @@ cpfl_parser_init(json_t *ob_root, struct 
cpfl_flow_js_parser *parser)
        return 0;
 }
 
+static int
+cpfl_check_is_p4_mode(json_t *ob_root)
+{
+       return json_object_get(ob_root, "patterns") ? false : true;
+}
+
 int
-cpfl_parser_create(struct cpfl_flow_js_parser **flow_parser, const char 
*filename)
+cpfl_parser_create(struct cpfl_flow_parser *flow_parser, const char *filename)
 {
        struct cpfl_flow_js_parser *parser;
+       struct cpfl_tdi_program *prog;
        json_error_t json_error;
        json_t *root;
        int ret;
 
-       parser = rte_zmalloc("flow_parser", sizeof(struct cpfl_flow_js_parser), 
0);
-       if (!parser) {
-               PMD_DRV_LOG(ERR, "Not enough memory to create flow parser.");
-               return -ENOMEM;
-       }
        root = json_load_file(filename, 0, &json_error);
        if (!root) {
                PMD_DRV_LOG(ERR, "Bad JSON file \"%s\": %s", filename, 
json_error.text);
-               goto free_parser;
+               return -EINVAL;
        }
-       ret = cpfl_parser_init(root, parser);
-       if (ret < 0) {
-               PMD_DRV_LOG(ERR, "parser init failed.");
-               goto free_parser;
+
+       if (cpfl_check_is_p4_mode(root)) {
+               PMD_DRV_LOG(NOTICE, "flow parser mode is p4 mode.");
+               prog = rte_zmalloc("tdi_parser", sizeof(struct 
cpfl_tdi_program), 0);
+               if (prog == NULL) {
+                       PMD_DRV_LOG(ERR, "Failed to create program object.");
+                       return -ENOMEM;
+               }
+               ret = cpfl_tdi_program_create(root, prog);
+               if (ret != 0) {
+                       PMD_INIT_LOG(ERR, "Failed to create tdi program from 
file %s", filename);
+                       rte_free(prog);
+                       return -EINVAL;
+               }
+               flow_parser->p4_parser = prog;
+               flow_parser->fixed_parser = NULL;
+               flow_parser->is_p4_parser = true;
+       } else {
+               PMD_DRV_LOG(NOTICE, "flow parser mode is fixed function mode.");
+               parser = rte_zmalloc("flow_parser", sizeof(struct 
cpfl_flow_js_parser), 0);
+               if (!parser) {
+                       PMD_DRV_LOG(ERR, "Not enough memory to create flow 
parser.");
+                       return -ENOMEM;
+               }
+
+               ret = cpfl_parser_init(root, parser);
+               if (ret < 0) {
+                       PMD_DRV_LOG(ERR, "parser init failed.");
+                       rte_free(parser);
+                       return -EINVAL;
+               }
+               flow_parser->fixed_parser = parser;
+               flow_parser->p4_parser = NULL;
+               flow_parser->is_p4_parser = false;
        }
-       *flow_parser = parser;
+
        json_decref(root);
 
        return 0;
-free_parser:
-       rte_free(parser);
-       return -EINVAL;
 }
 
 static void
diff --git a/drivers/net/cpfl/cpfl_flow_parser.h 
b/drivers/net/cpfl/cpfl_flow_parser.h
index 23904e39f1..d420464d5c 100644
--- a/drivers/net/cpfl/cpfl_flow_parser.h
+++ b/drivers/net/cpfl/cpfl_flow_parser.h
@@ -273,7 +273,7 @@ struct cpfl_flow_mr_action {
        };
 };
 
-int cpfl_parser_create(struct cpfl_flow_js_parser **parser, const char 
*filename);
+int cpfl_parser_create(struct cpfl_flow_parser *flow_parser, const char 
*filename);
 int cpfl_parser_destroy(struct cpfl_flow_js_parser *parser);
 int cpfl_flow_parse_items(struct cpfl_itf *itf,
                          struct cpfl_flow_js_parser *parser,
diff --git a/drivers/net/cpfl/cpfl_tdi_parser.c 
b/drivers/net/cpfl/cpfl_tdi_parser.c
new file mode 100644
index 0000000000..f771e8a60a
--- /dev/null
+++ b/drivers/net/cpfl/cpfl_tdi_parser.c
@@ -0,0 +1,1721 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Intel Corporation
+ */
+
+#include "cpfl_tdi_parser.h"
+#include "base/idpf_osdep.h"
+
+static int
+cpfl_tdi_get_integer_obj(json_t *jobj, const char *key, int *output)
+{
+       json_t *int_obj = json_object_get(jobj, key);
+
+       if (int_obj == NULL) {
+               PMD_DRV_LOG(ERR, "Missing %s", key);
+               return -EINVAL;
+       }
+
+       if (!json_is_integer(int_obj)) {
+               PMD_DRV_LOG(ERR, "%s is not a integer object.", key);
+               return -EINVAL;
+       }
+
+       *output = json_integer_value(int_obj);
+
+       return 0;
+}
+
+static int
+cpfl_tdi_get_string_obj(json_t *jobj, const char *key, char *output)
+{
+       json_t *str_obj = json_object_get(jobj, key);
+
+       if (str_obj == NULL) {
+               PMD_DRV_LOG(ERR, "Missing %s", key);
+               return -EINVAL;
+       }
+
+       if (!json_is_string(str_obj)) {
+               PMD_DRV_LOG(ERR, "%s is not a string object.", key);
+               return -EINVAL;
+       }
+
+       strncpy(output, json_string_value(str_obj), CPFL_TDI_JSON_STR_SIZE_MAX 
- 1);
+
+       return 0;
+}
+
+static int
+cpfl_tdi_get_boolean_obj(json_t *jobj, const char *key, bool *output)
+{
+       json_t *bool_obj = json_object_get(jobj, key);
+
+       if (bool_obj == NULL) {
+               PMD_DRV_LOG(ERR, "Missing %s", key);
+               return -EINVAL;
+       }
+
+       if (!json_is_boolean(bool_obj)) {
+               PMD_DRV_LOG(ERR, "%s is not a boolean object.", key);
+               return -EINVAL;
+       }
+
+       *output = (bool)json_integer_value(bool_obj);
+
+       return 0;
+}
+
+static int
+cpfl_tdi_get_array_obj(json_t *jobj, const char *key, json_t **output)
+{
+       json_t *array_obj = json_object_get(jobj, key);
+
+       if (array_obj == NULL) {
+               PMD_DRV_LOG(ERR, "Missing %s", key);
+               return -EINVAL;
+       }
+
+       if (!json_is_array(array_obj)) {
+               PMD_DRV_LOG(ERR, "%s is not a array object.", key);
+               return -EINVAL;
+       }
+
+       *output = array_obj;
+
+       return 0;
+}
+
+static int
+cpfl_tdi_get_object_obj(json_t *jobj, const char *key, json_t **output)
+{
+       json_t *obj_obj = json_object_get(jobj, key);
+
+       if (obj_obj == NULL) {
+               PMD_DRV_LOG(ERR, "Missing %s", key);
+               return -EINVAL;
+       }
+
+       if (!json_is_object(obj_obj)) {
+               PMD_DRV_LOG(ERR, "%s is not a array object.", key);
+               return -EINVAL;
+       }
+
+       *output = obj_obj;
+
+       return 0;
+}
+
+static int
+cpfl_tdi_parse_table_type(json_t *root, struct cpfl_tdi_table *table)
+{
+       char tt[CPFL_TDI_JSON_STR_SIZE_MAX];
+       int ret;
+
+       ret = cpfl_tdi_get_string_obj(root, "table_type", tt);
+       if (ret != 0)
+               return -EINVAL;
+
+       if (!strcmp(tt, "match")) {
+               table->table_type = CPFL_TDI_TABLE_TYPE_MATCH;
+       } else if (!strcmp(tt, "match_value_lookup_table")) {
+               table->table_type = 
CPFL_TDI_TABLE_TYPE_MATCH_VALUE_LOOKUP_TABLE;
+       } else if (!strcmp(tt, "policer_meter")) {
+               table->table_type = CPFL_TDI_TABLE_TYPE_POLICER_METER;
+       } else {
+               PMD_DRV_LOG(ERR, "Unknown table type %s", tt);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int
+cpfl_tdi_parse_table_dir(json_t *root, struct cpfl_tdi_table *table)
+{
+       char dir[CPFL_TDI_JSON_STR_SIZE_MAX];
+       int ret;
+
+       ret = cpfl_tdi_get_string_obj(root, "direction", dir);
+       if (ret != 0)
+               return -EINVAL;
+
+       if (!strcmp(dir, "RX")) {
+               table->direction = CPFL_TDI_TABLE_DIR_RX;
+       } else if (!strcmp(dir, "TX")) {
+               table->direction = CPFL_TDI_TABLE_DIR_TX;
+       } else if (!strcmp(dir, "BIDIRECTIONAL")) {
+               table->direction = CPFL_TDI_TABLE_DIR_BI;
+       } else {
+               PMD_DRV_LOG(ERR, "Unknown direction type %s", dir);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int
+cpfl_tdi_parse_match_type(json_t *root, struct cpfl_tdi_match_key_field *mkf)
+{
+       char mt[CPFL_TDI_JSON_STR_SIZE_MAX];
+       int ret;
+
+       ret = cpfl_tdi_get_string_obj(root, "match_type", mt);
+       if (ret != 0)
+               return ret;
+
+       if (!strcmp(mt, "exact")) {
+               mkf->match_type = CPFL_TDI_MATCH_TYPE_EXACT;
+       } else if (!strcmp(mt, "selector")) {
+               mkf->match_type = CPFL_TDI_MATCH_TYPE_SELECTOR;
+       } else if (!strcmp(mt, "ternary")) {
+               mkf->match_type = CPFL_TDI_MATCH_TYPE_TERNARY;
+       } else if (!strcmp(mt, "lpm")) {
+               mkf->match_type = CPFL_TDI_MATCH_TYPE_LPM;
+       } else {
+               PMD_DRV_LOG(ERR, "Unsupported match type %s.", mt);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int
+cpfl_tdi_parse_match_key_field_obj(json_t *root, struct 
cpfl_tdi_match_key_field *mkf)
+{
+       int ret, val = 0;
+       char last3char[4];
+
+       ret = cpfl_tdi_get_string_obj(root, "name", mkf->name);
+       if (ret != 0)
+               return ret;
+
+       ret = cpfl_tdi_get_string_obj(root, "instance_name", 
mkf->instance_name);
+       if (ret != 0)
+               return ret;
+
+       ret = cpfl_tdi_get_string_obj(root, "field_name", mkf->field_name);
+       if (ret != 0)
+               return ret;
+       strncpy(last3char, mkf->field_name + strlen(mkf->field_name) - 3, 3);
+       last3char[3] = '\0';
+       if (!strcmp(last3char, "VSI") || !strcmp(last3char, "vsi"))
+               mkf->is_vsi = true;
+       else
+               mkf->is_vsi = false;
+
+       ret = cpfl_tdi_parse_match_type(root, mkf);
+       if (ret != 0)
+               return ret;
+
+       ret = cpfl_tdi_get_integer_obj(root, "bit_width", &val);
+       if (ret != 0)
+               return ret;
+
+       mkf->bit_width = (uint16_t)val;
+
+       ret = cpfl_tdi_get_integer_obj(root, "index", &val);
+       if (ret != 0)
+               return ret;
+
+       mkf->index = (uint32_t)val;
+
+       ret = cpfl_tdi_get_integer_obj(root, "position", &val);
+       if (ret != 0)
+               return ret;
+
+       mkf->position = (uint32_t)val;
+
+       return 0;
+}
+
+static int
+cpfl_tdi_parse_match_key_fields(json_t *root, struct cpfl_tdi_table *table)
+{
+       int ret;
+       int array_len = json_array_size(root);
+
+       if (array_len == 0)
+               return 0;
+
+       table->match_key_field_num = (uint16_t)array_len;
+       table->match_key_fields =
+           rte_zmalloc(NULL, sizeof(struct cpfl_tdi_match_key_field) * 
array_len, 0);
+       if (table->match_key_fields == NULL) {
+               PMD_DRV_LOG(ERR, "Failed to create match key field array.");
+               return -ENOMEM;
+       }
+
+       for (int i = 0; i < array_len; i++) {
+               json_t *mkf_object = json_array_get(root, i);
+
+               ret = cpfl_tdi_parse_match_key_field_obj(mkf_object, 
&table->match_key_fields[i]);
+               if (ret != 0)
+                       return ret;
+       }
+
+       return 0;
+}
+
+static int
+cpfl_tdi_parse_byte_order(json_t *root, struct cpfl_tdi_match_key_format *mkf)
+{
+       char bo[CPFL_TDI_JSON_STR_SIZE_MAX];
+       int ret;
+
+       ret = cpfl_tdi_get_string_obj(root, "byte_order", bo);
+       if (ret != 0)
+               return -EINVAL;
+
+       if (!strcmp(bo, "HOST")) {
+               mkf->byte_order = CPFL_TDI_BYTE_ORDER_HOST;
+       } else if (!strcmp(bo, "NETWORK")) {
+               mkf->byte_order = CPFL_TDI_BYTE_ORDER_NETWORK;
+       } else {
+               PMD_DRV_LOG(ERR, "Unknown byte order type %s", bo);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int
+cpfl_tdi_parse_match_key_format_obj(json_t *root, struct 
cpfl_tdi_match_key_format *mkf)
+{
+       int ret, val = 0;
+
+       ret = cpfl_tdi_get_integer_obj(root, "match_key_handle", &val);
+       if (ret != 0)
+               return ret;
+
+       mkf->match_key_handle = (uint32_t)val;
+
+       ret = cpfl_tdi_parse_byte_order(root, mkf);
+       if (ret != 0)
+               return ret;
+
+       ret = cpfl_tdi_get_integer_obj(root, "byte_array_index", &val);
+       if (ret != 0)
+               return ret;
+
+       mkf->byte_array_index = (uint16_t)val;
+
+       ret = cpfl_tdi_get_integer_obj(root, "start_bit_offset", &val);
+       if (ret != 0)
+               return ret;
+
+       mkf->start_bit_offset = (uint16_t)val;
+
+       ret = cpfl_tdi_get_integer_obj(root, "bit_width", &val);
+       if (ret != 0)
+               return ret;
+
+       mkf->bit_width = (uint16_t)val;
+
+       return 0;
+}
+
+static int
+cpfl_tdi_parse_match_key_format_array(json_t *root, struct cpfl_tdi_table 
*table)
+{
+       int ret;
+       int array_len = json_array_size(root);
+
+       if (array_len == 0)
+               return 0;
+
+       table->match_key_format_num = (uint16_t)array_len;
+       table->match_key_format =
+           rte_zmalloc(NULL, sizeof(struct cpfl_tdi_match_key_format) * 
array_len, 0);
+       if (table->match_key_format == NULL) {
+               PMD_DRV_LOG(ERR, "Failed to create match key format array.");
+               return -ENOMEM;
+       }
+
+       for (int i = 0; i < array_len; i++) {
+               json_t *mkf_object = json_array_get(root, i);
+
+               ret = cpfl_tdi_parse_match_key_format_obj(mkf_object, 
&table->match_key_format[i]);
+               if (ret != 0)
+                       return ret;
+       }
+
+       return 0;
+}
+
+static int
+cpfl_tdi_parse_p4_parameter_obj(json_t *root, struct cpfl_tdi_p4_parameter 
*param)
+{
+       int ret, val = 0;
+
+       ret = cpfl_tdi_get_string_obj(root, "name", param->name);
+       if (ret != 0)
+               return ret;
+
+       ret = cpfl_tdi_get_integer_obj(root, "bit_width", &val);
+       if (ret != 0)
+               return ret;
+
+       param->bit_width = (uint16_t)val;
+
+       return 0;
+}
+
+static int
+cpfl_tdi_parse_p4_parameters(json_t *root, struct cpfl_tdi_action *act)
+{
+       int ret;
+       int array_len = json_array_size(root);
+
+       if (array_len == 0)
+               return 0;
+
+       act->p4_parameter_num = (uint16_t)array_len;
+       act->p4_parameters = rte_zmalloc(NULL, sizeof(struct 
cpfl_tdi_p4_parameter) * array_len, 0);
+       if (act->p4_parameters == NULL) {
+               PMD_DRV_LOG(ERR, "Failed to create p4 parameter array.");
+               return -ENOMEM;
+       }
+
+       for (int i = 0; i < array_len; i++) {
+               json_t *pp_object = json_array_get(root, i);
+
+               ret = cpfl_tdi_parse_p4_parameter_obj(pp_object, 
&act->p4_parameters[i]);
+               if (ret != 0)
+                       return ret;
+       }
+
+       return 0;
+}
+
+static int
+cpfl_tdi_parse_action_obj(json_t *root, struct cpfl_tdi_action *act)
+{
+       int ret, val = 0;
+       json_t *jobj = NULL;
+
+       ret = cpfl_tdi_get_string_obj(root, "name", act->name);
+       if (ret != 0)
+               return ret;
+
+       ret = cpfl_tdi_get_integer_obj(root, "handle", &val);
+       if (ret != 0)
+               return ret;
+
+       act->handle = (uint32_t)val;
+
+       ret = cpfl_tdi_get_boolean_obj(root, "constant_default_action",
+                                      &act->constant_default_action);
+       if (ret != 0)
+               return ret;
+
+       ret = cpfl_tdi_get_boolean_obj(root, "is_compiler_added_action",
+                                      &act->is_compiler_added_action);
+       if (ret != 0)
+               return ret;
+
+       ret = cpfl_tdi_get_boolean_obj(root, "allowed_as_hit_action", 
&act->allowed_as_hit_action);
+       if (ret != 0)
+               return ret;
+
+       ret = cpfl_tdi_get_boolean_obj(root, "allowed_as_default_action",
+                                      &act->allowed_as_default_action);
+       if (ret != 0)
+               return ret;
+
+       ret = cpfl_tdi_get_array_obj(root, "p4_parameters", &jobj);
+       if (ret != 0)
+               return ret;
+
+       return cpfl_tdi_parse_p4_parameters(jobj, act);
+}
+
+static int
+cpfl_tdi_parse_actions(json_t *root, struct cpfl_tdi_table *table)
+{
+       int ret;
+       int array_len = json_array_size(root);
+
+       if (array_len == 0)
+               return 0;
+
+       table->action_num = (uint16_t)array_len;
+       table->actions = rte_zmalloc(NULL, sizeof(struct cpfl_tdi_action) * 
array_len, 0);
+       if (table->actions == NULL) {
+               PMD_DRV_LOG(ERR, "Failed to create action array.");
+               return -ENOMEM;
+       }
+
+       for (int i = 0; i < array_len; i++) {
+               json_t *act_object = json_array_get(root, i);
+
+               ret = cpfl_tdi_parse_action_obj(act_object, &table->actions[i]);
+               if (ret != 0)
+                       return ret;
+       }
+
+       return 0;
+}
+
+static int
+cpfl_tdi_parse_ma_hw_block(json_t *root, struct cpfl_tdi_ma_hardware_block *hb)
+{
+       char name[CPFL_TDI_JSON_STR_SIZE_MAX];
+       int ret;
+
+       ret = cpfl_tdi_get_string_obj(root, "name", name);
+       if (ret != 0)
+               return -EINVAL;
+
+       if (!strcmp(name, "SEM")) {
+               hb->hw_block = CPFL_TDI_HW_BLOCK_SEM;
+       } else if (!strcmp(name, "LEM")) {
+               hb->hw_block = CPFL_TDI_HW_BLOCK_LEM;
+       } else if (!strcmp(name, "WCM")) {
+               hb->hw_block = CPFL_TDI_HW_BLOCK_WCM;
+       } else if (!strcmp(name, "LPM")) {
+               hb->hw_block = CPFL_TDI_HW_BLOCK_LPM;
+       } else if (!strcmp(name, "MOD")) {
+               hb->hw_block = CPFL_TDI_HW_BLOCK_MOD;
+       } else if (!strcmp(name, "HASH")) {
+               hb->hw_block = CPFL_TDI_HW_BLOCK_HASH;
+       } else if (!strcmp(name, "RC")) {
+               hb->hw_block = CPFL_TDI_HW_BLOCK_RC;
+       } else if (!strcmp(name, "CXP_LEM")) {
+               hb->hw_block = CPFL_TDI_HW_BLOCK_CXP_LEM;
+       } else if (!strcmp(name, "METER")) {
+               hb->hw_block = CPFL_TDI_HW_BLOCK_METER;
+       } else {
+               PMD_DRV_LOG(ERR, "Unknown hardware block type %s", name);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int
+cpfl_tdi_parse_profiles(json_t *root, struct cpfl_tdi_ma_hardware_block *hb)
+{
+       int array_len = json_array_size(root);
+
+       if (array_len > 16) {
+               PMD_DRV_LOG(ERR, "Profile array out of bound: %d.", array_len);
+               return -EINVAL;
+       }
+
+       if (array_len == 0)
+               return 0;
+
+       hb->profile_num = (uint16_t)array_len;
+       for (int i = 0; i < array_len; i++) {
+               int val;
+               json_t *int_obj = json_array_get(root, i);
+
+               if (!json_is_integer(int_obj)) {
+                       PMD_DRV_LOG(ERR, "Invalid profile id, not an integer.");
+                       return -EINVAL;
+               }
+               val = json_integer_value(int_obj);
+               hb->profile[i] = (uint8_t)val;
+       }
+
+       return 0;
+}
+
+static int
+cpfl_tdi_parse_immediate_field_obj(json_t *root, struct 
cpfl_tdi_immediate_field *imf)
+{
+       int ret, val = 0;
+
+       ret = cpfl_tdi_get_string_obj(root, "param_name", imf->param_name);
+       if (ret != 0)
+               return ret;
+
+       ret = cpfl_tdi_get_integer_obj(root, "param_handle", &val);
+       if (ret != 0)
+               return ret;
+
+       imf->param_handle = (uint32_t)val;
+
+       ret = cpfl_tdi_get_integer_obj(root, "dest_start", &val);
+       if (ret != 0)
+               return ret;
+
+       imf->dest_start = (uint16_t)val;
+       if (json_object_get(root, "start_bit_offset")) {
+               ret = cpfl_tdi_get_integer_obj(root, "start_bit_offset", &val);
+               if (ret != 0)
+                       return ret;
+
+               imf->start_bit_offset = (uint16_t)val;
+       }
+
+       ret = cpfl_tdi_get_integer_obj(root, "dest_width", &val);
+       if (ret != 0)
+               return ret;
+
+       imf->dest_width = (uint16_t)val;
+
+       return 0;
+}
+
+static int
+cpfl_tdi_parse_af_immediate_fields(json_t *root, struct cpfl_tdi_action_format 
*af)
+{
+       int ret;
+       int array_len = json_array_size(root);
+
+       if (array_len == 0)
+               return 0;
+
+       af->immediate_field_num = (uint16_t)array_len;
+       af->immediate_fields =
+           rte_zmalloc(NULL, sizeof(struct cpfl_tdi_immediate_field) * 
array_len, 0);
+       if (af->immediate_fields == NULL) {
+               PMD_DRV_LOG(ERR, "Failed to immediate field array.");
+               return -ENOMEM;
+       }
+
+       for (int i = 0; i < array_len; i++) {
+               json_t *if_object = json_array_get(root, i);
+
+               ret = cpfl_tdi_parse_immediate_field_obj(if_object, 
&af->immediate_fields[i]);
+               if (ret != 0)
+                       return ret;
+       }
+
+       return 0;
+}
+
+static int
+cpfl_tdi_parse_mod_field_type(json_t *root, struct cpfl_tdi_mod_field *mf)
+{
+       char t[CPFL_TDI_JSON_STR_SIZE_MAX];
+       int ret;
+       int val = 0;
+
+       ret = cpfl_tdi_get_string_obj(root, "type", t);
+       if (ret != 0)
+               return ret;
+
+       if (!strcmp("parameter", t)) {
+               mf->type = CPFL_TDI_MOD_FIELD_TYPE_PARAMETER;
+               ret = cpfl_tdi_get_integer_obj(root, "param_handle", &val);
+               if (ret != 0)
+                       return ret;
+               mf->param_handle = (uint32_t)val;
+       } else if (!strcmp("constant", t)) {
+               mf->type = CPFL_TDI_MOD_FIELD_TYPE_CONSTANT;
+       } else {
+               PMD_DRV_LOG(ERR, "Unknown mod field type %s.", t);
+       }
+
+       return 0;
+}
+
+static int
+cpfl_tdi_parse_mod_field_byte_order(json_t *root, struct cpfl_tdi_mod_field 
*mf)
+{
+       char bo[CPFL_TDI_JSON_STR_SIZE_MAX];
+       int ret;
+
+       ret = cpfl_tdi_get_string_obj(root, "byte_order", bo);
+       if (ret != 0)
+               return ret;
+
+       if (!strcmp("HOST", bo))
+               mf->byte_order = CPFL_TDI_BYTE_ORDER_HOST;
+       else if (!strcmp("NETWORK", bo))
+               mf->byte_order = CPFL_TDI_BYTE_ORDER_NETWORK;
+       else
+               PMD_DRV_LOG(ERR, "Unknown byte order type %s.", bo);
+
+       return 0;
+}
+
+static int
+cpfl_tdi_parse_mod_field_value(json_t *root, struct cpfl_tdi_mod_field *mf)
+{
+       int array_len = json_array_size(root);
+
+       if (array_len == 0)
+               return 0;
+
+       if (array_len > CPFL_TDI_VALUE_SIZE_MAX) {
+               PMD_DRV_LOG(ERR, "Value array out of bound.");
+               return -EINVAL;
+       }
+
+       mf->value_size = (uint16_t)array_len;
+       for (int i = 0; i < array_len; i++) {
+               int val;
+               json_t *val_obj = json_array_get(root, i);
+
+               if (!json_is_integer(val_obj)) {
+                       PMD_DRV_LOG(ERR, "Invalid value item, not an integer.");
+                       return -EINVAL;
+               }
+               val = json_integer_value(val_obj);
+               mf->value[i] = (uint8_t)val;
+       }
+
+       return 0;
+}
+
+static int
+cpfl_tdi_parse_mod_field_obj(json_t *root, struct cpfl_tdi_mod_field *mf)
+{
+       json_t *jobj = NULL;
+       int ret, val = 0;
+
+       ret = cpfl_tdi_get_string_obj(root, "name", mf->name);
+       if (ret != 0)
+               return ret;
+
+       ret = cpfl_tdi_get_integer_obj(root, "handle", &val);
+       if (ret != 0)
+               return ret;
+
+       mf->handle = (uint32_t)val;
+
+       ret = cpfl_tdi_parse_mod_field_type(root, mf);
+       if (ret != 0)
+               return ret;
+
+       ret = cpfl_tdi_parse_mod_field_byte_order(root, mf);
+       if (ret != 0)
+               return ret;
+
+       ret = cpfl_tdi_get_integer_obj(root, "byte_array_index", &val);
+       if (ret != 0)
+               return ret;
+
+       mf->byte_array_index = (uint16_t)val;
+
+       ret = cpfl_tdi_get_integer_obj(root, "start_bit_offset", &val);
+       if (ret != 0)
+               return ret;
+
+       mf->start_bit_offset = (uint16_t)val;
+
+       ret = cpfl_tdi_get_integer_obj(root, "bit_width", &val);
+       if (ret != 0)
+               return ret;
+
+       mf->bit_width = (uint16_t)val;
+
+       ret = cpfl_tdi_get_array_obj(root, "value", &jobj);
+       if (ret != 0)
+               return ret;
+
+       ret = cpfl_tdi_parse_mod_field_value(jobj, mf);
+       if (ret != 0)
+               return ret;
+
+       return 0;
+}
+
+static int
+cpfl_tdi_parse_mod_fields(json_t *root, struct cpfl_tdi_mod_content_format 
*mcf)
+{
+       int ret;
+       int array_len = json_array_size(root);
+
+       if (array_len == 0)
+               return 0;
+
+       mcf->mod_field_num = (uint16_t)array_len;
+       mcf->mod_fields = rte_zmalloc(NULL, sizeof(struct cpfl_tdi_mod_field) * 
array_len, 0);
+       if (mcf->mod_fields == NULL) {
+               PMD_DRV_LOG(ERR, "Failed to create mod field array.");
+               return -ENOMEM;
+       }
+
+       for (int i = 0; i < array_len; i++) {
+               json_t *mf_object = json_array_get(root, i);
+
+               ret = cpfl_tdi_parse_mod_field_obj(mf_object, 
&mcf->mod_fields[i]);
+               if (ret != 0)
+                       return ret;
+       }
+
+       return 0;
+}
+
+static int
+cpfl_tdi_parse_mod_content_format(json_t *root, struct 
cpfl_tdi_mod_content_format *mcf)
+{
+       json_t *jobj = NULL;
+       int ret, val = 0;
+
+       if (json_object_get(root, "mod_profile")) {
+               ret = cpfl_tdi_get_integer_obj(root, "mod_profile", &val);
+               if (ret != 0)
+                       return ret;
+               mcf->mod_profile = (uint16_t)val;
+       } else if (json_object_get(root, "mod_lut_num")) {
+               ret = cpfl_tdi_get_integer_obj(root, "mod_lut_num", &val);
+               if (ret != 0)
+                       return ret;
+               mcf->mod_lut_num = (uint16_t)val;
+       } else {
+               PMD_DRV_LOG(ERR, "Failed to parse mod_content_format.");
+               return -EINVAL;
+       }
+
+       ret = cpfl_tdi_get_integer_obj(root, "mod_obj_size", &val);
+       if (ret != 0)
+               return ret;
+
+       mcf->mod_obj_size = (uint16_t)val;
+
+       if (json_object_get(root, "mod_fields") != NULL) {
+               ret = cpfl_tdi_get_array_obj(root, "mod_fields", &jobj);
+               if (ret != 0)
+                       return ret;
+
+               return cpfl_tdi_parse_mod_fields(jobj, mcf);
+       }
+
+       return 0;
+}
+
+static int
+cpfl_tdi_pparse_action_code(json_t *root, struct cpfl_tdi_hw_action *ha)
+{
+       char ac[CPFL_TDI_JSON_STR_SIZE_MAX];
+       int ret;
+
+       ret = cpfl_tdi_get_string_obj(root, "action_code", ac);
+       if (ret != 0)
+               return -EINVAL;
+
+       if (!strcmp(ac, "SET10_1b")) {
+               ha->action_code = CPFL_TDI_ACTION_CODE_SET10_1b;
+       } else if (!strcmp(ac, "SET1_16b")) {
+               ha->action_code = CPFL_TDI_ACTION_CODE_SET1_16b;
+       } else if (!strcmp(ac, "SET1A_24b")) {
+               ha->action_code = CPFL_TDI_ACTION_CODE_SET1A_24b;
+       } else if (!strcmp(ac, "SET1B_24b")) {
+               ha->action_code = CPFL_TDI_ACTION_CODE_SET1B_24b;
+       } else if (!strcmp(ac, "SET2_8b")) {
+               ha->action_code = CPFL_TDI_ACTION_CODE_SET2_8b;
+       } else if (!strcmp(ac, "NOP")) {
+               ha->action_code = CPFL_TDI_ACTION_CODE_NOP;
+       } else if (!strcmp(ac, "AUX_DATA")) {
+               ha->action_code = CPFL_TDI_ACTION_CODE_AUX_DATA;
+       } else {
+               PMD_DRV_LOG(ERR, "Unknown action code type %s", ac);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int
+cpfl_tdi_parse_setmd_action_code(json_t *root, struct cpfl_tdi_hw_action *ha)
+{
+       char ac[CPFL_TDI_JSON_STR_SIZE_MAX];
+       int ret;
+
+       /* allow no value */
+       if (json_object_get(root, "setmd_action_code") == NULL) {
+               ha->setmd_action_code = CPFL_TDI_SETMD_ACTION_CODE_NONE;
+               return 0;
+       }
+
+       ret = cpfl_tdi_get_string_obj(root, "setmd_action_code", ac);
+       if (ret != 0)
+               return -EINVAL;
+
+       if (!strcmp(ac, "SET_8b")) {
+               ha->setmd_action_code = CPFL_TDI_SETMD_ACTION_CODE_SET_8b;
+       } else if (!strcmp(ac, "SET_16b")) {
+               ha->setmd_action_code = CPFL_TDI_SETMD_ACTION_CODE_SET_16b;
+       } else if (!strcmp(ac, "SET_32b_AUX")) {
+               ha->setmd_action_code = CPFL_TDI_SETMD_ACTION_CODE_SET_32b_AUX;
+       } else {
+               PMD_DRV_LOG(ERR, "Unknown setmd action code type %s", ac);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int
+cpfl_tdi_parse_hw_action_parameter_obj(json_t *root, struct 
cpfl_tdi_hw_action_parameter *param)
+{
+       int ret, val = 0;
+
+       ret = cpfl_tdi_get_string_obj(root, "param_name", param->param_name);
+       if (ret != 0)
+               return ret;
+
+       ret = cpfl_tdi_get_integer_obj(root, "param_handle", &val);
+       if (ret != 0)
+               return ret;
+
+       param->param_handle = (uint32_t)val;
+
+       return 0;
+}
+
+static int
+cpfl_tdi_parse_hw_action_parameters(json_t *root, struct cpfl_tdi_hw_action 
*ha)
+{
+       int ret;
+       int array_len = json_array_size(root);
+
+       if (array_len == 0)
+               return 0;
+
+       ha->parameter_num = (uint16_t)array_len;
+       ha->parameters =
+           rte_zmalloc(NULL, sizeof(struct cpfl_tdi_hw_action_parameter) * 
array_len, 0);
+       if (ha->parameters == NULL) {
+               PMD_DRV_LOG(ERR, "Failed to create hw action parameter array.");
+               return -ENOMEM;
+       }
+
+       for (int i = 0; i < array_len; i++) {
+               json_t *p_object = json_array_get(root, i);
+
+               ret = cpfl_tdi_parse_hw_action_parameter_obj(p_object, 
&ha->parameters[i]);
+               if (ret != 0)
+                       return ret;
+       }
+
+       return 0;
+}
+
+static int
+cpfl_tdi_parse_hw_action_obj(json_t *root, struct cpfl_tdi_hw_action *ha)
+{
+       int ret, val = 0;
+       json_t *jobj = NULL;
+
+       ret = cpfl_tdi_get_integer_obj(root, "prec", &val);
+       if (ret != 0)
+               return ret;
+
+       ha->prec = (uint16_t)val;
+
+       ret = cpfl_tdi_pparse_action_code(root, ha);
+       if (ret != 0)
+               return ret;
+
+       ret = cpfl_tdi_parse_setmd_action_code(root, ha);
+       if (ret != 0)
+               return ret;
+
+       ret = cpfl_tdi_get_integer_obj(root, "index", &val);
+       if (ret != 0)
+               return ret;
+
+       ha->index = (uint32_t)val;
+
+       if (json_object_get(root, "mod_profile") != NULL) {
+               ret = cpfl_tdi_get_integer_obj(root, "mod_profile", &val);
+               if (ret != 0)
+                       return ret;
+               ha->mod_profile = (uint16_t)val;
+       }
+
+       if (json_object_get(root, "prefetch") != NULL) {
+               ret = cpfl_tdi_get_integer_obj(root, "prefetch", &val);
+               if (ret != 0)
+                       return ret;
+               ha->prefetch = (uint16_t)val;
+       }
+
+       if (json_object_get(root, "parameters") != NULL) {
+               ret = cpfl_tdi_get_array_obj(root, "parameters", &jobj);
+               if (ret != 0)
+                       return ret;
+
+               ret = cpfl_tdi_parse_hw_action_parameters(jobj, ha);
+               if (ret != 0)
+                       return ret;
+       }
+
+       if (json_object_get(root, "p4_ref_action_handle")) {
+               ret = cpfl_tdi_get_integer_obj(root, "p4_ref_action_handle", 
&val);
+               if (ret != 0)
+                       return ret;
+               ha->p4_ref_action_handle = (uint32_t)val;
+       }
+
+       if (json_object_get(root, "p4_ref_table_handle")) {
+               ret = cpfl_tdi_get_integer_obj(root, "p4_ref_table_handle", 
&val);
+               if (ret != 0)
+                       return ret;
+               ha->p4_ref_table_handle = (uint32_t)val;
+       }
+
+       if (json_object_get(root, "value")) {
+               ret = cpfl_tdi_get_integer_obj(root, "value", &val);
+               if (ret != 0)
+                       return ret;
+               ha->value = (uint16_t)val;
+       }
+
+       if (json_object_get(root, "mask")) {
+               ret = cpfl_tdi_get_integer_obj(root, "mask", &val);
+               if (ret != 0)
+                       return ret;
+               ha->mask = (uint16_t)val;
+       }
+
+       if (json_object_get(root, "type_id")) {
+               ret = cpfl_tdi_get_integer_obj(root, "type_id", &val);
+               if (ret != 0)
+                       return ret;
+               ha->type_id = (uint16_t)val;
+       }
+
+       if (json_object_get(root, "offset")) {
+               ret = cpfl_tdi_get_integer_obj(root, "offset", &val);
+               if (ret != 0)
+                       return ret;
+               ha->offset = (uint16_t)val;
+       }
+
+       return 0;
+}
+
+static int
+cpfl_tdi_parse_hw_actions_list(json_t *root, struct cpfl_tdi_action_format *af)
+{
+       int ret;
+       int array_len = json_array_size(root);
+
+       if (array_len == 0)
+               return 0;
+
+       af->hw_action_num = (uint16_t)array_len;
+       af->hw_actions_list = rte_zmalloc(NULL, sizeof(struct 
cpfl_tdi_hw_action) * array_len, 0);
+       if (af->hw_actions_list == NULL) {
+               PMD_DRV_LOG(ERR, "Failed to create hw action array.");
+               return -ENOMEM;
+       }
+
+       for (int i = 0; i < array_len; i++) {
+               json_t *ha_object = json_array_get(root, i);
+
+               ret = cpfl_tdi_parse_hw_action_obj(ha_object, 
&af->hw_actions_list[i]);
+               if (ret != 0)
+                       return ret;
+       }
+
+       return 0;
+}
+
+static int
+cpfl_tdi_parse_action_format_obj(json_t *root, struct cpfl_tdi_action_format 
*af)
+{
+       int ret, val = 0;
+       json_t *jobj = NULL;
+
+       ret = cpfl_tdi_get_string_obj(root, "action_name", af->action_name);
+       if (ret != 0)
+               return ret;
+
+       ret = cpfl_tdi_get_integer_obj(root, "action_handle", &val);
+       if (ret != 0)
+               return ret;
+
+       af->action_handle = (uint32_t)val;
+
+       ret = cpfl_tdi_get_array_obj(root, "immediate_fields", &jobj);
+       if (ret != 0)
+               return ret;
+
+       ret = cpfl_tdi_parse_af_immediate_fields(jobj, af);
+       if (ret != 0)
+               return ret;
+
+       jobj = json_object_get(root, "mod_content_format");
+       if (jobj != NULL) {
+               ret = cpfl_tdi_parse_mod_content_format(jobj, 
&af->mod_content_format);
+               if (ret != 0)
+                       return ret;
+       }
+
+       ret = cpfl_tdi_get_array_obj(root, "hw_actions_list", &jobj);
+       if (ret != 0)
+               return ret;
+
+       return cpfl_tdi_parse_hw_actions_list(jobj, af);
+}
+
+static int
+cpfl_tdi_parse_action_format_array(json_t *root, struct 
cpfl_tdi_ma_hardware_block *hb)
+{
+       int ret;
+       int array_len = json_array_size(root);
+
+       if (array_len == 0)
+               return 0;
+
+       hb->action_format_num = (uint16_t)array_len;
+       hb->action_format = rte_zmalloc(NULL, sizeof(struct 
cpfl_tdi_action_format) * array_len, 0);
+       if (hb->action_format == NULL) {
+               PMD_DRV_LOG(ERR, "Failed to create action format array.");
+               return -ENOMEM;
+       }
+
+       for (int i = 0; i < array_len; i++) {
+               json_t *af_object = json_array_get(root, i);
+
+               ret = cpfl_tdi_parse_action_format_obj(af_object, 
&hb->action_format[i]);
+               if (ret != 0)
+                       return ret;
+       }
+
+       return 0;
+}
+
+static int
+cpfl_tdi_parse_act_rams(json_t *root, struct cpfl_tdi_wcm_params *wm)
+{
+       int array_len = json_array_size(root);
+
+       if (array_len == 0)
+               return 0;
+
+       if (array_len > 16) {
+               PMD_DRV_LOG(ERR, "Action ram array out of bound.");
+               return -EINVAL;
+       }
+
+       for (int i = 0; i < array_len; i++) {
+               int val;
+               json_t *am_obj = json_array_get(root, i);
+
+               if (!json_is_integer(am_obj)) {
+                       PMD_DRV_LOG(ERR, "Invalid action ram index, not an 
integer.");
+                       return -EINVAL;
+               }
+               val = json_integer_value(am_obj);
+               wm->act_rams[i] = (uint8_t)val;
+       }
+
+       return 0;
+}
+
+static int
+cpfl_tdi_parse_wcm_params(json_t *root, struct cpfl_tdi_wcm_params *wm)
+{
+       int ret, val = 0;
+       json_t *jobj = NULL;
+
+       ret = cpfl_tdi_get_integer_obj(root, "wcm_group", &val);
+       if (ret != 0)
+               return ret;
+
+       wm->wcm_group = (uint16_t)val;
+
+       ret = cpfl_tdi_get_integer_obj(root, "slice_start_idx", &val);
+       if (ret != 0)
+               return ret;
+
+       wm->slice_start_idx = (uint16_t)val;
+
+       ret = cpfl_tdi_get_integer_obj(root, "table_width", &val);
+       if (ret != 0)
+               return ret;
+
+       wm->table_width = (uint16_t)val;
+
+       ret = cpfl_tdi_get_integer_obj(root, "entry_cnt", &val);
+       if (ret != 0)
+               return ret;
+
+       wm->entry_cnt = (uint16_t)val;
+
+       ret = cpfl_tdi_get_integer_obj(root, "entry_idx", &val);
+       if (ret != 0)
+               return ret;
+
+       wm->entry_idx = (uint16_t)val;
+
+       ret = cpfl_tdi_get_array_obj(root, "act_rams", &jobj);
+       if (ret != 0)
+               return ret;
+
+       return cpfl_tdi_parse_act_rams(jobj, wm);
+}
+
+static int
+cpfl_tdi_parse_hb_immediate_fields(json_t *root, struct 
cpfl_tdi_ma_hardware_block *hb)
+{
+       int ret;
+       int array_len = json_array_size(root);
+
+       if (array_len == 0)
+               return 0;
+
+       hb->meter.immediate_field_num = (uint16_t)array_len;
+       hb->meter.immediate_fields =
+           rte_zmalloc(NULL, sizeof(struct cpfl_tdi_immediate_field) * 
array_len, 0);
+       if (hb->meter.immediate_fields == NULL) {
+               PMD_DRV_LOG(ERR, "Failed to immediate field array.");
+               return -ENOMEM;
+       }
+
+       for (int i = 0; i < array_len; i++) {
+               json_t *if_object = json_array_get(root, i);
+
+               ret = cpfl_tdi_parse_immediate_field_obj(if_object, 
&hb->meter.immediate_fields[i]);
+               if (ret != 0)
+                       return ret;
+       }
+
+       return 0;
+}
+
+static int
+cpfl_tdi_parse_ma_hardware_block_obj(json_t *root,
+                                    enum cpfl_tdi_table_type table_type,
+                                    struct cpfl_tdi_ma_hardware_block *hb)
+{
+       int ret, val = 0;
+       json_t *jobj = NULL;
+
+       ret = cpfl_tdi_parse_ma_hw_block(root, hb);
+       if (ret != 0)
+               return ret;
+
+       ret = cpfl_tdi_get_integer_obj(root, "id", &val);
+       if (ret != 0)
+               return ret;
+
+       hb->id = (uint32_t)val;
+
+       ret = cpfl_tdi_get_string_obj(root, "hw_interface", hb->hw_interface);
+       if (ret != 0)
+               return ret;
+       if (table_type == CPFL_TDI_TABLE_TYPE_MATCH) {
+               ret = cpfl_tdi_get_array_obj(root, "profile", &jobj);
+               if (ret != 0)
+                       return ret;
+
+               ret = cpfl_tdi_parse_profiles(jobj, hb);
+               if (ret != 0)
+                       return ret;
+
+               ret = cpfl_tdi_get_array_obj(root, "action_format", &jobj);
+               if (ret != 0)
+                       return ret;
+               ret = cpfl_tdi_parse_action_format_array(jobj, hb);
+               if (ret != 0)
+                       return ret;
+       }
+
+       switch (hb->hw_block) {
+       case CPFL_TDI_HW_BLOCK_SEM:
+               ret = cpfl_tdi_get_integer_obj(root, "sub_profile", &val);
+               if (ret != 0)
+                       return ret;
+
+               hb->sem.sub_profile = (uint16_t)val;
+
+               ret = cpfl_tdi_get_integer_obj(root, "obj_id", &val);
+               if (ret != 0)
+                       return ret;
+
+               hb->sem.obj_id = (uint32_t)val;
+               break;
+       case CPFL_TDI_HW_BLOCK_WCM:
+               ret = cpfl_tdi_get_object_obj(root, "wcm_params", &jobj);
+               if (ret != 0)
+                       return ret;
+
+               ret = cpfl_tdi_parse_wcm_params(jobj, &hb->wcm.wcm_params);
+               if (ret != 0)
+                       return ret;
+               break;
+       case CPFL_TDI_HW_BLOCK_MOD:
+               ret = cpfl_tdi_get_string_obj(root, "hw_resource", 
hb->mod.hw_resource);
+               if (ret != 0)
+                       return ret;
+
+               ret = cpfl_tdi_get_integer_obj(root, "hw_resource_id", &val);
+               if (ret != 0)
+                       return ret;
+               hb->mod.hw_resource_id = (uint32_t)val;
+               break;
+       case CPFL_TDI_HW_BLOCK_METER:
+               ret = cpfl_tdi_get_string_obj(root, "hw_resource", 
hb->mod.hw_resource);
+               if (ret != 0)
+                       return ret;
+               ret = cpfl_tdi_get_integer_obj(root, "hw_resource_id", &val);
+               if (ret != 0)
+                       return ret;
+               hb->mod.hw_resource_id = (uint32_t)val;
+               ret = cpfl_tdi_get_array_obj(root, "immediate_fields", &jobj);
+               if (ret != 0)
+                       return ret;
+
+               ret = cpfl_tdi_parse_hb_immediate_fields(jobj, hb);
+               if (ret != 0)
+                       return ret;
+               break;
+       case CPFL_TDI_HW_BLOCK_LEM:
+       case CPFL_TDI_HW_BLOCK_CXP_LEM:
+               ret = cpfl_tdi_get_integer_obj(root, "hash_size", &val);
+               if (ret != 0)
+                       return ret;
+               hb->lem.hash_size = (uint16_t)val;
+               break;
+       case CPFL_TDI_HW_BLOCK_LPM:
+               ret = cpfl_tdi_get_integer_obj(root, "max_prefix_len", &val);
+               if (ret != 0)
+                       return ret;
+               hb->lpm.max_prefix_len = (uint16_t)val;
+               break;
+       case CPFL_TDI_HW_BLOCK_HASH:
+               break;
+       default:
+               printf("not support this hardware_block type: %d\n", 
hb->hw_block);
+               break;
+       }
+
+       return 0;
+}
+
+static int
+cpfl_tdi_parse_ma_hardware_blocks(json_t *root,
+                                 enum cpfl_tdi_table_type table_type,
+                                 struct cpfl_tdi_match_attributes *ma)
+{
+       int ret;
+       int array_len = json_array_size(root);
+
+       if (array_len == 0)
+               return 0;
+
+       ma->hardware_block_num = (uint16_t)array_len;
+       ma->hardware_blocks =
+           rte_zmalloc(NULL, sizeof(struct cpfl_tdi_ma_hardware_block) * 
array_len, 0);
+       if (ma->hardware_blocks == NULL) {
+               PMD_DRV_LOG(ERR, "Failed to create match attribute's hardware 
block array.");
+               return -ENOMEM;
+       }
+
+       for (int i = 0; i < array_len; i++) {
+               json_t *hb_object = json_array_get(root, i);
+
+               ret = cpfl_tdi_parse_ma_hardware_block_obj(hb_object, 
table_type,
+                                                          
&ma->hardware_blocks[i]);
+               if (ret != 0)
+                       return ret;
+       }
+
+       return 0;
+}
+
+static int
+cpfl_tdi_parse_match_attributes(json_t *root,
+                               enum cpfl_tdi_table_type table_type,
+                               struct cpfl_tdi_match_attributes *ma)
+{
+       json_t *jobj = NULL;
+       int ret;
+
+       ret = cpfl_tdi_get_array_obj(root, "hardware_blocks", &jobj);
+       if (ret != 0)
+               return ret;
+
+       return cpfl_tdi_parse_ma_hardware_blocks(jobj, table_type, ma);
+}
+
+static int
+cpfl_tdi_parse_table_obj(json_t *root, struct cpfl_tdi_table *table)
+{
+       int ret, val = 0;
+       struct json_t *jobj = NULL;
+
+       ret = cpfl_tdi_parse_table_type(root, table);
+       if (ret != 0)
+               return ret;
+
+       ret = cpfl_tdi_get_integer_obj(root, "handle", &val);
+       if (ret != 0)
+               return ret;
+       table->handle = (uint32_t)val;
+
+       ret = cpfl_tdi_get_string_obj(root, "name", table->name);
+       if (ret != 0)
+               return ret;
+
+       if (table->table_type == CPFL_TDI_TABLE_TYPE_POLICER_METER) {
+               /* TODO */
+               return 0;
+       }
+
+       if (table->table_type == CPFL_TDI_TABLE_TYPE_MATCH) {
+               ret = cpfl_tdi_parse_table_dir(root, table);
+               if (ret != 0)
+                       return ret;
+               ret = cpfl_tdi_get_boolean_obj(root, "add_on_miss", 
&table->add_on_miss);
+               if (ret != 0)
+                       return ret;
+               ret = cpfl_tdi_get_boolean_obj(root, 
"idle_timeout_with_auto_delete",
+                                              
&table->idle_timeout_with_auto_delete);
+               if (ret != 0)
+                       return ret;
+               ret = cpfl_tdi_get_integer_obj(root, "default_action_handle", 
&val);
+               if (ret != 0)
+                       return ret;
+               table->default_action_handle = (uint32_t)val;
+               ret = cpfl_tdi_get_array_obj(root, "actions", &jobj);
+               if (ret != 0)
+                       return ret;
+
+               ret = cpfl_tdi_parse_actions(jobj, table);
+               if (ret != 0)
+                       return ret;
+       } else if (table->table_type == 
CPFL_TDI_TABLE_TYPE_MATCH_VALUE_LOOKUP_TABLE) {
+               ret = cpfl_tdi_get_integer_obj(root, "size", &val);
+               if (ret != 0)
+                       return ret;
+               table->size = (uint16_t)val;
+               ret = cpfl_tdi_get_boolean_obj(root, "p4_hidden", 
&table->p4_hidden);
+               if (ret != 0)
+                       return ret;
+       }
+
+       ret = cpfl_tdi_get_array_obj(root, "match_key_fields", &jobj);
+       if (ret != 0)
+               return ret;
+
+       ret = cpfl_tdi_parse_match_key_fields(jobj, table);
+       if (ret != 0)
+               return ret;
+
+       if (json_object_get(root, "match_key_format") != NULL) {
+               ret = cpfl_tdi_get_array_obj(root, "match_key_format", &jobj);
+               if (ret != 0)
+                       return ret;
+
+               ret = cpfl_tdi_parse_match_key_format_array(jobj, table);
+               if (ret != 0)
+                       return ret;
+       }
+
+       ret = cpfl_tdi_get_object_obj(root, "match_attributes", &jobj);
+       if (ret != 0)
+               return ret;
+
+       ret = cpfl_tdi_parse_match_attributes(jobj, table->table_type, 
&table->match_attributes);
+       if (ret != 0)
+               return ret;
+
+       return 0;
+}
+
+static int
+cpfl_tdi_parse_tables(json_t *root, struct cpfl_tdi_program *prog)
+{
+       int ret;
+       int array_len = json_array_size(root);
+
+       if (array_len == 0)
+               return 0;
+
+       prog->table_num = (uint16_t)array_len;
+       prog->tables = rte_zmalloc(NULL, sizeof(struct cpfl_tdi_table) * 
array_len, 0);
+       if (prog->tables == NULL) {
+               PMD_DRV_LOG(ERR, "Failed to create table array.");
+               return -ENOMEM;
+       }
+
+       for (int i = 0; i < array_len; i++) {
+               json_t *table_object = json_array_get(root, i);
+
+               ret = cpfl_tdi_parse_table_obj(table_object, &prog->tables[i]);
+               if (ret != 0)
+                       return ret;
+       }
+
+       return 0;
+}
+
+static int
+cpfl_tdi_parse_hash_space_cfg(json_t *root, struct cpfl_tdi_hash_space_cfg 
*cfg)
+{
+       int ret, val = 0;
+
+       ret = cpfl_tdi_get_integer_obj(root, "base_128_entries", &val);
+       if (ret != 0)
+               return ret;
+
+       cfg->base_128_entries = (uint32_t)val;
+
+       ret = cpfl_tdi_get_integer_obj(root, "base_256_entries", &val);
+       if (ret != 0)
+               return ret;
+
+       cfg->base_256_entries = (uint32_t)val;
+
+       return 0;
+}
+
+static int
+cpfl_tdi_parse_rc_entry_space_cfg(json_t *root, struct 
cpfl_tdi_rc_entry_space_cfg *cfg)
+{
+       int ret, val = 0;
+
+       ret = cpfl_tdi_get_integer_obj(root, "rc_num_banks", &val);
+       if (ret != 0)
+               return ret;
+
+       cfg->rc_num_banks = (uint32_t)val;
+
+       ret = cpfl_tdi_get_integer_obj(root, "rc_num_entries", &val);
+       if (ret != 0)
+               return ret;
+
+       cfg->rc_num_entries = (uint32_t)val;
+
+       return 0;
+}
+
+static int
+cpfl_tdi_parse_gc_hw_block(json_t *root, struct cpfl_tdi_gc_hardware_block *hb)
+{
+       char name[CPFL_TDI_JSON_STR_SIZE_MAX];
+       int ret;
+
+       ret = cpfl_tdi_get_string_obj(root, "name", name);
+       if (ret != 0)
+               return -EINVAL;
+
+       if (!strcmp(name, "SEM")) {
+               hb->hw_block = CPFL_TDI_HW_BLOCK_SEM;
+       } else if (!strcmp(name, "LEM")) {
+               hb->hw_block = CPFL_TDI_HW_BLOCK_LEM;
+       } else if (!strcmp(name, "WCM")) {
+               hb->hw_block = CPFL_TDI_HW_BLOCK_WCM;
+       } else if (!strcmp(name, "MOD")) {
+               hb->hw_block = CPFL_TDI_HW_BLOCK_MOD;
+       } else if (!strcmp(name, "HASH")) {
+               hb->hw_block = CPFL_TDI_HW_BLOCK_HASH;
+       } else if (!strcmp(name, "RC")) {
+               hb->hw_block = CPFL_TDI_HW_BLOCK_RC;
+       } else if (!strcmp(name, "CXP_LEM")) {
+               hb->hw_block = CPFL_TDI_HW_BLOCK_CXP_LEM;
+       } else {
+               PMD_DRV_LOG(ERR, "Unknown hardware block type %s", name);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int
+cpfl_tdi_parse_gc_hardware_block(json_t *root, struct 
cpfl_tdi_gc_hardware_block *hb)
+{
+       json_t *jobj = NULL;
+       int ret;
+
+       ret = cpfl_tdi_parse_gc_hw_block(root, hb);
+       if (ret != 0)
+               return ret;
+
+       switch (hb->hw_block) {
+       case CPFL_TDI_HW_BLOCK_MOD:
+               ret = cpfl_tdi_get_object_obj(root, "hash_space_cfg", &jobj);
+               if (ret != 0)
+                       return ret;
+
+               return cpfl_tdi_parse_hash_space_cfg(jobj, &hb->hash_space_cfg);
+       case CPFL_TDI_HW_BLOCK_RC:
+               ret = cpfl_tdi_get_object_obj(root, "rc_entry_space_cfg", 
&jobj);
+               if (ret != 0)
+                       return ret;
+               return cpfl_tdi_parse_rc_entry_space_cfg(jobj, 
&hb->rc_entry_space_cfg);
+       default:
+               break;
+       }
+
+       return 0;
+}
+
+static int
+cpfl_tdi_parse_gc_hardware_blocks(json_t *root, struct cpfl_tdi_global_configs 
*gc)
+{
+       int ret;
+       int array_len = json_array_size(root);
+
+       if (array_len == 0)
+               return 0;
+
+       gc->hardware_block_num = (uint16_t)array_len;
+       gc->hardware_blocks =
+           rte_zmalloc(NULL, sizeof(struct cpfl_tdi_gc_hardware_block) * 
array_len, 0);
+       if (gc->hardware_blocks == NULL) {
+               PMD_DRV_LOG(ERR, "Failed to create hardware block array.");
+               return -ENOMEM;
+       }
+
+       for (int i = 0; i < array_len; i++) {
+               json_t *hb_object = json_array_get(root, i);
+
+               ret = cpfl_tdi_parse_gc_hardware_block(hb_object, 
&gc->hardware_blocks[i]);
+               if (ret != 0)
+                       return ret;
+       }
+
+       return 0;
+}
+
+static int
+cpfl_tdi_parse_global_configs(json_t *root, struct cpfl_tdi_global_configs *gc)
+{
+       json_t *jobj = NULL;
+       int ret;
+
+       ret = cpfl_tdi_get_array_obj(root, "hardware_blocks", &jobj);
+       if (ret != 0)
+               return ret;
+
+       return cpfl_tdi_parse_gc_hardware_blocks(jobj, gc);
+}
+
+int
+cpfl_tdi_program_create(json_t *root, struct cpfl_tdi_program *prog)
+{
+       json_t *jobj = NULL;
+       int ret;
+
+       ret = cpfl_tdi_get_string_obj(root, "program_name", prog->program_name);
+       if (ret != 0)
+               goto err;
+
+       ret = cpfl_tdi_get_string_obj(root, "build_date", prog->build_date);
+       if (ret != 0)
+               goto err;
+
+       ret = cpfl_tdi_get_string_obj(root, "compile_command", 
prog->compile_command);
+       if (ret != 0)
+               goto err;
+
+       ret = cpfl_tdi_get_string_obj(root, "compiler_version", 
prog->compiler_version);
+       if (ret != 0)
+               goto err;
+
+       ret = cpfl_tdi_get_string_obj(root, "schema_version", 
prog->schema_version);
+       if (ret != 0)
+               goto err;
+
+       ret = cpfl_tdi_get_string_obj(root, "target", prog->target);
+       if (ret != 0)
+               goto err;
+
+       ret = cpfl_tdi_get_object_obj(root, "global_configs", &jobj);
+       if (ret != 0)
+               goto err;
+
+       ret = cpfl_tdi_parse_global_configs(jobj, &prog->global_configs);
+       if (ret != 0)
+               goto err;
+
+       ret = cpfl_tdi_get_array_obj(root, "tables", &jobj);
+       if (ret != 0)
+               goto err;
+
+       ret = cpfl_tdi_parse_tables(jobj, prog);
+       if (ret != 0)
+               goto err;
+
+       json_decref(root);
+
+       return 0;
+
+err:
+       cpfl_tdi_program_destroy(prog);
+       return ret;
+}
+
+static void
+cpfl_tdi_destroy_hw_action(struct cpfl_tdi_hw_action *action)
+{
+       if (action->parameter_num > 0)
+               rte_free(action->parameters);
+}
+
+static void
+cpfl_tdi_cpfl_tdi_destroy_action_format(struct cpfl_tdi_action_format *format)
+{
+       uint16_t i;
+
+       if (format->immediate_field_num > 0)
+               rte_free(format->immediate_fields);
+
+       if (format->mod_content_format.mod_field_num > 0)
+               rte_free(format->mod_content_format.mod_fields);
+
+       for (i = 0; i < format->hw_action_num; i++)
+               cpfl_tdi_destroy_hw_action(&format->hw_actions_list[i]);
+
+       if (format->hw_action_num > 0)
+               rte_free(format->hw_actions_list);
+}
+
+static void
+cpfl_tdi_destroy_hardware_block(struct cpfl_tdi_ma_hardware_block *hb)
+{
+       uint16_t i;
+
+       for (i = 0; i < hb->action_format_num; i++)
+               cpfl_tdi_cpfl_tdi_destroy_action_format(&hb->action_format[i]);
+
+       if (hb->action_format_num > 0)
+               rte_free(hb->action_format);
+}
+
+static void
+cpfl_tdi_destroy_action(struct cpfl_tdi_action *action)
+{
+       if (action->p4_parameter_num > 0)
+               rte_free(action->p4_parameters);
+}
+
+static void
+cpfl_tdi_destroy_table(struct cpfl_tdi_table *table)
+{
+       uint16_t i;
+
+       if (table->match_key_field_num > 0)
+               rte_free(table->match_key_fields);
+
+       if (table->match_key_format_num > 0)
+               rte_free(table->match_key_format);
+
+       for (i = 0; i < table->action_num; i++)
+               cpfl_tdi_destroy_action(&table->actions[i]);
+
+       if (table->action_num > 0)
+               rte_free(table->actions);
+
+       for (i = 0; i < table->match_attributes.hardware_block_num; i++)
+               
cpfl_tdi_destroy_hardware_block(&table->match_attributes.hardware_blocks[i]);
+
+       if (table->match_attributes.hardware_block_num > 0)
+               rte_free(table->match_attributes.hardware_blocks);
+}
+
+void
+cpfl_tdi_program_destroy(struct cpfl_tdi_program *program)
+{
+       uint16_t i;
+
+       for (i = 0; i < program->table_num; i++)
+               cpfl_tdi_destroy_table(&program->tables[i]);
+
+       if (program->table_num > 0)
+               rte_free(program->tables);
+
+       rte_free(program);
+}
diff --git a/drivers/net/cpfl/cpfl_tdi_parser.h 
b/drivers/net/cpfl/cpfl_tdi_parser.h
new file mode 100644
index 0000000000..9e036e762c
--- /dev/null
+++ b/drivers/net/cpfl/cpfl_tdi_parser.h
@@ -0,0 +1,294 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2023 Intel Corporation
+ */
+#ifndef _CPFL_TDI_PARSER_H_
+#define _CPFL_TDI_PARSER_H_
+
+#include <jansson.h>
+#include <rte_flow.h>
+
+#include "cpfl_ethdev.h"
+
+#define CPFL_TDI_JSON_STR_SIZE_MAX 100
+
+enum cpfl_tdi_table_type {
+       CPFL_TDI_TABLE_TYPE_MATCH,
+       CPFL_TDI_TABLE_TYPE_MATCH_VALUE_LOOKUP_TABLE,
+       CPFL_TDI_TABLE_TYPE_POLICER_METER,
+};
+
+enum cpfl_tdi_table_dir {
+       CPFL_TDI_TABLE_DIR_RX,
+       CPFL_TDI_TABLE_DIR_TX,
+       CPFL_TDI_TABLE_DIR_BI,
+};
+
+enum cpfl_tdi_match_type {
+       CPFL_TDI_MATCH_TYPE_EXACT,
+       CPFL_TDI_MATCH_TYPE_SELECTOR,
+       CPFL_TDI_MATCH_TYPE_TERNARY,
+       CPFL_TDI_MATCH_TYPE_LPM,
+};
+
+/**
+ * Byte order.
+ *
+ * To specify the byte order of table key / action field value in bytes.
+ */
+enum cpfl_tdi_byte_order {
+       CPFL_TDI_BYTE_ORDER_HOST,    /**< follow host byte order. */
+       CPFL_TDI_BYTE_ORDER_NETWORK, /**< follow network byte order. */
+};
+
+#define CPFL_TDI_NAME_SIZE_MAX 80
+
+struct cpfl_tdi_match_key_format {
+       uint32_t match_key_handle;
+       enum cpfl_tdi_byte_order byte_order;
+       uint16_t byte_array_index;
+       uint16_t start_bit_offset;
+       uint16_t bit_width;
+};
+
+struct cpfl_tdi_match_key_field {
+       char name[CPFL_TDI_JSON_STR_SIZE_MAX];
+       char instance_name[CPFL_TDI_JSON_STR_SIZE_MAX];
+       char field_name[CPFL_TDI_JSON_STR_SIZE_MAX];
+       bool is_vsi;
+       enum cpfl_tdi_match_type match_type;
+       uint16_t bit_width;
+       uint32_t index;
+       uint32_t position;
+};
+
+struct cpfl_tdi_p4_parameter {
+       char name[CPFL_TDI_JSON_STR_SIZE_MAX];
+       uint16_t bit_width;
+};
+
+struct cpfl_tdi_action {
+       char name[CPFL_TDI_JSON_STR_SIZE_MAX];
+       uint32_t handle;
+       bool constant_default_action;
+       bool is_compiler_added_action;
+       bool allowed_as_hit_action;
+       bool allowed_as_default_action;
+       uint16_t p4_parameter_num;
+       struct cpfl_tdi_p4_parameter *p4_parameters;
+};
+
+struct cpfl_tdi_immediate_field {
+       char param_name[CPFL_TDI_JSON_STR_SIZE_MAX];
+       uint32_t param_handle;
+       uint16_t dest_start;
+       uint16_t start_bit_offset;
+       uint16_t dest_width;
+};
+
+enum cpfl_tdi_mod_field_type {
+       CPFL_TDI_MOD_FIELD_TYPE_PARAMETER,
+       CPFL_TDI_MOD_FIELD_TYPE_CONSTANT,
+};
+
+#define CPFL_TDI_VALUE_SIZE_MAX 16
+
+struct cpfl_tdi_mod_field {
+       char name[CPFL_TDI_JSON_STR_SIZE_MAX];
+       uint32_t handle;
+       uint32_t param_handle;
+       enum cpfl_tdi_mod_field_type type;
+       enum cpfl_tdi_byte_order byte_order;
+       uint16_t byte_array_index;
+       uint16_t start_bit_offset;
+       uint16_t bit_width;
+       uint16_t value_size;
+       uint8_t value[CPFL_TDI_VALUE_SIZE_MAX];
+};
+
+struct cpfl_tdi_mod_content_format {
+       union {
+               uint16_t mod_profile;
+               uint16_t mod_lut_num;
+       };
+       uint16_t mod_obj_size;
+       uint16_t mod_field_num;
+       struct cpfl_tdi_mod_field *mod_fields;
+};
+
+struct cpfl_tdi_hw_action_parameter {
+       char param_name[CPFL_TDI_JSON_STR_SIZE_MAX];
+       uint32_t param_handle;
+};
+
+enum cpfl_tdi_action_code {
+       CPFL_TDI_ACTION_CODE_NONE,
+       CPFL_TDI_ACTION_CODE_SET10_1b,
+       CPFL_TDI_ACTION_CODE_SET1_16b,
+       CPFL_TDI_ACTION_CODE_SET1A_24b,
+       CPFL_TDI_ACTION_CODE_SET1B_24b,
+       CPFL_TDI_ACTION_CODE_SET2_8b,
+       CPFL_TDI_ACTION_CODE_NOP,
+       CPFL_TDI_ACTION_CODE_AUX_DATA,
+};
+
+enum cpfl_tdi_setmd_action_code {
+       CPFL_TDI_SETMD_ACTION_CODE_NONE,
+       CPFL_TDI_SETMD_ACTION_CODE_SET_8b,
+       CPFL_TDI_SETMD_ACTION_CODE_SET_16b,
+       CPFL_TDI_SETMD_ACTION_CODE_SET_32b_AUX,
+};
+
+struct cpfl_tdi_hw_action {
+       uint16_t prec;
+       enum cpfl_tdi_action_code action_code;
+       enum cpfl_tdi_setmd_action_code setmd_action_code;
+       uint16_t index;
+       uint16_t mod_profile;
+       uint16_t prefetch;
+       uint16_t parameter_num;
+       struct cpfl_tdi_hw_action_parameter *parameters;
+       uint32_t p4_ref_action_handle;
+       uint32_t p4_ref_table_handle;
+       uint16_t value;
+       uint16_t mask;
+       uint16_t type_id;
+       uint16_t offset;
+};
+
+struct cpfl_tdi_action_format {
+       char action_name[CPFL_TDI_JSON_STR_SIZE_MAX];
+       uint32_t action_handle;
+       uint16_t immediate_field_num;
+       struct cpfl_tdi_immediate_field *immediate_fields;
+       struct cpfl_tdi_mod_content_format mod_content_format;
+       uint16_t hw_action_num;
+       struct cpfl_tdi_hw_action *hw_actions_list;
+};
+
+enum cpfl_tdi_hw_block {
+       CPFL_TDI_HW_BLOCK_SEM,
+       CPFL_TDI_HW_BLOCK_LEM,
+       CPFL_TDI_HW_BLOCK_WCM,
+       CPFL_TDI_HW_BLOCK_LPM,
+       CPFL_TDI_HW_BLOCK_MOD,
+       CPFL_TDI_HW_BLOCK_METER,
+       CPFL_TDI_HW_BLOCK_HASH,
+       CPFL_TDI_HW_BLOCK_RC,
+       CPFL_TDI_HW_BLOCK_CXP_LEM,
+};
+
+struct cpfl_tdi_wcm_params {
+       uint16_t wcm_group;
+       uint16_t slice_start_idx;
+       uint16_t table_width;
+       uint16_t entry_cnt;
+       uint16_t entry_idx;
+       uint8_t act_rams[16];
+};
+
+struct cpfl_tdi_ma_hardware_block {
+       enum cpfl_tdi_hw_block hw_block;
+       uint32_t id;
+       char hw_interface[CPFL_TDI_JSON_STR_SIZE_MAX];
+       uint16_t profile_num;
+       uint16_t profile[16];
+       uint16_t action_format_num;
+       struct cpfl_tdi_action_format *action_format;
+       union {
+               struct {
+                       uint16_t sub_profile;
+                       uint32_t obj_id;
+               } sem;
+               struct {
+                       struct cpfl_tdi_wcm_params wcm_params;
+               } wcm;
+               struct {
+                       char hw_resource[CPFL_TDI_JSON_STR_SIZE_MAX];
+                       uint32_t hw_resource_id;
+               } mod;
+               struct {
+                       char hw_resource[CPFL_TDI_JSON_STR_SIZE_MAX];
+                       uint32_t hw_resource_id;
+                       uint16_t immediate_field_num;
+                       struct cpfl_tdi_immediate_field *immediate_fields;
+               } meter;
+               struct {
+                       uint16_t hash_size;
+               } lem;
+               struct {
+                       uint16_t max_prefix_len;
+               } lpm;
+       };
+};
+
+struct cpfl_tdi_match_attributes {
+       uint16_t hardware_block_num;
+       struct cpfl_tdi_ma_hardware_block *hardware_blocks;
+};
+
+struct cpfl_tdi_table {
+       enum cpfl_tdi_table_type table_type;
+       uint32_t handle;
+       char name[CPFL_TDI_JSON_STR_SIZE_MAX];
+       union {
+               /* "table_type": "match" */
+               struct {
+                       enum cpfl_tdi_table_dir direction;
+                       bool add_on_miss;
+                       bool idle_timeout_with_auto_delete;
+               };
+               /* "table_type": "match_value_lookup_table" */
+               struct {
+                       uint16_t size;
+                       bool p4_hidden;
+               };
+       };
+       uint16_t match_key_field_num;
+       struct cpfl_tdi_match_key_field *match_key_fields;
+       uint16_t match_key_format_num;
+       struct cpfl_tdi_match_key_format *match_key_format;
+       uint32_t default_action_handle;
+       uint16_t action_num;
+       struct cpfl_tdi_action *actions;
+       struct cpfl_tdi_match_attributes match_attributes;
+};
+
+struct cpfl_tdi_hash_space_cfg {
+       uint32_t base_128_entries;
+       uint32_t base_256_entries;
+};
+
+struct cpfl_tdi_rc_entry_space_cfg {
+       uint32_t rc_num_banks;
+       uint32_t rc_num_entries;
+};
+
+struct cpfl_tdi_gc_hardware_block {
+       enum cpfl_tdi_hw_block hw_block;
+       union {
+               struct cpfl_tdi_hash_space_cfg hash_space_cfg;
+               struct cpfl_tdi_rc_entry_space_cfg rc_entry_space_cfg;
+       };
+};
+
+struct cpfl_tdi_global_configs {
+       uint16_t hardware_block_num;
+       struct cpfl_tdi_gc_hardware_block *hardware_blocks;
+};
+
+struct cpfl_tdi_program {
+       char program_name[CPFL_TDI_JSON_STR_SIZE_MAX];
+       char build_date[CPFL_TDI_JSON_STR_SIZE_MAX];
+       char compile_command[2 * CPFL_TDI_JSON_STR_SIZE_MAX];
+       char compiler_version[CPFL_TDI_JSON_STR_SIZE_MAX];
+       char schema_version[CPFL_TDI_JSON_STR_SIZE_MAX];
+       char target[CPFL_TDI_JSON_STR_SIZE_MAX];
+       struct cpfl_tdi_global_configs global_configs;
+       uint16_t table_num;
+       struct cpfl_tdi_table *tables;
+};
+
+int cpfl_tdi_program_create(json_t *ob_root, struct cpfl_tdi_program *program);
+void cpfl_tdi_program_destroy(struct cpfl_tdi_program *program);
+
+#endif
diff --git a/drivers/net/cpfl/meson.build b/drivers/net/cpfl/meson.build
index e4e0e269bd..f948033f1f 100644
--- a/drivers/net/cpfl/meson.build
+++ b/drivers/net/cpfl/meson.build
@@ -47,6 +47,7 @@ if dpdk_conf.has('RTE_HAS_JANSSON')
             'cpfl_flow_engine_fxp.c',
             'cpfl_flow_parser.c',
             'cpfl_fxp_rule.c',
+            'cpfl_tdi_parser.c',
     )
     ext_deps += jansson_dep
 endif
-- 
2.34.1

Reply via email to