Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'mlx5-ipsec-packet-offload-support-in-eswitch-mode'

Leon Romanovsky says:

====================
mlx5 IPsec packet offload support in eswitch mode

This series from Jianbo adds mlx5 IPsec packet offload support in eswitch
offloaded mode.

It works exactly like "regular" IPsec, nothing special, except
now users can switch to switchdev before adding IPsec rules.

devlink dev eswitch set pci/0000:06:00.0 mode switchdev

Same configurations as here:

https://lore.kernel.org/netdev/cover.1670005543.git.leonro@nvidia.com/

Packet offload mode:
ip xfrm state offload packet dev <if-name> dir <in|out>
ip xfrm policy .... offload packet dev <if-name>
Crypto offload mode:
ip xfrm state offload crypto dev <if-name> dir <in|out>
or (backward compatibility)
ip xfrm state offload dev <if-name> dir <in|out>

v0: https://lore.kernel.org/all/cover.1689064922.git.leonro@nvidia.com
====================

Link: https://lore.kernel.org/r/cover.1690802064.git.leon@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+1279 -226
+4
drivers/net/ethernet/mellanox/mlx5/core/Makefile
··· 75 75 esw/acl/egress_lgcy.o esw/acl/egress_ofld.o \ 76 76 esw/acl/ingress_lgcy.o esw/acl/ingress_ofld.o 77 77 78 + ifneq ($(CONFIG_MLX5_EN_IPSEC),) 79 + mlx5_core-$(CONFIG_MLX5_ESWITCH) += esw/ipsec_fs.o 80 + endif 81 + 78 82 mlx5_core-$(CONFIG_MLX5_BRIDGE) += esw/bridge.o esw/bridge_mcast.o esw/bridge_debugfs.o \ 79 83 en/rep/bridge.o 80 84
+14 -3
drivers/net/ethernet/mellanox/mlx5/core/en/rep/tc.c
··· 715 715 uplink_priv = &uplink_rpriv->uplink_priv; 716 716 ct_priv = uplink_priv->ct_priv; 717 717 718 - if (!mlx5_ipsec_is_rx_flow(cqe) && 719 - !mlx5e_tc_update_skb(cqe, skb, mapping_ctx, reg_c0, ct_priv, zone_restore_id, tunnel_id, 720 - &tc_priv)) 718 + #ifdef CONFIG_MLX5_EN_IPSEC 719 + if (!(tunnel_id >> ESW_TUN_OPTS_BITS)) { 720 + u32 mapped_id; 721 + u32 metadata; 722 + 723 + mapped_id = tunnel_id & ESW_IPSEC_RX_MAPPED_ID_MASK; 724 + if (mapped_id && 725 + !mlx5_esw_ipsec_rx_make_metadata(priv, mapped_id, &metadata)) 726 + mlx5e_ipsec_offload_handle_rx_skb(priv->netdev, skb, metadata); 727 + } 728 + #endif 729 + 730 + if (!mlx5e_tc_update_skb(cqe, skb, mapping_ctx, reg_c0, ct_priv, 731 + zone_restore_id, tunnel_id, &tc_priv)) 721 732 goto free_skb; 722 733 723 734 forward:
+2
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c
··· 40 40 #include "en.h" 41 41 #include "ipsec.h" 42 42 #include "ipsec_rxtx.h" 43 + #include "en_rep.h" 43 44 44 45 #define MLX5_IPSEC_RESCHED msecs_to_jiffies(1000) 45 46 #define MLX5E_IPSEC_TUNNEL_SA XA_MARK_1 ··· 859 858 goto clear_aso; 860 859 } 861 860 861 + ipsec->is_uplink_rep = mlx5e_is_uplink_rep(priv); 862 862 ret = mlx5e_accel_ipsec_fs_init(ipsec); 863 863 if (ret) 864 864 goto err_fs_init;
+57 -8
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.h
··· 143 143 atomic64_t ipsec_tx_drop_trailer; 144 144 }; 145 145 146 - struct mlx5e_ipsec_rx; 146 + struct mlx5e_ipsec_fc; 147 147 struct mlx5e_ipsec_tx; 148 148 149 149 struct mlx5e_ipsec_work { ··· 169 169 spinlock_t lock; 170 170 }; 171 171 172 + struct mlx5e_ipsec_rx_create_attr { 173 + struct mlx5_flow_namespace *ns; 174 + struct mlx5_ttc_table *ttc; 175 + u32 family; 176 + int prio; 177 + int pol_level; 178 + int sa_level; 179 + int status_level; 180 + enum mlx5_flow_namespace_type chains_ns; 181 + }; 182 + 183 + struct mlx5e_ipsec_ft { 184 + struct mutex mutex; /* Protect changes to this struct */ 185 + struct mlx5_flow_table *pol; 186 + struct mlx5_flow_table *sa; 187 + struct mlx5_flow_table *status; 188 + u32 refcnt; 189 + }; 190 + 191 + struct mlx5e_ipsec_rule { 192 + struct mlx5_flow_handle *rule; 193 + struct mlx5_modify_hdr *modify_hdr; 194 + struct mlx5_pkt_reformat *pkt_reformat; 195 + struct mlx5_fc *fc; 196 + }; 197 + 198 + struct mlx5e_ipsec_miss { 199 + struct mlx5_flow_group *group; 200 + struct mlx5_flow_handle *rule; 201 + }; 202 + 203 + struct mlx5e_ipsec_rx { 204 + struct mlx5e_ipsec_ft ft; 205 + struct mlx5e_ipsec_miss pol; 206 + struct mlx5e_ipsec_miss sa; 207 + struct mlx5e_ipsec_rule status; 208 + struct mlx5e_ipsec_miss status_drop; 209 + struct mlx5_fc *status_drop_cnt; 210 + struct mlx5e_ipsec_fc *fc; 211 + struct mlx5_fs_chains *chains; 212 + u8 allow_tunnel_mode : 1; 213 + struct xarray ipsec_obj_id_map; 214 + }; 215 + 216 + struct mlx5e_ipsec_tx_create_attr { 217 + int prio; 218 + int pol_level; 219 + int sa_level; 220 + int cnt_level; 221 + enum mlx5_flow_namespace_type chains_ns; 222 + }; 223 + 172 224 struct mlx5e_ipsec { 173 225 struct mlx5_core_dev *mdev; 174 226 struct xarray sadb; ··· 230 178 struct mlx5e_flow_steering *fs; 231 179 struct mlx5e_ipsec_rx *rx_ipv4; 232 180 struct mlx5e_ipsec_rx *rx_ipv6; 181 + struct mlx5e_ipsec_rx *rx_esw; 233 182 struct mlx5e_ipsec_tx *tx; 183 + struct mlx5e_ipsec_tx *tx_esw; 234 184 struct mlx5e_ipsec_aso *aso; 235 185 struct notifier_block nb; 236 186 struct notifier_block netevent_nb; 237 187 struct mlx5_ipsec_fs *roce; 188 + u8 is_uplink_rep: 1; 238 189 }; 239 190 240 191 struct mlx5e_ipsec_esn_state { 241 192 u32 esn; 242 193 u32 esn_msb; 243 194 u8 overlap: 1; 244 - }; 245 - 246 - struct mlx5e_ipsec_rule { 247 - struct mlx5_flow_handle *rule; 248 - struct mlx5_modify_hdr *modify_hdr; 249 - struct mlx5_pkt_reformat *pkt_reformat; 250 - struct mlx5_fc *fc; 251 195 }; 252 196 253 197 struct mlx5e_ipsec_limits { ··· 265 217 struct mlx5e_ipsec_work *work; 266 218 struct mlx5e_ipsec_dwork *dwork; 267 219 struct mlx5e_ipsec_limits limits; 220 + u32 rx_mapped_id; 268 221 }; 269 222 270 223 struct mlx5_accel_pol_xfrm_attrs {
+522 -204
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c
··· 9 9 #include "fs_core.h" 10 10 #include "lib/ipsec_fs_roce.h" 11 11 #include "lib/fs_chains.h" 12 + #include "esw/ipsec_fs.h" 13 + #include "en_rep.h" 12 14 13 15 #define NUM_IPSEC_FTE BIT(15) 14 16 #define MLX5_REFORMAT_TYPE_ADD_ESP_TRANSPORT_SIZE 16 ··· 21 19 struct mlx5_fc *drop; 22 20 }; 23 21 24 - struct mlx5e_ipsec_ft { 25 - struct mutex mutex; /* Protect changes to this struct */ 26 - struct mlx5_flow_table *pol; 27 - struct mlx5_flow_table *sa; 28 - struct mlx5_flow_table *status; 29 - u32 refcnt; 30 - }; 31 - 32 - struct mlx5e_ipsec_miss { 33 - struct mlx5_flow_group *group; 34 - struct mlx5_flow_handle *rule; 35 - }; 36 - 37 - struct mlx5e_ipsec_rx { 38 - struct mlx5e_ipsec_ft ft; 39 - struct mlx5e_ipsec_miss pol; 40 - struct mlx5e_ipsec_miss sa; 41 - struct mlx5e_ipsec_rule status; 42 - struct mlx5e_ipsec_fc *fc; 43 - struct mlx5_fs_chains *chains; 44 - u8 allow_tunnel_mode : 1; 45 - }; 46 - 47 22 struct mlx5e_ipsec_tx { 48 23 struct mlx5e_ipsec_ft ft; 49 24 struct mlx5e_ipsec_miss pol; 25 + struct mlx5e_ipsec_miss sa; 50 26 struct mlx5e_ipsec_rule status; 51 27 struct mlx5_flow_namespace *ns; 52 28 struct mlx5e_ipsec_fc *fc; ··· 40 60 return MLX5_TT_IPV6_IPSEC_ESP; 41 61 } 42 62 43 - static struct mlx5e_ipsec_rx *ipsec_rx(struct mlx5e_ipsec *ipsec, u32 family) 63 + static struct mlx5e_ipsec_rx *ipsec_rx(struct mlx5e_ipsec *ipsec, u32 family, int type) 44 64 { 65 + if (ipsec->is_uplink_rep && type == XFRM_DEV_OFFLOAD_PACKET) 66 + return ipsec->rx_esw; 67 + 45 68 if (family == AF_INET) 46 69 return ipsec->rx_ipv4; 47 70 48 71 return ipsec->rx_ipv6; 72 + } 73 + 74 + static struct mlx5e_ipsec_tx *ipsec_tx(struct mlx5e_ipsec *ipsec, int type) 75 + { 76 + if (ipsec->is_uplink_rep && type == XFRM_DEV_OFFLOAD_PACKET) 77 + return ipsec->tx_esw; 78 + 79 + return ipsec->tx; 49 80 } 50 81 51 82 static struct mlx5_fs_chains * ··· 229 238 return err; 230 239 } 231 240 232 - static void rx_destroy(struct mlx5_core_dev *mdev, struct mlx5e_ipsec *ipsec, 233 - struct mlx5e_ipsec_rx *rx, u32 family) 241 + static void ipsec_rx_ft_disconnect(struct mlx5e_ipsec *ipsec, u32 family) 234 242 { 235 243 struct mlx5_ttc_table *ttc = mlx5e_fs_get_ttc(ipsec->fs, false); 236 244 237 - /* disconnect */ 238 245 mlx5_ttc_fwd_default_dest(ttc, family2tt(family)); 246 + } 247 + 248 + static void rx_destroy(struct mlx5_core_dev *mdev, struct mlx5e_ipsec *ipsec, 249 + struct mlx5e_ipsec_rx *rx, u32 family) 250 + { 251 + /* disconnect */ 252 + if (rx != ipsec->rx_esw) 253 + ipsec_rx_ft_disconnect(ipsec, family); 239 254 240 255 if (rx->chains) { 241 256 ipsec_chains_destroy(rx->chains); ··· 254 257 mlx5_del_flow_rules(rx->sa.rule); 255 258 mlx5_destroy_flow_group(rx->sa.group); 256 259 mlx5_destroy_flow_table(rx->ft.sa); 257 - if (rx->allow_tunnel_mode) 258 - mlx5_eswitch_unblock_encap(mdev); 259 - mlx5_del_flow_rules(rx->status.rule); 260 - mlx5_modify_header_dealloc(mdev, rx->status.modify_hdr); 260 + if (rx == ipsec->rx_esw) { 261 + mlx5_esw_ipsec_rx_status_destroy(ipsec, rx); 262 + } else { 263 + mlx5_del_flow_rules(rx->status.rule); 264 + mlx5_modify_header_dealloc(mdev, rx->status.modify_hdr); 265 + } 261 266 mlx5_destroy_flow_table(rx->ft.status); 262 267 263 268 mlx5_ipsec_fs_roce_rx_destroy(ipsec->roce, family); 264 269 } 265 270 271 + static void ipsec_rx_create_attr_set(struct mlx5e_ipsec *ipsec, 272 + struct mlx5e_ipsec_rx *rx, 273 + u32 family, 274 + struct mlx5e_ipsec_rx_create_attr *attr) 275 + { 276 + if (rx == ipsec->rx_esw) { 277 + /* For packet offload in switchdev mode, RX & TX use FDB namespace */ 278 + attr->ns = ipsec->tx_esw->ns; 279 + mlx5_esw_ipsec_rx_create_attr_set(ipsec, attr); 280 + return; 281 + } 282 + 283 + attr->ns = mlx5e_fs_get_ns(ipsec->fs, false); 284 + attr->ttc = mlx5e_fs_get_ttc(ipsec->fs, false); 285 + attr->family = family; 286 + attr->prio = MLX5E_NIC_PRIO; 287 + attr->pol_level = MLX5E_ACCEL_FS_POL_FT_LEVEL; 288 + attr->sa_level = MLX5E_ACCEL_FS_ESP_FT_LEVEL; 289 + attr->status_level = MLX5E_ACCEL_FS_ESP_FT_ERR_LEVEL; 290 + attr->chains_ns = MLX5_FLOW_NAMESPACE_KERNEL; 291 + } 292 + 293 + static int ipsec_rx_status_pass_dest_get(struct mlx5e_ipsec *ipsec, 294 + struct mlx5e_ipsec_rx *rx, 295 + struct mlx5e_ipsec_rx_create_attr *attr, 296 + struct mlx5_flow_destination *dest) 297 + { 298 + struct mlx5_flow_table *ft; 299 + int err; 300 + 301 + if (rx == ipsec->rx_esw) 302 + return mlx5_esw_ipsec_rx_status_pass_dest_get(ipsec, dest); 303 + 304 + *dest = mlx5_ttc_get_default_dest(attr->ttc, family2tt(attr->family)); 305 + err = mlx5_ipsec_fs_roce_rx_create(ipsec->mdev, ipsec->roce, attr->ns, dest, 306 + attr->family, MLX5E_ACCEL_FS_ESP_FT_ROCE_LEVEL, 307 + attr->prio); 308 + if (err) 309 + return err; 310 + 311 + ft = mlx5_ipsec_fs_roce_ft_get(ipsec->roce, attr->family); 312 + if (ft) { 313 + dest->type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE; 314 + dest->ft = ft; 315 + } 316 + 317 + return 0; 318 + } 319 + 320 + static void ipsec_rx_ft_connect(struct mlx5e_ipsec *ipsec, 321 + struct mlx5e_ipsec_rx *rx, 322 + struct mlx5e_ipsec_rx_create_attr *attr) 323 + { 324 + struct mlx5_flow_destination dest = {}; 325 + 326 + dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE; 327 + dest.ft = rx->ft.pol; 328 + mlx5_ttc_fwd_dest(attr->ttc, family2tt(attr->family), &dest); 329 + } 330 + 266 331 static int rx_create(struct mlx5_core_dev *mdev, struct mlx5e_ipsec *ipsec, 267 332 struct mlx5e_ipsec_rx *rx, u32 family) 268 333 { 269 - struct mlx5_flow_namespace *ns = mlx5e_fs_get_ns(ipsec->fs, false); 270 - struct mlx5_ttc_table *ttc = mlx5e_fs_get_ttc(ipsec->fs, false); 271 - struct mlx5_flow_destination default_dest; 334 + struct mlx5e_ipsec_rx_create_attr attr; 272 335 struct mlx5_flow_destination dest[2]; 273 336 struct mlx5_flow_table *ft; 274 337 u32 flags = 0; 275 338 int err; 276 339 277 - default_dest = mlx5_ttc_get_default_dest(ttc, family2tt(family)); 278 - err = mlx5_ipsec_fs_roce_rx_create(mdev, ipsec->roce, ns, &default_dest, 279 - family, MLX5E_ACCEL_FS_ESP_FT_ROCE_LEVEL, 280 - MLX5E_NIC_PRIO); 340 + ipsec_rx_create_attr_set(ipsec, rx, family, &attr); 341 + 342 + err = ipsec_rx_status_pass_dest_get(ipsec, rx, &attr, &dest[0]); 281 343 if (err) 282 344 return err; 283 345 284 - ft = ipsec_ft_create(ns, MLX5E_ACCEL_FS_ESP_FT_ERR_LEVEL, 285 - MLX5E_NIC_PRIO, 1, 0); 346 + ft = ipsec_ft_create(attr.ns, attr.status_level, attr.prio, 1, 0); 286 347 if (IS_ERR(ft)) { 287 348 err = PTR_ERR(ft); 288 349 goto err_fs_ft_status; 289 350 } 290 - 291 351 rx->ft.status = ft; 292 - 293 - ft = mlx5_ipsec_fs_roce_ft_get(ipsec->roce, family); 294 - if (ft) { 295 - dest[0].type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE; 296 - dest[0].ft = ft; 297 - } else { 298 - dest[0] = default_dest; 299 - } 300 352 301 353 dest[1].type = MLX5_FLOW_DESTINATION_TYPE_COUNTER; 302 354 dest[1].counter_id = mlx5_fc_id(rx->fc->cnt); 303 - err = ipsec_status_rule(mdev, rx, dest); 355 + if (rx == ipsec->rx_esw) 356 + err = mlx5_esw_ipsec_rx_status_create(ipsec, rx, dest); 357 + else 358 + err = ipsec_status_rule(mdev, rx, dest); 304 359 if (err) 305 360 goto err_add; 306 361 307 362 /* Create FT */ 308 - if (mlx5_ipsec_device_caps(mdev) & MLX5_IPSEC_CAP_TUNNEL) 309 - rx->allow_tunnel_mode = mlx5_eswitch_block_encap(mdev); 310 363 if (rx->allow_tunnel_mode) 311 364 flags = MLX5_FLOW_TABLE_TUNNEL_EN_REFORMAT; 312 - ft = ipsec_ft_create(ns, MLX5E_ACCEL_FS_ESP_FT_LEVEL, MLX5E_NIC_PRIO, 2, 313 - flags); 365 + ft = ipsec_ft_create(attr.ns, attr.sa_level, attr.prio, 2, flags); 314 366 if (IS_ERR(ft)) { 315 367 err = PTR_ERR(ft); 316 368 goto err_fs_ft; ··· 372 326 373 327 if (mlx5_ipsec_device_caps(mdev) & MLX5_IPSEC_CAP_PRIO) { 374 328 rx->chains = ipsec_chains_create(mdev, rx->ft.sa, 375 - MLX5_FLOW_NAMESPACE_KERNEL, 376 - MLX5E_NIC_PRIO, 377 - MLX5E_ACCEL_FS_POL_FT_LEVEL, 329 + attr.chains_ns, 330 + attr.prio, 331 + attr.pol_level, 378 332 &rx->ft.pol); 379 333 if (IS_ERR(rx->chains)) { 380 334 err = PTR_ERR(rx->chains); ··· 384 338 goto connect; 385 339 } 386 340 387 - ft = ipsec_ft_create(ns, MLX5E_ACCEL_FS_POL_FT_LEVEL, MLX5E_NIC_PRIO, 388 - 2, 0); 341 + ft = ipsec_ft_create(attr.ns, attr.pol_level, attr.prio, 2, 0); 389 342 if (IS_ERR(ft)) { 390 343 err = PTR_ERR(ft); 391 344 goto err_pol_ft; ··· 399 354 400 355 connect: 401 356 /* connect */ 402 - memset(dest, 0x00, sizeof(*dest)); 403 - dest[0].type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE; 404 - dest[0].ft = rx->ft.pol; 405 - mlx5_ttc_fwd_dest(ttc, family2tt(family), &dest[0]); 357 + if (rx != ipsec->rx_esw) 358 + ipsec_rx_ft_connect(ipsec, rx, &attr); 406 359 return 0; 407 360 408 361 err_pol_miss: ··· 411 368 err_fs: 412 369 mlx5_destroy_flow_table(rx->ft.sa); 413 370 err_fs_ft: 414 - if (rx->allow_tunnel_mode) 415 - mlx5_eswitch_unblock_encap(mdev); 416 371 mlx5_del_flow_rules(rx->status.rule); 417 372 mlx5_modify_header_dealloc(mdev, rx->status.modify_hdr); 418 373 err_add: ··· 428 387 if (rx->ft.refcnt) 429 388 goto skip; 430 389 431 - err = rx_create(mdev, ipsec, rx, family); 390 + if (mlx5_ipsec_device_caps(mdev) & MLX5_IPSEC_CAP_TUNNEL) 391 + rx->allow_tunnel_mode = mlx5_eswitch_block_encap(mdev); 392 + 393 + err = mlx5_eswitch_block_mode_trylock(mdev); 432 394 if (err) 433 - return err; 395 + goto err_out; 396 + 397 + err = rx_create(mdev, ipsec, rx, family); 398 + mlx5_eswitch_block_mode_unlock(mdev, err); 399 + if (err) 400 + goto err_out; 434 401 435 402 skip: 436 403 rx->ft.refcnt++; 437 404 return 0; 405 + 406 + err_out: 407 + if (rx->allow_tunnel_mode) 408 + mlx5_eswitch_unblock_encap(mdev); 409 + return err; 438 410 } 439 411 440 412 static void rx_put(struct mlx5e_ipsec *ipsec, struct mlx5e_ipsec_rx *rx, ··· 456 402 if (--rx->ft.refcnt) 457 403 return; 458 404 405 + mlx5_eswitch_unblock_mode_lock(ipsec->mdev); 459 406 rx_destroy(ipsec->mdev, ipsec, rx, family); 407 + mlx5_eswitch_unblock_mode_unlock(ipsec->mdev); 408 + 409 + if (rx->allow_tunnel_mode) 410 + mlx5_eswitch_unblock_encap(ipsec->mdev); 460 411 } 461 412 462 413 static struct mlx5e_ipsec_rx *rx_ft_get(struct mlx5_core_dev *mdev, 463 - struct mlx5e_ipsec *ipsec, u32 family) 414 + struct mlx5e_ipsec *ipsec, u32 family, 415 + int type) 464 416 { 465 - struct mlx5e_ipsec_rx *rx = ipsec_rx(ipsec, family); 417 + struct mlx5e_ipsec_rx *rx = ipsec_rx(ipsec, family, type); 466 418 int err; 467 419 468 420 mutex_lock(&rx->ft.mutex); ··· 482 422 483 423 static struct mlx5_flow_table *rx_ft_get_policy(struct mlx5_core_dev *mdev, 484 424 struct mlx5e_ipsec *ipsec, 485 - u32 family, u32 prio) 425 + u32 family, u32 prio, int type) 486 426 { 487 - struct mlx5e_ipsec_rx *rx = ipsec_rx(ipsec, family); 427 + struct mlx5e_ipsec_rx *rx = ipsec_rx(ipsec, family, type); 488 428 struct mlx5_flow_table *ft; 489 429 int err; 490 430 ··· 509 449 return ERR_PTR(err); 510 450 } 511 451 512 - static void rx_ft_put(struct mlx5e_ipsec *ipsec, u32 family) 452 + static void rx_ft_put(struct mlx5e_ipsec *ipsec, u32 family, int type) 513 453 { 514 - struct mlx5e_ipsec_rx *rx = ipsec_rx(ipsec, family); 454 + struct mlx5e_ipsec_rx *rx = ipsec_rx(ipsec, family, type); 515 455 516 456 mutex_lock(&rx->ft.mutex); 517 457 rx_put(ipsec, rx, family); 518 458 mutex_unlock(&rx->ft.mutex); 519 459 } 520 460 521 - static void rx_ft_put_policy(struct mlx5e_ipsec *ipsec, u32 family, u32 prio) 461 + static void rx_ft_put_policy(struct mlx5e_ipsec *ipsec, u32 family, u32 prio, int type) 522 462 { 523 - struct mlx5e_ipsec_rx *rx = ipsec_rx(ipsec, family); 463 + struct mlx5e_ipsec_rx *rx = ipsec_rx(ipsec, family, type); 524 464 525 465 mutex_lock(&rx->ft.mutex); 526 466 if (rx->chains) ··· 564 504 } 565 505 566 506 /* IPsec TX flow steering */ 567 - static void tx_destroy(struct mlx5_core_dev *mdev, struct mlx5e_ipsec_tx *tx, 507 + static void tx_destroy(struct mlx5e_ipsec *ipsec, struct mlx5e_ipsec_tx *tx, 568 508 struct mlx5_ipsec_fs *roce) 569 509 { 570 510 mlx5_ipsec_fs_roce_tx_destroy(roce); ··· 576 516 mlx5_destroy_flow_table(tx->ft.pol); 577 517 } 578 518 519 + if (tx == ipsec->tx_esw) { 520 + mlx5_del_flow_rules(tx->sa.rule); 521 + mlx5_destroy_flow_group(tx->sa.group); 522 + } 579 523 mlx5_destroy_flow_table(tx->ft.sa); 580 - if (tx->allow_tunnel_mode) 581 - mlx5_eswitch_unblock_encap(mdev); 582 524 mlx5_del_flow_rules(tx->status.rule); 583 525 mlx5_destroy_flow_table(tx->ft.status); 584 526 } 585 527 586 - static int tx_create(struct mlx5_core_dev *mdev, struct mlx5e_ipsec_tx *tx, 528 + static void ipsec_tx_create_attr_set(struct mlx5e_ipsec *ipsec, 529 + struct mlx5e_ipsec_tx *tx, 530 + struct mlx5e_ipsec_tx_create_attr *attr) 531 + { 532 + if (tx == ipsec->tx_esw) { 533 + mlx5_esw_ipsec_tx_create_attr_set(ipsec, attr); 534 + return; 535 + } 536 + 537 + attr->prio = 0; 538 + attr->pol_level = 0; 539 + attr->sa_level = 1; 540 + attr->cnt_level = 2; 541 + attr->chains_ns = MLX5_FLOW_NAMESPACE_EGRESS_IPSEC; 542 + } 543 + 544 + static int tx_create(struct mlx5e_ipsec *ipsec, struct mlx5e_ipsec_tx *tx, 587 545 struct mlx5_ipsec_fs *roce) 588 546 { 547 + struct mlx5_core_dev *mdev = ipsec->mdev; 548 + struct mlx5e_ipsec_tx_create_attr attr; 589 549 struct mlx5_flow_destination dest = {}; 590 550 struct mlx5_flow_table *ft; 591 551 u32 flags = 0; 592 552 int err; 593 553 594 - ft = ipsec_ft_create(tx->ns, 2, 0, 1, 0); 554 + ipsec_tx_create_attr_set(ipsec, tx, &attr); 555 + ft = ipsec_ft_create(tx->ns, attr.cnt_level, attr.prio, 1, 0); 595 556 if (IS_ERR(ft)) 596 557 return PTR_ERR(ft); 597 558 tx->ft.status = ft; ··· 621 540 if (err) 622 541 goto err_status_rule; 623 542 624 - if (mlx5_ipsec_device_caps(mdev) & MLX5_IPSEC_CAP_TUNNEL) 625 - tx->allow_tunnel_mode = mlx5_eswitch_block_encap(mdev); 626 543 if (tx->allow_tunnel_mode) 627 544 flags = MLX5_FLOW_TABLE_TUNNEL_EN_REFORMAT; 628 - ft = ipsec_ft_create(tx->ns, 1, 0, 4, flags); 545 + ft = ipsec_ft_create(tx->ns, attr.sa_level, attr.prio, 4, flags); 629 546 if (IS_ERR(ft)) { 630 547 err = PTR_ERR(ft); 631 548 goto err_sa_ft; 632 549 } 633 550 tx->ft.sa = ft; 634 551 552 + if (tx == ipsec->tx_esw) { 553 + dest.type = MLX5_FLOW_DESTINATION_TYPE_VPORT; 554 + dest.vport.num = MLX5_VPORT_UPLINK; 555 + err = ipsec_miss_create(mdev, tx->ft.sa, &tx->sa, &dest); 556 + if (err) 557 + goto err_sa_miss; 558 + memset(&dest, 0, sizeof(dest)); 559 + } 560 + 635 561 if (mlx5_ipsec_device_caps(mdev) & MLX5_IPSEC_CAP_PRIO) { 636 562 tx->chains = ipsec_chains_create( 637 - mdev, tx->ft.sa, MLX5_FLOW_NAMESPACE_EGRESS_IPSEC, 0, 0, 563 + mdev, tx->ft.sa, attr.chains_ns, attr.prio, attr.pol_level, 638 564 &tx->ft.pol); 639 565 if (IS_ERR(tx->chains)) { 640 566 err = PTR_ERR(tx->chains); ··· 651 563 goto connect_roce; 652 564 } 653 565 654 - ft = ipsec_ft_create(tx->ns, 0, 0, 2, 0); 566 + ft = ipsec_ft_create(tx->ns, attr.pol_level, attr.prio, 2, 0); 655 567 if (IS_ERR(ft)) { 656 568 err = PTR_ERR(ft); 657 569 goto err_pol_ft; ··· 680 592 mlx5_destroy_flow_table(tx->ft.pol); 681 593 } 682 594 err_pol_ft: 595 + if (tx == ipsec->tx_esw) { 596 + mlx5_del_flow_rules(tx->sa.rule); 597 + mlx5_destroy_flow_group(tx->sa.group); 598 + } 599 + err_sa_miss: 683 600 mlx5_destroy_flow_table(tx->ft.sa); 684 601 err_sa_ft: 685 - if (tx->allow_tunnel_mode) 686 - mlx5_eswitch_unblock_encap(mdev); 687 602 mlx5_del_flow_rules(tx->status.rule); 688 603 err_status_rule: 689 604 mlx5_destroy_flow_table(tx->ft.status); 690 605 return err; 606 + } 607 + 608 + static void ipsec_esw_tx_ft_policy_set(struct mlx5_core_dev *mdev, 609 + struct mlx5_flow_table *ft) 610 + { 611 + #ifdef CONFIG_MLX5_ESWITCH 612 + struct mlx5_eswitch *esw = mdev->priv.eswitch; 613 + struct mlx5e_rep_priv *uplink_rpriv; 614 + struct mlx5e_priv *priv; 615 + 616 + esw->offloads.ft_ipsec_tx_pol = ft; 617 + uplink_rpriv = mlx5_eswitch_get_uplink_priv(esw, REP_ETH); 618 + priv = netdev_priv(uplink_rpriv->netdev); 619 + if (!priv->channels.num) 620 + return; 621 + 622 + mlx5e_rep_deactivate_channels(priv); 623 + mlx5e_rep_activate_channels(priv); 624 + #endif 691 625 } 692 626 693 627 static int tx_get(struct mlx5_core_dev *mdev, struct mlx5e_ipsec *ipsec, ··· 720 610 if (tx->ft.refcnt) 721 611 goto skip; 722 612 723 - err = tx_create(mdev, tx, ipsec->roce); 613 + if (mlx5_ipsec_device_caps(mdev) & MLX5_IPSEC_CAP_TUNNEL) 614 + tx->allow_tunnel_mode = mlx5_eswitch_block_encap(mdev); 615 + 616 + err = mlx5_eswitch_block_mode_trylock(mdev); 724 617 if (err) 725 - return err; 618 + goto err_out; 619 + 620 + err = tx_create(ipsec, tx, ipsec->roce); 621 + if (err) { 622 + mlx5_eswitch_block_mode_unlock(mdev, err); 623 + goto err_out; 624 + } 625 + 626 + if (tx == ipsec->tx_esw) 627 + ipsec_esw_tx_ft_policy_set(mdev, tx->ft.pol); 628 + 629 + mlx5_eswitch_block_mode_unlock(mdev, err); 726 630 727 631 skip: 728 632 tx->ft.refcnt++; 729 633 return 0; 634 + 635 + err_out: 636 + if (tx->allow_tunnel_mode) 637 + mlx5_eswitch_unblock_encap(mdev); 638 + return err; 730 639 } 731 640 732 641 static void tx_put(struct mlx5e_ipsec *ipsec, struct mlx5e_ipsec_tx *tx) ··· 753 624 if (--tx->ft.refcnt) 754 625 return; 755 626 756 - tx_destroy(ipsec->mdev, tx, ipsec->roce); 627 + mlx5_eswitch_unblock_mode_lock(ipsec->mdev); 628 + 629 + if (tx == ipsec->tx_esw) { 630 + mlx5_esw_ipsec_restore_dest_uplink(ipsec->mdev); 631 + ipsec_esw_tx_ft_policy_set(ipsec->mdev, NULL); 632 + } 633 + 634 + tx_destroy(ipsec, tx, ipsec->roce); 635 + 636 + mlx5_eswitch_unblock_mode_unlock(ipsec->mdev); 637 + 638 + if (tx->allow_tunnel_mode) 639 + mlx5_eswitch_unblock_encap(ipsec->mdev); 757 640 } 758 641 759 642 static struct mlx5_flow_table *tx_ft_get_policy(struct mlx5_core_dev *mdev, 760 643 struct mlx5e_ipsec *ipsec, 761 - u32 prio) 644 + u32 prio, int type) 762 645 { 763 - struct mlx5e_ipsec_tx *tx = ipsec->tx; 646 + struct mlx5e_ipsec_tx *tx = ipsec_tx(ipsec, type); 764 647 struct mlx5_flow_table *ft; 765 648 int err; 766 649 ··· 798 657 } 799 658 800 659 static struct mlx5e_ipsec_tx *tx_ft_get(struct mlx5_core_dev *mdev, 801 - struct mlx5e_ipsec *ipsec) 660 + struct mlx5e_ipsec *ipsec, int type) 802 661 { 803 - struct mlx5e_ipsec_tx *tx = ipsec->tx; 662 + struct mlx5e_ipsec_tx *tx = ipsec_tx(ipsec, type); 804 663 int err; 805 664 806 665 mutex_lock(&tx->ft.mutex); ··· 812 671 return tx; 813 672 } 814 673 815 - static void tx_ft_put(struct mlx5e_ipsec *ipsec) 674 + static void tx_ft_put(struct mlx5e_ipsec *ipsec, int type) 816 675 { 817 - struct mlx5e_ipsec_tx *tx = ipsec->tx; 676 + struct mlx5e_ipsec_tx *tx = ipsec_tx(ipsec, type); 818 677 819 678 mutex_lock(&tx->ft.mutex); 820 679 tx_put(ipsec, tx); 821 680 mutex_unlock(&tx->ft.mutex); 822 681 } 823 682 824 - static void tx_ft_put_policy(struct mlx5e_ipsec *ipsec, u32 prio) 683 + static void tx_ft_put_policy(struct mlx5e_ipsec *ipsec, u32 prio, int type) 825 684 { 826 - struct mlx5e_ipsec_tx *tx = ipsec->tx; 685 + struct mlx5e_ipsec_tx *tx = ipsec_tx(ipsec, type); 827 686 828 687 mutex_lock(&tx->ft.mutex); 829 688 if (tx->chains) ··· 923 782 misc_parameters_2.metadata_reg_a, MLX5_ETH_WQE_FT_META_IPSEC); 924 783 } 925 784 926 - static void setup_fte_reg_c0(struct mlx5_flow_spec *spec, u32 reqid) 785 + static void setup_fte_reg_c4(struct mlx5_flow_spec *spec, u32 reqid) 927 786 { 928 787 /* Pass policy check before choosing this SA */ 929 788 spec->match_criteria_enable |= MLX5_MATCH_MISC_PARAMETERS_2; 930 789 931 - MLX5_SET(fte_match_param, spec->match_criteria, 932 - misc_parameters_2.metadata_reg_c_0, reqid); 790 + MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, 791 + misc_parameters_2.metadata_reg_c_4); 933 792 MLX5_SET(fte_match_param, spec->match_value, 934 - misc_parameters_2.metadata_reg_c_0, reqid); 793 + misc_parameters_2.metadata_reg_c_4, reqid); 935 794 } 936 795 937 796 static void setup_fte_upper_proto_match(struct mlx5_flow_spec *spec, struct upspec *upspec) ··· 955 814 } 956 815 } 957 816 958 - static int setup_modify_header(struct mlx5_core_dev *mdev, u32 val, u8 dir, 817 + static enum mlx5_flow_namespace_type ipsec_fs_get_ns(struct mlx5e_ipsec *ipsec, 818 + int type, u8 dir) 819 + { 820 + if (ipsec->is_uplink_rep && type == XFRM_DEV_OFFLOAD_PACKET) 821 + return MLX5_FLOW_NAMESPACE_FDB; 822 + 823 + if (dir == XFRM_DEV_OFFLOAD_IN) 824 + return MLX5_FLOW_NAMESPACE_KERNEL; 825 + 826 + return MLX5_FLOW_NAMESPACE_EGRESS; 827 + } 828 + 829 + static int setup_modify_header(struct mlx5e_ipsec *ipsec, int type, u32 val, u8 dir, 959 830 struct mlx5_flow_act *flow_act) 960 831 { 832 + enum mlx5_flow_namespace_type ns_type = ipsec_fs_get_ns(ipsec, type, dir); 961 833 u8 action[MLX5_UN_SZ_BYTES(set_add_copy_action_in_auto)] = {}; 962 - enum mlx5_flow_namespace_type ns_type; 834 + struct mlx5_core_dev *mdev = ipsec->mdev; 963 835 struct mlx5_modify_hdr *modify_hdr; 964 836 965 837 MLX5_SET(set_action_in, action, action_type, MLX5_ACTION_TYPE_SET); ··· 980 826 case XFRM_DEV_OFFLOAD_IN: 981 827 MLX5_SET(set_action_in, action, field, 982 828 MLX5_ACTION_IN_FIELD_METADATA_REG_B); 983 - ns_type = MLX5_FLOW_NAMESPACE_KERNEL; 984 829 break; 985 830 case XFRM_DEV_OFFLOAD_OUT: 986 831 MLX5_SET(set_action_in, action, field, 987 - MLX5_ACTION_IN_FIELD_METADATA_REG_C_0); 988 - ns_type = MLX5_FLOW_NAMESPACE_EGRESS; 832 + MLX5_ACTION_IN_FIELD_METADATA_REG_C_4); 989 833 break; 990 834 default: 991 835 return -EINVAL; ··· 1176 1024 return 0; 1177 1025 } 1178 1026 1179 - static int setup_pkt_reformat(struct mlx5_core_dev *mdev, 1027 + static int setup_pkt_reformat(struct mlx5e_ipsec *ipsec, 1180 1028 struct mlx5_accel_esp_xfrm_attrs *attrs, 1181 1029 struct mlx5_flow_act *flow_act) 1182 1030 { 1031 + enum mlx5_flow_namespace_type ns_type = ipsec_fs_get_ns(ipsec, attrs->type, 1032 + attrs->dir); 1183 1033 struct mlx5_pkt_reformat_params reformat_params = {}; 1034 + struct mlx5_core_dev *mdev = ipsec->mdev; 1184 1035 struct mlx5_pkt_reformat *pkt_reformat; 1185 - enum mlx5_flow_namespace_type ns_type; 1186 1036 int ret; 1187 - 1188 - switch (attrs->dir) { 1189 - case XFRM_DEV_OFFLOAD_IN: 1190 - ns_type = MLX5_FLOW_NAMESPACE_KERNEL; 1191 - break; 1192 - case XFRM_DEV_OFFLOAD_OUT: 1193 - ns_type = MLX5_FLOW_NAMESPACE_EGRESS; 1194 - break; 1195 - default: 1196 - return -EINVAL; 1197 - } 1198 1037 1199 1038 switch (attrs->mode) { 1200 1039 case XFRM_MODE_TRANSPORT: ··· 1223 1080 struct mlx5_flow_spec *spec; 1224 1081 struct mlx5e_ipsec_rx *rx; 1225 1082 struct mlx5_fc *counter; 1226 - int err; 1083 + int err = 0; 1227 1084 1228 - rx = rx_ft_get(mdev, ipsec, attrs->family); 1085 + rx = rx_ft_get(mdev, ipsec, attrs->family, attrs->type); 1229 1086 if (IS_ERR(rx)) 1230 1087 return PTR_ERR(rx); 1231 1088 ··· 1244 1101 setup_fte_esp(spec); 1245 1102 setup_fte_no_frags(spec); 1246 1103 1247 - err = setup_modify_header(mdev, sa_entry->ipsec_obj_id | BIT(31), 1248 - XFRM_DEV_OFFLOAD_IN, &flow_act); 1104 + if (rx != ipsec->rx_esw) 1105 + err = setup_modify_header(ipsec, attrs->type, 1106 + sa_entry->ipsec_obj_id | BIT(31), 1107 + XFRM_DEV_OFFLOAD_IN, &flow_act); 1108 + else 1109 + err = mlx5_esw_ipsec_rx_setup_modify_header(sa_entry, &flow_act); 1110 + 1249 1111 if (err) 1250 1112 goto err_mod_header; 1251 1113 1252 1114 switch (attrs->type) { 1253 1115 case XFRM_DEV_OFFLOAD_PACKET: 1254 - err = setup_pkt_reformat(mdev, attrs, &flow_act); 1116 + err = setup_pkt_reformat(ipsec, attrs, &flow_act); 1255 1117 if (err) 1256 1118 goto err_pkt_reformat; 1257 1119 break; ··· 1306 1158 err_mod_header: 1307 1159 kvfree(spec); 1308 1160 err_alloc: 1309 - rx_ft_put(ipsec, attrs->family); 1161 + rx_ft_put(ipsec, attrs->family, attrs->type); 1310 1162 return err; 1311 1163 } 1312 1164 ··· 1323 1175 struct mlx5_fc *counter; 1324 1176 int err; 1325 1177 1326 - tx = tx_ft_get(mdev, ipsec); 1178 + tx = tx_ft_get(mdev, ipsec, attrs->type); 1327 1179 if (IS_ERR(tx)) 1328 1180 return PTR_ERR(tx); 1329 1181 ··· 1349 1201 break; 1350 1202 case XFRM_DEV_OFFLOAD_PACKET: 1351 1203 if (attrs->reqid) 1352 - setup_fte_reg_c0(spec, attrs->reqid); 1353 - err = setup_pkt_reformat(mdev, attrs, &flow_act); 1204 + setup_fte_reg_c4(spec, attrs->reqid); 1205 + err = setup_pkt_reformat(ipsec, attrs, &flow_act); 1354 1206 if (err) 1355 1207 goto err_pkt_reformat; 1356 1208 break; ··· 1399 1251 err_pkt_reformat: 1400 1252 kvfree(spec); 1401 1253 err_alloc: 1402 - tx_ft_put(ipsec); 1254 + tx_ft_put(ipsec, attrs->type); 1403 1255 return err; 1404 1256 } 1405 1257 ··· 1407 1259 { 1408 1260 struct mlx5_accel_pol_xfrm_attrs *attrs = &pol_entry->attrs; 1409 1261 struct mlx5_core_dev *mdev = mlx5e_ipsec_pol2dev(pol_entry); 1410 - struct mlx5e_ipsec_tx *tx = pol_entry->ipsec->tx; 1262 + struct mlx5e_ipsec *ipsec = pol_entry->ipsec; 1411 1263 struct mlx5_flow_destination dest[2] = {}; 1412 1264 struct mlx5_flow_act flow_act = {}; 1413 1265 struct mlx5_flow_handle *rule; 1414 1266 struct mlx5_flow_spec *spec; 1415 1267 struct mlx5_flow_table *ft; 1268 + struct mlx5e_ipsec_tx *tx; 1416 1269 int err, dstn = 0; 1417 1270 1418 - ft = tx_ft_get_policy(mdev, pol_entry->ipsec, attrs->prio); 1271 + ft = tx_ft_get_policy(mdev, ipsec, attrs->prio, attrs->type); 1419 1272 if (IS_ERR(ft)) 1420 1273 return PTR_ERR(ft); 1421 1274 ··· 1426 1277 goto err_alloc; 1427 1278 } 1428 1279 1280 + tx = ipsec_tx(ipsec, attrs->type); 1429 1281 if (attrs->family == AF_INET) 1430 1282 setup_fte_addr4(spec, &attrs->saddr.a4, &attrs->daddr.a4); 1431 1283 else ··· 1441 1291 if (!attrs->reqid) 1442 1292 break; 1443 1293 1444 - err = setup_modify_header(mdev, attrs->reqid, 1294 + err = setup_modify_header(ipsec, attrs->type, attrs->reqid, 1445 1295 XFRM_DEV_OFFLOAD_OUT, &flow_act); 1446 1296 if (err) 1447 1297 goto err_mod_header; ··· 1460 1310 } 1461 1311 1462 1312 flow_act.flags |= FLOW_ACT_NO_APPEND; 1313 + if (tx == ipsec->tx_esw && tx->chains) 1314 + flow_act.flags |= FLOW_ACT_IGNORE_FLOW_LEVEL; 1463 1315 dest[dstn].ft = tx->ft.sa; 1464 1316 dest[dstn].type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE; 1465 1317 dstn++; ··· 1483 1331 err_mod_header: 1484 1332 kvfree(spec); 1485 1333 err_alloc: 1486 - tx_ft_put_policy(pol_entry->ipsec, attrs->prio); 1334 + tx_ft_put_policy(ipsec, attrs->prio, attrs->type); 1487 1335 return err; 1488 1336 } 1489 1337 ··· 1491 1339 { 1492 1340 struct mlx5_accel_pol_xfrm_attrs *attrs = &pol_entry->attrs; 1493 1341 struct mlx5_core_dev *mdev = mlx5e_ipsec_pol2dev(pol_entry); 1342 + struct mlx5e_ipsec *ipsec = pol_entry->ipsec; 1494 1343 struct mlx5_flow_destination dest[2]; 1495 1344 struct mlx5_flow_act flow_act = {}; 1496 1345 struct mlx5_flow_handle *rule; ··· 1500 1347 struct mlx5e_ipsec_rx *rx; 1501 1348 int err, dstn = 0; 1502 1349 1503 - ft = rx_ft_get_policy(mdev, pol_entry->ipsec, attrs->family, attrs->prio); 1350 + ft = rx_ft_get_policy(mdev, pol_entry->ipsec, attrs->family, attrs->prio, 1351 + attrs->type); 1504 1352 if (IS_ERR(ft)) 1505 1353 return PTR_ERR(ft); 1506 1354 1507 - rx = ipsec_rx(pol_entry->ipsec, attrs->family); 1355 + rx = ipsec_rx(pol_entry->ipsec, attrs->family, attrs->type); 1508 1356 1509 1357 spec = kvzalloc(sizeof(*spec), GFP_KERNEL); 1510 1358 if (!spec) { ··· 1537 1383 } 1538 1384 1539 1385 flow_act.flags |= FLOW_ACT_NO_APPEND; 1386 + if (rx == ipsec->rx_esw && rx->chains) 1387 + flow_act.flags |= FLOW_ACT_IGNORE_FLOW_LEVEL; 1540 1388 dest[dstn].type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE; 1541 1389 dest[dstn].ft = rx->ft.sa; 1542 1390 dstn++; ··· 1556 1400 err_action: 1557 1401 kvfree(spec); 1558 1402 err_alloc: 1559 - rx_ft_put_policy(pol_entry->ipsec, attrs->family, attrs->prio); 1403 + rx_ft_put_policy(pol_entry->ipsec, attrs->family, attrs->prio, attrs->type); 1560 1404 return err; 1405 + } 1406 + 1407 + static void ipsec_fs_destroy_single_counter(struct mlx5_core_dev *mdev, 1408 + struct mlx5e_ipsec_fc *fc) 1409 + { 1410 + mlx5_fc_destroy(mdev, fc->drop); 1411 + mlx5_fc_destroy(mdev, fc->cnt); 1412 + kfree(fc); 1561 1413 } 1562 1414 1563 1415 static void ipsec_fs_destroy_counters(struct mlx5e_ipsec *ipsec) 1564 1416 { 1565 - struct mlx5e_ipsec_rx *rx_ipv4 = ipsec->rx_ipv4; 1566 1417 struct mlx5_core_dev *mdev = ipsec->mdev; 1567 - struct mlx5e_ipsec_tx *tx = ipsec->tx; 1568 1418 1569 - mlx5_fc_destroy(mdev, tx->fc->drop); 1570 - mlx5_fc_destroy(mdev, tx->fc->cnt); 1571 - kfree(tx->fc); 1572 - mlx5_fc_destroy(mdev, rx_ipv4->fc->drop); 1573 - mlx5_fc_destroy(mdev, rx_ipv4->fc->cnt); 1574 - kfree(rx_ipv4->fc); 1419 + ipsec_fs_destroy_single_counter(mdev, ipsec->tx->fc); 1420 + ipsec_fs_destroy_single_counter(mdev, ipsec->rx_ipv4->fc); 1421 + if (ipsec->is_uplink_rep) { 1422 + ipsec_fs_destroy_single_counter(mdev, ipsec->tx_esw->fc); 1423 + ipsec_fs_destroy_single_counter(mdev, ipsec->rx_esw->fc); 1424 + } 1575 1425 } 1576 1426 1577 - static int ipsec_fs_init_counters(struct mlx5e_ipsec *ipsec) 1427 + static struct mlx5e_ipsec_fc *ipsec_fs_init_single_counter(struct mlx5_core_dev *mdev) 1578 1428 { 1579 - struct mlx5e_ipsec_rx *rx_ipv4 = ipsec->rx_ipv4; 1580 - struct mlx5e_ipsec_rx *rx_ipv6 = ipsec->rx_ipv6; 1581 - struct mlx5_core_dev *mdev = ipsec->mdev; 1582 - struct mlx5e_ipsec_tx *tx = ipsec->tx; 1583 1429 struct mlx5e_ipsec_fc *fc; 1584 1430 struct mlx5_fc *counter; 1585 1431 int err; 1586 1432 1587 - fc = kzalloc(sizeof(*rx_ipv4->fc), GFP_KERNEL); 1433 + fc = kzalloc(sizeof(*fc), GFP_KERNEL); 1588 1434 if (!fc) 1589 - return -ENOMEM; 1435 + return ERR_PTR(-ENOMEM); 1590 1436 1591 - /* Both IPv4 and IPv6 point to same flow counters struct. */ 1592 - rx_ipv4->fc = fc; 1593 - rx_ipv6->fc = fc; 1594 1437 counter = mlx5_fc_create(mdev, false); 1595 1438 if (IS_ERR(counter)) { 1596 1439 err = PTR_ERR(counter); 1440 + goto err_cnt; 1441 + } 1442 + fc->cnt = counter; 1443 + 1444 + counter = mlx5_fc_create(mdev, false); 1445 + if (IS_ERR(counter)) { 1446 + err = PTR_ERR(counter); 1447 + goto err_drop; 1448 + } 1449 + fc->drop = counter; 1450 + 1451 + return fc; 1452 + 1453 + err_drop: 1454 + mlx5_fc_destroy(mdev, fc->cnt); 1455 + err_cnt: 1456 + kfree(fc); 1457 + return ERR_PTR(err); 1458 + } 1459 + 1460 + static int ipsec_fs_init_counters(struct mlx5e_ipsec *ipsec) 1461 + { 1462 + struct mlx5_core_dev *mdev = ipsec->mdev; 1463 + struct mlx5e_ipsec_fc *fc; 1464 + int err; 1465 + 1466 + fc = ipsec_fs_init_single_counter(mdev); 1467 + if (IS_ERR(fc)) { 1468 + err = PTR_ERR(fc); 1597 1469 goto err_rx_cnt; 1598 1470 } 1471 + ipsec->rx_ipv4->fc = fc; 1599 1472 1600 - fc->cnt = counter; 1601 - counter = mlx5_fc_create(mdev, false); 1602 - if (IS_ERR(counter)) { 1603 - err = PTR_ERR(counter); 1604 - goto err_rx_drop; 1605 - } 1606 - 1607 - fc->drop = counter; 1608 - fc = kzalloc(sizeof(*tx->fc), GFP_KERNEL); 1609 - if (!fc) { 1610 - err = -ENOMEM; 1611 - goto err_tx_fc; 1612 - } 1613 - 1614 - tx->fc = fc; 1615 - counter = mlx5_fc_create(mdev, false); 1616 - if (IS_ERR(counter)) { 1617 - err = PTR_ERR(counter); 1473 + fc = ipsec_fs_init_single_counter(mdev); 1474 + if (IS_ERR(fc)) { 1475 + err = PTR_ERR(fc); 1618 1476 goto err_tx_cnt; 1619 1477 } 1478 + ipsec->tx->fc = fc; 1620 1479 1621 - fc->cnt = counter; 1622 - counter = mlx5_fc_create(mdev, false); 1623 - if (IS_ERR(counter)) { 1624 - err = PTR_ERR(counter); 1625 - goto err_tx_drop; 1480 + if (ipsec->is_uplink_rep) { 1481 + fc = ipsec_fs_init_single_counter(mdev); 1482 + if (IS_ERR(fc)) { 1483 + err = PTR_ERR(fc); 1484 + goto err_rx_esw_cnt; 1485 + } 1486 + ipsec->rx_esw->fc = fc; 1487 + 1488 + fc = ipsec_fs_init_single_counter(mdev); 1489 + if (IS_ERR(fc)) { 1490 + err = PTR_ERR(fc); 1491 + goto err_tx_esw_cnt; 1492 + } 1493 + ipsec->tx_esw->fc = fc; 1626 1494 } 1627 1495 1628 - fc->drop = counter; 1496 + /* Both IPv4 and IPv6 point to same flow counters struct. */ 1497 + ipsec->rx_ipv6->fc = ipsec->rx_ipv4->fc; 1629 1498 return 0; 1630 1499 1631 - err_tx_drop: 1632 - mlx5_fc_destroy(mdev, tx->fc->cnt); 1500 + err_tx_esw_cnt: 1501 + ipsec_fs_destroy_single_counter(mdev, ipsec->rx_esw->fc); 1502 + err_rx_esw_cnt: 1503 + ipsec_fs_destroy_single_counter(mdev, ipsec->tx->fc); 1633 1504 err_tx_cnt: 1634 - kfree(tx->fc); 1635 - err_tx_fc: 1636 - mlx5_fc_destroy(mdev, rx_ipv4->fc->drop); 1637 - err_rx_drop: 1638 - mlx5_fc_destroy(mdev, rx_ipv4->fc->cnt); 1505 + ipsec_fs_destroy_single_counter(mdev, ipsec->rx_ipv4->fc); 1639 1506 err_rx_cnt: 1640 - kfree(rx_ipv4->fc); 1641 1507 return err; 1642 1508 } 1643 1509 ··· 1669 1491 struct mlx5e_ipsec *ipsec = priv->ipsec; 1670 1492 struct mlx5e_ipsec_hw_stats *stats; 1671 1493 struct mlx5e_ipsec_fc *fc; 1494 + u64 packets, bytes; 1672 1495 1673 1496 stats = (struct mlx5e_ipsec_hw_stats *)ipsec_stats; 1674 1497 ··· 1691 1512 mlx5_fc_query(mdev, fc->cnt, &stats->ipsec_tx_pkts, &stats->ipsec_tx_bytes); 1692 1513 mlx5_fc_query(mdev, fc->drop, &stats->ipsec_tx_drop_pkts, 1693 1514 &stats->ipsec_tx_drop_bytes); 1515 + 1516 + if (ipsec->is_uplink_rep) { 1517 + fc = ipsec->rx_esw->fc; 1518 + if (!mlx5_fc_query(mdev, fc->cnt, &packets, &bytes)) { 1519 + stats->ipsec_rx_pkts += packets; 1520 + stats->ipsec_rx_bytes += bytes; 1521 + } 1522 + 1523 + if (!mlx5_fc_query(mdev, fc->drop, &packets, &bytes)) { 1524 + stats->ipsec_rx_drop_pkts += packets; 1525 + stats->ipsec_rx_drop_bytes += bytes; 1526 + } 1527 + 1528 + fc = ipsec->tx_esw->fc; 1529 + if (!mlx5_fc_query(mdev, fc->cnt, &packets, &bytes)) { 1530 + stats->ipsec_tx_pkts += packets; 1531 + stats->ipsec_tx_bytes += bytes; 1532 + } 1533 + 1534 + if (!mlx5_fc_query(mdev, fc->drop, &packets, &bytes)) { 1535 + stats->ipsec_tx_drop_pkts += packets; 1536 + stats->ipsec_tx_drop_bytes += bytes; 1537 + } 1538 + } 1539 + } 1540 + 1541 + #ifdef CONFIG_MLX5_ESWITCH 1542 + static int mlx5e_ipsec_block_tc_offload(struct mlx5_core_dev *mdev) 1543 + { 1544 + struct mlx5_eswitch *esw = mdev->priv.eswitch; 1545 + int err = 0; 1546 + 1547 + if (esw) 1548 + down_write(&esw->mode_lock); 1549 + 1550 + if (mdev->num_block_ipsec) { 1551 + err = -EBUSY; 1552 + goto unlock; 1553 + } 1554 + 1555 + mdev->num_block_tc++; 1556 + 1557 + unlock: 1558 + if (esw) 1559 + up_write(&esw->mode_lock); 1560 + 1561 + return err; 1562 + } 1563 + #else 1564 + static int mlx5e_ipsec_block_tc_offload(struct mlx5_core_dev *mdev) 1565 + { 1566 + if (mdev->num_block_ipsec) 1567 + return -EBUSY; 1568 + 1569 + mdev->num_block_tc++; 1570 + return 0; 1571 + } 1572 + #endif 1573 + 1574 + static void mlx5e_ipsec_unblock_tc_offload(struct mlx5_core_dev *mdev) 1575 + { 1576 + mdev->num_block_tc++; 1694 1577 } 1695 1578 1696 1579 int mlx5e_accel_ipsec_fs_add_rule(struct mlx5e_ipsec_sa_entry *sa_entry) 1697 1580 { 1698 - if (sa_entry->attrs.dir == XFRM_DEV_OFFLOAD_OUT) 1699 - return tx_add_rule(sa_entry); 1581 + int err; 1700 1582 1701 - return rx_add_rule(sa_entry); 1583 + if (sa_entry->attrs.type == XFRM_DEV_OFFLOAD_PACKET) { 1584 + err = mlx5e_ipsec_block_tc_offload(sa_entry->ipsec->mdev); 1585 + if (err) 1586 + return err; 1587 + } 1588 + 1589 + if (sa_entry->attrs.dir == XFRM_DEV_OFFLOAD_OUT) 1590 + err = tx_add_rule(sa_entry); 1591 + else 1592 + err = rx_add_rule(sa_entry); 1593 + 1594 + if (err) 1595 + goto err_out; 1596 + 1597 + return 0; 1598 + 1599 + err_out: 1600 + if (sa_entry->attrs.type == XFRM_DEV_OFFLOAD_PACKET) 1601 + mlx5e_ipsec_unblock_tc_offload(sa_entry->ipsec->mdev); 1602 + return err; 1702 1603 } 1703 1604 1704 1605 void mlx5e_accel_ipsec_fs_del_rule(struct mlx5e_ipsec_sa_entry *sa_entry) ··· 1791 1532 if (ipsec_rule->pkt_reformat) 1792 1533 mlx5_packet_reformat_dealloc(mdev, ipsec_rule->pkt_reformat); 1793 1534 1535 + if (sa_entry->attrs.type == XFRM_DEV_OFFLOAD_PACKET) 1536 + mlx5e_ipsec_unblock_tc_offload(mdev); 1537 + 1794 1538 if (sa_entry->attrs.dir == XFRM_DEV_OFFLOAD_OUT) { 1795 - tx_ft_put(sa_entry->ipsec); 1539 + tx_ft_put(sa_entry->ipsec, sa_entry->attrs.type); 1796 1540 return; 1797 1541 } 1798 1542 1799 1543 mlx5_modify_header_dealloc(mdev, ipsec_rule->modify_hdr); 1800 - rx_ft_put(sa_entry->ipsec, sa_entry->attrs.family); 1544 + mlx5_esw_ipsec_rx_id_mapping_remove(sa_entry); 1545 + rx_ft_put(sa_entry->ipsec, sa_entry->attrs.family, sa_entry->attrs.type); 1801 1546 } 1802 1547 1803 1548 int mlx5e_accel_ipsec_fs_add_pol(struct mlx5e_ipsec_pol_entry *pol_entry) 1804 1549 { 1805 - if (pol_entry->attrs.dir == XFRM_DEV_OFFLOAD_OUT) 1806 - return tx_add_policy(pol_entry); 1550 + int err; 1807 1551 1808 - return rx_add_policy(pol_entry); 1552 + err = mlx5e_ipsec_block_tc_offload(pol_entry->ipsec->mdev); 1553 + if (err) 1554 + return err; 1555 + 1556 + if (pol_entry->attrs.dir == XFRM_DEV_OFFLOAD_OUT) 1557 + err = tx_add_policy(pol_entry); 1558 + else 1559 + err = rx_add_policy(pol_entry); 1560 + 1561 + if (err) 1562 + goto err_out; 1563 + 1564 + return 0; 1565 + 1566 + err_out: 1567 + mlx5e_ipsec_unblock_tc_offload(pol_entry->ipsec->mdev); 1568 + return err; 1809 1569 } 1810 1570 1811 1571 void mlx5e_accel_ipsec_fs_del_pol(struct mlx5e_ipsec_pol_entry *pol_entry) ··· 1834 1556 1835 1557 mlx5_del_flow_rules(ipsec_rule->rule); 1836 1558 1559 + mlx5e_ipsec_unblock_tc_offload(pol_entry->ipsec->mdev); 1560 + 1837 1561 if (pol_entry->attrs.dir == XFRM_DEV_OFFLOAD_IN) { 1838 1562 rx_ft_put_policy(pol_entry->ipsec, pol_entry->attrs.family, 1839 - pol_entry->attrs.prio); 1563 + pol_entry->attrs.prio, pol_entry->attrs.type); 1840 1564 return; 1841 1565 } 1842 1566 1843 1567 if (ipsec_rule->modify_hdr) 1844 1568 mlx5_modify_header_dealloc(mdev, ipsec_rule->modify_hdr); 1845 1569 1846 - tx_ft_put_policy(pol_entry->ipsec, pol_entry->attrs.prio); 1570 + tx_ft_put_policy(pol_entry->ipsec, pol_entry->attrs.prio, pol_entry->attrs.type); 1847 1571 } 1848 1572 1849 1573 void mlx5e_accel_ipsec_fs_cleanup(struct mlx5e_ipsec *ipsec) ··· 1853 1573 if (!ipsec->tx) 1854 1574 return; 1855 1575 1856 - if (mlx5_ipsec_device_caps(ipsec->mdev) & MLX5_IPSEC_CAP_ROCE) 1576 + if (ipsec->roce) 1857 1577 mlx5_ipsec_fs_roce_cleanup(ipsec->roce); 1858 1578 1859 1579 ipsec_fs_destroy_counters(ipsec); ··· 1868 1588 mutex_destroy(&ipsec->rx_ipv6->ft.mutex); 1869 1589 WARN_ON(ipsec->rx_ipv6->ft.refcnt); 1870 1590 kfree(ipsec->rx_ipv6); 1591 + 1592 + if (ipsec->is_uplink_rep) { 1593 + xa_destroy(&ipsec->rx_esw->ipsec_obj_id_map); 1594 + 1595 + mutex_destroy(&ipsec->tx_esw->ft.mutex); 1596 + WARN_ON(ipsec->tx_esw->ft.refcnt); 1597 + kfree(ipsec->tx_esw); 1598 + 1599 + mutex_destroy(&ipsec->rx_esw->ft.mutex); 1600 + WARN_ON(ipsec->rx_esw->ft.refcnt); 1601 + kfree(ipsec->rx_esw); 1602 + } 1871 1603 } 1872 1604 1873 1605 int mlx5e_accel_ipsec_fs_init(struct mlx5e_ipsec *ipsec) 1874 1606 { 1875 1607 struct mlx5_core_dev *mdev = ipsec->mdev; 1876 - struct mlx5_flow_namespace *ns; 1608 + struct mlx5_flow_namespace *ns, *ns_esw; 1877 1609 int err = -ENOMEM; 1878 1610 1879 1611 ns = mlx5_get_flow_namespace(ipsec->mdev, ··· 1893 1601 if (!ns) 1894 1602 return -EOPNOTSUPP; 1895 1603 1604 + if (ipsec->is_uplink_rep) { 1605 + ns_esw = mlx5_get_flow_namespace(mdev, MLX5_FLOW_NAMESPACE_FDB); 1606 + if (!ns_esw) 1607 + return -EOPNOTSUPP; 1608 + 1609 + ipsec->tx_esw = kzalloc(sizeof(*ipsec->tx_esw), GFP_KERNEL); 1610 + if (!ipsec->tx_esw) 1611 + return -ENOMEM; 1612 + 1613 + ipsec->rx_esw = kzalloc(sizeof(*ipsec->rx_esw), GFP_KERNEL); 1614 + if (!ipsec->rx_esw) 1615 + goto err_rx_esw; 1616 + } 1617 + 1896 1618 ipsec->tx = kzalloc(sizeof(*ipsec->tx), GFP_KERNEL); 1897 1619 if (!ipsec->tx) 1898 - return -ENOMEM; 1620 + goto err_tx; 1899 1621 1900 1622 ipsec->rx_ipv4 = kzalloc(sizeof(*ipsec->rx_ipv4), GFP_KERNEL); 1901 1623 if (!ipsec->rx_ipv4) ··· 1928 1622 mutex_init(&ipsec->rx_ipv6->ft.mutex); 1929 1623 ipsec->tx->ns = ns; 1930 1624 1931 - if (mlx5_ipsec_device_caps(mdev) & MLX5_IPSEC_CAP_ROCE) 1625 + if (ipsec->is_uplink_rep) { 1626 + mutex_init(&ipsec->tx_esw->ft.mutex); 1627 + mutex_init(&ipsec->rx_esw->ft.mutex); 1628 + ipsec->tx_esw->ns = ns_esw; 1629 + xa_init_flags(&ipsec->rx_esw->ipsec_obj_id_map, XA_FLAGS_ALLOC1); 1630 + } else if (mlx5_ipsec_device_caps(mdev) & MLX5_IPSEC_CAP_ROCE) { 1932 1631 ipsec->roce = mlx5_ipsec_fs_roce_init(mdev); 1632 + } 1933 1633 1934 1634 return 0; 1935 1635 ··· 1945 1633 kfree(ipsec->rx_ipv4); 1946 1634 err_rx_ipv4: 1947 1635 kfree(ipsec->tx); 1636 + err_tx: 1637 + kfree(ipsec->rx_esw); 1638 + err_rx_esw: 1639 + kfree(ipsec->tx_esw); 1948 1640 return err; 1949 1641 } 1950 1642 ··· 1970 1654 1971 1655 bool mlx5e_ipsec_fs_tunnel_enabled(struct mlx5e_ipsec_sa_entry *sa_entry) 1972 1656 { 1973 - struct mlx5e_ipsec_rx *rx = 1974 - ipsec_rx(sa_entry->ipsec, sa_entry->attrs.family); 1975 - struct mlx5e_ipsec_tx *tx = sa_entry->ipsec->tx; 1657 + struct mlx5_accel_esp_xfrm_attrs *attrs = &sa_entry->attrs; 1658 + struct mlx5e_ipsec_rx *rx; 1659 + struct mlx5e_ipsec_tx *tx; 1976 1660 1661 + rx = ipsec_rx(sa_entry->ipsec, attrs->family, attrs->type); 1662 + tx = ipsec_tx(sa_entry->ipsec, attrs->type); 1977 1663 if (sa_entry->attrs.dir == XFRM_DEV_OFFLOAD_OUT) 1978 1664 return tx->allow_tunnel_mode; 1979 1665
+3 -2
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_offload.c
··· 45 45 MLX5_CAP_FLOWTABLE_NIC_RX(mdev, decap)) 46 46 caps |= MLX5_IPSEC_CAP_PACKET_OFFLOAD; 47 47 48 - if (MLX5_CAP_FLOWTABLE_NIC_TX(mdev, ignore_flow_level) && 49 - MLX5_CAP_FLOWTABLE_NIC_RX(mdev, ignore_flow_level)) 48 + if ((MLX5_CAP_FLOWTABLE_NIC_TX(mdev, ignore_flow_level) && 49 + MLX5_CAP_FLOWTABLE_NIC_RX(mdev, ignore_flow_level)) || 50 + MLX5_CAP_ESW_FLOWTABLE_FDB(mdev, ignore_flow_level)) 50 51 caps |= MLX5_IPSEC_CAP_PRIO; 51 52 52 53 if (MLX5_CAP_FLOWTABLE_NIC_TX(mdev,
+23 -2
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.c
··· 37 37 #include "ipsec.h" 38 38 #include "ipsec_rxtx.h" 39 39 #include "en.h" 40 + #include "esw/ipsec_fs.h" 40 41 41 42 enum { 42 43 MLX5E_IPSEC_TX_SYNDROME_OFFLOAD = 0x8, ··· 310 309 311 310 void mlx5e_ipsec_offload_handle_rx_skb(struct net_device *netdev, 312 311 struct sk_buff *skb, 313 - struct mlx5_cqe64 *cqe) 312 + u32 ipsec_meta_data) 314 313 { 315 - u32 ipsec_meta_data = be32_to_cpu(cqe->ft_metadata); 316 314 struct mlx5e_priv *priv = netdev_priv(netdev); 317 315 struct mlx5e_ipsec *ipsec = priv->ipsec; 318 316 struct mlx5e_ipsec_sa_entry *sa_entry; ··· 355 355 default: 356 356 atomic64_inc(&ipsec->sw_stats.ipsec_rx_drop_syndrome); 357 357 } 358 + } 359 + 360 + int mlx5_esw_ipsec_rx_make_metadata(struct mlx5e_priv *priv, u32 id, u32 *metadata) 361 + { 362 + struct mlx5e_ipsec *ipsec = priv->ipsec; 363 + u32 ipsec_obj_id; 364 + int err; 365 + 366 + if (!ipsec || !ipsec->is_uplink_rep) 367 + return -EINVAL; 368 + 369 + err = mlx5_esw_ipsec_rx_ipsec_obj_id_search(priv, id, &ipsec_obj_id); 370 + if (err) { 371 + atomic64_inc(&ipsec->sw_stats.ipsec_rx_drop_sadb_miss); 372 + return err; 373 + } 374 + 375 + *metadata = MLX5_IPSEC_METADATA_CREATE(ipsec_obj_id, 376 + MLX5E_IPSEC_OFFLOAD_RX_SYNDROME_DECRYPTED); 377 + 378 + return 0; 358 379 }
+4 -2
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.h
··· 43 43 #define MLX5_IPSEC_METADATA_MARKER(metadata) (((metadata) >> 31) & 0x1) 44 44 #define MLX5_IPSEC_METADATA_SYNDROM(metadata) (((metadata) >> 24) & GENMASK(5, 0)) 45 45 #define MLX5_IPSEC_METADATA_HANDLE(metadata) ((metadata) & GENMASK(23, 0)) 46 + #define MLX5_IPSEC_METADATA_CREATE(id, syndrome) ((id) | ((syndrome) << 24)) 46 47 47 48 struct mlx5e_accel_tx_ipsec_state { 48 49 struct xfrm_offload *xo; ··· 67 66 struct mlx5_wqe_inline_seg *inlseg); 68 67 void mlx5e_ipsec_offload_handle_rx_skb(struct net_device *netdev, 69 68 struct sk_buff *skb, 70 - struct mlx5_cqe64 *cqe); 69 + u32 ipsec_meta_data); 70 + int mlx5_esw_ipsec_rx_make_metadata(struct mlx5e_priv *priv, u32 id, u32 *metadata); 71 71 static inline unsigned int mlx5e_ipsec_tx_ids_len(struct mlx5e_accel_tx_ipsec_state *ipsec_st) 72 72 { 73 73 return ipsec_st->tailen; ··· 147 145 static inline 148 146 void mlx5e_ipsec_offload_handle_rx_skb(struct net_device *netdev, 149 147 struct sk_buff *skb, 150 - struct mlx5_cqe64 *cqe) 148 + u32 ipsec_meta_data) 151 149 {} 152 150 153 151 static inline bool mlx5e_ipsec_eseg_meta(struct mlx5_wqe_eth_seg *eseg)
+1
drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
··· 1338 1338 &MLX5E_STATS_GRP(channels), 1339 1339 &MLX5E_STATS_GRP(per_port_buff_congest), 1340 1340 #ifdef CONFIG_MLX5_EN_IPSEC 1341 + &MLX5E_STATS_GRP(ipsec_hw), 1341 1342 &MLX5E_STATS_GRP(ipsec_sw), 1342 1343 #endif 1343 1344 &MLX5E_STATS_GRP(ptp),
+2 -1
drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
··· 1543 1543 mlx5e_ktls_handle_rx_skb(rq, skb, cqe, &cqe_bcnt); 1544 1544 1545 1545 if (unlikely(mlx5_ipsec_is_rx_flow(cqe))) 1546 - mlx5e_ipsec_offload_handle_rx_skb(netdev, skb, cqe); 1546 + mlx5e_ipsec_offload_handle_rx_skb(netdev, skb, 1547 + be32_to_cpu(cqe->ft_metadata)); 1547 1548 1548 1549 if (unlikely(mlx5e_macsec_is_rx_flow(cqe))) 1549 1550 mlx5e_macsec_offload_handle_rx_skb(netdev, skb, cqe);
+47
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
··· 4606 4606 return netif_is_lag_port(dev) && rpriv && rpriv->rep->vport != MLX5_VPORT_UPLINK; 4607 4607 } 4608 4608 4609 + /* As IPsec and TC order is not aligned between software and hardware-offload, 4610 + * either IPsec offload or TC offload, not both, is allowed for a specific interface. 4611 + */ 4612 + static bool is_tc_ipsec_order_check_needed(struct net_device *filter, struct mlx5e_priv *priv) 4613 + { 4614 + if (!IS_ENABLED(CONFIG_MLX5_EN_IPSEC)) 4615 + return false; 4616 + 4617 + if (filter != priv->netdev) 4618 + return false; 4619 + 4620 + if (mlx5e_eswitch_vf_rep(priv->netdev)) 4621 + return false; 4622 + 4623 + return true; 4624 + } 4625 + 4626 + static int mlx5e_tc_block_ipsec_offload(struct net_device *filter, struct mlx5e_priv *priv) 4627 + { 4628 + struct mlx5_core_dev *mdev = priv->mdev; 4629 + 4630 + if (!is_tc_ipsec_order_check_needed(filter, priv)) 4631 + return 0; 4632 + 4633 + if (mdev->num_block_tc) 4634 + return -EBUSY; 4635 + 4636 + mdev->num_block_ipsec++; 4637 + 4638 + return 0; 4639 + } 4640 + 4641 + static void mlx5e_tc_unblock_ipsec_offload(struct net_device *filter, struct mlx5e_priv *priv) 4642 + { 4643 + if (!is_tc_ipsec_order_check_needed(filter, priv)) 4644 + return; 4645 + 4646 + priv->mdev->num_block_ipsec--; 4647 + } 4648 + 4609 4649 int mlx5e_configure_flower(struct net_device *dev, struct mlx5e_priv *priv, 4610 4650 struct flow_cls_offload *f, unsigned long flags) 4611 4651 { ··· 4657 4617 4658 4618 if (!mlx5_esw_hold(priv->mdev)) 4659 4619 return -EBUSY; 4620 + 4621 + err = mlx5e_tc_block_ipsec_offload(dev, priv); 4622 + if (err) 4623 + goto esw_release; 4660 4624 4661 4625 mlx5_esw_get(priv->mdev); 4662 4626 ··· 4707 4663 err_free: 4708 4664 mlx5e_flow_put(priv, flow); 4709 4665 out: 4666 + mlx5e_tc_unblock_ipsec_offload(dev, priv); 4710 4667 mlx5_esw_put(priv->mdev); 4668 + esw_release: 4711 4669 mlx5_esw_release(priv->mdev); 4712 4670 return err; 4713 4671 } ··· 4750 4704 trace_mlx5e_delete_flower(f); 4751 4705 mlx5e_flow_put(priv, flow); 4752 4706 4707 + mlx5e_tc_unblock_ipsec_offload(dev, priv); 4753 4708 mlx5_esw_put(priv->mdev); 4754 4709 return 0; 4755 4710
+325
drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB 2 + // Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 + 4 + #include "fs_core.h" 5 + #include "eswitch.h" 6 + #include "en_accel/ipsec.h" 7 + #include "esw/ipsec_fs.h" 8 + #if IS_ENABLED(CONFIG_MLX5_CLS_ACT) 9 + #include "en/tc_priv.h" 10 + #endif 11 + 12 + enum { 13 + MLX5_ESW_IPSEC_RX_POL_FT_LEVEL, 14 + MLX5_ESW_IPSEC_RX_ESP_FT_LEVEL, 15 + MLX5_ESW_IPSEC_RX_ESP_FT_CHK_LEVEL, 16 + }; 17 + 18 + enum { 19 + MLX5_ESW_IPSEC_TX_POL_FT_LEVEL, 20 + MLX5_ESW_IPSEC_TX_ESP_FT_LEVEL, 21 + MLX5_ESW_IPSEC_TX_ESP_FT_CNT_LEVEL, 22 + }; 23 + 24 + static void esw_ipsec_rx_status_drop_destroy(struct mlx5e_ipsec *ipsec, 25 + struct mlx5e_ipsec_rx *rx) 26 + { 27 + mlx5_del_flow_rules(rx->status_drop.rule); 28 + mlx5_destroy_flow_group(rx->status_drop.group); 29 + mlx5_fc_destroy(ipsec->mdev, rx->status_drop_cnt); 30 + } 31 + 32 + static void esw_ipsec_rx_status_pass_destroy(struct mlx5e_ipsec *ipsec, 33 + struct mlx5e_ipsec_rx *rx) 34 + { 35 + mlx5_del_flow_rules(rx->status.rule); 36 + mlx5_chains_put_table(esw_chains(ipsec->mdev->priv.eswitch), 0, 1, 0); 37 + } 38 + 39 + static int esw_ipsec_rx_status_drop_create(struct mlx5e_ipsec *ipsec, 40 + struct mlx5e_ipsec_rx *rx) 41 + { 42 + int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in); 43 + struct mlx5_flow_table *ft = rx->ft.status; 44 + struct mlx5_core_dev *mdev = ipsec->mdev; 45 + struct mlx5_flow_destination dest = {}; 46 + struct mlx5_flow_act flow_act = {}; 47 + struct mlx5_flow_handle *rule; 48 + struct mlx5_fc *flow_counter; 49 + struct mlx5_flow_spec *spec; 50 + struct mlx5_flow_group *g; 51 + u32 *flow_group_in; 52 + int err = 0; 53 + 54 + flow_group_in = kvzalloc(inlen, GFP_KERNEL); 55 + spec = kvzalloc(sizeof(*spec), GFP_KERNEL); 56 + if (!flow_group_in || !spec) { 57 + err = -ENOMEM; 58 + goto err_out; 59 + } 60 + 61 + MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, ft->max_fte - 1); 62 + MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, ft->max_fte - 1); 63 + g = mlx5_create_flow_group(ft, flow_group_in); 64 + if (IS_ERR(g)) { 65 + err = PTR_ERR(g); 66 + mlx5_core_err(mdev, 67 + "Failed to add ipsec rx status drop flow group, err=%d\n", err); 68 + goto err_out; 69 + } 70 + 71 + flow_counter = mlx5_fc_create(mdev, false); 72 + if (IS_ERR(flow_counter)) { 73 + err = PTR_ERR(flow_counter); 74 + mlx5_core_err(mdev, 75 + "Failed to add ipsec rx status drop rule counter, err=%d\n", err); 76 + goto err_cnt; 77 + } 78 + 79 + flow_act.action = MLX5_FLOW_CONTEXT_ACTION_DROP | MLX5_FLOW_CONTEXT_ACTION_COUNT; 80 + dest.type = MLX5_FLOW_DESTINATION_TYPE_COUNTER; 81 + dest.counter_id = mlx5_fc_id(flow_counter); 82 + spec->flow_context.flow_source = MLX5_FLOW_CONTEXT_FLOW_SOURCE_UPLINK; 83 + rule = mlx5_add_flow_rules(ft, spec, &flow_act, &dest, 1); 84 + if (IS_ERR(rule)) { 85 + err = PTR_ERR(rule); 86 + mlx5_core_err(mdev, 87 + "Failed to add ipsec rx status drop rule, err=%d\n", err); 88 + goto err_rule; 89 + } 90 + 91 + rx->status_drop.group = g; 92 + rx->status_drop.rule = rule; 93 + rx->status_drop_cnt = flow_counter; 94 + 95 + kvfree(flow_group_in); 96 + kvfree(spec); 97 + return 0; 98 + 99 + err_rule: 100 + mlx5_fc_destroy(mdev, flow_counter); 101 + err_cnt: 102 + mlx5_destroy_flow_group(g); 103 + err_out: 104 + kvfree(flow_group_in); 105 + kvfree(spec); 106 + return err; 107 + } 108 + 109 + static int esw_ipsec_rx_status_pass_create(struct mlx5e_ipsec *ipsec, 110 + struct mlx5e_ipsec_rx *rx, 111 + struct mlx5_flow_destination *dest) 112 + { 113 + struct mlx5_flow_act flow_act = {}; 114 + struct mlx5_flow_handle *rule; 115 + struct mlx5_flow_spec *spec; 116 + int err; 117 + 118 + spec = kvzalloc(sizeof(*spec), GFP_KERNEL); 119 + if (!spec) 120 + return -ENOMEM; 121 + 122 + MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, 123 + misc_parameters_2.ipsec_syndrome); 124 + MLX5_SET(fte_match_param, spec->match_value, 125 + misc_parameters_2.ipsec_syndrome, 0); 126 + spec->flow_context.flow_source = MLX5_FLOW_CONTEXT_FLOW_SOURCE_UPLINK; 127 + spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS_2; 128 + flow_act.flags = FLOW_ACT_NO_APPEND; 129 + flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST | 130 + MLX5_FLOW_CONTEXT_ACTION_COUNT; 131 + rule = mlx5_add_flow_rules(rx->ft.status, spec, &flow_act, dest, 2); 132 + if (IS_ERR(rule)) { 133 + err = PTR_ERR(rule); 134 + mlx5_core_warn(ipsec->mdev, 135 + "Failed to add ipsec rx status pass rule, err=%d\n", err); 136 + goto err_rule; 137 + } 138 + 139 + rx->status.rule = rule; 140 + kvfree(spec); 141 + return 0; 142 + 143 + err_rule: 144 + kvfree(spec); 145 + return err; 146 + } 147 + 148 + void mlx5_esw_ipsec_rx_status_destroy(struct mlx5e_ipsec *ipsec, 149 + struct mlx5e_ipsec_rx *rx) 150 + { 151 + esw_ipsec_rx_status_pass_destroy(ipsec, rx); 152 + esw_ipsec_rx_status_drop_destroy(ipsec, rx); 153 + } 154 + 155 + int mlx5_esw_ipsec_rx_status_create(struct mlx5e_ipsec *ipsec, 156 + struct mlx5e_ipsec_rx *rx, 157 + struct mlx5_flow_destination *dest) 158 + { 159 + int err; 160 + 161 + err = esw_ipsec_rx_status_drop_create(ipsec, rx); 162 + if (err) 163 + return err; 164 + 165 + err = esw_ipsec_rx_status_pass_create(ipsec, rx, dest); 166 + if (err) 167 + goto err_pass_create; 168 + 169 + return 0; 170 + 171 + err_pass_create: 172 + esw_ipsec_rx_status_drop_destroy(ipsec, rx); 173 + return err; 174 + } 175 + 176 + void mlx5_esw_ipsec_rx_create_attr_set(struct mlx5e_ipsec *ipsec, 177 + struct mlx5e_ipsec_rx_create_attr *attr) 178 + { 179 + attr->prio = FDB_CRYPTO_INGRESS; 180 + attr->pol_level = MLX5_ESW_IPSEC_RX_POL_FT_LEVEL; 181 + attr->sa_level = MLX5_ESW_IPSEC_RX_ESP_FT_LEVEL; 182 + attr->status_level = MLX5_ESW_IPSEC_RX_ESP_FT_CHK_LEVEL; 183 + attr->chains_ns = MLX5_FLOW_NAMESPACE_FDB; 184 + } 185 + 186 + int mlx5_esw_ipsec_rx_status_pass_dest_get(struct mlx5e_ipsec *ipsec, 187 + struct mlx5_flow_destination *dest) 188 + { 189 + dest->type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE; 190 + dest->ft = mlx5_chains_get_table(esw_chains(ipsec->mdev->priv.eswitch), 0, 1, 0); 191 + 192 + return 0; 193 + } 194 + 195 + int mlx5_esw_ipsec_rx_setup_modify_header(struct mlx5e_ipsec_sa_entry *sa_entry, 196 + struct mlx5_flow_act *flow_act) 197 + { 198 + u8 action[MLX5_UN_SZ_BYTES(set_add_copy_action_in_auto)] = {}; 199 + struct mlx5e_ipsec *ipsec = sa_entry->ipsec; 200 + struct mlx5_core_dev *mdev = ipsec->mdev; 201 + struct mlx5_modify_hdr *modify_hdr; 202 + u32 mapped_id; 203 + int err; 204 + 205 + err = xa_alloc_bh(&ipsec->rx_esw->ipsec_obj_id_map, &mapped_id, 206 + xa_mk_value(sa_entry->ipsec_obj_id), 207 + XA_LIMIT(1, ESW_IPSEC_RX_MAPPED_ID_MASK), 0); 208 + if (err) 209 + return err; 210 + 211 + /* reuse tunnel bits for ipsec, 212 + * tun_id is always 0 and tun_opts is mapped to ipsec_obj_id. 213 + */ 214 + MLX5_SET(set_action_in, action, action_type, MLX5_ACTION_TYPE_SET); 215 + MLX5_SET(set_action_in, action, field, 216 + MLX5_ACTION_IN_FIELD_METADATA_REG_C_1); 217 + MLX5_SET(set_action_in, action, offset, ESW_ZONE_ID_BITS); 218 + MLX5_SET(set_action_in, action, length, 219 + ESW_TUN_ID_BITS + ESW_TUN_OPTS_BITS); 220 + MLX5_SET(set_action_in, action, data, mapped_id); 221 + 222 + modify_hdr = mlx5_modify_header_alloc(mdev, MLX5_FLOW_NAMESPACE_FDB, 223 + 1, action); 224 + if (IS_ERR(modify_hdr)) { 225 + err = PTR_ERR(modify_hdr); 226 + goto err_header_alloc; 227 + } 228 + 229 + sa_entry->rx_mapped_id = mapped_id; 230 + flow_act->modify_hdr = modify_hdr; 231 + flow_act->action |= MLX5_FLOW_CONTEXT_ACTION_MOD_HDR; 232 + 233 + return 0; 234 + 235 + err_header_alloc: 236 + xa_erase_bh(&ipsec->rx_esw->ipsec_obj_id_map, mapped_id); 237 + return err; 238 + } 239 + 240 + void mlx5_esw_ipsec_rx_id_mapping_remove(struct mlx5e_ipsec_sa_entry *sa_entry) 241 + { 242 + struct mlx5e_ipsec *ipsec = sa_entry->ipsec; 243 + 244 + if (sa_entry->rx_mapped_id) 245 + xa_erase_bh(&ipsec->rx_esw->ipsec_obj_id_map, 246 + sa_entry->rx_mapped_id); 247 + } 248 + 249 + int mlx5_esw_ipsec_rx_ipsec_obj_id_search(struct mlx5e_priv *priv, u32 id, 250 + u32 *ipsec_obj_id) 251 + { 252 + struct mlx5e_ipsec *ipsec = priv->ipsec; 253 + void *val; 254 + 255 + val = xa_load(&ipsec->rx_esw->ipsec_obj_id_map, id); 256 + if (!val) 257 + return -ENOENT; 258 + 259 + *ipsec_obj_id = xa_to_value(val); 260 + 261 + return 0; 262 + } 263 + 264 + void mlx5_esw_ipsec_tx_create_attr_set(struct mlx5e_ipsec *ipsec, 265 + struct mlx5e_ipsec_tx_create_attr *attr) 266 + { 267 + attr->prio = FDB_CRYPTO_EGRESS; 268 + attr->pol_level = MLX5_ESW_IPSEC_TX_POL_FT_LEVEL; 269 + attr->sa_level = MLX5_ESW_IPSEC_TX_ESP_FT_LEVEL; 270 + attr->cnt_level = MLX5_ESW_IPSEC_TX_ESP_FT_CNT_LEVEL; 271 + attr->chains_ns = MLX5_FLOW_NAMESPACE_FDB; 272 + } 273 + 274 + #if IS_ENABLED(CONFIG_MLX5_CLS_ACT) 275 + static int mlx5_esw_ipsec_modify_flow_dests(struct mlx5_eswitch *esw, 276 + struct mlx5e_tc_flow *flow) 277 + { 278 + struct mlx5_esw_flow_attr *esw_attr; 279 + struct mlx5_flow_attr *attr; 280 + int err; 281 + 282 + attr = flow->attr; 283 + esw_attr = attr->esw_attr; 284 + if (esw_attr->out_count - esw_attr->split_count > 1) 285 + return 0; 286 + 287 + err = mlx5_eswitch_restore_ipsec_rule(esw, flow->rule[0], esw_attr, 288 + esw_attr->out_count - 1); 289 + 290 + return err; 291 + } 292 + #endif 293 + 294 + void mlx5_esw_ipsec_restore_dest_uplink(struct mlx5_core_dev *mdev) 295 + { 296 + #if IS_ENABLED(CONFIG_MLX5_CLS_ACT) 297 + struct mlx5_eswitch *esw = mdev->priv.eswitch; 298 + struct mlx5_eswitch_rep *rep; 299 + struct mlx5e_rep_priv *rpriv; 300 + struct rhashtable_iter iter; 301 + struct mlx5e_tc_flow *flow; 302 + unsigned long i; 303 + int err; 304 + 305 + xa_for_each(&esw->offloads.vport_reps, i, rep) { 306 + rpriv = rep->rep_data[REP_ETH].priv; 307 + if (!rpriv || !rpriv->netdev) 308 + continue; 309 + 310 + rhashtable_walk_enter(&rpriv->tc_ht, &iter); 311 + rhashtable_walk_start(&iter); 312 + while ((flow = rhashtable_walk_next(&iter)) != NULL) { 313 + if (IS_ERR(flow)) 314 + continue; 315 + 316 + err = mlx5_esw_ipsec_modify_flow_dests(esw, flow); 317 + if (err) 318 + mlx5_core_warn_once(mdev, 319 + "Faided to modify flow dests for IPsec"); 320 + } 321 + rhashtable_walk_stop(&iter); 322 + rhashtable_walk_exit(&iter); 323 + } 324 + #endif 325 + }
+67
drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ 2 + /* Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved. */ 3 + 4 + #ifndef __MLX5_ESW_IPSEC_FS_H__ 5 + #define __MLX5_ESW_IPSEC_FS_H__ 6 + 7 + struct mlx5e_ipsec; 8 + struct mlx5e_ipsec_sa_entry; 9 + 10 + #ifdef CONFIG_MLX5_ESWITCH 11 + void mlx5_esw_ipsec_rx_status_destroy(struct mlx5e_ipsec *ipsec, 12 + struct mlx5e_ipsec_rx *rx); 13 + int mlx5_esw_ipsec_rx_status_create(struct mlx5e_ipsec *ipsec, 14 + struct mlx5e_ipsec_rx *rx, 15 + struct mlx5_flow_destination *dest); 16 + void mlx5_esw_ipsec_rx_create_attr_set(struct mlx5e_ipsec *ipsec, 17 + struct mlx5e_ipsec_rx_create_attr *attr); 18 + int mlx5_esw_ipsec_rx_status_pass_dest_get(struct mlx5e_ipsec *ipsec, 19 + struct mlx5_flow_destination *dest); 20 + int mlx5_esw_ipsec_rx_setup_modify_header(struct mlx5e_ipsec_sa_entry *sa_entry, 21 + struct mlx5_flow_act *flow_act); 22 + void mlx5_esw_ipsec_rx_id_mapping_remove(struct mlx5e_ipsec_sa_entry *sa_entry); 23 + int mlx5_esw_ipsec_rx_ipsec_obj_id_search(struct mlx5e_priv *priv, u32 id, 24 + u32 *ipsec_obj_id); 25 + void mlx5_esw_ipsec_tx_create_attr_set(struct mlx5e_ipsec *ipsec, 26 + struct mlx5e_ipsec_tx_create_attr *attr); 27 + void mlx5_esw_ipsec_restore_dest_uplink(struct mlx5_core_dev *mdev); 28 + #else 29 + static inline void mlx5_esw_ipsec_rx_status_destroy(struct mlx5e_ipsec *ipsec, 30 + struct mlx5e_ipsec_rx *rx) {} 31 + 32 + static inline int mlx5_esw_ipsec_rx_status_create(struct mlx5e_ipsec *ipsec, 33 + struct mlx5e_ipsec_rx *rx, 34 + struct mlx5_flow_destination *dest) 35 + { 36 + return -EINVAL; 37 + } 38 + 39 + static inline void mlx5_esw_ipsec_rx_create_attr_set(struct mlx5e_ipsec *ipsec, 40 + struct mlx5e_ipsec_rx_create_attr *attr) {} 41 + 42 + static inline int mlx5_esw_ipsec_rx_status_pass_dest_get(struct mlx5e_ipsec *ipsec, 43 + struct mlx5_flow_destination *dest) 44 + { 45 + return -EINVAL; 46 + } 47 + 48 + static inline int mlx5_esw_ipsec_rx_setup_modify_header(struct mlx5e_ipsec_sa_entry *sa_entry, 49 + struct mlx5_flow_act *flow_act) 50 + { 51 + return -EINVAL; 52 + } 53 + 54 + static inline void mlx5_esw_ipsec_rx_id_mapping_remove(struct mlx5e_ipsec_sa_entry *sa_entry) {} 55 + 56 + static inline int mlx5_esw_ipsec_rx_ipsec_obj_id_search(struct mlx5e_priv *priv, u32 id, 57 + u32 *ipsec_obj_id) 58 + { 59 + return -EINVAL; 60 + } 61 + 62 + static inline void mlx5_esw_ipsec_tx_create_attr_set(struct mlx5e_ipsec *ipsec, 63 + struct mlx5e_ipsec_tx_create_attr *attr) {} 64 + 65 + static inline void mlx5_esw_ipsec_restore_dest_uplink(struct mlx5_core_dev *mdev) {} 66 + #endif /* CONFIG_MLX5_ESWITCH */ 67 + #endif /* __MLX5_ESW_IPSEC_FS_H__ */
+17
drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
··· 254 254 struct mlx5_flow_group *vport_rx_group; 255 255 struct mlx5_flow_group *vport_rx_drop_group; 256 256 struct mlx5_flow_handle *vport_rx_drop_rule; 257 + struct mlx5_flow_table *ft_ipsec_tx_pol; 257 258 struct xarray vport_reps; 258 259 struct list_head peer_flows[MLX5_MAX_PORTS]; 259 260 struct mutex peer_mutex; ··· 270 269 u8 inline_mode; 271 270 atomic64_t num_flows; 272 271 u64 num_block_encap; 272 + u64 num_block_mode; 273 273 enum devlink_eswitch_encap_mode encap; 274 274 struct ida vport_metadata_ida; 275 275 unsigned int host_number; /* ECPF supports one external host */ ··· 785 783 bool mlx5_eswitch_block_encap(struct mlx5_core_dev *dev); 786 784 void mlx5_eswitch_unblock_encap(struct mlx5_core_dev *dev); 787 785 786 + int mlx5_eswitch_block_mode_trylock(struct mlx5_core_dev *dev); 787 + void mlx5_eswitch_block_mode_unlock(struct mlx5_core_dev *dev, int err); 788 + void mlx5_eswitch_unblock_mode_lock(struct mlx5_core_dev *dev); 789 + void mlx5_eswitch_unblock_mode_unlock(struct mlx5_core_dev *dev); 790 + 788 791 static inline int mlx5_eswitch_num_vfs(struct mlx5_eswitch *esw) 789 792 { 790 793 if (mlx5_esw_allowed(esw)) ··· 811 804 return esw->fdb_table.offloads.slow_fdb; 812 805 } 813 806 807 + int mlx5_eswitch_restore_ipsec_rule(struct mlx5_eswitch *esw, struct mlx5_flow_handle *rule, 808 + struct mlx5_esw_flow_attr *esw_attr, int attr_idx); 814 809 #else /* CONFIG_MLX5_ESWITCH */ 815 810 /* eswitch API stubs */ 816 811 static inline int mlx5_eswitch_init(struct mlx5_core_dev *dev) { return 0; } ··· 871 862 static inline void mlx5_eswitch_unblock_encap(struct mlx5_core_dev *dev) 872 863 { 873 864 } 865 + 866 + static inline int mlx5_eswitch_block_mode_trylock(struct mlx5_core_dev *dev) { return 0; } 867 + 868 + static inline void mlx5_eswitch_block_mode_unlock(struct mlx5_core_dev *dev, int err) {} 869 + 870 + static inline void mlx5_eswitch_unblock_mode_lock(struct mlx5_core_dev *dev) {} 871 + 872 + static inline void mlx5_eswitch_unblock_mode_unlock(struct mlx5_core_dev *dev) {} 874 873 #endif /* CONFIG_MLX5_ESWITCH */ 875 874 876 875 #endif /* __MLX5_ESWITCH_H__ */
+171 -3
drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
··· 424 424 mlx5_chains_put_table(chains, chain, prio, level); 425 425 } 426 426 427 + static bool esw_same_vhca_id(struct mlx5_core_dev *mdev1, struct mlx5_core_dev *mdev2) 428 + { 429 + return MLX5_CAP_GEN(mdev1, vhca_id) == MLX5_CAP_GEN(mdev2, vhca_id); 430 + } 431 + 432 + static bool esw_setup_uplink_fwd_ipsec_needed(struct mlx5_eswitch *esw, 433 + struct mlx5_esw_flow_attr *esw_attr, 434 + int attr_idx) 435 + { 436 + if (esw->offloads.ft_ipsec_tx_pol && 437 + esw_attr->dests[attr_idx].rep && 438 + esw_attr->dests[attr_idx].rep->vport == MLX5_VPORT_UPLINK && 439 + /* To be aligned with software, encryption is needed only for tunnel device */ 440 + (esw_attr->dests[attr_idx].flags & MLX5_ESW_DEST_ENCAP_VALID) && 441 + esw_attr->dests[attr_idx].rep != esw_attr->in_rep && 442 + esw_same_vhca_id(esw_attr->dests[attr_idx].mdev, esw->dev)) 443 + return true; 444 + 445 + return false; 446 + } 447 + 448 + static bool esw_flow_dests_fwd_ipsec_check(struct mlx5_eswitch *esw, 449 + struct mlx5_esw_flow_attr *esw_attr) 450 + { 451 + int i; 452 + 453 + if (!esw->offloads.ft_ipsec_tx_pol) 454 + return true; 455 + 456 + for (i = 0; i < esw_attr->split_count; i++) 457 + if (esw_setup_uplink_fwd_ipsec_needed(esw, esw_attr, i)) 458 + return false; 459 + 460 + for (i = esw_attr->split_count; i < esw_attr->out_count; i++) 461 + if (esw_setup_uplink_fwd_ipsec_needed(esw, esw_attr, i) && 462 + (esw_attr->out_count - esw_attr->split_count > 1)) 463 + return false; 464 + 465 + return true; 466 + } 467 + 427 468 static void 428 - esw_setup_vport_dest(struct mlx5_flow_destination *dest, struct mlx5_flow_act *flow_act, 429 - struct mlx5_eswitch *esw, struct mlx5_esw_flow_attr *esw_attr, 430 - int attr_idx, int dest_idx, bool pkt_reformat) 469 + esw_setup_dest_fwd_vport(struct mlx5_flow_destination *dest, struct mlx5_flow_act *flow_act, 470 + struct mlx5_eswitch *esw, struct mlx5_esw_flow_attr *esw_attr, 471 + int attr_idx, int dest_idx, bool pkt_reformat) 431 472 { 432 473 dest[dest_idx].type = MLX5_FLOW_DESTINATION_TYPE_VPORT; 433 474 dest[dest_idx].vport.num = esw_attr->dests[attr_idx].rep->vport; ··· 488 447 dest[dest_idx].vport.flags |= MLX5_FLOW_DEST_VPORT_REFORMAT_ID; 489 448 dest[dest_idx].vport.pkt_reformat = esw_attr->dests[attr_idx].pkt_reformat; 490 449 } 450 + } 451 + 452 + static void 453 + esw_setup_dest_fwd_ipsec(struct mlx5_flow_destination *dest, struct mlx5_flow_act *flow_act, 454 + struct mlx5_eswitch *esw, struct mlx5_esw_flow_attr *esw_attr, 455 + int attr_idx, int dest_idx, bool pkt_reformat) 456 + { 457 + dest[dest_idx].ft = esw->offloads.ft_ipsec_tx_pol; 458 + dest[dest_idx].type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE; 459 + if (pkt_reformat && 460 + esw_attr->dests[attr_idx].flags & MLX5_ESW_DEST_ENCAP_VALID) { 461 + flow_act->action |= MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT; 462 + flow_act->pkt_reformat = esw_attr->dests[attr_idx].pkt_reformat; 463 + } 464 + } 465 + 466 + static void 467 + esw_setup_vport_dest(struct mlx5_flow_destination *dest, struct mlx5_flow_act *flow_act, 468 + struct mlx5_eswitch *esw, struct mlx5_esw_flow_attr *esw_attr, 469 + int attr_idx, int dest_idx, bool pkt_reformat) 470 + { 471 + if (esw_setup_uplink_fwd_ipsec_needed(esw, esw_attr, attr_idx)) 472 + esw_setup_dest_fwd_ipsec(dest, flow_act, esw, esw_attr, 473 + attr_idx, dest_idx, pkt_reformat); 474 + else 475 + esw_setup_dest_fwd_vport(dest, flow_act, esw, esw_attr, 476 + attr_idx, dest_idx, pkt_reformat); 491 477 } 492 478 493 479 static int ··· 641 573 return ERR_PTR(-EOPNOTSUPP); 642 574 643 575 if (!mlx5_eswitch_vlan_actions_supported(esw->dev, 1)) 576 + return ERR_PTR(-EOPNOTSUPP); 577 + 578 + if (!esw_flow_dests_fwd_ipsec_check(esw, esw_attr)) 644 579 return ERR_PTR(-EOPNOTSUPP); 645 580 646 581 dest = kcalloc(MLX5_MAX_FLOW_FWD_VPORTS + 1, sizeof(*dest), GFP_KERNEL); ··· 954 883 dest.vport.vhca_id = MLX5_CAP_GEN(rep->esw->dev, vhca_id); 955 884 dest.vport.flags |= MLX5_FLOW_DEST_VPORT_VHCA_ID; 956 885 flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST; 886 + 887 + if (rep->vport == MLX5_VPORT_UPLINK && on_esw->offloads.ft_ipsec_tx_pol) { 888 + dest.ft = on_esw->offloads.ft_ipsec_tx_pol; 889 + flow_act.flags = FLOW_ACT_IGNORE_FLOW_LEVEL; 890 + dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE; 891 + } else { 892 + dest.type = MLX5_FLOW_DESTINATION_TYPE_VPORT; 893 + dest.vport.num = rep->vport; 894 + dest.vport.vhca_id = MLX5_CAP_GEN(rep->esw->dev, vhca_id); 895 + dest.vport.flags |= MLX5_FLOW_DEST_VPORT_VHCA_ID; 896 + } 957 897 958 898 if (MLX5_CAP_ESW_FLOWTABLE(on_esw->dev, flow_source) && 959 899 rep->vport == MLX5_VPORT_UPLINK) ··· 3589 3507 return net_eq(devl_net, netdev_net); 3590 3508 } 3591 3509 3510 + int mlx5_eswitch_block_mode_trylock(struct mlx5_core_dev *dev) 3511 + { 3512 + struct devlink *devlink = priv_to_devlink(dev); 3513 + struct mlx5_eswitch *esw; 3514 + int err; 3515 + 3516 + devl_lock(devlink); 3517 + esw = mlx5_devlink_eswitch_get(devlink); 3518 + if (IS_ERR(esw)) { 3519 + /* Failure means no eswitch => not possible to change eswitch mode */ 3520 + devl_unlock(devlink); 3521 + return 0; 3522 + } 3523 + 3524 + err = mlx5_esw_try_lock(esw); 3525 + if (err < 0) { 3526 + devl_unlock(devlink); 3527 + return err; 3528 + } 3529 + 3530 + return 0; 3531 + } 3532 + 3533 + void mlx5_eswitch_block_mode_unlock(struct mlx5_core_dev *dev, int err) 3534 + { 3535 + struct devlink *devlink = priv_to_devlink(dev); 3536 + struct mlx5_eswitch *esw; 3537 + 3538 + esw = mlx5_devlink_eswitch_get(devlink); 3539 + if (IS_ERR(esw)) 3540 + return; 3541 + 3542 + if (!err) 3543 + esw->offloads.num_block_mode++; 3544 + mlx5_esw_unlock(esw); 3545 + devl_unlock(devlink); 3546 + } 3547 + 3548 + void mlx5_eswitch_unblock_mode_lock(struct mlx5_core_dev *dev) 3549 + { 3550 + struct devlink *devlink = priv_to_devlink(dev); 3551 + struct mlx5_eswitch *esw; 3552 + 3553 + esw = mlx5_devlink_eswitch_get(devlink); 3554 + if (IS_ERR(esw)) 3555 + return; 3556 + 3557 + down_write(&esw->mode_lock); 3558 + } 3559 + 3560 + void mlx5_eswitch_unblock_mode_unlock(struct mlx5_core_dev *dev) 3561 + { 3562 + struct devlink *devlink = priv_to_devlink(dev); 3563 + struct mlx5_eswitch *esw; 3564 + 3565 + esw = mlx5_devlink_eswitch_get(devlink); 3566 + if (IS_ERR(esw)) 3567 + return; 3568 + 3569 + esw->offloads.num_block_mode--; 3570 + up_write(&esw->mode_lock); 3571 + } 3572 + 3592 3573 int mlx5_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode, 3593 3574 struct netlink_ext_ack *extack) 3594 3575 { ··· 3684 3539 3685 3540 if (cur_mlx5_mode == mlx5_mode) 3686 3541 goto unlock; 3542 + 3543 + if (esw->offloads.num_block_mode) { 3544 + NL_SET_ERR_MSG_MOD(extack, 3545 + "Can't change eswitch mode when IPsec SA and/or policies are configured"); 3546 + err = -EOPNOTSUPP; 3547 + goto unlock; 3548 + } 3687 3549 3688 3550 mlx5_eswitch_disable_locked(esw); 3689 3551 if (mode == DEVLINK_ESWITCH_MODE_SWITCHDEV) { ··· 4444 4292 out: 4445 4293 mutex_unlock(&esw->state_lock); 4446 4294 return err; 4295 + } 4296 + 4297 + int 4298 + mlx5_eswitch_restore_ipsec_rule(struct mlx5_eswitch *esw, struct mlx5_flow_handle *rule, 4299 + struct mlx5_esw_flow_attr *esw_attr, int attr_idx) 4300 + { 4301 + struct mlx5_flow_destination new_dest = {}; 4302 + struct mlx5_flow_destination old_dest = {}; 4303 + 4304 + if (!esw_setup_uplink_fwd_ipsec_needed(esw, esw_attr, attr_idx)) 4305 + return 0; 4306 + 4307 + esw_setup_dest_fwd_ipsec(&old_dest, NULL, esw, esw_attr, attr_idx, 0, false); 4308 + esw_setup_dest_fwd_vport(&new_dest, NULL, esw, esw_attr, attr_idx, 0, false); 4309 + 4310 + return mlx5_modify_rule_destination(rule, &new_dest, &old_dest); 4447 4311 }
+13 -1
drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
··· 1066 1066 } 1067 1067 1068 1068 for (i = 0; i < handle->num_rules; i++) { 1069 - if (mlx5_flow_dests_cmp(new_dest, &handle->rule[i]->dest_attr)) 1069 + if (mlx5_flow_dests_cmp(old_dest, &handle->rule[i]->dest_attr)) 1070 1070 return _mlx5_modify_rule_destination(handle->rule[i], 1071 1071 new_dest); 1072 1072 } ··· 2987 2987 if (err) 2988 2988 goto out_err; 2989 2989 2990 + maj_prio = fs_create_prio(&steering->fdb_root_ns->ns, FDB_CRYPTO_INGRESS, 3); 2991 + if (IS_ERR(maj_prio)) { 2992 + err = PTR_ERR(maj_prio); 2993 + goto out_err; 2994 + } 2995 + 2990 2996 err = create_fdb_fast_path(steering); 2991 2997 if (err) 2992 2998 goto out_err; ··· 3010 3004 } 3011 3005 3012 3006 maj_prio = fs_create_prio(&steering->fdb_root_ns->ns, FDB_SLOW_PATH, 1); 3007 + if (IS_ERR(maj_prio)) { 3008 + err = PTR_ERR(maj_prio); 3009 + goto out_err; 3010 + } 3011 + 3012 + maj_prio = fs_create_prio(&steering->fdb_root_ns->ns, FDB_CRYPTO_EGRESS, 3); 3013 3013 if (IS_ERR(maj_prio)) { 3014 3014 err = PTR_ERR(maj_prio); 3015 3015 goto out_err;
+2
include/linux/mlx5/driver.h
··· 806 806 u32 vsc_addr; 807 807 struct mlx5_hv_vhca *hv_vhca; 808 808 struct mlx5_thermal *thermal; 809 + u64 num_block_tc; 810 + u64 num_block_ipsec; 809 811 }; 810 812 811 813 struct mlx5_db {
+3
include/linux/mlx5/eswitch.h
··· 144 144 GENMASK(31 - ESW_TUN_ID_BITS - ESW_RESERVED_BITS, \ 145 145 ESW_TUN_OPTS_OFFSET + 1) 146 146 147 + /* reuse tun_opts for the mapped ipsec obj id when tun_id is 0 (invalid) */ 148 + #define ESW_IPSEC_RX_MAPPED_ID_MASK GENMASK(ESW_TUN_OPTS_BITS - 1, 0) 149 + 147 150 u8 mlx5_eswitch_mode(const struct mlx5_core_dev *dev); 148 151 u16 mlx5_eswitch_get_total_vports(const struct mlx5_core_dev *dev); 149 152 struct mlx5_core_dev *mlx5_eswitch_get_core_dev(struct mlx5_eswitch *esw);
+2
include/linux/mlx5/fs.h
··· 109 109 110 110 enum { 111 111 FDB_BYPASS_PATH, 112 + FDB_CRYPTO_INGRESS, 112 113 FDB_TC_OFFLOAD, 113 114 FDB_FT_OFFLOAD, 114 115 FDB_TC_MISS, 115 116 FDB_BR_OFFLOAD, 116 117 FDB_SLOW_PATH, 118 + FDB_CRYPTO_EGRESS, 117 119 FDB_PER_VPORT, 118 120 }; 119 121