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 7A4AAA0C47;
	Tue,  5 Oct 2021 11:22:34 +0200 (CEST)
Received: from [217.70.189.124] (localhost [127.0.0.1])
	by mails.dpdk.org (Postfix) with ESMTP id 01A6A412F0;
	Tue,  5 Oct 2021 11:22:34 +0200 (CEST)
Received: from NAM12-DM6-obe.outbound.protection.outlook.com
 (mail-dm6nam12on2054.outbound.protection.outlook.com [40.107.243.54])
 by mails.dpdk.org (Postfix) with ESMTP id 2CCDE412D2
 for <dev@dpdk.org>; Tue,  5 Oct 2021 11:22:32 +0200 (CEST)
ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none;
 b=Tf+MN07d5Y1mM1zd9qYGbM8sxWH597evwrvseIuQtnH0R3wk7TI6NSYT17e5dziMw9iJINYH31pXRqoO+zsEibXcIB/pbZPYyCXYpfXd1u76yt6tulzjN55Q/NPNZkJHxwPq5f3ZklhfZgSwgI/NIZKiAAny0C6dGrAyQguGasabxMHDWERr3uKwJkxSRYT3OwzLR3n7gH2wromn3cFVwBrzrVtynOkRU6xJ9XR4SuyVpIWkf9pakihBY1mvNKRtMPWO2KBLA62TbBIyDe1Eet3b9lvk/35T+Rx3V4OZWUMdsWTGbEXo4Z+GCN241dRfmvMCfZ8usXNpbXd0+r4Tiw==
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=f2dNR0tuIAbVKAqO7LP6j5liFCgtjJk65MARbHpPPUo=;
 b=E1nE2VftHinFe5guijHaW+uZZkB8PrKe2u7wCPrA+MEUKahMkgn+kaVb0gBtDhQkUixR5ROmAlbjCPqAHyTMERRSCyhR5gj5Gk0hSRqsrplwbQ5S3jy4kOupwMm8BgKc4AT0d1IFUgVT3tIWdQJsdoLiLCieB/X1KVTLyi7204K0Fu0WXORhEaUvDiSffnTLv354YvLI9awGyVvKVOOAekWi+RdKrhBnxGT+o4f5j1jhPpFOeF2v7kHPB5pcV/DOLhRQVOQIsyJ5k9sgcOc/TfjRj2/HyTvy1wB/nyW5OJajeFfD+MTYjvzllx9A6la4SwTL9dUGzAOsUJLtWy1aHQ==
ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass
 smtp.mailfrom=nvidia.com; dmarc=pass action=none header.from=nvidia.com;
 dkim=pass header.d=nvidia.com; arc=none
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=Nvidia.com;
 s=selector2;
 h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck;
 bh=f2dNR0tuIAbVKAqO7LP6j5liFCgtjJk65MARbHpPPUo=;
 b=MEBk63qUG2EjKyC0Ezt70VXwOHVLu5x+v82f+8LvriDBzfIQwHSVuz8Xm85liNbZktL+mvjNkVU9rOt/pOtVwPX6dG6E2x567SY6/wAwuFKn7cHBTIsz6CVI4RyVDq4QhIQlimDewnGqlNnyn7lGXUPUqjv/Uq4FmmqER4Swz/nTLhSzF/G1t3sxx8qRaCSUc72qyPsz7pxYaEA2buZqTNM0dbQVLiwNqioFqwKuoN2B0dlkYikUigRmdSsFVldgSP4nZINeRuVpHahwyOUgfYkpOO94grQwaBS4/4TSu2+WnWlLB93waZ0uYf6MrlNyE/5Bvox261VPCznVvFANjw==
Received: from DM8PR12MB5400.namprd12.prod.outlook.com (2603:10b6:8:3b::12) by
 DM4PR12MB5248.namprd12.prod.outlook.com (2603:10b6:5:39c::15) with
 Microsoft
 SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id
 15.20.4566.17; Tue, 5 Oct 2021 09:22:30 +0000
Received: from DM8PR12MB5400.namprd12.prod.outlook.com
 ([fe80::d03d:1f75:ca20:6a32]) by DM8PR12MB5400.namprd12.prod.outlook.com
 ([fe80::d03d:1f75:ca20:6a32%5]) with mapi id 15.20.4566.022; Tue, 5 Oct 2021
 09:22:30 +0000
From: Ori Kam <orika@nvidia.com>
To: Ivan Malov <ivan.malov@oktetlabs.ru>, "dev@dpdk.org" <dev@dpdk.org>
CC: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>, Xiaoyun Li
 <xiaoyun.li@intel.com>, NBU-Contact-Thomas Monjalon <thomas@monjalon.net>,
 Ferruh Yigit <ferruh.yigit@intel.com>, Ray Kinsella <mdr@ashroe.eu>
