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 60B00430EC; Thu, 24 Aug 2023 09:25:18 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 076DD410EE; Thu, 24 Aug 2023 09:25:18 +0200 (CEST) Received: from mgamail.intel.com (mgamail.intel.com [192.55.52.88]) by mails.dpdk.org (Postfix) with ESMTP id EE80E40EE1 for ; Thu, 24 Aug 2023 09:25:15 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1692861916; x=1724397916; h=from:to:cc:subject:date:message-id:references: in-reply-to:content-transfer-encoding:mime-version; bh=mUcN4eDtTCKc3BVUCiTYwes25fZFGbV+ToOFbJZaWlE=; b=B/J8hzSSr9pdZtN2GdXQps9my4I2H1dwk9Uq0uay7PI/jhwvESCXGUMw 9GRRBk5ydI64tSLb8xFxN+QtrHodZG0FRdFfxCFfUFw6EIQD/zMXty5MA zSIyfi67ACzUWincWcdtyXjHjSJ8EO3BOjw4yidRvkWAX4en//y7bxOnK KHNQSLzlO1Xgo32iVRdu1W+NYEFYYCAmkxEQ4WetEj3FHLjupzcVZT2NK gTk5fz5jwTV1v551NSV86jJEMG29gXt0hY+kBPzbvbqHX6irOgSn2JWCG 5mUV3J7/PQVCRWzir2/ywtDXWbzLiHiQJYs5F1Zx68B5rmLM9nD3NsV0x g==; X-IronPort-AV: E=McAfee;i="6600,9927,10811"; a="405366653" X-IronPort-AV: E=Sophos;i="6.01,195,1684825200"; d="scan'208";a="405366653" Received: from orsmga003.jf.intel.com ([10.7.209.27]) by fmsmga101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 24 Aug 2023 00:25:14 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10811"; a="686769032" X-IronPort-AV: E=Sophos;i="6.01,195,1684825200"; d="scan'208";a="686769032" Received: from fmsmsx601.amr.corp.intel.com ([10.18.126.81]) by orsmga003.jf.intel.com with ESMTP; 24 Aug 2023 00:25:13 -0700 Received: from fmsmsx610.amr.corp.intel.com (10.18.126.90) by fmsmsx601.amr.corp.intel.com (10.18.126.81) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.27; Thu, 24 Aug 2023 00:25:13 -0700 Received: from fmsedg602.ED.cps.intel.com (10.1.192.136) by fmsmsx610.amr.corp.intel.com (10.18.126.90) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.27 via Frontend Transport; Thu, 24 Aug 2023 00:25:13 -0700 Received: from NAM02-BN1-obe.outbound.protection.outlook.com (104.47.51.48) by edgegateway.intel.com (192.55.55.71) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.1.2507.27; Thu, 24 Aug 2023 00:25:12 -0700 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=OU4U+goaqOhlX5E+7AlzLikNW6noiJSmaCmdx8A4Etz5k+Vd++ewNNiecpdT1fxX/wp4V8feB6AtK+C7sEuXVF0Q17hDLRJEqt1nJeX5o1zSKS3idq7I1eP58ZZiuIqU/rWmLyPF8NJH1WNsIWAoJI9ZmzlRTeIjo222i13aeTZkBAGwfUeUrnxvQabpXUdKf3ruf9Mridhqg2DVxI+uDevmVkeZNIomE632WPgvkudltslMBdIt7mVlk0VBaLrRzOH4H/kAgT6QWfE0KKS0ITkuF/PwPqgm0CsSQAfCJBK6voeQyhyBhJq9tlbZMuI71ZI+vEsyR5CQJvO0Tuyo3Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=pWiL11XaS/3NBgtf90MZDYsbWuHG2T5lxU2VswBU4yw=; b=SHCkQzgGLwwF2NpQr7+3RVjci0VenCXq/JSXXdsV4CooplUg9Oomjtvbd0kOi2FUvT3w7xzRhCCOUxUo9FdSpu7JChPshcsPjM66e6GP38zuH7U71xK/hDv3JGVb/kzgdXyv490ZZM0ibYH1okNiyvAGptyasBzeUB+apSGs4zHi8oUuwsuxtQ7Da/LBPEKbeSFmJOmj0ZEEFRvl3TddNFpdidpUzWEENOPxyU9aQ+OD5RfWsLG3LMVb3GT7lrdH1d7OMyBzmATwVMige1DeugxBFzDm1joKK/+eQjfiJ+Liuqlpp4Gvl5BLreHs3FENcIR0SKzewFx9g3ZkeeyayQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=intel.com; dmarc=pass action=none header.from=intel.com; dkim=pass header.d=intel.com; arc=none Received: from LV2PR11MB5997.namprd11.prod.outlook.com (2603:10b6:408:17f::10) by SA2PR11MB5068.namprd11.prod.outlook.com (2603:10b6:806:116::10) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6699.27; Thu, 24 Aug 2023 07:25:10 +0000 Received: from LV2PR11MB5997.namprd11.prod.outlook.com ([fe80::7423:9a2e:7dd5:e56]) by LV2PR11MB5997.namprd11.prod.outlook.com ([fe80::7423:9a2e:7dd5:e56%3]) with mapi id 15.20.6699.026; Thu, 24 Aug 2023 07:25:10 +0000 From: "Xing, Beilei" To: "Qiao, Wenjing" , "Zhang, Yuying" CC: "dev@dpdk.org" , "Liu, Mingxia" Subject: RE: [PATCH v2 2/4] net/cpfl: add flow json parser Thread-Topic: [PATCH v2 2/4] net/cpfl: add flow json parser Thread-Index: AQHZzDtj6fidT+E6ZEuslw4Qjt9dbq/43v2w Date: Thu, 24 Aug 2023 07:25:09 +0000 Message-ID: References: <20230811093032.2065099-2-wenjing.qiao@intel.com> <20230811100012.2078135-3-wenjing.qiao@intel.com> In-Reply-To: <20230811100012.2078135-3-wenjing.qiao@intel.com> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: authentication-results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=intel.com; x-ms-publictraffictype: Email x-ms-traffictypediagnostic: LV2PR11MB5997:EE_|SA2PR11MB5068:EE_ x-ms-office365-filtering-correlation-id: 2715d2bd-36d5-46d2-c3ad-08dba4733f9a x-ms-exchange-senderadcheck: 1 x-ms-exchange-antispam-relay: 0 x-microsoft-antispam: BCL:0; x-microsoft-antispam-message-info: AwvxafsPePf+l07wfSq8rNQZgpTf5eb7nX8IkVVEEeBdtWLVTuXWu1eupaWFjQZMvlZxLslsLgdDxdRfhZqa7nxn+7Jj5c8hIDhgFTRo6rVWUCcD2yaUtVwdAAXN/Z6TtUWDm9DWD8tMvisrWLZEH0qip0rJuaSofjUaEKB5t3STR8IgcN/dkJFL0BVamV4R4JH5u0abTjy//OU1KToCqaquyNYTEVKGgMSDLZL+7LxFNX9qTszDZk5G6upPbWyXFZ8u5B2JANoSl5lzz2gLVfDh7Ep3oFIsTZKNBCjRk8FczFTBRjE8zXm9fzWYbzNXmThiH8SYgloWtVyVEGV8kmtRq6+3AqSMo3CoVPQa6VjeSPyDnLrQz1z1ALWGg0sweLKU7ddj/g88IC1z18Gp4ybdBLSI7Ycv7lymdYFTIGGacGJK8nk7D8Av07EWDGU14NI6wBxgaZmQhGtdal+skdrb6ImfeueDd3N4MRSZklO9v70uJmQ4YSVrsfpex5I1NeEUxd6MQC4yfz6UgcGlu2mPgdyWn1KA23++xTt11Nu8iApimDfqgjK3NxhioEEm1QiAh9m1ofKOa8nhlIyhWz9W1Fy6+4oy1qTHKFnRpsjx1Uev7PD6g3OR6OApgMLbWUmzSG1jwmRI88CzEMWfog== x-forefront-antispam-report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:LV2PR11MB5997.namprd11.prod.outlook.com; PTR:; CAT:NONE; SFS:(13230031)(366004)(39860400002)(346002)(376002)(396003)(136003)(1800799009)(186009)(451199024)(64756008)(54906003)(66446008)(66476007)(66946007)(76116006)(66556008)(6636002)(316002)(82960400001)(122000001)(478600001)(110136005)(55016003)(26005)(38100700002)(38070700005)(33656002)(71200400001)(41300700001)(53546011)(6506007)(7696005)(86362001)(2906002)(9686003)(30864003)(4326008)(8676002)(8936002)(83380400001)(52536014)(107886003)(5660300002)(21314003)(579004)(559001); DIR:OUT; SFP:1102; x-ms-exchange-antispam-messagedata-chunkcount: 1 x-ms-exchange-antispam-messagedata-0: =?us-ascii?Q?Hg/KYkTK045zEK7xMVxL25+Cm2B8HUC8Ehu2i9RshY3ElEz8cDfErg+AILEH?= =?us-ascii?Q?TRA3ROAaksYFLemmqK4aWNk4Itilj086WtqkYyDU49c2d1yGqkPkeYmd2nPT?= =?us-ascii?Q?Z+C5/njk/BdTFCUOlWIRwocM6MsPIvpeZ+W5RL3eSO/gFUBkSXFWa/StFuhs?= =?us-ascii?Q?Dx8a7ejgfl1Tn1BOoW0nyOY7cSdqb/NmLvZ02q6sH9IDfyQweVPVltX7edn5?= =?us-ascii?Q?L3cornWs3QNIaOCrA488LUXf4FuLI9dLDT5t7pm+6S8Cl9cKcLL6Y1d4uJmX?= =?us-ascii?Q?I2aKhW/VZxepuimmKtjPWpyrmm3/pCWKsemJIOdFOzkAFeDfuWqhh9WQTydt?= =?us-ascii?Q?6E4GKFLpYYNJHKCtmiVq2WmUaHgCwId0i5mBsSP3yOTrYnaFkdjN7G14xoUq?= =?us-ascii?Q?RL6JE5+W37yo3FQh0m+UZOq83OoyYUeAFuN6Xv+sEdRffjTDcdvgRmhTHcZd?= =?us-ascii?Q?V4VNFUf2edkvLUN2bDRchh/jSQ7jPclZ2ISdJDi7LSZPXwjf7UyZHihD3V/e?= =?us-ascii?Q?vqXaAr3vx1AS79x+LIkiT9KBksT/p+Zf0xP42iODgptW3jzSqxtTuuWyyZow?= =?us-ascii?Q?AugJQujTKyjHqPSqyHUsFwNXQQRfMXcr2T91kAZCDoWZM0rwWSlOsVIi5oBN?= =?us-ascii?Q?IgiwU3BHQdJkghb03aUo26jzIrDw8XFGD4YkcuRbhahjTJSlpuo9xuw2y5VG?= =?us-ascii?Q?Mf3uFbrFUNxyhnZnMEkNRQfL7xG+NEQVddFYsx5tJwcWauDIXo4jIXWoNuDw?= =?us-ascii?Q?8ZvdfzAOP+beubucmOm9RE8fOZTxsMuPb8luvZtyUXrZ4p/G9YiYwCisjY5F?= =?us-ascii?Q?nGZBflD92u5q953c3GQWqeiHGdXL3npxk31/m8yO5kGxo94k3Ae2Wi1zqWWA?= =?us-ascii?Q?Xlb0fkj+5GIPRrsPGGtJ9ElAIsgQZz2/jH+TM9XnfERLneKl2XbC8GiQHCOx?= =?us-ascii?Q?O5guFB/cNs3XN900h9IktBMWyCNrtxpoo6g+t+xBCmdfzPcpVxbivKZZaWY5?= =?us-ascii?Q?i4GORS+6nczWnhMyu5i3B+oG+CCtbHFctYWJLzs4xKctFCnY2auwPiDSvaHc?= =?us-ascii?Q?zEB7ThrICG5C+BjHXkJVn+VCI8LFQYiYV+y2xUzyBaK/cy/vqELj7z5uAc9F?= =?us-ascii?Q?aq6LktaAzk3c61gyaIpYAn/sWECcKJZNAVnoZdQL93KMp3jnScqM23fCJ4W7?= =?us-ascii?Q?noL2Z/cN9h88Gcy68CJzY2kiGQrBtI3QSgnSAfUOEzAPyNALTV9GDL2EWdc5?= =?us-ascii?Q?nEnMbfDZeAhhRLJC2nIunlhYEMypgHQS8B8jdC+4xUy4CqJWaKW/szf8GPeS?= =?us-ascii?Q?Fa52gfWt0LXqen6rwugUOehM13SAjcPR9mv1+ML5osiWkz5n0gXiKgKRpPfR?= =?us-ascii?Q?UycgPgsvljgpY+mowwpGGhXOqlWPKn5CZbWajhRM9+/3A3QP16BfR4Igi8gA?= =?us-ascii?Q?DSMhVxjkw+B3A8uFZYYrMdVRCnOS33jcMnRDAXkY53ePipF3gLFIYShONRro?= =?us-ascii?Q?5zPNiIo9BLZsqKJ4Y6ChXlpk31tEeGT1W/eOFLlJ8EfELzJhO4zvy+W7sA4W?= =?us-ascii?Q?7Z+jTW+11us1SLnm4+KGiwi1ttnAdqqaRrt4GdK4?= Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-AuthSource: LV2PR11MB5997.namprd11.prod.outlook.com X-MS-Exchange-CrossTenant-Network-Message-Id: 2715d2bd-36d5-46d2-c3ad-08dba4733f9a X-MS-Exchange-CrossTenant-originalarrivaltime: 24 Aug 2023 07:25:09.7746 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: 46c98d88-e344-4ed4-8496-4ed7712e255d X-MS-Exchange-CrossTenant-mailboxtype: HOSTED X-MS-Exchange-CrossTenant-userprincipalname: XzHZt3H9dzM+vcE9JVTWk9BrDzgGZRdM3luX4ozLij+1jIkamHy+hAWDKtHmMi5ccYEMkirCKBrX4woIU2yvSQ== X-MS-Exchange-Transport-CrossTenantHeadersStamped: SA2PR11MB5068 X-OriginatorOrg: intel.com 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 > -----Original Message----- > From: Qiao, Wenjing > Sent: Friday, August 11, 2023 6:00 PM > To: Zhang, Yuying ; Xing, Beilei > > Cc: dev@dpdk.org; Liu, Mingxia ; Qiao, Wenjing > > Subject: [PATCH v2 2/4] net/cpfl: add flow json parser >=20 > A JSON file will be used to direct DPDK CPF PMD to > parse rte_flow tokens into low level hardware resources > defined in a DDP package file. >=20 > Signed-off-by: Wenjing Qiao > --- > Depends-on: series-29139 ("net/cpfl: support port representor") > --- > drivers/net/cpfl/cpfl_flow_parser.c | 1758 +++++++++++++++++++++++++++ > drivers/net/cpfl/cpfl_flow_parser.h | 205 ++++ > drivers/net/cpfl/meson.build | 3 + > 3 files changed, 1966 insertions(+) > create mode 100644 drivers/net/cpfl/cpfl_flow_parser.c > create mode 100644 drivers/net/cpfl/cpfl_flow_parser.h >=20 > diff --git a/drivers/net/cpfl/cpfl_flow_parser.c > b/drivers/net/cpfl/cpfl_flow_parser.c > new file mode 100644 > index 0000000000..b4635813ff > --- /dev/null > +++ b/drivers/net/cpfl/cpfl_flow_parser.c > @@ -0,0 +1,1758 @@ > +/* SPDX-License-Identifier: BSD-3-Clause > + * Copyright(c) 2023 Intel Corporation > + */ > + > +#include > +#include > +#include > + > +#include "cpfl_flow_parser.h" > +#include "cpfl_ethdev.h" > +#include "rte_malloc.h" > + > +static enum rte_flow_item_type > +cpfl_get_item_type_by_str(const char *type) > +{ > + if (strcmp(type, "eth") =3D=3D 0) > + return RTE_FLOW_ITEM_TYPE_ETH; > + else if (strcmp(type, "ipv4") =3D=3D 0) > + return RTE_FLOW_ITEM_TYPE_IPV4; > + else if (strcmp(type, "tcp") =3D=3D 0) > + return RTE_FLOW_ITEM_TYPE_TCP; > + else if (strcmp(type, "udp") =3D=3D 0) > + return RTE_FLOW_ITEM_TYPE_UDP; > + else if (strcmp(type, "vxlan") =3D=3D 0) > + return RTE_FLOW_ITEM_TYPE_VXLAN; > + else if (strcmp(type, "icmp") =3D=3D 0) > + return RTE_FLOW_ITEM_TYPE_ICMP; > + else if (strcmp(type, "vlan") =3D=3D 0) > + return RTE_FLOW_ITEM_TYPE_VLAN; > + > + PMD_DRV_LOG(ERR, "Not support this type: %s.", type); > + return RTE_FLOW_ITEM_TYPE_VOID; > +} > + > +static enum rte_flow_action_type > +cpfl_get_action_type_by_str(const char *type) > +{ > + if (strcmp(type, "vxlan_encap") =3D=3D 0) > + return RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP; > + > + PMD_DRV_LOG(ERR, "Not support this type: %s.", type); Why the function only supports vxlan_encap? It's a bit confused. If only for vxlan_encap, better to change the function name. > + return RTE_FLOW_ACTION_TYPE_VOID; > +} > + > +static const char * > +cpfl_json_object_to_string(json_object *object, const char *name) > +{ > + json_object *subobject; > + > + if (!object) { > + PMD_DRV_LOG(ERR, "object doesn't exist."); > + return NULL; > + } > + subobject =3D json_object_object_get(object, name); > + if (!subobject) { > + PMD_DRV_LOG(ERR, "%s doesn't exist.", name); > + return 0; Return NULL? > + } > + return json_object_get_string(subobject); > +} > + <...> > +static int > +cpfl_flow_js_pattern_key_proto_field(json_object *cjson_field, > + struct cpfl_flow_js_pr_key_proto *js_field) > +{ > + if (cjson_field) { How about=20 if (cjson_field ! =3D0 ) return 0; first? > + int len, i; > + > + len =3D json_object_array_length(cjson_field); > + js_field->fields_size =3D len; > + if (len =3D=3D 0) > + return 0; > + js_field->fields =3D > + rte_malloc(NULL, sizeof(struct > cpfl_flow_js_pr_key_proto_field) * len, 0); > + if (!js_field->fields) { > + PMD_DRV_LOG(ERR, "Failed to alloc memory."); > + return -ENOMEM; > + } > + for (i =3D 0; i < len; i++) { > + json_object *object; > + const char *name, *mask; > + > + object =3D json_object_array_get_idx(cjson_field, i); > + name =3D cpfl_json_object_to_string(object, "name"); > + if (!name) { > + rte_free(js_field->fields); > + PMD_DRV_LOG(ERR, "Can not parse string > 'name'."); > + return -EINVAL; > + } > + if (strlen(name) > CPFL_FLOW_JSON_STR_SIZE_MAX) { > + rte_free(js_field->fields); > + PMD_DRV_LOG(ERR, "The 'name' is too > long."); > + return -EINVAL; > + } > + memcpy(js_field->fields[i].name, name, strlen(name)); > + > + if (js_field->type =3D=3D RTE_FLOW_ITEM_TYPE_ETH || > + js_field->type =3D=3D RTE_FLOW_ITEM_TYPE_IPV4) { > + mask =3D cpfl_json_object_to_string(object, > "mask"); > + if (!mask) { > + rte_free(js_field->fields); > + PMD_DRV_LOG(ERR, "Can not parse > string 'mask'."); > + return -EINVAL; > + } > + memcpy(js_field->fields[i].mask, mask, > strlen(mask)); > + } else { > + uint32_t mask_32b; > + int ret; > + > + ret =3D cpfl_json_object_to_uint32(object, > "mask", &mask_32b); > + if (ret < 0) { > + rte_free(js_field->fields); > + PMD_DRV_LOG(ERR, "Can not parse > uint32 'mask'."); > + return -EINVAL; > + } > + js_field->fields[i].mask_32b =3D mask_32b; > + } > + } > + } > + return 0; > +} > + <...> > + > +static int > +cpfl_flow_js_pattern_act_fv_proto(json_object *cjson_value, struct > cpfl_flow_js_fv *js_fv) > +{ > + uint16_t layer =3D 0, offset =3D 0, mask =3D 0; > + const char *header; > + enum rte_flow_item_type type; > + int ret; > + > + ret =3D cpfl_json_object_to_uint16(cjson_value, "layer", &layer); > + if (ret < 0) { > + PMD_DRV_LOG(ERR, "Can not parse 'value'."); > + return -EINVAL; > + } > + > + header =3D cpfl_json_object_to_string(cjson_value, "header"); > + if (!header) { > + PMD_DRV_LOG(ERR, "Can not parse string 'header'."); > + return -EINVAL; > + } > + ret =3D cpfl_json_object_to_uint16(cjson_value, "offset", &offset); > + if (ret < 0) { > + PMD_DRV_LOG(ERR, "Can not parse 'offset'."); > + return -EINVAL; > + } > + ret =3D cpfl_json_object_to_uint16(cjson_value, "mask", &mask); > + if (ret < 0) { > + PMD_DRV_LOG(ERR, "Can not parse 'mask'."); > + return -EINVAL; > + } > + js_fv->proto.layer =3D layer; > + js_fv->proto.offset =3D offset; > + js_fv->proto.mask =3D mask; > + type =3D cpfl_get_item_type_by_str(header); > + if (type =3D=3D RTE_FLOW_ITEM_TYPE_VOID) > + return -EINVAL; > + No need the blank line. > + else > + js_fv->proto.header =3D type; > + return 0; > +} > + <...> > +static int > +cpfl_flow_js_mr_key(json_object *cjson_mr_key, struct cpfl_flow_js_mr_ke= y > *js_mr_key) > +{ > + int len, i; > + > + len =3D json_object_array_length(cjson_mr_key); > + js_mr_key->actions =3D rte_malloc(NULL, sizeof(struct > cpfl_flow_js_mr_key_action) * len, 0); > + if (!js_mr_key->actions) { > + PMD_DRV_LOG(ERR, "Failed to alloc memory."); > + return -ENOMEM; > + } > + js_mr_key->actions_size =3D len; > + for (i =3D 0; i < len; i++) { > + json_object *object, *cjson_mr_key_data; > + const char *type; > + enum rte_flow_action_type act_type; > + > + object =3D json_object_array_get_idx(cjson_mr_key, i); > + /* mr->key->actions->type */ > + type =3D cpfl_json_object_to_string(object, "type"); > + if (!type) { > + rte_free(js_mr_key->actions); > + PMD_DRV_LOG(ERR, "Can not parse string 'type'."); > + return -EINVAL; > + } > + act_type =3D cpfl_get_action_type_by_str(type); > + if (act_type =3D=3D RTE_FLOW_ACTION_TYPE_VOID) { > + rte_free(js_mr_key->actions); > + return -EINVAL; > + } > + js_mr_key->actions[i].type =3D act_type; > + /* mr->key->actions->data */ > + cjson_mr_key_data =3D json_object_object_get(object, "data"); > + if (js_mr_key->actions[i].type =3D=3D > RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP) { > + json_object *cjson_mr_key_proto; > + int proto_size, j; > + struct cpfl_flow_js_mr_key_action_vxlan_encap > *encap; > + > + cjson_mr_key_proto =3D > json_object_object_get(cjson_mr_key_data, "protocols"); > + encap =3D &js_mr_key->actions[i].encap; > + if (!cjson_mr_key_proto) { > + encap->proto_size =3D 0; > + continue; > + } > + proto_size =3D > json_object_array_length(cjson_mr_key_proto); > + encap->proto_size =3D proto_size; > + for (j =3D 0; j < proto_size; j++) { > + const char *s; > + json_object *subobject; > + enum rte_flow_item_type proto_type; > + > + subobject =3D > json_object_array_get_idx(cjson_mr_key_proto, j); > + s =3D json_object_get_string(subobject); > + proto_type =3D cpfl_get_item_type_by_str(s); > + if (proto_type =3D=3D > RTE_FLOW_ITEM_TYPE_VOID) { > + rte_free(js_mr_key->actions); > + PMD_DRV_LOG(ERR, "parse > VXLAN_ENCAP failed."); > + return -EINVAL; > + } > + encap->protocols[j] =3D proto_type; > + } > + No need the blank line, please check all patches. > + } else { > + PMD_DRV_LOG(ERR, "not support this type: %d.", > js_mr_key->actions[i].type); > + return -EINVAL; > + } > + } > + return 0; > +} > + <...> > +static int > +cpfl_flow_js_mr_action(json_object *cjson_mr_act, struct > cpfl_flow_js_mr_action *js_mr_act) > +{ > + json_object *cjson_mr_action_data; > + const char *type; > + > + /* mr->action->type */ > + type =3D cpfl_json_object_to_string(cjson_mr_act, "type"); > + if (!type) { > + PMD_DRV_LOG(ERR, "Can not parse string 'type'."); > + return -EINVAL; > + } > + > + /* mr->action->data */ > + cjson_mr_action_data =3D json_object_object_get(cjson_mr_act, "data"); > + if (strcmp(type, "mod") =3D=3D 0) { > + json_object *layout; > + uint16_t profile =3D 0; > + int ret; > + > + js_mr_act->type =3D CPFL_JS_MR_ACTION_TYPE_MOD; > + ret =3D cpfl_json_object_to_uint16(cjson_mr_action_data, > "profile", &profile); > + if (ret < 0) { > + PMD_DRV_LOG(ERR, "Can not parse 'profile'."); > + return -EINVAL; > + } > + js_mr_act->mod.prof =3D profile; > + layout =3D json_object_object_get(cjson_mr_action_data, > "layout"); > + ret =3D cpfl_flow_js_mr_layout(layout, &js_mr_act->mod); > + if (ret < 0) { > + PMD_DRV_LOG(ERR, "Can not parse layout."); > + return ret; > + } > + } else { There're two spaces after else. > + PMD_DRV_LOG(ERR, "not support this type: %s.", type); > + return -EINVAL; > + } > + > + return 0; > +} > + > +static int > +cpfl_flow_js_mod_rule(json_object *json_root, struct cpfl_flow_js_parser > *parser) > +{ > + json_object *cjson_mr; > + int i, len; > + > + cjson_mr =3D json_object_object_get(json_root, "modifications"); > + if (!cjson_mr) { > + PMD_DRV_LOG(INFO, "The modifications is optional."); > + return 0; > + } > + > + len =3D json_object_array_length(cjson_mr); > + parser->mr_size =3D len; > + if (len =3D=3D 0) > + return 0; Move the check before 'parser->mr_size =3D len;'. > + parser->modifications =3D rte_malloc(NULL, sizeof(struct > cpfl_flow_js_mr) * len, 0); > + if (!parser->modifications) { > + PMD_DRV_LOG(ERR, "Failed to alloc memory."); > + return -ENOMEM; > + } > + > + for (i =3D 0; i < len; i++) { > + int ret; > + json_object *object, *cjson_mr_key, *cjson_mr_action, > *cjson_mr_key_action; > + > + object =3D json_object_array_get_idx(cjson_mr, i); > + /* mr->key */ > + cjson_mr_key =3D json_object_object_get(object, "key"); > + /* mr->key->actions */ > + cjson_mr_key_action =3D json_object_object_get(cjson_mr_key, > "actions"); > + > + ret =3D cpfl_flow_js_mr_key(cjson_mr_key_action, &parser- > >modifications[i].key); > + if (ret < 0) { > + rte_free(parser->modifications); > + PMD_DRV_LOG(ERR, "parse mr_key failed."); > + return -EINVAL; > + } > + /* mr->action */ > + cjson_mr_action =3D json_object_object_get(object, "action"); > + ret =3D cpfl_flow_js_mr_action(cjson_mr_action, &parser- > >modifications[i].action); > + if (ret < 0) { > + rte_free(parser->modifications); > + PMD_DRV_LOG(ERR, "parse mr_action failed."); > + return -EINVAL; > + } > + } > + > + return 0; > +} > + > +static int > +cpfl_parser_init(json_object *json_root, struct cpfl_flow_js_parser *par= ser) > +{ > + int ret =3D 0; > + > + ret =3D cpfl_flow_js_pattern_rule(json_root, parser); > + if (ret < 0) { > + PMD_DRV_LOG(ERR, "parse pattern_rule failed."); > + return ret; > + } > + ret =3D cpfl_flow_js_mod_rule(json_root, parser); > + if (ret < 0) { > + PMD_DRV_LOG(ERR, "parse mod_rule failed."); > + return ret; This ' return ret;' can be omitted. Since it will be executed at last anywa= y. > + } > + > + return ret; > +} > + > +int > +cpfl_parser_create(struct cpfl_flow_js_parser **flow_parser, const char > *filename) > +{ > + struct cpfl_flow_js_parser *parser; > + json_object *root; > + int ret; > + > + parser =3D 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 =3D json_object_from_file(filename); > + if (!root) { > + PMD_DRV_LOG(ERR, "Can not load JSON file: %s.", filename); > + rte_free(parser); > + return -EINVAL; > + } > + ret =3D cpfl_parser_init(root, parser); > + if (ret < 0) { > + PMD_DRV_LOG(ERR, "parser init failed."); > + rte_free(parser); > + return -EINVAL; > + } > + *flow_parser =3D parser; > + > + ret =3D json_object_put(root); > + if (ret !=3D 1) { > + PMD_DRV_LOG(ERR, "Free json_object failed."); Need to free parser here. For all the error handling, better to use goto. > + return -EINVAL; > + } > + > + return 0; > +} > + > +static void > +cpfl_parser_free_pr_action(struct cpfl_flow_js_pr_action *pr_act) > +{ > + if (pr_act->type =3D=3D CPFL_JS_PR_ACTION_TYPE_SEM) { > + if (pr_act->sem.fv) Rte_free will check the pointer, so if condition can be omitted. Please check all rte_free(xxx) in the patches. > + rte_free(pr_act->sem.fv); > + } > +} > + > +int > +cpfl_parser_destroy(struct cpfl_flow_js_parser *parser) > +{ > + int i, j; > + Better to check if parser is valid. > + for (i =3D 0; i < parser->pr_size; i++) { > + struct cpfl_flow_js_pr *pattern =3D &parser->patterns[i]; > + > + for (j =3D 0; j < pattern->key.proto_size; j++) { > + if (pattern->key.protocols[j].fields) > + rte_free(pattern->key.protocols[j].fields); > + } > + if (pattern->key.protocols) > + rte_free(pattern->key.protocols); > + > + if (pattern->key.attributes) > + rte_free(pattern->key.attributes); > + > + for (j =3D 0; j < pattern->actions_size; j++) { > + struct cpfl_flow_js_pr_action *pr_act; > + > + pr_act =3D &pattern->actions[j]; > + cpfl_parser_free_pr_action(pr_act); > + } > + > + if (pattern->actions) > + rte_free(pattern->actions); > + } > + if (parser->patterns) > + rte_free(parser->patterns); > + > + for (i =3D 0; i < parser->mr_size; i++) { > + struct cpfl_flow_js_mr *mr =3D &parser->modifications[i]; > + > + if (mr->key.actions) > + rte_free(mr->key.actions); > + if (mr->action.type =3D=3D CPFL_JS_MR_ACTION_TYPE_MOD && > mr->action.mod.layout) > + rte_free(mr->action.mod.layout); > + } > + if (parser->modifications) > + rte_free(parser->modifications); > + > + rte_free(parser); > + return 0; > +} > + <...> > + > +static int > +cpfl_parse_pr_actions(struct cpfl_flow_js_pr_action *actions, > + int size, > + const struct rte_flow_item *items, > + const struct rte_flow_attr *attr, > + struct cpfl_flow_pr_action *pr_action) > +{ > + int i, ret; > + > + for (i =3D 0; i < size; i++) { > + struct cpfl_flow_js_pr_action *pr_act; > + enum cpfl_flow_pr_action_type type; > + > + pr_act =3D &actions[i]; > + /* pr->actions->type */ > + type =3D pr_act->type; > + /* pr->actions->data */ > + if (attr->group % 10 =3D=3D 1 && type =3D=3D > CPFL_JS_PR_ACTION_TYPE_SEM) { > + struct cpfl_flow_js_pr_action_sem *sem =3D &pr_act- > >sem; > + > + pr_action->type =3D CPFL_JS_PR_ACTION_TYPE_SEM; > + pr_action->sem.prof =3D sem->prof; > + pr_action->sem.subprof =3D sem->subprof; > + pr_action->sem.keysize =3D sem->keysize; > + memset(pr_action->sem.cpfl_flow_pr_fv, 0, > + sizeof(pr_action->sem.cpfl_flow_pr_fv)); > + ret =3D cpfl_parse_fieldvectors(sem->fv, sem->fv_size, > + pr_action- > >sem.cpfl_flow_pr_fv, items); > + return ret; > + } else if (attr->group > 4 || attr->group =3D=3D 0) { What does 4 mean here? How about define a macro to describe it? > + return -EPERM; > + } > + } > + return 0; > +} > + > +static int > +str2MAC(const char *mask, uint8_t *addr_bytes) Please keep cpfl pmd function name style. > +{ > + int i, size, j; > + uint8_t n; > + > + size =3D strlen(mask); > + n =3D 0; > + j =3D 0; > + for (i =3D 0; i < size; i++) { > + char ch =3D mask[i]; > + > + if (ch =3D=3D ':') { > + if (j >=3D RTE_ETHER_ADDR_LEN) > + return -EINVAL; > + addr_bytes[j++] =3D n; > + n =3D 0; > + } else if (ch >=3D 'a' && ch <=3D 'f') { > + n =3D n * 16 + ch - 'a' + 10; > + } else if (ch >=3D 'A' && ch <=3D 'F') { > + n =3D n * 16 + ch - 'A' + 10; > + } else if (ch >=3D '0' && ch <=3D '9') { > + n =3D n * 16 + ch - '0'; > + } else { > + return -EINVAL; > + } > + } > + if (j < RTE_ETHER_ADDR_LEN) > + addr_bytes[j++] =3D n; > + > + if (j !=3D RTE_ETHER_ADDR_LEN) > + return -EINVAL; > + return 0; > +} > + > +static int > +cpfl_check_eth_mask(const char *mask, const uint8_t > addr_bytes[RTE_ETHER_ADDR_LEN]) > +{ > + int i, ret; > + uint8_t mask_bytes[RTE_ETHER_ADDR_LEN] =3D {0}; > + > + ret =3D str2MAC(mask, mask_bytes); > + if (ret < 0) { > + PMD_DRV_LOG(ERR, "string to mac address failed."); > + return -EINVAL; > + } > + for (i =3D 0; i < RTE_ETHER_ADDR_LEN; i++) { > + if (mask_bytes[i] !=3D addr_bytes[i]) > + return -EINVAL; > + } > + return 0; > +} > + > +static int > +cpfl_check_ipv4_mask(const char *mask, rte_be32_t addr) > +{ > + uint32_t out_addr; > + > + /* success return 0; invalid return -EINVAL; fail return -ENOTSUP */ > + int ret =3D inet_pton(AF_INET, mask, &out_addr); > + > + if (ret < 0) > + return -EINVAL; > + > + if (out_addr !=3D addr) > + return -EINVAL; > + > + return 0; > +} > + > +static int > +cpfl_check_eth(struct cpfl_flow_js_pr_key_proto *proto, const struct > rte_flow_item_eth *eth_mask) > +{ > + int field_size, j; > + int flag_dst_addr, flag_src_addr, flag_ether_type; > + struct cpfl_flow_js_pr_key_proto_field *field; > + > + if (!proto) > + return 0; > + /* eth_mask->dst.addr_bytes */ Could you detail the comments? Seems it's not related with the following co= de. > + > + field_size =3D proto->fields_size; > + if (field_size !=3D 0 && !eth_mask) > + return -EINVAL; > + > + if (field_size =3D=3D 0 && eth_mask) > + return -EINVAL; > + > + if (field_size =3D=3D 0 && !eth_mask) > + return 0; > + > + flag_dst_addr =3D false; > + flag_src_addr =3D false; > + flag_ether_type =3D false; > + for (j =3D 0; j < field_size; j++) { > + const char *name, *s_mask; > + > + field =3D &proto->fields[j]; > + /* match: rte_flow_item_eth.dst, more see Field Mapping > + */ > + name =3D field->name; > + /* match: rte_flow_item->mask */ > + if (strcmp(name, "src_addr") =3D=3D 0) { > + s_mask =3D field->mask; > + if (cpfl_check_eth_mask(s_mask, eth_mask- > >src.addr_bytes) < 0) > + return -EINVAL; > + flag_src_addr =3D true; > + } else if (strcmp(name, "dst_addr") =3D=3D 0) { > + s_mask =3D field->mask; > + if (cpfl_check_eth_mask(s_mask, eth_mask- > >dst.addr_bytes) < 0) > + return -EINVAL; > + flag_dst_addr =3D true; > + } else if (strcmp(name, "ether_type") =3D=3D 0) { > + uint16_t mask =3D (uint16_t)field->mask_32b; > + > + if (mask !=3D eth_mask->type) > + return -EINVAL; > + flag_ether_type =3D true; > + } else { > + /* TODO: more type... */ > + PMD_DRV_LOG(ERR, "not support this name."); > + return -EINVAL; > + } > + } > + if (!flag_src_addr) { > + if (strcmp((const char *)eth_mask->src.addr_bytes, > "\x00\x00\x00\x00\x00\x00") !=3D 0) > + return -EINVAL; > + } > + if (!flag_dst_addr) { > + if (strcmp((const char *)eth_mask->dst.addr_bytes, > "\x00\x00\x00\x00\x00\x00") !=3D 0) > + return -EINVAL; > + } > + if (!flag_ether_type) { > + if (eth_mask->hdr.ether_type !=3D (rte_be16_t)0) > + return -EINVAL; > + } > + > + return 0; > +} > + > +static int > +cpfl_check_ipv4(struct cpfl_flow_js_pr_key_proto *proto, const struct > rte_flow_item_ipv4 *ipv4_mask) > +{ > + if (proto) { How about=20 if (proto =3D=3D NULL) return 0; first? Please check all other functions. > + int field_size, j; > + int flag_next_proto_id, flag_src_addr, flag_dst_addr; > + struct cpfl_flow_js_pr_key_proto_field *field; > + > + field_size =3D proto->fields_size; > + if (field_size !=3D 0 && !ipv4_mask) > + return -EINVAL; > + > + if (field_size =3D=3D 0 && ipv4_mask) > + return -EINVAL; > + > + if (field_size =3D=3D 0 && !ipv4_mask) > + return 0; > + > + flag_dst_addr =3D false; > + flag_src_addr =3D false; > + flag_next_proto_id =3D false; > + for (j =3D 0; j < field_size; j++) { > + const char *name; > + > + field =3D &proto->fields[j]; > + name =3D field->name; > + if (strcmp(name, "src_addr") =3D=3D 0) { > + /* match: rte_flow_item->mask */ > + const char *mask; > + > + mask =3D field->mask; > + if (cpfl_check_ipv4_mask(mask, ipv4_mask- > >hdr.src_addr) < 0) > + return -EINVAL; > + flag_src_addr =3D true; > + } else if (strcmp(name, "dst_addr") =3D=3D 0) { > + const char *mask; > + > + mask =3D field->mask; > + if (cpfl_check_ipv4_mask(mask, ipv4_mask- > >hdr.dst_addr) < 0) > + return -EINVAL; > + flag_dst_addr =3D true; > + } else if (strcmp(name, "next_proto_id") =3D=3D 0) { > + uint8_t mask; > + > + mask =3D (uint8_t)field->mask_32b; > + if (mask !=3D ipv4_mask->hdr.next_proto_id) > + return -EINVAL; > + flag_next_proto_id =3D true; > + } else { > + PMD_DRV_LOG(ERR, "not support this > name."); > + return -EINVAL; > + } > + } > + if (!flag_src_addr) { > + if (ipv4_mask->hdr.src_addr !=3D (rte_be32_t)0) > + return -EINVAL; > + } > + if (!flag_dst_addr) { > + if (ipv4_mask->hdr.dst_addr !=3D (rte_be32_t)0) > + return -EINVAL; > + } > + if (!flag_next_proto_id) { > + if (ipv4_mask->hdr.next_proto_id !=3D (uint8_t)0) > + return -EINVAL; > + } > + } > + return 0; > +} > + <...> > +static int > +cpfl_check_pattern_key_proto(struct cpfl_flow_js_pr_key_proto *protocols= , > + int proto_size, > + const struct rte_flow_item *items) > +{ > + int i, length, j =3D 0; According to the coding style, split j =3D 0 from definition of i and lengt= h. > + > + length =3D cpfl_get_items_length(items); > + > + if (proto_size > length - 1) > + return -EINVAL; > + > + for (i =3D 0; i < proto_size; i++) { > + struct cpfl_flow_js_pr_key_proto *key_proto; > + enum rte_flow_item_type type; > + > + key_proto =3D &protocols[i]; > + /* pr->key->proto->type */ > + type =3D key_proto->type; > + /* pr->key->proto->fields */ > + switch (type) { > + case RTE_FLOW_ITEM_TYPE_ETH: > + if (items[j++].type =3D=3D RTE_FLOW_ITEM_TYPE_ETH) { > + const struct rte_flow_item_eth *eth_mask; > + int ret; > + > + eth_mask =3D (const struct rte_flow_item_eth > *)items[i].mask; > + ret =3D cpfl_check_eth(key_proto, eth_mask); > + if (ret < 0) > + return ret; > + } else { > + return -EINVAL; > + } > + break; <...> > + > + > +/* output: uint8_t *buffer, uint16_t *byte_len */ > +static int > +cpfl_parse_layout(struct cpfl_flow_js_mr_layout *layouts, int layout_siz= e, > + struct cpfl_flow_mr_key_action *mr_key_action, > + uint8_t *buffer, uint16_t *byte_len) > +{ > + int i, start =3D 0; int start =3D 0; int i; > + > + for (i =3D 0; i < layout_size; i++) { > + int index, size, offset; > + const char *hint; > + const uint8_t *addr; > + struct cpfl_flow_mr_key_action *temp; > + struct cpfl_flow_js_mr_layout *layout; > + > + layout =3D &layouts[i]; > + /* index links to the element of the actions array. */ > + index =3D layout->index; > + size =3D layout->size; > + offset =3D layout->offset; > + if (index =3D=3D -1) { > + hint =3D "dummpy"; > + start +=3D size; > + continue; > + } > + hint =3D layout->hint; > + addr =3D NULL; > + temp =3D mr_key_action + index; > + > + if (temp->type =3D=3D RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP) { > + const struct rte_flow_action_vxlan_encap > *action_vxlan_encap; > + struct rte_flow_item *definition; > + int def_length, k; > + > + action_vxlan_encap =3D > + (const struct rte_flow_action_vxlan_encap *)temp- > >encap.action->conf; > + definition =3D action_vxlan_encap->definition; > + def_length =3D cpfl_get_items_length(definition); > + for (k =3D 0; k < def_length - 1; k++) { > + if ((strcmp(hint, "eth") =3D=3D 0 && > + definition[k].type =3D=3D > RTE_FLOW_ITEM_TYPE_ETH) || > + (strcmp(hint, "ipv4") =3D=3D 0 && > + definition[k].type =3D=3D > RTE_FLOW_ITEM_TYPE_IPV4) || > + (strcmp(hint, "udp") =3D=3D 0 && > + definition[k].type =3D=3D > RTE_FLOW_ITEM_TYPE_UDP) || > + (strcmp(hint, "tcp") =3D=3D 0 && > + definition[k].type =3D=3D > RTE_FLOW_ITEM_TYPE_TCP) || > + (strcmp(hint, "vxlan") =3D=3D 0 && > + definition[k].type =3D=3D > RTE_FLOW_ITEM_TYPE_VXLAN)) { > + addr =3D (const uint8_t > *)(definition[k].spec); > + if (start > 255) { Better to use macro for 255. > + *byte_len =3D 0; > + PMD_DRV_LOG(ERR, "byte > length is too long%s", > + hint); > + return -EINVAL; > + } > + memcpy(buffer + start, addr + offset, > size); > + break; > + } /* TODO: more hint... */ > + } > + if (k =3D=3D def_length - 1) { > + *byte_len =3D 0; > + PMD_DRV_LOG(ERR, "can not find > corresponding hint: %s", hint); > + return -EINVAL; > + } > + } else { > + *byte_len =3D 0; > + PMD_DRV_LOG(ERR, "Not support this type: %d.", > temp->type); > + return -EINVAL; > + } > + /* else TODO: more type... */ > + > + start +=3D size; > + } > + *byte_len =3D start; > + return 0; > +} > + <...> > diff --git a/drivers/net/cpfl/cpfl_flow_parser.h > b/drivers/net/cpfl/cpfl_flow_parser.h > new file mode 100644 > index 0000000000..af33051ce2 > --- /dev/null > +++ b/drivers/net/cpfl/cpfl_flow_parser.h > @@ -0,0 +1,205 @@ > +/* SPDX-License-Identifier: BSD-3-Clause > + * Copyright(c) 2023 Intel Corporation > + */ > +#include > +#include > + > +#ifndef _CPFL_FLOW_PARSER_H_ > +#define _CPFL_FLOW_PARSER_H_ > + > +#define CPFL_FLOW_JSON_STR_SIZE_MAX 100 > + > +/* Pattern Rules Storage Begin*/ > +enum cpfl_flow_pr_action_type { > + CPFL_JS_PR_ACTION_TYPE_SEM, > + CPFL_JS_PR_ACTION_TYPE_UNKNOWN =3D -1, > +}; > + > +struct cpfl_flow_js_pr_key_attr { > + uint16_t ingress; > + uint16_t egress; > +}; > + > +struct cpfl_flow_js_pr_key_proto_field { > + char name[CPFL_FLOW_JSON_STR_SIZE_MAX]; > + union { > + char mask[CPFL_FLOW_JSON_STR_SIZE_MAX]; > + uint32_t mask_32b; > + }; > +}; > + > +struct cpfl_flow_js_pr_key_proto { > + enum rte_flow_item_type type; > + struct cpfl_flow_js_pr_key_proto_field *fields; > + int fields_size; > +}; > + > +enum cpfl_flow_js_fv_type { > + CPFL_FV_TYPE_PROTOCOL, > + CPFL_FV_TYPE_IMMEDIATE, > + CPFL_FV_TYPE_UNKNOWN =3D -1, > + No need the blank line. Could you add some comments for the type? > +}; > + > +struct cpfl_flow_js_fv { > + uint16_t offset; > + enum cpfl_flow_js_fv_type type; > + union { > + uint16_t immediate; > + struct { > + uint16_t layer; > + enum rte_flow_item_type header; > + uint16_t offset; > + uint16_t mask; > + } proto; > + }; > +}; > + > +#define CPFL_MAX_SEM_FV_KEY_SIZE 64 Move all macros up with CPFL_FLOW_JSON_STR_SIZE_MAX. <...>