From mboxrd@z Thu Jan  1 00:00:00 1970
Return-Path: <dev-bounces@dpdk.org>
Received: from dpdk.org (dpdk.org [92.243.14.124])
	by inbox.dpdk.org (Postfix) with ESMTP id B6F9FA00BE;
	Tue, 28 Apr 2020 07:54:14 +0200 (CEST)
Received: from [92.243.14.124] (localhost [127.0.0.1])
	by dpdk.org (Postfix) with ESMTP id 9BB151D17E;
	Tue, 28 Apr 2020 07:54:14 +0200 (CEST)
Received: from mx0b-0016f401.pphosted.com (mx0a-0016f401.pphosted.com
 [67.231.148.174]) by dpdk.org (Postfix) with ESMTP id 2BE471D176
 for <dev@dpdk.org>; Tue, 28 Apr 2020 07:54:13 +0200 (CEST)
Received: from pps.filterd (m0045849.ppops.net [127.0.0.1])
 by mx0a-0016f401.pphosted.com (8.16.0.42/8.16.0.42) with SMTP id
 03S5olDi026177; Mon, 27 Apr 2020 22:54:12 -0700
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=marvell.com;
 h=from : to : cc :
 subject : date : message-id : references : in-reply-to : content-type :
 content-transfer-encoding : mime-version; s=pfpt0818;
 bh=0NPJ8Di5PGrjBt5/YgOLs6rJfFoch2/UyqKYwZUPdVI=;
 b=XWkr+7DiBlB8d1z9v7FBVok3WOTNe7C1REQMJRbJ8jcnPDv7fOPuNcqlxItICahLQ/mZ
 DdDhTAC6jIM7/FH/6Z5eWecpSa/Ma3AzggaJeU6JBth5UjrJJGtW8Bzz0IQg5yj3bG6o
 XGCgKYkPMLkNVucW7bg+W2v1tYvOQEu83ZAxHLT7plviAXihbKJTZdCCy+QUMxpo1B0x
 zRlrjaHGNpfCBsKmE3zIyHunvr26xUSSuifq/HQR6d75PAzJ5aUdFarU1iY/4nf+CcGI
 ckqc6Fey5LD4Oj9zTI6hQIRTvHWaV07DbDQ33K599q9YlnOliaXFUoMmm0eDKxsHN284 Vw== 
Received: from sc-exch03.marvell.com ([199.233.58.183])
 by mx0a-0016f401.pphosted.com with ESMTP id 30mjjqb068-1
 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT);
 Mon, 27 Apr 2020 22:54:12 -0700
Received: from SC-EXCH02.marvell.com (10.93.176.82) by SC-EXCH03.marvell.com
 (10.93.176.83) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Mon, 27 Apr
 2020 22:54:10 -0700