Thread-Topic: [PATCH] ethdev: let apps find transfer admin port for a given
 ethdev
Thread-Index: AQHXuYEF7mIz57bbu0KuupGgVTkvZqvEFz1g
Date: Tue, 5 Oct 2021 09:22:30 +0000
Message-ID: <DM8PR12MB5400A23EB75FFD381B8E732CD6AF9@DM8PR12MB5400.namprd12.prod.outlook.com>
References: <20210907125157.3843-1-ivan.malov@oktetlabs.ru>
 <20211005003604.31684-1-ivan.malov@oktetlabs.ru>
In-Reply-To: <20211005003604.31684-1-ivan.malov@oktetlabs.ru>
Accept-Language: en-US
Content-Language: en-US
X-MS-Has-Attach: 
X-MS-TNEF-Correlator: 
authentication-results: oktetlabs.ru; dkim=none (message not signed)
 header.d=none;oktetlabs.ru; dmarc=none action=none header.from=nvidia.com;
x-ms-publictraffictype: Email
x-ms-office365-filtering-correlation-id: d4497142-cabf-4447-2785-08d987e1a80f
x-ms-traffictypediagnostic: DM4PR12MB5248:
x-ld-processed: 43083d15-7273-40c1-b7db-39efd9ccc17a,ExtAddr
x-microsoft-antispam-prvs: <DM4PR12MB5248A9921948DE90A092DAC3D6AF9@DM4PR12MB5248.namprd12.prod.outlook.com>
x-ms-oob-tlc-oobclassifiers: OLM:475;
x-ms-exchange-senderadcheck: 1
x-ms-exchange-antispam-relay: 0
x-microsoft-antispam: BCL:0;
x-microsoft-antispam-message-info: hr6h+TPQ6d2JJQWtwMs7a5HtVkRy5lE2kuib0dHLxSnGYNXBlmO0KngzCFriNvTvhj1+CXuBwh7Wfx5qzYW7idGmPk4zuibUtcw75KLYDxeNdjdGFQSp/m5/jcRKZj5d+o+/i1HjB+tUR8FFXi6I+bHi0FXU5HLs+Ru37K6bF/LuoFrcX/PvLHJ+X2Sl/pX+hu7pft2NXY2Ocjyt66KfyFHgjVRz+xkW4nONTIFXN9SuvhrLx/RWc0VCt2mHQnlzaQA9yBJ28UZzOFGixAd2cpNxlgoyWRI5hVDSEPY84NQRWO4W/Qid+4uGK3JAmXHmAAiayF+I95TLphYxfeCN9RFtZKufPvMbk0btB0fbAkyc+KgbmZxE/ZIG1+KlDK2PK5Y3FG8Xy6dceOnZfbqEjxj8ZmPFg01U0Gg83haH3tPYLMpKFOGMbO7lIXhk1f4YOEk9mG8oJK055fcig/bSl5re6cm0vw/d6IsL2Sq7eTciQ2BfL10UZ3fIE1jVxZTJs16oDUCuhAT8QriYihPM7dRvg3oDhKevvF3GJIxKG01TLP+YzOJjnYWqkpXGf7pary6xLT5H/SPaoR1UYGJiICXwOAoBFezXMzZ+nIO0jApxsBordlrfbxegPNstQgdJLRkCqZLJDEdyf6cTcKCZjNu1DkX5zT5i1hBwdZmJ+CebtZ3njpbTVima6UNIDlc+ZB1N7aWronY0uNiOVgu0L+1FKGN/3PurEOJpKzqLxhK9ma6sPFTXvmlunYY2GeZHger+8FL5r1pmzUWK1+k5MBcUmqlRhOVNcditT/nmcfW5/UM072xyVoR3f75AgQHlHmN2bWWYOAY6MujpEstlcQ==
x-forefront-antispam-report: CIP:255.255.255.255; CTRY:; LANG:en; SCL:1; SRV:;
 IPV:NLI; SFV:NSPM; H:DM8PR12MB5400.namprd12.prod.outlook.com; PTR:; CAT:NONE;
 SFS:(4636009)(366004)(66446008)(5660300002)(110136005)(66556008)(30864003)(66946007)(33656002)(54906003)(66476007)(7696005)(186003)(64756008)(2906002)(4326008)(966005)(83380400001)(8676002)(71200400001)(86362001)(8936002)(55016002)(53546011)(6506007)(38070700005)(38100700002)(122000001)(9686003)(76116006)(316002)(52536014)(508600001);
 DIR:OUT; SFP:1101; 
