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

Merge branch 'mlx5-next' of https://git.kernel.org/pub/scm/linux/kernel/git/mellanox/linux

Leon Romanovsky says:

====================
mlx5-next changes

Following previous conversations [1] and our clear commitment to do
the TC work [2], please pull mlx5-next shared branch, which includes
low-level steering logic to allow RoCEv2 traffic to be encrypted/
decrypted through IPsec.

[1] https://lore.kernel.org/all/20230126230815.224239-1-saeed@kernel.org/
[2] https://lore.kernel.org/all/Y+Z7lVVWqnRBiPh2@nvidia.com/

* 'mlx5-next' of https://git.kernel.org/pub/scm/linux/kernel/git/mellanox/linux:
net/mlx5: Configure IPsec steering for egress RoCEv2 traffic
net/mlx5: Configure IPsec steering for ingress RoCEv2 traffic
net/mlx5: Add IPSec priorities in RDMA namespaces
net/mlx5: Implement new destination type TABLE_TYPE
net/mlx5: Introduce new destination type TABLE_TYPE
====================

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

+511 -15
+1 -1
drivers/net/ethernet/mellanox/mlx5/core/Makefile
··· 97 97 98 98 mlx5_core-$(CONFIG_MLX5_EN_IPSEC) += en_accel/ipsec.o en_accel/ipsec_rxtx.o \ 99 99 en_accel/ipsec_stats.o en_accel/ipsec_fs.o \ 100 - en_accel/ipsec_offload.o 100 + en_accel/ipsec_offload.o lib/ipsec_fs_roce.o 101 101 102 102 mlx5_core-$(CONFIG_MLX5_EN_TLS) += en_accel/ktls_stats.o \ 103 103 en_accel/fs_tcp.o en_accel/ktls.o en_accel/ktls_txrx.o \
+4
drivers/net/ethernet/mellanox/mlx5/core/diag/fs_tracepoint.c
··· 275 275 fs_dest_range_field_to_str(dst->range.field), 276 276 dst->range.min, dst->range.max); 277 277 break; 278 + case MLX5_FLOW_DESTINATION_TYPE_TABLE_TYPE: 279 + trace_seq_printf(p, "flow_table_type=%u id:%u\n", dst->ft->type, 280 + dst->ft->id); 281 + break; 278 282 case MLX5_FLOW_DESTINATION_TYPE_NONE: 279 283 trace_seq_printf(p, "none\n"); 280 284 break;
+1
drivers/net/ethernet/mellanox/mlx5/core/en/fs.h
··· 87 87 MLX5E_ACCEL_FS_POL_FT_LEVEL = MLX5E_INNER_TTC_FT_LEVEL + 1, 88 88 MLX5E_ACCEL_FS_ESP_FT_LEVEL, 89 89 MLX5E_ACCEL_FS_ESP_FT_ERR_LEVEL, 90 + MLX5E_ACCEL_FS_ESP_FT_ROCE_LEVEL, 90 91 #endif 91 92 }; 92 93
+2
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.h
··· 93 93 MLX5_IPSEC_CAP_CRYPTO = 1 << 0, 94 94 MLX5_IPSEC_CAP_ESN = 1 << 1, 95 95 MLX5_IPSEC_CAP_PACKET_OFFLOAD = 1 << 2, 96 + MLX5_IPSEC_CAP_ROCE = 1 << 3, 96 97 }; 97 98 98 99 struct mlx5e_priv; ··· 148 147 struct mlx5e_ipsec_tx *tx; 149 148 struct mlx5e_ipsec_aso *aso; 150 149 struct notifier_block nb; 150 + struct mlx5_ipsec_fs *roce; 151 151 }; 152 152 153 153 struct mlx5e_ipsec_esn_state {
+47 -7
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c
··· 6 6 #include "en/fs.h" 7 7 #include "ipsec.h" 8 8 #include "fs_core.h" 9 + #include "lib/ipsec_fs_roce.h" 9 10 10 11 #define NUM_IPSEC_FTE BIT(15) 11 12 ··· 167 166 return err; 168 167 } 169 168 170 - static void rx_destroy(struct mlx5_core_dev *mdev, struct mlx5e_ipsec_rx *rx) 169 + static void rx_destroy(struct mlx5_core_dev *mdev, struct mlx5e_ipsec *ipsec, 170 + struct mlx5e_ipsec_rx *rx, u32 family) 171 171 { 172 172 mlx5_del_flow_rules(rx->pol.rule); 173 173 mlx5_destroy_flow_group(rx->pol.group); ··· 181 179 mlx5_del_flow_rules(rx->status.rule); 182 180 mlx5_modify_header_dealloc(mdev, rx->status.modify_hdr); 183 181 mlx5_destroy_flow_table(rx->ft.status); 182 + 183 + mlx5_ipsec_fs_roce_rx_destroy(ipsec->roce, family); 184 184 } 185 185 186 186 static int rx_create(struct mlx5_core_dev *mdev, struct mlx5e_ipsec *ipsec, ··· 190 186 { 191 187 struct mlx5_flow_namespace *ns = mlx5e_fs_get_ns(ipsec->fs, false); 192 188 struct mlx5_ttc_table *ttc = mlx5e_fs_get_ttc(ipsec->fs, false); 189 + struct mlx5_flow_destination default_dest; 193 190 struct mlx5_flow_destination dest[2]; 194 191 struct mlx5_flow_table *ft; 195 192 int err; 196 193 194 + default_dest = mlx5_ttc_get_default_dest(ttc, family2tt(family)); 195 + err = mlx5_ipsec_fs_roce_rx_create(mdev, ipsec->roce, ns, &default_dest, 196 + family, MLX5E_ACCEL_FS_ESP_FT_ROCE_LEVEL, 197 + MLX5E_NIC_PRIO); 198 + if (err) 199 + return err; 200 + 197 201 ft = ipsec_ft_create(ns, MLX5E_ACCEL_FS_ESP_FT_ERR_LEVEL, 198 202 MLX5E_NIC_PRIO, 1); 199 - if (IS_ERR(ft)) 200 - return PTR_ERR(ft); 203 + if (IS_ERR(ft)) { 204 + err = PTR_ERR(ft); 205 + goto err_fs_ft_status; 206 + } 201 207 202 208 rx->ft.status = ft; 203 209 204 - dest[0] = mlx5_ttc_get_default_dest(ttc, family2tt(family)); 210 + ft = mlx5_ipsec_fs_roce_ft_get(ipsec->roce, family); 211 + if (ft) { 212 + dest[0].type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE; 213 + dest[0].ft = ft; 214 + } else { 215 + dest[0] = default_dest; 216 + } 217 + 205 218 dest[1].type = MLX5_FLOW_DESTINATION_TYPE_COUNTER; 206 219 dest[1].counter_id = mlx5_fc_id(rx->fc->cnt); 207 220 err = ipsec_status_rule(mdev, rx, dest); ··· 266 245 mlx5_modify_header_dealloc(mdev, rx->status.modify_hdr); 267 246 err_add: 268 247 mlx5_destroy_flow_table(rx->ft.status); 248 + err_fs_ft_status: 249 + mlx5_ipsec_fs_roce_rx_destroy(ipsec->roce, family); 269 250 return err; 270 251 } 271 252 ··· 327 304 mlx5_ttc_fwd_default_dest(ttc, family2tt(family)); 328 305 329 306 /* remove FT */ 330 - rx_destroy(mdev, rx); 307 + rx_destroy(mdev, ipsec, rx, family); 331 308 332 309 out: 333 310 mutex_unlock(&rx->ft.mutex); 334 311 } 335 312 336 313 /* IPsec TX flow steering */ 337 - static int tx_create(struct mlx5_core_dev *mdev, struct mlx5e_ipsec_tx *tx) 314 + static int tx_create(struct mlx5_core_dev *mdev, struct mlx5e_ipsec_tx *tx, 315 + struct mlx5_ipsec_fs *roce) 338 316 { 339 317 struct mlx5_flow_destination dest = {}; 340 318 struct mlx5_flow_table *ft; ··· 358 334 err = ipsec_miss_create(mdev, tx->ft.pol, &tx->pol, &dest); 359 335 if (err) 360 336 goto err_pol_miss; 337 + 338 + err = mlx5_ipsec_fs_roce_tx_create(mdev, roce, tx->ft.pol); 339 + if (err) 340 + goto err_roce; 361 341 return 0; 362 342 343 + err_roce: 344 + mlx5_del_flow_rules(tx->pol.rule); 345 + mlx5_destroy_flow_group(tx->pol.group); 363 346 err_pol_miss: 364 347 mlx5_destroy_flow_table(tx->ft.pol); 365 348 err_pol_ft: ··· 384 353 if (tx->ft.refcnt) 385 354 goto skip; 386 355 387 - err = tx_create(mdev, tx); 356 + err = tx_create(mdev, tx, ipsec->roce); 388 357 if (err) 389 358 goto out; 359 + 390 360 skip: 391 361 tx->ft.refcnt++; 392 362 out: ··· 406 374 if (tx->ft.refcnt) 407 375 goto out; 408 376 377 + mlx5_ipsec_fs_roce_tx_destroy(ipsec->roce); 409 378 mlx5_del_flow_rules(tx->pol.rule); 410 379 mlx5_destroy_flow_group(tx->pol.group); 411 380 mlx5_destroy_flow_table(tx->ft.pol); ··· 1064 1031 if (!ipsec->tx) 1065 1032 return; 1066 1033 1034 + if (mlx5_ipsec_device_caps(ipsec->mdev) & MLX5_IPSEC_CAP_ROCE) 1035 + mlx5_ipsec_fs_roce_cleanup(ipsec->roce); 1036 + 1067 1037 ipsec_fs_destroy_counters(ipsec); 1068 1038 mutex_destroy(&ipsec->tx->ft.mutex); 1069 1039 WARN_ON(ipsec->tx->ft.refcnt); ··· 1083 1047 1084 1048 int mlx5e_accel_ipsec_fs_init(struct mlx5e_ipsec *ipsec) 1085 1049 { 1050 + struct mlx5_core_dev *mdev = ipsec->mdev; 1086 1051 struct mlx5_flow_namespace *ns; 1087 1052 int err = -ENOMEM; 1088 1053 ··· 1112 1075 mutex_init(&ipsec->rx_ipv4->ft.mutex); 1113 1076 mutex_init(&ipsec->rx_ipv6->ft.mutex); 1114 1077 ipsec->tx->ns = ns; 1078 + 1079 + if (mlx5_ipsec_device_caps(mdev) & MLX5_IPSEC_CAP_ROCE) 1080 + ipsec->roce = mlx5_ipsec_fs_roce_init(mdev); 1115 1081 1116 1082 return 0; 1117 1083
+5
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_offload.c
··· 42 42 MLX5_CAP_FLOWTABLE_NIC_RX(mdev, decap)) 43 43 caps |= MLX5_IPSEC_CAP_PACKET_OFFLOAD; 44 44 45 + if (mlx5_get_roce_state(mdev) && 46 + MLX5_CAP_GEN_2(mdev, flow_table_type_2_type) & MLX5_FT_NIC_RX_2_NIC_RX_RDMA && 47 + MLX5_CAP_GEN_2(mdev, flow_table_type_2_type) & MLX5_FT_NIC_TX_RDMA_2_NIC_TX) 48 + caps |= MLX5_IPSEC_CAP_ROCE; 49 + 45 50 if (!caps) 46 51 return 0; 47 52
+6
drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c
··· 646 646 id = dst->dest_attr.sampler_id; 647 647 ifc_type = MLX5_IFC_FLOW_DESTINATION_TYPE_FLOW_SAMPLER; 648 648 break; 649 + case MLX5_FLOW_DESTINATION_TYPE_TABLE_TYPE: 650 + MLX5_SET(dest_format_struct, in_dests, 651 + destination_table_type, dst->dest_attr.ft->type); 652 + id = dst->dest_attr.ft->id; 653 + ifc_type = MLX5_IFC_FLOW_DESTINATION_TYPE_TABLE_TYPE; 654 + break; 649 655 default: 650 656 id = dst->dest_attr.tir_num; 651 657 ifc_type = MLX5_IFC_FLOW_DESTINATION_TYPE_TIR;
+39 -5
drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
··· 113 113 #define ETHTOOL_PRIO_NUM_LEVELS 1 114 114 #define ETHTOOL_NUM_PRIOS 11 115 115 #define ETHTOOL_MIN_LEVEL (KERNEL_MIN_LEVEL + ETHTOOL_NUM_PRIOS) 116 - /* Promiscuous, Vlan, mac, ttc, inner ttc, {UDP/ANY/aRFS/accel/{esp, esp_err}}, IPsec policy */ 117 - #define KERNEL_NIC_PRIO_NUM_LEVELS 8 116 + /* Promiscuous, Vlan, mac, ttc, inner ttc, {UDP/ANY/aRFS/accel/{esp, esp_err}}, IPsec policy, 117 + * IPsec RoCE policy 118 + */ 119 + #define KERNEL_NIC_PRIO_NUM_LEVELS 9 118 120 #define KERNEL_NIC_NUM_PRIOS 1 119 121 /* One more level for tc */ 120 122 #define KERNEL_MIN_LEVEL (KERNEL_NIC_PRIO_NUM_LEVELS + 1) ··· 223 221 }; 224 222 225 223 enum { 224 + RDMA_RX_IPSEC_PRIO, 226 225 RDMA_RX_COUNTERS_PRIO, 227 226 RDMA_RX_BYPASS_PRIO, 228 227 RDMA_RX_KERNEL_PRIO, 229 228 }; 229 + 230 + #define RDMA_RX_IPSEC_NUM_PRIOS 1 231 + #define RDMA_RX_IPSEC_NUM_LEVELS 2 232 + #define RDMA_RX_IPSEC_MIN_LEVEL (RDMA_RX_IPSEC_NUM_LEVELS) 230 233 231 234 #define RDMA_RX_BYPASS_MIN_LEVEL MLX5_BY_PASS_NUM_REGULAR_PRIOS 232 235 #define RDMA_RX_KERNEL_MIN_LEVEL (RDMA_RX_BYPASS_MIN_LEVEL + 1) ··· 239 232 240 233 static struct init_tree_node rdma_rx_root_fs = { 241 234 .type = FS_TYPE_NAMESPACE, 242 - .ar_size = 3, 235 + .ar_size = 4, 243 236 .children = (struct init_tree_node[]) { 237 + [RDMA_RX_IPSEC_PRIO] = 238 + ADD_PRIO(0, RDMA_RX_IPSEC_MIN_LEVEL, 0, 239 + FS_CHAINING_CAPS, 240 + ADD_NS(MLX5_FLOW_TABLE_MISS_ACTION_DEF, 241 + ADD_MULTIPLE_PRIO(RDMA_RX_IPSEC_NUM_PRIOS, 242 + RDMA_RX_IPSEC_NUM_LEVELS))), 244 243 [RDMA_RX_COUNTERS_PRIO] = 245 244 ADD_PRIO(0, RDMA_RX_COUNTERS_MIN_LEVEL, 0, 246 245 FS_CHAINING_CAPS, ··· 269 256 270 257 enum { 271 258 RDMA_TX_COUNTERS_PRIO, 259 + RDMA_TX_IPSEC_PRIO, 272 260 RDMA_TX_BYPASS_PRIO, 273 261 }; 274 262 275 263 #define RDMA_TX_BYPASS_MIN_LEVEL MLX5_BY_PASS_NUM_PRIOS 276 264 #define RDMA_TX_COUNTERS_MIN_LEVEL (RDMA_TX_BYPASS_MIN_LEVEL + 1) 277 265 266 + #define RDMA_TX_IPSEC_NUM_PRIOS 1 267 + #define RDMA_TX_IPSEC_PRIO_NUM_LEVELS 1 268 + #define RDMA_TX_IPSEC_MIN_LEVEL (RDMA_TX_COUNTERS_MIN_LEVEL + RDMA_TX_IPSEC_NUM_PRIOS) 269 + 278 270 static struct init_tree_node rdma_tx_root_fs = { 279 271 .type = FS_TYPE_NAMESPACE, 280 - .ar_size = 2, 272 + .ar_size = 3, 281 273 .children = (struct init_tree_node[]) { 282 274 [RDMA_TX_COUNTERS_PRIO] = 283 275 ADD_PRIO(0, RDMA_TX_COUNTERS_MIN_LEVEL, 0, ··· 290 272 ADD_NS(MLX5_FLOW_TABLE_MISS_ACTION_DEF, 291 273 ADD_MULTIPLE_PRIO(MLX5_RDMA_TX_NUM_COUNTERS_PRIOS, 292 274 RDMA_TX_COUNTERS_PRIO_NUM_LEVELS))), 275 + [RDMA_TX_IPSEC_PRIO] = 276 + ADD_PRIO(0, RDMA_TX_IPSEC_MIN_LEVEL, 0, 277 + FS_CHAINING_CAPS, 278 + ADD_NS(MLX5_FLOW_TABLE_MISS_ACTION_DEF, 279 + ADD_MULTIPLE_PRIO(RDMA_TX_IPSEC_NUM_PRIOS, 280 + RDMA_TX_IPSEC_PRIO_NUM_LEVELS))), 281 + 293 282 [RDMA_TX_BYPASS_PRIO] = 294 283 ADD_PRIO(0, RDMA_TX_BYPASS_MIN_LEVEL, 0, 295 284 FS_CHAINING_CAPS_RDMA_TX, ··· 476 451 type == MLX5_FLOW_DESTINATION_TYPE_VPORT || 477 452 type == MLX5_FLOW_DESTINATION_TYPE_FLOW_SAMPLER || 478 453 type == MLX5_FLOW_DESTINATION_TYPE_TIR || 479 - type == MLX5_FLOW_DESTINATION_TYPE_RANGE; 454 + type == MLX5_FLOW_DESTINATION_TYPE_RANGE || 455 + type == MLX5_FLOW_DESTINATION_TYPE_TABLE_TYPE; 480 456 } 481 457 482 458 static bool check_valid_spec(const struct mlx5_flow_spec *spec) ··· 2393 2367 case MLX5_FLOW_NAMESPACE_RDMA_TX_COUNTERS: 2394 2368 root_ns = steering->rdma_tx_root_ns; 2395 2369 prio = RDMA_TX_COUNTERS_PRIO; 2370 + break; 2371 + case MLX5_FLOW_NAMESPACE_RDMA_RX_IPSEC: 2372 + root_ns = steering->rdma_rx_root_ns; 2373 + prio = RDMA_RX_IPSEC_PRIO; 2374 + break; 2375 + case MLX5_FLOW_NAMESPACE_RDMA_TX_IPSEC: 2376 + root_ns = steering->rdma_tx_root_ns; 2377 + prio = RDMA_TX_IPSEC_PRIO; 2396 2378 break; 2397 2379 default: /* Must be NIC RX */ 2398 2380 WARN_ON(!is_nic_rx_ns(type));
+368
drivers/net/ethernet/mellanox/mlx5/core/lib/ipsec_fs_roce.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB 2 + /* Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved. */ 3 + 4 + #include "fs_core.h" 5 + #include "lib/ipsec_fs_roce.h" 6 + #include "mlx5_core.h" 7 + 8 + struct mlx5_ipsec_miss { 9 + struct mlx5_flow_group *group; 10 + struct mlx5_flow_handle *rule; 11 + }; 12 + 13 + struct mlx5_ipsec_rx_roce { 14 + struct mlx5_flow_group *g; 15 + struct mlx5_flow_table *ft; 16 + struct mlx5_flow_handle *rule; 17 + struct mlx5_ipsec_miss roce_miss; 18 + 19 + struct mlx5_flow_table *ft_rdma; 20 + struct mlx5_flow_namespace *ns_rdma; 21 + }; 22 + 23 + struct mlx5_ipsec_tx_roce { 24 + struct mlx5_flow_group *g; 25 + struct mlx5_flow_table *ft; 26 + struct mlx5_flow_handle *rule; 27 + struct mlx5_flow_namespace *ns; 28 + }; 29 + 30 + struct mlx5_ipsec_fs { 31 + struct mlx5_ipsec_rx_roce ipv4_rx; 32 + struct mlx5_ipsec_rx_roce ipv6_rx; 33 + struct mlx5_ipsec_tx_roce tx; 34 + }; 35 + 36 + static void ipsec_fs_roce_setup_udp_dport(struct mlx5_flow_spec *spec, 37 + u16 dport) 38 + { 39 + spec->match_criteria_enable |= MLX5_MATCH_OUTER_HEADERS; 40 + MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, outer_headers.ip_protocol); 41 + MLX5_SET(fte_match_param, spec->match_value, outer_headers.ip_protocol, IPPROTO_UDP); 42 + MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, outer_headers.udp_dport); 43 + MLX5_SET(fte_match_param, spec->match_value, outer_headers.udp_dport, dport); 44 + } 45 + 46 + static int 47 + ipsec_fs_roce_rx_rule_setup(struct mlx5_core_dev *mdev, 48 + struct mlx5_flow_destination *default_dst, 49 + struct mlx5_ipsec_rx_roce *roce) 50 + { 51 + struct mlx5_flow_destination dst = {}; 52 + MLX5_DECLARE_FLOW_ACT(flow_act); 53 + struct mlx5_flow_handle *rule; 54 + struct mlx5_flow_spec *spec; 55 + int err = 0; 56 + 57 + spec = kvzalloc(sizeof(*spec), GFP_KERNEL); 58 + if (!spec) 59 + return -ENOMEM; 60 + 61 + ipsec_fs_roce_setup_udp_dport(spec, ROCE_V2_UDP_DPORT); 62 + 63 + flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST; 64 + dst.type = MLX5_FLOW_DESTINATION_TYPE_TABLE_TYPE; 65 + dst.ft = roce->ft_rdma; 66 + rule = mlx5_add_flow_rules(roce->ft, spec, &flow_act, &dst, 1); 67 + if (IS_ERR(rule)) { 68 + err = PTR_ERR(rule); 69 + mlx5_core_err(mdev, "Fail to add RX RoCE IPsec rule err=%d\n", 70 + err); 71 + goto fail_add_rule; 72 + } 73 + 74 + roce->rule = rule; 75 + 76 + memset(spec, 0, sizeof(*spec)); 77 + rule = mlx5_add_flow_rules(roce->ft, spec, &flow_act, default_dst, 1); 78 + if (IS_ERR(rule)) { 79 + err = PTR_ERR(rule); 80 + mlx5_core_err(mdev, "Fail to add RX RoCE IPsec miss rule err=%d\n", 81 + err); 82 + goto fail_add_default_rule; 83 + } 84 + 85 + roce->roce_miss.rule = rule; 86 + 87 + kvfree(spec); 88 + return 0; 89 + 90 + fail_add_default_rule: 91 + mlx5_del_flow_rules(roce->rule); 92 + fail_add_rule: 93 + kvfree(spec); 94 + return err; 95 + } 96 + 97 + static int ipsec_fs_roce_tx_rule_setup(struct mlx5_core_dev *mdev, 98 + struct mlx5_ipsec_tx_roce *roce, 99 + struct mlx5_flow_table *pol_ft) 100 + { 101 + struct mlx5_flow_destination dst = {}; 102 + MLX5_DECLARE_FLOW_ACT(flow_act); 103 + struct mlx5_flow_handle *rule; 104 + int err = 0; 105 + 106 + flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST; 107 + dst.type = MLX5_FLOW_DESTINATION_TYPE_TABLE_TYPE; 108 + dst.ft = pol_ft; 109 + rule = mlx5_add_flow_rules(roce->ft, NULL, &flow_act, &dst, 110 + 1); 111 + if (IS_ERR(rule)) { 112 + err = PTR_ERR(rule); 113 + mlx5_core_err(mdev, "Fail to add TX RoCE IPsec rule err=%d\n", 114 + err); 115 + goto out; 116 + } 117 + roce->rule = rule; 118 + 119 + out: 120 + return err; 121 + } 122 + 123 + void mlx5_ipsec_fs_roce_tx_destroy(struct mlx5_ipsec_fs *ipsec_roce) 124 + { 125 + struct mlx5_ipsec_tx_roce *tx_roce; 126 + 127 + if (!ipsec_roce) 128 + return; 129 + 130 + tx_roce = &ipsec_roce->tx; 131 + 132 + mlx5_del_flow_rules(tx_roce->rule); 133 + mlx5_destroy_flow_group(tx_roce->g); 134 + mlx5_destroy_flow_table(tx_roce->ft); 135 + } 136 + 137 + #define MLX5_TX_ROCE_GROUP_SIZE BIT(0) 138 + 139 + int mlx5_ipsec_fs_roce_tx_create(struct mlx5_core_dev *mdev, 140 + struct mlx5_ipsec_fs *ipsec_roce, 141 + struct mlx5_flow_table *pol_ft) 142 + { 143 + struct mlx5_flow_table_attr ft_attr = {}; 144 + struct mlx5_ipsec_tx_roce *roce; 145 + struct mlx5_flow_table *ft; 146 + struct mlx5_flow_group *g; 147 + int ix = 0; 148 + int err; 149 + u32 *in; 150 + 151 + if (!ipsec_roce) 152 + return 0; 153 + 154 + roce = &ipsec_roce->tx; 155 + 156 + in = kvzalloc(MLX5_ST_SZ_BYTES(create_flow_group_in), GFP_KERNEL); 157 + if (!in) 158 + return -ENOMEM; 159 + 160 + ft_attr.max_fte = 1; 161 + ft = mlx5_create_flow_table(roce->ns, &ft_attr); 162 + if (IS_ERR(ft)) { 163 + err = PTR_ERR(ft); 164 + mlx5_core_err(mdev, "Fail to create RoCE IPsec tx ft err=%d\n", err); 165 + return err; 166 + } 167 + 168 + roce->ft = ft; 169 + 170 + MLX5_SET_CFG(in, start_flow_index, ix); 171 + ix += MLX5_TX_ROCE_GROUP_SIZE; 172 + MLX5_SET_CFG(in, end_flow_index, ix - 1); 173 + g = mlx5_create_flow_group(ft, in); 174 + if (IS_ERR(g)) { 175 + err = PTR_ERR(g); 176 + mlx5_core_err(mdev, "Fail to create RoCE IPsec tx group err=%d\n", err); 177 + goto fail; 178 + } 179 + roce->g = g; 180 + 181 + err = ipsec_fs_roce_tx_rule_setup(mdev, roce, pol_ft); 182 + if (err) { 183 + mlx5_core_err(mdev, "Fail to create RoCE IPsec tx rules err=%d\n", err); 184 + goto rule_fail; 185 + } 186 + 187 + return 0; 188 + 189 + rule_fail: 190 + mlx5_destroy_flow_group(roce->g); 191 + fail: 192 + mlx5_destroy_flow_table(ft); 193 + return err; 194 + } 195 + 196 + struct mlx5_flow_table *mlx5_ipsec_fs_roce_ft_get(struct mlx5_ipsec_fs *ipsec_roce, u32 family) 197 + { 198 + struct mlx5_ipsec_rx_roce *rx_roce; 199 + 200 + if (!ipsec_roce) 201 + return NULL; 202 + 203 + rx_roce = (family == AF_INET) ? &ipsec_roce->ipv4_rx : 204 + &ipsec_roce->ipv6_rx; 205 + 206 + return rx_roce->ft; 207 + } 208 + 209 + void mlx5_ipsec_fs_roce_rx_destroy(struct mlx5_ipsec_fs *ipsec_roce, u32 family) 210 + { 211 + struct mlx5_ipsec_rx_roce *rx_roce; 212 + 213 + if (!ipsec_roce) 214 + return; 215 + 216 + rx_roce = (family == AF_INET) ? &ipsec_roce->ipv4_rx : 217 + &ipsec_roce->ipv6_rx; 218 + 219 + mlx5_del_flow_rules(rx_roce->roce_miss.rule); 220 + mlx5_del_flow_rules(rx_roce->rule); 221 + mlx5_destroy_flow_table(rx_roce->ft_rdma); 222 + mlx5_destroy_flow_group(rx_roce->roce_miss.group); 223 + mlx5_destroy_flow_group(rx_roce->g); 224 + mlx5_destroy_flow_table(rx_roce->ft); 225 + } 226 + 227 + #define MLX5_RX_ROCE_GROUP_SIZE BIT(0) 228 + 229 + int mlx5_ipsec_fs_roce_rx_create(struct mlx5_core_dev *mdev, 230 + struct mlx5_ipsec_fs *ipsec_roce, 231 + struct mlx5_flow_namespace *ns, 232 + struct mlx5_flow_destination *default_dst, 233 + u32 family, u32 level, u32 prio) 234 + { 235 + struct mlx5_flow_table_attr ft_attr = {}; 236 + struct mlx5_ipsec_rx_roce *roce; 237 + struct mlx5_flow_table *ft; 238 + struct mlx5_flow_group *g; 239 + void *outer_headers_c; 240 + int ix = 0; 241 + u32 *in; 242 + int err; 243 + u8 *mc; 244 + 245 + if (!ipsec_roce) 246 + return 0; 247 + 248 + roce = (family == AF_INET) ? &ipsec_roce->ipv4_rx : 249 + &ipsec_roce->ipv6_rx; 250 + 251 + ft_attr.max_fte = 2; 252 + ft_attr.level = level; 253 + ft_attr.prio = prio; 254 + ft = mlx5_create_flow_table(ns, &ft_attr); 255 + if (IS_ERR(ft)) { 256 + err = PTR_ERR(ft); 257 + mlx5_core_err(mdev, "Fail to create RoCE IPsec rx ft at nic err=%d\n", err); 258 + return err; 259 + } 260 + 261 + roce->ft = ft; 262 + 263 + in = kvzalloc(MLX5_ST_SZ_BYTES(create_flow_group_in), GFP_KERNEL); 264 + if (!in) { 265 + err = -ENOMEM; 266 + goto fail_nomem; 267 + } 268 + 269 + mc = MLX5_ADDR_OF(create_flow_group_in, in, match_criteria); 270 + outer_headers_c = MLX5_ADDR_OF(fte_match_param, mc, outer_headers); 271 + MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, outer_headers_c, ip_protocol); 272 + MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, outer_headers_c, udp_dport); 273 + 274 + MLX5_SET_CFG(in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS); 275 + MLX5_SET_CFG(in, start_flow_index, ix); 276 + ix += MLX5_RX_ROCE_GROUP_SIZE; 277 + MLX5_SET_CFG(in, end_flow_index, ix - 1); 278 + g = mlx5_create_flow_group(ft, in); 279 + if (IS_ERR(g)) { 280 + err = PTR_ERR(g); 281 + mlx5_core_err(mdev, "Fail to create RoCE IPsec rx group at nic err=%d\n", err); 282 + goto fail_group; 283 + } 284 + roce->g = g; 285 + 286 + memset(in, 0, MLX5_ST_SZ_BYTES(create_flow_group_in)); 287 + MLX5_SET_CFG(in, start_flow_index, ix); 288 + ix += MLX5_RX_ROCE_GROUP_SIZE; 289 + MLX5_SET_CFG(in, end_flow_index, ix - 1); 290 + g = mlx5_create_flow_group(ft, in); 291 + if (IS_ERR(g)) { 292 + err = PTR_ERR(g); 293 + mlx5_core_err(mdev, "Fail to create RoCE IPsec rx miss group at nic err=%d\n", err); 294 + goto fail_mgroup; 295 + } 296 + roce->roce_miss.group = g; 297 + 298 + memset(&ft_attr, 0, sizeof(ft_attr)); 299 + if (family == AF_INET) 300 + ft_attr.level = 1; 301 + ft = mlx5_create_flow_table(roce->ns_rdma, &ft_attr); 302 + if (IS_ERR(ft)) { 303 + err = PTR_ERR(ft); 304 + mlx5_core_err(mdev, "Fail to create RoCE IPsec rx ft at rdma err=%d\n", err); 305 + goto fail_rdma_table; 306 + } 307 + 308 + roce->ft_rdma = ft; 309 + 310 + err = ipsec_fs_roce_rx_rule_setup(mdev, default_dst, roce); 311 + if (err) { 312 + mlx5_core_err(mdev, "Fail to create RoCE IPsec rx rules err=%d\n", err); 313 + goto fail_setup_rule; 314 + } 315 + 316 + kvfree(in); 317 + return 0; 318 + 319 + fail_setup_rule: 320 + mlx5_destroy_flow_table(roce->ft_rdma); 321 + fail_rdma_table: 322 + mlx5_destroy_flow_group(roce->roce_miss.group); 323 + fail_mgroup: 324 + mlx5_destroy_flow_group(roce->g); 325 + fail_group: 326 + kvfree(in); 327 + fail_nomem: 328 + mlx5_destroy_flow_table(roce->ft); 329 + return err; 330 + } 331 + 332 + void mlx5_ipsec_fs_roce_cleanup(struct mlx5_ipsec_fs *ipsec_roce) 333 + { 334 + kfree(ipsec_roce); 335 + } 336 + 337 + struct mlx5_ipsec_fs *mlx5_ipsec_fs_roce_init(struct mlx5_core_dev *mdev) 338 + { 339 + struct mlx5_ipsec_fs *roce_ipsec; 340 + struct mlx5_flow_namespace *ns; 341 + 342 + ns = mlx5_get_flow_namespace(mdev, MLX5_FLOW_NAMESPACE_RDMA_RX_IPSEC); 343 + if (!ns) { 344 + mlx5_core_err(mdev, "Failed to get RoCE rx ns\n"); 345 + return NULL; 346 + } 347 + 348 + roce_ipsec = kzalloc(sizeof(*roce_ipsec), GFP_KERNEL); 349 + if (!roce_ipsec) 350 + return NULL; 351 + 352 + roce_ipsec->ipv4_rx.ns_rdma = ns; 353 + roce_ipsec->ipv6_rx.ns_rdma = ns; 354 + 355 + ns = mlx5_get_flow_namespace(mdev, MLX5_FLOW_NAMESPACE_RDMA_TX_IPSEC); 356 + if (!ns) { 357 + mlx5_core_err(mdev, "Failed to get RoCE tx ns\n"); 358 + goto err_tx; 359 + } 360 + 361 + roce_ipsec->tx.ns = ns; 362 + 363 + return roce_ipsec; 364 + 365 + err_tx: 366 + kfree(roce_ipsec); 367 + return NULL; 368 + }
+25
drivers/net/ethernet/mellanox/mlx5/core/lib/ipsec_fs_roce.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ 2 + /* Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved. */ 3 + 4 + #ifndef __MLX5_LIB_IPSEC_H__ 5 + #define __MLX5_LIB_IPSEC_H__ 6 + 7 + struct mlx5_ipsec_fs; 8 + 9 + struct mlx5_flow_table * 10 + mlx5_ipsec_fs_roce_ft_get(struct mlx5_ipsec_fs *ipsec_roce, u32 family); 11 + void mlx5_ipsec_fs_roce_rx_destroy(struct mlx5_ipsec_fs *ipsec_roce, 12 + u32 family); 13 + int mlx5_ipsec_fs_roce_rx_create(struct mlx5_core_dev *mdev, 14 + struct mlx5_ipsec_fs *ipsec_roce, 15 + struct mlx5_flow_namespace *ns, 16 + struct mlx5_flow_destination *default_dst, 17 + u32 family, u32 level, u32 prio); 18 + void mlx5_ipsec_fs_roce_tx_destroy(struct mlx5_ipsec_fs *ipsec_roce); 19 + int mlx5_ipsec_fs_roce_tx_create(struct mlx5_core_dev *mdev, 20 + struct mlx5_ipsec_fs *ipsec_roce, 21 + struct mlx5_flow_table *pol_ft); 22 + void mlx5_ipsec_fs_roce_cleanup(struct mlx5_ipsec_fs *ipsec_roce); 23 + struct mlx5_ipsec_fs *mlx5_ipsec_fs_roce_init(struct mlx5_core_dev *mdev); 24 + 25 + #endif /* __MLX5_LIB_IPSEC_H__ */
+3
include/linux/mlx5/fs.h
··· 51 51 MLX5_FLOW_DESTINATION_TYPE_COUNTER, 52 52 MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE_NUM, 53 53 MLX5_FLOW_DESTINATION_TYPE_RANGE, 54 + MLX5_FLOW_DESTINATION_TYPE_TABLE_TYPE, 54 55 }; 55 56 56 57 enum { ··· 103 102 MLX5_FLOW_NAMESPACE_PORT_SEL, 104 103 MLX5_FLOW_NAMESPACE_RDMA_RX_COUNTERS, 105 104 MLX5_FLOW_NAMESPACE_RDMA_TX_COUNTERS, 105 + MLX5_FLOW_NAMESPACE_RDMA_RX_IPSEC, 106 + MLX5_FLOW_NAMESPACE_RDMA_TX_IPSEC, 106 107 }; 107 108 108 109 enum {
+10 -2
include/linux/mlx5/mlx5_ifc.h
··· 316 316 MLX5_CMD_OP_GENERAL_END = 0xd00, 317 317 }; 318 318 319 + enum { 320 + MLX5_FT_NIC_RX_2_NIC_RX_RDMA = BIT(0), 321 + MLX5_FT_NIC_TX_RDMA_2_NIC_TX = BIT(1), 322 + }; 323 + 319 324 struct mlx5_ifc_flow_table_fields_supported_bits { 320 325 u8 outer_dmac[0x1]; 321 326 u8 outer_smac[0x1]; ··· 1934 1929 1935 1930 u8 reserved_at_e0[0xc0]; 1936 1931 1937 - u8 reserved_at_1a0[0xb]; 1932 + u8 flow_table_type_2_type[0x8]; 1933 + u8 reserved_at_1a8[0x3]; 1938 1934 u8 log_min_mkey_entity_size[0x5]; 1939 1935 u8 reserved_at_1b0[0x10]; 1940 1936 ··· 1959 1953 MLX5_IFC_FLOW_DESTINATION_TYPE_TIR = 0x2, 1960 1954 MLX5_IFC_FLOW_DESTINATION_TYPE_FLOW_SAMPLER = 0x6, 1961 1955 MLX5_IFC_FLOW_DESTINATION_TYPE_UPLINK = 0x8, 1956 + MLX5_IFC_FLOW_DESTINATION_TYPE_TABLE_TYPE = 0xA, 1962 1957 }; 1963 1958 1964 1959 enum mlx5_flow_table_miss_action { ··· 1974 1967 1975 1968 u8 destination_eswitch_owner_vhca_id_valid[0x1]; 1976 1969 u8 packet_reformat[0x1]; 1977 - u8 reserved_at_22[0xe]; 1970 + u8 reserved_at_22[0x6]; 1971 + u8 destination_table_type[0x8]; 1978 1972 u8 destination_eswitch_owner_vhca_id[0x10]; 1979 1973 }; 1980 1974