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

net/mlx5: Configure MACsec steering for ingress RoCEv2 traffic

Add steering tables/rules to check if the decrypted traffic is RoCEv2,
if so copy reg_b_metadata to a temp reg and forward it to RDMA_RX domain.
The rules are added once the MACsec device is assigned an IP address
where we verify that the packet ip is for MACsec device and that the temp
reg has MACsec operation and a valid SCI inside.

Signed-off-by: Patrisious Haddad <phaddad@nvidia.com>
Signed-off-by: Leon Romanovsky <leonro@nvidia.com>

authored by

Patrisious Haddad and committed by
Leon Romanovsky
8c14a2c7 9b240d10

+352 -9
+1 -1
drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
··· 107 107 LEFTOVERS_NUM_PRIOS) 108 108 109 109 #define KERNEL_RX_MACSEC_NUM_PRIOS 1 110 - #define KERNEL_RX_MACSEC_NUM_LEVELS 2 110 + #define KERNEL_RX_MACSEC_NUM_LEVELS 3 111 111 #define KERNEL_RX_MACSEC_MIN_LEVEL (BY_PASS_MIN_LEVEL + KERNEL_RX_MACSEC_NUM_PRIOS) 112 112 113 113 #define ETHTOOL_PRIO_NUM_LEVELS 1
+351 -8
drivers/net/ethernet/mellanox/mlx5/core/lib/macsec_fs.c
··· 22 22 #define TX_CHECK_TABLE_NUM_FTE 2 23 23 #define RX_CRYPTO_TABLE_LEVEL 0 24 24 #define RX_CHECK_TABLE_LEVEL 1 25 + #define RX_ROCE_TABLE_LEVEL 2 25 26 #define RX_CHECK_TABLE_NUM_FTE 3 27 + #define RX_ROCE_TABLE_NUM_FTE 2 26 28 #define RX_CRYPTO_TABLE_NUM_GROUPS 3 27 29 #define RX_CRYPTO_TABLE_SA_RULE_WITH_SCI_GROUP_SIZE \ 28 30 ((CRYPTO_NUM_MAXSEC_FTE - CRYPTO_TABLE_DEFAULT_RULE_GROUP_SIZE) / 2) 29 31 #define RX_CRYPTO_TABLE_SA_RULE_WITHOUT_SCI_GROUP_SIZE \ 30 32 (CRYPTO_NUM_MAXSEC_FTE - RX_CRYPTO_TABLE_SA_RULE_WITH_SCI_GROUP_SIZE) 31 33 #define RX_NUM_OF_RULES_PER_SA 2 34 + 35 + #define RDMA_RX_ROCE_IP_TABLE_LEVEL 0 36 + #define RDMA_RX_ROCE_MACSEC_OP_TABLE_LEVEL 1 32 37 33 38 #define MLX5_MACSEC_TAG_LEN 8 /* SecTAG length with ethertype and without the optional SCI */ 34 39 #define MLX5_MACSEC_SECTAG_TCI_AN_FIELD_BITMASK 0x23 ··· 109 104 struct mlx5_modify_hdr *meta_modhdr; 110 105 }; 111 106 107 + struct mlx5_macsec_miss { 108 + struct mlx5_flow_group *g; 109 + struct mlx5_flow_handle *rule; 110 + }; 111 + 112 + struct mlx5_macsec_rx_roce { 113 + /* Flow table/rules in NIC domain, to check if it's a RoCE packet */ 114 + struct mlx5_flow_group *g; 115 + struct mlx5_flow_table *ft; 116 + struct mlx5_flow_handle *rule; 117 + struct mlx5_modify_hdr *copy_modify_hdr; 118 + struct mlx5_macsec_miss nic_miss; 119 + 120 + /* Flow table/rule in RDMA domain, to check dgid */ 121 + struct mlx5_flow_table *ft_ip_check; 122 + struct mlx5_flow_table *ft_macsec_op_check; 123 + struct mlx5_macsec_miss miss; 124 + }; 125 + 112 126 struct mlx5_macsec_rx { 113 127 struct mlx5_flow_handle *check_rule[2]; 114 128 struct mlx5_pkt_reformat *check_rule_pkt_reformat[2]; 115 129 116 130 struct mlx5_macsec_tables tables; 131 + struct mlx5_macsec_rx_roce roce; 117 132 }; 118 133 119 134 union mlx5_macsec_rule { ··· 957 932 return err; 958 933 } 959 934 935 + static void macsec_fs_rx_roce_miss_destroy(struct mlx5_macsec_miss *miss) 936 + { 937 + mlx5_del_flow_rules(miss->rule); 938 + mlx5_destroy_flow_group(miss->g); 939 + } 940 + 941 + static void macsec_fs_rdma_rx_destroy(struct mlx5_macsec_rx_roce *roce, struct mlx5_core_dev *mdev) 942 + { 943 + if (!mlx5_is_macsec_roce_supported(mdev)) 944 + return; 945 + 946 + mlx5_del_flow_rules(roce->nic_miss.rule); 947 + mlx5_del_flow_rules(roce->rule); 948 + mlx5_modify_header_dealloc(mdev, roce->copy_modify_hdr); 949 + mlx5_destroy_flow_group(roce->nic_miss.g); 950 + mlx5_destroy_flow_group(roce->g); 951 + mlx5_destroy_flow_table(roce->ft); 952 + 953 + macsec_fs_rx_roce_miss_destroy(&roce->miss); 954 + mlx5_destroy_flow_table(roce->ft_macsec_op_check); 955 + mlx5_destroy_flow_table(roce->ft_ip_check); 956 + } 957 + 960 958 static void macsec_fs_rx_destroy(struct mlx5_macsec_fs *macsec_fs) 961 959 { 962 960 struct mlx5_macsec_rx *rx_fs = macsec_fs->rx_fs; ··· 1024 976 } 1025 977 1026 978 macsec_fs_destroy_flow_table(&rx_tables->ft_crypto); 979 + 980 + macsec_fs_rdma_rx_destroy(&macsec_fs->rx_fs->roce, macsec_fs->mdev); 1027 981 } 1028 982 1029 983 static int macsec_fs_rx_create_crypto_table_groups(struct mlx5_macsec_flow_table *ft) ··· 1121 1071 struct mlx5_pkt_reformat_params reformat_params = {}; 1122 1072 struct mlx5_macsec_rx *rx_fs = macsec_fs->rx_fs; 1123 1073 struct mlx5_core_dev *mdev = macsec_fs->mdev; 1074 + struct mlx5_flow_destination roce_dest[2]; 1124 1075 struct mlx5_macsec_tables *rx_tables; 1125 1076 struct mlx5_flow_handle *rule; 1126 - int err = 0; 1077 + int err = 0, dstn = 0; 1127 1078 1128 1079 rx_tables = &rx_fs->tables; 1129 1080 ··· 1165 1114 MLX5_MACSEC_SECTAG_TCI_AN_FIELD_OFFSET); 1166 1115 1167 1116 flow_act->flags = FLOW_ACT_NO_APPEND; 1168 - flow_act->action = MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_PRIO | 1169 - MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT | 1170 - MLX5_FLOW_CONTEXT_ACTION_COUNT; 1171 - dest->type = MLX5_FLOW_DESTINATION_TYPE_COUNTER; 1172 - dest->counter_id = mlx5_fc_id(rx_tables->check_rule_counter); 1173 - rule = mlx5_add_flow_rules(rx_tables->ft_check, spec, flow_act, dest, 1); 1117 + 1118 + if (rx_fs->roce.ft) { 1119 + flow_act->action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST; 1120 + roce_dest[dstn].type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE; 1121 + roce_dest[dstn].ft = rx_fs->roce.ft; 1122 + dstn++; 1123 + } else { 1124 + flow_act->action = MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_PRIO; 1125 + } 1126 + 1127 + flow_act->action |= MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT | 1128 + MLX5_FLOW_CONTEXT_ACTION_COUNT; 1129 + roce_dest[dstn].type = MLX5_FLOW_DESTINATION_TYPE_COUNTER; 1130 + roce_dest[dstn].counter_id = mlx5_fc_id(rx_tables->check_rule_counter); 1131 + rule = mlx5_add_flow_rules(rx_tables->ft_check, spec, flow_act, roce_dest, dstn + 1); 1132 + 1174 1133 if (IS_ERR(rule)) { 1175 1134 err = PTR_ERR(rule); 1176 1135 mlx5_core_err(mdev, "Failed to add MACsec Rx check rule, err=%d\n", err); ··· 1190 1129 rx_fs->check_rule[rule_index] = rule; 1191 1130 1192 1131 return 0; 1132 + } 1133 + 1134 + static int macsec_fs_rx_roce_miss_create(struct mlx5_core_dev *mdev, 1135 + struct mlx5_macsec_rx_roce *roce) 1136 + { 1137 + struct mlx5_flow_act flow_act = {}; 1138 + struct mlx5_flow_group *flow_group; 1139 + struct mlx5_flow_handle *rule; 1140 + u32 *flow_group_in; 1141 + int err; 1142 + 1143 + flow_group_in = kvzalloc(MLX5_ST_SZ_BYTES(create_flow_group_in), GFP_KERNEL); 1144 + if (!flow_group_in) 1145 + return -ENOMEM; 1146 + 1147 + /* IP check ft has no miss rule since we use default miss action which is go to next PRIO */ 1148 + MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 1149 + roce->ft_macsec_op_check->max_fte - 1); 1150 + MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, 1151 + roce->ft_macsec_op_check->max_fte - 1); 1152 + flow_group = mlx5_create_flow_group(roce->ft_macsec_op_check, flow_group_in); 1153 + if (IS_ERR(flow_group)) { 1154 + err = PTR_ERR(flow_group); 1155 + mlx5_core_err(mdev, 1156 + "Failed to create miss flow group for MACsec RoCE operation check table err(%d)\n", 1157 + err); 1158 + goto err_macsec_op_miss_group; 1159 + } 1160 + roce->miss.g = flow_group; 1161 + 1162 + flow_act.action = MLX5_FLOW_CONTEXT_ACTION_DROP; 1163 + rule = mlx5_add_flow_rules(roce->ft_macsec_op_check, NULL, &flow_act, NULL, 0); 1164 + if (IS_ERR(rule)) { 1165 + err = PTR_ERR(rule); 1166 + mlx5_core_err(mdev, "Failed to add miss rule to MACsec RoCE operation check table err(%d)\n", 1167 + err); 1168 + goto err_macsec_op_rule; 1169 + } 1170 + roce->miss.rule = rule; 1171 + 1172 + kvfree(flow_group_in); 1173 + return 0; 1174 + 1175 + err_macsec_op_rule: 1176 + mlx5_destroy_flow_group(roce->miss.g); 1177 + err_macsec_op_miss_group: 1178 + kvfree(flow_group_in); 1179 + return err; 1180 + } 1181 + 1182 + #define MLX5_RX_ROCE_GROUP_SIZE BIT(0) 1183 + 1184 + static int macsec_fs_rx_roce_jump_to_rdma_groups_create(struct mlx5_core_dev *mdev, 1185 + struct mlx5_macsec_rx_roce *roce) 1186 + { 1187 + struct mlx5_flow_group *g; 1188 + void *outer_headers_c; 1189 + int ix = 0; 1190 + u32 *in; 1191 + int err; 1192 + u8 *mc; 1193 + 1194 + in = kvzalloc(MLX5_ST_SZ_BYTES(create_flow_group_in), GFP_KERNEL); 1195 + if (!in) 1196 + return -ENOMEM; 1197 + 1198 + mc = MLX5_ADDR_OF(create_flow_group_in, in, match_criteria); 1199 + outer_headers_c = MLX5_ADDR_OF(fte_match_param, mc, outer_headers); 1200 + MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, outer_headers_c, ip_protocol); 1201 + MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, outer_headers_c, udp_dport); 1202 + 1203 + MLX5_SET_CFG(in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS); 1204 + MLX5_SET_CFG(in, start_flow_index, ix); 1205 + ix += MLX5_RX_ROCE_GROUP_SIZE; 1206 + MLX5_SET_CFG(in, end_flow_index, ix - 1); 1207 + g = mlx5_create_flow_group(roce->ft, in); 1208 + if (IS_ERR(g)) { 1209 + err = PTR_ERR(g); 1210 + mlx5_core_err(mdev, "Failed to create main flow group for MACsec RoCE NIC UDP table err(%d)\n", 1211 + err); 1212 + goto err_udp_group; 1213 + } 1214 + roce->g = g; 1215 + 1216 + memset(in, 0, MLX5_ST_SZ_BYTES(create_flow_group_in)); 1217 + MLX5_SET_CFG(in, start_flow_index, ix); 1218 + ix += MLX5_RX_ROCE_GROUP_SIZE; 1219 + MLX5_SET_CFG(in, end_flow_index, ix - 1); 1220 + g = mlx5_create_flow_group(roce->ft, in); 1221 + if (IS_ERR(g)) { 1222 + err = PTR_ERR(g); 1223 + mlx5_core_err(mdev, "Failed to create miss flow group for MACsec RoCE NIC UDP table err(%d)\n", 1224 + err); 1225 + goto err_udp_miss_group; 1226 + } 1227 + roce->nic_miss.g = g; 1228 + 1229 + kvfree(in); 1230 + return 0; 1231 + 1232 + err_udp_miss_group: 1233 + mlx5_destroy_flow_group(roce->g); 1234 + err_udp_group: 1235 + kvfree(in); 1236 + return err; 1237 + } 1238 + 1239 + static int macsec_fs_rx_roce_jump_to_rdma_rules_create(struct mlx5_macsec_fs *macsec_fs, 1240 + struct mlx5_macsec_rx_roce *roce) 1241 + { 1242 + u8 action[MLX5_UN_SZ_BYTES(set_add_copy_action_in_auto)] = {}; 1243 + struct mlx5_core_dev *mdev = macsec_fs->mdev; 1244 + struct mlx5_flow_destination dst = {}; 1245 + struct mlx5_modify_hdr *modify_hdr; 1246 + MLX5_DECLARE_FLOW_ACT(flow_act); 1247 + struct mlx5_flow_handle *rule; 1248 + struct mlx5_flow_spec *spec; 1249 + int err; 1250 + 1251 + spec = kvzalloc(sizeof(*spec), GFP_KERNEL); 1252 + if (!spec) 1253 + return -ENOMEM; 1254 + 1255 + spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS; 1256 + MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, outer_headers.ip_protocol); 1257 + MLX5_SET(fte_match_param, spec->match_value, outer_headers.ip_protocol, IPPROTO_UDP); 1258 + MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, outer_headers.udp_dport); 1259 + MLX5_SET(fte_match_param, spec->match_value, outer_headers.udp_dport, ROCE_V2_UDP_DPORT); 1260 + 1261 + MLX5_SET(copy_action_in, action, action_type, MLX5_ACTION_TYPE_COPY); 1262 + MLX5_SET(copy_action_in, action, src_field, MLX5_ACTION_IN_FIELD_METADATA_REG_B); 1263 + MLX5_SET(copy_action_in, action, src_offset, 0); 1264 + MLX5_SET(copy_action_in, action, length, 32); 1265 + MLX5_SET(copy_action_in, action, dst_field, MLX5_ACTION_IN_FIELD_METADATA_REG_C_5); 1266 + MLX5_SET(copy_action_in, action, dst_offset, 0); 1267 + 1268 + modify_hdr = mlx5_modify_header_alloc(macsec_fs->mdev, MLX5_FLOW_NAMESPACE_KERNEL_RX_MACSEC, 1269 + 1, action); 1270 + 1271 + if (IS_ERR(modify_hdr)) { 1272 + err = PTR_ERR(modify_hdr); 1273 + mlx5_core_err(mdev, 1274 + "Failed to alloc macsec copy modify_header_id err(%d)\n", err); 1275 + goto err_alloc_hdr; 1276 + } 1277 + 1278 + flow_act.action = MLX5_FLOW_CONTEXT_ACTION_MOD_HDR | MLX5_FLOW_CONTEXT_ACTION_FWD_DEST; 1279 + flow_act.modify_hdr = modify_hdr; 1280 + dst.type = MLX5_FLOW_DESTINATION_TYPE_TABLE_TYPE; 1281 + dst.ft = roce->ft_ip_check; 1282 + rule = mlx5_add_flow_rules(roce->ft, spec, &flow_act, &dst, 1); 1283 + if (IS_ERR(rule)) { 1284 + err = PTR_ERR(rule); 1285 + mlx5_core_err(mdev, "Failed to add rule to MACsec RoCE NIC UDP table err(%d)\n", 1286 + err); 1287 + goto err_add_rule; 1288 + } 1289 + roce->rule = rule; 1290 + roce->copy_modify_hdr = modify_hdr; 1291 + 1292 + memset(&flow_act, 0, sizeof(flow_act)); 1293 + flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_PRIO; 1294 + rule = mlx5_add_flow_rules(roce->ft, NULL, &flow_act, NULL, 0); 1295 + if (IS_ERR(rule)) { 1296 + err = PTR_ERR(rule); 1297 + mlx5_core_err(mdev, "Failed to add miss rule to MACsec RoCE NIC UDP table err(%d)\n", 1298 + err); 1299 + goto err_add_rule2; 1300 + } 1301 + roce->nic_miss.rule = rule; 1302 + 1303 + kvfree(spec); 1304 + return 0; 1305 + 1306 + err_add_rule2: 1307 + mlx5_del_flow_rules(roce->rule); 1308 + err_add_rule: 1309 + mlx5_modify_header_dealloc(macsec_fs->mdev, modify_hdr); 1310 + err_alloc_hdr: 1311 + kvfree(spec); 1312 + return err; 1313 + } 1314 + 1315 + static int macsec_fs_rx_roce_jump_to_rdma_create(struct mlx5_macsec_fs *macsec_fs, 1316 + struct mlx5_macsec_rx_roce *roce) 1317 + { 1318 + int err; 1319 + 1320 + err = macsec_fs_rx_roce_jump_to_rdma_groups_create(macsec_fs->mdev, roce); 1321 + if (err) 1322 + return err; 1323 + 1324 + err = macsec_fs_rx_roce_jump_to_rdma_rules_create(macsec_fs, roce); 1325 + if (err) 1326 + goto err; 1327 + 1328 + return 0; 1329 + err: 1330 + mlx5_destroy_flow_group(roce->nic_miss.g); 1331 + mlx5_destroy_flow_group(roce->g); 1332 + return err; 1333 + } 1334 + 1335 + static int macsec_fs_rx_roce_create(struct mlx5_macsec_fs *macsec_fs) 1336 + { 1337 + struct mlx5_macsec_rx *rx_fs = macsec_fs->rx_fs; 1338 + struct mlx5_core_dev *mdev = macsec_fs->mdev; 1339 + struct mlx5_flow_table_attr ft_attr = {}; 1340 + struct mlx5_flow_namespace *ns; 1341 + struct mlx5_flow_table *ft; 1342 + int err = 0; 1343 + 1344 + if (!mlx5_is_macsec_roce_supported(macsec_fs->mdev)) { 1345 + mlx5_core_dbg(mdev, "Failed to init RoCE MACsec, capabilities not supported\n"); 1346 + return 0; 1347 + } 1348 + 1349 + ns = mlx5_get_flow_namespace(macsec_fs->mdev, MLX5_FLOW_NAMESPACE_RDMA_RX_MACSEC); 1350 + if (!ns) 1351 + return -ENOMEM; 1352 + 1353 + ft = macsec_fs_auto_group_table_create(ns, 0, RDMA_RX_ROCE_IP_TABLE_LEVEL, 1354 + CRYPTO_NUM_MAXSEC_FTE); 1355 + if (IS_ERR(ft)) { 1356 + err = PTR_ERR(ft); 1357 + mlx5_core_err(mdev, 1358 + "Failed to create MACsec IP check RoCE table err(%d)\n", err); 1359 + return err; 1360 + } 1361 + rx_fs->roce.ft_ip_check = ft; 1362 + 1363 + ft = macsec_fs_auto_group_table_create(ns, 0, RDMA_RX_ROCE_MACSEC_OP_TABLE_LEVEL, 1364 + CRYPTO_NUM_MAXSEC_FTE); 1365 + if (IS_ERR(ft)) { 1366 + err = PTR_ERR(ft); 1367 + mlx5_core_err(mdev, 1368 + "Failed to create MACsec operation check RoCE table err(%d)\n", 1369 + err); 1370 + goto err_macsec_op; 1371 + } 1372 + rx_fs->roce.ft_macsec_op_check = ft; 1373 + 1374 + err = macsec_fs_rx_roce_miss_create(mdev, &rx_fs->roce); 1375 + if (err) 1376 + goto err_miss_create; 1377 + 1378 + ns = mlx5_get_flow_namespace(macsec_fs->mdev, MLX5_FLOW_NAMESPACE_KERNEL_RX_MACSEC); 1379 + if (!ns) { 1380 + err = -EOPNOTSUPP; 1381 + goto err_ns; 1382 + } 1383 + 1384 + ft_attr.level = RX_ROCE_TABLE_LEVEL; 1385 + ft_attr.max_fte = RX_ROCE_TABLE_NUM_FTE; 1386 + ft = mlx5_create_flow_table(ns, &ft_attr); 1387 + if (IS_ERR(ft)) { 1388 + err = PTR_ERR(ft); 1389 + mlx5_core_err(mdev, 1390 + "Failed to create MACsec jump to RX RoCE, NIC table err(%d)\n", err); 1391 + goto err_ns; 1392 + } 1393 + rx_fs->roce.ft = ft; 1394 + 1395 + err = macsec_fs_rx_roce_jump_to_rdma_create(macsec_fs, &rx_fs->roce); 1396 + if (err) 1397 + goto err_udp_ft; 1398 + 1399 + return 0; 1400 + 1401 + err_udp_ft: 1402 + mlx5_destroy_flow_table(rx_fs->roce.ft); 1403 + err_ns: 1404 + macsec_fs_rx_roce_miss_destroy(&rx_fs->roce.miss); 1405 + err_miss_create: 1406 + mlx5_destroy_flow_table(rx_fs->roce.ft_macsec_op_check); 1407 + err_macsec_op: 1408 + mlx5_destroy_flow_table(rx_fs->roce.ft_ip_check); 1409 + return err; 1193 1410 } 1194 1411 1195 1412 static int macsec_fs_rx_create(struct mlx5_macsec_fs *macsec_fs) ··· 1505 1166 rx_tables = &rx_fs->tables; 1506 1167 ft_crypto = &rx_tables->ft_crypto; 1507 1168 1169 + err = macsec_fs_rx_roce_create(macsec_fs); 1170 + if (err) 1171 + goto out_flow_group; 1172 + 1508 1173 /* Rx crypto table */ 1509 1174 ft_attr.level = RX_CRYPTO_TABLE_LEVEL; 1510 1175 ft_attr.max_fte = CRYPTO_NUM_MAXSEC_FTE; ··· 1517 1174 if (IS_ERR(flow_table)) { 1518 1175 err = PTR_ERR(flow_table); 1519 1176 mlx5_core_err(mdev, "Failed to create MACsec Rx crypto table err(%d)\n", err); 1520 - goto out_flow_group; 1177 + goto err; 1521 1178 } 1522 1179 ft_crypto->t = flow_table; 1523 1180