x-ms-exchange-antispam-messagedata-chunkcount: 1
x-ms-exchange-antispam-messagedata-0: =?us-ascii?Q?J4V8weRYsUio9e/NBkUlAt+uHEA1IlrCNP0tjgdQuCy5M4F7A7wTdkFaajro?=
 =?us-ascii?Q?bS4Kp2MdE8VML4/9kFrqeiPSvZvWREn5nx1PwYgUiqmzXIHpsfPKJyX4Ajcu?=
 =?us-ascii?Q?GNhBr0YNq8RtjrT3AylMUB6DRXG+iCa+P+ytpyUZa94nHlOT45J2jaIxIgK7?=
 =?us-ascii?Q?iCQJ9rjixaIN7ezq4CyB7NywzEaTiVPGOy2c2iUPvGGRSz7hZ3MbyMJnnsIX?=
 =?us-ascii?Q?T6YO+Vo6um+nNuiqQRUbinUPCNthjh59tvKdIBI68wZjiXCb+y8m9XQh3+PQ?=
 =?us-ascii?Q?lhc0Pb3l1zlyVMgMxnHIwxXLw7vfP2qifwyt+nZ/f+Gr30qWToFtUGerTx8z?=
 =?us-ascii?Q?xBs3JZBJp4+zFWIwXiJUzRjVO8XoduSupV64aVe7D1BDXwK0V8OWADBOfgxr?=
 =?us-ascii?Q?nIneagIUq42zHEkfO23EzByYUh2+X6t1Zg7/ST1iPUS8K08UQbDdpqo17RcW?=
 =?us-ascii?Q?iHJ8yMTLoy4AeC4dZUZJHFPEvixFIe+j4t4qT5e/aV9ir0P6EJ08Y/pzkXwF?=
 =?us-ascii?Q?nOT97YYEReATlA+0bKBP4+MPvbQduGw/56qhz15ISkv2le1XTeUiLRbGYSjg?=
 =?us-ascii?Q?hYVJVCITjuhtpyW7ftnKrvCSR9XD/es4BVjIHG7fAl757g5azy553t1GDmSN?=
 =?us-ascii?Q?H6TvWFvYzAMdFinCvuEtKCPm6Ix83gXKfbYdFgJ11g5CG8oDMyfrHq4z98NO?=
 =?us-ascii?Q?YzuRiykbWcp8S3W0Oow9feYUBtShpwTHMBEiyJPfAzGKv7j6yqS/GJwS5JJa?=
 =?us-ascii?Q?XIFhbyX6FWYOrs8AUtjoUfVxcoOzPl9hMBxXiKndINfT3xfWgNXzxz0Hcfde?=
 =?us-ascii?Q?makLBJh3+bA/p6b0yK77Smw7PcOeX9PHYWFpstYQ/XRYr2mIDIIcz47L20/U?=
 =?us-ascii?Q?4xz3pB1uKsYriowhUeV4hy5BC+DCM16apWMI46UNOa/mbs3sIYwc0f39kqDB?=
 =?us-ascii?Q?QvMhnPJ8YrJdI3SuNO85B8IX2bW0L/iUx3ceucKPzywSbazOdEmuHiTp6alC?=
 =?us-ascii?Q?dPFROwgaqg0HERSJ97kWncxPdMy8z6TP1pchZ5P/AKd4qjfhyekxSfKi7J7U?=
 =?us-ascii?Q?IjAg34In1hxcE+wSUaja2AzPzH2Mles4JjJtXs7y4XarmsWvc9H+6XtXHkek?=
 =?us-ascii?Q?dKkz4EHecUr5zhC3ssVFV/1m10HQYgAMGpVAxDoOpGkf4LBPZrOJcFS+Q2z6?=
 =?us-ascii?Q?9Mleuj+Om/PgOntPnJApH76rDIaIGghDDK1CjaOmFSIf7S65nDeOxKmA3L9D?=
 =?us-ascii?Q?3Mxa8bsHhf7DoA2cvRVSneZf1iD55UmZAcP9e45dFSzT36OLPGfXjwEgwMUP?=
 =?us-ascii?Q?g4WA8qeAyOpXWdEI4TjH0vnvU656LRZJotKLq7gX7SWI6u9fFlzkoXQYWCen?=
 =?us-ascii?Q?fZZ9fo8LbhPhxfcoGrWX+bAs6H7/?=
