From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 8A3BA4375D; Fri, 22 Dec 2023 11:10:04 +0100 (CET) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 7819D402F0; Fri, 22 Dec 2023 11:10:04 +0100 (CET) Received: from mgamail.intel.com (mgamail.intel.com [134.134.136.20]) by mails.dpdk.org (Postfix) with ESMTP id 799F74067C for ; Fri, 22 Dec 2023 11:10:02 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1703239802; x=1734775802; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=Ow9tbu4BYmF06S7u8KRkX6H5qIvINhV0u3Vr51gsOY0=; b=BNgWdb/1yjrOMzGNCRXJRQNDxAnRsNCiNGEQS43iNSCi8MTmKGlCc9+r hZ2cmnyfQiEGtsIndgqlEzzmatF/XGLMhspRvx5tLP7JxFb3h5Ot22j3s ZmmjGkJSf9rZbh+f8U7WKh8v31wnW4dfZHScpEaDcLmr5cm+lw8fbN5VZ GhKIJEPB1JkOPPWMDSu6J/crd+neeiWKofdf1Eiv3uNNgPwKLt1fElnbk h/F+lPFeobmJSUqY+Ej6nMHZPkxokSPMnwt4qPJCwFBplkK1UKBpcc93t QlbIvu8noYuOftxvPYEdgHndyStvnoyAzImAZI0XYqkLl7PBQB2b/Tx6l w==; X-IronPort-AV: E=McAfee;i="6600,9927,10931"; a="386525288" X-IronPort-AV: E=Sophos;i="6.04,296,1695711600"; d="scan'208";a="386525288" Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by orsmga101.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 22 Dec 2023 02:10:01 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10931"; a="920605319" X-IronPort-AV: E=Sophos;i="6.04,296,1695711600"; d="scan'208";a="920605319" Received: from dpdk-wenjing-02.sh.intel.com ([10.67.118.228]) by fmsmga001.fm.intel.com with ESMTP; 22 Dec 2023 02:09:58 -0800 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 1/2] net/cpfl: parse flow offloading hint from P4 context file Date: Fri, 22 Dec 2023 10:08:39 +0000 Message-Id: <20231222100837.260493-2-wenjing.qiao@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20231222100837.260493-1-wenjing.qiao@intel.com> References: <20231222100837.260493-1-wenjing.qiao@intel.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit 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 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 --- 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 | 1715 +++++++++++++++++++++++ drivers/net/cpfl/cpfl_tdi_parser.h | 293 ++++ drivers/net/cpfl/meson.build | 1 + 8 files changed, 2077 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 #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..ed12ef04ad --- /dev/null +++ b/drivers/net/cpfl/cpfl_tdi_parser.c @@ -0,0 +1,1715 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Intel Corporation + */ +#include +#include + +#include "cpfl_tdi_parser.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; + + 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; + + 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..c3d84adb77 --- /dev/null +++ b/drivers/net/cpfl/cpfl_tdi_parser.h @@ -0,0 +1,293 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Intel Corporation + */ +#ifndef _CPFL_TDI_PARSER_H_ +#define _CPFL_TDI_PARSER_H_ + +#include +#include + +#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]; + 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