From mboxrd@z Thu Jan  1 00:00:00 1970
Return-Path: <dev-bounces@dpdk.org>
Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124])
	by inbox.dpdk.org (Postfix) with ESMTP id 2AF2FA00BE;
	Mon, 20 Dec 2021 16:54:01 +0100 (CET)
Received: from [217.70.189.124] (localhost [127.0.0.1])
	by mails.dpdk.org (Postfix) with ESMTP id AAD6E40040;
	Mon, 20 Dec 2021 16:54:00 +0100 (CET)
Received: from mga17.intel.com (mga17.intel.com [192.55.52.151])
 by mails.dpdk.org (Postfix) with ESMTP id 7182D4003C
 for <dev@dpdk.org>; Mon, 20 Dec 2021 16:53:58 +0100 (CET)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple;
 d=intel.com; i=@intel.com; q=dns/txt; s=Intel;
 t=1640015638; x=1671551638;
 h=from:to:cc:subject:date:message-id:references:
 in-reply-to:content-transfer-encoding:mime-version;
 bh=ZOlmAUQk8F6Fk9qJO6wcvJAvptyidNmAeIwmFOa5scI=;
 b=WHovkF0FNf0+rbVLMsyv1m6JgnnT/22xdWbK1INnTmYpK+7dGdMIFodD
 +K15XH+08eXPDluFJ+6bfTK3pIUdmFAlzeUZG7kxUBFiz3Gd3KwvYeIg4
 7goQFdMipu1cFAOGTb8C5NMll+KBa7xgAn+shXrbm9UcGaezuIsgpcBRh
 y+SE+1HcJKBhghttPm/Z+sBhg0nmRcXCYLRxRZknI0gfDwTZCiPz8Pixz
 CvMizdP1FO+sBSAC+8FzDRC9vzZR5KIAS/Wlj1JpaG0yU43BP3U2CgEYw
 xYL1bWEOB3XQcLfaRipPRhxowys3xOY9Nuvn2B6y7U9rDjewTAD+FLSB6 g==;
X-IronPort-AV: E=McAfee;i="6200,9189,10203"; a="220883688"
X-IronPort-AV: E=Sophos;i="5.88,220,1635231600"; d="scan'208";a="220883688"
Received: from orsmga004.jf.intel.com ([10.7.209.38])
 by fmsmga107.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384;
 20 Dec 2021 07:53:57 -0800
X-ExtLoop1: 1
X-IronPort-AV: E=Sophos;i="5.88,220,1635231600"; d="scan'208";a="616443656"
Received: from orsmsx605.amr.corp.intel.com ([10.22.229.18])
 by orsmga004.jf.intel.com with ESMTP; 20 Dec 2021 07:53:57 -0800