x-ms-exchange-transport-forked: True
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: quoted-printable
MIME-Version: 1.0
X-OriginatorOrg: Nvidia.com
X-MS-Exchange-CrossTenant-AuthAs: Internal
X-MS-Exchange-CrossTenant-AuthSource: DM8PR12MB5400.namprd12.prod.outlook.com
X-MS-Exchange-CrossTenant-Network-Message-Id: d4497142-cabf-4447-2785-08d987e1a80f
X-MS-Exchange-CrossTenant-originalarrivaltime: 05 Oct 2021 09:22:30.5547 (UTC)
X-MS-Exchange-CrossTenant-fromentityheader: Hosted
X-MS-Exchange-CrossTenant-id: 43083d15-7273-40c1-b7db-39efd9ccc17a
X-MS-Exchange-CrossTenant-mailboxtype: HOSTED
X-MS-Exchange-CrossTenant-userprincipalname: H8SYfhktYaKVlEM3NscBYHBCpU/Uu4GGujdD6i3RIh3HOJaTxA6M/NYmwLlNmlQ5TVuIQqMk5kKZMUzHS+afGw==
X-MS-Exchange-Transport-CrossTenantHeadersStamped: DM4PR12MB5248
Subject: Re: [dpdk-dev] [PATCH] ethdev: let apps find transfer admin port
 for a given ethdev
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
Sender: "dev" <dev-bounces@dpdk.org>

Hi Ivan,

> -----Original Message-----
> From: Ivan Malov <ivan.malov@oktetlabs.ru>
> Sent: Tuesday, October 5, 2021 3:36 AM
> Subject: [PATCH] ethdev: let apps find transfer admin port for a given et=
hdev
>=20
> Introduce a helper API to let applications find transfer admin port for a=
 given