Received: from NAM02-BL2-obe.outbound.protection.outlook.com (104.47.38.58) by
 SC-EXCH02.marvell.com (10.93.176.82) with Microsoft SMTP Server
 (TLS) id
 15.0.1497.2 via Frontend Transport; Mon, 27 Apr 2020 22:54:10 -0700
ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none;
 b=Nr1AIzZV2ZKlaG0KAkIu76zjl91D8Mu0Ea8jDn3PSiGxI2lQ4OxVN09UGbenbzVH6JQfIdILGCNnPiOfyiDZ+NcMW1viFkA1A3z1p7jm/NIP48FvXlnQ2dxFTLFiZ6dHzvCJGp/4srUDTH8Vc0EQU/TuD8GY7zaZBo4e88CMOHwZiN7papZ7hxTEWhlFZfgsi/ftUqB8hdwbs8Grern2x8ZZ4SJgEPIw720P7fCPLn78ER6rLEx/8pVmD/LC+xx00vUBCKURLllciAfXPzfxLxACW4lCQ+S/G5uAVluwZ2FqkylaMh3gtwmlQ5SJjYHWD4t501UOf3TEZG8pwNeXcA==
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-SenderADCheck;
 bh=0NPJ8Di5PGrjBt5/YgOLs6rJfFoch2/UyqKYwZUPdVI=;
 b=IHWquVl6NF6vMsqiV4Eq1DaLzGCDkh4LvKgp5Q146+QrVHoZLZN9/ekO8ShWgV5Rl8Z3W8FQre4TTQTUd8WOx+YDlJkvAgtnOW7HBqYzuGelMN4TtP+0iTvMKBFTiXme/NRYJjbi6xV9VCrFWoH6XKfOscuoMTW6FrgUGiWog9+4L2AfYICckf9oK0x99nIwiEZ1sN4tUeGEG/x7Ah3xWt7wZyHFm8JHDDkXC4XAH0ezuffVQx/Tn8OUCfpKWNove3GgB8PgAIOrsCFPChWSqouoASFTDzRuP6JMSEtgXDm//Vlym4SP+MtMb3L7dSdpTLUC8d7L8chDzuZTKu3x1Q==
ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass
 smtp.mailfrom=marvell.com; dmarc=pass action=none header.from=marvell.com;
 dkim=pass header.d=marvell.com; arc=none
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
 d=marvell.onmicrosoft.com; s=selector1-marvell-onmicrosoft-com;
 h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck;
 bh=0NPJ8Di5PGrjBt5/YgOLs6rJfFoch2/UyqKYwZUPdVI=;
 b=FdEY5wJ2fd8K5SFdacF8GilBap0J7L+DXNtHsL6SD1Dh4KZ/QBJMVGy3TD04sDq6dDR48W2cFdkdYSom9YCuoPhE62/kcsMYr8TbyxelQua6VelNDfVHdunBqVGPns1/voJjm+tMMQG0eW2vQEnvlSk/l5cSfMA4XlL3hCw3tvs=
