From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from EUR03-DB5-obe.outbound.protection.outlook.com (mail-eopbgr40070.outbound.protection.outlook.com [40.107.4.70]) by dpdk.org (Postfix) with ESMTP id 1F4E61B120 for ; Mon, 24 Sep 2018 21:55:18 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=Mellanox.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=6Z9syhJ4Coghhurzqr81FWDgKX/JRJ9DFn/pGAeR1vo=; b=aNpJoM5LZxm12TXIoG9DM+yblhd+RONFXi6M2PEvYkDVI8UnOXAYcdq//fHhHxR3GZ7nmTJgr42n8N8oSz4FwiV/2JMxsPvC3vdwpGNex4rd64Hkjae4oDBbklaX75rhr4RTZGGB0EuCL/NjEKzbhTzn3GPsJKdbvnLNnsYOD0Y= Received: from DB3PR0502MB3980.eurprd05.prod.outlook.com (52.134.72.27) by DB3PR0502MB3995.eurprd05.prod.outlook.com (52.134.72.30) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.1164.25; Mon, 24 Sep 2018 19:55:16 +0000 Received: from DB3PR0502MB3980.eurprd05.prod.outlook.com ([fe80::1cb0:661b:ecab:6045]) by DB3PR0502MB3980.eurprd05.prod.outlook.com ([fe80::1cb0:661b:ecab:6045%2]) with mapi id 15.20.1164.017; Mon, 24 Sep 2018 19:55:16 +0000 From: Yongseok Koh To: Thomas Monjalon , Shahaf Shuler CC: "dev@dpdk.org" , Yongseok Koh Thread-Topic: [PATCH v2 2/3] net/mlx5: remove Netlink flow driver Thread-Index: AQHUVECDcmImSLPZZkikH6mdl79Tig== Date: Mon, 24 Sep 2018 19:55:16 +0000 Message-ID: <20180924195503.18894-3-yskoh@mellanox.com> References: <20180919072143.23211-1-yskoh@mellanox.com> <20180924195503.18894-1-yskoh@mellanox.com> In-Reply-To: <20180924195503.18894-1-yskoh@mellanox.com> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-clientproxiedby: MWHPR2001CA0016.namprd20.prod.outlook.com (2603:10b6:301:15::26) To DB3PR0502MB3980.eurprd05.prod.outlook.com (2603:10a6:8:10::27) authentication-results: spf=none (sender IP is ) smtp.mailfrom=yskoh@mellanox.com; x-ms-exchange-messagesentrepresentingtype: 1 x-originating-ip: [209.116.155.178] x-ms-publictraffictype: Email x-microsoft-exchange-diagnostics: 1; DB3PR0502MB3995; 6:XpqcBUB8LYZFpiZshQc5pivLnvy28322olCNRo+MlxeUGuga/HHWGg92edZGSDax4H+HDSwY9nmDq8Ns/YaQXm2rxZth9Hv+EVsxHxAIYRUw3JxGLEzbETFCB8q+zJG99GwjvxvHLqmfpzUGfXWABLTR9R1N5CbsvjvtGRptOo4YYRQFALTc1Shl/UXFEvZrM3jyUyPIU7YmVTf3uOEKFob6h+hLpDX7MgjZ0TaWyNkAKV32iWOJNRjVaw+sTqUF72BD4WwcP/paSnsbI11AHNu8B5L3zoYgNKZxf0Dto1bejS2JIcKH9zH2WsZPupbj/r7nr+5a/IUquUpFBo7aBSnp+Wo6u9rb8Cb2Bq0bUpP271Nn7GSGR8Pl64MRTSBHSwJEvW86mehZI6pPJQNppXqbNtbQBNW+TKpiTwSJz0WO74ZARZghVUCDhpOgj8Vd8+Ht5UsljtrzTbMGmHiAZw==; 5:B8P4PnyAnAyAngMJS+YJNknrGNZOa1ln7hpVA1MtdyaNLhPznkGLqFumb23gsBL/hNfXYCoZxABiudWkjUTOl/faUsoE76vw4dqGqTWWr0HlY/bYH5hgCxEI+j8SSRWdO7aorPwS6qV5WlcuZjfEw9AMO0LRj0BusAFrGLVDPZQ=; 7:GHLoEkseMXuEa8SFqwW1bvzVsQCEZdQKxWSM5rFe84ATzPJwR36xrpH9DC7bPDmrBMJJXHbRKl/QexX+XWORRv+G/jC+RBcH7hgDL1MPTvjWYkJdXAydpNqsPUObLV1AI736B9Bazc++Kngg+KtuUt0vIMKF8p8O72TCvIW5BMv3q0QD25+m5LsJV/BFqyx3teOloxu7swJ7JE1wJJcRS3pv9D3tJGwVECXMMq+TuZPeAcwghnFLbM81mMvrk7tj x-ms-office365-filtering-correlation-id: 70eebe49-4a8c-4e7e-ba79-08d62257a5ae x-ms-office365-filtering-ht: Tenant x-microsoft-antispam: BCL:0; PCL:0; RULEID:(7020095)(4652040)(8989299)(4534165)(4627221)(201703031133081)(201702281549075)(8990200)(5600074)(711020)(4618075)(2017052603328)(7153060)(7193020); SRVR:DB3PR0502MB3995; x-ms-traffictypediagnostic: DB3PR0502MB3995: x-ld-processed: a652971c-7d2e-4d9b-a6a4-d149256f461b,ExtAddr x-microsoft-antispam-prvs: x-exchange-antispam-report-test: UriScan:(269456686620040)(211171220733660); x-ms-exchange-senderadcheck: 1 x-exchange-antispam-report-cfa-test: BCL:0; PCL:0; RULEID:(8211001083)(6040522)(2401047)(8121501046)(5005006)(10201501046)(3231355)(944501410)(52105095)(93006095)(93001095)(3002001)(6055026)(149066)(150027)(6041310)(20161123560045)(201703131423095)(201702281528075)(20161123555045)(201703061421075)(201703061406153)(20161123558120)(20161123564045)(20161123562045)(201708071742011)(7699051); SRVR:DB3PR0502MB3995; BCL:0; PCL:0; RULEID:; SRVR:DB3PR0502MB3995; x-forefront-prvs: 0805EC9467 x-forefront-antispam-report: SFV:NSPM; SFS:(10009020)(136003)(346002)(396003)(376002)(366004)(39860400002)(199004)(189003)(486006)(2906002)(14444005)(99286004)(105586002)(106356001)(110136005)(71200400001)(68736007)(54906003)(107886003)(25786009)(5250100002)(316002)(11346002)(446003)(4326008)(7736002)(53936002)(476003)(2616005)(305945005)(66066001)(5660300001)(6436002)(26005)(6116002)(102836004)(1076002)(3846002)(8676002)(8936002)(478600001)(14454004)(6506007)(81156014)(386003)(81166006)(53946003)(36756003)(16200700003)(6636002)(6486002)(71190400001)(52116002)(86362001)(76176011)(97736004)(5024004)(2900100001)(575784001)(256004)(186003)(6512007)(579004)(559001)(569006); DIR:OUT; SFP:1101; SCL:1; SRVR:DB3PR0502MB3995; H:DB3PR0502MB3980.eurprd05.prod.outlook.com; FPR:; SPF:None; LANG:en; PTR:InfoNoRecords; A:1; MX:1; received-spf: None (protection.outlook.com: mellanox.com does not designate permitted sender hosts) x-microsoft-antispam-message-info: h8V9XwUhcn2xl83iSzVtuUyoWI71kIZe3sZVpyk+qT/yubYabb0RZKHnMMyEcl925fnjIe8SA/0/f7jpBq2VEXd8sw+lF4jAl5HhVzRPYcEm0m3Re+4OgCibE+k3OoIwMdJW4a/HdsQUqJEx5JofAlW/Zmz/6CYOgOyEv1gxDTZxciZklW/kZhGva62fDu8yBHlLzs16WB1y70UpWToQ6Zf6kFPEIU9HJ7a4Oxz4MX6vZNZf0f/3GEhc100jH9wJn/31GRkzHTbB8tleRZeYZf/iabzg271mjGnVS0e5U6e74fIYrj8Q8+Vq0ZRuoVZXH08vMam43jYDpt3UMOmFJ/yZkJ6fOlngELqKtwNd2Co= spamdiagnosticoutput: 1:99 spamdiagnosticmetadata: NSPM Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 X-OriginatorOrg: Mellanox.com X-MS-Exchange-CrossTenant-Network-Message-Id: 70eebe49-4a8c-4e7e-ba79-08d62257a5ae X-MS-Exchange-CrossTenant-originalarrivaltime: 24 Sep 2018 19:55:16.2632 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: a652971c-7d2e-4d9b-a6a4-d149256f461b X-MS-Exchange-Transport-CrossTenantHeadersStamped: DB3PR0502MB3995 Subject: [dpdk-dev] [PATCH v2 2/3] net/mlx5: remove Netlink flow driver X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 24 Sep 2018 19:55:18 -0000 Netlink based E-Switch flow engine will be migrated to the new flow engine. nl_flow will be renamed to flow_tcf as it goes through Linux TC flower interface. Signed-off-by: Yongseok Koh --- drivers/net/mlx5/Makefile | 1 - drivers/net/mlx5/meson.build | 1 - drivers/net/mlx5/mlx5.c | 32 - drivers/net/mlx5/mlx5.h | 25 - drivers/net/mlx5/mlx5_nl_flow.c | 1228 -----------------------------------= ---- 5 files changed, 1287 deletions(-) delete mode 100644 drivers/net/mlx5/mlx5_nl_flow.c diff --git a/drivers/net/mlx5/Makefile b/drivers/net/mlx5/Makefile index 4243b37ca..9c1044808 100644 --- a/drivers/net/mlx5/Makefile +++ b/drivers/net/mlx5/Makefile @@ -35,7 +35,6 @@ SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) +=3D mlx5_flow_dv.c SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) +=3D mlx5_flow_verbs.c SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) +=3D mlx5_socket.c SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) +=3D mlx5_nl.c -SRCS-$(CONFIG_RTE_LIBRTE_MLX5_PMD) +=3D mlx5_nl_flow.c =20 ifeq ($(CONFIG_RTE_LIBRTE_MLX5_DLOPEN_DEPS),y) INSTALL-$(CONFIG_RTE_LIBRTE_MLX5_PMD)-lib +=3D $(LIB_GLUE) diff --git a/drivers/net/mlx5/meson.build b/drivers/net/mlx5/meson.build index 3d09ece4f..e5376291c 100644 --- a/drivers/net/mlx5/meson.build +++ b/drivers/net/mlx5/meson.build @@ -36,7 +36,6 @@ if build 'mlx5_mac.c', 'mlx5_mr.c', 'mlx5_nl.c', - 'mlx5_nl_flow.c', 'mlx5_rss.c', 'mlx5_rxmode.c', 'mlx5_rxq.c', diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c index 2f7d046e0..bb9a63fba 100644 --- a/drivers/net/mlx5/mlx5.c +++ b/drivers/net/mlx5/mlx5.c @@ -286,8 +286,6 @@ mlx5_dev_close(struct rte_eth_dev *dev) close(priv->nl_socket_route); if (priv->nl_socket_rdma >=3D 0) close(priv->nl_socket_rdma); - if (priv->mnl_socket) - mlx5_nl_flow_socket_destroy(priv->mnl_socket); ret =3D mlx5_hrxq_ibv_verify(dev); if (ret) DRV_LOG(WARNING, "port %u some hash Rx queue still remain", @@ -1137,34 +1135,6 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev, claim_zero(mlx5_mac_addr_add(eth_dev, &mac, 0, 0)); if (vf && config.vf_nl_en) mlx5_nl_mac_addr_sync(eth_dev); - priv->mnl_socket =3D mlx5_nl_flow_socket_create(); - if (!priv->mnl_socket) { - err =3D -rte_errno; - DRV_LOG(WARNING, - "flow rules relying on switch offloads will not be" - " supported: cannot open libmnl socket: %s", - strerror(rte_errno)); - } else { - struct rte_flow_error error; - unsigned int ifindex =3D mlx5_ifindex(eth_dev); - - if (!ifindex) { - err =3D -rte_errno; - error.message =3D - "cannot retrieve network interface index"; - } else { - err =3D mlx5_nl_flow_init(priv->mnl_socket, ifindex, - &error); - } - if (err) { - DRV_LOG(WARNING, - "flow rules relying on switch offloads will" - " not be supported: %s: %s", - error.message, strerror(rte_errno)); - mlx5_nl_flow_socket_destroy(priv->mnl_socket); - priv->mnl_socket =3D NULL; - } - } TAILQ_INIT(&priv->flows); TAILQ_INIT(&priv->ctrl_flows); /* Hint libmlx5 to use PMD allocator for data plane resources */ @@ -1217,8 +1187,6 @@ mlx5_dev_spawn(struct rte_device *dpdk_dev, close(priv->nl_socket_route); if (priv->nl_socket_rdma >=3D 0) close(priv->nl_socket_rdma); - if (priv->mnl_socket) - mlx5_nl_flow_socket_destroy(priv->mnl_socket); if (own_domain_id) claim_zero(rte_eth_switch_domain_free(priv->domain_id)); rte_free(priv); diff --git a/drivers/net/mlx5/mlx5.h b/drivers/net/mlx5/mlx5.h index 8bb619d9e..8de0d74ce 100644 --- a/drivers/net/mlx5/mlx5.h +++ b/drivers/net/mlx5/mlx5.h @@ -158,12 +158,6 @@ struct mlx5_drop { struct mlx5_rxq_ibv *rxq; /* Verbs Rx queue. */ }; =20 -/** DPDK port to network interface index (ifindex) conversion. */ -struct mlx5_nl_flow_ptoi { - uint16_t port_id; /**< DPDK port ID. */ - unsigned int ifindex; /**< Network interface index. */ -}; - struct mnl_socket; =20 struct priv { @@ -399,23 +393,4 @@ unsigned int mlx5_nl_ifindex(int nl, const char *name)= ; int mlx5_nl_switch_info(int nl, unsigned int ifindex, struct mlx5_switch_info *info); =20 -/* mlx5_nl_flow.c */ - -int mlx5_nl_flow_transpose(void *buf, - size_t size, - const struct mlx5_nl_flow_ptoi *ptoi, - const struct rte_flow_attr *attr, - const struct rte_flow_item *pattern, - const struct rte_flow_action *actions, - struct rte_flow_error *error); -void mlx5_nl_flow_brand(void *buf, uint32_t handle); -int mlx5_nl_flow_create(struct mnl_socket *nl, void *buf, - struct rte_flow_error *error); -int mlx5_nl_flow_destroy(struct mnl_socket *nl, void *buf, - struct rte_flow_error *error); -int mlx5_nl_flow_init(struct mnl_socket *nl, unsigned int ifindex, - struct rte_flow_error *error); -struct mnl_socket *mlx5_nl_flow_socket_create(void); -void mlx5_nl_flow_socket_destroy(struct mnl_socket *nl); - #endif /* RTE_PMD_MLX5_H_ */ diff --git a/drivers/net/mlx5/mlx5_nl_flow.c b/drivers/net/mlx5/mlx5_nl_flo= w.c deleted file mode 100644 index beb03c911..000000000 --- a/drivers/net/mlx5/mlx5_nl_flow.c +++ /dev/null @@ -1,1228 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright 2018 6WIND S.A. - * Copyright 2018 Mellanox Technologies, Ltd - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "mlx5.h" -#include "mlx5_autoconf.h" - -#ifdef HAVE_TC_ACT_VLAN - -#include - -#else /* HAVE_TC_ACT_VLAN */ - -#define TCA_VLAN_ACT_POP 1 -#define TCA_VLAN_ACT_PUSH 2 -#define TCA_VLAN_ACT_MODIFY 3 -#define TCA_VLAN_PARMS 2 -#define TCA_VLAN_PUSH_VLAN_ID 3 -#define TCA_VLAN_PUSH_VLAN_PROTOCOL 4 -#define TCA_VLAN_PAD 5 -#define TCA_VLAN_PUSH_VLAN_PRIORITY 6 - -struct tc_vlan { - tc_gen; - int v_action; -}; - -#endif /* HAVE_TC_ACT_VLAN */ - -/* Normally found in linux/netlink.h. */ -#ifndef NETLINK_CAP_ACK -#define NETLINK_CAP_ACK 10 -#endif - -/* Normally found in linux/pkt_sched.h. */ -#ifndef TC_H_MIN_INGRESS -#define TC_H_MIN_INGRESS 0xfff2u -#endif - -/* Normally found in linux/pkt_cls.h. */ -#ifndef TCA_CLS_FLAGS_SKIP_SW -#define TCA_CLS_FLAGS_SKIP_SW (1 << 1) -#endif -#ifndef HAVE_TCA_FLOWER_ACT -#define TCA_FLOWER_ACT 3 -#endif -#ifndef HAVE_TCA_FLOWER_FLAGS -#define TCA_FLOWER_FLAGS 22 -#endif -#ifndef HAVE_TCA_FLOWER_KEY_ETH_TYPE -#define TCA_FLOWER_KEY_ETH_TYPE 8 -#endif -#ifndef HAVE_TCA_FLOWER_KEY_ETH_DST -#define TCA_FLOWER_KEY_ETH_DST 4 -#endif -#ifndef HAVE_TCA_FLOWER_KEY_ETH_DST_MASK -#define TCA_FLOWER_KEY_ETH_DST_MASK 5 -#endif -#ifndef HAVE_TCA_FLOWER_KEY_ETH_SRC -#define TCA_FLOWER_KEY_ETH_SRC 6 -#endif -#ifndef HAVE_TCA_FLOWER_KEY_ETH_SRC_MASK -#define TCA_FLOWER_KEY_ETH_SRC_MASK 7 -#endif -#ifndef HAVE_TCA_FLOWER_KEY_IP_PROTO -#define TCA_FLOWER_KEY_IP_PROTO 9 -#endif -#ifndef HAVE_TCA_FLOWER_KEY_IPV4_SRC -#define TCA_FLOWER_KEY_IPV4_SRC 10 -#endif -#ifndef HAVE_TCA_FLOWER_KEY_IPV4_SRC_MASK -#define TCA_FLOWER_KEY_IPV4_SRC_MASK 11 -#endif -#ifndef HAVE_TCA_FLOWER_KEY_IPV4_DST -#define TCA_FLOWER_KEY_IPV4_DST 12 -#endif -#ifndef HAVE_TCA_FLOWER_KEY_IPV4_DST_MASK -#define TCA_FLOWER_KEY_IPV4_DST_MASK 13 -#endif -#ifndef HAVE_TCA_FLOWER_KEY_IPV6_SRC -#define TCA_FLOWER_KEY_IPV6_SRC 14 -#endif -#ifndef HAVE_TCA_FLOWER_KEY_IPV6_SRC_MASK -#define TCA_FLOWER_KEY_IPV6_SRC_MASK 15 -#endif -#ifndef HAVE_TCA_FLOWER_KEY_IPV6_DST -#define TCA_FLOWER_KEY_IPV6_DST 16 -#endif -#ifndef HAVE_TCA_FLOWER_KEY_IPV6_DST_MASK -#define TCA_FLOWER_KEY_IPV6_DST_MASK 17 -#endif -#ifndef HAVE_TCA_FLOWER_KEY_TCP_SRC -#define TCA_FLOWER_KEY_TCP_SRC 18 -#endif -#ifndef HAVE_TCA_FLOWER_KEY_TCP_SRC_MASK -#define TCA_FLOWER_KEY_TCP_SRC_MASK 35 -#endif -#ifndef HAVE_TCA_FLOWER_KEY_TCP_DST -#define TCA_FLOWER_KEY_TCP_DST 19 -#endif -#ifndef HAVE_TCA_FLOWER_KEY_TCP_DST_MASK -#define TCA_FLOWER_KEY_TCP_DST_MASK 36 -#endif -#ifndef HAVE_TCA_FLOWER_KEY_UDP_SRC -#define TCA_FLOWER_KEY_UDP_SRC 20 -#endif -#ifndef HAVE_TCA_FLOWER_KEY_UDP_SRC_MASK -#define TCA_FLOWER_KEY_UDP_SRC_MASK 37 -#endif -#ifndef HAVE_TCA_FLOWER_KEY_UDP_DST -#define TCA_FLOWER_KEY_UDP_DST 21 -#endif -#ifndef HAVE_TCA_FLOWER_KEY_UDP_DST_MASK -#define TCA_FLOWER_KEY_UDP_DST_MASK 38 -#endif -#ifndef HAVE_TCA_FLOWER_KEY_VLAN_ID -#define TCA_FLOWER_KEY_VLAN_ID 23 -#endif -#ifndef HAVE_TCA_FLOWER_KEY_VLAN_PRIO -#define TCA_FLOWER_KEY_VLAN_PRIO 24 -#endif -#ifndef HAVE_TCA_FLOWER_KEY_VLAN_ETH_TYPE -#define TCA_FLOWER_KEY_VLAN_ETH_TYPE 25 -#endif - -/** Parser state definitions for mlx5_nl_flow_trans[]. */ -enum mlx5_nl_flow_trans { - INVALID, - BACK, - ATTR, - PATTERN, - ITEM_VOID, - ITEM_PORT_ID, - ITEM_ETH, - ITEM_VLAN, - ITEM_IPV4, - ITEM_IPV6, - ITEM_TCP, - ITEM_UDP, - ACTIONS, - ACTION_VOID, - ACTION_PORT_ID, - ACTION_DROP, - ACTION_OF_POP_VLAN, - ACTION_OF_PUSH_VLAN, - ACTION_OF_SET_VLAN_VID, - ACTION_OF_SET_VLAN_PCP, - END, -}; - -#define TRANS(...) (const enum mlx5_nl_flow_trans []){ __VA_ARGS__, INVALI= D, } - -#define PATTERN_COMMON \ - ITEM_VOID, ITEM_PORT_ID, ACTIONS -#define ACTIONS_COMMON \ - ACTION_VOID, ACTION_OF_POP_VLAN, ACTION_OF_PUSH_VLAN, \ - ACTION_OF_SET_VLAN_VID, ACTION_OF_SET_VLAN_PCP -#define ACTIONS_FATE \ - ACTION_PORT_ID, ACTION_DROP - -/** Parser state transitions used by mlx5_nl_flow_transpose(). */ -static const enum mlx5_nl_flow_trans *const mlx5_nl_flow_trans[] =3D { - [INVALID] =3D NULL, - [BACK] =3D NULL, - [ATTR] =3D TRANS(PATTERN), - [PATTERN] =3D TRANS(ITEM_ETH, PATTERN_COMMON), - [ITEM_VOID] =3D TRANS(BACK), - [ITEM_PORT_ID] =3D TRANS(BACK), - [ITEM_ETH] =3D TRANS(ITEM_IPV4, ITEM_IPV6, ITEM_VLAN, PATTERN_COMMON), - [ITEM_VLAN] =3D TRANS(ITEM_IPV4, ITEM_IPV6, PATTERN_COMMON), - [ITEM_IPV4] =3D TRANS(ITEM_TCP, ITEM_UDP, PATTERN_COMMON), - [ITEM_IPV6] =3D TRANS(ITEM_TCP, ITEM_UDP, PATTERN_COMMON), - [ITEM_TCP] =3D TRANS(PATTERN_COMMON), - [ITEM_UDP] =3D TRANS(PATTERN_COMMON), - [ACTIONS] =3D TRANS(ACTIONS_FATE, ACTIONS_COMMON), - [ACTION_VOID] =3D TRANS(BACK), - [ACTION_PORT_ID] =3D TRANS(ACTION_VOID, END), - [ACTION_DROP] =3D TRANS(ACTION_VOID, END), - [ACTION_OF_POP_VLAN] =3D TRANS(ACTIONS_FATE, ACTIONS_COMMON), - [ACTION_OF_PUSH_VLAN] =3D TRANS(ACTIONS_FATE, ACTIONS_COMMON), - [ACTION_OF_SET_VLAN_VID] =3D TRANS(ACTIONS_FATE, ACTIONS_COMMON), - [ACTION_OF_SET_VLAN_PCP] =3D TRANS(ACTIONS_FATE, ACTIONS_COMMON), - [END] =3D NULL, -}; - -/** Empty masks for known item types. */ -static const union { - struct rte_flow_item_port_id port_id; - struct rte_flow_item_eth eth; - struct rte_flow_item_vlan vlan; - struct rte_flow_item_ipv4 ipv4; - struct rte_flow_item_ipv6 ipv6; - struct rte_flow_item_tcp tcp; - struct rte_flow_item_udp udp; -} mlx5_nl_flow_mask_empty; - -/** Supported masks for known item types. */ -static const struct { - struct rte_flow_item_port_id port_id; - struct rte_flow_item_eth eth; - struct rte_flow_item_vlan vlan; - struct rte_flow_item_ipv4 ipv4; - struct rte_flow_item_ipv6 ipv6; - struct rte_flow_item_tcp tcp; - struct rte_flow_item_udp udp; -} mlx5_nl_flow_mask_supported =3D { - .port_id =3D { - .id =3D 0xffffffff, - }, - .eth =3D { - .type =3D RTE_BE16(0xffff), - .dst.addr_bytes =3D "\xff\xff\xff\xff\xff\xff", - .src.addr_bytes =3D "\xff\xff\xff\xff\xff\xff", - }, - .vlan =3D { - /* PCP and VID only, no DEI. */ - .tci =3D RTE_BE16(0xefff), - .inner_type =3D RTE_BE16(0xffff), - }, - .ipv4.hdr =3D { - .next_proto_id =3D 0xff, - .src_addr =3D RTE_BE32(0xffffffff), - .dst_addr =3D RTE_BE32(0xffffffff), - }, - .ipv6.hdr =3D { - .proto =3D 0xff, - .src_addr =3D - "\xff\xff\xff\xff\xff\xff\xff\xff" - "\xff\xff\xff\xff\xff\xff\xff\xff", - .dst_addr =3D - "\xff\xff\xff\xff\xff\xff\xff\xff" - "\xff\xff\xff\xff\xff\xff\xff\xff", - }, - .tcp.hdr =3D { - .src_port =3D RTE_BE16(0xffff), - .dst_port =3D RTE_BE16(0xffff), - }, - .udp.hdr =3D { - .src_port =3D RTE_BE16(0xffff), - .dst_port =3D RTE_BE16(0xffff), - }, -}; - -/** - * Retrieve mask for pattern item. - * - * This function does basic sanity checks on a pattern item in order to - * return the most appropriate mask for it. - * - * @param[in] item - * Item specification. - * @param[in] mask_default - * Default mask for pattern item as specified by the flow API. - * @param[in] mask_supported - * Mask fields supported by the implementation. - * @param[in] mask_empty - * Empty mask to return when there is no specification. - * @param[out] error - * Perform verbose error reporting if not NULL. - * - * @return - * Either @p item->mask or one of the mask parameters on success, NULL - * otherwise and rte_errno is set. - */ -static const void * -mlx5_nl_flow_item_mask(const struct rte_flow_item *item, - const void *mask_default, - const void *mask_supported, - const void *mask_empty, - size_t mask_size, - struct rte_flow_error *error) -{ - const uint8_t *mask; - size_t i; - - /* item->last and item->mask cannot exist without item->spec. */ - if (!item->spec && (item->mask || item->last)) { - rte_flow_error_set - (error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM, item, - "\"mask\" or \"last\" field provided without a" - " corresponding \"spec\""); - return NULL; - } - /* No spec, no mask, no problem. */ - if (!item->spec) - return mask_empty; - mask =3D item->mask ? item->mask : mask_default; - assert(mask); - /* - * Single-pass check to make sure that: - * - Mask is supported, no bits are set outside mask_supported. - * - Both item->spec and item->last are included in mask. - */ - for (i =3D 0; i !=3D mask_size; ++i) { - if (!mask[i]) - continue; - if ((mask[i] | ((const uint8_t *)mask_supported)[i]) !=3D - ((const uint8_t *)mask_supported)[i]) { - rte_flow_error_set - (error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM_MASK, - mask, "unsupported field found in \"mask\""); - return NULL; - } - if (item->last && - (((const uint8_t *)item->spec)[i] & mask[i]) !=3D - (((const uint8_t *)item->last)[i] & mask[i])) { - rte_flow_error_set - (error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM_LAST, - item->last, - "range between \"spec\" and \"last\" not" - " comprised in \"mask\""); - return NULL; - } - } - return mask; -} - -/** - * Transpose flow rule description to rtnetlink message. - * - * This function transposes a flow rule description to a traffic control - * (TC) filter creation message ready to be sent over Netlink. - * - * Target interface is specified as the first entry of the @p ptoi table. - * Subsequent entries enable this function to resolve other DPDK port IDs - * found in the flow rule. - * - * @param[out] buf - * Output message buffer. May be NULL when @p size is 0. - * @param size - * Size of @p buf. Message may be truncated if not large enough. - * @param[in] ptoi - * DPDK port ID to network interface index translation table. This table - * is terminated by an entry with a zero ifindex value. - * @param[in] attr - * Flow rule attributes. - * @param[in] pattern - * Pattern specification. - * @param[in] actions - * Associated actions. - * @param[out] error - * Perform verbose error reporting if not NULL. - * - * @return - * A positive value representing the exact size of the message in bytes - * regardless of the @p size parameter on success, a negative errno valu= e - * otherwise and rte_errno is set. - */ -int -mlx5_nl_flow_transpose(void *buf, - size_t size, - const struct mlx5_nl_flow_ptoi *ptoi, - const struct rte_flow_attr *attr, - const struct rte_flow_item *pattern, - const struct rte_flow_action *actions, - struct rte_flow_error *error) -{ - alignas(struct nlmsghdr) - uint8_t buf_tmp[mnl_nlmsg_size(sizeof(struct tcmsg) + 1024)]; - const struct rte_flow_item *item; - const struct rte_flow_action *action; - unsigned int n; - uint32_t act_index_cur; - bool in_port_id_set; - bool eth_type_set; - bool vlan_present; - bool vlan_eth_type_set; - bool ip_proto_set; - struct nlattr *na_flower; - struct nlattr *na_flower_act; - struct nlattr *na_vlan_id; - struct nlattr *na_vlan_priority; - const enum mlx5_nl_flow_trans *trans; - const enum mlx5_nl_flow_trans *back; - - if (!size) - goto error_nobufs; -init: - item =3D pattern; - action =3D actions; - n =3D 0; - act_index_cur =3D 0; - in_port_id_set =3D false; - eth_type_set =3D false; - vlan_present =3D false; - vlan_eth_type_set =3D false; - ip_proto_set =3D false; - na_flower =3D NULL; - na_flower_act =3D NULL; - na_vlan_id =3D NULL; - na_vlan_priority =3D NULL; - trans =3D TRANS(ATTR); - back =3D trans; -trans: - switch (trans[n++]) { - union { - const struct rte_flow_item_port_id *port_id; - const struct rte_flow_item_eth *eth; - const struct rte_flow_item_vlan *vlan; - const struct rte_flow_item_ipv4 *ipv4; - const struct rte_flow_item_ipv6 *ipv6; - const struct rte_flow_item_tcp *tcp; - const struct rte_flow_item_udp *udp; - } spec, mask; - union { - const struct rte_flow_action_port_id *port_id; - const struct rte_flow_action_of_push_vlan *of_push_vlan; - const struct rte_flow_action_of_set_vlan_vid * - of_set_vlan_vid; - const struct rte_flow_action_of_set_vlan_pcp * - of_set_vlan_pcp; - } conf; - struct nlmsghdr *nlh; - struct tcmsg *tcm; - struct nlattr *act_index; - struct nlattr *act; - unsigned int i; - - case INVALID: - if (item->type) - return rte_flow_error_set - (error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM, - item, "unsupported pattern item combination"); - else if (action->type) - return rte_flow_error_set - (error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION, - action, "unsupported action combination"); - return rte_flow_error_set - (error, ENOTSUP, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, - "flow rule lacks some kind of fate action"); - case BACK: - trans =3D back; - n =3D 0; - goto trans; - case ATTR: - /* - * Supported attributes: no groups, some priorities and - * ingress only. Don't care about transfer as it is the - * caller's problem. - */ - if (attr->group) - return rte_flow_error_set - (error, ENOTSUP, - RTE_FLOW_ERROR_TYPE_ATTR_GROUP, - attr, "groups are not supported"); - if (attr->priority > 0xfffe) - return rte_flow_error_set - (error, ENOTSUP, - RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY, - attr, "lowest priority level is 0xfffe"); - if (!attr->ingress) - return rte_flow_error_set - (error, ENOTSUP, - RTE_FLOW_ERROR_TYPE_ATTR_INGRESS, - attr, "only ingress is supported"); - if (attr->egress) - return rte_flow_error_set - (error, ENOTSUP, - RTE_FLOW_ERROR_TYPE_ATTR_INGRESS, - attr, "egress is not supported"); - if (size < mnl_nlmsg_size(sizeof(*tcm))) - goto error_nobufs; - nlh =3D mnl_nlmsg_put_header(buf); - nlh->nlmsg_type =3D 0; - nlh->nlmsg_flags =3D 0; - nlh->nlmsg_seq =3D 0; - tcm =3D mnl_nlmsg_put_extra_header(nlh, sizeof(*tcm)); - tcm->tcm_family =3D AF_UNSPEC; - tcm->tcm_ifindex =3D ptoi[0].ifindex; - /* - * Let kernel pick a handle by default. A predictable handle - * can be set by the caller on the resulting buffer through - * mlx5_nl_flow_brand(). - */ - tcm->tcm_handle =3D 0; - tcm->tcm_parent =3D TC_H_MAKE(TC_H_INGRESS, TC_H_MIN_INGRESS); - /* - * Priority cannot be zero to prevent the kernel from - * picking one automatically. - */ - tcm->tcm_info =3D TC_H_MAKE((attr->priority + 1) << 16, - RTE_BE16(ETH_P_ALL)); - break; - case PATTERN: - if (!mnl_attr_put_strz_check(buf, size, TCA_KIND, "flower")) - goto error_nobufs; - na_flower =3D mnl_attr_nest_start_check(buf, size, TCA_OPTIONS); - if (!na_flower) - goto error_nobufs; - if (!mnl_attr_put_u32_check(buf, size, TCA_FLOWER_FLAGS, - TCA_CLS_FLAGS_SKIP_SW)) - goto error_nobufs; - break; - case ITEM_VOID: - if (item->type !=3D RTE_FLOW_ITEM_TYPE_VOID) - goto trans; - ++item; - break; - case ITEM_PORT_ID: - if (item->type !=3D RTE_FLOW_ITEM_TYPE_PORT_ID) - goto trans; - mask.port_id =3D mlx5_nl_flow_item_mask - (item, &rte_flow_item_port_id_mask, - &mlx5_nl_flow_mask_supported.port_id, - &mlx5_nl_flow_mask_empty.port_id, - sizeof(mlx5_nl_flow_mask_supported.port_id), error); - if (!mask.port_id) - return -rte_errno; - if (mask.port_id =3D=3D &mlx5_nl_flow_mask_empty.port_id) { - in_port_id_set =3D 1; - ++item; - break; - } - spec.port_id =3D item->spec; - if (mask.port_id->id && mask.port_id->id !=3D 0xffffffff) - return rte_flow_error_set - (error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM_MASK, - mask.port_id, - "no support for partial mask on" - " \"id\" field"); - if (!mask.port_id->id) - i =3D 0; - else - for (i =3D 0; ptoi[i].ifindex; ++i) - if (ptoi[i].port_id =3D=3D spec.port_id->id) - break; - if (!ptoi[i].ifindex) - return rte_flow_error_set - (error, ENODEV, RTE_FLOW_ERROR_TYPE_ITEM_SPEC, - spec.port_id, - "missing data to convert port ID to ifindex"); - tcm =3D mnl_nlmsg_get_payload(buf); - if (in_port_id_set && - ptoi[i].ifindex !=3D (unsigned int)tcm->tcm_ifindex) - return rte_flow_error_set - (error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM_SPEC, - spec.port_id, - "cannot match traffic for several port IDs" - " through a single flow rule"); - tcm->tcm_ifindex =3D ptoi[i].ifindex; - in_port_id_set =3D 1; - ++item; - break; - case ITEM_ETH: - if (item->type !=3D RTE_FLOW_ITEM_TYPE_ETH) - goto trans; - mask.eth =3D mlx5_nl_flow_item_mask - (item, &rte_flow_item_eth_mask, - &mlx5_nl_flow_mask_supported.eth, - &mlx5_nl_flow_mask_empty.eth, - sizeof(mlx5_nl_flow_mask_supported.eth), error); - if (!mask.eth) - return -rte_errno; - if (mask.eth =3D=3D &mlx5_nl_flow_mask_empty.eth) { - ++item; - break; - } - spec.eth =3D item->spec; - if (mask.eth->type && mask.eth->type !=3D RTE_BE16(0xffff)) - return rte_flow_error_set - (error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM_MASK, - mask.eth, - "no support for partial mask on" - " \"type\" field"); - if (mask.eth->type) { - if (!mnl_attr_put_u16_check(buf, size, - TCA_FLOWER_KEY_ETH_TYPE, - spec.eth->type)) - goto error_nobufs; - eth_type_set =3D 1; - } - if ((!is_zero_ether_addr(&mask.eth->dst) && - (!mnl_attr_put_check(buf, size, - TCA_FLOWER_KEY_ETH_DST, - ETHER_ADDR_LEN, - spec.eth->dst.addr_bytes) || - !mnl_attr_put_check(buf, size, - TCA_FLOWER_KEY_ETH_DST_MASK, - ETHER_ADDR_LEN, - mask.eth->dst.addr_bytes))) || - (!is_zero_ether_addr(&mask.eth->src) && - (!mnl_attr_put_check(buf, size, - TCA_FLOWER_KEY_ETH_SRC, - ETHER_ADDR_LEN, - spec.eth->src.addr_bytes) || - !mnl_attr_put_check(buf, size, - TCA_FLOWER_KEY_ETH_SRC_MASK, - ETHER_ADDR_LEN, - mask.eth->src.addr_bytes)))) - goto error_nobufs; - ++item; - break; - case ITEM_VLAN: - if (item->type !=3D RTE_FLOW_ITEM_TYPE_VLAN) - goto trans; - mask.vlan =3D mlx5_nl_flow_item_mask - (item, &rte_flow_item_vlan_mask, - &mlx5_nl_flow_mask_supported.vlan, - &mlx5_nl_flow_mask_empty.vlan, - sizeof(mlx5_nl_flow_mask_supported.vlan), error); - if (!mask.vlan) - return -rte_errno; - if (!eth_type_set && - !mnl_attr_put_u16_check(buf, size, - TCA_FLOWER_KEY_ETH_TYPE, - RTE_BE16(ETH_P_8021Q))) - goto error_nobufs; - eth_type_set =3D 1; - vlan_present =3D 1; - if (mask.vlan =3D=3D &mlx5_nl_flow_mask_empty.vlan) { - ++item; - break; - } - spec.vlan =3D item->spec; - if ((mask.vlan->tci & RTE_BE16(0xe000) && - (mask.vlan->tci & RTE_BE16(0xe000)) !=3D RTE_BE16(0xe000)) || - (mask.vlan->tci & RTE_BE16(0x0fff) && - (mask.vlan->tci & RTE_BE16(0x0fff)) !=3D RTE_BE16(0x0fff)) || - (mask.vlan->inner_type && - mask.vlan->inner_type !=3D RTE_BE16(0xffff))) - return rte_flow_error_set - (error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM_MASK, - mask.vlan, - "no support for partial masks on" - " \"tci\" (PCP and VID parts) and" - " \"inner_type\" fields"); - if (mask.vlan->inner_type) { - if (!mnl_attr_put_u16_check - (buf, size, TCA_FLOWER_KEY_VLAN_ETH_TYPE, - spec.vlan->inner_type)) - goto error_nobufs; - vlan_eth_type_set =3D 1; - } - if ((mask.vlan->tci & RTE_BE16(0xe000) && - !mnl_attr_put_u8_check - (buf, size, TCA_FLOWER_KEY_VLAN_PRIO, - (rte_be_to_cpu_16(spec.vlan->tci) >> 13) & 0x7)) || - (mask.vlan->tci & RTE_BE16(0x0fff) && - !mnl_attr_put_u16_check - (buf, size, TCA_FLOWER_KEY_VLAN_ID, - rte_be_to_cpu_16(spec.vlan->tci & RTE_BE16(0x0fff))))) - goto error_nobufs; - ++item; - break; - case ITEM_IPV4: - if (item->type !=3D RTE_FLOW_ITEM_TYPE_IPV4) - goto trans; - mask.ipv4 =3D mlx5_nl_flow_item_mask - (item, &rte_flow_item_ipv4_mask, - &mlx5_nl_flow_mask_supported.ipv4, - &mlx5_nl_flow_mask_empty.ipv4, - sizeof(mlx5_nl_flow_mask_supported.ipv4), error); - if (!mask.ipv4) - return -rte_errno; - if ((!eth_type_set || !vlan_eth_type_set) && - !mnl_attr_put_u16_check(buf, size, - vlan_present ? - TCA_FLOWER_KEY_VLAN_ETH_TYPE : - TCA_FLOWER_KEY_ETH_TYPE, - RTE_BE16(ETH_P_IP))) - goto error_nobufs; - eth_type_set =3D 1; - vlan_eth_type_set =3D 1; - if (mask.ipv4 =3D=3D &mlx5_nl_flow_mask_empty.ipv4) { - ++item; - break; - } - spec.ipv4 =3D item->spec; - if (mask.ipv4->hdr.next_proto_id && - mask.ipv4->hdr.next_proto_id !=3D 0xff) - return rte_flow_error_set - (error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM_MASK, - mask.ipv4, - "no support for partial mask on" - " \"hdr.next_proto_id\" field"); - if (mask.ipv4->hdr.next_proto_id) { - if (!mnl_attr_put_u8_check - (buf, size, TCA_FLOWER_KEY_IP_PROTO, - spec.ipv4->hdr.next_proto_id)) - goto error_nobufs; - ip_proto_set =3D 1; - } - if ((mask.ipv4->hdr.src_addr && - (!mnl_attr_put_u32_check(buf, size, - TCA_FLOWER_KEY_IPV4_SRC, - spec.ipv4->hdr.src_addr) || - !mnl_attr_put_u32_check(buf, size, - TCA_FLOWER_KEY_IPV4_SRC_MASK, - mask.ipv4->hdr.src_addr))) || - (mask.ipv4->hdr.dst_addr && - (!mnl_attr_put_u32_check(buf, size, - TCA_FLOWER_KEY_IPV4_DST, - spec.ipv4->hdr.dst_addr) || - !mnl_attr_put_u32_check(buf, size, - TCA_FLOWER_KEY_IPV4_DST_MASK, - mask.ipv4->hdr.dst_addr)))) - goto error_nobufs; - ++item; - break; - case ITEM_IPV6: - if (item->type !=3D RTE_FLOW_ITEM_TYPE_IPV6) - goto trans; - mask.ipv6 =3D mlx5_nl_flow_item_mask - (item, &rte_flow_item_ipv6_mask, - &mlx5_nl_flow_mask_supported.ipv6, - &mlx5_nl_flow_mask_empty.ipv6, - sizeof(mlx5_nl_flow_mask_supported.ipv6), error); - if (!mask.ipv6) - return -rte_errno; - if ((!eth_type_set || !vlan_eth_type_set) && - !mnl_attr_put_u16_check(buf, size, - vlan_present ? - TCA_FLOWER_KEY_VLAN_ETH_TYPE : - TCA_FLOWER_KEY_ETH_TYPE, - RTE_BE16(ETH_P_IPV6))) - goto error_nobufs; - eth_type_set =3D 1; - vlan_eth_type_set =3D 1; - if (mask.ipv6 =3D=3D &mlx5_nl_flow_mask_empty.ipv6) { - ++item; - break; - } - spec.ipv6 =3D item->spec; - if (mask.ipv6->hdr.proto && mask.ipv6->hdr.proto !=3D 0xff) - return rte_flow_error_set - (error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM_MASK, - mask.ipv6, - "no support for partial mask on" - " \"hdr.proto\" field"); - if (mask.ipv6->hdr.proto) { - if (!mnl_attr_put_u8_check - (buf, size, TCA_FLOWER_KEY_IP_PROTO, - spec.ipv6->hdr.proto)) - goto error_nobufs; - ip_proto_set =3D 1; - } - if ((!IN6_IS_ADDR_UNSPECIFIED(mask.ipv6->hdr.src_addr) && - (!mnl_attr_put_check(buf, size, - TCA_FLOWER_KEY_IPV6_SRC, - sizeof(spec.ipv6->hdr.src_addr), - spec.ipv6->hdr.src_addr) || - !mnl_attr_put_check(buf, size, - TCA_FLOWER_KEY_IPV6_SRC_MASK, - sizeof(mask.ipv6->hdr.src_addr), - mask.ipv6->hdr.src_addr))) || - (!IN6_IS_ADDR_UNSPECIFIED(mask.ipv6->hdr.dst_addr) && - (!mnl_attr_put_check(buf, size, - TCA_FLOWER_KEY_IPV6_DST, - sizeof(spec.ipv6->hdr.dst_addr), - spec.ipv6->hdr.dst_addr) || - !mnl_attr_put_check(buf, size, - TCA_FLOWER_KEY_IPV6_DST_MASK, - sizeof(mask.ipv6->hdr.dst_addr), - mask.ipv6->hdr.dst_addr)))) - goto error_nobufs; - ++item; - break; - case ITEM_TCP: - if (item->type !=3D RTE_FLOW_ITEM_TYPE_TCP) - goto trans; - mask.tcp =3D mlx5_nl_flow_item_mask - (item, &rte_flow_item_tcp_mask, - &mlx5_nl_flow_mask_supported.tcp, - &mlx5_nl_flow_mask_empty.tcp, - sizeof(mlx5_nl_flow_mask_supported.tcp), error); - if (!mask.tcp) - return -rte_errno; - if (!ip_proto_set && - !mnl_attr_put_u8_check(buf, size, - TCA_FLOWER_KEY_IP_PROTO, - IPPROTO_TCP)) - goto error_nobufs; - if (mask.tcp =3D=3D &mlx5_nl_flow_mask_empty.tcp) { - ++item; - break; - } - spec.tcp =3D item->spec; - if ((mask.tcp->hdr.src_port && - (!mnl_attr_put_u16_check(buf, size, - TCA_FLOWER_KEY_TCP_SRC, - spec.tcp->hdr.src_port) || - !mnl_attr_put_u16_check(buf, size, - TCA_FLOWER_KEY_TCP_SRC_MASK, - mask.tcp->hdr.src_port))) || - (mask.tcp->hdr.dst_port && - (!mnl_attr_put_u16_check(buf, size, - TCA_FLOWER_KEY_TCP_DST, - spec.tcp->hdr.dst_port) || - !mnl_attr_put_u16_check(buf, size, - TCA_FLOWER_KEY_TCP_DST_MASK, - mask.tcp->hdr.dst_port)))) - goto error_nobufs; - ++item; - break; - case ITEM_UDP: - if (item->type !=3D RTE_FLOW_ITEM_TYPE_UDP) - goto trans; - mask.udp =3D mlx5_nl_flow_item_mask - (item, &rte_flow_item_udp_mask, - &mlx5_nl_flow_mask_supported.udp, - &mlx5_nl_flow_mask_empty.udp, - sizeof(mlx5_nl_flow_mask_supported.udp), error); - if (!mask.udp) - return -rte_errno; - if (!ip_proto_set && - !mnl_attr_put_u8_check(buf, size, - TCA_FLOWER_KEY_IP_PROTO, - IPPROTO_UDP)) - goto error_nobufs; - if (mask.udp =3D=3D &mlx5_nl_flow_mask_empty.udp) { - ++item; - break; - } - spec.udp =3D item->spec; - if ((mask.udp->hdr.src_port && - (!mnl_attr_put_u16_check(buf, size, - TCA_FLOWER_KEY_UDP_SRC, - spec.udp->hdr.src_port) || - !mnl_attr_put_u16_check(buf, size, - TCA_FLOWER_KEY_UDP_SRC_MASK, - mask.udp->hdr.src_port))) || - (mask.udp->hdr.dst_port && - (!mnl_attr_put_u16_check(buf, size, - TCA_FLOWER_KEY_UDP_DST, - spec.udp->hdr.dst_port) || - !mnl_attr_put_u16_check(buf, size, - TCA_FLOWER_KEY_UDP_DST_MASK, - mask.udp->hdr.dst_port)))) - goto error_nobufs; - ++item; - break; - case ACTIONS: - if (item->type !=3D RTE_FLOW_ITEM_TYPE_END) - goto trans; - assert(na_flower); - assert(!na_flower_act); - na_flower_act =3D - mnl_attr_nest_start_check(buf, size, TCA_FLOWER_ACT); - if (!na_flower_act) - goto error_nobufs; - act_index_cur =3D 1; - break; - case ACTION_VOID: - if (action->type !=3D RTE_FLOW_ACTION_TYPE_VOID) - goto trans; - ++action; - break; - case ACTION_PORT_ID: - if (action->type !=3D RTE_FLOW_ACTION_TYPE_PORT_ID) - goto trans; - conf.port_id =3D action->conf; - if (conf.port_id->original) - i =3D 0; - else - for (i =3D 0; ptoi[i].ifindex; ++i) - if (ptoi[i].port_id =3D=3D conf.port_id->id) - break; - if (!ptoi[i].ifindex) - return rte_flow_error_set - (error, ENODEV, RTE_FLOW_ERROR_TYPE_ACTION_CONF, - conf.port_id, - "missing data to convert port ID to ifindex"); - act_index =3D - mnl_attr_nest_start_check(buf, size, act_index_cur++); - if (!act_index || - !mnl_attr_put_strz_check(buf, size, TCA_ACT_KIND, "mirred")) - goto error_nobufs; - act =3D mnl_attr_nest_start_check(buf, size, TCA_ACT_OPTIONS); - if (!act) - goto error_nobufs; - if (!mnl_attr_put_check(buf, size, TCA_MIRRED_PARMS, - sizeof(struct tc_mirred), - &(struct tc_mirred){ - .action =3D TC_ACT_STOLEN, - .eaction =3D TCA_EGRESS_REDIR, - .ifindex =3D ptoi[i].ifindex, - })) - goto error_nobufs; - mnl_attr_nest_end(buf, act); - mnl_attr_nest_end(buf, act_index); - ++action; - break; - case ACTION_DROP: - if (action->type !=3D RTE_FLOW_ACTION_TYPE_DROP) - goto trans; - act_index =3D - mnl_attr_nest_start_check(buf, size, act_index_cur++); - if (!act_index || - !mnl_attr_put_strz_check(buf, size, TCA_ACT_KIND, "gact")) - goto error_nobufs; - act =3D mnl_attr_nest_start_check(buf, size, TCA_ACT_OPTIONS); - if (!act) - goto error_nobufs; - if (!mnl_attr_put_check(buf, size, TCA_GACT_PARMS, - sizeof(struct tc_gact), - &(struct tc_gact){ - .action =3D TC_ACT_SHOT, - })) - goto error_nobufs; - mnl_attr_nest_end(buf, act); - mnl_attr_nest_end(buf, act_index); - ++action; - break; - case ACTION_OF_POP_VLAN: - if (action->type !=3D RTE_FLOW_ACTION_TYPE_OF_POP_VLAN) - goto trans; - conf.of_push_vlan =3D NULL; - i =3D TCA_VLAN_ACT_POP; - goto action_of_vlan; - case ACTION_OF_PUSH_VLAN: - if (action->type !=3D RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN) - goto trans; - conf.of_push_vlan =3D action->conf; - i =3D TCA_VLAN_ACT_PUSH; - goto action_of_vlan; - case ACTION_OF_SET_VLAN_VID: - if (action->type !=3D RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID) - goto trans; - conf.of_set_vlan_vid =3D action->conf; - if (na_vlan_id) - goto override_na_vlan_id; - i =3D TCA_VLAN_ACT_MODIFY; - goto action_of_vlan; - case ACTION_OF_SET_VLAN_PCP: - if (action->type !=3D RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP) - goto trans; - conf.of_set_vlan_pcp =3D action->conf; - if (na_vlan_priority) - goto override_na_vlan_priority; - i =3D TCA_VLAN_ACT_MODIFY; - goto action_of_vlan; -action_of_vlan: - act_index =3D - mnl_attr_nest_start_check(buf, size, act_index_cur++); - if (!act_index || - !mnl_attr_put_strz_check(buf, size, TCA_ACT_KIND, "vlan")) - goto error_nobufs; - act =3D mnl_attr_nest_start_check(buf, size, TCA_ACT_OPTIONS); - if (!act) - goto error_nobufs; - if (!mnl_attr_put_check(buf, size, TCA_VLAN_PARMS, - sizeof(struct tc_vlan), - &(struct tc_vlan){ - .action =3D TC_ACT_PIPE, - .v_action =3D i, - })) - goto error_nobufs; - if (i =3D=3D TCA_VLAN_ACT_POP) { - mnl_attr_nest_end(buf, act); - mnl_attr_nest_end(buf, act_index); - ++action; - break; - } - if (i =3D=3D TCA_VLAN_ACT_PUSH && - !mnl_attr_put_u16_check(buf, size, - TCA_VLAN_PUSH_VLAN_PROTOCOL, - conf.of_push_vlan->ethertype)) - goto error_nobufs; - na_vlan_id =3D mnl_nlmsg_get_payload_tail(buf); - if (!mnl_attr_put_u16_check(buf, size, TCA_VLAN_PAD, 0)) - goto error_nobufs; - na_vlan_priority =3D mnl_nlmsg_get_payload_tail(buf); - if (!mnl_attr_put_u8_check(buf, size, TCA_VLAN_PAD, 0)) - goto error_nobufs; - mnl_attr_nest_end(buf, act); - mnl_attr_nest_end(buf, act_index); - if (action->type =3D=3D RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID) { -override_na_vlan_id: - na_vlan_id->nla_type =3D TCA_VLAN_PUSH_VLAN_ID; - *(uint16_t *)mnl_attr_get_payload(na_vlan_id) =3D - rte_be_to_cpu_16 - (conf.of_set_vlan_vid->vlan_vid); - } else if (action->type =3D=3D - RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP) { -override_na_vlan_priority: - na_vlan_priority->nla_type =3D - TCA_VLAN_PUSH_VLAN_PRIORITY; - *(uint8_t *)mnl_attr_get_payload(na_vlan_priority) =3D - conf.of_set_vlan_pcp->vlan_pcp; - } - ++action; - break; - case END: - if (item->type !=3D RTE_FLOW_ITEM_TYPE_END || - action->type !=3D RTE_FLOW_ACTION_TYPE_END) - goto trans; - if (na_flower_act) - mnl_attr_nest_end(buf, na_flower_act); - if (na_flower) - mnl_attr_nest_end(buf, na_flower); - nlh =3D buf; - return nlh->nlmsg_len; - } - back =3D trans; - trans =3D mlx5_nl_flow_trans[trans[n - 1]]; - n =3D 0; - goto trans; -error_nobufs: - if (buf !=3D buf_tmp) { - buf =3D buf_tmp; - size =3D sizeof(buf_tmp); - goto init; - } - return rte_flow_error_set - (error, ENOBUFS, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, - "generated TC message is too large"); -} - -/** - * Brand rtnetlink buffer with unique handle. - * - * This handle should be unique for a given network interface to avoid - * collisions. - * - * @param buf - * Flow rule buffer previously initialized by mlx5_nl_flow_transpose(). - * @param handle - * Unique 32-bit handle to use. - */ -void -mlx5_nl_flow_brand(void *buf, uint32_t handle) -{ - struct tcmsg *tcm =3D mnl_nlmsg_get_payload(buf); - - tcm->tcm_handle =3D handle; -} - -/** - * Send Netlink message with acknowledgment. - * - * @param nl - * Libmnl socket to use. - * @param nlh - * Message to send. This function always raises the NLM_F_ACK flag befor= e - * sending. - * - * @return - * 0 on success, a negative errno value otherwise and rte_errno is set. - */ -static int -mlx5_nl_flow_nl_ack(struct mnl_socket *nl, struct nlmsghdr *nlh) -{ - alignas(struct nlmsghdr) - uint8_t ans[mnl_nlmsg_size(sizeof(struct nlmsgerr)) + - nlh->nlmsg_len - sizeof(*nlh)]; - uint32_t seq =3D random(); - int ret; - - nlh->nlmsg_flags |=3D NLM_F_ACK; - nlh->nlmsg_seq =3D seq; - ret =3D mnl_socket_sendto(nl, nlh, nlh->nlmsg_len); - if (ret !=3D -1) - ret =3D mnl_socket_recvfrom(nl, ans, sizeof(ans)); - if (ret !=3D -1) - ret =3D mnl_cb_run - (ans, ret, seq, mnl_socket_get_portid(nl), NULL, NULL); - if (!ret) - return 0; - rte_errno =3D errno; - return -rte_errno; -} - -/** - * Create a Netlink flow rule. - * - * @param nl - * Libmnl socket to use. - * @param buf - * Flow rule buffer previously initialized by mlx5_nl_flow_transpose(). - * @param[out] error - * Perform verbose error reporting if not NULL. - * - * @return - * 0 on success, a negative errno value otherwise and rte_errno is set. - */ -int -mlx5_nl_flow_create(struct mnl_socket *nl, void *buf, - struct rte_flow_error *error) -{ - struct nlmsghdr *nlh =3D buf; - - nlh->nlmsg_type =3D RTM_NEWTFILTER; - nlh->nlmsg_flags =3D NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL; - if (!mlx5_nl_flow_nl_ack(nl, nlh)) - return 0; - return rte_flow_error_set - (error, rte_errno, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, - "netlink: failed to create TC flow rule"); -} - -/** - * Destroy a Netlink flow rule. - * - * @param nl - * Libmnl socket to use. - * @param buf - * Flow rule buffer previously initialized by mlx5_nl_flow_transpose(). - * @param[out] error - * Perform verbose error reporting if not NULL. - * - * @return - * 0 on success, a negative errno value otherwise and rte_errno is set. - */ -int -mlx5_nl_flow_destroy(struct mnl_socket *nl, void *buf, - struct rte_flow_error *error) -{ - struct nlmsghdr *nlh =3D buf; - - nlh->nlmsg_type =3D RTM_DELTFILTER; - nlh->nlmsg_flags =3D NLM_F_REQUEST; - if (!mlx5_nl_flow_nl_ack(nl, nlh)) - return 0; - return rte_flow_error_set - (error, errno, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL, - "netlink: failed to destroy TC flow rule"); -} - -/** - * Initialize ingress qdisc of a given network interface. - * - * @param nl - * Libmnl socket of the @p NETLINK_ROUTE kind. - * @param ifindex - * Index of network interface to initialize. - * @param[out] error - * Perform verbose error reporting if not NULL. - * - * @return - * 0 on success, a negative errno value otherwise and rte_errno is set. - */ -int -mlx5_nl_flow_init(struct mnl_socket *nl, unsigned int ifindex, - struct rte_flow_error *error) -{ - struct nlmsghdr *nlh; - struct tcmsg *tcm; - alignas(struct nlmsghdr) - uint8_t buf[mnl_nlmsg_size(sizeof(*tcm) + 128)]; - - /* Destroy existing ingress qdisc and everything attached to it. */ - nlh =3D mnl_nlmsg_put_header(buf); - nlh->nlmsg_type =3D RTM_DELQDISC; - nlh->nlmsg_flags =3D NLM_F_REQUEST; - tcm =3D mnl_nlmsg_put_extra_header(nlh, sizeof(*tcm)); - tcm->tcm_family =3D AF_UNSPEC; - tcm->tcm_ifindex =3D ifindex; - tcm->tcm_handle =3D TC_H_MAKE(TC_H_INGRESS, 0); - tcm->tcm_parent =3D TC_H_INGRESS; - /* Ignore errors when qdisc is already absent. */ - if (mlx5_nl_flow_nl_ack(nl, nlh) && - rte_errno !=3D EINVAL && rte_errno !=3D ENOENT) - return rte_flow_error_set - (error, rte_errno, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, - NULL, "netlink: failed to remove ingress qdisc"); - /* Create fresh ingress qdisc. */ - nlh =3D mnl_nlmsg_put_header(buf); - nlh->nlmsg_type =3D RTM_NEWQDISC; - nlh->nlmsg_flags =3D NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL; - tcm =3D mnl_nlmsg_put_extra_header(nlh, sizeof(*tcm)); - tcm->tcm_family =3D AF_UNSPEC; - tcm->tcm_ifindex =3D ifindex; - tcm->tcm_handle =3D TC_H_MAKE(TC_H_INGRESS, 0); - tcm->tcm_parent =3D TC_H_INGRESS; - mnl_attr_put_strz_check(nlh, sizeof(buf), TCA_KIND, "ingress"); - if (mlx5_nl_flow_nl_ack(nl, nlh)) - return rte_flow_error_set - (error, rte_errno, RTE_FLOW_ERROR_TYPE_UNSPECIFIED, - NULL, "netlink: failed to create ingress qdisc"); - return 0; -} - -/** - * Create and configure a libmnl socket for Netlink flow rules. - * - * @return - * A valid libmnl socket object pointer on success, NULL otherwise and - * rte_errno is set. - */ -struct mnl_socket * -mlx5_nl_flow_socket_create(void) -{ - struct mnl_socket *nl =3D mnl_socket_open(NETLINK_ROUTE); - - if (nl) { - mnl_socket_setsockopt(nl, NETLINK_CAP_ACK, &(int){ 1 }, - sizeof(int)); - if (!mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID)) - return nl; - } - rte_errno =3D errno; - if (nl) - mnl_socket_close(nl); - return NULL; -} - -/** - * Destroy a libmnl socket. - */ -void -mlx5_nl_flow_socket_destroy(struct mnl_socket *nl) -{ - mnl_socket_close(nl); -} --=20 2.11.0