> ethdev to avoid failures when managing "transfer" flows through unprivile=
ged
> ports.
>=20
> Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
> Reviewed-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
> ---
> Patch series [1] has reworked support for "transfer" flows.
> As a result, an application no longer needs to communicate such flows thr=
ough
> a particular ethdev where it receives the corresponding packets in the fi=
rst
> place.
>=20
> Hence, this patch is a legitimate follow-up to the series [1].
> At the same time, it's a follow-up to the early RFC [2].
>=20
> net/sfc driver is going to support this method. The corresponding patch i=
s
> already in progress and will be provided in the course of this release cy=
cle.
>=20
> [1] https://patches.dpdk.org/project/dpdk/list/?series=3D19326
> [2] https://patches.dpdk.org/project/dpdk/list/?series=3D18737
> ---
>  app/test-pmd/config.c                  | 106 ++++++++++++++++++++++++-
>  app/test-pmd/testpmd.c                 |  21 +++++
>  app/test-pmd/testpmd.h                 |   4 +
>  app/test-pmd/util.c                    |   5 +-
>  doc/guides/rel_notes/release_21_11.rst |   3 +
>  lib/ethdev/rte_flow.c                  |  22 +++++
>  lib/ethdev/rte_flow.h                  |  32 ++++++++
>  lib/ethdev/rte_flow_driver.h           |   5 ++
>  lib/ethdev/version.map                 |   3 +
>  9 files changed, 197 insertions(+), 4 deletions(-)
>=20
> diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c index
> 9c66329e96..2772c83d0a 100644
> --- a/app/test-pmd/config.c
> +++ b/app/test-pmd/config.c
> @@ -1505,10 +1505,25 @@ port_action_handle_create(portid_t port_id,
> uint32_t id,
>  	struct port_indirect_action *pia;
>  	int ret;
>  	struct rte_flow_error error;
> +	struct rte_port *port;
> +
> +	if (port_id_is_invalid(port_id, ENABLED_WARN) ||
> +	    port_id =3D=3D (portid_t)RTE_PORT_ALL)
> +		return -EINVAL;
>=20

Is this part of the patch or a general fix?

>  	ret =3D action_alloc(port_id, id, &pia);
>  	if (ret)
>  		return ret;
> +
> +	port =3D &ports[port_id];
> +
> +	if (conf->transfer)
> +		port_id =3D port->flow_transfer_proxy;
> +
> +	if (port_id_is_invalid(port_id, ENABLED_WARN) ||
> +	    port_id =3D=3D (portid_t)RTE_PORT_ALL)
> +		return -EINVAL;
> +
>  	if (action->type =3D=3D RTE_FLOW_ACTION_TYPE_AGE) {
>  		struct rte_flow_action_age *age =3D
>  			(struct rte_flow_action_age *)(uintptr_t)(action->conf);
> @@ -1531,6 +1546,7 @@ port_action_handle_create(portid_t port_id,
> uint32_t id,
>  		return port_flow_complain(&error);
>  	}
>  	pia->type =3D action->type;
> +	pia->transfer =3D conf->transfer;
>  	printf("Indirect action #%u created\n", pia->id);
>  	return 0;
>  }
> @@ -1557,9 +1573,18 @@ port_action_handle_destroy(portid_t port_id,
>  		for (i =3D 0; i !=3D n; ++i) {
>  			struct rte_flow_error error;
>  			struct port_indirect_action *pia =3D *tmp;
> +			portid_t port_id_eff =3D port_id;
>=20
>  			if (actions[i] !=3D pia->id)
>  				continue;
> +
> +			if (pia->transfer)
> +				port_id_eff =3D port->flow_transfer_proxy;
> +
> +			if (port_id_is_invalid(port_id_eff, ENABLED_WARN) ||
> +			    port_id_eff =3D=3D (portid_t)RTE_PORT_ALL)
> +				return -EINVAL;
> +
>  			/*
>  			 * Poisoning to make sure PMDs update it in case
>  			 * of error.
> @@ -1567,7 +1592,7 @@ port_action_handle_destroy(portid_t port_id,
>  			memset(&error, 0x33, sizeof(error));
>=20
>  			if (pia->handle && rte_flow_action_handle_destroy(
> -					port_id, pia->handle, &error)) {
> +					port_id_eff, pia->handle, &error)) {
>  				ret =3D port_flow_complain(&error);
>  				continue;
>  			}
> @@ -1602,8 +1627,15 @@ port_action_handle_update(portid_t port_id,
> uint32_t id,
>  	struct rte_flow_error error;
>  	struct rte_flow_action_handle *action_handle;
>  	struct port_indirect_action *pia;
> +	struct rte_port *port;
>  	const void *update;
>=20
> +	if (port_id_is_invalid(port_id, ENABLED_WARN) ||
> +	    port_id =3D=3D (portid_t)RTE_PORT_ALL)
> +		return -EINVAL;
> +
> +	port =3D &ports[port_id];
> +
>  	action_handle =3D port_action_handle_get_by_id(port_id, id);
>  	if (!action_handle)
>  		return -EINVAL;
> @@ -1618,6 +1650,14 @@ port_action_handle_update(portid_t port_id,
> uint32_t id,
>  		update =3D action;
>  		break;
>  	}
> +
> +	if (pia->transfer)
> +		port_id =3D port->flow_transfer_proxy;
> +
> +	if (port_id_is_invalid(port_id, ENABLED_WARN) ||
> +	    port_id =3D=3D (portid_t)RTE_PORT_ALL)
> +		return -EINVAL;
> +
>  	if (rte_flow_action_handle_update(port_id, action_handle, update,
>  					  &error)) {
>  		return port_flow_complain(&error);
> @@ -1636,6 +1676,14 @@ port_action_handle_query(portid_t port_id,
> uint32_t id)
>  		struct rte_flow_query_age age;
>  		struct rte_flow_action_conntrack ct;
>  	} query;
> +	portid_t port_id_eff =3D port_id;
> +	struct rte_port *port;
> +
> +	if (port_id_is_invalid(port_id, ENABLED_WARN) ||
> +	    port_id =3D=3D (portid_t)RTE_PORT_ALL)
> +		return -EINVAL;
> +
> +	port =3D &ports[port_id];
>=20
>  	pia =3D action_get_by_id(port_id, id);
>  	if (!pia)
> @@ -1650,10 +1698,19 @@ port_action_handle_query(portid_t port_id,
> uint32_t id)
>  			id, pia->type, port_id);
>  		return -ENOTSUP;
>  	}
> +
> +	if (pia->transfer)
> +		port_id_eff =3D port->flow_transfer_proxy;
> +
> +	if (port_id_is_invalid(port_id_eff, ENABLED_WARN) ||
> +	    port_id_eff =3D=3D (portid_t)RTE_PORT_ALL)
> +		return -EINVAL;
> +
>  	/* Poisoning to make sure PMDs update it in case of error. */
>  	memset(&error, 0x55, sizeof(error));
>  	memset(&query, 0, sizeof(query));
> -	if (rte_flow_action_handle_query(port_id, pia->handle, &query,
> &error))
> +	if (rte_flow_action_handle_query(port_id_eff, pia->handle, &query,
> +					 &error))
>  		return port_flow_complain(&error);
>  	switch (pia->type) {
>  	case RTE_FLOW_ACTION_TYPE_AGE:
> @@ -1872,6 +1929,20 @@ port_flow_validate(portid_t port_id,  {
>  	struct rte_flow_error error;
>  	struct port_flow_tunnel *pft =3D NULL;
> +	struct rte_port *port;
> +
> +	if (port_id_is_invalid(port_id, ENABLED_WARN) ||
> +	    port_id =3D=3D (portid_t)RTE_PORT_ALL)
> +		return -EINVAL;
> +
> +	port =3D &ports[port_id];
> +
> +	if (attr->transfer)
> +		port_id =3D port->flow_transfer_proxy;
> +
> +	if (port_id_is_invalid(port_id, ENABLED_WARN) ||
> +	    port_id =3D=3D (portid_t)RTE_PORT_ALL)
> +		return -EINVAL;
>=20
>  	/* Poisoning to make sure PMDs update it in case of error. */
>  	memset(&error, 0x11, sizeof(error));
> @@ -1925,7 +1996,19 @@ port_flow_create(portid_t port_id,
>  	struct port_flow_tunnel *pft =3D NULL;
>  	struct rte_flow_action_age *age =3D age_action_get(actions);
>=20
> +	if (port_id_is_invalid(port_id, ENABLED_WARN) ||
> +	    port_id =3D=3D (portid_t)RTE_PORT_ALL)
> +		return -EINVAL;
> +
>  	port =3D &ports[port_id];
> +
> +	if (attr->transfer)
> +		port_id =3D port->flow_transfer_proxy;
> +
> +	if (port_id_is_invalid(port_id, ENABLED_WARN) ||
> +	    port_id =3D=3D (portid_t)RTE_PORT_ALL)
> +		return -EINVAL;
> +
>  	if (port->flow_list) {
>  		if (port->flow_list->id =3D=3D UINT32_MAX) {
>  			fprintf(stderr,
> @@ -1989,6 +2072,7 @@ port_flow_destroy(portid_t port_id, uint32_t n, con=
st
> uint32_t *rule)
>  		uint32_t i;
>=20
>  		for (i =3D 0; i !=3D n; ++i) {
> +			portid_t port_id_eff =3D port_id;
>  			struct rte_flow_error error;
>  			struct port_flow *pf =3D *tmp;
>=20
> @@ -1999,7 +2083,15 @@ port_flow_destroy(portid_t port_id, uint32_t n,
> const uint32_t *rule)
>  			 * of error.
>  			 */
>  			memset(&error, 0x33, sizeof(error));
> -			if (rte_flow_destroy(port_id, pf->flow, &error)) {
> +
> +			if (pf->rule.attr->transfer)
> +				port_id_eff =3D port->flow_transfer_proxy;
> +
> +			if (port_id_is_invalid(port_id_eff, ENABLED_WARN) ||
> +			    port_id_eff =3D=3D (portid_t)RTE_PORT_ALL)
> +				return -EINVAL;
> +
> +			if (rte_flow_destroy(port_id_eff, pf->flow, &error)) {
>  				ret =3D port_flow_complain(&error);
>  				continue;
>  			}
> @@ -2133,6 +2225,14 @@ port_flow_query(portid_t port_id, uint32_t rule,
>  		fprintf(stderr, "Flow rule #%u not found\n", rule);
>  		return -ENOENT;
>  	}
> +
> +	if (pf->rule.attr->transfer)
> +		port_id =3D port->flow_transfer_proxy;
> +
> +	if (port_id_is_invalid(port_id, ENABLED_WARN) ||
> +	    port_id =3D=3D (portid_t)RTE_PORT_ALL)
> +		return -EINVAL;
> +
>  	ret =3D rte_flow_conv(RTE_FLOW_CONV_OP_ACTION_NAME_PTR,
>  			    &name, sizeof(name),
>  			    (void *)(uintptr_t)action->type, &error); diff --git
> a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c index
> 97ae52e17e..a88e920bd0 100644
> --- a/app/test-pmd/testpmd.c
> +++ b/app/test-pmd/testpmd.c
> @@ -533,6 +533,25 @@ int proc_id;
>   */
>  unsigned int num_procs =3D 1;
>=20
> +static void
> +flow_pick_transfer_proxy_mp(uint16_t port_id) {
> +	struct rte_port *port =3D &ports[port_id];
> +	int ret;
> +
> +	port->flow_transfer_proxy =3D port_id;
> +
> +	if (!is_proc_primary())
> +		return;
> +
> +	ret =3D rte_flow_pick_transfer_proxy(port_id, &port-
> >flow_transfer_proxy,
> +					   NULL);
> +	if (ret !=3D 0) {
> +		fprintf(stderr, "Error picking flow transfer proxy for port %u: %s
> - ignore\n",
> +			port_id, rte_strerror(-ret));
> +	}
> +}
> +
>  static int
>  eth_dev_configure_mp(uint16_t port_id, uint16_t nb_rx_q, uint16_t nb_tx_=
q,
>  		      const struct rte_eth_conf *dev_conf) @@ -1489,6 +1508,8
> @@ init_config_port_offloads(portid_t pid, uint32_t socket_id)
>  	int ret;
>  	int i;
>=20
> +	flow_pick_transfer_proxy_mp(pid);
> +
>  	port->dev_conf.txmode =3D tx_mode;
>  	port->dev_conf.rxmode =3D rx_mode;
>=20
> diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h index
> 5863b2f43f..b3dfd350e5 100644
> --- a/app/test-pmd/testpmd.h
> +++ b/app/test-pmd/testpmd.h
> @@ -173,6 +173,8 @@ struct port_indirect_action {
>  	enum rte_flow_action_type type; /**< Action type. */
>  	struct rte_flow_action_handle *handle;	/**< Indirect action handle. */
>  	enum age_action_context_type age_type; /**< Age action context
> type. */
> +	/** If true, the action applies to "transfer" flows, and vice versa */
> +	bool transfer;
>  };
>=20
>  struct port_flow_tunnel {
> @@ -234,6 +236,8 @@ struct rte_port {
>  	/**< dynamic flags. */
>  	uint64_t		mbuf_dynf;
>  	const struct rte_eth_rxtx_callback
> *tx_set_dynf_cb[RTE_MAX_QUEUES_PER_PORT+1];
> +	/** Associated port which is supposed to handle "transfer" flows */
> +	portid_t		flow_transfer_proxy;
>  };
>=20
>  /**
> diff --git a/app/test-pmd/util.c b/app/test-pmd/util.c index
> 14a9a251fb..d9edbbf9ee 100644
> --- a/app/test-pmd/util.c
> +++ b/app/test-pmd/util.c
> @@ -98,13 +98,16 @@ dump_pkt_burst(uint16_t port_id, uint16_t queue,
> struct rte_mbuf *pkts[],
>  		int ret;
>  		struct rte_flow_error error;
>  		struct rte_flow_restore_info info =3D { 0, };
> +		struct rte_port *port =3D &ports[port_id];
>=20
>  		mb =3D pkts[i];
>  		eth_hdr =3D rte_pktmbuf_read(mb, 0, sizeof(_eth_hdr),
> &_eth_hdr);
>  		eth_type =3D RTE_BE_TO_CPU_16(eth_hdr->ether_type);
>  		packet_type =3D mb->packet_type;
>  		is_encapsulation =3D RTE_ETH_IS_TUNNEL_PKT(packet_type);
> -		ret =3D rte_flow_get_restore_info(port_id, mb, &info, &error);
> +
> +		ret =3D rte_flow_get_restore_info(port->flow_transfer_proxy,
> +						mb, &info, &error);

I'm not sure this is correct,
Since to restore the data you need to know the port that this traffic was s=
ent to.
Even if the action was offloaded on the proxy port, it is important to know=
 what was the
destination port.
even setting the tunnel must be done on the target port and not the proxy p=
ort.

>  		if (!ret) {
>  			MKDUMPSTR(print_buf, buf_size, cur_len,
>  				  "restore info:");
> diff --git a/doc/guides/rel_notes/release_21_11.rst
> b/doc/guides/rel_notes/release_21_11.rst
> index 37776c135e..cc0ea4695a 100644
> --- a/doc/guides/rel_notes/release_21_11.rst
> +++ b/doc/guides/rel_notes/release_21_11.rst
> @@ -67,6 +67,9 @@ New Features
>    Added macros ETH_RSS_IPV4_CHKSUM and ETH_RSS_L4_CHKSUM, now IPv4
> and
>    TCP/UDP/SCTP header checksum field can be used as input set for RSS.
>=20
> +* **Added an API to pick flow transfer proxy port**
> +  A new API, ``rte_flow_pick_transfer_proxy()``, was added.
> +
>  * **Updated Broadcom bnxt PMD.**
>=20
>    * Added flow offload support for Thor.
> diff --git a/lib/ethdev/rte_flow.c b/lib/ethdev/rte_flow.c index
> 647bbf91ce..15e978f7f7 100644
> --- a/lib/ethdev/rte_flow.c
> +++ b/lib/ethdev/rte_flow.c
> @@ -1270,3 +1270,25 @@ rte_flow_tunnel_item_release(uint16_t port_id,
>  				  RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
>  				  NULL, rte_strerror(ENOTSUP));
>  }
> +
> +int
> +rte_flow_pick_transfer_proxy(uint16_t port_id, uint16_t *proxy_port_id,
> +			     struct rte_flow_error *error)

What about replaceing pick with get?

> +{
> +	struct rte_eth_dev *dev =3D &rte_eth_devices[port_id];
> +	const struct rte_flow_ops *ops =3D rte_flow_ops_get(port_id, error);
> +
> +	if (unlikely(ops =3D=3D NULL))
> +		return -rte_errno;
> +
> +	if (likely(ops->pick_transfer_proxy !=3D NULL)) {
> +		return flow_err(port_id,
> +				ops->pick_transfer_proxy(dev, proxy_port_id,
> +							 error),
> +				error);
> +	}
> +
> +	*proxy_port_id =3D port_id;
> +
> +	return 0;
> +}
> diff --git a/lib/ethdev/rte_flow.h b/lib/ethdev/rte_flow.h index
> f195aa7224..d2cb476189 100644
> --- a/lib/ethdev/rte_flow.h
> +++ b/lib/ethdev/rte_flow.h
> @@ -122,6 +122,10 @@ struct rte_flow_attr {
>  	 *
>  	 * In order to match traffic originating from specific source(s), the
>  	 * application should use pattern items ETHDEV and ESWITCH_PORT.
> +	 *
> +	 * Communicating "transfer" flows via unprivileged ethdevs may not
> +	 * be possible. In order to pick the ethdev suitable for that, the
> +	 * application should use @p rte_flow_pick_transfer_proxy().
>  	 */
>  	uint32_t transfer:1;
>  	uint32_t reserved:29; /**< Reserved, must be zero. */ @@ -4427,6
> +4431,34 @@ rte_flow_tunnel_item_release(uint16_t port_id,
>  			     struct rte_flow_item *items,
>  			     uint32_t num_of_items,
>  			     struct rte_flow_error *error);
> +
> +/**
> + * An application receiving packets on a given ethdev may want to have
> +their
> + * processing offloaded to the e-switch lying beneath this ethdev by
> +means
> + * of maintaining "transfer" flows. However, it need never use this
> +exact
> + * ethdev as an entry point for such flows to be managed through. More
> +to
> + * that, this particular ethdev may be short of privileges to control
> +the
> + * e-switch. Instead, the application should find an admin ethdev
> +sitting
> + * on top of the same e-switch to be used as the entry point (a "proxy")=
.
> + *

This explanation is not clear, can you rephrase it?

> + * This API is a helper to find such "transfer proxy" for a given ethdev=
.
> + *
> + * @note
> + *   If the PMD serving @p port_id doesn't have the corresponding method
> + *   implemented, the API will return @p port_id via @p proxy_port_id.

+1=20

> + *
> + * @param port_id
> + *   ID of the ethdev in question
> + * @param[out] proxy_port_id
> + *   ID of the "transfer proxy"
> + *
> + * @return
> + *   0 on success, a negative error code otherwise
> + */
> +__rte_experimental
> +int
> +rte_flow_pick_transfer_proxy(uint16_t port_id, uint16_t *proxy_port_id,
> +			     struct rte_flow_error *error);
>  #ifdef __cplusplus
>  }
>  #endif
> diff --git a/lib/ethdev/rte_flow_driver.h b/lib/ethdev/rte_flow_driver.h =
index
> 46f62c2ec2..ed52e59a0a 100644
> --- a/lib/ethdev/rte_flow_driver.h
> +++ b/lib/ethdev/rte_flow_driver.h
> @@ -139,6 +139,11 @@ struct rte_flow_ops {
>  		 struct rte_flow_item *pmd_items,
>  		 uint32_t num_of_items,
>  		 struct rte_flow_error *err);
> +	/** See rte_flow_pick_transfer_proxy() */
> +	int (*pick_transfer_proxy)
> +		(struct rte_eth_dev *dev,
> +		 uint16_t *proxy_port_id,
> +		 struct rte_flow_error *error);
>  };
>=20
>  /**
> diff --git a/lib/ethdev/version.map b/lib/ethdev/version.map index
> 904bce6ea1..d4286dc8dd 100644
> --- a/lib/ethdev/version.map
> +++ b/lib/ethdev/version.map
> @@ -247,6 +247,9 @@ EXPERIMENTAL {
>  	rte_mtr_meter_policy_delete;
>  	rte_mtr_meter_policy_update;
>  	rte_mtr_meter_policy_validate;
> +
> +	# added in 21.11
> +	rte_flow_pick_transfer_proxy;
>  };
>=20
>  INTERNAL {
> --
> 2.20.1

Best,
Ori