Received: from BY5PR18MB3105.namprd18.prod.outlook.com (2603:10b6:a03:1a4::30)
 by BY5PR18MB3283.namprd18.prod.outlook.com (2603:10b6:a03:196::11)
 with Microsoft SMTP Server (version=TLS1_2,
 cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.2937.22; Tue, 28 Apr
 2020 05:54:09 +0000
Received: from BY5PR18MB3105.namprd18.prod.outlook.com
 ([fe80::cc6:c7ae:dc40:7ddf]) by BY5PR18MB3105.namprd18.prod.outlook.com
 ([fe80::cc6:c7ae:dc40:7ddf%7]) with mapi id 15.20.2937.023; Tue, 28 Apr 2020
 05:54:08 +0000
From: Sunil Kumar Kori <skori@marvell.com>
To: Pavan Nikhilesh Bhagavatula <pbhagavatula@marvell.com>, "Jerin Jacob
 Kollanukkaran" <jerinj@marvell.com>, "thomas@monjalon.net"
 <thomas@monjalon.net>, John McNamara <john.mcnamara@intel.com>, "Marko
 Kovacevic" <marko.kovacevic@intel.com>, Ori Kam <orika@mellanox.com>,
 "Bruce Richardson" <bruce.richardson@intel.com>, Radu Nicolau
 <radu.nicolau@intel.com>, Akhil Goyal <akhil.goyal@nxp.com>,
 Tomasz Kantecki <tomasz.kantecki@intel.com>, Pavan Nikhilesh Bhagavatula
 <pbhagavatula@marvell.com>
CC: "Andrzej Ostruszka [C]" <aostruszka@marvell.com>, "dev@dpdk.org"
 <dev@dpdk.org>, Vamsi Krishna Attunuru <vattunuru@marvell.com>
Thread-Topic: [dpdk-dev] [PATCH v4] examples/l2fwd: add cmdline option for
 forwarding port info
Thread-Index: AQHWHSFuVEKaj+yhIkWaRR2qkhfFqA==
Date: Tue, 28 Apr 2020 05:54:08 +0000
Message-ID: <BY5PR18MB31053D0FF83908E110CE769EB4AC0@BY5PR18MB3105.namprd18.prod.outlook.com>
References: <20200427075944.1314-1-pbhagavatula@marvell.com>
 <20200427183118.3315-1-pbhagavatula@marvell.com>
In-Reply-To: <20200427183118.3315-1-pbhagavatula@marvell.com>
Accept-Language: en-US
Content-Language: en-US
X-MS-Has-Attach: 
X-MS-TNEF-Correlator: 
x-originating-ip: [2401:4900:1690:2160:b4ea:fa92:9a4f:42d8]
x-ms-publictraffictype: Email
x-ms-office365-filtering-correlation-id: 207ce479-2eba-4e63-357d-08d7eb389191
x-ms-traffictypediagnostic: BY5PR18MB3283:
x-ms-exchange-transport-forked: True
x-microsoft-antispam-prvs: <BY5PR18MB3283A54FD3EABF801EF467C1B4AC0@BY5PR18MB3283.namprd18.prod.outlook.com>
x-ms-oob-tlc-oobclassifiers: OLM:186;
x-forefront-prvs: 0387D64A71
x-forefront-antispam-report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:;
 IPV:NLI; SFV:NSPM; H:BY5PR18MB3105.namprd18.prod.outlook.com; PTR:; CAT:NONE;
 SFTY:;
 SFS:(4636009)(136003)(39860400002)(376002)(346002)(366004)(396003)(316002)(5660300002)(86362001)(110136005)(186003)(8936002)(8676002)(52536014)(7696005)(478600001)(81156014)(30864003)(66476007)(2906002)(66946007)(33656002)(54906003)(4326008)(9686003)(66446008)(66556008)(71200400001)(6636002)(76116006)(6506007)(107886003)(55016002)(64756008)(921003);
 DIR:OUT; SFP:1101; 
x-ms-exchange-senderadcheck: 1
x-microsoft-antispam: BCL:0;
x-microsoft-antispam-message-info: wnP5GyQB/cwCyY+TRX7gKwpK395/QHKax/ivR12BGdmj5fLRWlnRjXus3Q4iCFaBqu5bDc56oRjW4O7U/GTzcQbZlEA+9H60cgtBBfVBkQVUCB+XneNBAIM+pDRgpPpglxttWWdtegR8z3MwGhxk19+HdEB8gUmIH+V/7wCe+76SSgukNhlvpU5gQhE22eOgfL2/WxFw8RWGKugtQiNxUdnA52xv/ooFjiNgBG3Wo0TtZW7lkNOl1igyHLsU8Hb/WRnhqBJbL52Lqz7vRng5BCssdz7KId8xd2kTdDRWAAgrAxnrX2dUTtfixrtEhJ/57c5rBDZn34yUU1g5EVolP/rH43KuQ+F7f6vnrLtb9XKdNDa9zZuMY8dpE+WW008KhnYVZxGOv2nY2o2gn6Wdi3OemSUq8NZNoeGHzBcwmybKaozR212Bkq1aZBFYrNq11yNNifl6ex+OhVRTPTePTowBsiulL82pDDxjDgJORjs=
x-ms-exchange-antispam-messagedata: 9m2fAFnUutyOVxm/YcnJR5JXJ9ruUKc4PXewMxihYm1hKhU+GoPHlN02ICx7b96eL/2KssJyelFKnnRKYTanTj8Y1eK14DniIN1lyXIoYdOcbpUvAsRXO2NvvknP9B4U02jKZ6Wzw5SdbB2ClsWeZlwmIwVa8v0JAynoawEwW1DdMoB+HmAVby5Z2agqUOeHOy26oIxUIYcEo4tpS2iP88atUFysMjUC5nsrzZEJOk116cGcB3a3FXs00gWtYXK5qiLVXWSYIbg18LubxpItTQvUG5gRnrxnRx/KcsfrDaX1vEBu7p9T3uf+mpiEOyNiENeb2JivfTfSZk3EknDvfJi1ffIk5+hFYmuQyNlHrV1Fmq2BHO0k6OSStTCGY3W/ibBOuIemlcJfPSUU5z2hKvcelJD+DM+iZioRtz3BcsfFvxPB4/SHf3tFjCqCuts9FpvSlLqgGuh04JL9Rhr9NDoIQu7RVrAaDvYf8S2UCrzJkVCn4fnxsBpW1NqCICV25p53unxlZvZGPLMHKioZIvCNKRYgW2ZLPN6wPGPCnjB/8uuZr1+LPNIt70odFUHV94BR0P5FISl0kPcEpOdHs30zmweaLp3AWCyOb8RkPPR+MN4Vf2uEY1s18wBwVLjcdAnVfQTHDRVHM5PfFwxoKWpshahMAYAka386orvDkeDBOzUri1pnmeojzJ+aickfHKpjPWkpNp0uYZEswApchopVLC9MJHKsZUKnX3M5NcVBL4lqwrHUqXArBtcWnogzPpyPjBKZtT3pL5ZUYM0cG9WQRv6KRWvZYV0tdwblceUpoIhSSNoi+vtVd7l7Rwjcff/oXWMcNphH+ZtPKSnX1GalsFzhomkNWGht1nW4nWV7E/vGYJjq0CPjuy2hPncy
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: quoted-printable
MIME-Version: 1.0
X-MS-Exchange-CrossTenant-Network-Message-Id: 207ce479-2eba-4e63-357d-08d7eb389191
X-MS-Exchange-CrossTenant-originalarrivaltime: 28 Apr 2020 05:54:08.7354 (UTC)
X-MS-Exchange-CrossTenant-fromentityheader: Hosted
X-MS-Exchange-CrossTenant-id: 70e1fb47-1155-421d-87fc-2e58f638b6e0
X-MS-Exchange-CrossTenant-mailboxtype: HOSTED
X-MS-Exchange-CrossTenant-userprincipalname: xMMhnZAPgGDKww5zK/kw1T8OGVzwOlGVVIuJwGsGoPqZ7ouiJ66Bhl+HUm2YZ7xb7KXG10Fj/3HBacNka3VYnA==
X-MS-Exchange-Transport-CrossTenantHeadersStamped: BY5PR18MB3283
X-OriginatorOrg: marvell.com
X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:6.0.138, 18.0.676
 definitions=2020-04-28_02:2020-04-27,
 2020-04-28 signatures=0
Subject: Re: [dpdk-dev] [PATCH v4] examples/l2fwd: add cmdline option for
 forwarding port info
X-BeenThere: dev@dpdk.org
X-Mailman-Version: 2.1.15
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
Sender: "dev" <dev-bounces@dpdk.org>

Looks okay.=20

Regards
Sunil Kumar Kori

>-----Original Message-----
>From: pbhagavatula@marvell.com <pbhagavatula@marvell.com>
>Sent: Tuesday, April 28, 2020 12:01 AM
>To: Jerin Jacob Kollanukkaran <jerinj@marvell.com>; thomas@monjalon.net;
>John McNamara <john.mcnamara@intel.com>; Marko Kovacevic
><marko.kovacevic@intel.com>; Ori Kam <orika@mellanox.com>; Bruce
>Richardson <bruce.richardson@intel.com>; Radu Nicolau
><radu.nicolau@intel.com>; Akhil Goyal <akhil.goyal@nxp.com>; Tomasz
>Kantecki <tomasz.kantecki@intel.com>; Sunil Kumar Kori
><skori@marvell.com>; Pavan Nikhilesh Bhagavatula
><pbhagavatula@marvell.com>
>Cc: Andrzej Ostruszka [C] <aostruszka@marvell.com>; dev@dpdk.org; Vamsi
>Krishna Attunuru <vattunuru@marvell.com>
>Subject: [dpdk-dev] [PATCH v4] examples/l2fwd: add cmdline option for
>forwarding port info
>
>From: Vamsi Attunuru <vattunuru@marvell.com>
>
>Current l2fwd application statically configures adjacent ports as destinat=
ion
>ports for forwarding the traffic.
>
>Add a portmap option to pass the forwarding port pair mapping which allows
>the user to configure forwarding port mapping.
>
>If no portmap argument is specified, destination port map is not changed a=
nd
>traffic gets forwarded with existing mapping.
>
>To align port/queue configuration of each lcore with destination port map,
>port/queue configuration of each lcore gets modified when portmap option i=
s
>specified.
>
>Ex: ./l2fwd -c 0xff -- -p 0x3f -q 2 --portmap=3D"(0,3)(1,4)(2,5)"
>
>With above portmap option, traffic received from portid =3D 0 gets forward=
ed to
>port =3D 3 and vice versa, similarly traffic gets forwarded on other port =
pairs
>(1,4) and (2,5)
>
>Signed-off-by: Vamsi Attunuru <vattunuru@marvell.com>
>Signed-off-by: Pavan Nikhilesh <pbhagavatula@marvell.com>
>Acked-by: Andrzej Ostruszka <aostruszka@marvell.com>
Acked-by: Sunil Kumar Kori <skori@marvell.com>

>---
> v4 Changes:
> * Documentation changes. (Sunil)
> * reduce port_pair_params_array size. (Sunil)
>
> v3 Changes:
> * s/config/portmap/
> * rebase on master
>
> v2 Changes:
> * Fix command option format in docs.
> * Use memcpy instead of snprintf.
> * Rephrase if-else condition.
>
> doc/guides/rel_notes/release_20_05.rst        |   7 +
> .../sample_app_ug/l2_forward_real_virtual.rst |  17 +-
> examples/l2fwd/main.c                         | 182 +++++++++++++++---
> 3 files changed, 180 insertions(+), 26 deletions(-)
>
>diff --git a/doc/guides/rel_notes/release_20_05.rst
>b/doc/guides/rel_notes/release_20_05.rst
>index b124c3f28..019bec5d7 100644
>--- a/doc/guides/rel_notes/release_20_05.rst
>+++ b/doc/guides/rel_notes/release_20_05.rst
>@@ -212,6 +212,13 @@ New Features
>   * Added IPsec inbound load-distribution support for ipsec-secgw applica=
tion
>     using NIC load distribution feature(Flow Director).
>
>+* **Added --portmap command line parameter to l2fwd example.**
>+
>+  Added new command line option ``--portmap=3D"(port, port)[,(port,
>+ port)]"`` to  pass forwarding port details.
>+  See the :doc:`doc/guides/sample_app_ug/l2_forward_real_virtual` for
>+ more  details of this parameter usage.
>+
>
> Removed Items
> -------------
>diff --git a/doc/guides/sample_app_ug/l2_forward_real_virtual.rst
>b/doc/guides/sample_app_ug/l2_forward_real_virtual.rst
>index 39d6b0067..90ca609d6 100644
>--- a/doc/guides/sample_app_ug/l2_forward_real_virtual.rst
>+++ b/doc/guides/sample_app_ug/l2_forward_real_virtual.rst
>@@ -91,7 +91,10 @@ The application requires a number of command line
>options:
>
> .. code-block:: console
>
>-    ./build/l2fwd [EAL options] -- -p PORTMASK [-q NQ] --[no-]mac-updatin=
g
>+    ./build/l2fwd [EAL options] -- -p PORTMASK
>+                                   [-q NQ]
>+                                   --[no-]mac-updating
>+                                   [--portmap=3D"(port, port)[,(port,
>+ port)]"]
>
> where,
>
>@@ -99,7 +102,9 @@ where,
>
> *   q NQ: A number of queues (=3Dports) per lcore (default is 1)
>
>-*   --[no-]mac-updating: Enable or disable MAC addresses updating (enable=
d
>by default).
>+*   --[no-]mac-updating: Enable or disable MAC addresses updating (enable=
d
>by default)
>+
>+*   --portmap=3D"(port,port)[,(port,port)]": Determines forwarding ports
>mapping.
>
> To run the application in linux environment with 4 lcores, 16 ports and 8=
 RX
