Skip to contentSkip to conversation

Flow actions to mutate packets

PATCH In review Leon Romanovsky 4 participants 31 messages Jul 29, 2018 – Jul 31, 2018

Subsystems (6)
lore
Share & tools
lore
#0 lore raw

cover Flow actions to mutate packets

From: Leon Romanovsky <[email protected]>

Hi,

This is PATCH variant of RFC posted in previous week to the ML.
https://patchwork.ozlabs.org/cover/944184/

Changelog:
RFC -> v0:
* Patch 1 a new patch which refactors the logic
when getting a flow namespace.
* Patch 2 was split into two.
* Patch 3: Fixed a typo in commit message
* Patch 5: Updated commit message
* Patch 7: Updated commit message
Renamed:
- MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT_ID to MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT
- packet_reformat_id to reformat_id in struct mlx5_flow_act
- packet_reformat_id to encap_id in struct mlx5_esw_flow_attr
- packet_reformat_id to encap_id in struct mlx5e_encap_entry
- PACKET_REFORMAT to REFORMAT when printing trace points
* Patch 9: Updated commit message
Updated function declaration in mlx5_core.h, could of lead to compile error on bisection.
* Patch 11: Disallow egress rules insertion when in switchdev mode
* Patch 12: A new patch to deal with passing enum values using the IOCTL infrastructure.
* Patch 13: Use new enum value attribute when passing enum mlx5_ib_uapi_flow_table_type
* Patch 15: Don't set encap flags on flow tables if in switchdev mode
* Patch 17: Use new enum value attribute when passing enum mlx5_ib_uapi_flow_table_type and enum mlx5_ib_uapi_flow_action_packet_reformat_type
* Patch 19: Allow creation of both MLX5_IB_UAPI_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L3_TUNNEL and MLX5_IB_UAPI_FLOW_ACTION_PACKET_REFORMAT_TYPE_L3_TUNNEL_TO_L2 packet reformat actions.
* Patch 20: A new patch which allows attaching packet reformat actions to flow tables on NIC RX.

Thanks

------------------------------------------------------------------------

Quoted 1 line

From Mark:

This series exposes the ability to create flow actions which can mutate packet headers. We do that by exposing two new verbs:
* modify header - can change existing packet headers. packet
* reformat - can encapsulate or decapsulate a packet.
Once created a flow action must be attached to a steering rule for it to take effect.

Thanks

Guy Levi (1):
IB/uverbs: Add IDRs array attribute type to ioctl() interface

Mark Bloch (26):
net/mlx5: Cleanup flow namespace getter switch logic net/mlx5: Add proper NIC TX steering flow tables support net/mlx5: Export modify header alloc/dealloc functions net/mlx5: Add support for more namespaces when allocating modify
header
net/mlx5: Break encap/decap into two separated flow table creation
flags
net/mlx5: Move header encap type to IFC header file
{net, RDMA}/mlx5: Rename encap to reformat packet net/mlx5: Expose new packet reformat capabilities net/mlx5: Pass a namespace for packet reformat ID allocation net/mlx5: Export packet reformat alloc/dealloc functions RDMA/mlx5: Add NIC TX steering support
RDMA/uverbs: Add UVERBS_ATTR_CONST_IN to the specs language RDMA/mlx5: Add a new flow action verb, modify header RDMA/mlx5: Enable attaching modify header to steering flows RDMA/mlx5: Enable decap and packet reformat on flow tables RDMA/uverbs: Add generic function to fill in flow action object RDMA/mlx5: Add new flow action verb, packet reformat RDMA/mlx5: Enable attaching DECAP action to steering flows RDMA/mlx5: Extend packet reformat verbs
RDMA/mlx5: Enable reformat on NIC RX if supported RDMA/mlx5: Enable attaching packet reformat action to steering flows RDMA/mlx5: Refactor flow action parsing to be more generic RDMA/mlx5: Refactor DEVX flow creation
RDMA/mlx5: Add flow actions support to DEVX create flow RDMA/mlx5: Add NIC TX namespace when getting a flow table RDMA/mlx5: Allow creating a matcher for a NIC TX flow table

 drivers/infiniband/core/uverbs_ioctl.c             | 115 ++++++-
 .../infiniband/core/uverbs_std_types_flow_action.c |   7 +-
 drivers/infiniband/hw/mlx5/devx.c                  |   6 +-
 drivers/infiniband/hw/mlx5/flow.c                  | 351 ++++++++++++++++++++-
 drivers/infiniband/hw/mlx5/main.c                  | 140 +++++---
 drivers/infiniband/hw/mlx5/mlx5_ib.h               |  26 +-
 drivers/net/ethernet/mellanox/mlx5/core/cmd.c      |   8 +-
 .../mellanox/mlx5/core/diag/fs_tracepoint.h        |   2 +-
 drivers/net/ethernet/mellanox/mlx5/core/en_tc.c    |  50 +--
 drivers/net/ethernet/mellanox/mlx5/core/eswitch.c  |   2 +-
 .../ethernet/mellanox/mlx5/core/eswitch_offloads.c |   9 +-
 drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c   |  87 +++--
 drivers/net/ethernet/mellanox/mlx5/core/fs_core.c  |  57 ++--
 .../net/ethernet/mellanox/mlx5/core/mlx5_core.h    |  11 -
 include/linux/mlx5/device.h                        |   6 +
 include/linux/mlx5/fs.h                            |  20 +-
 include/linux/mlx5/mlx5_ifc.h                      |  70 ++--
 include/rdma/uverbs_ioctl.h                        |  98 +++++-
 include/rdma/uverbs_std_types.h                    |  12 +
 include/uapi/rdma/mlx5_user_ioctl_cmds.h           |  20 ++
 include/uapi/rdma/mlx5_user_ioctl_verbs.h          |  12 +
 include/uapi/rdma/rdma_user_ioctl_cmds.h           |   2 +-
 22 files changed, 928 insertions(+), 183 deletions(-)
#1 lore raw

PATCH 1/27 net/mlx5: Cleanup flow namespace getter switch logic

From: Mark Bloch <[email protected]>

Refactor the switch logic so it's simpler to follow and understand.

---
 drivers/net/ethernet/mellanox/mlx5/core/fs_core.c | 22 +++++++++-------------
 1 file changed, 9 insertions(+), 13 deletions(-)
drivers/net/ethernet/mellanox/mlx5/core/fs_core.c +9 -13
index 0d8378243903..17bbad8ee882 100644
@@ -1976,7 +1976,7 @@ struct mlx5_flow_namespace *mlx5_get_flow_namespace(struct mlx5_core_dev *dev,
 						    enum mlx5_flow_namespace_type type)
 {
 	struct mlx5_flow_steering *steering = dev->priv.steering;
-	struct mlx5_flow_root_namespace *root_ns;
+	struct mlx5_flow_root_namespace *steering_ns = NULL;
 	int prio;
 	struct fs_prio *fs_prio;
 	struct mlx5_flow_namespace *ns;
@@ -1992,37 +1992,33 @@ struct mlx5_flow_namespace *mlx5_get_flow_namespace(struct mlx5_core_dev *dev,
 	case MLX5_FLOW_NAMESPACE_KERNEL:
 	case MLX5_FLOW_NAMESPACE_LEFTOVERS:
 	case MLX5_FLOW_NAMESPACE_ANCHOR:
+		steering_ns = steering->root_ns;
 		prio = type;
 		break;
 	case MLX5_FLOW_NAMESPACE_FDB:
 		if (steering->fdb_root_ns)
 			return &steering->fdb_root_ns->ns;
-		else
-			return NULL;
+		break;
 	case MLX5_FLOW_NAMESPACE_SNIFFER_RX:
 		if (steering->sniffer_rx_root_ns)
 			return &steering->sniffer_rx_root_ns->ns;
-		else
-			return NULL;
+		break;
 	case MLX5_FLOW_NAMESPACE_SNIFFER_TX:
 		if (steering->sniffer_tx_root_ns)
 			return &steering->sniffer_tx_root_ns->ns;
-		else
-			return NULL;
+		break;
 	case MLX5_FLOW_NAMESPACE_EGRESS:
 		if (steering->egress_root_ns)
 			return &steering->egress_root_ns->ns;
-		else
-			return NULL;
+		break;
 	default:
-		return NULL;
+		break;
 	}
 
-	root_ns = steering->root_ns;
-	if (!root_ns)
+	if (!steering_ns)
 		return NULL;
 
-	fs_prio = find_prio(&root_ns->ns, prio);
+	fs_prio = find_prio(&steering_ns->ns, prio);
 	if (!fs_prio)
 		return NULL;
 
Signature · 1 line
2.14.4
#2 lore raw

PATCH 2/27 net/mlx5: Add proper NIC TX steering flow tables support

In reply to Leon Romanovsky

From: Mark Bloch <[email protected]>

Expose the ability to add steering rules to NIC TX flow tables. For now, we are only adding TX bypass (egress) which is used by the RDMA side. This will allow an administrator to control outgoing traffic and tweak it if needed, for example preforming encapsulation or rewriting headers.

---
 drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c  |  2 +-
 drivers/net/ethernet/mellanox/mlx5/core/fs_core.c | 33 +++++++++++++++++------
 include/linux/mlx5/device.h                       |  6 +++++
 3 files changed, 32 insertions(+), 9 deletions(-)
drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c +1 -1
index 8e01f818021b..28c7301e08f4 100644
@@ -760,8 +760,8 @@ const struct mlx5_flow_cmds *mlx5_fs_cmd_get_default(enum fs_flow_table_type typ
 	case FS_FT_FDB:
 	case FS_FT_SNIFFER_RX:
 	case FS_FT_SNIFFER_TX:
-		return mlx5_fs_cmd_get_fw_cmds();
 	case FS_FT_NIC_TX:
+		return mlx5_fs_cmd_get_fw_cmds();
 	default:
 		return mlx5_fs_cmd_get_stub_cmds();
 	}
drivers/net/ethernet/mellanox/mlx5/core/fs_core.c +25 -8
index 17bbad8ee882..8243a93e1d6c 100644
@@ -150,6 +150,17 @@ static struct init_tree_node {
 	}
 };
 
