Skip to content

Commit b691b11

Browse files
chumakdkuba-moo
authored andcommitted
net/mlx5: Implement devlink port function cmds to control ipsec_packet
Implement devlink port function commands to enable / disable IPsec packet offloads. This is used to control the IPsec capability of the device. When ipsec_offload is enabled for a VF, it prevents adding IPsec packet offloads on the PF, because the two cannot be active simultaneously due to HW constraints. Conversely, if there are any active IPsec packet offloads on the PF, it's not allowed to enable ipsec_packet on a VF, until PF IPsec offloads are cleared. Signed-off-by: Dima Chumak <dchumak@nvidia.com> Signed-off-by: Leon Romanovsky <leonro@nvidia.com> Signed-off-by: Saeed Mahameed <saeedm@nvidia.com> Link: https://lore.kernel.org/r/20230825062836.103744-9-saeed@kernel.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
1 parent 06bab69 commit b691b11

6 files changed

Lines changed: 173 additions & 4 deletions

File tree

Documentation/networking/device_drivers/ethernet/mellanox/mlx5/switchdev.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,16 @@ IPsec capability enabled, any IPsec offloading is blocked on the PF.
200200
mlx5 driver support devlink port function attr mechanism to setup ipsec_crypto
201201
capability. (refer to Documentation/networking/devlink/devlink-port.rst)
202202

203+
IPsec packet capability setup
204+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
205+
User who wants mlx5 PCI VFs to be able to perform IPsec packet offloading need
206+
to explicitly enable the VF ipsec_packet capability. Enabling IPsec capability
207+
for VFs is supported starting with ConnectX6dx devices and above. When a VF has
208+
IPsec capability enabled, any IPsec offloading is blocked on the PF.
209+
210+
mlx5 driver support devlink port function attr mechanism to setup ipsec_packet
211+
capability. (refer to Documentation/networking/devlink/devlink-port.rst)
212+
203213
SF state setup
204214
--------------
205215

drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,8 @@ static const struct devlink_port_ops mlx5_esw_pf_vf_dl_port_ops = {
9595
#ifdef CONFIG_XFRM_OFFLOAD
9696
.port_fn_ipsec_crypto_get = mlx5_devlink_port_fn_ipsec_crypto_get,
9797
.port_fn_ipsec_crypto_set = mlx5_devlink_port_fn_ipsec_crypto_set,
98+
.port_fn_ipsec_packet_get = mlx5_devlink_port_fn_ipsec_packet_get,
99+
.port_fn_ipsec_packet_set = mlx5_devlink_port_fn_ipsec_packet_set,
98100
#endif /* CONFIG_XFRM_OFFLOAD */
99101
};
100102

drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec.c

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ static int esw_ipsec_vf_query_generic(struct mlx5_core_dev *dev, u16 vport_num,
3737

3838
enum esw_vport_ipsec_offload {
3939
MLX5_ESW_VPORT_IPSEC_CRYPTO_OFFLOAD,
40+
MLX5_ESW_VPORT_IPSEC_PACKET_OFFLOAD,
4041
};
4142

4243
int mlx5_esw_ipsec_vf_offload_get(struct mlx5_core_dev *dev, struct mlx5_vport *vport)
@@ -55,6 +56,7 @@ int mlx5_esw_ipsec_vf_offload_get(struct mlx5_core_dev *dev, struct mlx5_vport *
5556

5657
if (!ipsec_enabled) {
5758
vport->info.ipsec_crypto_enabled = false;
59+
vport->info.ipsec_packet_enabled = false;
5860
return 0;
5961
}
6062

@@ -69,6 +71,8 @@ int mlx5_esw_ipsec_vf_offload_get(struct mlx5_core_dev *dev, struct mlx5_vport *
6971
hca_cap = MLX5_ADDR_OF(query_hca_cap_out, query_cap, capability);
7072
vport->info.ipsec_crypto_enabled =
7173
MLX5_GET(ipsec_cap, hca_cap, ipsec_crypto_offload);
74+
vport->info.ipsec_packet_enabled =
75+
MLX5_GET(ipsec_cap, hca_cap, ipsec_full_offload);
7276
free:
7377
kvfree(query_cap);
7478
return err;
@@ -143,6 +147,9 @@ static int esw_ipsec_vf_set_bytype(struct mlx5_core_dev *dev, struct mlx5_vport
143147
case MLX5_ESW_VPORT_IPSEC_CRYPTO_OFFLOAD:
144148
MLX5_SET(ipsec_cap, cap, ipsec_crypto_offload, enable);
145149
break;
150+
case MLX5_ESW_VPORT_IPSEC_PACKET_OFFLOAD:
151+
MLX5_SET(ipsec_cap, cap, ipsec_full_offload, enable);
152+
break;
146153
default:
147154
ret = -EOPNOTSUPP;
148155
goto free;
@@ -222,15 +229,28 @@ static int esw_ipsec_vf_offload_set_bytype(struct mlx5_eswitch *esw, struct mlx5
222229
err = esw_ipsec_vf_set_bytype(dev, vport, enable, type);
223230
if (err)
224231
return err;
225-
err = esw_ipsec_vf_set_generic(dev, vport->vport, enable);
232+
err = mlx5_esw_ipsec_vf_offload_get(dev, vport);
226233
if (err)
227234
return err;
235+
236+
/* The generic ipsec_offload cap can be disabled only if both
237+
* ipsec_crypto_offload and ipsec_full_offload aren't enabled.
238+
*/
239+
if (!vport->info.ipsec_crypto_enabled &&
240+
!vport->info.ipsec_packet_enabled) {
241+
err = esw_ipsec_vf_set_generic(dev, vport->vport, enable);
242+
if (err)
243+
return err;
244+
}
228245
}
229246

230247
switch (type) {
231248
case MLX5_ESW_VPORT_IPSEC_CRYPTO_OFFLOAD:
232249
vport->info.ipsec_crypto_enabled = enable;
233250
break;
251+
case MLX5_ESW_VPORT_IPSEC_PACKET_OFFLOAD:
252+
vport->info.ipsec_packet_enabled = enable;
253+
break;
234254
default:
235255
return -EINVAL;
236256
}
@@ -301,9 +321,49 @@ int mlx5_esw_ipsec_vf_crypto_offload_supported(struct mlx5_core_dev *dev,
301321
return err;
302322
}
303323

324+
int mlx5_esw_ipsec_vf_packet_offload_supported(struct mlx5_core_dev *dev,
325+
u16 vport_num)
326+
{
327+
int query_sz = MLX5_ST_SZ_BYTES(query_hca_cap_out);
328+
void *hca_cap, *query_cap;
329+
int ret;
330+
331+
if (!mlx5_esw_ipsec_vf_offload_supported(dev))
332+
return -EOPNOTSUPP;
333+
334+
ret = esw_ipsec_offload_supported(dev, vport_num);
335+
if (ret)
336+
return ret;
337+
338+
query_cap = kvzalloc(query_sz, GFP_KERNEL);
339+
if (!query_cap)
340+
return -ENOMEM;
341+
342+
ret = mlx5_vport_get_other_func_cap(dev, vport_num, query_cap, MLX5_CAP_FLOW_TABLE);
343+
if (ret)
344+
goto out;
345+
346+
hca_cap = MLX5_ADDR_OF(query_hca_cap_out, query_cap, capability);
347+
if (!MLX5_GET(flow_table_nic_cap, hca_cap, flow_table_properties_nic_receive.decap)) {
348+
ret = -EOPNOTSUPP;
349+
goto out;
350+
}
351+
352+
out:
353+
kvfree(query_cap);
354+
return ret;
355+
}
356+
304357
int mlx5_esw_ipsec_vf_crypto_offload_set(struct mlx5_eswitch *esw, struct mlx5_vport *vport,
305358
bool enable)
306359
{
307360
return esw_ipsec_vf_offload_set_bytype(esw, vport, enable,
308361
MLX5_ESW_VPORT_IPSEC_CRYPTO_OFFLOAD);
309362
}
363+
364+
int mlx5_esw_ipsec_vf_packet_offload_set(struct mlx5_eswitch *esw, struct mlx5_vport *vport,
365+
bool enable)
366+
{
367+
return esw_ipsec_vf_offload_set_bytype(esw, vport, enable,
368+
MLX5_ESW_VPORT_IPSEC_PACKET_OFFLOAD);
369+
}

drivers/net/ethernet/mellanox/mlx5/core/eswitch.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -834,7 +834,6 @@ static int mlx5_esw_vport_caps_get(struct mlx5_eswitch *esw, struct mlx5_vport *
834834
vport->info.mig_enabled = MLX5_GET(cmd_hca_cap_2, hca_caps, migratable);
835835

836836
err = mlx5_esw_ipsec_vf_offload_get(esw->dev, vport);
837-
838837
out_free:
839838
kfree(query_ctx);
840839
return err;
@@ -917,7 +916,8 @@ int mlx5_esw_vport_enable(struct mlx5_eswitch *esw, struct mlx5_vport *vport,
917916
/* Sync with current vport context */
918917
vport->enabled_events = enabled_events;
919918
vport->enabled = true;
920-
if (vport->vport != MLX5_VPORT_PF && vport->info.ipsec_crypto_enabled)
919+
if (vport->vport != MLX5_VPORT_PF &&
920+
(vport->info.ipsec_crypto_enabled || vport->info.ipsec_packet_enabled))
921921
esw->enabled_ipsec_vf_count++;
922922

923923
/* Esw manager is trusted by default. Host PF (vport 0) is trusted as well
@@ -975,7 +975,8 @@ void mlx5_esw_vport_disable(struct mlx5_eswitch *esw, struct mlx5_vport *vport)
975975
MLX5_CAP_GEN(esw->dev, vhca_resource_manager))
976976
mlx5_esw_vport_vhca_id_clear(esw, vport_num);
977977

978-
if (vport->vport != MLX5_VPORT_PF && vport->info.ipsec_crypto_enabled)
978+
if (vport->vport != MLX5_VPORT_PF &&
979+
(vport->info.ipsec_crypto_enabled || vport->info.ipsec_packet_enabled))
979980
esw->enabled_ipsec_vf_count--;
980981

981982
/* We don't assume VFs will cleanup after themselves.

drivers/net/ethernet/mellanox/mlx5/core/eswitch.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ struct mlx5_vport_info {
164164
u8 roce_enabled: 1;
165165
u8 mig_enabled: 1;
166166
u8 ipsec_crypto_enabled: 1;
167+
u8 ipsec_packet_enabled: 1;
167168
};
168169

169170
/* Vport context events */
@@ -565,6 +566,10 @@ int mlx5_devlink_port_fn_ipsec_crypto_get(struct devlink_port *port, bool *is_en
565566
struct netlink_ext_ack *extack);
566567
int mlx5_devlink_port_fn_ipsec_crypto_set(struct devlink_port *port, bool enable,
567568
struct netlink_ext_ack *extack);
569+
int mlx5_devlink_port_fn_ipsec_packet_get(struct devlink_port *port, bool *is_enabled,
570+
struct netlink_ext_ack *extack);
571+
int mlx5_devlink_port_fn_ipsec_packet_set(struct devlink_port *port, bool enable,
572+
struct netlink_ext_ack *extack);
568573
#endif /* CONFIG_XFRM_OFFLOAD */
569574
void *mlx5_eswitch_get_uplink_priv(struct mlx5_eswitch *esw, u8 rep_type);
570575

@@ -872,6 +877,13 @@ int mlx5_esw_ipsec_vf_crypto_offload_supported(struct mlx5_core_dev *dev,
872877
u16 vport_num);
873878
int mlx5_esw_ipsec_vf_crypto_offload_set(struct mlx5_eswitch *esw, struct mlx5_vport *vport,
874879
bool enable);
880+
int mlx5_esw_ipsec_vf_packet_offload_set(struct mlx5_eswitch *esw, struct mlx5_vport *vport,
881+
bool enable);
882+
int mlx5_esw_ipsec_vf_packet_offload_supported(struct mlx5_core_dev *dev,
883+
u16 vport_num);
884+
void mlx5_esw_vport_ipsec_offload_enable(struct mlx5_eswitch *esw);
885+
void mlx5_esw_vport_ipsec_offload_disable(struct mlx5_eswitch *esw);
886+
875887
#else /* CONFIG_MLX5_ESWITCH */
876888
/* eswitch API stubs */
877889
static inline int mlx5_eswitch_init(struct mlx5_core_dev *dev) { return 0; }

drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4451,4 +4451,88 @@ int mlx5_devlink_port_fn_ipsec_crypto_set(struct devlink_port *port, bool enable
44514451
mutex_unlock(&esw->state_lock);
44524452
return err;
44534453
}
4454+
4455+
int mlx5_devlink_port_fn_ipsec_packet_get(struct devlink_port *port, bool *is_enabled,
4456+
struct netlink_ext_ack *extack)
4457+
{
4458+
struct mlx5_eswitch *esw;
4459+
struct mlx5_vport *vport;
4460+
int err = 0;
4461+
4462+
esw = mlx5_devlink_eswitch_get(port->devlink);
4463+
if (IS_ERR(esw))
4464+
return PTR_ERR(esw);
4465+
4466+
if (!mlx5_esw_ipsec_vf_offload_supported(esw->dev)) {
4467+
NL_SET_ERR_MSG_MOD(extack, "Device doesn't support IPsec packet");
4468+
return -EOPNOTSUPP;
4469+
}
4470+
4471+
vport = mlx5_devlink_port_vport_get(port);
4472+
4473+
mutex_lock(&esw->state_lock);
4474+
if (!vport->enabled) {
4475+
err = -EOPNOTSUPP;
4476+
goto unlock;
4477+
}
4478+
4479+
*is_enabled = vport->info.ipsec_packet_enabled;
4480+
unlock:
4481+
mutex_unlock(&esw->state_lock);
4482+
return err;
4483+
}
4484+
4485+
int mlx5_devlink_port_fn_ipsec_packet_set(struct devlink_port *port,
4486+
bool enable,
4487+
struct netlink_ext_ack *extack)
4488+
{
4489+
struct mlx5_eswitch *esw;
4490+
struct mlx5_vport *vport;
4491+
u16 vport_num;
4492+
int err;
4493+
4494+
esw = mlx5_devlink_eswitch_get(port->devlink);
4495+
if (IS_ERR(esw))
4496+
return PTR_ERR(esw);
4497+
4498+
vport_num = mlx5_esw_devlink_port_index_to_vport_num(port->index);
4499+
err = mlx5_esw_ipsec_vf_packet_offload_supported(esw->dev, vport_num);
4500+
if (err) {
4501+
NL_SET_ERR_MSG_MOD(extack,
4502+
"Device doesn't support IPsec packet mode");
4503+
return err;
4504+
}
4505+
4506+
vport = mlx5_devlink_port_vport_get(port);
4507+
mutex_lock(&esw->state_lock);
4508+
if (!vport->enabled) {
4509+
err = -EOPNOTSUPP;
4510+
NL_SET_ERR_MSG_MOD(extack, "Eswitch vport is disabled");
4511+
goto unlock;
4512+
}
4513+
4514+
if (vport->info.ipsec_packet_enabled == enable)
4515+
goto unlock;
4516+
4517+
if (!esw->enabled_ipsec_vf_count && esw->dev->num_ipsec_offloads) {
4518+
err = -EBUSY;
4519+
goto unlock;
4520+
}
4521+
4522+
err = mlx5_esw_ipsec_vf_packet_offload_set(esw, vport, enable);
4523+
if (err) {
4524+
NL_SET_ERR_MSG_MOD(extack,
4525+
"Failed to set IPsec packet mode");
4526+
goto unlock;
4527+
}
4528+
4529+
vport->info.ipsec_packet_enabled = enable;
4530+
if (enable)
4531+
esw->enabled_ipsec_vf_count++;
4532+
else
4533+
esw->enabled_ipsec_vf_count--;
4534+
unlock:
4535+
mutex_unlock(&esw->state_lock);
4536+
return err;
4537+
}
44544538
#endif /* CONFIG_XFRM_OFFLOAD */

0 commit comments

Comments
 (0)