>queues per lcore and MAC address  updating enabled, issue the command:
>@@ -108,6 +113,14 @@ updating enabled, issue the command:
>
>     $ ./build/l2fwd -l 0-3 -n 4 -- -q 8 -p ffff
>
>+To run the application in linux environment with 4 lcores, 4 ports, 8
>+RX queues per lcore, to forward RX traffic of ports 0 & 1 on ports 2 &
>+3 respectively and vice versa, issue the command:
>+
>+.. code-block:: console
>+
>+    $ ./build/l2fwd -l 0-3 -n 4 -- -q 8 -p f --portmap=3D"(0,2)(1,3)"
>+
> Refer to the *DPDK Getting Started Guide* for general information on runn=
ing
>applications  and the Environment Abstraction Layer (EAL) options.
>
>diff --git a/examples/l2fwd/main.c b/examples/l2fwd/main.c index
>88ddfe589..1d84cd789 100644
>--- a/examples/l2fwd/main.c
>+++ b/examples/l2fwd/main.c
>@@ -38,6 +38,7 @@
> #include <rte_ethdev.h>
> #include <rte_mempool.h>
> #include <rte_mbuf.h>
>+#include <rte_string_fns.h>
>
> static volatile bool force_quit;
>
>@@ -67,6 +68,15 @@ static uint32_t l2fwd_enabled_port_mask =3D 0;
> /* list of enabled ports */
> static uint32_t l2fwd_dst_ports[RTE_MAX_ETHPORTS];
>
>+struct port_pair_params {
>+#define NUM_PORTS	2
>+	uint16_t port[NUM_PORTS];
>+} __rte_cache_aligned;
>+
>+static struct port_pair_params
>port_pair_params_array[RTE_MAX_ETHPORTS
>+/ 2]; static struct port_pair_params *port_pair_params; static uint16_t
>+nb_port_pair_params;
>+
> static unsigned int l2fwd_rx_queue_per_lcore =3D 1;
>
> #define MAX_RX_QUEUE_PER_LCORE 16
>@@ -294,11 +304,13 @@ l2fwd_usage(const char *prgname)
> 	printf("%s [EAL options] -- -p PORTMASK [-q NQ]\n"
> 	       "  -p PORTMASK: hexadecimal bitmask of ports to configure\n"
> 	       "  -q NQ: number of queue (=3Dports) per lcore (default is 1)\n"
>-		   "  -T PERIOD: statistics will be refreshed each PERIOD
>seconds (0 to disable, 10 default, 86400 maximum)\n"
>-		   "  --[no-]mac-updating: Enable or disable MAC addresses
>updating (enabled by default)\n"
>-		   "      When enabled:\n"
>-		   "       - The source MAC address is replaced by the TX port
>MAC address\n"
>-		   "       - The destination MAC address is replaced by
>02:00:00:00:00:TX_PORT_ID\n",
>+	       "  -T PERIOD: statistics will be refreshed each PERIOD seconds (0=
 to
>disable, 10 default, 86400 maximum)\n"
>+	       "  --[no-]mac-updating: Enable or disable MAC addresses updating
>(enabled by default)\n"
>+	       "      When enabled:\n"
>+	       "       - The source MAC address is replaced by the TX port MAC
>address\n"
>+	       "       - The destination MAC address is replaced by
>02:00:00:00:00:TX_PORT_ID\n"
>+	       "  --portmap: Configure forwarding port pair mapping\n"
>+	       "	      Default: alternate port pairs\n\n",
> 	       prgname);
> }
>
>@@ -319,6 +331,61 @@ l2fwd_parse_portmask(const char *portmask)
> 	return pm;
> }
>
>+static int
>+l2fwd_parse_port_pair_config(const char *q_arg) {
>+	enum fieldnames {
>+		FLD_PORT1 =3D 0,
>+		FLD_PORT2,
>+		_NUM_FLD
>+	};
>+	unsigned long int_fld[_NUM_FLD];
>+	const char *p, *p0 =3D q_arg;
>+	char *str_fld[_NUM_FLD];
>+	unsigned int size;
>+	char s[256];
>+	char *end;
>+	int i;
>+
>+	nb_port_pair_params =3D 0;
>+
>+	while ((p =3D strchr(p0, '(')) !=3D NULL) {
>+		++p;
>+		p0 =3D strchr(p, ')');
>+		if (p0 =3D=3D NULL)
>+			return -1;
>+
>+		size =3D p0 - p;
>+		if (size >=3D sizeof(s))
>+			return -1;
>+
>+		memcpy(s, p, size);
>+		s[size] =3D '\0';
>+		if (rte_strsplit(s, sizeof(s), str_fld,
>+				 _NUM_FLD, ',') !=3D _NUM_FLD)
>+			return -1;
>+		for (i =3D 0; i < _NUM_FLD; i++) {
>+			errno =3D 0;
>+			int_fld[i] =3D strtoul(str_fld[i], &end, 0);
>+			if (errno !=3D 0 || end =3D=3D str_fld[i] ||
>+			    int_fld[i] >=3D RTE_MAX_ETHPORTS)
>+				return -1;
>+		}
>+		if (nb_port_pair_params >=3D RTE_MAX_ETHPORTS/2) {
>+			printf("exceeded max number of port pair params:
>%hu\n",
>+				nb_port_pair_params);
>+			return -1;
>+		}
>+		port_pair_params_array[nb_port_pair_params].port[0] =3D
>+				(uint16_t)int_fld[FLD_PORT1];
>+		port_pair_params_array[nb_port_pair_params].port[1] =3D
>+				(uint16_t)int_fld[FLD_PORT2];
>+		++nb_port_pair_params;
>+	}
>+	port_pair_params =3D port_pair_params_array;
>+	return 0;
>+}
>+
> static unsigned int
> l2fwd_parse_nqueue(const char *q_arg)
> {
>@@ -361,6 +428,7 @@ static const char short_options[] =3D
>
> #define CMD_LINE_OPT_MAC_UPDATING "mac-updating"
> #define CMD_LINE_OPT_NO_MAC_UPDATING "no-mac-updating"
>+#define CMD_LINE_OPT_PORTMAP_CONFIG "portmap"
>
> enum {
> 	/* long options mapped to a short option */ @@ -368,11 +436,13 @@
>enum {
> 	/* first long only option value must be >=3D 256, so that we won't
> 	 * conflict with short options */
> 	CMD_LINE_OPT_MIN_NUM =3D 256,
>+	CMD_LINE_OPT_PORTMAP_NUM,
> };
>
> static const struct option lgopts[] =3D {
> 	{ CMD_LINE_OPT_MAC_UPDATING, no_argument, &mac_updating,
>1},
> 	{ CMD_LINE_OPT_NO_MAC_UPDATING, no_argument,
>&mac_updating, 0},
>+	{ CMD_LINE_OPT_PORTMAP_CONFIG, 1, 0,
>CMD_LINE_OPT_PORTMAP_NUM},
> 	{NULL, 0, 0, 0}
> };
>
>@@ -386,6 +456,7 @@ l2fwd_parse_args(int argc, char **argv)
> 	char *prgname =3D argv[0];
>
> 	argvopt =3D argv;
>+	port_pair_params =3D NULL;
>
> 	while ((opt =3D getopt_long(argc, argvopt, short_options,
> 				  lgopts, &option_index)) !=3D EOF) { @@ -423,7
>+494,13 @@ l2fwd_parse_args(int argc, char **argv)
> 			break;
>
> 		/* long options */
>-		case 0:
>+		case CMD_LINE_OPT_PORTMAP_NUM:
>+			ret =3D l2fwd_parse_port_pair_config(optarg);
>+			if (ret) {
>+				fprintf(stderr, "Invalid config\n");
>+				l2fwd_usage(prgname);
>+				return -1;
>+			}
> 			break;
>
> 		default:
>@@ -440,6 +517,48 @@ l2fwd_parse_args(int argc, char **argv)
> 	return ret;
> }
>
>+/*
>+ * Check port pair config with enabled port mask,
>+ * and for valid port pair combinations.
>+ */
>+static int
>+check_port_pair_config(void)
>+{
>+	uint32_t port_pair_config_mask =3D 0;
>+	uint32_t port_pair_mask =3D 0;
>+	uint16_t index, i, portid;
>+
>+	for (index =3D 0; index < nb_port_pair_params; index++) {
>+		port_pair_mask =3D 0;
>+
>+		for (i =3D 0; i < NUM_PORTS; i++)  {
>+			portid =3D port_pair_params[index].port[i];
>+			if ((l2fwd_enabled_port_mask & (1 << portid)) =3D=3D 0) {
>+				printf("port %u is not enabled in port
>mask\n",
>+				       portid);
>+				return -1;
>+			}
>+			if (!rte_eth_dev_is_valid_port(portid)) {
>+				printf("port %u is not present on the
>board\n",
>+				       portid);
>+				return -1;
>+			}
>+
>+			port_pair_mask |=3D 1 << portid;
>+		}
>+
>+		if (port_pair_config_mask & port_pair_mask) {
>+			printf("port %u is used in other port pairs\n", portid);
>+			return -1;
>+		}
>+		port_pair_config_mask |=3D port_pair_mask;
>+	}
>+
>+	l2fwd_enabled_port_mask &=3D port_pair_config_mask;
>+
>+	return 0;
>+}
>+
> /* Check the link status of all ports in up to 9s, and print them finally=
 */  static
>void  check_all_ports_link_status(uint32_t port_mask) @@ -555,6 +674,11
>@@ main(int argc, char **argv)
> 	if (nb_ports =3D=3D 0)
> 		rte_exit(EXIT_FAILURE, "No Ethernet ports - bye\n");
>
>+	if (port_pair_params !=3D NULL) {
>+		if (check_port_pair_config() < 0)
>+			rte_exit(EXIT_FAILURE, "Invalid port pair config\n");
>+	}
>+
> 	/* check port mask to possible port mask */
> 	if (l2fwd_enabled_port_mask & ~((1 << nb_ports) - 1))
> 		rte_exit(EXIT_FAILURE, "Invalid portmask; possible (0x%x)\n",
>@@ -565,26 +689,35 @@ main(int argc, char **argv)
> 		l2fwd_dst_ports[portid] =3D 0;
> 	last_port =3D 0;
>
>-	/*
>-	 * Each logical core is assigned a dedicated TX queue on each port.
>-	 */
>-	RTE_ETH_FOREACH_DEV(portid) {
>-		/* skip ports that are not enabled */
>-		if ((l2fwd_enabled_port_mask & (1 << portid)) =3D=3D 0)
>-			continue;
>+	/* populate destination port details */
>+	if (port_pair_params !=3D NULL) {
>+		uint16_t idx, p;
>
>-		if (nb_ports_in_mask % 2) {
>-			l2fwd_dst_ports[portid] =3D last_port;
>-			l2fwd_dst_ports[last_port] =3D portid;
>+		for (idx =3D 0; idx < (nb_port_pair_params << 1); idx++) {
>+			p =3D idx & 1;
>+			portid =3D port_pair_params[idx >> 1].port[p];
>+			l2fwd_dst_ports[portid] =3D
>+				port_pair_params[idx >> 1].port[p ^ 1];
> 		}
>-		else
>-			last_port =3D portid;
>+	} else {
>+		RTE_ETH_FOREACH_DEV(portid) {
>+			/* skip ports that are not enabled */
>+			if ((l2fwd_enabled_port_mask & (1 << portid)) =3D=3D 0)
>+				continue;
>
>-		nb_ports_in_mask++;
>-	}
>-	if (nb_ports_in_mask % 2) {
>-		printf("Notice: odd number of ports in portmask.\n");
>-		l2fwd_dst_ports[last_port] =3D last_port;
>+			if (nb_ports_in_mask % 2) {
>+				l2fwd_dst_ports[portid] =3D last_port;
>+				l2fwd_dst_ports[last_port] =3D portid;
>+			} else {
>+				last_port =3D portid;
>+			}
>+
>+			nb_ports_in_mask++;
>+		}
>+		if (nb_ports_in_mask % 2) {
>+			printf("Notice: odd number of ports in portmask.\n");
>+			l2fwd_dst_ports[last_port] =3D last_port;
>+		}
> 	}
>
> 	rx_lcore_id =3D 0;
>@@ -613,7 +746,8 @@ main(int argc, char **argv)
>
> 		qconf->rx_port_list[qconf->n_rx_port] =3D portid;
> 		qconf->n_rx_port++;
>-		printf("Lcore %u: RX port %u\n", rx_lcore_id, portid);
>+		printf("Lcore %u: RX port %u TX port %u\n", rx_lcore_id,
>+		       portid, l2fwd_dst_ports[portid]);
> 	}
>
> 	nb_mbufs =3D RTE_MAX(nb_ports * (nb_rxd + nb_txd +
>MAX_PKT_BURST +
>--
>2.17.1