+static struct init_tree_node egress_root_fs = {
+	.type = FS_TYPE_NAMESPACE,
+	.ar_size = 1,
+	.children = (struct init_tree_node[]) {
+		ADD_PRIO(0, MLX5_BY_PASS_NUM_PRIOS, 0,
+			 FS_CHAINING_CAPS,
+			 ADD_NS(ADD_MULTIPLE_PRIO(MLX5_BY_PASS_NUM_PRIOS,
+						  BY_PASS_PRIO_NUM_LEVELS))),
+	}
+};
+
 enum fs_i_lock_class {
 	FS_LOCK_GRANDPARENT,
 	FS_LOCK_PARENT,
@@ -2008,8 +2019,10 @@ struct mlx5_flow_namespace *mlx5_get_flow_namespace(struct mlx5_core_dev *dev,
 			return &steering->sniffer_tx_root_ns->ns;
 		break;
 	case MLX5_FLOW_NAMESPACE_EGRESS:
-		if (steering->egress_root_ns)
-			return &steering->egress_root_ns->ns;
+		if (steering->egress_root_ns) {
+			steering_ns = steering->egress_root_ns;
+			prio = 0;
+		}
 		break;
 	default:
 		break;
@@ -2530,16 +2543,20 @@ static int init_ingress_acls_root_ns(struct mlx5_core_dev *dev)
 
 static int init_egress_root_ns(struct mlx5_flow_steering *steering)
 {
-	struct fs_prio *prio;
-
 	steering->egress_root_ns = create_root_ns(steering,
 						  FS_FT_NIC_TX);
 	if (!steering->egress_root_ns)
 		return -ENOMEM;
 
-	/* create 1 prio*/
-	prio = fs_create_prio(&steering->egress_root_ns->ns, 0, 1);
-	return PTR_ERR_OR_ZERO(prio);
+	if (init_root_tree(steering, &egress_root_fs,
+			   &steering->egress_root_ns->ns.node))
+		goto cleanup;
+	set_prio_attrs(steering->egress_root_ns);
+	return 0;
+cleanup:
+	cleanup_root_ns(steering->egress_root_ns);
+	steering->egress_root_ns = NULL;
+	return -ENOMEM;
 }
 
 int mlx5_init_fs(struct mlx5_core_dev *dev)
@@ -2607,7 +2624,7 @@ int mlx5_init_fs(struct mlx5_core_dev *dev)
 			goto err;
 	}
 
-	if (MLX5_IPSEC_DEV(dev)) {
+	if (MLX5_IPSEC_DEV(dev) || MLX5_CAP_FLOWTABLE_NIC_TX(dev, ft_support)) {
 		err = init_egress_root_ns(steering);
 		if (err)
 			goto err;
include/linux/mlx5/device.h +6 -0
index 0566c6a94805..e9c35eb1cc26 100644
@@ -1113,6 +1113,12 @@ enum mlx5_qcam_feature_groups {
 #define MLX5_CAP_FLOWTABLE_NIC_RX_MAX(mdev, cap) \
 	MLX5_CAP_FLOWTABLE_MAX(mdev, flow_table_properties_nic_receive.cap)
 
+#define MLX5_CAP_FLOWTABLE_NIC_TX(mdev, cap) \
+		MLX5_CAP_FLOWTABLE(mdev, flow_table_properties_nic_transmit.cap)
+
+#define MLX5_CAP_FLOWTABLE_NIC_TX_MAX(mdev, cap) \
+		MLX5_CAP_FLOWTABLE_MAX(mdev, flow_table_properties_nic_transmit.cap)
+
 #define MLX5_CAP_FLOWTABLE_SNIFFER_RX(mdev, cap) \
 	MLX5_CAP_FLOWTABLE(mdev, flow_table_properties_nic_receive_sniffer.cap)
 
Signature · 1 line
2.14.4
#3 lore raw

PATCH 3/27 net/mlx5: Export modify header alloc/dealloc functions

In reply to Leon Romanovsky

From: Mark Bloch <[email protected]>

Those functions will be used by the RDMA side to create modify header actions to be attached to flow steering rules via verbs.

---
 drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c    | 2 ++
 drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h | 5 -----
 include/linux/mlx5/fs.h                             | 6 ++++++
 3 files changed, 8 insertions(+), 5 deletions(-)
drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c +2 -0
index 28c7301e08f4..37bea30b68ac 100644
@@ -702,6 +702,7 @@ int mlx5_modify_header_alloc(struct mlx5_core_dev *dev,
 	kfree(in);
 	return err;
 }
+EXPORT_SYMBOL(mlx5_modify_header_alloc);
 
 void mlx5_modify_header_dealloc(struct mlx5_core_dev *dev, u32 modify_header_id)
 {
@@ -716,6 +717,7 @@ void mlx5_modify_header_dealloc(struct mlx5_core_dev *dev, u32 modify_header_id)
 
 	mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
 }
+EXPORT_SYMBOL(mlx5_modify_header_dealloc);
 
 static const struct mlx5_flow_cmds mlx5_flow_cmds = {
 	.create_flow_table = mlx5_cmd_create_flow_table,
drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h +0 -5
index 49955117ae36..b076ce14c48c 100644
@@ -177,11 +177,6 @@ int mlx5_encap_alloc(struct mlx5_core_dev *dev,
 		     u32 *encap_id);
 void mlx5_encap_dealloc(struct mlx5_core_dev *dev, u32 encap_id);
 
-int mlx5_modify_header_alloc(struct mlx5_core_dev *dev,
-			     u8 namespace, u8 num_actions,
-			     void *modify_actions, u32 *modify_header_id);
-void mlx5_modify_header_dealloc(struct mlx5_core_dev *dev, u32 modify_header_id);
-
 bool mlx5_lag_intf_add(struct mlx5_interface *intf, struct mlx5_priv *priv);
 
 int mlx5_query_mtpps(struct mlx5_core_dev *dev, u32 *mtpps, u32 mtpps_size);
include/linux/mlx5/fs.h +6 -0
index af0592400499..245f9e80ef92 100644
@@ -196,4 +196,10 @@ int mlx5_fc_query(struct mlx5_core_dev *dev, struct mlx5_fc *counter,
 int mlx5_fs_add_rx_underlay_qpn(struct mlx5_core_dev *dev, u32 underlay_qpn);
 int mlx5_fs_remove_rx_underlay_qpn(struct mlx5_core_dev *dev, u32 underlay_qpn);
 
+int mlx5_modify_header_alloc(struct mlx5_core_dev *dev,
+			     u8 namespace, u8 num_actions,
+			     void *modify_actions, u32 *modify_header_id);
+void mlx5_modify_header_dealloc(struct mlx5_core_dev *dev,
+				u32 modify_header_id);
+
 #endif
Signature · 1 line
2.14.4
#4 lore raw

PATCH 4/27 net/mlx5: Add support for more namespaces when allocating modify header

In reply to Leon Romanovsky

From: Mark Bloch <[email protected]>

There are RX and TX flow steering namespaces with different number of actions. Initialize them accordingly.

---
 drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c | 5 +++++
 1 file changed, 5 insertions(+)
drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c +5 -0
index 37bea30b68ac..9ae777e56529 100644
@@ -667,9 +667,14 @@ int mlx5_modify_header_alloc(struct mlx5_core_dev *dev,
 		table_type = FS_FT_FDB;
 		break;
 	case MLX5_FLOW_NAMESPACE_KERNEL:
+	case MLX5_FLOW_NAMESPACE_BYPASS:
 		max_actions = MLX5_CAP_FLOWTABLE_NIC_RX(dev, max_modify_header_actions);
 		table_type = FS_FT_NIC_RX;
 		break;
+	case MLX5_FLOW_NAMESPACE_EGRESS:
+		max_actions = MLX5_CAP_FLOWTABLE_NIC_TX(dev, max_modify_header_actions);
+		table_type = FS_FT_NIC_TX;
+		break;
 	default:
 		return -EOPNOTSUPP;
 	}
Signature · 1 line
2.14.4
#5 lore raw

PATCH 5/27 net/mlx5: Break encap/decap into two separated flow table creation flags

In reply to Leon Romanovsky

From: Mark Bloch <[email protected]>

Today we are able to attach encap and decap actions only to the FDB. In preparation to enable those actions on the NIC flow tables, break the single flag into two. Those flags control whatever a decap or encap operations can be attached to the flow table created. For FDB, if encapsulation is required, we set both of them.

---
 drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c | 3 ++-
 drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c           | 7 ++++---
 include/linux/mlx5/fs.h                                    | 3 ++-
 3 files changed, 8 insertions(+), 5 deletions(-)
drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +2 -1
index 8f50ce80ff66..83341c92602e 100644
@@ -524,7 +524,8 @@ static int esw_create_offloads_fast_fdb_table(struct mlx5_eswitch *esw)
 		esw_size >>= 1;
 
 	if (esw->offloads.encap != DEVLINK_ESWITCH_ENCAP_MODE_NONE)
-		flags |= MLX5_FLOW_TABLE_TUNNEL_EN;
+		flags |= (MLX5_FLOW_TABLE_TUNNEL_EN_ENCAP |
+			  MLX5_FLOW_TABLE_TUNNEL_EN_DECAP);
 
 	fdb = mlx5_create_auto_grouped_flow_table(root_ns, FDB_FAST_PATH,
 						  esw_size,
drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c +4 -3
index 9ae777e56529..1698f325a21e 100644
@@ -152,7 +152,8 @@ static int mlx5_cmd_create_flow_table(struct mlx5_core_dev *dev,
 				      struct mlx5_flow_table *next_ft,
 				      unsigned int *table_id, u32 flags)
 {
-	int en_encap_decap = !!(flags & MLX5_FLOW_TABLE_TUNNEL_EN);
+	int en_encap = !!(flags & MLX5_FLOW_TABLE_TUNNEL_EN_ENCAP);
+	int en_decap = !!(flags & MLX5_FLOW_TABLE_TUNNEL_EN_DECAP);
 	u32 out[MLX5_ST_SZ_DW(create_flow_table_out)] = {0};
 	u32 in[MLX5_ST_SZ_DW(create_flow_table_in)]   = {0};
 	int err;
@@ -169,9 +170,9 @@ static int mlx5_cmd_create_flow_table(struct mlx5_core_dev *dev,
 	}
 
 	MLX5_SET(create_flow_table_in, in, flow_table_context.decap_en,
-		 en_encap_decap);
+		 en_decap);
 	MLX5_SET(create_flow_table_in, in, flow_table_context.encap_en,
-		 en_encap_decap);
+		 en_encap);
 
 	switch (op_mod) {
 	case FS_FT_OP_MOD_NORMAL:
include/linux/mlx5/fs.h +2 -1
index 245f9e80ef92..816cbfa00c3b 100644
@@ -45,7 +45,8 @@ enum {
 };
 
 enum {
-	MLX5_FLOW_TABLE_TUNNEL_EN = BIT(0),
+	MLX5_FLOW_TABLE_TUNNEL_EN_ENCAP = BIT(0),
+	MLX5_FLOW_TABLE_TUNNEL_EN_DECAP = BIT(1),
 };
 
 #define LEFTOVERS_RULE_NUM	 2
Signature · 1 line
2.14.4
#6 lore raw

PATCH 6/27 net/mlx5: Move header encap type to IFC header file

In reply to Leon Romanovsky

From: Mark Bloch <[email protected]>

Those bits are hardware specification and should be defined at the IFC header file.

---
 drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 5 -----
 include/linux/mlx5/mlx5_ifc.h                   | 5 +++++
 2 files changed, 5 insertions(+), 5 deletions(-)
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +0 -5
index 0edf4751a8ba..74601f9d1c28 100644
@@ -100,11 +100,6 @@ struct mlx5e_tc_flow_parse_attr {
 	int mirred_ifindex;
 };
 
-enum {
-	MLX5_HEADER_TYPE_VXLAN = 0x0,
-	MLX5_HEADER_TYPE_NVGRE = 0x1,
-};
-
 #define MLX5E_TC_TABLE_NUM_GROUPS 4
 #define MLX5E_TC_TABLE_MAX_GROUP_SIZE BIT(16)
 
include/linux/mlx5/mlx5_ifc.h +5 -0
index 5e04e2053fd7..1745366ee5b7 100644
@@ -4843,6 +4843,11 @@ struct mlx5_ifc_alloc_encap_header_out_bits {
 	u8         reserved_at_60[0x20];
 };
 
+enum {
+	MLX5_HEADER_TYPE_VXLAN = 0x0,
+	MLX5_HEADER_TYPE_NVGRE = 0x1,
+};
+
 struct mlx5_ifc_alloc_encap_header_in_bits {
 	u8         opcode[0x10];
 	u8         reserved_at_10[0x10];
Signature · 1 line
2.14.4
#7 lore raw

PATCH 7/27 {net, RDMA}/mlx5: Rename encap to reformat packet

In reply to Leon Romanovsky

From: Mark Bloch <[email protected]>

Renames all encap mlx5_{core,ib} code to use the new naming of packet reformat. No functional change is introduced. This is done because the original naming didn't reflect correctly the operation being done by this action. For example not only can we encapsulate a packet, but also decapsulate it.

---
 drivers/infiniband/hw/mlx5/devx.c                  |  6 +--
 drivers/net/ethernet/mellanox/mlx5/core/cmd.c      |  8 +--
 .../mellanox/mlx5/core/diag/fs_tracepoint.h        |  2 +-
 drivers/net/ethernet/mellanox/mlx5/core/en_tc.c    | 42 ++++++++-------
 drivers/net/ethernet/mellanox/mlx5/core/eswitch.c  |  2 +-
 .../ethernet/mellanox/mlx5/core/eswitch_offloads.c |  8 +--
 drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c   | 63 ++++++++++++----------
 drivers/net/ethernet/mellanox/mlx5/core/fs_core.c  |  2 +-
 .../net/ethernet/mellanox/mlx5/core/mlx5_core.h    | 13 ++---
 include/linux/mlx5/fs.h                            |  4 +-
 include/linux/mlx5/mlx5_ifc.h                      | 50 ++++++++---------
 11 files changed, 106 insertions(+), 94 deletions(-)
drivers/infiniband/hw/mlx5/devx.c +3 -3
index c9a7a12a8c13..3da36fa7024e 100644
@@ -284,7 +284,7 @@ static bool devx_is_obj_create_cmd(const void *in)
 	case MLX5_CMD_OP_CREATE_FLOW_TABLE:
 	case MLX5_CMD_OP_CREATE_FLOW_GROUP:
 	case MLX5_CMD_OP_ALLOC_FLOW_COUNTER:
-	case MLX5_CMD_OP_ALLOC_ENCAP_HEADER:
+	case MLX5_CMD_OP_ALLOC_PACKET_REFORMAT_CONTEXT:
 	case MLX5_CMD_OP_ALLOC_MODIFY_HEADER_CONTEXT:
 	case MLX5_CMD_OP_CREATE_SCHEDULING_ELEMENT:
 	case MLX5_CMD_OP_ADD_VXLAN_UDP_DPORT:
@@ -627,9 +627,9 @@ static void devx_obj_build_destroy_cmd(void *in, void *out, void *din,
 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
 			 MLX5_CMD_OP_DEALLOC_FLOW_COUNTER);
 		break;
-	case MLX5_CMD_OP_ALLOC_ENCAP_HEADER:
+	case MLX5_CMD_OP_ALLOC_PACKET_REFORMAT_CONTEXT:
 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
-			 MLX5_CMD_OP_DEALLOC_ENCAP_HEADER);
+			 MLX5_CMD_OP_DEALLOC_PACKET_REFORMAT_CONTEXT);
 		break;
 	case MLX5_CMD_OP_ALLOC_MODIFY_HEADER_CONTEXT:
 		MLX5_SET(general_obj_in_cmd_hdr, din, opcode,
drivers/net/ethernet/mellanox/mlx5/core/cmd.c +4 -4
index 381dbfa6a68e..694ed2afa7ed 100644
@@ -308,7 +308,7 @@ static int mlx5_internal_err_ret_value(struct mlx5_core_dev *dev, u16 op,
 	case MLX5_CMD_OP_MODIFY_FLOW_TABLE:
 	case MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY:
 	case MLX5_CMD_OP_SET_FLOW_TABLE_ROOT:
-	case MLX5_CMD_OP_DEALLOC_ENCAP_HEADER:
+	case MLX5_CMD_OP_DEALLOC_PACKET_REFORMAT_CONTEXT:
 	case MLX5_CMD_OP_DEALLOC_MODIFY_HEADER_CONTEXT:
 	case MLX5_CMD_OP_FPGA_DESTROY_QP:
 	case MLX5_CMD_OP_DESTROY_GENERAL_OBJECT:
@@ -426,7 +426,7 @@ static int mlx5_internal_err_ret_value(struct mlx5_core_dev *dev, u16 op,
 	case MLX5_CMD_OP_QUERY_FLOW_TABLE_ENTRY:
 	case MLX5_CMD_OP_ALLOC_FLOW_COUNTER:
 	case MLX5_CMD_OP_QUERY_FLOW_COUNTER:
-	case MLX5_CMD_OP_ALLOC_ENCAP_HEADER:
+	case MLX5_CMD_OP_ALLOC_PACKET_REFORMAT_CONTEXT:
 	case MLX5_CMD_OP_ALLOC_MODIFY_HEADER_CONTEXT:
 	case MLX5_CMD_OP_FPGA_CREATE_QP:
 	case MLX5_CMD_OP_FPGA_MODIFY_QP:
@@ -599,8 +599,8 @@ const char *mlx5_command_str(int command)
 	MLX5_COMMAND_STR_CASE(DEALLOC_FLOW_COUNTER);
 	MLX5_COMMAND_STR_CASE(QUERY_FLOW_COUNTER);
 	MLX5_COMMAND_STR_CASE(MODIFY_FLOW_TABLE);
-	MLX5_COMMAND_STR_CASE(ALLOC_ENCAP_HEADER);
-	MLX5_COMMAND_STR_CASE(DEALLOC_ENCAP_HEADER);
+	MLX5_COMMAND_STR_CASE(ALLOC_PACKET_REFORMAT_CONTEXT);
+	MLX5_COMMAND_STR_CASE(DEALLOC_PACKET_REFORMAT_CONTEXT);
 	MLX5_COMMAND_STR_CASE(ALLOC_MODIFY_HEADER_CONTEXT);
 	MLX5_COMMAND_STR_CASE(DEALLOC_MODIFY_HEADER_CONTEXT);
 	MLX5_COMMAND_STR_CASE(FPGA_CREATE_QP);
drivers/net/ethernet/mellanox/mlx5/core/diag/fs_tracepoint.h +1 -1
index 0240aee9189e..e83dda441a81 100644
@@ -133,7 +133,7 @@ TRACE_EVENT(mlx5_fs_del_fg,
 	{MLX5_FLOW_CONTEXT_ACTION_DROP,		 "DROP"},\
 	{MLX5_FLOW_CONTEXT_ACTION_FWD_DEST,	 "FWD"},\
 	{MLX5_FLOW_CONTEXT_ACTION_COUNT,	 "CNT"},\
-	{MLX5_FLOW_CONTEXT_ACTION_ENCAP,	 "ENCAP"},\
+	{MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT, "REFORMAT"},\
 	{MLX5_FLOW_CONTEXT_ACTION_DECAP,	 "DECAP"},\
 	{MLX5_FLOW_CONTEXT_ACTION_MOD_HDR,	 "MOD_HDR"},\
 	{MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH,	 "VLAN_PUSH"},\
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +22 -20

138 lines not on this page · raw message

drivers/net/ethernet/mellanox/mlx5/core/eswitch.c +1 -1
index f63dfbcd29fe..d2c877de523b 100644
@@ -1748,7 +1748,7 @@ int mlx5_eswitch_init(struct mlx5_core_dev *dev)
 	esw->enabled_vports = 0;
 	esw->mode = SRIOV_NONE;
 	esw->offloads.inline_mode = MLX5_INLINE_MODE_NONE;
-	if (MLX5_CAP_ESW_FLOWTABLE_FDB(dev, encap) &&
+	if (MLX5_CAP_ESW_FLOWTABLE_FDB(dev, reformat) &&
 	    MLX5_CAP_ESW_FLOWTABLE_FDB(dev, decap))
 		esw->offloads.encap = DEVLINK_ESWITCH_ENCAP_MODE_BASIC;
 	else
drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +4 -4
index 83341c92602e..5be923035f62 100644
@@ -122,8 +122,8 @@ mlx5_eswitch_add_offloaded_rule(struct mlx5_eswitch *esw,
 	if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR)
 		flow_act.modify_id = attr->mod_hdr_id;
 
-	if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_ENCAP)
-		flow_act.encap_id = attr->encap_id;
+	if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT)
+		flow_act.reformat_id = attr->encap_id;
 
 	rule = mlx5_add_flow_rules(ft, spec, &flow_act, dest, i);
 	if (IS_ERR(rule))
@@ -524,7 +524,7 @@ static int esw_create_offloads_fast_fdb_table(struct mlx5_eswitch *esw)
 		esw_size >>= 1;
 
 	if (esw->offloads.encap != DEVLINK_ESWITCH_ENCAP_MODE_NONE)
-		flags |= (MLX5_FLOW_TABLE_TUNNEL_EN_ENCAP |
+		flags |= (MLX5_FLOW_TABLE_TUNNEL_EN_REFORMAT |
 			  MLX5_FLOW_TABLE_TUNNEL_EN_DECAP);
 
 	fdb = mlx5_create_auto_grouped_flow_table(root_ns, FDB_FAST_PATH,
@@ -1240,7 +1240,7 @@ int mlx5_devlink_eswitch_encap_mode_set(struct devlink *devlink, u8 encap)
 		return err;
 
 	if (encap != DEVLINK_ESWITCH_ENCAP_MODE_NONE &&
-	    (!MLX5_CAP_ESW_FLOWTABLE_FDB(dev, encap) ||
+	    (!MLX5_CAP_ESW_FLOWTABLE_FDB(dev, reformat) ||
 	     !MLX5_CAP_ESW_FLOWTABLE_FDB(dev, decap)))
 		return -EOPNOTSUPP;
 
drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c +36 -27

112 lines not on this page · raw message

drivers/net/ethernet/mellanox/mlx5/core/fs_core.c +1 -1
index 8243a93e1d6c..9ac199076972 100644
@@ -1398,7 +1398,7 @@ static bool check_conflicting_actions(u32 action1, u32 action2)
 		return false;
 
 	if (xored_actions & (MLX5_FLOW_CONTEXT_ACTION_DROP  |
-			     MLX5_FLOW_CONTEXT_ACTION_ENCAP |
+			     MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT |
 			     MLX5_FLOW_CONTEXT_ACTION_DECAP |
 			     MLX5_FLOW_CONTEXT_ACTION_MOD_HDR  |
 			     MLX5_FLOW_CONTEXT_ACTION_VLAN_POP |
drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h +7 -6
index b076ce14c48c..e16f6e6e03e1 100644
@@ -170,12 +170,13 @@ struct mlx5_core_dev *mlx5_get_next_phys_dev(struct mlx5_core_dev *dev);
 void mlx5_dev_list_lock(void);
 void mlx5_dev_list_unlock(void);
 int mlx5_dev_list_trylock(void);
-int mlx5_encap_alloc(struct mlx5_core_dev *dev,
-		     int header_type,
-		     size_t size,
-		     void *encap_header,
-		     u32 *encap_id);
-void mlx5_encap_dealloc(struct mlx5_core_dev *dev, u32 encap_id);
+int mlx5_packet_reformat_alloc(struct mlx5_core_dev *dev,
+			       int reformat_type,
+			       size_t size,
+			       void *reformat_data,
+			       u32 *packet_reformat_id);
+void mlx5_packet_reformat_dealloc(struct mlx5_core_dev *dev,
+				  u32 packet_reformat_id);
 
 bool mlx5_lag_intf_add(struct mlx5_interface *intf, struct mlx5_priv *priv);
 
include/linux/mlx5/fs.h +2 -2
index 816cbfa00c3b..3bd5ad3fa28a 100644
@@ -45,7 +45,7 @@ enum {
 };
 
 enum {
-	MLX5_FLOW_TABLE_TUNNEL_EN_ENCAP = BIT(0),
+	MLX5_FLOW_TABLE_TUNNEL_EN_REFORMAT = BIT(0),
 	MLX5_FLOW_TABLE_TUNNEL_EN_DECAP = BIT(1),
 };
 
@@ -160,7 +160,7 @@ struct mlx5_flow_act {
 	u32 action;
 	bool has_flow_tag;
 	u32 flow_tag;
-	u32 encap_id;
+	u32 reformat_id;
 	u32 modify_id;
 	uintptr_t esp_id;
 	struct mlx5_fs_vlan vlan[MLX5_FS_VLAN_DEPTH];
include/linux/mlx5/mlx5_ifc.h +25 -25

149 lines not on this page · raw message

Signature · 1 line
2.14.4
#8 lore raw

PATCH 8/27 net/mlx5: Expose new packet reformat capabilities

In reply to Leon Romanovsky

From: Mark Bloch <[email protected]>

Expose new abilities when creating a packet reformat context.

The new types which can be created are:
MLX5_REFORMAT_TYPE_L2_TO_L2_TUNNEL: Ability to create generic encap operation to be done by the HW.

MLX5_REFORMAT_TYPE_L3_TUNNEL_TO_L2: Ability to create generic decap operation where the inner packet doesn't contain L2.

MLX5_REFORMAT_TYPE_L2_TO_L3_TUNNEL: Ability to create generic encap operation to be done by the HW. The L2 of the original packet is dropped.

---
 include/linux/mlx5/mlx5_ifc.h | 19 ++++++++++++++++---
 1 file changed, 16 insertions(+), 3 deletions(-)
include/linux/mlx5/mlx5_ifc.h +16 -3
index f83435d749b6..9f26e53677ca 100644
@@ -344,8 +344,12 @@ struct mlx5_ifc_flow_table_prop_layout_bits {
 	u8         reserved_at_c[0x1];
 	u8         pop_vlan_2[0x1];
 	u8         push_vlan_2[0x1];
-	u8         reserved_at_f[0x11];
-
+	u8	   reformat_and_vlan_action[0x1];
+	u8	   reserved_at_10[0x2];
+	u8	   reformat_l3_tunnel_to_l2[0x1];
+	u8	   reformat_l2_to_l3_tunnel[0x1];
+	u8	   reformat_and_modify_action[0x1];
+	u8         reserved_at_14[0xb];
 	u8         reserved_at_20[0x2];
 	u8         log_max_ft_size[0x6];
 	u8         log_max_modify_header_context[0x8];
@@ -554,7 +558,13 @@ struct mlx5_ifc_flow_table_nic_cap_bits {
 	u8         nic_rx_multi_path_tirs[0x1];
 	u8         nic_rx_multi_path_tirs_fts[0x1];
 	u8         allow_sniffer_and_nic_rx_shared_tir[0x1];
-	u8         reserved_at_3[0x1fd];
+	u8	   reserved_at_3[0x1d];
+	u8	   encap_general_header[0x1];
+	u8	   reserved_at_21[0xa];
+	u8	   log_max_packet_reformat_context[0x5];
+	u8	   reserved_at_30[0x6];
+	u8	   max_encap_header_size[0xa];
+	u8	   reserved_at_40[0x1c0];
 
 	struct mlx5_ifc_flow_table_prop_layout_bits flow_table_properties_nic_receive;
 
@@ -4846,6 +4856,9 @@ struct mlx5_ifc_alloc_packet_reformat_context_out_bits {
 enum {
 	MLX5_REFORMAT_TYPE_L2_TO_VXLAN = 0x0,
 	MLX5_REFORMAT_TYPE_L2_TO_NVGRE = 0x1,
+	MLX5_REFORMAT_TYPE_L2_TO_L2_TUNNEL = 0x2,
+	MLX5_REFORMAT_TYPE_L3_TUNNEL_TO_L2 = 0x3,
+	MLX5_REFORMAT_TYPE_L2_TO_L3_TUNNEL = 0x4,
 };
 
 struct mlx5_ifc_alloc_packet_reformat_context_in_bits {
Signature · 1 line
2.14.4
#9 lore raw

PATCH 9/27 net/mlx5: Pass a namespace for packet reformat ID allocation

In reply to Leon Romanovsky

From: Mark Bloch <[email protected]>

Currently we attach packet reformat actions only to the FDB namespace. In preparation to be able to use that for NIC steering, pass the actual namespace as a parameter.

---
 drivers/net/ethernet/mellanox/mlx5/core/en_tc.c     | 3 +++
 drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c    | 8 +++++++-
 drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h | 1 +
 3 files changed, 11 insertions(+), 1 deletion(-)
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +3 -0
index ec787e8a0be4..f111bf08f2be 100644
@@ -925,6 +925,7 @@ void mlx5e_tc_encap_flows_add(struct mlx5e_priv *priv,
 
 	err = mlx5_packet_reformat_alloc(priv->mdev, e->tunnel_type,
 					 e->encap_size, e->encap_header,
+					 MLX5_FLOW_NAMESPACE_FDB,
 					 &e->encap_id);
 	if (err) {
 		mlx5_core_warn(priv->mdev, "Failed to offload cached encapsulation header, %d\n",
@@ -2314,6 +2315,7 @@ static int mlx5e_create_encap_header_ipv4(struct mlx5e_priv *priv,
 
 	err = mlx5_packet_reformat_alloc(priv->mdev, e->tunnel_type,
 					 ipv4_encap_size, encap_header,
+					 MLX5_FLOW_NAMESPACE_FDB,
 					 &e->encap_id);
 	if (err)
 		goto destroy_neigh_entry;
@@ -2422,6 +2424,7 @@ static int mlx5e_create_encap_header_ipv6(struct mlx5e_priv *priv,
 
 	err = mlx5_packet_reformat_alloc(priv->mdev, e->tunnel_type,
 					 ipv6_encap_size, encap_header,
+					 MLX5_FLOW_NAMESPACE_FDB,
 					 &e->encap_id);
 	if (err)
 		goto destroy_neigh_entry;
drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c +7 -1
index 4539b709db20..d686668a8d52 100644
@@ -600,16 +600,22 @@ int mlx5_packet_reformat_alloc(struct mlx5_core_dev *dev,
 			       int reformat_type,
 			       size_t size,
 			       void *reformat_data,
+			       int namespace,
 			       u32 *packet_reformat_id)
 {
-	int max_encap_size = MLX5_CAP_ESW(dev, max_encap_header_size);
 	u32 out[MLX5_ST_SZ_DW(alloc_packet_reformat_context_out)];
 	void *packet_reformat_context_in;
+	int max_encap_size;
 	void *reformat;
 	int inlen;
 	int err;
 	u32 *in;
 
+	if (namespace == MLX5_FLOW_NAMESPACE_FDB)
+		max_encap_size = MLX5_CAP_ESW(dev, max_encap_header_size);
+	else
+		max_encap_size = MLX5_CAP_FLOWTABLE(dev, max_encap_header_size);
+
 	if (size > max_encap_size) {
 		mlx5_core_warn(dev, "encap size %zd too big, max supported is %d\n",
 			       size, max_encap_size);
drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h +1 -0
index e16f6e6e03e1..0f3d9942d1a9 100644
@@ -174,6 +174,7 @@ int mlx5_packet_reformat_alloc(struct mlx5_core_dev *dev,
 			       int reformat_type,
 			       size_t size,
 			       void *reformat_data,
+			       int namespace,
 			       u32 *packet_reformat_id);
 void mlx5_packet_reformat_dealloc(struct mlx5_core_dev *dev,
 				  u32 packet_reformat_id);
Signature · 1 line
2.14.4
#10 lore raw

PATCH 10/27 net/mlx5: Export packet reformat alloc/dealloc functions

In reply to Leon Romanovsky

From: Mark Bloch <[email protected]>

This will allow for the RDMA side to allocate packet reformat context.

---
 drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c    | 2 ++
 drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h | 8 --------
 include/linux/mlx5/fs.h                             | 9 +++++++++
 3 files changed, 11 insertions(+), 8 deletions(-)
drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c +2 -0
index d686668a8d52..eb91cbf42ce7 100644
@@ -651,6 +651,7 @@ int mlx5_packet_reformat_alloc(struct mlx5_core_dev *dev,
 	kfree(in);
 	return err;
 }
+EXPORT_SYMBOL(mlx5_packet_reformat_alloc);
 
 void mlx5_packet_reformat_dealloc(struct mlx5_core_dev *dev,
 				  u32 packet_reformat_id)
@@ -666,6 +667,7 @@ void mlx5_packet_reformat_dealloc(struct mlx5_core_dev *dev,
 
 	mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
 }
+EXPORT_SYMBOL(mlx5_packet_reformat_dealloc);
 
 int mlx5_modify_header_alloc(struct mlx5_core_dev *dev,
 			     u8 namespace, u8 num_actions,
drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h +0 -8
index 0f3d9942d1a9..4b1b505b20e0 100644
@@ -170,14 +170,6 @@ struct mlx5_core_dev *mlx5_get_next_phys_dev(struct mlx5_core_dev *dev);
 void mlx5_dev_list_lock(void);
 void mlx5_dev_list_unlock(void);
 int mlx5_dev_list_trylock(void);
-int mlx5_packet_reformat_alloc(struct mlx5_core_dev *dev,
-			       int reformat_type,
-			       size_t size,
-			       void *reformat_data,
-			       int namespace,
-			       u32 *packet_reformat_id);
-void mlx5_packet_reformat_dealloc(struct mlx5_core_dev *dev,
-				  u32 packet_reformat_id);
 
 bool mlx5_lag_intf_add(struct mlx5_interface *intf, struct mlx5_priv *priv);
 
include/linux/mlx5/fs.h +9 -0
index 3bd5ad3fa28a..1068bc8ce7fa 100644
@@ -203,4 +203,13 @@ int mlx5_modify_header_alloc(struct mlx5_core_dev *dev,
 void mlx5_modify_header_dealloc(struct mlx5_core_dev *dev,
 				u32 modify_header_id);
 
+int mlx5_packet_reformat_alloc(struct mlx5_core_dev *dev,
+			       int reformat_type,
+			       size_t size,
+			       void *reformat_data,
+			       int namespace,
+			       u32 *packet_reformat_id);
+void mlx5_packet_reformat_dealloc(struct mlx5_core_dev *dev,
+				  u32 packet_reformat_id);
+
 #endif
Signature · 1 line
2.14.4
#11 lore raw

PATCH 11/27 RDMA/mlx5: Add NIC TX steering support

In reply to Leon Romanovsky

From: Mark Bloch <[email protected]>

Add support for proper NIC TX (egress) steering with multiple priorities. We expose the same number of priorities as the bypass (NIC RX) steering.

---
 drivers/infiniband/hw/mlx5/main.c    | 28 ++++++++++++++++++----------
 drivers/infiniband/hw/mlx5/mlx5_ib.h |  1 +
 2 files changed, 19 insertions(+), 10 deletions(-)
drivers/infiniband/hw/mlx5/main.c +18 -10
index 9011187ca081..b3281e408d2a 100644
@@ -2883,7 +2883,7 @@ is_valid_esp_aes_gcm(struct mlx5_core_dev *mdev,
 	 * rules would be supported, always return VALID_SPEC_NA.
 	 */
 	if (!is_crypto)
-		return egress ? VALID_SPEC_INVALID : VALID_SPEC_NA;
+		return VALID_SPEC_NA;
 
 	return is_crypto && is_ipsec &&
 		(!egress || (!is_drop && !flow_act->has_flow_tag)) ?
@@ -3058,21 +3058,26 @@ static struct mlx5_ib_flow_prio *get_flow_table(struct mlx5_ib_dev *dev,
 	max_table_size = BIT(MLX5_CAP_FLOWTABLE_NIC_RX(dev->mdev,
 						       log_max_ft_size));
 	if (flow_attr->type == IB_FLOW_ATTR_NORMAL) {
-		if (ft_type == MLX5_IB_FT_TX)
-			priority = 0;
-		else if (flow_is_multicast_only(flow_attr) &&
-			 !dont_trap)
+		enum mlx5_flow_namespace_type fn_type;
+
+		if (flow_is_multicast_only(flow_attr) &&
+		    !dont_trap)
 			priority = MLX5_IB_FLOW_MCAST_PRIO;
 		else
 			priority = ib_prio_to_core_prio(flow_attr->priority,
 							dont_trap);
-		ns = mlx5_get_flow_namespace(dev->mdev,
-					     ft_type == MLX5_IB_FT_TX ?
-					     MLX5_FLOW_NAMESPACE_EGRESS :
-					     MLX5_FLOW_NAMESPACE_BYPASS);
+		if (ft_type == MLX5_IB_FT_RX) {
+			fn_type = MLX5_FLOW_NAMESPACE_BYPASS;
+			prio = &dev->flow_db->prios[priority];
+		} else {
+			max_table_size = BIT(MLX5_CAP_FLOWTABLE_NIC_TX(dev->mdev,
+								       log_max_ft_size));
+			fn_type = MLX5_FLOW_NAMESPACE_EGRESS;
+			prio = &dev->flow_db->egress_prios[priority];
+		}
+		ns = mlx5_get_flow_namespace(dev->mdev, fn_type);
 		num_entries = MLX5_FS_MAX_ENTRIES;
 		num_groups = MLX5_FS_MAX_TYPES;
-		prio = &dev->flow_db->prios[priority];
 	} else if (flow_attr->type == IB_FLOW_ATTR_ALL_DEFAULT ||
 		   flow_attr->type == IB_FLOW_ATTR_MC_DEFAULT) {
 		ns = mlx5_get_flow_namespace(dev->mdev,
@@ -3271,6 +3276,9 @@ static struct mlx5_ib_flow_handler *_create_flow_rule(struct mlx5_ib_dev *dev,
 	if (!is_valid_attr(dev->mdev, flow_attr))
 		return ERR_PTR(-EINVAL);
 
+	if (dev->rep && is_egress)
+		return ERR_PTR(-EINVAL);
+
 	spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
 	handler = kzalloc(sizeof(*handler), GFP_KERNEL);
 	if (!handler || !spec) {
drivers/infiniband/hw/mlx5/mlx5_ib.h +1 -0
index 462505c8fa25..01bef4c2d396 100644
@@ -188,6 +188,7 @@ struct mlx5_ib_flow_matcher {
 
 struct mlx5_ib_flow_db {
 	struct mlx5_ib_flow_prio	prios[MLX5_IB_NUM_FLOW_FT];
+	struct mlx5_ib_flow_prio	egress_prios[MLX5_IB_NUM_FLOW_FT];
 	struct mlx5_ib_flow_prio	sniffer[MLX5_IB_NUM_SNIFFER_FTS];
 	struct mlx5_ib_flow_prio	egress[MLX5_IB_NUM_EGRESS_FTS];
 	struct mlx5_flow_table		*lag_demux_ft;
Signature · 1 line
2.14.4
#12 lore raw

PATCH 12/27 RDMA/uverbs: Add UVERBS_ATTR_CONST_IN to the specs language

In reply to Leon Romanovsky

From: Mark Bloch <[email protected]>

This makes it clear and safe to access constants past in from user space. We define a consistent ABI of u64 for all constants, and verify that the data passed in can be represented by the type the user supplies.

The expectation is this will always be used with an enum declaring the constant values, and the user will use the enum type as input to the accessor.

---
 drivers/infiniband/core/uverbs_ioctl.c | 21 +++++++++++++++++++++
 include/rdma/uverbs_ioctl.h            | 30 ++++++++++++++++++++++++++++++
 2 files changed, 51 insertions(+)
drivers/infiniband/core/uverbs_ioctl.c +21 -0
index 23a1777f26e2..3ad3b69e32ab 100644
@@ -537,3 +537,24 @@ int uverbs_get_flags32(u32 *to, const struct uverbs_attr_bundle *attrs_bundle,
 	return 0;
 }
 EXPORT_SYMBOL(uverbs_get_flags32);
+
+int _uverbs_get_const(s64 *to, const struct uverbs_attr_bundle *attrs_bundle,
+		      size_t idx, s64 lower_bound, u64 upper_bound)
+
+{
+	const struct uverbs_attr *attr;
+
+	attr = uverbs_attr_get(attrs_bundle, idx);
+	if (IS_ERR(attr))
+		return PTR_ERR(attr);
+
+	WARN_ON(attr->ptr_attr.len != 8);
+
+	*to = attr->ptr_attr.data;
+
+	if (*to < lower_bound || *to > upper_bound)
+		return -EINVAL;
+
+	return 0;
+}
+EXPORT_SYMBOL(_uverbs_get_const);
include/rdma/uverbs_ioctl.h +30 -0
index 19b421d2d82a..f703c8ebbb02 100644
@@ -268,6 +268,15 @@ struct uverbs_object_tree_def {
 			  __VA_ARGS__ },                                       \
 	})
 
+/* An input value that is a member in the enum _enum_type. */
+#define UVERBS_ATTR_CONST_IN(_attr_id, _enum_type, ...)                        \
+	UVERBS_ATTR_PTR_IN(                                                    \
+		_attr_id,                                                      \
+		UVERBS_ATTR_SIZE(sizeof(u64) + BUILD_BUG_ON_ZERO(              \
+						!sizeof(_enum_type)),          \
+				 sizeof(u64)),                                 \
+		__VA_ARGS__)
+
 /*
  * An input value that is a bitwise combination of values of _enum_type.
  * This permits the flag value to be passed as either a u32 or u64, it must
@@ -536,6 +545,27 @@ int uverbs_get_flags64(u64 *to, const struct uverbs_attr_bundle *attrs_bundle,
 		       size_t idx, u64 allowed_bits);
 int uverbs_get_flags32(u32 *to, const struct uverbs_attr_bundle *attrs_bundle,
 		       size_t idx, u64 allowed_bits);
+#if IS_ENABLED(CONFIG_INFINIBAND_USER_ACCESS)
+int _uverbs_get_const(s64 *to, const struct uverbs_attr_bundle *attrs_bundle,
+		      size_t idx, s64 lower_bound, u64 upper_bound);
+#else
+static inline int
+_uverbs_get_const(s64 *to, const struct uverbs_attr_bundle *attrs_bundle,
+		  size_t idx, s64 lower_bound, u64 upper_bound)
+{
+	return -EINVAL;
+}
+#endif
+
+#define uverbs_get_const(_to, _attrs_bundle, _idx)                             \
+	({                                                                     \
+		s64 _val;                                                      \
+		int _ret = _uverbs_get_const(&_val, _attrs_bundle, _idx,       \
+					     type_min(typeof(*_to)),           \
+					     type_max(typeof(*_to)));          \
+		(*_to) = _val;                                                 \
+		_ret;                                                          \
+	})
 
 /* =================================================
  *	 Definitions -> Specs infrastructure
Signature · 1 line
2.14.4
#13 lore raw

PATCH 13/27 RDMA/mlx5: Add a new flow action verb, modify header

In reply to Leon Romanovsky

From: Mark Bloch <[email protected]>

Expose the ability to create a flow action which mutates packet headers. The data passed from userspace should be modify header actions as defined by Mellanox's PRM.

---
 drivers/infiniband/hw/mlx5/flow.c         | 128 ++++++++++++++++++++++++++++++
 drivers/infiniband/hw/mlx5/main.c         |   5 +-
 drivers/infiniband/hw/mlx5/mlx5_ib.h      |  15 ++++
 include/uapi/rdma/mlx5_user_ioctl_cmds.h  |  10 +++
 include/uapi/rdma/mlx5_user_ioctl_verbs.h |   5 ++
 5 files changed, 162 insertions(+), 1 deletion(-)
drivers/infiniband/hw/mlx5/flow.c +128 -0
index ee398a9b5f26..2c7d75cb8ade 100644
@@ -8,6 +8,7 @@
 #include <rdma/uverbs_types.h>
 #include <rdma/uverbs_ioctl.h>
 #include <rdma/mlx5_user_ioctl_cmds.h>
+#include <rdma/mlx5_user_ioctl_verbs.h>
 #include <rdma/ib_umem.h>
 #include <linux/mlx5/driver.h>
 #include <linux/mlx5/fs.h>
@@ -177,6 +178,114 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_FLOW_MATCHER_CREATE)(
 	return err;
 }
 
+static int mlx5_ib_ft_type_to_namespace(u8 table_type, u8 *namespace)
+{
+	switch (table_type) {
+	case MLX5_IB_UAPI_FLOW_TABLE_TYPE_NIC_RX:
+		*namespace = MLX5_FLOW_NAMESPACE_BYPASS;
+		break;
+	case MLX5_IB_UAPI_FLOW_TABLE_TYPE_NIC_TX:
+		*namespace = MLX5_FLOW_NAMESPACE_EGRESS;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+void mlx5_ib_destroy_flow_action_raw(struct mlx5_ib_flow_action *maction)
+{
+	switch (maction->flow_action_raw.sub_type) {
+	case MLX5_IB_FLOW_ACTION_MODIFY_HEADER:
+		mlx5_modify_header_dealloc(maction->flow_action_raw.dev->mdev,
+					   maction->flow_action_raw.action_id);
+		break;
+	default:
+		WARN_ON(true);
+		break;
+	}
+}
+
+static struct ib_flow_action *
+mlx5_ib_create_modify_header(struct mlx5_ib_dev *dev, u8 ft_type,
+			     u8 num_actions, void *in)
+{
+	struct mlx5_ib_flow_action *maction;
+	u8 namespace;
+	int ret;
+
+	ret = mlx5_ib_ft_type_to_namespace(ft_type, &namespace);
+	if (ret)
+		return ERR_PTR(-EINVAL);
+
+	maction = kzalloc(sizeof(*maction), GFP_KERNEL);
+	if (!maction)
+		return ERR_PTR(-ENOMEM);
+
+	ret = mlx5_modify_header_alloc(dev->mdev, namespace, num_actions, in,
+				       &maction->flow_action_raw.action_id);
+
+	if (ret) {
+		kfree(maction);
+		return ERR_PTR(ret);
+	}
+	maction->flow_action_raw.sub_type =
+		MLX5_IB_FLOW_ACTION_MODIFY_HEADER;
+	maction->flow_action_raw.dev = dev;
+
+	return &maction->ib_action;
+}
+
+static bool mlx5_ib_modify_header_supported(struct mlx5_ib_dev *dev)
+{
+	return MLX5_CAP_FLOWTABLE_NIC_RX(dev->mdev, max_modify_header_actions) ||
+	       MLX5_CAP_FLOWTABLE_NIC_TX(dev->mdev, max_modify_header_actions);
+}
+
+static int UVERBS_HANDLER(MLX5_IB_METHOD_FLOW_ACTION_CREATE_MODIFY_HEADER)(struct ib_device *ib_dev,
+									   struct ib_uverbs_file *file,
+									   struct uverbs_attr_bundle *attrs)
+{
+	struct ib_uobject *uobj = uverbs_attr_get_uobject(attrs,
+					MLX5_IB_ATTR_CREATE_MODIFY_HEADER_HANDLE);
+	struct mlx5_ib_dev *mdev = to_mdev(uobj->context->device);
+	enum mlx5_ib_uapi_flow_table_type ft_type;
+	struct ib_flow_action *action;
+	void *in;
+	int len;
+	int ret;
+
+	if (!mlx5_ib_modify_header_supported(mdev))
+		return -EOPNOTSUPP;
+
+	in = uverbs_attr_get_alloced_ptr(attrs,
+					 MLX5_IB_ATTR_CREATE_MODIFY_HEADER_ACTIONS_PRM);
+	len = uverbs_attr_get_len(attrs, MLX5_IB_ATTR_CREATE_MODIFY_HEADER_ACTIONS_PRM);
+
+	if (len % MLX5_UN_SZ_BYTES(set_action_in_add_action_in_auto))
+		return -EINVAL;
+
+	ret = uverbs_get_const(&ft_type, attrs,
+			       MLX5_IB_ATTR_CREATE_MODIFY_HEADER_FT_TYPE);
+	if (ret)
+		return -EINVAL;
+
+	action = mlx5_ib_create_modify_header(mdev, ft_type,
+					      len / MLX5_UN_SZ_BYTES(set_action_in_add_action_in_auto),
+					      in);
+	if (IS_ERR(action))
+		return PTR_ERR(action);
+
+	atomic_set(&action->usecnt, 0);
+	action->device = uobj->context->device;
+	action->type = IB_FLOW_ACTION_UNSPECIFIED;
+	action->uobject = uobj;
+	uobj->object = action;
+
+	return 0;
+}
+
 DECLARE_UVERBS_NAMED_METHOD(
 	MLX5_IB_METHOD_CREATE_FLOW,
 	UVERBS_ATTR_IDR(MLX5_IB_ATTR_CREATE_FLOW_HANDLE,
@@ -211,6 +320,24 @@ ADD_UVERBS_METHODS(mlx5_ib_fs,
 		   &UVERBS_METHOD(MLX5_IB_METHOD_CREATE_FLOW),
 		   &UVERBS_METHOD(MLX5_IB_METHOD_DESTROY_FLOW));
 
+DECLARE_UVERBS_NAMED_METHOD(
+	MLX5_IB_METHOD_FLOW_ACTION_CREATE_MODIFY_HEADER,
+	UVERBS_ATTR_IDR(MLX5_IB_ATTR_CREATE_MODIFY_HEADER_HANDLE,
+			UVERBS_OBJECT_FLOW_ACTION,
+			UVERBS_ACCESS_NEW,
+			UA_MANDATORY),
+	UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_CREATE_MODIFY_HEADER_ACTIONS_PRM,
+			   UVERBS_ATTR_MIN_SIZE(MLX5_UN_SZ_BYTES(set_action_in_add_action_in_auto)),
+			   UA_MANDATORY,
+			   UA_ALLOC_AND_COPY),
+	UVERBS_ATTR_CONST_IN(MLX5_IB_ATTR_CREATE_MODIFY_HEADER_FT_TYPE,
+			     enum mlx5_ib_uapi_flow_table_type,
+			     UA_MANDATORY));
+
+ADD_UVERBS_METHODS(mlx5_ib_flow_actions,
+		   UVERBS_OBJECT_FLOW_ACTION,
+		   &UVERBS_METHOD(MLX5_IB_METHOD_FLOW_ACTION_CREATE_MODIFY_HEADER));
+
 DECLARE_UVERBS_NAMED_METHOD(
 	MLX5_IB_METHOD_FLOW_MATCHER_CREATE,
 	UVERBS_ATTR_IDR(MLX5_IB_ATTR_FLOW_MATCHER_CREATE_HANDLE,
@@ -249,6 +376,7 @@ int mlx5_ib_get_flow_trees(const struct uverbs_object_tree_def **root)
 
 	root[i++] = &flow_objects;
 	root[i++] = &mlx5_ib_fs;
+	root[i++] = &mlx5_ib_flow_actions;
 
 	return i;
 }
drivers/infiniband/hw/mlx5/main.c +4 -1
index b3281e408d2a..b56ac6614be6 100644
@@ -3997,6 +3997,9 @@ static int mlx5_ib_destroy_flow_action(struct ib_flow_action *action)
 		 */
 		mlx5_accel_esp_destroy_xfrm(maction->esp_aes_gcm.ctx);
 		break;
+	case IB_FLOW_ACTION_UNSPECIFIED:
+		mlx5_ib_destroy_flow_action_raw(maction);
+		break;
 	default:
 		WARN_ON(true);
 		break;
@@ -5533,7 +5536,7 @@ ADD_UVERBS_ATTRIBUTES_SIMPLE(
 	UVERBS_ATTR_FLAGS_IN(MLX5_IB_ATTR_CREATE_FLOW_ACTION_FLAGS,
 			     enum mlx5_ib_uapi_flow_action_flags));
 
-#define NUM_TREES	5
+#define NUM_TREES	6
 static int populate_specs_root(struct mlx5_ib_dev *dev)
 {
 	const struct uverbs_object_tree_def *default_root[NUM_TREES + 1] = {
drivers/infiniband/hw/mlx5/mlx5_ib.h +15 -0
index 01bef4c2d396..b5dd68114588 100644
@@ -151,6 +151,10 @@ struct mlx5_ib_pd {
 	u32			pdn;
 };
 
+enum {
+	MLX5_IB_FLOW_ACTION_MODIFY_HEADER,
+};
+
 #define MLX5_IB_FLOW_MCAST_PRIO		(MLX5_BY_PASS_NUM_PRIOS - 1)
 #define MLX5_IB_FLOW_LAST_PRIO		(MLX5_BY_PASS_NUM_REGULAR_PRIOS - 1)
 #if (MLX5_IB_FLOW_LAST_PRIO <= 0)
@@ -815,6 +819,11 @@ struct mlx5_ib_flow_action {
 			u64			    ib_flags;
 			struct mlx5_accel_esp_xfrm *ctx;
 		} esp_aes_gcm;
+		struct {
+			struct mlx5_ib_dev *dev;
+			u32 sub_type;
+			u32 action_id;
+		} flow_action_raw;
 	};
 };
 
@@ -1238,6 +1247,7 @@ struct mlx5_ib_flow_handler *mlx5_ib_raw_fs_rule_add(
 	void *cmd_in, int inlen, int dest_id, int dest_type);
 bool mlx5_ib_devx_is_flow_dest(void *obj, int *dest_id, int *dest_type);
 int mlx5_ib_get_flow_trees(const struct uverbs_object_tree_def **root);
+void mlx5_ib_destroy_flow_action_raw(struct mlx5_ib_flow_action *maction);
 #else
 static inline int
 mlx5_ib_devx_create(struct mlx5_ib_dev *dev,
@@ -1256,6 +1266,11 @@ mlx5_ib_get_flow_trees(const struct uverbs_object_tree_def **root)
 {
 	return 0;
 }
+static inline void
+mlx5_ib_destroy_flow_action_raw(struct mlx5_ib_flow_action *maction)
+{
+	return;
+};
 #endif
 static inline void init_query_mad(struct ib_smp *mad)
 {
include/uapi/rdma/mlx5_user_ioctl_cmds.h +10 -0
index 9c51801b9e64..9c83e13c0e89 100644
@@ -166,4 +166,14 @@ enum mlx5_ib_flow_methods {
 	MLX5_IB_METHOD_DESTROY_FLOW,
 };
 
+enum mlx5_ib_flow_action_methods {
+	MLX5_IB_METHOD_FLOW_ACTION_CREATE_MODIFY_HEADER = (1U << UVERBS_ID_NS_SHIFT),
+};
+
+enum mlx5_ib_create_flow_action_create_modify_header_attrs {
+	MLX5_IB_ATTR_CREATE_MODIFY_HEADER_HANDLE = (1U << UVERBS_ID_NS_SHIFT),
+	MLX5_IB_ATTR_CREATE_MODIFY_HEADER_ACTIONS_PRM,
+	MLX5_IB_ATTR_CREATE_MODIFY_HEADER_FT_TYPE,
+};
+
 #endif
include/uapi/rdma/mlx5_user_ioctl_verbs.h +5 -0
index 8a2fb33f3ed4..ceb6d0d8529a 100644
@@ -39,5 +39,10 @@ enum mlx5_ib_uapi_flow_action_flags {
 	MLX5_IB_UAPI_FLOW_ACTION_FLAGS_REQUIRE_METADATA	= 1 << 0,
 };
 
+enum mlx5_ib_uapi_flow_table_type {
+	MLX5_IB_UAPI_FLOW_TABLE_TYPE_NIC_RX     = 0x0,
+	MLX5_IB_UAPI_FLOW_TABLE_TYPE_NIC_TX	= 0x1,
+};
+
 #endif
 
Signature · 1 line
2.14.4
#14 lore raw

PATCH 14/27 RDMA/mlx5: Enable attaching modify header to steering flows

In reply to Leon Romanovsky

From: Mark Bloch <[email protected]>

When creating a flow steering rule, allow the user to attach a modify header action.

---
 drivers/infiniband/hw/mlx5/main.c | 8 ++++++++
 1 file changed, 8 insertions(+)
drivers/infiniband/hw/mlx5/main.c +8 -0
index b56ac6614be6..473c8e5d21a5 100644
@@ -2466,6 +2466,14 @@ static int parse_flow_flow_action(const union ib_flow_spec *ib_spec,
 			MLX5_FLOW_CONTEXT_ACTION_ENCRYPT :
 			MLX5_FLOW_CONTEXT_ACTION_DECRYPT;
 		return 0;
+	case IB_FLOW_ACTION_UNSPECIFIED:
+		if (maction->flow_action_raw.sub_type ==
+		    MLX5_IB_FLOW_ACTION_MODIFY_HEADER) {
+			action->action |= MLX5_FLOW_CONTEXT_ACTION_MOD_HDR;
+			action->modify_id = maction->flow_action_raw.action_id;
+			return 0;
+		}
+		/* fall through */
 	default:
 		return -EOPNOTSUPP;
 	}
Signature · 1 line
2.14.4
#15 lore raw

PATCH 15/27 RDMA/mlx5: Enable decap and packet reformat on flow tables

In reply to Leon Romanovsky

From: Mark Bloch <[email protected]>

If NIC RX flow tables support decap operation, enable it on creation. If NIC TX flow tables support reformat operation, enable it on creation.

---
 drivers/infiniband/hw/mlx5/main.c | 17 +++++++++++++----
 1 file changed, 13 insertions(+), 4 deletions(-)
drivers/infiniband/hw/mlx5/main.c +13 -4
index 473c8e5d21a5..d826d7b21c2e 100644
@@ -3034,14 +3034,15 @@ enum flow_table_type {
 static struct mlx5_ib_flow_prio *_get_prio(struct mlx5_flow_namespace *ns,
 					   struct mlx5_ib_flow_prio *prio,
 					   int priority,
-					   int num_entries, int num_groups)
+					   int num_entries, int num_groups,
+					   u32 flags)
 {
 	struct mlx5_flow_table *ft;
 
 	ft = mlx5_create_auto_grouped_flow_table(ns, priority,
 						 num_entries,
 						 num_groups,
-						 0, 0);
+						 0, flags);
 	if (IS_ERR(ft))
 		return ERR_CAST(ft);
 
@@ -3061,6 +3062,7 @@ static struct mlx5_ib_flow_prio *get_flow_table(struct mlx5_ib_dev *dev,
 	int max_table_size;
 	int num_entries;
 	int num_groups;
+	u32 flags = 0;
 	int priority;
 
 	max_table_size = BIT(MLX5_CAP_FLOWTABLE_NIC_RX(dev->mdev,
@@ -3077,11 +3079,17 @@ static struct mlx5_ib_flow_prio *get_flow_table(struct mlx5_ib_dev *dev,
 		if (ft_type == MLX5_IB_FT_RX) {
 			fn_type = MLX5_FLOW_NAMESPACE_BYPASS;
 			prio = &dev->flow_db->prios[priority];
+			if (!dev->rep &&
+			    MLX5_CAP_FLOWTABLE_NIC_RX(dev->mdev, decap))
+				flags |= MLX5_FLOW_TABLE_TUNNEL_EN_DECAP;
 		} else {
 			max_table_size = BIT(MLX5_CAP_FLOWTABLE_NIC_TX(dev->mdev,
 								       log_max_ft_size));
 			fn_type = MLX5_FLOW_NAMESPACE_EGRESS;
 			prio = &dev->flow_db->egress_prios[priority];
+			if (!dev->rep && MLX5_CAP_FLOWTABLE_NIC_TX(dev->mdev,
+								   reformat))
+				flags |= MLX5_FLOW_TABLE_TUNNEL_EN_REFORMAT;
 		}
 		ns = mlx5_get_flow_namespace(dev->mdev, fn_type);
 		num_entries = MLX5_FS_MAX_ENTRIES;
@@ -3117,7 +3125,8 @@ static struct mlx5_ib_flow_prio *get_flow_table(struct mlx5_ib_dev *dev,
 
 	ft = prio->flow_table;
 	if (!ft)
-		return _get_prio(ns, prio, priority, num_entries, num_groups);
+		return _get_prio(ns, prio, priority, num_entries, num_groups,
+				 flags);
 
 	return prio;
 }
@@ -3695,7 +3704,7 @@ static struct mlx5_ib_flow_prio *_get_flow_table(struct mlx5_ib_dev *dev,
 		return prio;
 
 	return _get_prio(ns, prio, priority, MLX5_FS_MAX_ENTRIES,
-			 MLX5_FS_MAX_TYPES);
+			 MLX5_FS_MAX_TYPES, 0);
 }
 
 static struct mlx5_ib_flow_handler *
Signature · 1 line
2.14.4
#16 lore raw

PATCH 16/27 RDMA/uverbs: Add generic function to fill in flow action object

In reply to Leon Romanovsky

From: Mark Bloch <[email protected]>

Refactor the initialization of a flow action object to a common function.

---
 drivers/infiniband/core/uverbs_std_types_flow_action.c |  7 ++-----
 drivers/infiniband/hw/mlx5/flow.c                      |  8 +++-----
 include/rdma/uverbs_std_types.h                        | 12 ++++++++++++
 3 files changed, 17 insertions(+), 10 deletions(-)
drivers/infiniband/core/uverbs_std_types_flow_action.c +2 -5
index adb9209c4710..8beacfdb9f27 100644
@@ -327,11 +327,8 @@ static int UVERBS_HANDLER(UVERBS_METHOD_FLOW_ACTION_ESP_CREATE)(struct ib_device
 	if (IS_ERR(action))
 		return PTR_ERR(action);
 
-	atomic_set(&action->usecnt, 0);
-	action->device = ib_dev;
-	action->type = IB_FLOW_ACTION_ESP;
-	action->uobject = uobj;
-	uobj->object = action;
+	uverbs_flow_action_fill_action(action, uobj, ib_dev,
+				       IB_FLOW_ACTION_ESP);
 
 	return 0;
 }
drivers/infiniband/hw/mlx5/flow.c +3 -5
index 2c7d75cb8ade..d0325e468801 100644
@@ -7,6 +7,7 @@
 #include <rdma/ib_verbs.h>
 #include <rdma/uverbs_types.h>
 #include <rdma/uverbs_ioctl.h>
+#include <rdma/uverbs_std_types.h>
 #include <rdma/mlx5_user_ioctl_cmds.h>
 #include <rdma/mlx5_user_ioctl_verbs.h>
 #include <rdma/ib_umem.h>
@@ -277,11 +278,8 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_FLOW_ACTION_CREATE_MODIFY_HEADER)(struc
 	if (IS_ERR(action))
 		return PTR_ERR(action);
 
-	atomic_set(&action->usecnt, 0);
-	action->device = uobj->context->device;
-	action->type = IB_FLOW_ACTION_UNSPECIFIED;
-	action->uobject = uobj;
-	uobj->object = action;
+	uverbs_flow_action_fill_action(action, uobj, uobj->context->device,
+				       IB_FLOW_ACTION_UNSPECIFIED);
 
 	return 0;
 }
include/rdma/uverbs_std_types.h +12 -0
index 076f085d2dcf..3686da497cf6 100644
@@ -125,5 +125,17 @@ static inline struct ib_uobject *__uobj_alloc(const struct uverbs_obj_type *type
 
 #define uobj_alloc(_type, _ufile) __uobj_alloc(uobj_get_type(_type), _ufile)
 
+static inline void uverbs_flow_action_fill_action(struct ib_flow_action *action,
+						  struct ib_uobject *uobj,
+						  struct ib_device *ib_dev,
+						  enum ib_flow_action_type type)
+{
+	atomic_set(&action->usecnt, 0);
+	action->device = ib_dev;
+	action->type = type;
+	action->uobject = uobj;
+	uobj->object = action;
+}
+
 #endif
 
Signature · 1 line
2.14.4
#17 lore raw

PATCH 17/27 RDMA/mlx5: Add new flow action verb, packet reformat

In reply to Leon Romanovsky

From: Mark Bloch <[email protected]>

For now, only add L2_TUNNEL_TO_L2 option, for example this can be used to decap VXLAN packets.

---
 drivers/infiniband/hw/mlx5/flow.c         | 76 ++++++++++++++++++++++++++++++-
 drivers/infiniband/hw/mlx5/mlx5_ib.h      |  1 +
 include/uapi/rdma/mlx5_user_ioctl_cmds.h  |  7 +++
 include/uapi/rdma/mlx5_user_ioctl_verbs.h |  4 ++
 4 files changed, 87 insertions(+), 1 deletion(-)
drivers/infiniband/hw/mlx5/flow.c +75 -1
index d0325e468801..0fea98cb7d42 100644
@@ -202,6 +202,8 @@ void mlx5_ib_destroy_flow_action_raw(struct mlx5_ib_flow_action *maction)
 		mlx5_modify_header_dealloc(maction->flow_action_raw.dev->mdev,
 					   maction->flow_action_raw.action_id);
 		break;
+	case MLX5_IB_FLOW_ACTION_DECAP:
+		break;
 	default:
 		WARN_ON(true);
 		break;
@@ -284,6 +286,64 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_FLOW_ACTION_CREATE_MODIFY_HEADER)(struc
 	return 0;
 }
 
+static bool mlx5_ib_flow_action_packet_reformat_valid(struct mlx5_ib_dev *ibdev,
+						      u8 packet_reformat_type,
+						      u8 ft_type)
+{
+	switch (packet_reformat_type) {
+	case MLX5_IB_UAPI_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TUNNEL_TO_L2:
+		if (ft_type == MLX5_IB_UAPI_FLOW_TABLE_TYPE_NIC_RX)
+			return MLX5_CAP_FLOWTABLE_NIC_RX(ibdev->mdev, decap);
+		break;
+	default:
+		break;
+	}
+
+	return false;
+}
+
+static int UVERBS_HANDLER(MLX5_IB_METHOD_FLOW_ACTION_CREATE_PACKET_REFORMAT)(struct ib_device *ib_dev,
+									     struct ib_uverbs_file *file,
+									     struct uverbs_attr_bundle *attrs)
+{
+	struct ib_uobject *uobj = uverbs_attr_get_uobject(attrs,
+				       MLX5_IB_ATTR_CREATE_PACKET_REFORMAT_HANDLE);
+	struct mlx5_ib_dev *mdev = to_mdev(uobj->context->device);
+	enum mlx5_ib_uapi_flow_action_packet_reformat_type dv_prt;
+	enum mlx5_ib_uapi_flow_table_type ft_type;
+	struct mlx5_ib_flow_action *maction;
+	int ret;
+
+	ret = uverbs_get_const(&ft_type, attrs,
+			       MLX5_IB_ATTR_CREATE_PACKET_REFORMAT_FT_TYPE);
+	if (ret)
+		return -EINVAL;
+
+	ret = uverbs_get_const(&dv_prt, attrs,
+			       MLX5_IB_ATTR_CREATE_PACKET_REFORMAT_TYPE);
+	if (ret)
+		return -EINVAL;
+
+	if (!mlx5_ib_flow_action_packet_reformat_valid(mdev, dv_prt, ft_type))
+		return -EOPNOTSUPP;
+
+	maction = kzalloc(sizeof(*maction), GFP_KERNEL);
+	if (!maction)
+		return -ENOMEM;
+
+	if (dv_prt ==
+	    MLX5_IB_UAPI_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TUNNEL_TO_L2) {
+		maction->flow_action_raw.sub_type =
+			MLX5_IB_FLOW_ACTION_DECAP;
+		maction->flow_action_raw.dev = mdev;
+	}
+
+	uverbs_flow_action_fill_action(&maction->ib_action, uobj,
+				       uobj->context->device,
+				       IB_FLOW_ACTION_UNSPECIFIED);
+	return 0;
+}
+
 DECLARE_UVERBS_NAMED_METHOD(
 	MLX5_IB_METHOD_CREATE_FLOW,
 	UVERBS_ATTR_IDR(MLX5_IB_ATTR_CREATE_FLOW_HANDLE,
@@ -332,9 +392,23 @@ DECLARE_UVERBS_NAMED_METHOD(
 			     enum mlx5_ib_uapi_flow_table_type,
 			     UA_MANDATORY));
 
+DECLARE_UVERBS_NAMED_METHOD(
+	MLX5_IB_METHOD_FLOW_ACTION_CREATE_PACKET_REFORMAT,
+	UVERBS_ATTR_IDR(MLX5_IB_ATTR_CREATE_PACKET_REFORMAT_HANDLE,
+			UVERBS_OBJECT_FLOW_ACTION,
+			UVERBS_ACCESS_NEW,
+			UA_MANDATORY),
+	UVERBS_ATTR_CONST_IN(MLX5_IB_ATTR_CREATE_PACKET_REFORMAT_TYPE,
+			     enum mlx5_ib_uapi_flow_action_packet_reformat_type,
+			     UA_MANDATORY),
+	UVERBS_ATTR_CONST_IN(MLX5_IB_ATTR_CREATE_PACKET_REFORMAT_FT_TYPE,
+			     enum mlx5_ib_uapi_flow_table_type,
+			     UA_MANDATORY));
+
 ADD_UVERBS_METHODS(mlx5_ib_flow_actions,
 		   UVERBS_OBJECT_FLOW_ACTION,
-		   &UVERBS_METHOD(MLX5_IB_METHOD_FLOW_ACTION_CREATE_MODIFY_HEADER));
+		   &UVERBS_METHOD(MLX5_IB_METHOD_FLOW_ACTION_CREATE_MODIFY_HEADER),
+		   &UVERBS_METHOD(MLX5_IB_METHOD_FLOW_ACTION_CREATE_PACKET_REFORMAT));
 
 DECLARE_UVERBS_NAMED_METHOD(
 	MLX5_IB_METHOD_FLOW_MATCHER_CREATE,
drivers/infiniband/hw/mlx5/mlx5_ib.h +1 -0
index b5dd68114588..856cb389c821 100644
@@ -153,6 +153,7 @@ struct mlx5_ib_pd {
 
 enum {
 	MLX5_IB_FLOW_ACTION_MODIFY_HEADER,
+	MLX5_IB_FLOW_ACTION_DECAP,
 };
 
 #define MLX5_IB_FLOW_MCAST_PRIO		(MLX5_BY_PASS_NUM_PRIOS - 1)
include/uapi/rdma/mlx5_user_ioctl_cmds.h +7 -0
index 9c83e13c0e89..40db7fca3d0b 100644
@@ -168,6 +168,7 @@ enum mlx5_ib_flow_methods {
 
 enum mlx5_ib_flow_action_methods {
 	MLX5_IB_METHOD_FLOW_ACTION_CREATE_MODIFY_HEADER = (1U << UVERBS_ID_NS_SHIFT),
+	MLX5_IB_METHOD_FLOW_ACTION_CREATE_PACKET_REFORMAT,
 };
 
 enum mlx5_ib_create_flow_action_create_modify_header_attrs {
@@ -176,4 +177,10 @@ enum mlx5_ib_create_flow_action_create_modify_header_attrs {
 	MLX5_IB_ATTR_CREATE_MODIFY_HEADER_FT_TYPE,
 };
 
+enum mlx5_ib_create_flow_action_create_packet_reformat_attrs {
+	MLX5_IB_ATTR_CREATE_PACKET_REFORMAT_HANDLE = (1U << UVERBS_ID_NS_SHIFT),
+	MLX5_IB_ATTR_CREATE_PACKET_REFORMAT_TYPE,
+	MLX5_IB_ATTR_CREATE_PACKET_REFORMAT_FT_TYPE,
+};
+
 #endif
include/uapi/rdma/mlx5_user_ioctl_verbs.h +4 -0
index ceb6d0d8529a..b5fda0fcd484 100644
@@ -44,5 +44,9 @@ enum mlx5_ib_uapi_flow_table_type {
 	MLX5_IB_UAPI_FLOW_TABLE_TYPE_NIC_TX	= 0x1,
 };
 
+enum mlx5_ib_uapi_flow_action_packet_reformat_type {
+	MLX5_IB_UAPI_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TUNNEL_TO_L2 = 0x0,
+};
+
 #endif
 
Signature · 1 line
2.14.4
#18 lore raw

PATCH 18/27 RDMA/mlx5: Enable attaching DECAP action to steering flows

In reply to Leon Romanovsky

From: Mark Bloch <[email protected]>

Any matching flow will be stripped of it's VXLAN tunnel, only the inner L2 onward is left.

---
 drivers/infiniband/hw/mlx5/main.c | 5 +++++
 1 file changed, 5 insertions(+)
drivers/infiniband/hw/mlx5/main.c +5 -0
index d826d7b21c2e..9c42a1059590 100644
@@ -2473,6 +2473,11 @@ static int parse_flow_flow_action(const union ib_flow_spec *ib_spec,
 			action->modify_id = maction->flow_action_raw.action_id;
 			return 0;
 		}
+		if (maction->flow_action_raw.sub_type ==
+		    MLX5_IB_FLOW_ACTION_DECAP) {
+			action->action |= MLX5_FLOW_CONTEXT_ACTION_DECAP;
+			return 0;
+		}
 		/* fall through */
 	default:
 		return -EOPNOTSUPP;
Signature · 1 line
2.14.4
#19 lore raw

PATCH 19/27 RDMA/mlx5: Extend packet reformat verbs

In reply to Leon Romanovsky

From: Mark Bloch <[email protected]>

We expose new actions:

L2_TO_L2_TUNNEL - A generic encap from L2 to L2, the data passed should be the encapsulating headers.

L3_TUNNEL_TO_L2 - Will do decap where the inner packet starts from L3, the data should be mac or mac + vlan (14 or 18 bytes).

L2_TO_L3_TUNNEL - Will do encap where is L2 of the original packet will not be included, the data should be the encapsulating header.

---
 drivers/infiniband/hw/mlx5/flow.c         | 95 +++++++++++++++++++++++++++++++
 drivers/infiniband/hw/mlx5/mlx5_ib.h      |  1 +
 include/uapi/rdma/mlx5_user_ioctl_cmds.h  |  1 +
 include/uapi/rdma/mlx5_user_ioctl_verbs.h |  3 +
 4 files changed, 100 insertions(+)
drivers/infiniband/hw/mlx5/flow.c +95 -0
index 0fea98cb7d42..a6b4f37a5359 100644
@@ -202,6 +202,10 @@ void mlx5_ib_destroy_flow_action_raw(struct mlx5_ib_flow_action *maction)
 		mlx5_modify_header_dealloc(maction->flow_action_raw.dev->mdev,
 					   maction->flow_action_raw.action_id);
 		break;
+	case MLX5_IB_FLOW_ACTION_PACKET_REFORMAT:
+		mlx5_packet_reformat_dealloc(maction->flow_action_raw.dev->mdev,
+					     maction->flow_action_raw.action_id);
+		break;
 	case MLX5_IB_FLOW_ACTION_DECAP:
 		break;
 	default:
@@ -291,6 +295,21 @@ static bool mlx5_ib_flow_action_packet_reformat_valid(struct mlx5_ib_dev *ibdev,
 						      u8 ft_type)
 {
 	switch (packet_reformat_type) {
+	case MLX5_IB_UAPI_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L2_TUNNEL:
+		if (ft_type == MLX5_IB_UAPI_FLOW_TABLE_TYPE_NIC_TX)
+			return MLX5_CAP_FLOWTABLE(ibdev->mdev,
+						  encap_general_header);
+		break;
+	case MLX5_IB_UAPI_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L3_TUNNEL:
+		if (ft_type == MLX5_IB_UAPI_FLOW_TABLE_TYPE_NIC_TX)
+			return MLX5_CAP_FLOWTABLE_NIC_TX(ibdev->mdev,
+							 reformat_l2_to_l3_tunnel);
+		break;
+	case MLX5_IB_UAPI_FLOW_ACTION_PACKET_REFORMAT_TYPE_L3_TUNNEL_TO_L2:
+		if (ft_type == MLX5_IB_UAPI_FLOW_TABLE_TYPE_NIC_RX)
+			return MLX5_CAP_FLOWTABLE_NIC_RX(ibdev->mdev,
+							 reformat_l3_tunnel_to_l2);
+		break;
 	case MLX5_IB_UAPI_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TUNNEL_TO_L2:
 		if (ft_type == MLX5_IB_UAPI_FLOW_TABLE_TYPE_NIC_RX)
 			return MLX5_CAP_FLOWTABLE_NIC_RX(ibdev->mdev, decap);
@@ -302,6 +321,55 @@ static bool mlx5_ib_flow_action_packet_reformat_valid(struct mlx5_ib_dev *ibdev,
 	return false;
 }
 
+static int mlx5_ib_dv_to_prm_packet_reforamt_type(u8 dv_prt, u8 *prm_prt)
+{
+	switch (dv_prt) {
+	case MLX5_IB_UAPI_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L2_TUNNEL:
+		*prm_prt = MLX5_REFORMAT_TYPE_L2_TO_L2_TUNNEL;
+		break;
+	case MLX5_IB_UAPI_FLOW_ACTION_PACKET_REFORMAT_TYPE_L3_TUNNEL_TO_L2:
+		*prm_prt = MLX5_REFORMAT_TYPE_L3_TUNNEL_TO_L2;
+		break;
+	case MLX5_IB_UAPI_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L3_TUNNEL:
+		*prm_prt = MLX5_REFORMAT_TYPE_L2_TO_L3_TUNNEL;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int mlx5_ib_flow_action_create_packet_reformat_ctx(struct mlx5_ib_dev *dev,
+							  struct mlx5_ib_flow_action *maction,
+							  u8 ft_type, u8 dv_prt,
+							  void *in, size_t len)
+{
+	u8 namespace;
+	u8 prm_prt;
+	int ret;
+
+	ret = mlx5_ib_ft_type_to_namespace(ft_type, &namespace);
+	if (ret)
+		return ret;
+
+	ret = mlx5_ib_dv_to_prm_packet_reforamt_type(dv_prt, &prm_prt);
+	if (ret)
+		return ret;
+
+	ret = mlx5_packet_reformat_alloc(dev->mdev, prm_prt, len,
+					 in, namespace,
+					 &maction->flow_action_raw.action_id);
+	if (ret)
+		return ret;
+
+	maction->flow_action_raw.sub_type =
+		MLX5_IB_FLOW_ACTION_PACKET_REFORMAT;
+	maction->flow_action_raw.dev = dev;
+
+	return 0;
+}
+
 static int UVERBS_HANDLER(MLX5_IB_METHOD_FLOW_ACTION_CREATE_PACKET_REFORMAT)(struct ib_device *ib_dev,
 									     struct ib_uverbs_file *file,
 									     struct uverbs_attr_bundle *attrs)
@@ -336,12 +404,36 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_FLOW_ACTION_CREATE_PACKET_REFORMAT)(str
 		maction->flow_action_raw.sub_type =
 			MLX5_IB_FLOW_ACTION_DECAP;
 		maction->flow_action_raw.dev = mdev;
+	} else {
+		void *in;
+		int len;
+
+		in = uverbs_attr_get_alloced_ptr(attrs,
+						 MLX5_IB_ATTR_CREATE_PACKET_REFORMAT_DATA_BUF);
+		if (IS_ERR(in)) {
+			ret = PTR_ERR(in);
+			goto free_maction;
+		}
+
+		len = uverbs_attr_get_len(attrs,
+					  MLX5_IB_ATTR_CREATE_PACKET_REFORMAT_DATA_BUF);
+
+		ret = mlx5_ib_flow_action_create_packet_reformat_ctx(mdev, maction,
+								     ft_type,
+								     dv_prt, in,
+								     len);
+		if (ret)
+			goto free_maction;
 	}
 
 	uverbs_flow_action_fill_action(&maction->ib_action, uobj,
 				       uobj->context->device,
 				       IB_FLOW_ACTION_UNSPECIFIED);
 	return 0;
+
+free_maction:
+	kfree(maction);
+	return ret;
 }
 
 DECLARE_UVERBS_NAMED_METHOD(
@@ -398,6 +490,9 @@ DECLARE_UVERBS_NAMED_METHOD(
 			UVERBS_OBJECT_FLOW_ACTION,
 			UVERBS_ACCESS_NEW,
 			UA_MANDATORY),
+	UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_CREATE_PACKET_REFORMAT_DATA_BUF,
+			   UVERBS_ATTR_MIN_SIZE(1),
+			   UA_ALLOC_AND_COPY),
 	UVERBS_ATTR_CONST_IN(MLX5_IB_ATTR_CREATE_PACKET_REFORMAT_TYPE,
 			     enum mlx5_ib_uapi_flow_action_packet_reformat_type,
 			     UA_MANDATORY),
drivers/infiniband/hw/mlx5/mlx5_ib.h +1 -0
index 856cb389c821..bb7a902a347f 100644
@@ -153,6 +153,7 @@ struct mlx5_ib_pd {
 
 enum {
 	MLX5_IB_FLOW_ACTION_MODIFY_HEADER,
+	MLX5_IB_FLOW_ACTION_PACKET_REFORMAT,
 	MLX5_IB_FLOW_ACTION_DECAP,
 };
 
include/uapi/rdma/mlx5_user_ioctl_cmds.h +1 -0
index 40db7fca3d0b..75c7093fd95b 100644
@@ -181,6 +181,7 @@ enum mlx5_ib_create_flow_action_create_packet_reformat_attrs {
 	MLX5_IB_ATTR_CREATE_PACKET_REFORMAT_HANDLE = (1U << UVERBS_ID_NS_SHIFT),
 	MLX5_IB_ATTR_CREATE_PACKET_REFORMAT_TYPE,
 	MLX5_IB_ATTR_CREATE_PACKET_REFORMAT_FT_TYPE,
+	MLX5_IB_ATTR_CREATE_PACKET_REFORMAT_DATA_BUF,
 };
 
 #endif
include/uapi/rdma/mlx5_user_ioctl_verbs.h +3 -0
index b5fda0fcd484..4ef62c0e8452 100644
@@ -46,6 +46,9 @@ enum mlx5_ib_uapi_flow_table_type {
 
 enum mlx5_ib_uapi_flow_action_packet_reformat_type {
 	MLX5_IB_UAPI_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TUNNEL_TO_L2 = 0x0,
+	MLX5_IB_UAPI_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L2_TUNNEL = 0x1,
+	MLX5_IB_UAPI_FLOW_ACTION_PACKET_REFORMAT_TYPE_L3_TUNNEL_TO_L2 = 0x2,
+	MLX5_IB_UAPI_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L3_TUNNEL = 0x3,
 };
 
 #endif
Signature · 1 line
2.14.4
#20 lore raw

PATCH 20/27 RDMA/mlx5: Enable reformat on NIC RX if supported

In reply to Leon Romanovsky

From: Mark Bloch <[email protected]>

A L3_TUNNEL_TO_L2 decap flow action requires to enable the encap bit on the Flow table, enable it if supported. This will allow to attach those flow actions to NIC RX steering. We don't enable if running on a representor.

---
 drivers/infiniband/hw/mlx5/main.c | 4 ++++
 1 file changed, 4 insertions(+)
drivers/infiniband/hw/mlx5/main.c +4 -0
index 9c42a1059590..b1c7cf26e206 100644
@@ -3087,6 +3087,10 @@ static struct mlx5_ib_flow_prio *get_flow_table(struct mlx5_ib_dev *dev,
 			if (!dev->rep &&
 			    MLX5_CAP_FLOWTABLE_NIC_RX(dev->mdev, decap))
 				flags |= MLX5_FLOW_TABLE_TUNNEL_EN_DECAP;
+			if (!dev->rep &&
+			    MLX5_CAP_FLOWTABLE_NIC_RX(dev->mdev,
+						      reformat_l3_tunnel_to_l2))
+				flags |= MLX5_FLOW_TABLE_TUNNEL_EN_REFORMAT;
 		} else {
 			max_table_size = BIT(MLX5_CAP_FLOWTABLE_NIC_TX(dev->mdev,
 								       log_max_ft_size));
Signature · 1 line
2.14.4
#21 lore raw

PATCH 21/27 RDMA/mlx5: Enable attaching packet reformat action to steering flows

In reply to Leon Romanovsky

From: Mark Bloch <[email protected]>

Any matching rules will be mutated based on the packet reformat context which is attached to that given flow rule.

---
 drivers/infiniband/hw/mlx5/main.c | 7 +++++++
 1 file changed, 7 insertions(+)
drivers/infiniband/hw/mlx5/main.c +7 -0
index b1c7cf26e206..0af0bdc5804b 100644
@@ -2478,6 +2478,13 @@ static int parse_flow_flow_action(const union ib_flow_spec *ib_spec,
 			action->action |= MLX5_FLOW_CONTEXT_ACTION_DECAP;
 			return 0;
 		}
+		if (maction->flow_action_raw.sub_type ==
+		    MLX5_IB_FLOW_ACTION_PACKET_REFORMAT) {
+			action->action |=
+				MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT;
+			action->reformat_id = maction->flow_action_raw.action_id;
+			return 0;
+		}
 		/* fall through */
 	default:
 		return -EOPNOTSUPP;
Signature · 1 line
2.14.4
#22 lore raw

PATCH 22/27 IB/uverbs: Add IDRs array attribute type to ioctl() interface

In reply to Leon Romanovsky

From: Guy Levi <[email protected]>

Methods sometimes need to get a flexible set of idrs and not a strict set as can be achieved today by the conventional idr attribute. This is an idrs-array-like behavior.
Since this may be popular used, we add a new IDRS_ARRAY attribute to the generic uverbs ioctl layer.

This attribute is embedded in methods, like any other attributes we currently have. IDRS_ARRAY points to array of idrs of the same object type and same access rights (only write and read are supported). It is defined with minimum and maximum length to be enforced and can be defined as mandatory attribute.

---
 drivers/infiniband/core/uverbs_ioctl.c   | 94 +++++++++++++++++++++++++++++++-
 include/rdma/uverbs_ioctl.h              | 68 ++++++++++++++++++++++-
 include/uapi/rdma/rdma_user_ioctl_cmds.h |  2 +-
 3 files changed, 160 insertions(+), 4 deletions(-)
drivers/infiniband/core/uverbs_ioctl.c +92 -2
index 3ad3b69e32ab..ce40f97dbbf2 100644
@@ -46,6 +46,79 @@ static bool uverbs_is_attr_cleared(const struct ib_uverbs_attr *uattr,
 			   0, uattr->len - len);
 }
 
+static int uverbs_process_idrs_arr_attr(struct ib_uverbs_file *ufile,
+					struct uverbs_objs_arr_attr *attr,
+					const struct ib_uverbs_attr *uattr,
+					const struct uverbs_attr_spec *spec)
+{
+	const struct uverbs_object_spec *object;
+	int err;
+	int i = 0; /* Initialization for error flow */
+
+	if (!ufile->ucontext || uattr->attr_data.reserved)
+		return -EINVAL;
+
+	if (uattr->len % sizeof(u32))
+		return -EINVAL;
+
+	attr->len = uattr->len / sizeof(u32);
+
+	if (attr->len < spec->u2.objs_arr.min_len ||
+	    attr->len > spec->u2.objs_arr.max_len)
+		return -EINVAL;
+
+	attr->uobjects = kvmalloc_array(attr->len, sizeof(*attr->uobjects),
+					GFP_KERNEL);
+	if (!attr->uobjects)
+		return -ENOMEM;
+
+	/* Since idr is 4B and *uobjects is >= 4B, we can use
+	 * attr->uobjects to store idrs array and avoid additional memory
+	 * allocation. The idrs array is offset to the end of the uobjects
+	 * array so we will be able to read a 4B idr and replace with a
+	 * 8B pointer.
+	 */
+	if (uattr->len > sizeof(uattr->data)) {
+		err = copy_from_user((u8 *)attr->uobjects + uattr->len,
+				     u64_to_user_ptr(uattr->data),
+				     uattr->len);
+		if (err) {
+			err = -EFAULT;
+			goto err_objs_arr;
+		}
+	} else {
+		memcpy((u8 *)attr->uobjects + uattr->len, &uattr->data,
+		       uattr->len);
+	}
+
+	object = uverbs_get_object(ufile, spec->u2.objs_arr.obj_type);
+	if (!object) {
+		err = -EINVAL;
+		goto err_objs_arr;
+	}
+
+	for (i = 0; i < attr->len; i++) {
+		attr->uobjects[i] =
+			uverbs_get_uobject_from_file(object->type_attrs, ufile,
+						     spec->u2.objs_arr.access,
+						     ((u32 *)attr->uobjects)[attr->len + i]);
+		if (IS_ERR(attr->uobjects[i])) {
+			err = PTR_ERR(attr->uobjects[i]);
+			goto err_objs_arr;
+		}
+	}
+
+	return 0;
+
+err_objs_arr:
+	while (i > 0)
+		uverbs_finalize_object(attr->uobjects[--i],
+				       spec->u2.objs_arr.access, false);
+
+	kvfree(attr->uobjects);
+	return err;
+}
+
 static int uverbs_process_attr(struct ib_uverbs_file *ufile,
 			       const struct ib_uverbs_attr *uattr,
 			       u16 attr_id,
@@ -59,6 +132,7 @@ static int uverbs_process_attr(struct ib_uverbs_file *ufile,
 	const struct uverbs_object_spec *object;
 	struct uverbs_obj_attr *o_attr;
 	struct uverbs_attr *elements = attr_bundle_h->attrs;
+	int err;
 
 	if (attr_id >= attr_spec_bucket->num_attrs) {
 		if (uattr->flags & UVERBS_ATTR_F_MANDATORY)
@@ -176,6 +250,14 @@ static int uverbs_process_attr(struct ib_uverbs_file *ufile,
 		}
 
 		break;
+
+	case UVERBS_ATTR_TYPE_IDRS_ARRAY:
+		err = uverbs_process_idrs_arr_attr(ufile, &e->objs_arr_attr,
+						   uattr, spec);
+		if (err)
+			return err;
+
+		break;
 	default:
 		return -EOPNOTSUPP;
 	}
@@ -204,6 +286,7 @@ static int uverbs_finalize_attrs(struct uverbs_attr_bundle *attrs_bundle,
 		for (j = 0; j < curr_bundle->num_attrs; j++) {
 			struct uverbs_attr *attr;
 			const struct uverbs_attr_spec *spec;
+			int current_ret;
 
 			if (!uverbs_attr_is_valid_in_hash(curr_bundle, j))
 				continue;
@@ -213,8 +296,6 @@ static int uverbs_finalize_attrs(struct uverbs_attr_bundle *attrs_bundle,
 
 			if (spec->type == UVERBS_ATTR_TYPE_IDR ||
 			    spec->type == UVERBS_ATTR_TYPE_FD) {
-				int current_ret;
-
 				current_ret = uverbs_finalize_object(
 					attr->obj_attr.uobject,
 					spec->u.obj.access, commit);
@@ -224,6 +305,15 @@ static int uverbs_finalize_attrs(struct uverbs_attr_bundle *attrs_bundle,
 				   spec->alloc_and_copy &&
 				   !uverbs_attr_ptr_is_inline(attr)) {
 				kvfree(attr->ptr_attr.ptr);
+			} else if (spec->type == UVERBS_ATTR_TYPE_IDRS_ARRAY) {
+				for (i = 0; i < attr->objs_arr_attr.len; i++) {
+					current_ret =
+						uverbs_finalize_object(attr->objs_arr_attr.uobjects[i],
+								       spec->u2.objs_arr.access, commit);
+					if (!ret)
+						ret = current_ret;
+				}
+				kvfree(attr->objs_arr_attr.uobjects);
 			}
 		}
 	}
include/rdma/uverbs_ioctl.h +67 -1

110 lines not on this page · raw message

include/uapi/rdma/rdma_user_ioctl_cmds.h +1 -1
index 24800c6c1f32..95762b04a72d 100644
@@ -53,7 +53,7 @@ enum {
 
 struct ib_uverbs_attr {
 	__u16 attr_id;		/* command specific type attribute */
-	__u16 len;		/* only for pointers */
+	__u16 len;		/* only for pointers and IDRs array */
 	__u16 flags;		/* combination of UVERBS_ATTR_F_XXXX */
 	union {
 		struct {
Signature · 1 line
2.14.4
#23 lore raw

PATCH 23/27 RDMA/mlx5: Refactor flow action parsing to be more generic

In reply to Leon Romanovsky

From: Mark Bloch <[email protected]>

Make the parsing of flow actions more generic so it could be used by DEVX create flow.

---
 drivers/infiniband/hw/mlx5/main.c    | 13 +++++++------
 drivers/infiniband/hw/mlx5/mlx5_ib.h |  3 +++
 2 files changed, 10 insertions(+), 6 deletions(-)
drivers/infiniband/hw/mlx5/main.c +7 -6
index 0af0bdc5804b..81780beeb83c 100644
@@ -2452,17 +2452,16 @@ static int check_mpls_supp_fields(u32 field_support, const __be32 *set_mask)
 		   offsetof(typeof(filter), field) -\
 		   sizeof(filter.field))
 
-static int parse_flow_flow_action(const union ib_flow_spec *ib_spec,
-				  const struct ib_flow_attr *flow_attr,
-				  struct mlx5_flow_act *action)
+int parse_flow_flow_action(struct mlx5_ib_flow_action *maction,
+			   bool is_egress,
+			   struct mlx5_flow_act *action)
 {
-	struct mlx5_ib_flow_action *maction = to_mflow_act(ib_spec->action.act);
 
 	switch (maction->ib_action.type) {
 	case IB_FLOW_ACTION_ESP:
 		/* Currently only AES_GCM keymat is supported by the driver */
 		action->esp_id = (uintptr_t)maction->esp_aes_gcm.ctx;
-		action->action |= flow_attr->flags & IB_FLOW_ATTR_FLAGS_EGRESS ?
+		action->action |= is_egress ?
 			MLX5_FLOW_CONTEXT_ACTION_ENCRYPT :
 			MLX5_FLOW_CONTEXT_ACTION_DECRYPT;
 		return 0;
@@ -2822,7 +2821,9 @@ static int parse_flow_attr(struct mlx5_core_dev *mdev, u32 *match_c,
 		action->action |= MLX5_FLOW_CONTEXT_ACTION_DROP;
 		break;
 	case IB_FLOW_SPEC_ACTION_HANDLE:
-		ret = parse_flow_flow_action(ib_spec, flow_attr, action);
+		ret = parse_flow_flow_action(to_mflow_act(ib_spec->action.act),
+					     flow_attr->flags & IB_FLOW_ATTR_FLAGS_EGRESS,
+					     action);
 		if (ret)
 			return ret;
 		break;
drivers/infiniband/hw/mlx5/mlx5_ib.h +3 -0
index bb7a902a347f..97fa894deafc 100644
@@ -870,6 +870,9 @@ to_mcounters(struct ib_counters *ibcntrs)
 	return container_of(ibcntrs, struct mlx5_ib_mcounters, ibcntrs);
 }
 
+int parse_flow_flow_action(struct mlx5_ib_flow_action *maction,
+			   bool is_egress,
+			   struct mlx5_flow_act *action);
 struct mlx5_ib_dev {
 	struct ib_device		ib_dev;
 	struct mlx5_core_dev		*mdev;
Signature · 1 line
2.14.4
#24 lore raw

PATCH 24/27 RDMA/mlx5: Refactor DEVX flow creation

In reply to Leon Romanovsky

From: Mark Bloch <[email protected]>

Move struct mlx5_flow_act to be passed from the METHOD entry point, this will allow to add support for flow action for the DEVX path.

---
 drivers/infiniband/hw/mlx5/flow.c    |  4 +++-
 drivers/infiniband/hw/mlx5/main.c    | 12 +++++++-----
 drivers/infiniband/hw/mlx5/mlx5_ib.h |  4 +++-
 3 files changed, 13 insertions(+), 7 deletions(-)
drivers/infiniband/hw/mlx5/flow.c +3 -1
index a6b4f37a5359..072b8fc7e057 100644
@@ -44,6 +44,7 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_CREATE_FLOW)(
 	struct ib_device *ib_dev, struct ib_uverbs_file *file,
 	struct uverbs_attr_bundle *attrs)
 {
+	struct mlx5_flow_act flow_act = {.flow_tag = MLX5_FS_DEFAULT_FLOW_TAG};
 	struct mlx5_ib_flow_handler *flow_handler;
 	struct mlx5_ib_flow_matcher *fs_matcher;
 	void *devx_obj;
@@ -106,7 +107,8 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_CREATE_FLOW)(
 				    MLX5_IB_ATTR_CREATE_FLOW_MATCH_VALUE);
 	fs_matcher = uverbs_attr_get_obj(attrs,
 					 MLX5_IB_ATTR_CREATE_FLOW_MATCHER);
-	flow_handler = mlx5_ib_raw_fs_rule_add(dev, fs_matcher, cmd_in, inlen,
+	flow_handler = mlx5_ib_raw_fs_rule_add(dev, fs_matcher, &flow_act,
+					       cmd_in, inlen,
 					       dest_id, dest_type);
 	if (IS_ERR(flow_handler))
 		return PTR_ERR(flow_handler);
drivers/infiniband/hw/mlx5/main.c +7 -5
index 81780beeb83c..2b2af82dc32e 100644
@@ -3729,10 +3729,10 @@ _create_raw_flow_rule(struct mlx5_ib_dev *dev,
 		      struct mlx5_ib_flow_prio *ft_prio,
 		      struct mlx5_flow_destination *dst,
 		      struct mlx5_ib_flow_matcher  *fs_matcher,
+		      struct mlx5_flow_act *flow_act,
 		      void *cmd_in, int inlen)
 {
 	struct mlx5_ib_flow_handler *handler;
-	struct mlx5_flow_act flow_act = {.flow_tag = MLX5_FS_DEFAULT_FLOW_TAG};
 	struct mlx5_flow_spec *spec;
 	struct mlx5_flow_table *ft = ft_prio->flow_table;
 	int err = 0;
@@ -3751,9 +3751,8 @@ _create_raw_flow_rule(struct mlx5_ib_dev *dev,
 	       fs_matcher->mask_len);
 	spec->match_criteria_enable = fs_matcher->match_criteria_enable;
 
-	flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
 	handler->rule = mlx5_add_flow_rules(ft, spec,
-					    &flow_act, dst, 1);
+					    flow_act, dst, 1);
 
 	if (IS_ERR(handler->rule)) {
 		err = PTR_ERR(handler->rule);
@@ -3815,6 +3814,7 @@ static bool raw_fs_is_multicast(struct mlx5_ib_flow_matcher *fs_matcher,
 struct mlx5_ib_flow_handler *
 mlx5_ib_raw_fs_rule_add(struct mlx5_ib_dev *dev,
 			struct mlx5_ib_flow_matcher *fs_matcher,
+			struct mlx5_flow_act *flow_act,
 			void *cmd_in, int inlen, int dest_id,
 			int dest_type)
 {
@@ -3847,13 +3847,15 @@ mlx5_ib_raw_fs_rule_add(struct mlx5_ib_dev *dev,
 	if (dest_type == MLX5_FLOW_DESTINATION_TYPE_TIR) {
 		dst->type = dest_type;
 		dst->tir_num = dest_id;
+		flow_act->action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
 	} else {
 		dst->type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE_NUM;
 		dst->ft_num = dest_id;
+		flow_act->action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
 	}
 
-	handler = _create_raw_flow_rule(dev, ft_prio, dst, fs_matcher, cmd_in,
-					inlen);
+	handler = _create_raw_flow_rule(dev, ft_prio, dst, fs_matcher, flow_act,
+					cmd_in, inlen);
 
 	if (IS_ERR(handler)) {
 		err = PTR_ERR(handler);
drivers/infiniband/hw/mlx5/mlx5_ib.h +3 -1
index 97fa894deafc..76f1c178cef7 100644
@@ -39,6 +39,7 @@
 #include <rdma/ib_smi.h>
 #include <linux/mlx5/driver.h>
 #include <linux/mlx5/cq.h>
+#include <linux/mlx5/fs.h>
 #include <linux/mlx5/qp.h>
 #include <linux/mlx5/srq.h>
 #include <linux/types.h>
@@ -1249,7 +1250,8 @@ void mlx5_ib_devx_destroy(struct mlx5_ib_dev *dev,
 const struct uverbs_object_tree_def *mlx5_ib_get_devx_tree(void);
 struct mlx5_ib_flow_handler *mlx5_ib_raw_fs_rule_add(
 	struct mlx5_ib_dev *dev, struct mlx5_ib_flow_matcher *fs_matcher,
-	void *cmd_in, int inlen, int dest_id, int dest_type);
+	struct mlx5_flow_act *flow_act, void *cmd_in, int inlen,
+	int dest_id, int dest_type);
 bool mlx5_ib_devx_is_flow_dest(void *obj, int *dest_id, int *dest_type);
 int mlx5_ib_get_flow_trees(const struct uverbs_object_tree_def **root);
 void mlx5_ib_destroy_flow_action_raw(struct mlx5_ib_flow_action *maction);
Signature · 1 line
2.14.4
#25 lore raw

PATCH 25/27 RDMA/mlx5: Add flow actions support to DEVX create flow

In reply to Leon Romanovsky

From: Mark Bloch <[email protected]>

Support attaching flow actions to a flow rule via DEVX. For now only NIC RX path is supported.

---
 drivers/infiniband/hw/mlx5/flow.c        | 21 ++++++++++++++++++++-
 include/uapi/rdma/mlx5_user_ioctl_cmds.h |  1 +
 2 files changed, 21 insertions(+), 1 deletion(-)
drivers/infiniband/hw/mlx5/flow.c +20 -1
index 072b8fc7e057..b254b55e8de0 100644
@@ -47,6 +47,7 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_CREATE_FLOW)(
 	struct mlx5_flow_act flow_act = {.flow_tag = MLX5_FS_DEFAULT_FLOW_TAG};
 	struct mlx5_ib_flow_handler *flow_handler;
 	struct mlx5_ib_flow_matcher *fs_matcher;
+	struct ib_uobject **arr_flow_actions;
 	void *devx_obj;
 	int dest_id, dest_type;
 	void *cmd_in;
@@ -56,6 +57,9 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_CREATE_FLOW)(
 	struct ib_uobject *uobj =
 		uverbs_attr_get_uobject(attrs, MLX5_IB_ATTR_CREATE_FLOW_HANDLE);
 	struct mlx5_ib_dev *dev = to_mdev(uobj->context->device);
+	int len;
+	int ret;
+	int i;
 
 	if (!capable(CAP_NET_RAW))
 		return -EPERM;
@@ -107,6 +111,18 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_CREATE_FLOW)(
 				    MLX5_IB_ATTR_CREATE_FLOW_MATCH_VALUE);
 	fs_matcher = uverbs_attr_get_obj(attrs,
 					 MLX5_IB_ATTR_CREATE_FLOW_MATCHER);
+
+	len = uverbs_attr_get_uobjs_arr(attrs,
+					MLX5_IB_ATTR_CREATE_FLOW_ARR_FLOW_ACTIONS,
+					&arr_flow_actions);
+	for (i = 0; i < len; i++) {
+		struct mlx5_ib_flow_action *maction = to_mflow_act(arr_flow_actions[i]->object);
+
+		ret = parse_flow_flow_action(maction, false, &flow_act);
+		if (ret)
+			return -EINVAL;
+	}
+
 	flow_handler = mlx5_ib_raw_fs_rule_add(dev, fs_matcher, &flow_act,
 					       cmd_in, inlen,
 					       dest_id, dest_type);
@@ -458,7 +474,10 @@ DECLARE_UVERBS_NAMED_METHOD(
 			UVERBS_ACCESS_READ),
 	UVERBS_ATTR_IDR(MLX5_IB_ATTR_CREATE_FLOW_DEST_DEVX,
 			MLX5_IB_OBJECT_DEVX_OBJ,
-			UVERBS_ACCESS_READ));
+			UVERBS_ACCESS_READ),
+	UVERBS_ATTR_IDRS_ARR(MLX5_IB_ATTR_CREATE_FLOW_ARR_FLOW_ACTIONS,
+			     UVERBS_OBJECT_FLOW_ACTION,
+			     UVERBS_ACCESS_READ, 1, 1));
 
 DECLARE_UVERBS_NAMED_METHOD_DESTROY(
 	MLX5_IB_METHOD_DESTROY_FLOW,
include/uapi/rdma/mlx5_user_ioctl_cmds.h +1 -0
index 75c7093fd95b..91c3d42ebd0f 100644
@@ -155,6 +155,7 @@ enum mlx5_ib_create_flow_attrs {
 	MLX5_IB_ATTR_CREATE_FLOW_DEST_QP,
 	MLX5_IB_ATTR_CREATE_FLOW_DEST_DEVX,
 	MLX5_IB_ATTR_CREATE_FLOW_MATCHER,
+	MLX5_IB_ATTR_CREATE_FLOW_ARR_FLOW_ACTIONS,
 };
 
 enum mlx5_ib_destoy_flow_attrs {
Signature · 1 line
2.14.4
#26 lore raw

PATCH 26/27 RDMA/mlx5: Add NIC TX namespace when getting a flow table

In reply to Leon Romanovsky

From: Mark Bloch <[email protected]>

Add the ability to get a NIC TX flow table when using _get_flow_table(). This will allow to create a matcher and a flow rule on the NIC TX path.

---
 drivers/infiniband/hw/mlx5/flow.c    |  1 +
 drivers/infiniband/hw/mlx5/main.c    | 38 ++++++++++++++++++++++++++----------
 drivers/infiniband/hw/mlx5/mlx5_ib.h |  1 +
 3 files changed, 30 insertions(+), 10 deletions(-)
drivers/infiniband/hw/mlx5/flow.c +1 -0
index b254b55e8de0..2422629f48c9 100644
@@ -162,6 +162,7 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_FLOW_MATCHER_CREATE)(
 	if (!obj)
 		return -ENOMEM;
 
+	obj->ns_type = MLX5_FLOW_NAMESPACE_BYPASS;
 	obj->mask_len = uverbs_attr_get_len(
 		attrs, MLX5_IB_ATTR_FLOW_MATCHER_MATCH_MASK);
 	err = uverbs_copy_from(&obj->matcher_mask,
drivers/infiniband/hw/mlx5/main.c +28 -10
index 2b2af82dc32e..ba4bcbc3adb6 100644
@@ -3695,33 +3695,52 @@ static struct ib_flow *mlx5_ib_create_flow(struct ib_qp *qp,
 }
 
 static struct mlx5_ib_flow_prio *_get_flow_table(struct mlx5_ib_dev *dev,
-						 int priority, bool mcast)
+						 struct mlx5_ib_flow_matcher *fs_matcher,
+						 bool mcast)
 {
-	int max_table_size;
 	struct mlx5_flow_namespace *ns = NULL;
 	struct mlx5_ib_flow_prio *prio;
+	int max_table_size = 0;
+	u32 flags = 0;
+	int priority;
+
+	if (fs_matcher->ns_type == MLX5_FLOW_NAMESPACE_BYPASS) {
+		max_table_size = BIT(MLX5_CAP_FLOWTABLE_NIC_RX(dev->mdev,
+							       log_max_ft_size));
+		if (MLX5_CAP_FLOWTABLE_NIC_RX(dev->mdev, decap))
+			flags |= MLX5_FLOW_TABLE_TUNNEL_EN_DECAP;
+		if (MLX5_CAP_FLOWTABLE_NIC_RX(dev->mdev,
+					      reformat_l3_tunnel_to_l2))
+			flags |= MLX5_FLOW_TABLE_TUNNEL_EN_REFORMAT;
+	} else { /* Can only be MLX5_FLOW_NAMESPACE_EGRESS */
+		max_table_size = BIT(MLX5_CAP_FLOWTABLE_NIC_TX(dev->mdev,
+							       log_max_ft_size));
+		if (MLX5_CAP_FLOWTABLE_NIC_TX(dev->mdev, reformat))
+			flags |= MLX5_FLOW_TABLE_TUNNEL_EN_REFORMAT;
+	}
 
-	max_table_size = BIT(MLX5_CAP_FLOWTABLE_NIC_RX(dev->mdev,
-			     log_max_ft_size));
 	if (max_table_size < MLX5_FS_MAX_ENTRIES)
 		return ERR_PTR(-ENOMEM);
 
 	if (mcast)
 		priority = MLX5_IB_FLOW_MCAST_PRIO;
 	else
-		priority = ib_prio_to_core_prio(priority, false);
+		priority = ib_prio_to_core_prio(fs_matcher->priority, false);
 
-	ns = mlx5_get_flow_namespace(dev->mdev, MLX5_FLOW_NAMESPACE_BYPASS);
+	ns = mlx5_get_flow_namespace(dev->mdev, fs_matcher->ns_type);
 	if (!ns)
 		return ERR_PTR(-ENOTSUPP);
 
-	prio = &dev->flow_db->prios[priority];
+	if (fs_matcher->ns_type == MLX5_FLOW_NAMESPACE_BYPASS)
+		prio = &dev->flow_db->prios[priority];
+	else
+		prio = &dev->flow_db->egress_prios[priority];
 
 	if (prio->flow_table)
 		return prio;
 
 	return _get_prio(ns, prio, priority, MLX5_FS_MAX_ENTRIES,
-			 MLX5_FS_MAX_TYPES, 0);
+			 MLX5_FS_MAX_TYPES, flags);
 }
 
 static struct mlx5_ib_flow_handler *
@@ -3820,7 +3839,6 @@ mlx5_ib_raw_fs_rule_add(struct mlx5_ib_dev *dev,
 {
 	struct mlx5_flow_destination *dst;
 	struct mlx5_ib_flow_prio *ft_prio;
-	int priority = fs_matcher->priority;
 	struct mlx5_ib_flow_handler *handler;
 	bool mcast;
 	int err;
@@ -3838,7 +3856,7 @@ mlx5_ib_raw_fs_rule_add(struct mlx5_ib_dev *dev,
 	mcast = raw_fs_is_multicast(fs_matcher, cmd_in);
 	mutex_lock(&dev->flow_db->lock);
 
-	ft_prio = _get_flow_table(dev, priority, mcast);
+	ft_prio = _get_flow_table(dev, fs_matcher, mcast);
 	if (IS_ERR(ft_prio)) {
 		err = PTR_ERR(ft_prio);
 		goto unlock;
drivers/infiniband/hw/mlx5/mlx5_ib.h +1 -0
index 76f1c178cef7..639b5dccf079 100644
@@ -187,6 +187,7 @@ struct mlx5_ib_flow_matcher {
 	struct mlx5_ib_match_params matcher_mask;
 	int			mask_len;
 	enum mlx5_ib_flow_type	flow_type;
+	u8			ns_type;
 	u16			priority;
 	struct mlx5_core_dev	*mdev;
 	atomic_t		usecnt;
Signature · 1 line
2.14.4
#27 lore raw

PATCH 27/27 RDMA/mlx5: Allow creating a matcher for a NIC TX flow table

In reply to Leon Romanovsky

From: Mark Bloch <[email protected]>

Currently a matcher can only be created and attached to a NIC RX flow table. Extend it to allow it on NIC TX flow tables as well.

In order to achieve that, We:

1) Expose a new attribute: MLX5_IB_ATTR_FLOW_MATCHER_FLOW_FLAGS. enum ib_flow_flags is used as valid flags. Only IB_FLOW_ATTR_FLAGS_EGRESS is supported.

2) Remove the requirement to have a DEVX or QP destination when creating a flow. A flow added to NIC TX flow table will forward the packet outside of the vport (Wire or E-Switch in the SR-iOV case).

Only a single flow action can be attached to a flow rule at the moment.

---
 drivers/infiniband/hw/mlx5/flow.c        | 62 +++++++++++++++++++++-----------
 drivers/infiniband/hw/mlx5/main.c        |  5 ++-
 include/uapi/rdma/mlx5_user_ioctl_cmds.h |  1 +
 3 files changed, 46 insertions(+), 22 deletions(-)
drivers/infiniband/hw/mlx5/flow.c +41 -21
index 2422629f48c9..26c5112100e6 100644
@@ -18,6 +18,22 @@
 #define UVERBS_MODULE_NAME mlx5_ib
 #include <rdma/uverbs_named_ioctl.h>
 
+static int mlx5_ib_ft_type_to_namespace(u8 table_type, u8 *namespace)
+{
+	switch (table_type) {
+	case MLX5_IB_UAPI_FLOW_TABLE_TYPE_NIC_RX:
+		*namespace = MLX5_FLOW_NAMESPACE_BYPASS;
+		break;
+	case MLX5_IB_UAPI_FLOW_TABLE_TYPE_NIC_TX:
+		*namespace = MLX5_FLOW_NAMESPACE_EGRESS;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
 static const struct uverbs_attr_spec mlx5_ib_flow_type[] = {
 	[MLX5_IB_FLOW_TYPE_NORMAL] = {
 		.type = UVERBS_ATTR_TYPE_PTR_IN,
@@ -69,7 +85,14 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_CREATE_FLOW)(
 	dest_qp = uverbs_attr_is_valid(attrs,
 				       MLX5_IB_ATTR_CREATE_FLOW_DEST_QP);
 
-	if ((dest_devx && dest_qp) || (!dest_devx && !dest_qp))
+	fs_matcher = uverbs_attr_get_obj(attrs,
+					 MLX5_IB_ATTR_CREATE_FLOW_MATCHER);
+	if (fs_matcher->ns_type == MLX5_FLOW_NAMESPACE_BYPASS &&
+	    ((dest_devx && dest_qp) || (!dest_devx && !dest_qp)))
+		return -EINVAL;
+
+	if (fs_matcher->ns_type == MLX5_FLOW_NAMESPACE_EGRESS &&
+	    (dest_devx || dest_qp))
 		return -EINVAL;
 
 	if (dest_devx) {
@@ -83,7 +106,7 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_CREATE_FLOW)(
 		 */
 		if (!mlx5_ib_devx_is_flow_dest(devx_obj, &dest_id, &dest_type))
 			return -EINVAL;
-	} else {
+	} else if (dest_qp) {
 		struct mlx5_ib_qp *mqp;
 
 		qp = uverbs_attr_get_obj(attrs,
@@ -100,6 +123,8 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_CREATE_FLOW)(
 		else
 			dest_id = mqp->raw_packet_qp.rq.tirn;
 		dest_type = MLX5_FLOW_DESTINATION_TYPE_TIR;
+	} else {
+		dest_type = MLX5_FLOW_DESTINATION_TYPE_PORT;
 	}
 
 	if (dev->rep)
@@ -109,8 +134,6 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_CREATE_FLOW)(
 		attrs, MLX5_IB_ATTR_CREATE_FLOW_MATCH_VALUE);
 	inlen = uverbs_attr_get_len(attrs,
 				    MLX5_IB_ATTR_CREATE_FLOW_MATCH_VALUE);
-	fs_matcher = uverbs_attr_get_obj(attrs,
-					 MLX5_IB_ATTR_CREATE_FLOW_MATCHER);
 
 	len = uverbs_attr_get_uobjs_arr(attrs,
 					MLX5_IB_ATTR_CREATE_FLOW_ARR_FLOW_ACTIONS,
@@ -156,6 +179,7 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_FLOW_MATCHER_CREATE)(
 		attrs, MLX5_IB_ATTR_FLOW_MATCHER_CREATE_HANDLE);
 	struct mlx5_ib_dev *dev = to_mdev(uobj->context->device);
 	struct mlx5_ib_flow_matcher *obj;
+	u32 flags;
 	int err;
 
 	obj = kzalloc(sizeof(struct mlx5_ib_flow_matcher), GFP_KERNEL);
@@ -188,6 +212,16 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_FLOW_MATCHER_CREATE)(
 	if (err)
 		goto end;
 
+	err = uverbs_get_flags32(&flags, attrs,
+				 MLX5_IB_ATTR_FLOW_MATCHER_FLOW_FLAGS,
+				 IB_FLOW_ATTR_FLAGS_EGRESS);
+	if (!err && flags) {
+		err = mlx5_ib_ft_type_to_namespace(MLX5_IB_UAPI_FLOW_TABLE_TYPE_NIC_TX,
+						   &obj->ns_type);
+		if (err)
+			goto end;
+	}
+
 	uobj->object = obj;
 	obj->mdev = dev->mdev;
 	atomic_set(&obj->usecnt, 0);
@@ -198,22 +232,6 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_FLOW_MATCHER_CREATE)(
 	return err;
 }
 
-static int mlx5_ib_ft_type_to_namespace(u8 table_type, u8 *namespace)
-{
-	switch (table_type) {
-	case MLX5_IB_UAPI_FLOW_TABLE_TYPE_NIC_RX:
-		*namespace = MLX5_FLOW_NAMESPACE_BYPASS;
-		break;
-	case MLX5_IB_UAPI_FLOW_TABLE_TYPE_NIC_TX:
-		*namespace = MLX5_FLOW_NAMESPACE_EGRESS;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
 void mlx5_ib_destroy_flow_action_raw(struct mlx5_ib_flow_action *maction)
 {
 	switch (maction->flow_action_raw.sub_type) {
@@ -542,7 +560,9 @@ DECLARE_UVERBS_NAMED_METHOD(
 			    UA_MANDATORY),
 	UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_FLOW_MATCHER_MATCH_CRITERIA,
 			   UVERBS_ATTR_TYPE(u8),
-			   UA_MANDATORY));
+			   UA_MANDATORY),
+	UVERBS_ATTR_FLAGS_IN(MLX5_IB_ATTR_FLOW_MATCHER_FLOW_FLAGS,
+			     enum ib_flow_flags));
 
 DECLARE_UVERBS_NAMED_METHOD_DESTROY(
 	MLX5_IB_METHOD_FLOW_MATCHER_DESTROY,
drivers/infiniband/hw/mlx5/main.c +4 -1
index ba4bcbc3adb6..08bf16161435 100644
@@ -3866,10 +3866,13 @@ mlx5_ib_raw_fs_rule_add(struct mlx5_ib_dev *dev,
 		dst->type = dest_type;
 		dst->tir_num = dest_id;
 		flow_act->action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
-	} else {
+	} else if (dest_type == MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE) {
 		dst->type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE_NUM;
 		dst->ft_num = dest_id;
 		flow_act->action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
+	} else {
+		dst->type = MLX5_FLOW_DESTINATION_TYPE_PORT;
+		flow_act->action |= MLX5_FLOW_CONTEXT_ACTION_ALLOW;
 	}
 
 	handler = _create_raw_flow_rule(dev, ft_prio, dst, fs_matcher, flow_act,
include/uapi/rdma/mlx5_user_ioctl_cmds.h +1 -0
index 91c3d42ebd0f..fb4a8b17cca8 100644
@@ -125,6 +125,7 @@ enum mlx5_ib_flow_matcher_create_attrs {
 	MLX5_IB_ATTR_FLOW_MATCHER_MATCH_MASK,
 	MLX5_IB_ATTR_FLOW_MATCHER_FLOW_TYPE,
 	MLX5_IB_ATTR_FLOW_MATCHER_MATCH_CRITERIA,
+	MLX5_IB_ATTR_FLOW_MATCHER_FLOW_FLAGS,
 };
 
 enum mlx5_ib_flow_matcher_destroy_attrs {
Signature · 1 line
2.14.4
#28 lore raw
In reply to Leon Romanovsky
Quoted 43 lines · Leon Romanovsky

From: Leon Romanovsky <[email protected]>

Hi,

This is PATCH variant of RFC posted in previous week to the ML.
https://patchwork.ozlabs.org/cover/944184/

Changelog:
RFC -> v0:
* Patch 1 a new patch which refactors the logic
when getting a flow namespace.
* Patch 2 was split into two.
* Patch 3: Fixed a typo in commit message
* Patch 5: Updated commit message
* Patch 7: Updated commit message
Renamed:
- MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT_ID to MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT
- packet_reformat_id to reformat_id in struct mlx5_flow_act
- packet_reformat_id to encap_id in struct mlx5_esw_flow_attr
- packet_reformat_id to encap_id in struct mlx5e_encap_entry
- PACKET_REFORMAT to REFORMAT when printing trace points
* Patch 9: Updated commit message
Updated function declaration in mlx5_core.h, could of lead to compile error on bisection.
* Patch 11: Disallow egress rules insertion when in switchdev mode
* Patch 12: A new patch to deal with passing enum values using the IOCTL infrastructure.
* Patch 13: Use new enum value attribute when passing enum mlx5_ib_uapi_flow_table_type
* Patch 15: Don't set encap flags on flow tables if in switchdev mode
* Patch 17: Use new enum value attribute when passing enum mlx5_ib_uapi_flow_table_type and enum mlx5_ib_uapi_flow_action_packet_reformat_type
* Patch 19: Allow creation of both MLX5_IB_UAPI_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L3_TUNNEL and MLX5_IB_UAPI_FLOW_ACTION_PACKET_REFORMAT_TYPE_L3_TUNNEL_TO_L2 packet reformat actions.
* Patch 20: A new patch which allows attaching packet reformat actions to flow tables on NIC RX.

Thanks

Quoted 7 lines

From Mark:
This series exposes the ability to create flow actions which can mutate packet headers. We do that by exposing two new verbs:
* modify header - can change existing packet headers. packet
* reformat - can encapsulate or decapsulate a packet.
Once created a flow action must be attached to a steering rule for it to take effect.

Mark, this got a bit big in terms of patch count, however most of the patches fit on one screen and the overall line count isn't too bad.

Can this be split somehow?

Thanks,
Jason

#29 lore raw
Quoted 52 lines · Jason Gunthorpe
Quoted 43 lines · Leon Romanovsky

From: Leon Romanovsky <[email protected]>

Hi,

This is PATCH variant of RFC posted in previous week to the ML.
https://patchwork.ozlabs.org/cover/944184/

Changelog:
RFC -> v0:
* Patch 1 a new patch which refactors the logic
when getting a flow namespace.
* Patch 2 was split into two.
* Patch 3: Fixed a typo in commit message
* Patch 5: Updated commit message
* Patch 7: Updated commit message
Renamed:
- MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT_ID to MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT
- packet_reformat_id to reformat_id in struct mlx5_flow_act
- packet_reformat_id to encap_id in struct mlx5_esw_flow_attr
- packet_reformat_id to encap_id in struct mlx5e_encap_entry
- PACKET_REFORMAT to REFORMAT when printing trace points
* Patch 9: Updated commit message
Updated function declaration in mlx5_core.h, could of lead to compile error on bisection.
* Patch 11: Disallow egress rules insertion when in switchdev mode
* Patch 12: A new patch to deal with passing enum values using the IOCTL infrastructure.
* Patch 13: Use new enum value attribute when passing enum mlx5_ib_uapi_flow_table_type
* Patch 15: Don't set encap flags on flow tables if in switchdev mode
* Patch 17: Use new enum value attribute when passing enum mlx5_ib_uapi_flow_table_type and enum mlx5_ib_uapi_flow_action_packet_reformat_type
* Patch 19: Allow creation of both MLX5_IB_UAPI_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L3_TUNNEL and MLX5_IB_UAPI_FLOW_ACTION_PACKET_REFORMAT_TYPE_L3_TUNNEL_TO_L2 packet reformat actions.
* Patch 20: A new patch which allows attaching packet reformat actions to flow tables on NIC RX.

Thanks

Quoted 7 lines

From Mark:
This series exposes the ability to create flow actions which can mutate packet headers. We do that by exposing two new verbs:
* modify header - can change existing packet headers. packet
* reformat - can encapsulate or decapsulate a packet.
Once created a flow action must be attached to a steering rule for it to take effect.

Quoted 2 lines

Mark, this got a bit big in terms of patch count, however most of the patches fit on one screen and the overall line count isn't too bad.

Yes, there is a lot of code refactoring inside mlx5 drivers but overall the code is very simple. The difference from the RFC is mainly renames and commit messages and the last 6 patches which add support for flow action to mlx5 create flow, that wasn't posted with the RFC as the mlx5 create flow code wasn't merged yet.

Quoted 3 lines

Can this be split somehow?

It can be split into 3 series like this:

Refactoring mlx5_core + rename + creation of flow actions:
patch [01/27]: net/mlx5: Cleanup flow namespace getter switch logic
patch [02/27]: net/mlx5: Add proper NIC TX steering flow tables support patch [03/27]: net/mlx5: Export modify header alloc/dealloc functions patch [04/27]: net/mlx5: Add support for more namespaces when allocating modify header patch [05/27]: net/mlx5: Break encap/decap into two separated flow table creation flags patch [06/27]: net/mlx5: Move header encap type to IFC header file
patch [07/27]: {net, RDMA}/mlx5: Rename encap to reformat packet
patch [08/27]: net/mlx5: Expose new packet reformat capabilities
patch [09/27]: net/mlx5: Pass a namespace for packet reformat ID allocation patch [10/27]: net/mlx5: Export packet reformat alloc/dealloc functions patch [12/27]: RDMA/uverbs: Add UVERBS_ATTR_CONST_IN to the specs language patch [13/27]: RDMA/mlx5: Add a new flow action verb, modify header
patch [16/27]: RDMA/uverbs: Add generic function to fill in flow action object patch [17/27]: RDMA/mlx5: Add new flow action verb, packet reformat
patch [19/27]: RDMA/mlx5: Extend packet reformat verbs

Enable attaching modify header and packet reformat flow actions via verbs create flow:
patch [11/27]: RDMA/mlx5: Add NIC TX steering support
patch [14/27]: RDMA/mlx5: Enable attaching modify header to steering flows patch [15/27]: RDMA/mlx5: Enable decap and packet reformat on flow tables patch [18/27]: RDMA/mlx5: Enable attaching DECAP action to steering flows patch [20/27]: RDMA/mlx5: Enable reformat on NIC RX if supported
patch [21/27]: RDMA/mlx5: Enable attaching packet reformat action to steering flows

Enable attaching modify header and packet reformat flow actions via mlx5 create flow:
patch [22/27]: IB/uverbs: Add IDRs array attribute type to ioctl() interface patch [23/27]: RDMA/mlx5: Refactor flow action parsing to be more generic patch [24/27]: RDMA/mlx5: Refactor DEVX flow creation
patch [25/27]: RDMA/mlx5: Add flow actions support to DEVX create flow patch [26/27]: RDMA/mlx5: Add NIC TX namespace when getting a flow table patch [27/27]: RDMA/mlx5: Allow creating a matcher for a NIC TX flow table

Quoted 3 lines

Thanks,
Jason

Mark

#30 lore raw
In reply to Leon Romanovsky
Quoted 111 lines · Leon Romanovsky

From: Leon Romanovsky <[email protected]>

Hi,

This is PATCH variant of RFC posted in previous week to the ML.
https://patchwork.ozlabs.org/cover/944184/

Changelog:
RFC -> v0:
* Patch 1 a new patch which refactors the logic
when getting a flow namespace.
* Patch 2 was split into two.
* Patch 3: Fixed a typo in commit message
* Patch 5: Updated commit message
* Patch 7: Updated commit message
Renamed:
- MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT_ID to MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT
- packet_reformat_id to reformat_id in struct mlx5_flow_act
- packet_reformat_id to encap_id in struct mlx5_esw_flow_attr
- packet_reformat_id to encap_id in struct mlx5e_encap_entry
- PACKET_REFORMAT to REFORMAT when printing trace points
* Patch 9: Updated commit message
Updated function declaration in mlx5_core.h, could of lead to compile error on bisection.
* Patch 11: Disallow egress rules insertion when in switchdev mode
* Patch 12: A new patch to deal with passing enum values using the IOCTL infrastructure.
* Patch 13: Use new enum value attribute when passing enum mlx5_ib_uapi_flow_table_type
* Patch 15: Don't set encap flags on flow tables if in switchdev mode
* Patch 17: Use new enum value attribute when passing enum mlx5_ib_uapi_flow_table_type and enum mlx5_ib_uapi_flow_action_packet_reformat_type
* Patch 19: Allow creation of both MLX5_IB_UAPI_FLOW_ACTION_PACKET_REFORMAT_TYPE_L2_TO_L3_TUNNEL and MLX5_IB_UAPI_FLOW_ACTION_PACKET_REFORMAT_TYPE_L3_TUNNEL_TO_L2 packet reformat actions.
* Patch 20: A new patch which allows attaching packet reformat actions to flow tables on NIC RX.

Thanks

------------------------------------------------------------------------
From Mark:
This series exposes the ability to create flow actions which can mutate packet headers. We do that by exposing two new verbs:
* modify header - can change existing packet headers. packet
* reformat - can encapsulate or decapsulate a packet.
Once created a flow action must be attached to a steering rule for it to take effect.

Thanks

Guy Levi (1):
IB/uverbs: Add IDRs array attribute type to ioctl() interface

Mark Bloch (26):
net/mlx5: Cleanup flow namespace getter switch logic net/mlx5: Add proper NIC TX steering flow tables support net/mlx5: Export modify header alloc/dealloc functions net/mlx5: Add support for more namespaces when allocating modify
header
net/mlx5: Break encap/decap into two separated flow table creation
flags
net/mlx5: Move header encap type to IFC header file
{net, RDMA}/mlx5: Rename encap to reformat packet net/mlx5: Expose new packet reformat capabilities net/mlx5: Pass a namespace for packet reformat ID allocation net/mlx5: Export packet reformat alloc/dealloc functions RDMA/mlx5: Add NIC TX steering support
RDMA/uverbs: Add UVERBS_ATTR_CONST_IN to the specs language RDMA/mlx5: Add a new flow action verb, modify header RDMA/mlx5: Enable attaching modify header to steering flows RDMA/mlx5: Enable decap and packet reformat on flow tables RDMA/uverbs: Add generic function to fill in flow action object RDMA/mlx5: Add new flow action verb, packet reformat RDMA/mlx5: Enable attaching DECAP action to steering flows RDMA/mlx5: Extend packet reformat verbs
RDMA/mlx5: Enable reformat on NIC RX if supported RDMA/mlx5: Enable attaching packet reformat action to steering flows RDMA/mlx5: Refactor flow action parsing to be more generic RDMA/mlx5: Refactor DEVX flow creation
RDMA/mlx5: Add flow actions support to DEVX create flow RDMA/mlx5: Add NIC TX namespace when getting a flow table RDMA/mlx5: Allow creating a matcher for a NIC TX flow table

 drivers/infiniband/core/uverbs_ioctl.c             | 115 ++++++-
 .../infiniband/core/uverbs_std_types_flow_action.c |   7 +-
 drivers/infiniband/hw/mlx5/devx.c                  |   6 +-
 drivers/infiniband/hw/mlx5/flow.c                  | 351 ++++++++++++++++++++-
 drivers/infiniband/hw/mlx5/main.c                  | 140 +++++---
 drivers/infiniband/hw/mlx5/mlx5_ib.h               |  26 +-
 drivers/net/ethernet/mellanox/mlx5/core/cmd.c      |   8 +-
 .../mellanox/mlx5/core/diag/fs_tracepoint.h        |   2 +-
 drivers/net/ethernet/mellanox/mlx5/core/en_tc.c    |  50 +--
 drivers/net/ethernet/mellanox/mlx5/core/eswitch.c  |   2 +-
 .../ethernet/mellanox/mlx5/core/eswitch_offloads.c |   9 +-
 drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c   |  87 +++--
 drivers/net/ethernet/mellanox/mlx5/core/fs_core.c  |  57 ++--
 .../net/ethernet/mellanox/mlx5/core/mlx5_core.h    |  11 -
 include/linux/mlx5/device.h                        |   6 +
 include/linux/mlx5/fs.h                            |  20 +-
 include/linux/mlx5/mlx5_ifc.h                      |  70 ++--
 include/rdma/uverbs_ioctl.h                        |  98 +++++-
 include/rdma/uverbs_std_types.h                    |  12 +
 include/uapi/rdma/mlx5_user_ioctl_cmds.h           |  20 ++
 include/uapi/rdma/mlx5_user_ioctl_verbs.h          |  12 +
 include/uapi/rdma/rdma_user_ioctl_cmds.h           |   2 +-
 22 files changed, 928 insertions(+), 183 deletions(-)
Quoted 1 line

--

Jason, Doug

Please drop this series, we will reshuffle it to have less patches in the series and will resubmit.

Thanks