Received: from orsmsx601.amr.corp.intel.com (10.22.229.14) by
 ORSMSX605.amr.corp.intel.com (10.22.229.18) with Microsoft SMTP Server
 (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id
 15.1.2308.20; Mon, 20 Dec 2021 07:53:56 -0800
Received: from ORSEDG601.ED.cps.intel.com (10.7.248.6) by
 orsmsx601.amr.corp.intel.com (10.22.229.14) with Microsoft SMTP Server
 (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id
 15.1.2308.20 via Frontend Transport; Mon, 20 Dec 2021 07:53:56 -0800
Received: from NAM10-MW2-obe.outbound.protection.outlook.com (104.47.55.105)
 by edgegateway.intel.com (134.134.137.102) with Microsoft SMTP Server
 (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id
 15.1.2308.20; Mon, 20 Dec 2021 07:53:56 -0800
ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none;
 b=JUGKGN4i4XMKo/eV4GeptwPQ2fmsS3quQrbMRzrNH4ZDv/jQppoPKuMbwAc7zHHueumRRKModJ1nNFf9nBSNtNahg2AVF1UqiNEfax3PAdJIFc+GXs3l02JHHBlT2x0vW+qO06Fw4tXce3VhOQ/1X57HY4+UxOzkTOb4hlJ86kfayQN88VJX5CVhaJblXwH7WlKqCcePZ+tIgL3KYlFET/J78Ku9J+CMPhFQm8kpU1E3uoY53rpq0p2AK4fem9p9gFXfMByUEH1Uz/3l2Rqk+IwAnvqCfv352/gSej0aH7VC6EBTUcqLs0MHMBA+h6n2SYqmGoJMuRf9XwiQepMfxw==
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=6S6K9rnuPxxjwSAH0sGypijIG6/2rdFh6xCl9NHQJAA=;
 b=H7JrPdcO5Jyz2w7BrDW1u6bRYPDN7zSpLQ/cO65RS0SkEadDTNQPDW/lCm1J/nZgZbUXW8ETtSsQeVgq3/K+Bq5epo+/JItlp/3FaOtuCFmKp+KBIKWfUXqozSp0x3JP0/jY2nf9epTU22fX2EHyk3Vusj2Oyuv2gOaI/btCd8vDhEvTs1x0QvGeuCycRaXN8V4kYKLCMCk9Di4fRDpUXDddWPkFFgHtCXQFC8I9LKc5sB8JnqBXxnahA3N2bsiBb7U62kDEMUZD0zcWoMm5XgCs8l6FzQOqeK1ArVw1NEdhxYBFN9te20idQzTNtYS/Ky+0JY0/J75PJfh18Y82cw==
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 DM6PR11MB4491.namprd11.prod.outlook.com (2603:10b6:5:204::19)
 by DM6PR11MB4379.namprd11.prod.outlook.com (2603:10b6:5:1db::19) with
 Microsoft SMTP Server (version=TLS1_2,
 cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4801.14; Mon, 20 Dec
 2021 15:53:54 +0000
Received: from DM6PR11MB4491.namprd11.prod.outlook.com
 ([fe80::fc25:a06b:f39b:569a]) by DM6PR11MB4491.namprd11.prod.outlook.com
 ([fe80::fc25:a06b:f39b:569a%5]) with mapi id 15.20.4801.020; Mon, 20 Dec 2021
 15:53:54 +0000
From: "Ananyev, Konstantin" <konstantin.ananyev@intel.com>
To: "Morrissey, Sean" <sean.morrissey@intel.com>
CC: "dev@dpdk.org" <dev@dpdk.org>, "Morrissey, Sean"
 <sean.morrissey@intel.com>, Ravi Kerur <rkerur@gmail.com>
Subject: RE: [PATCH v2 2/2] examples/l3fwd: add config file support for EM
Thread-Topic: [PATCH v2 2/2] examples/l3fwd: add config file support for EM
Thread-Index: AQHX9ZIRwkkTggUtEkC52JNoIIfmDaw7hWtQ
Date: Mon, 20 Dec 2021 15:53:53 +0000
Message-ID: <DM6PR11MB4491669FC49FC37A1B685A239A7B9@DM6PR11MB4491.namprd11.prod.outlook.com>
References: <20211216150104.860924-1-sean.morrissey@intel.com>
 <20211220110837.970261-1-sean.morrissey@intel.com>
 <20211220110837.970261-3-sean.morrissey@intel.com>
In-Reply-To: <20211220110837.970261-3-sean.morrissey@intel.com>
Accept-Language: en-GB, en-US
Content-Language: en-US
X-MS-Has-Attach: 
X-MS-TNEF-Correlator: 
dlp-product: dlpe-windows
dlp-reaction: no-action
dlp-version: 11.6.200.16
authentication-results: dkim=none (message not signed)
 header.d=none;dmarc=none action=none header.from=intel.com;
x-ms-publictraffictype: Email
x-ms-office365-filtering-correlation-id: 9ab4aefd-9a87-4249-b0d8-08d9c3d0eca7
x-ms-traffictypediagnostic: DM6PR11MB4379:EE_
x-microsoft-antispam-prvs: <DM6PR11MB4379F27E73E3DF0281CBC2A29A7B9@DM6PR11MB4379.namprd11.prod.outlook.com>
x-ms-oob-tlc-oobclassifiers: OLM:883;
x-ms-exchange-senderadcheck: 1
x-ms-exchange-antispam-relay: 0
x-microsoft-antispam: BCL:0;
x-microsoft-antispam-message-info: v4/FzkAed4c/kFwiblL+Wc2OSc0osG+aOM4nuHsmw5pElxreKwCgXBrDQJjBg2wy81hv+LAF/N/mKNeRAtZwLUEUTry9VmldjqtXhAX1rmzSy5pnwWiPd7q/2CGVzNtmz5dss9wnOBhqI7nmjHpNV2jTjZ7xmttZYKxWInBRBPu9l4iIA+NZZ+Xt8BcXDWIoVu/VF18E9Z+3K0grWIQqPHQ2eEOp1NBq5RfEBesiNgXkocZ4qpkNKAmimUvWJ33jo89B8ZC8RLMqSc294slHjcDgJDfsGX06wfyeDUtUs2L8brEtfFD2l/G5hS7Z0uxw+8FrqK4LCyBxbseNW7ryIElcM2WeKj1A03xe9ERcjMwCbi0IN5zxlR9ZDO9VsUqOUUixcxXEW+QLKCkyatWFYdmtj3Z08/2fSPUW07yB1uZ53GE9lY1snAWWV4MK2cT1igtZ48jnkx6DVvRPyjXMTo8KOqPoAfr2Jkg2pbb/O7PJKOcGicykzvjVwRTtIdilxYF4yL51d9kvMevSmFXm/69D8HHf3jlQgxzvIwr2J0QTIVFBabIkeE3s1k5ErqMln/CxZVVvWPd4Dfsy6uBrAWiBUbmKqMbuYkXq3haVczsMgt4tSKTTLCT2baSCGPY7Ac313r6yhSPeEqxsCshPw2h1TmBCYr0DHCAAnhda89mPo3VJib2HiMSXSDbg8C/fpkrWJACL+TnHdMYYBjtJDg==
x-forefront-antispam-report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:;
 IPV:NLI; SFV:NSPM; H:DM6PR11MB4491.namprd11.prod.outlook.com; PTR:; CAT:NONE;
 SFS:(366004)(186003)(38070700005)(82960400001)(83380400001)(5660300002)(33656002)(54906003)(7696005)(30864003)(9686003)(508600001)(26005)(2906002)(316002)(6636002)(6506007)(4326008)(8676002)(8936002)(66946007)(66476007)(55236004)(76116006)(6862004)(66446008)(64756008)(66556008)(55016003)(71200400001)(52536014)(38100700002)(122000001)(86362001);
 DIR:OUT; SFP:1102; 
x-ms-exchange-antispam-messagedata-chunkcount: 1
x-ms-exchange-antispam-messagedata-0: =?us-ascii?Q?yZjOM0+FTQLp5dEmBZlu4UmMPnXXXTXoNdgYTDiqD+FaorVK0DZFeQyWBYX5?=
 =?us-ascii?Q?WqMkrZ200r4Un/ODiDn5V0NZa/LXtjkC0RpxIEO52+ftVgc5egha479wbqV2?=
 =?us-ascii?Q?nQVqV09E/6FF+AKtbBg2rT44A2wUR12q8zof5sbexvN9QphOxb8jXm+qpwbm?=
 =?us-ascii?Q?Hi1hbNOj7hOkYq5xDPbkIoBuBeCr/hjuVRueXyIuiwvqqe3pgwaUvWVFnPPs?=
 =?us-ascii?Q?GE5zjeSkwcwGboc9riRs39XeMeRr9cR6uSWiyX/WKEUt1t7+osnhttgyF/Ik?=
 =?us-ascii?Q?zP5YvwO0lGFcBs0lCg+Ua+pt44QhNOKfcGkuu5qmfkzsFL+yiCMCsh+yWns5?=
 =?us-ascii?Q?xvwo9SqhzKPqN4CeRHfbjHK2+J+ke950kIYlEPOWMGFPHMi7y01YYWWVte4s?=
 =?us-ascii?Q?h+O57qWZdR+jiaBL2vrYuIDgPD4U3u942jUqaY20LHNxIqqzhk02cumtvRLK?=
 =?us-ascii?Q?qapGpuQwXzTkT5M4vx71tBp27DfIwaQW8gz/lJ+1TnqFqNl8LrV8X/PJxKBi?=
 =?us-ascii?Q?e/GxBIX9I+RH7Lad82nM0RBVvaZDBxGQAQxbDQixO/nX+P0m6bNzRPDbA1vj?=
 =?us-ascii?Q?5OiFs5FMA81EpMzi7em1E7vKQjMLyUi6JjTfC5qffyLGlAAbSCwyK8065UYV?=
 =?us-ascii?Q?Pg+1LGPBoQgSPxJyZa93Pz4K32pP2vcbi9rPy/7v0QPFfQ5/zM853yCG2XZH?=
 =?us-ascii?Q?JKAaiMIZ8g+G3/DdxYkJFlhpkIzGzNJOFN0lUMimsS7IVAjVpAEDJVV6qcCW?=
 =?us-ascii?Q?NgqXqKQ/KswYknO0up6gQWVVDvw+jySh38IUAhKoK9kFpzfVR3ekimW9e+WV?=
 =?us-ascii?Q?OOOOxoIwoL/sOYN0R2SRcJSeAoElapqEtifhsB0LhjpXkzbfvgDWRVKb72PN?=
 =?us-ascii?Q?LibkPNGkwDoHTPhYtM/6c+AQTHNxrXrzTi7kl/YYkg6b4pQbmApJ3zMn6fEV?=
 =?us-ascii?Q?K5nbBviQS0JhO+qxe1NvLFDOs0UkQZpB2vscZJg6c3r3+0bHSwqeJeLiIfHx?=
 =?us-ascii?Q?2YI+1TI2dSiap0Xa7yvxHj0xgQKsUGm10oNb74GpAadpfA8zvMs0ysnZFEO7?=
 =?us-ascii?Q?t/VQqWA6FegDHPY0h9LjmrRQXp+szlG3oZmWwfzR6QePDRSG1nLEHCfQUHF8?=
 =?us-ascii?Q?IbtpzhddterqX0p59oFYLPBtsKf49/LDGgGitqYKUHt/mOmNVkptK/tGVCff?=
 =?us-ascii?Q?2gVYFP2EXZZCninQWb+ZW3ZJ29a0kFLAR8Vgyl6dTPwFaTmtWZXYTLY2RVjP?=
 =?us-ascii?Q?2SiHz0Jx+llzTw0dzahGczaEiqWTunAsm6QFBkQ26z9qmVHXfHmJxKs3lhy6?=
 =?us-ascii?Q?qbBxtCAv5Pz+qrKtLfDi+/H1HftcntawG+omfbJCdNF5HMZQrSC/Z9zlPGV3?=
 =?us-ascii?Q?hKXO6L6V8/YRZoqhIxg3F8XgPYPqPmwKkR0MdxcgyYkYpFzsS8PjKTNYj4qZ?=
 =?us-ascii?Q?pNFCwGdGU3gBjUasxBl2KtYuDw5mP+v3WoGEB4lWVwR6EN2E4v1bxg7rVhBn?=
 =?us-ascii?Q?LqQRa3uEFsmuuSTAGaUR+Er2XBoH/TFPcWcD8MMnFrCCib65aSH95OgXfsAc?=
 =?us-ascii?Q?VsUDIKWXdNH8VyQ1V6IYw2YUmOzZZZAcEgNw22SiggcbIAU97Csq50OpuYAk?=
 =?us-ascii?Q?wL3O83dF4RvLs53HvLBLVS6gb3MhJdA5ZDN8ssfom7+09a/n0MqkuU0xyLaz?=
 =?us-ascii?Q?v62uOw=3D=3D?=
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: DM6PR11MB4491.namprd11.prod.outlook.com
X-MS-Exchange-CrossTenant-Network-Message-Id: 9ab4aefd-9a87-4249-b0d8-08d9c3d0eca7
X-MS-Exchange-CrossTenant-originalarrivaltime: 20 Dec 2021 15:53:53.9725 (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: J2Osql3fSeCCPCyeW4WTHSzqSHDGwPOUh7lS7EdH2xer0shOx1RU6I7Mh5aDUkL61Adpu8xWv6WmgUbLyBTkE1SJWCQvE3D/mmEDHcGB7gs=
X-MS-Exchange-Transport-CrossTenantHeadersStamped: DM6PR11MB4379
X-OriginatorOrg: intel.com
X-BeenThere: dev@dpdk.org
X-Mailman-Version: 2.1.29
Precedence: list
List-Id: DPDK patches and discussions <dev.dpdk.org>
List-Unsubscribe: <https://mails.dpdk.org/options/dev>,
 <mailto:dev-request@dpdk.org?subject=unsubscribe>
List-Archive: <http://mails.dpdk.org/archives/dev/>
List-Post: <mailto:dev@dpdk.org>
List-Help: <mailto:dev-request@dpdk.org?subject=help>
List-Subscribe: <https://mails.dpdk.org/listinfo/dev>,
 <mailto:dev-request@dpdk.org?subject=subscribe>
Errors-To: dev-bounces@dpdk.org


Hi Sean,

Few comments below.

> Add support to define ipv4 and ipv6 forwarding tables
> from reading from a config file for EM with a format
> similar to l3fwd-acl one.
>=20
> With the removal of the hardcoded route tables for IPv4
> and IPv6 from 'l3fwd_em', these routes have been moved
> to a separate default config file for use with EM.
>=20
> Related l3fwd docs have been updated to relfect these
> changes.
>=20
> Signed-off-by: Sean Morrissey <sean.morrissey@intel.com>
> Signed-off-by: Ravi Kerur <rkerur@gmail.com>
> ---
>  doc/guides/sample_app_ug/l3_forward.rst |  89 +++--
>  examples/l3fwd/em_default_v4.cfg        |  17 +
>  examples/l3fwd/em_default_v6.cfg        |  17 +
>  examples/l3fwd/l3fwd_em.c               | 473 ++++++++++++++----------
>  examples/l3fwd/l3fwd_route.h            |  38 +-
>  5 files changed, 412 insertions(+), 222 deletions(-)
>  create mode 100644 examples/l3fwd/em_default_v4.cfg
>  create mode 100644 examples/l3fwd/em_default_v6.cfg
>=20

...

> diff --git a/examples/l3fwd/l3fwd_em.c b/examples/l3fwd/l3fwd_em.c

....

> @@ -346,6 +278,178 @@ em_get_ipv6_dst_port(void *ipv6_hdr, uint16_t porti=
d, void *lookup_struct)
>  #include "l3fwd_em.h"
>  #endif
>=20
> +static int
> +em_parse_v6_net(const char *in, uint32_t *v)
> +{
> +	int32_t rc;
> +
> +	/* get address. */
> +	rc =3D inet_pton(AF_INET6, in, &v);

Why '&v'?
I believe it should be:
rc =3D inet_pton(AF_INET6, in, v);
here.

> +	if (rc !=3D 1)
> +		return -EINVAL;
> +
> +	return 0;
> +}
> +
> +static int
> +em_parse_v6_rule(char *str, struct em_rule *v)
> +{
> +	int i, rc;
> +	uint32_t ip[4];
> +	char *s, *sp, *in[CB_FLD_MAX];
> +	static const char *dlm =3D " \t\n";
> +	int dim =3D CB_FLD_MAX;
> +	s =3D str;
> +
> +	for (i =3D 0; i !=3D dim; i++, s =3D NULL) {
> +		in[i] =3D strtok_r(s, dlm, &sp);
> +		if (in[i] =3D=3D NULL)
> +			return -EINVAL;
> +	}
> +
> +	ip[0] =3D *(v->v6_key.ip32_dst);
> +	rc =3D em_parse_v6_net(in[CB_FLD_DST_ADDR], ip);

Doesn't look right to me.
I think it should be just:
rc =3D em_parse_v6_net(in[CB_FLD_DST_ADDR], v->v6_key.ip32_dst);
and we don't need local 'ip[]' at all.=20


> +	if (rc !=3D 0)
> +		return rc;
> +	ip[0] =3D *(v->v6_key.ip32_src);
> +	rc =3D em_parse_v6_net(in[CB_FLD_SRC_ADDR], ip);

Same:
rc =3D em_parse_v6_net(in[CB_FLD_SRC_ADDR], v->v6_key.ip32_src);

> +	if (rc !=3D 0)
> +		return rc;
> +
> +
> +	/* source port. */
> +	GET_CB_FIELD(in[CB_FLD_SRC_PORT], v->v6_key.port_src, 0, UINT16_MAX, 0)=
;
> +	/* destination port. */
> +	GET_CB_FIELD(in[CB_FLD_DST_PORT], v->v6_key.port_dst, 0, UINT16_MAX, 0)=
;
> +	/* protocol. */
> +	GET_CB_FIELD(in[CB_FLD_PROTO], v->v6_key.proto, 0, UINT8_MAX, 0);
> +	/* out interface. */
> +	GET_CB_FIELD(in[CB_FLD_IF_OUT], v->if_out, 0, UINT8_MAX, 0);
> +
> +	return 0;
> +}
> +
> +static int
> +em_parse_v4_rule(char *str, struct em_rule *v)
> +{
> +	int i, rc;
> +	char *s, *sp, *in[CB_FLD_MAX];
> +	static const char *dlm =3D " \t\n";
> +	int dim =3D CB_FLD_MAX;
> +	s =3D str;
> +
> +	for (i =3D 0; i !=3D dim; i++, s =3D NULL) {
> +		in[i] =3D strtok_r(s, dlm, &sp);
> +		if (in[i] =3D=3D NULL)
> +			return -EINVAL;
> +	}
> +
> +	rc =3D inet_pton(AF_INET, in[CB_FLD_DST_ADDR], &(v->v4_key.ip_dst));
> +	v->v4_key.ip_dst =3D ntohl(v->v4_key.ip_dst);
> +	if (rc !=3D 1)
> +		return rc;
> +
> +	rc =3D inet_pton(AF_INET, in[CB_FLD_SRC_ADDR], &(v->v4_key.ip_src));
> +	v->v4_key.ip_src =3D ntohl(v->v4_key.ip_src);
> +	if (rc !=3D 1)
> +		return rc;
> +
> +	/* source port. */
> +	GET_CB_FIELD(in[CB_FLD_SRC_PORT], v->v4_key.port_src, 0, UINT16_MAX, 0)=
;
> +	/* destination port. */
> +	GET_CB_FIELD(in[CB_FLD_DST_PORT], v->v4_key.port_dst, 0, UINT16_MAX, 0)=
;
> +	/* protocol. */
> +	GET_CB_FIELD(in[CB_FLD_PROTO], v->v4_key.proto, 0, UINT8_MAX, 0);
> +	/* out interface. */
> +	GET_CB_FIELD(in[CB_FLD_IF_OUT], v->if_out, 0, UINT8_MAX, 0);
> +
> +	return 0;
> +}
> +
> +static int
> +em_add_rules(const char *rule_path,
> +		struct em_rule **proute_base,
> +		int (*parser)(char *, struct em_rule *))
> +{
> +	struct em_rule *route_rules;
> +	struct em_rule *next;
> +	unsigned int route_num =3D 0;
> +	unsigned int route_cnt =3D 0;
> +	char buff[LINE_MAX];
> +	FILE *fh;
> +	unsigned int i =3D 0, rule_size =3D sizeof(*next);
> +	int val;
> +
> +	*proute_base =3D NULL;
> +	fh =3D fopen(rule_path, "rb");
> +	if (fh =3D=3D NULL)
> +		return -EINVAL;
> +
> +	while ((fgets(buff, LINE_MAX, fh) !=3D NULL)) {
> +		if (buff[0] =3D=3D ROUTE_LEAD_CHAR)
> +			route_num++;
> +	}
> +
> +	if (route_num =3D=3D 0) {
> +		fclose(fh);
> +		return -EINVAL;
> +	}
> +
> +	val =3D fseek(fh, 0, SEEK_SET);
> +	if (val < 0) {
> +		fclose(fh);
> +		return -EINVAL;
> +	}
> +
> +	route_rules =3D calloc(route_num, rule_size);
> +
> +	if (route_rules =3D=3D NULL) {
> +		fclose(fh);
> +		return -EINVAL;
> +	}
> +
> +	i =3D 0;
> +	while (fgets(buff, LINE_MAX, fh) !=3D NULL) {
> +		i++;
> +		if (is_bypass_line(buff))
> +			continue;
> +
> +		char s =3D buff[0];
> +
> +		/* Route entry */
> +		if (s =3D=3D ROUTE_LEAD_CHAR)
> +			next =3D &route_rules[route_cnt];
> +
> +		/* Illegal line */
> +		else {
> +			RTE_LOG(ERR, L3FWD,
> +				"%s Line %u: should start with leading "
> +				"char %c\n",
> +				rule_path, i, ROUTE_LEAD_CHAR);
> +			fclose(fh);
> +			free(route_rules);
> +			return -EINVAL;
> +		}
> +
> +		if (parser(buff + 1, next) !=3D 0) {
> +			RTE_LOG(ERR, L3FWD,
> +				"%s Line %u: parse rules error\n",
> +				rule_path, i);
> +			fclose(fh);
> +			free(route_rules);
> +			return -EINVAL;
> +		}
> +
> +		route_cnt++;
> +	}
> +
> +	fclose(fh);
> +
> +	*proute_base =3D route_rules;
> +
> +	return route_cnt;
> +}
> +
>  static void
>  convert_ipv4_5tuple(struct ipv4_5tuple *key1,
>  		union ipv4_5tuple_host *key2)
> @@ -382,122 +486,92 @@ convert_ipv6_5tuple(struct ipv6_5tuple *key1,
>  #define BIT_8_TO_15 0x0000ff00
>=20
>  static inline void
> -populate_ipv4_few_flow_into_table(const struct rte_hash *h)
> +populate_ipv4_flow_into_table(const struct rte_hash *h)
>  {
> -	uint32_t i;
> +	int i;
>  	int32_t ret;
> +	struct rte_eth_dev_info dev_info;
> +	char srcbuf[INET6_ADDRSTRLEN];
> +	char dstbuf[INET6_ADDRSTRLEN];
>=20
>  	mask0 =3D (rte_xmm_t){.u32 =3D {BIT_8_TO_15, ALL_32_BITS,
>  				ALL_32_BITS, ALL_32_BITS} };
>=20
> -	for (i =3D 0; i < IPV4_L3FWD_EM_NUM_ROUTES; i++) {
> -		struct ipv4_l3fwd_em_route  entry;
> +	for (i =3D 0; i < route_num_v4; i++) {
> +		struct em_rule *entry;
>  		union ipv4_5tuple_host newkey;
> +		struct in_addr src;
> +		struct in_addr dst;
>=20
> -		entry =3D ipv4_l3fwd_em_route_array[i];
> -		convert_ipv4_5tuple(&entry.key, &newkey);
> +		if ((1 << em_route_base_v4[i].if_out &
> +				enabled_port_mask) =3D=3D 0)
> +			continue;
> +
> +		entry =3D &em_route_base_v4[i];
> +		convert_ipv4_5tuple(&(entry->v4_key), &newkey);
>  		ret =3D rte_hash_add_key(h, (void *) &newkey);
>  		if (ret < 0) {
>  			rte_exit(EXIT_FAILURE, "Unable to add entry %" PRIu32
>  				" to the l3fwd hash.\n", i);
>  		}
> -		ipv4_l3fwd_out_if[ret] =3D entry.if_out;
> +		ipv4_l3fwd_out_if[ret] =3D entry->if_out;
> +		rte_eth_dev_info_get(em_route_base_v4[i].if_out,
> +				     &dev_info);
> +
> +		src.s_addr =3D htonl(em_route_base_v4[i].v4_key.ip_src);
> +		dst.s_addr =3D htonl(em_route_base_v4[i].v4_key.ip_dst);
> +		printf("EM: Adding route %s %s (%d) [%s]\n",
> +			   inet_ntop(AF_INET, &dst, dstbuf, sizeof(dstbuf)),
> +		       inet_ntop(AF_INET, &src, srcbuf, sizeof(srcbuf)),
> +		       em_route_base_v4[i].if_out, dev_info.device->name);
>  	}
>  	printf("Hash: Adding 0x%" PRIx64 " keys\n",
> -		(uint64_t)IPV4_L3FWD_EM_NUM_ROUTES);
> +		(uint64_t)route_num_v4);
>  }
>=20
>  #define BIT_16_TO_23 0x00ff0000
>  static inline void
> -populate_ipv6_few_flow_into_table(const struct rte_hash *h)
> +populate_ipv6_flow_into_table(const struct rte_hash *h)
>  {
> -	uint32_t i;
> +	int i;
>  	int32_t ret;
> +	struct rte_eth_dev_info dev_info;
> +	char srcbuf[INET6_ADDRSTRLEN];
> +	char dstbuf[INET6_ADDRSTRLEN];
>=20
>  	mask1 =3D (rte_xmm_t){.u32 =3D {BIT_16_TO_23, ALL_32_BITS,
>  				ALL_32_BITS, ALL_32_BITS} };
>=20
>  	mask2 =3D (rte_xmm_t){.u32 =3D {ALL_32_BITS, ALL_32_BITS, 0, 0} };
>=20
> -	for (i =3D 0; i < IPV6_L3FWD_EM_NUM_ROUTES; i++) {
> -		struct ipv6_l3fwd_em_route entry;
> +	for (i =3D 0; i < route_num_v6; i++) {
> +		struct em_rule *entry;
>  		union ipv6_5tuple_host newkey;
>=20
> -		entry =3D ipv6_l3fwd_em_route_array[i];
> -		convert_ipv6_5tuple(&entry.key, &newkey);
> +		if ((1 << em_route_base_v6[i].if_out &
> +				enabled_port_mask) =3D=3D 0)
> +			continue;
> +
> +		entry =3D &em_route_base_v6[i];
> +		convert_ipv6_5tuple(&(entry->v6_key), &newkey);
>  		ret =3D rte_hash_add_key(h, (void *) &newkey);
>  		if (ret < 0) {
>  			rte_exit(EXIT_FAILURE, "Unable to add entry %" PRIu32
>  				" to the l3fwd hash.\n", i);
>  		}
> -		ipv6_l3fwd_out_if[ret] =3D entry.if_out;
> +		ipv6_l3fwd_out_if[ret] =3D entry->if_out;
> +		rte_eth_dev_info_get(em_route_base_v6[i].if_out,
> +				     &dev_info);
> +
> +		printf("EM: Adding route %s %s (%d) [%s]\n",
> +			   inet_ntop(AF_INET6, em_route_base_v6[i].v6_key.ip32_dst,
> +			   dstbuf, sizeof(dstbuf)),
> +		       inet_ntop(AF_INET6, em_route_base_v6[i].v6_key.ip32_src,
> +			   srcbuf, sizeof(srcbuf)),
> +		       em_route_base_v6[i].if_out, dev_info.device->name);

I think we need to print full key here: <dest_ip,src_ip, dst_port, src_port=
, proro>.
Otherwise it is sort of misleading.
Same for ipv4.


>  	}
>  	printf("Hash: Adding 0x%" PRIx64 "keys\n",
> -		(uint64_t)IPV6_L3FWD_EM_NUM_ROUTES);
> -}
> -
> -#define NUMBER_PORT_USED 16
> -static inline void
> -populate_ipv4_many_flow_into_table(const struct rte_hash *h,
> -		unsigned int nr_flow)
> -{
> -	unsigned i;
> -
> -	mask0 =3D (rte_xmm_t){.u32 =3D {BIT_8_TO_15, ALL_32_BITS,
> -				ALL_32_BITS, ALL_32_BITS} };
> -
> -	for (i =3D 0; i < nr_flow; i++) {
> -		uint8_t port =3D i % NUMBER_PORT_USED;
> -		struct ipv4_l3fwd_em_route entry;
> -		union ipv4_5tuple_host newkey;
> -
> -		uint8_t a =3D (uint8_t)((port + 1) % BYTE_VALUE_MAX);
> -
> -		/* Create the ipv4 exact match flow */
> -		memset(&entry, 0, sizeof(entry));
> -		entry =3D ipv4_l3fwd_em_route_array[port];
> -		entry.key.ip_dst =3D RTE_IPV4(198, 18, port, a);
> -		convert_ipv4_5tuple(&entry.key, &newkey);
> -		int32_t ret =3D rte_hash_add_key(h, (void *) &newkey);
> -
> -		if (ret < 0)
> -			rte_exit(EXIT_FAILURE, "Unable to add entry %u\n", i);
> -
> -		ipv4_l3fwd_out_if[ret] =3D (uint8_t) entry.if_out;
> -
> -	}
> -	printf("Hash: Adding 0x%x keys\n", nr_flow);
> -}
> -
> -static inline void
> -populate_ipv6_many_flow_into_table(const struct rte_hash *h,
> -		unsigned int nr_flow)
> -{
> -	unsigned i;
> -
> -	mask1 =3D (rte_xmm_t){.u32 =3D {BIT_16_TO_23, ALL_32_BITS,
> -				ALL_32_BITS, ALL_32_BITS} };
> -	mask2 =3D (rte_xmm_t){.u32 =3D {ALL_32_BITS, ALL_32_BITS, 0, 0} };
> -
> -	for (i =3D 0; i < nr_flow; i++) {
> -		uint8_t port =3D i % NUMBER_PORT_USED;
> -		struct ipv6_l3fwd_em_route entry;
> -		union ipv6_5tuple_host newkey;
> -
> -		/* Create the ipv6 exact match flow */
> -		memset(&entry, 0, sizeof(entry));
> -		entry =3D ipv6_l3fwd_em_route_array[port];
> -		entry.key.ip_dst[15] =3D (port + 1) % BYTE_VALUE_MAX;
> -		convert_ipv6_5tuple(&entry.key, &newkey);
> -		int32_t ret =3D rte_hash_add_key(h, (void *) &newkey);
> -
> -		if (ret < 0)
> -			rte_exit(EXIT_FAILURE, "Unable to add entry %u\n", i);
> -
> -		ipv6_l3fwd_out_if[ret] =3D (uint8_t) entry.if_out;
> -
> -	}
> -	printf("Hash: Adding 0x%x keys\n", nr_flow);
> +		(uint64_t)route_num_v6);
>  }
>=20
>  /* Requirements:
> @@ -972,17 +1046,53 @@ em_event_main_loop_tx_q_burst_vector(__rte_unused =
void *dummy)
>  	return 0;
>  }
>=20
> +static void
> +free_em_routes(void)
> +{
> +	free(em_route_base_v4);
> +	free(em_route_base_v6);
> +	em_route_base_v4 =3D NULL;
> +	em_route_base_v6 =3D NULL;
> +	route_num_v4 =3D 0;
> +	route_num_v6 =3D 0;
> +}
> +
>  /* Load rules from the input file */
>  void
>  read_config_files_em(void)
>  {
> -	/* Empty till config file support added to EM */
> +	/* ipv4 check */
> +	if (parm_config.rule_ipv4_name !=3D NULL) {
> +		route_num_v4 =3D em_add_rules(parm_config.rule_ipv4_name,
> +					&em_route_base_v4, &em_parse_v4_rule);
> +		if (route_num_v4 < 0) {
> +			free_em_routes();
> +			rte_exit(EXIT_FAILURE, "Failed to add EM IPv4 rules\n");
> +		}
> +	} else {
> +		RTE_LOG(ERR, L3FWD, "EM IPv4 rule file not specified\n");
> +		rte_exit(EXIT_FAILURE, "Failed to get valid EM options\n");
> +	}
> +
> +	/* ipv6 check */
> +	if (parm_config.rule_ipv6_name !=3D NULL) {
> +		route_num_v6 =3D em_add_rules(parm_config.rule_ipv6_name,
> +					&em_route_base_v6, &em_parse_v6_rule);
> +		if (route_num_v6 < 0) {
> +			free_em_routes();
> +			rte_exit(EXIT_FAILURE, "Failed to add EM IPv6 rules\n");
> +		}
> +	} else {
> +		RTE_LOG(ERR, L3FWD, "EM IPv6 rule file not specified\n");
> +		rte_exit(EXIT_FAILURE, "Failed to get valid EM options\n");
> +	}
>  }
>=20
>  /* Initialize exact match (hash) parameters. 8< */
>  void
>  setup_hash(const int socketid)
>  {
> +	printf("IPPPROTO_UDP: %d\n", IPPROTO_UDP);

Looks unrelated, pls remove.

>  	struct rte_hash_parameters ipv4_l3fwd_hash_params =3D {
>  		.name =3D NULL,
>  		.entries =3D L3FWD_HASH_ENTRIES,
> @@ -1023,35 +1133,18 @@ setup_hash(const int socketid)
>  			"Unable to create the l3fwd hash on socket %d\n",
>  			socketid);
>=20