1 /* 2 * Copyright (c) 2015, Mellanox Technologies. All rights reserved. 3 * 4 * This software is available to you under a choice of one of two 5 * licenses. You may choose to be licensed under the terms of the GNU 6 * General Public License (GPL) Version 2, available from the file 7 * COPYING in the main directory of this source tree, or the 8 * OpenIB.org BSD license below: 9 * 10 * Redistribution and use in source and binary forms, with or 11 * without modification, are permitted provided that the following 12 * conditions are met: 13 * 14 * - Redistributions of source code must retain the above 15 * copyright notice, this list of conditions and the following 16 * disclaimer. 17 * 18 * - Redistributions in binary form must reproduce the above 19 * copyright notice, this list of conditions and the following 20 * disclaimer in the documentation and/or other materials 21 * provided with the distribution. 22 * 23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 * SOFTWARE. 31 */ 32 33 #include <linux/mlx5/driver.h> 34 #include <linux/mlx5/device.h> 35 #include <linux/mlx5/mlx5_ifc.h> 36 37 #include "fs_core.h" 38 #include "fs_cmd.h" 39 #include "fs_ft_pool.h" 40 #include "mlx5_core.h" 41 #include "eswitch.h" 42 43 static int mlx5_cmd_stub_update_root_ft(struct mlx5_flow_root_namespace *ns, 44 struct mlx5_flow_table *ft, 45 u32 underlay_qpn, 46 bool disconnect) 47 { 48 return 0; 49 } 50 51 static int mlx5_cmd_stub_create_flow_table(struct mlx5_flow_root_namespace *ns, 52 struct mlx5_flow_table *ft, 53 struct mlx5_flow_table_attr *ft_attr, 54 struct mlx5_flow_table *next_ft) 55 { 56 int max_fte = ft_attr->max_fte; 57 58 ft->max_fte = max_fte ? roundup_pow_of_two(max_fte) : 1; 59 60 return 0; 61 } 62 63 static int mlx5_cmd_stub_destroy_flow_table(struct mlx5_flow_root_namespace *ns, 64 struct mlx5_flow_table *ft) 65 { 66 return 0; 67 } 68 69 static int mlx5_cmd_stub_modify_flow_table(struct mlx5_flow_root_namespace *ns, 70 struct mlx5_flow_table *ft, 71 struct mlx5_flow_table *next_ft) 72 { 73 return 0; 74 } 75 76 static int mlx5_cmd_stub_create_flow_group(struct mlx5_flow_root_namespace *ns, 77 struct mlx5_flow_table *ft, 78 u32 *in, 79 struct mlx5_flow_group *fg) 80 { 81 return 0; 82 } 83 84 static int mlx5_cmd_stub_destroy_flow_group(struct mlx5_flow_root_namespace *ns, 85 struct mlx5_flow_table *ft, 86 struct mlx5_flow_group *fg) 87 { 88 return 0; 89 } 90 91 static int mlx5_cmd_stub_create_fte(struct mlx5_flow_root_namespace *ns, 92 struct mlx5_flow_table *ft, 93 struct mlx5_flow_group *group, 94 struct fs_fte *fte) 95 { 96 return 0; 97 } 98 99 static int mlx5_cmd_stub_update_fte(struct mlx5_flow_root_namespace *ns, 100 struct mlx5_flow_table *ft, 101 struct mlx5_flow_group *group, 102 int modify_mask, 103 struct fs_fte *fte) 104 { 105 return -EOPNOTSUPP; 106 } 107 108 static int mlx5_cmd_stub_delete_fte(struct mlx5_flow_root_namespace *ns, 109 struct mlx5_flow_table *ft, 110 struct fs_fte *fte) 111 { 112 return 0; 113 } 114 115 static int mlx5_cmd_stub_packet_reformat_alloc(struct mlx5_flow_root_namespace *ns, 116 struct mlx5_pkt_reformat_params *params, 117 enum mlx5_flow_namespace_type namespace, 118 struct mlx5_pkt_reformat *pkt_reformat) 119 { 120 return 0; 121 } 122 123 static void mlx5_cmd_stub_packet_reformat_dealloc(struct mlx5_flow_root_namespace *ns, 124 struct mlx5_pkt_reformat *pkt_reformat) 125 { 126 } 127 128 static int mlx5_cmd_stub_modify_header_alloc(struct mlx5_flow_root_namespace *ns, 129 u8 namespace, u8 num_actions, 130 void *modify_actions, 131 struct mlx5_modify_hdr *modify_hdr) 132 { 133 return 0; 134 } 135 136 static void mlx5_cmd_stub_modify_header_dealloc(struct mlx5_flow_root_namespace *ns, 137 struct mlx5_modify_hdr *modify_hdr) 138 { 139 } 140 141 static int mlx5_cmd_stub_set_peer(struct mlx5_flow_root_namespace *ns, 142 struct mlx5_flow_root_namespace *peer_ns, 143 u16 peer_vhca_id) 144 { 145 return 0; 146 } 147 148 static int mlx5_cmd_stub_create_ns(struct mlx5_flow_root_namespace *ns) 149 { 150 return 0; 151 } 152 153 static int mlx5_cmd_stub_destroy_ns(struct mlx5_flow_root_namespace *ns) 154 { 155 return 0; 156 } 157 158 static u32 mlx5_cmd_stub_get_capabilities(struct mlx5_flow_root_namespace *ns, 159 enum fs_flow_table_type ft_type) 160 { 161 return 0; 162 } 163 164 static int mlx5_cmd_set_slave_root_fdb(struct mlx5_core_dev *master, 165 struct mlx5_core_dev *slave, 166 bool ft_id_valid, 167 u32 ft_id) 168 { 169 u32 out[MLX5_ST_SZ_DW(set_flow_table_root_out)] = {}; 170 u32 in[MLX5_ST_SZ_DW(set_flow_table_root_in)] = {}; 171 struct mlx5_flow_root_namespace *root; 172 struct mlx5_flow_namespace *ns; 173 174 MLX5_SET(set_flow_table_root_in, in, opcode, 175 MLX5_CMD_OP_SET_FLOW_TABLE_ROOT); 176 MLX5_SET(set_flow_table_root_in, in, table_type, 177 FS_FT_FDB); 178 if (ft_id_valid) { 179 MLX5_SET(set_flow_table_root_in, in, 180 table_eswitch_owner_vhca_id_valid, 1); 181 MLX5_SET(set_flow_table_root_in, in, 182 table_eswitch_owner_vhca_id, 183 MLX5_CAP_GEN(master, vhca_id)); 184 MLX5_SET(set_flow_table_root_in, in, table_id, 185 ft_id); 186 } else { 187 ns = mlx5_get_flow_namespace(slave, 188 MLX5_FLOW_NAMESPACE_FDB); 189 root = find_root(&ns->node); 190 MLX5_SET(set_flow_table_root_in, in, table_id, 191 root->root_ft->id); 192 } 193 194 return mlx5_cmd_exec(slave, in, sizeof(in), out, sizeof(out)); 195 } 196 197 static int 198 mlx5_cmd_stub_destroy_match_definer(struct mlx5_flow_root_namespace *ns, 199 int definer_id) 200 { 201 return 0; 202 } 203 204 static int 205 mlx5_cmd_stub_create_match_definer(struct mlx5_flow_root_namespace *ns, 206 u16 format_id, u32 *match_mask) 207 { 208 return 0; 209 } 210 211 static int mlx5_cmd_update_root_ft(struct mlx5_flow_root_namespace *ns, 212 struct mlx5_flow_table *ft, u32 underlay_qpn, 213 bool disconnect) 214 { 215 u32 in[MLX5_ST_SZ_DW(set_flow_table_root_in)] = {}; 216 struct mlx5_core_dev *dev = ns->dev; 217 int err; 218 219 if ((MLX5_CAP_GEN(dev, port_type) == MLX5_CAP_PORT_TYPE_IB) && 220 underlay_qpn == 0) 221 return 0; 222 223 if (ft->type == FS_FT_FDB && 224 mlx5_lag_is_shared_fdb(dev) && 225 !mlx5_lag_is_master(dev)) 226 return 0; 227 228 MLX5_SET(set_flow_table_root_in, in, opcode, 229 MLX5_CMD_OP_SET_FLOW_TABLE_ROOT); 230 MLX5_SET(set_flow_table_root_in, in, table_type, ft->type); 231 232 if (disconnect) 233 MLX5_SET(set_flow_table_root_in, in, op_mod, 1); 234 else 235 MLX5_SET(set_flow_table_root_in, in, table_id, ft->id); 236 237 MLX5_SET(set_flow_table_root_in, in, underlay_qpn, underlay_qpn); 238 MLX5_SET(set_flow_table_root_in, in, vport_number, ft->vport); 239 MLX5_SET(set_flow_table_root_in, in, other_vport, 240 !!(ft->flags & MLX5_FLOW_TABLE_OTHER_VPORT)); 241 242 err = mlx5_cmd_exec_in(dev, set_flow_table_root, in); 243 if (!err && 244 ft->type == FS_FT_FDB && 245 mlx5_lag_is_shared_fdb(dev) && 246 mlx5_lag_is_master(dev)) { 247 struct mlx5_core_dev *peer_dev; 248 int i, j; 249 250 mlx5_lag_for_each_peer_mdev(dev, peer_dev, i) { 251 err = mlx5_cmd_set_slave_root_fdb(dev, peer_dev, !disconnect, 252 (!disconnect) ? ft->id : 0); 253 if (err && !disconnect) { 254 mlx5_lag_for_each_peer_mdev(dev, peer_dev, j) { 255 if (j < i) 256 mlx5_cmd_set_slave_root_fdb(dev, peer_dev, 1, 257 ns->root_ft->id); 258 else 259 break; 260 } 261 262 MLX5_SET(set_flow_table_root_in, in, op_mod, 0); 263 MLX5_SET(set_flow_table_root_in, in, table_id, 264 ns->root_ft->id); 265 mlx5_cmd_exec_in(dev, set_flow_table_root, in); 266 } 267 if (err) 268 break; 269 } 270 271 } 272 273 return err; 274 } 275 276 static int mlx5_cmd_create_flow_table(struct mlx5_flow_root_namespace *ns, 277 struct mlx5_flow_table *ft, 278 struct mlx5_flow_table_attr *ft_attr, 279 struct mlx5_flow_table *next_ft) 280 { 281 int en_encap = !!(ft->flags & MLX5_FLOW_TABLE_TUNNEL_EN_REFORMAT); 282 int en_decap = !!(ft->flags & MLX5_FLOW_TABLE_TUNNEL_EN_DECAP); 283 int term = !!(ft->flags & MLX5_FLOW_TABLE_TERMINATION); 284 u32 out[MLX5_ST_SZ_DW(create_flow_table_out)] = {}; 285 u32 in[MLX5_ST_SZ_DW(create_flow_table_in)] = {}; 286 struct mlx5_core_dev *dev = ns->dev; 287 unsigned int size; 288 int err; 289 290 size = mlx5_ft_pool_get_avail_sz(dev, ft->type, ft_attr->max_fte); 291 if (!size) 292 return -ENOSPC; 293 294 MLX5_SET(create_flow_table_in, in, opcode, 295 MLX5_CMD_OP_CREATE_FLOW_TABLE); 296 297 MLX5_SET(create_flow_table_in, in, uid, ft_attr->uid); 298 MLX5_SET(create_flow_table_in, in, table_type, ft->type); 299 MLX5_SET(create_flow_table_in, in, flow_table_context.level, ft->level); 300 MLX5_SET(create_flow_table_in, in, flow_table_context.log_size, size ? ilog2(size) : 0); 301 MLX5_SET(create_flow_table_in, in, vport_number, ft->vport); 302 MLX5_SET(create_flow_table_in, in, other_vport, 303 !!(ft->flags & MLX5_FLOW_TABLE_OTHER_VPORT)); 304 305 MLX5_SET(create_flow_table_in, in, flow_table_context.decap_en, 306 en_decap); 307 MLX5_SET(create_flow_table_in, in, flow_table_context.reformat_en, 308 en_encap); 309 MLX5_SET(create_flow_table_in, in, flow_table_context.termination_table, 310 term); 311 312 switch (ft->op_mod) { 313 case FS_FT_OP_MOD_NORMAL: 314 if (next_ft) { 315 MLX5_SET(create_flow_table_in, in, 316 flow_table_context.table_miss_action, 317 MLX5_FLOW_TABLE_MISS_ACTION_FWD); 318 MLX5_SET(create_flow_table_in, in, 319 flow_table_context.table_miss_id, next_ft->id); 320 } else { 321 MLX5_SET(create_flow_table_in, in, 322 flow_table_context.table_miss_action, 323 ft->def_miss_action); 324 } 325 break; 326 327 case FS_FT_OP_MOD_LAG_DEMUX: 328 MLX5_SET(create_flow_table_in, in, op_mod, 0x1); 329 if (next_ft) 330 MLX5_SET(create_flow_table_in, in, 331 flow_table_context.lag_master_next_table_id, 332 next_ft->id); 333 break; 334 } 335 336 err = mlx5_cmd_exec_inout(dev, create_flow_table, in, out); 337 if (!err) { 338 ft->id = MLX5_GET(create_flow_table_out, out, 339 table_id); 340 ft->max_fte = size; 341 } else { 342 mlx5_ft_pool_put_sz(ns->dev, size); 343 } 344 345 return err; 346 } 347 348 static int mlx5_cmd_destroy_flow_table(struct mlx5_flow_root_namespace *ns, 349 struct mlx5_flow_table *ft) 350 { 351 u32 in[MLX5_ST_SZ_DW(destroy_flow_table_in)] = {}; 352 struct mlx5_core_dev *dev = ns->dev; 353 int err; 354 355 MLX5_SET(destroy_flow_table_in, in, opcode, 356 MLX5_CMD_OP_DESTROY_FLOW_TABLE); 357 MLX5_SET(destroy_flow_table_in, in, table_type, ft->type); 358 MLX5_SET(destroy_flow_table_in, in, table_id, ft->id); 359 MLX5_SET(destroy_flow_table_in, in, vport_number, ft->vport); 360 MLX5_SET(destroy_flow_table_in, in, other_vport, 361 !!(ft->flags & MLX5_FLOW_TABLE_OTHER_VPORT)); 362 363 err = mlx5_cmd_exec_in(dev, destroy_flow_table, in); 364 if (!err) 365 mlx5_ft_pool_put_sz(ns->dev, ft->max_fte); 366 367 return err; 368 } 369 370 static int mlx5_cmd_modify_flow_table(struct mlx5_flow_root_namespace *ns, 371 struct mlx5_flow_table *ft, 372 struct mlx5_flow_table *next_ft) 373 { 374 u32 in[MLX5_ST_SZ_DW(modify_flow_table_in)] = {}; 375 struct mlx5_core_dev *dev = ns->dev; 376 377 MLX5_SET(modify_flow_table_in, in, opcode, 378 MLX5_CMD_OP_MODIFY_FLOW_TABLE); 379 MLX5_SET(modify_flow_table_in, in, table_type, ft->type); 380 MLX5_SET(modify_flow_table_in, in, table_id, ft->id); 381 382 if (ft->op_mod == FS_FT_OP_MOD_LAG_DEMUX) { 383 MLX5_SET(modify_flow_table_in, in, modify_field_select, 384 MLX5_MODIFY_FLOW_TABLE_LAG_NEXT_TABLE_ID); 385 if (next_ft) { 386 MLX5_SET(modify_flow_table_in, in, 387 flow_table_context.lag_master_next_table_id, next_ft->id); 388 } else { 389 MLX5_SET(modify_flow_table_in, in, 390 flow_table_context.lag_master_next_table_id, 0); 391 } 392 } else { 393 MLX5_SET(modify_flow_table_in, in, vport_number, ft->vport); 394 MLX5_SET(modify_flow_table_in, in, other_vport, 395 !!(ft->flags & MLX5_FLOW_TABLE_OTHER_VPORT)); 396 MLX5_SET(modify_flow_table_in, in, modify_field_select, 397 MLX5_MODIFY_FLOW_TABLE_MISS_TABLE_ID); 398 if (next_ft) { 399 MLX5_SET(modify_flow_table_in, in, 400 flow_table_context.table_miss_action, 401 MLX5_FLOW_TABLE_MISS_ACTION_FWD); 402 MLX5_SET(modify_flow_table_in, in, 403 flow_table_context.table_miss_id, 404 next_ft->id); 405 } else { 406 MLX5_SET(modify_flow_table_in, in, 407 flow_table_context.table_miss_action, 408 ft->def_miss_action); 409 } 410 } 411 412 return mlx5_cmd_exec_in(dev, modify_flow_table, in); 413 } 414 415 static int mlx5_cmd_create_flow_group(struct mlx5_flow_root_namespace *ns, 416 struct mlx5_flow_table *ft, 417 u32 *in, 418 struct mlx5_flow_group *fg) 419 { 420 u32 out[MLX5_ST_SZ_DW(create_flow_group_out)] = {}; 421 struct mlx5_core_dev *dev = ns->dev; 422 int err; 423 424 MLX5_SET(create_flow_group_in, in, opcode, 425 MLX5_CMD_OP_CREATE_FLOW_GROUP); 426 MLX5_SET(create_flow_group_in, in, table_type, ft->type); 427 MLX5_SET(create_flow_group_in, in, table_id, ft->id); 428 MLX5_SET(create_flow_group_in, in, vport_number, ft->vport); 429 MLX5_SET(create_flow_group_in, in, other_vport, 430 !!(ft->flags & MLX5_FLOW_TABLE_OTHER_VPORT)); 431 err = mlx5_cmd_exec_inout(dev, create_flow_group, in, out); 432 if (!err) 433 fg->id = MLX5_GET(create_flow_group_out, out, 434 group_id); 435 return err; 436 } 437 438 static int mlx5_cmd_destroy_flow_group(struct mlx5_flow_root_namespace *ns, 439 struct mlx5_flow_table *ft, 440 struct mlx5_flow_group *fg) 441 { 442 u32 in[MLX5_ST_SZ_DW(destroy_flow_group_in)] = {}; 443 struct mlx5_core_dev *dev = ns->dev; 444 445 MLX5_SET(destroy_flow_group_in, in, opcode, 446 MLX5_CMD_OP_DESTROY_FLOW_GROUP); 447 MLX5_SET(destroy_flow_group_in, in, table_type, ft->type); 448 MLX5_SET(destroy_flow_group_in, in, table_id, ft->id); 449 MLX5_SET(destroy_flow_group_in, in, group_id, fg->id); 450 MLX5_SET(destroy_flow_group_in, in, vport_number, ft->vport); 451 MLX5_SET(destroy_flow_group_in, in, other_vport, 452 !!(ft->flags & MLX5_FLOW_TABLE_OTHER_VPORT)); 453 return mlx5_cmd_exec_in(dev, destroy_flow_group, in); 454 } 455 456 static int mlx5_set_extended_dest(struct mlx5_core_dev *dev, 457 struct fs_fte *fte, bool *extended_dest) 458 { 459 int fw_log_max_fdb_encap_uplink = 460 MLX5_CAP_ESW(dev, log_max_fdb_encap_uplink); 461 int num_fwd_destinations = 0; 462 struct mlx5_flow_rule *dst; 463 int num_encap = 0; 464 465 *extended_dest = false; 466 if (!(fte->action.action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST)) 467 return 0; 468 469 list_for_each_entry(dst, &fte->node.children, node.list) { 470 if (dst->dest_attr.type == MLX5_FLOW_DESTINATION_TYPE_COUNTER || 471 dst->dest_attr.type == MLX5_FLOW_DESTINATION_TYPE_NONE) 472 continue; 473 if ((dst->dest_attr.type == MLX5_FLOW_DESTINATION_TYPE_VPORT || 474 dst->dest_attr.type == MLX5_FLOW_DESTINATION_TYPE_UPLINK) && 475 dst->dest_attr.vport.flags & MLX5_FLOW_DEST_VPORT_REFORMAT_ID) 476 num_encap++; 477 num_fwd_destinations++; 478 } 479 if (num_fwd_destinations > 1 && num_encap > 0) 480 *extended_dest = true; 481 482 if (*extended_dest && !fw_log_max_fdb_encap_uplink) { 483 mlx5_core_warn(dev, "FW does not support extended destination"); 484 return -EOPNOTSUPP; 485 } 486 if (num_encap > (1 << fw_log_max_fdb_encap_uplink)) { 487 mlx5_core_warn(dev, "FW does not support more than %d encaps", 488 1 << fw_log_max_fdb_encap_uplink); 489 return -EOPNOTSUPP; 490 } 491 492 return 0; 493 } 494 495 static void 496 mlx5_cmd_set_fte_flow_meter(struct fs_fte *fte, void *in_flow_context) 497 { 498 void *exe_aso_ctrl; 499 void *execute_aso; 500 501 execute_aso = MLX5_ADDR_OF(flow_context, in_flow_context, 502 execute_aso[0]); 503 MLX5_SET(execute_aso, execute_aso, valid, 1); 504 MLX5_SET(execute_aso, execute_aso, aso_object_id, 505 fte->action.exe_aso.object_id); 506 507 exe_aso_ctrl = MLX5_ADDR_OF(execute_aso, execute_aso, exe_aso_ctrl); 508 MLX5_SET(exe_aso_ctrl_flow_meter, exe_aso_ctrl, return_reg_id, 509 fte->action.exe_aso.return_reg_id); 510 MLX5_SET(exe_aso_ctrl_flow_meter, exe_aso_ctrl, aso_type, 511 fte->action.exe_aso.type); 512 MLX5_SET(exe_aso_ctrl_flow_meter, exe_aso_ctrl, init_color, 513 fte->action.exe_aso.flow_meter.init_color); 514 MLX5_SET(exe_aso_ctrl_flow_meter, exe_aso_ctrl, meter_id, 515 fte->action.exe_aso.flow_meter.meter_idx); 516 } 517 518 static int mlx5_cmd_set_fte(struct mlx5_core_dev *dev, 519 int opmod, int modify_mask, 520 struct mlx5_flow_table *ft, 521 unsigned group_id, 522 struct fs_fte *fte) 523 { 524 u32 out[MLX5_ST_SZ_DW(set_fte_out)] = {0}; 525 bool extended_dest = false; 526 struct mlx5_flow_rule *dst; 527 void *in_flow_context, *vlan; 528 void *in_match_value; 529 int reformat_id = 0; 530 unsigned int inlen; 531 int dst_cnt_size; 532 u32 *in, action; 533 void *in_dests; 534 int err; 535 536 if (mlx5_set_extended_dest(dev, fte, &extended_dest)) 537 return -EOPNOTSUPP; 538 539 if (!extended_dest) 540 dst_cnt_size = MLX5_ST_SZ_BYTES(dest_format_struct); 541 else 542 dst_cnt_size = MLX5_ST_SZ_BYTES(extended_dest_format); 543 544 inlen = MLX5_ST_SZ_BYTES(set_fte_in) + fte->dests_size * dst_cnt_size; 545 in = kvzalloc(inlen, GFP_KERNEL); 546 if (!in) 547 return -ENOMEM; 548 549 MLX5_SET(set_fte_in, in, opcode, MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY); 550 MLX5_SET(set_fte_in, in, op_mod, opmod); 551 MLX5_SET(set_fte_in, in, modify_enable_mask, modify_mask); 552 MLX5_SET(set_fte_in, in, table_type, ft->type); 553 MLX5_SET(set_fte_in, in, table_id, ft->id); 554 MLX5_SET(set_fte_in, in, flow_index, fte->index); 555 MLX5_SET(set_fte_in, in, ignore_flow_level, 556 !!(fte->action.flags & FLOW_ACT_IGNORE_FLOW_LEVEL)); 557 558 MLX5_SET(set_fte_in, in, vport_number, ft->vport); 559 MLX5_SET(set_fte_in, in, other_vport, 560 !!(ft->flags & MLX5_FLOW_TABLE_OTHER_VPORT)); 561 562 in_flow_context = MLX5_ADDR_OF(set_fte_in, in, flow_context); 563 MLX5_SET(flow_context, in_flow_context, group_id, group_id); 564 565 MLX5_SET(flow_context, in_flow_context, flow_tag, 566 fte->flow_context.flow_tag); 567 MLX5_SET(flow_context, in_flow_context, flow_source, 568 fte->flow_context.flow_source); 569 MLX5_SET(flow_context, in_flow_context, uplink_hairpin_en, 570 !!(fte->flow_context.flags & FLOW_CONTEXT_UPLINK_HAIRPIN_EN)); 571 572 MLX5_SET(flow_context, in_flow_context, extended_destination, 573 extended_dest); 574 575 action = fte->action.action; 576 if (extended_dest) 577 action &= ~MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT; 578 579 MLX5_SET(flow_context, in_flow_context, action, action); 580 581 if (!extended_dest && fte->action.pkt_reformat) { 582 struct mlx5_pkt_reformat *pkt_reformat = fte->action.pkt_reformat; 583 584 if (pkt_reformat->owner == MLX5_FLOW_RESOURCE_OWNER_SW) { 585 reformat_id = mlx5_fs_dr_action_get_pkt_reformat_id(pkt_reformat); 586 if (reformat_id < 0) { 587 mlx5_core_err(dev, 588 "Unsupported SW-owned pkt_reformat type (%d) in FW-owned table\n", 589 pkt_reformat->reformat_type); 590 err = reformat_id; 591 goto err_out; 592 } 593 } else { 594 reformat_id = fte->action.pkt_reformat->id; 595 } 596 } 597 598 MLX5_SET(flow_context, in_flow_context, packet_reformat_id, (u32)reformat_id); 599 600 if (fte->action.modify_hdr) { 601 if (fte->action.modify_hdr->owner == MLX5_FLOW_RESOURCE_OWNER_SW) { 602 mlx5_core_err(dev, "Can't use SW-owned modify_hdr in FW-owned table\n"); 603 err = -EOPNOTSUPP; 604 goto err_out; 605 } 606 607 MLX5_SET(flow_context, in_flow_context, modify_header_id, 608 fte->action.modify_hdr->id); 609 } 610 611 MLX5_SET(flow_context, in_flow_context, encrypt_decrypt_type, 612 fte->action.crypto.type); 613 MLX5_SET(flow_context, in_flow_context, encrypt_decrypt_obj_id, 614 fte->action.crypto.obj_id); 615 616 vlan = MLX5_ADDR_OF(flow_context, in_flow_context, push_vlan); 617 618 MLX5_SET(vlan, vlan, ethtype, fte->action.vlan[0].ethtype); 619 MLX5_SET(vlan, vlan, vid, fte->action.vlan[0].vid); 620 MLX5_SET(vlan, vlan, prio, fte->action.vlan[0].prio); 621 622 vlan = MLX5_ADDR_OF(flow_context, in_flow_context, push_vlan_2); 623 624 MLX5_SET(vlan, vlan, ethtype, fte->action.vlan[1].ethtype); 625 MLX5_SET(vlan, vlan, vid, fte->action.vlan[1].vid); 626 MLX5_SET(vlan, vlan, prio, fte->action.vlan[1].prio); 627 628 in_match_value = MLX5_ADDR_OF(flow_context, in_flow_context, 629 match_value); 630 memcpy(in_match_value, &fte->val, sizeof(fte->val)); 631 632 in_dests = MLX5_ADDR_OF(flow_context, in_flow_context, destination); 633 if (fte->action.action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST) { 634 int list_size = 0; 635 636 list_for_each_entry(dst, &fte->node.children, node.list) { 637 enum mlx5_flow_destination_type type = dst->dest_attr.type; 638 enum mlx5_ifc_flow_destination_type ifc_type; 639 unsigned int id; 640 641 if (type == MLX5_FLOW_DESTINATION_TYPE_COUNTER) 642 continue; 643 644 switch (type) { 645 case MLX5_FLOW_DESTINATION_TYPE_NONE: 646 continue; 647 case MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE_NUM: 648 id = dst->dest_attr.ft_num; 649 ifc_type = MLX5_IFC_FLOW_DESTINATION_TYPE_FLOW_TABLE; 650 break; 651 case MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE: 652 id = dst->dest_attr.ft->id; 653 ifc_type = MLX5_IFC_FLOW_DESTINATION_TYPE_FLOW_TABLE; 654 break; 655 case MLX5_FLOW_DESTINATION_TYPE_UPLINK: 656 case MLX5_FLOW_DESTINATION_TYPE_VPORT: 657 MLX5_SET(dest_format_struct, in_dests, 658 destination_eswitch_owner_vhca_id_valid, 659 !!(dst->dest_attr.vport.flags & 660 MLX5_FLOW_DEST_VPORT_VHCA_ID)); 661 MLX5_SET(dest_format_struct, in_dests, 662 destination_eswitch_owner_vhca_id, 663 dst->dest_attr.vport.vhca_id); 664 if (type == MLX5_FLOW_DESTINATION_TYPE_UPLINK) { 665 /* destination_id is reserved */ 666 id = 0; 667 ifc_type = MLX5_IFC_FLOW_DESTINATION_TYPE_UPLINK; 668 break; 669 } 670 ifc_type = MLX5_IFC_FLOW_DESTINATION_TYPE_VPORT; 671 id = dst->dest_attr.vport.num; 672 if (extended_dest && 673 dst->dest_attr.vport.pkt_reformat) { 674 MLX5_SET(dest_format_struct, in_dests, 675 packet_reformat, 676 !!(dst->dest_attr.vport.flags & 677 MLX5_FLOW_DEST_VPORT_REFORMAT_ID)); 678 MLX5_SET(extended_dest_format, in_dests, 679 packet_reformat_id, 680 dst->dest_attr.vport.pkt_reformat->id); 681 } 682 break; 683 case MLX5_FLOW_DESTINATION_TYPE_FLOW_SAMPLER: 684 id = dst->dest_attr.sampler_id; 685 ifc_type = MLX5_IFC_FLOW_DESTINATION_TYPE_FLOW_SAMPLER; 686 break; 687 case MLX5_FLOW_DESTINATION_TYPE_TABLE_TYPE: 688 MLX5_SET(dest_format_struct, in_dests, 689 destination_table_type, dst->dest_attr.ft->type); 690 id = dst->dest_attr.ft->id; 691 ifc_type = MLX5_IFC_FLOW_DESTINATION_TYPE_TABLE_TYPE; 692 break; 693 default: 694 id = dst->dest_attr.tir_num; 695 ifc_type = MLX5_IFC_FLOW_DESTINATION_TYPE_TIR; 696 } 697 698 MLX5_SET(dest_format_struct, in_dests, destination_type, 699 ifc_type); 700 MLX5_SET(dest_format_struct, in_dests, destination_id, id); 701 in_dests += dst_cnt_size; 702 list_size++; 703 } 704 705 MLX5_SET(flow_context, in_flow_context, destination_list_size, 706 list_size); 707 } 708 709 if (fte->action.action & MLX5_FLOW_CONTEXT_ACTION_COUNT) { 710 int max_list_size = BIT(MLX5_CAP_FLOWTABLE_TYPE(dev, 711 log_max_flow_counter, 712 ft->type)); 713 int list_size = 0; 714 715 list_for_each_entry(dst, &fte->node.children, node.list) { 716 if (dst->dest_attr.type != 717 MLX5_FLOW_DESTINATION_TYPE_COUNTER) 718 continue; 719 720 MLX5_SET(flow_counter_list, in_dests, flow_counter_id, 721 dst->dest_attr.counter_id); 722 in_dests += dst_cnt_size; 723 list_size++; 724 } 725 if (list_size > max_list_size) { 726 err = -EINVAL; 727 goto err_out; 728 } 729 730 MLX5_SET(flow_context, in_flow_context, flow_counter_list_size, 731 list_size); 732 } 733 734 if (fte->action.action & MLX5_FLOW_CONTEXT_ACTION_EXECUTE_ASO) { 735 if (fte->action.exe_aso.type == MLX5_EXE_ASO_FLOW_METER) { 736 mlx5_cmd_set_fte_flow_meter(fte, in_flow_context); 737 } else { 738 err = -EOPNOTSUPP; 739 goto err_out; 740 } 741 } 742 743 err = mlx5_cmd_exec(dev, in, inlen, out, sizeof(out)); 744 err_out: 745 kvfree(in); 746 return err; 747 } 748 749 static int mlx5_cmd_create_fte(struct mlx5_flow_root_namespace *ns, 750 struct mlx5_flow_table *ft, 751 struct mlx5_flow_group *group, 752 struct fs_fte *fte) 753 { 754 struct mlx5_core_dev *dev = ns->dev; 755 unsigned int group_id = group->id; 756 757 return mlx5_cmd_set_fte(dev, 0, 0, ft, group_id, fte); 758 } 759 760 static int mlx5_cmd_update_fte(struct mlx5_flow_root_namespace *ns, 761 struct mlx5_flow_table *ft, 762 struct mlx5_flow_group *fg, 763 int modify_mask, 764 struct fs_fte *fte) 765 { 766 int opmod; 767 struct mlx5_core_dev *dev = ns->dev; 768 int atomic_mod_cap = MLX5_CAP_FLOWTABLE(dev, 769 flow_table_properties_nic_receive. 770 flow_modify_en); 771 if (!atomic_mod_cap) 772 return -EOPNOTSUPP; 773 opmod = 1; 774 775 return mlx5_cmd_set_fte(dev, opmod, modify_mask, ft, fg->id, fte); 776 } 777 778 static int mlx5_cmd_delete_fte(struct mlx5_flow_root_namespace *ns, 779 struct mlx5_flow_table *ft, 780 struct fs_fte *fte) 781 { 782 u32 in[MLX5_ST_SZ_DW(delete_fte_in)] = {}; 783 struct mlx5_core_dev *dev = ns->dev; 784 785 MLX5_SET(delete_fte_in, in, opcode, MLX5_CMD_OP_DELETE_FLOW_TABLE_ENTRY); 786 MLX5_SET(delete_fte_in, in, table_type, ft->type); 787 MLX5_SET(delete_fte_in, in, table_id, ft->id); 788 MLX5_SET(delete_fte_in, in, flow_index, fte->index); 789 MLX5_SET(delete_fte_in, in, vport_number, ft->vport); 790 MLX5_SET(delete_fte_in, in, other_vport, 791 !!(ft->flags & MLX5_FLOW_TABLE_OTHER_VPORT)); 792 793 return mlx5_cmd_exec_in(dev, delete_fte, in); 794 } 795 796 int mlx5_cmd_fc_bulk_alloc(struct mlx5_core_dev *dev, 797 enum mlx5_fc_bulk_alloc_bitmask alloc_bitmask, 798 u32 *id) 799 { 800 u32 out[MLX5_ST_SZ_DW(alloc_flow_counter_out)] = {}; 801 u32 in[MLX5_ST_SZ_DW(alloc_flow_counter_in)] = {}; 802 int err; 803 804 MLX5_SET(alloc_flow_counter_in, in, opcode, 805 MLX5_CMD_OP_ALLOC_FLOW_COUNTER); 806 MLX5_SET(alloc_flow_counter_in, in, flow_counter_bulk, alloc_bitmask); 807 808 err = mlx5_cmd_exec_inout(dev, alloc_flow_counter, in, out); 809 if (!err) 810 *id = MLX5_GET(alloc_flow_counter_out, out, flow_counter_id); 811 return err; 812 } 813 814 int mlx5_cmd_fc_alloc(struct mlx5_core_dev *dev, u32 *id) 815 { 816 return mlx5_cmd_fc_bulk_alloc(dev, 0, id); 817 } 818 819 int mlx5_cmd_fc_free(struct mlx5_core_dev *dev, u32 id) 820 { 821 u32 in[MLX5_ST_SZ_DW(dealloc_flow_counter_in)] = {}; 822 823 MLX5_SET(dealloc_flow_counter_in, in, opcode, 824 MLX5_CMD_OP_DEALLOC_FLOW_COUNTER); 825 MLX5_SET(dealloc_flow_counter_in, in, flow_counter_id, id); 826 return mlx5_cmd_exec_in(dev, dealloc_flow_counter, in); 827 } 828 829 int mlx5_cmd_fc_query(struct mlx5_core_dev *dev, u32 id, 830 u64 *packets, u64 *bytes) 831 { 832 u32 out[MLX5_ST_SZ_BYTES(query_flow_counter_out) + 833 MLX5_ST_SZ_BYTES(traffic_counter)] = {}; 834 u32 in[MLX5_ST_SZ_DW(query_flow_counter_in)] = {}; 835 void *stats; 836 int err = 0; 837 838 MLX5_SET(query_flow_counter_in, in, opcode, 839 MLX5_CMD_OP_QUERY_FLOW_COUNTER); 840 MLX5_SET(query_flow_counter_in, in, op_mod, 0); 841 MLX5_SET(query_flow_counter_in, in, flow_counter_id, id); 842 err = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out)); 843 if (err) 844 return err; 845 846 stats = MLX5_ADDR_OF(query_flow_counter_out, out, flow_statistics); 847 *packets = MLX5_GET64(traffic_counter, stats, packets); 848 *bytes = MLX5_GET64(traffic_counter, stats, octets); 849 return 0; 850 } 851 852 int mlx5_cmd_fc_get_bulk_query_out_len(int bulk_len) 853 { 854 return MLX5_ST_SZ_BYTES(query_flow_counter_out) + 855 MLX5_ST_SZ_BYTES(traffic_counter) * bulk_len; 856 } 857 858 int mlx5_cmd_fc_bulk_query(struct mlx5_core_dev *dev, u32 base_id, int bulk_len, 859 u32 *out) 860 { 861 int outlen = mlx5_cmd_fc_get_bulk_query_out_len(bulk_len); 862 u32 in[MLX5_ST_SZ_DW(query_flow_counter_in)] = {}; 863 864 MLX5_SET(query_flow_counter_in, in, opcode, 865 MLX5_CMD_OP_QUERY_FLOW_COUNTER); 866 MLX5_SET(query_flow_counter_in, in, flow_counter_id, base_id); 867 MLX5_SET(query_flow_counter_in, in, num_of_counters, bulk_len); 868 return mlx5_cmd_exec(dev, in, sizeof(in), out, outlen); 869 } 870 871 static int mlx5_cmd_packet_reformat_alloc(struct mlx5_flow_root_namespace *ns, 872 struct mlx5_pkt_reformat_params *params, 873 enum mlx5_flow_namespace_type namespace, 874 struct mlx5_pkt_reformat *pkt_reformat) 875 { 876 u32 out[MLX5_ST_SZ_DW(alloc_packet_reformat_context_out)] = {}; 877 struct mlx5_core_dev *dev = ns->dev; 878 void *packet_reformat_context_in; 879 int max_encap_size; 880 void *reformat; 881 int inlen; 882 int err; 883 u32 *in; 884 885 if (namespace == MLX5_FLOW_NAMESPACE_FDB || 886 namespace == MLX5_FLOW_NAMESPACE_FDB_BYPASS) 887 max_encap_size = MLX5_CAP_ESW(dev, max_encap_header_size); 888 else 889 max_encap_size = MLX5_CAP_FLOWTABLE(dev, max_encap_header_size); 890 891 if (params->size > max_encap_size) { 892 mlx5_core_warn(dev, "encap size %zd too big, max supported is %d\n", 893 params->size, max_encap_size); 894 return -EINVAL; 895 } 896 897 in = kzalloc(MLX5_ST_SZ_BYTES(alloc_packet_reformat_context_in) + 898 params->size, GFP_KERNEL); 899 if (!in) 900 return -ENOMEM; 901 902 packet_reformat_context_in = MLX5_ADDR_OF(alloc_packet_reformat_context_in, 903 in, packet_reformat_context); 904 reformat = MLX5_ADDR_OF(packet_reformat_context_in, 905 packet_reformat_context_in, 906 reformat_data); 907 inlen = reformat - (void *)in + params->size; 908 909 MLX5_SET(alloc_packet_reformat_context_in, in, opcode, 910 MLX5_CMD_OP_ALLOC_PACKET_REFORMAT_CONTEXT); 911 MLX5_SET(packet_reformat_context_in, packet_reformat_context_in, 912 reformat_data_size, params->size); 913 MLX5_SET(packet_reformat_context_in, packet_reformat_context_in, 914 reformat_type, params->type); 915 MLX5_SET(packet_reformat_context_in, packet_reformat_context_in, 916 reformat_param_0, params->param_0); 917 MLX5_SET(packet_reformat_context_in, packet_reformat_context_in, 918 reformat_param_1, params->param_1); 919 if (params->data && params->size) 920 memcpy(reformat, params->data, params->size); 921 922 err = mlx5_cmd_exec(dev, in, inlen, out, sizeof(out)); 923 924 pkt_reformat->id = MLX5_GET(alloc_packet_reformat_context_out, 925 out, packet_reformat_id); 926 pkt_reformat->owner = MLX5_FLOW_RESOURCE_OWNER_FW; 927 928 kfree(in); 929 return err; 930 } 931 932 static void mlx5_cmd_packet_reformat_dealloc(struct mlx5_flow_root_namespace *ns, 933 struct mlx5_pkt_reformat *pkt_reformat) 934 { 935 u32 in[MLX5_ST_SZ_DW(dealloc_packet_reformat_context_in)] = {}; 936 struct mlx5_core_dev *dev = ns->dev; 937 938 MLX5_SET(dealloc_packet_reformat_context_in, in, opcode, 939 MLX5_CMD_OP_DEALLOC_PACKET_REFORMAT_CONTEXT); 940 MLX5_SET(dealloc_packet_reformat_context_in, in, packet_reformat_id, 941 pkt_reformat->id); 942 943 mlx5_cmd_exec_in(dev, dealloc_packet_reformat_context, in); 944 } 945 946 static int mlx5_cmd_modify_header_alloc(struct mlx5_flow_root_namespace *ns, 947 u8 namespace, u8 num_actions, 948 void *modify_actions, 949 struct mlx5_modify_hdr *modify_hdr) 950 { 951 u32 out[MLX5_ST_SZ_DW(alloc_modify_header_context_out)] = {}; 952 int max_actions, actions_size, inlen, err; 953 struct mlx5_core_dev *dev = ns->dev; 954 void *actions_in; 955 u8 table_type; 956 u32 *in; 957 958 switch (namespace) { 959 case MLX5_FLOW_NAMESPACE_FDB: 960 case MLX5_FLOW_NAMESPACE_FDB_BYPASS: 961 max_actions = MLX5_CAP_ESW_FLOWTABLE_FDB(dev, max_modify_header_actions); 962 table_type = FS_FT_FDB; 963 break; 964 case MLX5_FLOW_NAMESPACE_KERNEL_RX_MACSEC: 965 case MLX5_FLOW_NAMESPACE_KERNEL: 966 case MLX5_FLOW_NAMESPACE_BYPASS: 967 max_actions = MLX5_CAP_FLOWTABLE_NIC_RX(dev, max_modify_header_actions); 968 table_type = FS_FT_NIC_RX; 969 break; 970 case MLX5_FLOW_NAMESPACE_EGRESS: 971 case MLX5_FLOW_NAMESPACE_EGRESS_IPSEC: 972 case MLX5_FLOW_NAMESPACE_EGRESS_MACSEC: 973 max_actions = MLX5_CAP_FLOWTABLE_NIC_TX(dev, max_modify_header_actions); 974 table_type = FS_FT_NIC_TX; 975 break; 976 case MLX5_FLOW_NAMESPACE_ESW_INGRESS: 977 max_actions = MLX5_CAP_ESW_INGRESS_ACL(dev, max_modify_header_actions); 978 table_type = FS_FT_ESW_INGRESS_ACL; 979 break; 980 case MLX5_FLOW_NAMESPACE_RDMA_TX_MACSEC: 981 case MLX5_FLOW_NAMESPACE_RDMA_TX: 982 max_actions = MLX5_CAP_FLOWTABLE_RDMA_TX(dev, max_modify_header_actions); 983 table_type = FS_FT_RDMA_TX; 984 break; 985 default: 986 return -EOPNOTSUPP; 987 } 988 989 if (num_actions > max_actions) { 990 mlx5_core_warn(dev, "too many modify header actions %d, max supported %d\n", 991 num_actions, max_actions); 992 return -EOPNOTSUPP; 993 } 994 995 actions_size = MLX5_UN_SZ_BYTES(set_add_copy_action_in_auto) * num_actions; 996 inlen = MLX5_ST_SZ_BYTES(alloc_modify_header_context_in) + actions_size; 997 998 in = kzalloc(inlen, GFP_KERNEL); 999 if (!in) 1000 return -ENOMEM; 1001 1002 MLX5_SET(alloc_modify_header_context_in, in, opcode, 1003 MLX5_CMD_OP_ALLOC_MODIFY_HEADER_CONTEXT); 1004 MLX5_SET(alloc_modify_header_context_in, in, table_type, table_type); 1005 MLX5_SET(alloc_modify_header_context_in, in, num_of_actions, num_actions); 1006 1007 actions_in = MLX5_ADDR_OF(alloc_modify_header_context_in, in, actions); 1008 memcpy(actions_in, modify_actions, actions_size); 1009 1010 err = mlx5_cmd_exec(dev, in, inlen, out, sizeof(out)); 1011 1012 modify_hdr->id = MLX5_GET(alloc_modify_header_context_out, out, modify_header_id); 1013 modify_hdr->owner = MLX5_FLOW_RESOURCE_OWNER_FW; 1014 kfree(in); 1015 return err; 1016 } 1017 1018 static void mlx5_cmd_modify_header_dealloc(struct mlx5_flow_root_namespace *ns, 1019 struct mlx5_modify_hdr *modify_hdr) 1020 { 1021 u32 in[MLX5_ST_SZ_DW(dealloc_modify_header_context_in)] = {}; 1022 struct mlx5_core_dev *dev = ns->dev; 1023 1024 MLX5_SET(dealloc_modify_header_context_in, in, opcode, 1025 MLX5_CMD_OP_DEALLOC_MODIFY_HEADER_CONTEXT); 1026 MLX5_SET(dealloc_modify_header_context_in, in, modify_header_id, 1027 modify_hdr->id); 1028 1029 mlx5_cmd_exec_in(dev, dealloc_modify_header_context, in); 1030 } 1031 1032 static int mlx5_cmd_destroy_match_definer(struct mlx5_flow_root_namespace *ns, 1033 int definer_id) 1034 { 1035 u32 in[MLX5_ST_SZ_DW(general_obj_in_cmd_hdr)] = {}; 1036 u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)]; 1037 1038 MLX5_SET(general_obj_in_cmd_hdr, in, opcode, 1039 MLX5_CMD_OP_DESTROY_GENERAL_OBJECT); 1040 MLX5_SET(general_obj_in_cmd_hdr, in, obj_type, 1041 MLX5_OBJ_TYPE_MATCH_DEFINER); 1042 MLX5_SET(general_obj_in_cmd_hdr, in, obj_id, definer_id); 1043 1044 return mlx5_cmd_exec(ns->dev, in, sizeof(in), out, sizeof(out)); 1045 } 1046 1047 static int mlx5_cmd_create_match_definer(struct mlx5_flow_root_namespace *ns, 1048 u16 format_id, u32 *match_mask) 1049 { 1050 u32 out[MLX5_ST_SZ_DW(create_match_definer_out)] = {}; 1051 u32 in[MLX5_ST_SZ_DW(create_match_definer_in)] = {}; 1052 struct mlx5_core_dev *dev = ns->dev; 1053 void *ptr; 1054 int err; 1055 1056 MLX5_SET(create_match_definer_in, in, general_obj_in_cmd_hdr.opcode, 1057 MLX5_CMD_OP_CREATE_GENERAL_OBJECT); 1058 MLX5_SET(create_match_definer_in, in, general_obj_in_cmd_hdr.obj_type, 1059 MLX5_OBJ_TYPE_MATCH_DEFINER); 1060 1061 ptr = MLX5_ADDR_OF(create_match_definer_in, in, obj_context); 1062 MLX5_SET(match_definer, ptr, format_id, format_id); 1063 1064 ptr = MLX5_ADDR_OF(match_definer, ptr, match_mask); 1065 memcpy(ptr, match_mask, MLX5_FLD_SZ_BYTES(match_definer, match_mask)); 1066 1067 err = mlx5_cmd_exec_inout(dev, create_match_definer, in, out); 1068 return err ? err : MLX5_GET(general_obj_out_cmd_hdr, out, obj_id); 1069 } 1070 1071 static u32 mlx5_cmd_get_capabilities(struct mlx5_flow_root_namespace *ns, 1072 enum fs_flow_table_type ft_type) 1073 { 1074 return 0; 1075 } 1076 1077 static const struct mlx5_flow_cmds mlx5_flow_cmds = { 1078 .create_flow_table = mlx5_cmd_create_flow_table, 1079 .destroy_flow_table = mlx5_cmd_destroy_flow_table, 1080 .modify_flow_table = mlx5_cmd_modify_flow_table, 1081 .create_flow_group = mlx5_cmd_create_flow_group, 1082 .destroy_flow_group = mlx5_cmd_destroy_flow_group, 1083 .create_fte = mlx5_cmd_create_fte, 1084 .update_fte = mlx5_cmd_update_fte, 1085 .delete_fte = mlx5_cmd_delete_fte, 1086 .update_root_ft = mlx5_cmd_update_root_ft, 1087 .packet_reformat_alloc = mlx5_cmd_packet_reformat_alloc, 1088 .packet_reformat_dealloc = mlx5_cmd_packet_reformat_dealloc, 1089 .modify_header_alloc = mlx5_cmd_modify_header_alloc, 1090 .modify_header_dealloc = mlx5_cmd_modify_header_dealloc, 1091 .create_match_definer = mlx5_cmd_create_match_definer, 1092 .destroy_match_definer = mlx5_cmd_destroy_match_definer, 1093 .set_peer = mlx5_cmd_stub_set_peer, 1094 .create_ns = mlx5_cmd_stub_create_ns, 1095 .destroy_ns = mlx5_cmd_stub_destroy_ns, 1096 .get_capabilities = mlx5_cmd_get_capabilities, 1097 }; 1098 1099 static const struct mlx5_flow_cmds mlx5_flow_cmd_stubs = { 1100 .create_flow_table = mlx5_cmd_stub_create_flow_table, 1101 .destroy_flow_table = mlx5_cmd_stub_destroy_flow_table, 1102 .modify_flow_table = mlx5_cmd_stub_modify_flow_table, 1103 .create_flow_group = mlx5_cmd_stub_create_flow_group, 1104 .destroy_flow_group = mlx5_cmd_stub_destroy_flow_group, 1105 .create_fte = mlx5_cmd_stub_create_fte, 1106 .update_fte = mlx5_cmd_stub_update_fte, 1107 .delete_fte = mlx5_cmd_stub_delete_fte, 1108 .update_root_ft = mlx5_cmd_stub_update_root_ft, 1109 .packet_reformat_alloc = mlx5_cmd_stub_packet_reformat_alloc, 1110 .packet_reformat_dealloc = mlx5_cmd_stub_packet_reformat_dealloc, 1111 .modify_header_alloc = mlx5_cmd_stub_modify_header_alloc, 1112 .modify_header_dealloc = mlx5_cmd_stub_modify_header_dealloc, 1113 .create_match_definer = mlx5_cmd_stub_create_match_definer, 1114 .destroy_match_definer = mlx5_cmd_stub_destroy_match_definer, 1115 .set_peer = mlx5_cmd_stub_set_peer, 1116 .create_ns = mlx5_cmd_stub_create_ns, 1117 .destroy_ns = mlx5_cmd_stub_destroy_ns, 1118 .get_capabilities = mlx5_cmd_stub_get_capabilities, 1119 }; 1120 1121 const struct mlx5_flow_cmds *mlx5_fs_cmd_get_fw_cmds(void) 1122 { 1123 return &mlx5_flow_cmds; 1124 } 1125 1126 static const struct mlx5_flow_cmds *mlx5_fs_cmd_get_stub_cmds(void) 1127 { 1128 return &mlx5_flow_cmd_stubs; 1129 } 1130 1131 const struct mlx5_flow_cmds *mlx5_fs_cmd_get_default(enum fs_flow_table_type type) 1132 { 1133 switch (type) { 1134 case FS_FT_NIC_RX: 1135 case FS_FT_ESW_EGRESS_ACL: 1136 case FS_FT_ESW_INGRESS_ACL: 1137 case FS_FT_FDB: 1138 case FS_FT_SNIFFER_RX: 1139 case FS_FT_SNIFFER_TX: 1140 case FS_FT_NIC_TX: 1141 case FS_FT_RDMA_RX: 1142 case FS_FT_RDMA_TX: 1143 case FS_FT_PORT_SEL: 1144 return mlx5_fs_cmd_get_fw_cmds(); 1145 default: 1146 return mlx5_fs_cmd_get_stub_cmds(); 1147 } 1148 } 1149