1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB 2 /* Copyright (c) 2019 Mellanox Technologies */ 3 4 #include "mlx5_core.h" 5 #include "fs_core.h" 6 #include "fs_cmd.h" 7 #include "mlx5dr.h" 8 #include "fs_dr.h" 9 10 static bool mlx5_dr_is_fw_table(u32 flags) 11 { 12 if (flags & MLX5_FLOW_TABLE_TERMINATION) 13 return true; 14 15 return false; 16 } 17 18 static int mlx5_cmd_dr_update_root_ft(struct mlx5_flow_root_namespace *ns, 19 struct mlx5_flow_table *ft, 20 u32 underlay_qpn, 21 bool disconnect) 22 { 23 return mlx5_fs_cmd_get_fw_cmds()->update_root_ft(ns, ft, underlay_qpn, 24 disconnect); 25 } 26 27 static int set_miss_action(struct mlx5_flow_root_namespace *ns, 28 struct mlx5_flow_table *ft, 29 struct mlx5_flow_table *next_ft) 30 { 31 struct mlx5dr_action *old_miss_action; 32 struct mlx5dr_action *action = NULL; 33 struct mlx5dr_table *next_tbl; 34 int err; 35 36 next_tbl = next_ft ? next_ft->fs_dr_table.dr_table : NULL; 37 if (next_tbl) { 38 action = mlx5dr_action_create_dest_table(next_tbl); 39 if (!action) 40 return -EINVAL; 41 } 42 old_miss_action = ft->fs_dr_table.miss_action; 43 err = mlx5dr_table_set_miss_action(ft->fs_dr_table.dr_table, action); 44 if (err && action) { 45 err = mlx5dr_action_destroy(action); 46 if (err) { 47 action = NULL; 48 mlx5_core_err(ns->dev, "Failed to destroy action (%d)\n", 49 err); 50 } 51 } 52 ft->fs_dr_table.miss_action = action; 53 if (old_miss_action) { 54 err = mlx5dr_action_destroy(old_miss_action); 55 if (err) 56 mlx5_core_err(ns->dev, "Failed to destroy action (%d)\n", 57 err); 58 } 59 60 return err; 61 } 62 63 static int mlx5_cmd_dr_create_flow_table(struct mlx5_flow_root_namespace *ns, 64 struct mlx5_flow_table *ft, 65 unsigned int log_size, 66 struct mlx5_flow_table *next_ft) 67 { 68 struct mlx5dr_table *tbl; 69 u32 flags; 70 int err; 71 72 if (mlx5_dr_is_fw_table(ft->flags)) 73 return mlx5_fs_cmd_get_fw_cmds()->create_flow_table(ns, ft, 74 log_size, 75 next_ft); 76 flags = ft->flags; 77 /* turn off encap/decap if not supported for sw-str by fw */ 78 if (!MLX5_CAP_FLOWTABLE(ns->dev, sw_owner_reformat_supported)) 79 flags = ft->flags & ~(MLX5_FLOW_TABLE_TUNNEL_EN_REFORMAT | 80 MLX5_FLOW_TABLE_TUNNEL_EN_DECAP); 81 82 tbl = mlx5dr_table_create(ns->fs_dr_domain.dr_domain, ft->level, flags); 83 if (!tbl) { 84 mlx5_core_err(ns->dev, "Failed creating dr flow_table\n"); 85 return -EINVAL; 86 } 87 88 ft->fs_dr_table.dr_table = tbl; 89 ft->id = mlx5dr_table_get_id(tbl); 90 91 if (next_ft) { 92 err = set_miss_action(ns, ft, next_ft); 93 if (err) { 94 mlx5dr_table_destroy(tbl); 95 ft->fs_dr_table.dr_table = NULL; 96 return err; 97 } 98 } 99 100 return 0; 101 } 102 103 static int mlx5_cmd_dr_destroy_flow_table(struct mlx5_flow_root_namespace *ns, 104 struct mlx5_flow_table *ft) 105 { 106 struct mlx5dr_action *action = ft->fs_dr_table.miss_action; 107 int err; 108 109 if (mlx5_dr_is_fw_table(ft->flags)) 110 return mlx5_fs_cmd_get_fw_cmds()->destroy_flow_table(ns, ft); 111 112 err = mlx5dr_table_destroy(ft->fs_dr_table.dr_table); 113 if (err) { 114 mlx5_core_err(ns->dev, "Failed to destroy flow_table (%d)\n", 115 err); 116 return err; 117 } 118 if (action) { 119 err = mlx5dr_action_destroy(action); 120 if (err) { 121 mlx5_core_err(ns->dev, "Failed to destroy action(%d)\n", 122 err); 123 return err; 124 } 125 } 126 127 return err; 128 } 129 130 static int mlx5_cmd_dr_modify_flow_table(struct mlx5_flow_root_namespace *ns, 131 struct mlx5_flow_table *ft, 132 struct mlx5_flow_table *next_ft) 133 { 134 return set_miss_action(ns, ft, next_ft); 135 } 136 137 static int mlx5_cmd_dr_create_flow_group(struct mlx5_flow_root_namespace *ns, 138 struct mlx5_flow_table *ft, 139 u32 *in, 140 struct mlx5_flow_group *fg) 141 { 142 struct mlx5dr_matcher *matcher; 143 u32 priority = MLX5_GET(create_flow_group_in, in, 144 start_flow_index); 145 u8 match_criteria_enable = MLX5_GET(create_flow_group_in, 146 in, 147 match_criteria_enable); 148 struct mlx5dr_match_parameters mask; 149 150 if (mlx5_dr_is_fw_table(ft->flags)) 151 return mlx5_fs_cmd_get_fw_cmds()->create_flow_group(ns, ft, in, 152 fg); 153 154 mask.match_buf = MLX5_ADDR_OF(create_flow_group_in, 155 in, match_criteria); 156 mask.match_sz = sizeof(fg->mask.match_criteria); 157 158 matcher = mlx5dr_matcher_create(ft->fs_dr_table.dr_table, 159 priority, 160 match_criteria_enable, 161 &mask); 162 if (!matcher) { 163 mlx5_core_err(ns->dev, "Failed creating matcher\n"); 164 return -EINVAL; 165 } 166 167 fg->fs_dr_matcher.dr_matcher = matcher; 168 return 0; 169 } 170 171 static int mlx5_cmd_dr_destroy_flow_group(struct mlx5_flow_root_namespace *ns, 172 struct mlx5_flow_table *ft, 173 struct mlx5_flow_group *fg) 174 { 175 if (mlx5_dr_is_fw_table(ft->flags)) 176 return mlx5_fs_cmd_get_fw_cmds()->destroy_flow_group(ns, ft, fg); 177 178 return mlx5dr_matcher_destroy(fg->fs_dr_matcher.dr_matcher); 179 } 180 181 static struct mlx5dr_action *create_vport_action(struct mlx5dr_domain *domain, 182 struct mlx5_flow_rule *dst) 183 { 184 struct mlx5_flow_destination *dest_attr = &dst->dest_attr; 185 186 return mlx5dr_action_create_dest_vport(domain, dest_attr->vport.num, 187 dest_attr->vport.flags & 188 MLX5_FLOW_DEST_VPORT_VHCA_ID, 189 dest_attr->vport.vhca_id); 190 } 191 192 static struct mlx5dr_action *create_ft_action(struct mlx5dr_domain *domain, 193 struct mlx5_flow_rule *dst) 194 { 195 struct mlx5_flow_table *dest_ft = dst->dest_attr.ft; 196 197 if (mlx5_dr_is_fw_table(dest_ft->flags)) 198 return mlx5dr_action_create_dest_flow_fw_table(domain, dest_ft); 199 return mlx5dr_action_create_dest_table(dest_ft->fs_dr_table.dr_table); 200 } 201 202 static struct mlx5dr_action *create_action_push_vlan(struct mlx5dr_domain *domain, 203 struct mlx5_fs_vlan *vlan) 204 { 205 u16 n_ethtype = vlan->ethtype; 206 u8 prio = vlan->prio; 207 u16 vid = vlan->vid; 208 u32 vlan_hdr; 209 210 vlan_hdr = (u32)n_ethtype << 16 | (u32)(prio) << 12 | (u32)vid; 211 return mlx5dr_action_create_push_vlan(domain, htonl(vlan_hdr)); 212 } 213 214 static bool contain_vport_reformat_action(struct mlx5_flow_rule *dst) 215 { 216 return dst->dest_attr.type == MLX5_FLOW_DESTINATION_TYPE_VPORT && 217 dst->dest_attr.vport.flags & MLX5_FLOW_DEST_VPORT_REFORMAT_ID; 218 } 219 220 #define MLX5_FLOW_CONTEXT_ACTION_MAX 20 221 static int mlx5_cmd_dr_create_fte(struct mlx5_flow_root_namespace *ns, 222 struct mlx5_flow_table *ft, 223 struct mlx5_flow_group *group, 224 struct fs_fte *fte) 225 { 226 struct mlx5dr_domain *domain = ns->fs_dr_domain.dr_domain; 227 struct mlx5dr_action_dest *term_actions; 228 struct mlx5dr_match_parameters params; 229 struct mlx5_core_dev *dev = ns->dev; 230 struct mlx5dr_action **fs_dr_actions; 231 struct mlx5dr_action *tmp_action; 232 struct mlx5dr_action **actions; 233 bool delay_encap_set = false; 234 struct mlx5dr_rule *rule; 235 struct mlx5_flow_rule *dst; 236 int fs_dr_num_actions = 0; 237 int num_term_actions = 0; 238 int num_actions = 0; 239 size_t match_sz; 240 int err = 0; 241 int i; 242 243 if (mlx5_dr_is_fw_table(ft->flags)) 244 return mlx5_fs_cmd_get_fw_cmds()->create_fte(ns, ft, group, fte); 245 246 actions = kcalloc(MLX5_FLOW_CONTEXT_ACTION_MAX, sizeof(*actions), 247 GFP_KERNEL); 248 if (!actions) { 249 err = -ENOMEM; 250 goto out_err; 251 } 252 253 fs_dr_actions = kcalloc(MLX5_FLOW_CONTEXT_ACTION_MAX, 254 sizeof(*fs_dr_actions), GFP_KERNEL); 255 if (!fs_dr_actions) { 256 err = -ENOMEM; 257 goto free_actions_alloc; 258 } 259 260 term_actions = kcalloc(MLX5_FLOW_CONTEXT_ACTION_MAX, 261 sizeof(*term_actions), GFP_KERNEL); 262 if (!term_actions) { 263 err = -ENOMEM; 264 goto free_fs_dr_actions_alloc; 265 } 266 267 match_sz = sizeof(fte->val); 268 269 /* Drop reformat action bit if destination vport set with reformat */ 270 if (fte->action.action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST) { 271 list_for_each_entry(dst, &fte->node.children, node.list) { 272 if (!contain_vport_reformat_action(dst)) 273 continue; 274 275 fte->action.action &= ~MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT; 276 break; 277 } 278 } 279 280 /* The order of the actions are must to be keep, only the following 281 * order is supported by SW steering: 282 * TX: modify header -> push vlan -> encap 283 * RX: decap -> pop vlan -> modify header 284 */ 285 if (fte->action.action & MLX5_FLOW_CONTEXT_ACTION_DECAP) { 286 enum mlx5dr_action_reformat_type decap_type = 287 DR_ACTION_REFORMAT_TYP_TNL_L2_TO_L2; 288 289 tmp_action = mlx5dr_action_create_packet_reformat(domain, 290 decap_type, 0, 291 NULL); 292 if (!tmp_action) { 293 err = -ENOMEM; 294 goto free_actions; 295 } 296 fs_dr_actions[fs_dr_num_actions++] = tmp_action; 297 actions[num_actions++] = tmp_action; 298 } 299 300 if (fte->action.action & MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT) { 301 bool is_decap = fte->action.pkt_reformat->reformat_type == 302 MLX5_REFORMAT_TYPE_L3_TUNNEL_TO_L2; 303 304 if (is_decap) 305 actions[num_actions++] = 306 fte->action.pkt_reformat->action.dr_action; 307 else 308 delay_encap_set = true; 309 } 310 311 if (fte->action.action & MLX5_FLOW_CONTEXT_ACTION_VLAN_POP) { 312 tmp_action = 313 mlx5dr_action_create_pop_vlan(); 314 if (!tmp_action) { 315 err = -ENOMEM; 316 goto free_actions; 317 } 318 fs_dr_actions[fs_dr_num_actions++] = tmp_action; 319 actions[num_actions++] = tmp_action; 320 } 321 322 if (fte->action.action & MLX5_FLOW_CONTEXT_ACTION_VLAN_POP_2) { 323 tmp_action = 324 mlx5dr_action_create_pop_vlan(); 325 if (!tmp_action) { 326 err = -ENOMEM; 327 goto free_actions; 328 } 329 fs_dr_actions[fs_dr_num_actions++] = tmp_action; 330 actions[num_actions++] = tmp_action; 331 } 332 333 if (fte->action.action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR) 334 actions[num_actions++] = 335 fte->action.modify_hdr->action.dr_action; 336 337 if (fte->action.action & MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH) { 338 tmp_action = create_action_push_vlan(domain, &fte->action.vlan[0]); 339 if (!tmp_action) { 340 err = -ENOMEM; 341 goto free_actions; 342 } 343 fs_dr_actions[fs_dr_num_actions++] = tmp_action; 344 actions[num_actions++] = tmp_action; 345 } 346 347 if (fte->action.action & MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH_2) { 348 tmp_action = create_action_push_vlan(domain, &fte->action.vlan[1]); 349 if (!tmp_action) { 350 err = -ENOMEM; 351 goto free_actions; 352 } 353 fs_dr_actions[fs_dr_num_actions++] = tmp_action; 354 actions[num_actions++] = tmp_action; 355 } 356 357 if (delay_encap_set) 358 actions[num_actions++] = 359 fte->action.pkt_reformat->action.dr_action; 360 361 /* The order of the actions below is not important */ 362 363 if (fte->action.action & MLX5_FLOW_CONTEXT_ACTION_DROP) { 364 tmp_action = mlx5dr_action_create_drop(); 365 if (!tmp_action) { 366 err = -ENOMEM; 367 goto free_actions; 368 } 369 fs_dr_actions[fs_dr_num_actions++] = tmp_action; 370 term_actions[num_term_actions++].dest = tmp_action; 371 } 372 373 if (fte->flow_context.flow_tag) { 374 tmp_action = 375 mlx5dr_action_create_tag(fte->flow_context.flow_tag); 376 if (!tmp_action) { 377 err = -ENOMEM; 378 goto free_actions; 379 } 380 fs_dr_actions[fs_dr_num_actions++] = tmp_action; 381 actions[num_actions++] = tmp_action; 382 } 383 384 if (fte->action.action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST) { 385 list_for_each_entry(dst, &fte->node.children, node.list) { 386 enum mlx5_flow_destination_type type = dst->dest_attr.type; 387 u32 ft_id; 388 389 if (num_actions == MLX5_FLOW_CONTEXT_ACTION_MAX || 390 num_term_actions >= MLX5_FLOW_CONTEXT_ACTION_MAX) { 391 err = -ENOSPC; 392 goto free_actions; 393 } 394 395 if (type == MLX5_FLOW_DESTINATION_TYPE_COUNTER) 396 continue; 397 398 switch (type) { 399 case MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE: 400 tmp_action = create_ft_action(domain, dst); 401 if (!tmp_action) { 402 err = -ENOMEM; 403 goto free_actions; 404 } 405 fs_dr_actions[fs_dr_num_actions++] = tmp_action; 406 term_actions[num_term_actions++].dest = tmp_action; 407 break; 408 case MLX5_FLOW_DESTINATION_TYPE_VPORT: 409 tmp_action = create_vport_action(domain, dst); 410 if (!tmp_action) { 411 err = -ENOMEM; 412 goto free_actions; 413 } 414 fs_dr_actions[fs_dr_num_actions++] = tmp_action; 415 term_actions[num_term_actions].dest = tmp_action; 416 417 if (dst->dest_attr.vport.flags & 418 MLX5_FLOW_DEST_VPORT_REFORMAT_ID) 419 term_actions[num_term_actions].reformat = 420 dst->dest_attr.vport.pkt_reformat->action.dr_action; 421 422 num_term_actions++; 423 break; 424 case MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE_NUM: 425 ft_id = dst->dest_attr.ft_num; 426 tmp_action = mlx5dr_action_create_dest_table_num(domain, 427 ft_id); 428 if (!tmp_action) { 429 err = -ENOMEM; 430 goto free_actions; 431 } 432 fs_dr_actions[fs_dr_num_actions++] = tmp_action; 433 term_actions[num_term_actions++].dest = tmp_action; 434 break; 435 default: 436 err = -EOPNOTSUPP; 437 goto free_actions; 438 } 439 } 440 } 441 442 if (fte->action.action & MLX5_FLOW_CONTEXT_ACTION_COUNT) { 443 list_for_each_entry(dst, &fte->node.children, node.list) { 444 u32 id; 445 446 if (dst->dest_attr.type != 447 MLX5_FLOW_DESTINATION_TYPE_COUNTER) 448 continue; 449 450 if (num_actions == MLX5_FLOW_CONTEXT_ACTION_MAX) { 451 err = -ENOSPC; 452 goto free_actions; 453 } 454 455 id = dst->dest_attr.counter_id; 456 tmp_action = 457 mlx5dr_action_create_flow_counter(id); 458 if (!tmp_action) { 459 err = -ENOMEM; 460 goto free_actions; 461 } 462 463 fs_dr_actions[fs_dr_num_actions++] = tmp_action; 464 actions[num_actions++] = tmp_action; 465 } 466 } 467 468 params.match_sz = match_sz; 469 params.match_buf = (u64 *)fte->val; 470 if (num_term_actions == 1) { 471 if (term_actions->reformat) 472 actions[num_actions++] = term_actions->reformat; 473 474 actions[num_actions++] = term_actions->dest; 475 } else if (num_term_actions > 1) { 476 tmp_action = mlx5dr_action_create_mult_dest_tbl(domain, 477 term_actions, 478 num_term_actions); 479 if (!tmp_action) { 480 err = -EOPNOTSUPP; 481 goto free_actions; 482 } 483 fs_dr_actions[fs_dr_num_actions++] = tmp_action; 484 actions[num_actions++] = tmp_action; 485 } 486 487 rule = mlx5dr_rule_create(group->fs_dr_matcher.dr_matcher, 488 ¶ms, 489 num_actions, 490 actions, 491 fte->flow_context.flow_source); 492 if (!rule) { 493 err = -EINVAL; 494 goto free_actions; 495 } 496 497 kfree(term_actions); 498 kfree(actions); 499 500 fte->fs_dr_rule.dr_rule = rule; 501 fte->fs_dr_rule.num_actions = fs_dr_num_actions; 502 fte->fs_dr_rule.dr_actions = fs_dr_actions; 503 504 return 0; 505 506 free_actions: 507 /* Free in reverse order to handle action dependencies */ 508 for (i = fs_dr_num_actions - 1; i >= 0; i--) 509 if (!IS_ERR_OR_NULL(fs_dr_actions[i])) 510 mlx5dr_action_destroy(fs_dr_actions[i]); 511 512 kfree(term_actions); 513 free_fs_dr_actions_alloc: 514 kfree(fs_dr_actions); 515 free_actions_alloc: 516 kfree(actions); 517 out_err: 518 mlx5_core_err(dev, "Failed to create dr rule err(%d)\n", err); 519 return err; 520 } 521 522 static int mlx5_cmd_dr_packet_reformat_alloc(struct mlx5_flow_root_namespace *ns, 523 int reformat_type, 524 size_t size, 525 void *reformat_data, 526 enum mlx5_flow_namespace_type namespace, 527 struct mlx5_pkt_reformat *pkt_reformat) 528 { 529 struct mlx5dr_domain *dr_domain = ns->fs_dr_domain.dr_domain; 530 struct mlx5dr_action *action; 531 int dr_reformat; 532 533 switch (reformat_type) { 534 case MLX5_REFORMAT_TYPE_L2_TO_VXLAN: 535 case MLX5_REFORMAT_TYPE_L2_TO_NVGRE: 536 case MLX5_REFORMAT_TYPE_L2_TO_L2_TUNNEL: 537 dr_reformat = DR_ACTION_REFORMAT_TYP_L2_TO_TNL_L2; 538 break; 539 case MLX5_REFORMAT_TYPE_L3_TUNNEL_TO_L2: 540 dr_reformat = DR_ACTION_REFORMAT_TYP_TNL_L3_TO_L2; 541 break; 542 case MLX5_REFORMAT_TYPE_L2_TO_L3_TUNNEL: 543 dr_reformat = DR_ACTION_REFORMAT_TYP_L2_TO_TNL_L3; 544 break; 545 default: 546 mlx5_core_err(ns->dev, "Packet-reformat not supported(%d)\n", 547 reformat_type); 548 return -EOPNOTSUPP; 549 } 550 551 action = mlx5dr_action_create_packet_reformat(dr_domain, 552 dr_reformat, 553 size, 554 reformat_data); 555 if (!action) { 556 mlx5_core_err(ns->dev, "Failed allocating packet-reformat action\n"); 557 return -EINVAL; 558 } 559 560 pkt_reformat->action.dr_action = action; 561 562 return 0; 563 } 564 565 static void mlx5_cmd_dr_packet_reformat_dealloc(struct mlx5_flow_root_namespace *ns, 566 struct mlx5_pkt_reformat *pkt_reformat) 567 { 568 mlx5dr_action_destroy(pkt_reformat->action.dr_action); 569 } 570 571 static int mlx5_cmd_dr_modify_header_alloc(struct mlx5_flow_root_namespace *ns, 572 u8 namespace, u8 num_actions, 573 void *modify_actions, 574 struct mlx5_modify_hdr *modify_hdr) 575 { 576 struct mlx5dr_domain *dr_domain = ns->fs_dr_domain.dr_domain; 577 struct mlx5dr_action *action; 578 size_t actions_sz; 579 580 actions_sz = MLX5_UN_SZ_BYTES(set_add_copy_action_in_auto) * 581 num_actions; 582 action = mlx5dr_action_create_modify_header(dr_domain, 0, 583 actions_sz, 584 modify_actions); 585 if (!action) { 586 mlx5_core_err(ns->dev, "Failed allocating modify-header action\n"); 587 return -EINVAL; 588 } 589 590 modify_hdr->action.dr_action = action; 591 592 return 0; 593 } 594 595 static void mlx5_cmd_dr_modify_header_dealloc(struct mlx5_flow_root_namespace *ns, 596 struct mlx5_modify_hdr *modify_hdr) 597 { 598 mlx5dr_action_destroy(modify_hdr->action.dr_action); 599 } 600 601 static int mlx5_cmd_dr_update_fte(struct mlx5_flow_root_namespace *ns, 602 struct mlx5_flow_table *ft, 603 struct mlx5_flow_group *group, 604 int modify_mask, 605 struct fs_fte *fte) 606 { 607 return -EOPNOTSUPP; 608 } 609 610 static int mlx5_cmd_dr_delete_fte(struct mlx5_flow_root_namespace *ns, 611 struct mlx5_flow_table *ft, 612 struct fs_fte *fte) 613 { 614 struct mlx5_fs_dr_rule *rule = &fte->fs_dr_rule; 615 int err; 616 int i; 617 618 if (mlx5_dr_is_fw_table(ft->flags)) 619 return mlx5_fs_cmd_get_fw_cmds()->delete_fte(ns, ft, fte); 620 621 err = mlx5dr_rule_destroy(rule->dr_rule); 622 if (err) 623 return err; 624 625 /* Free in reverse order to handle action dependencies */ 626 for (i = rule->num_actions - 1; i >= 0; i--) 627 if (!IS_ERR_OR_NULL(rule->dr_actions[i])) 628 mlx5dr_action_destroy(rule->dr_actions[i]); 629 630 kfree(rule->dr_actions); 631 return 0; 632 } 633 634 static int mlx5_cmd_dr_set_peer(struct mlx5_flow_root_namespace *ns, 635 struct mlx5_flow_root_namespace *peer_ns) 636 { 637 struct mlx5dr_domain *peer_domain = NULL; 638 639 if (peer_ns) 640 peer_domain = peer_ns->fs_dr_domain.dr_domain; 641 mlx5dr_domain_set_peer(ns->fs_dr_domain.dr_domain, 642 peer_domain); 643 return 0; 644 } 645 646 static int mlx5_cmd_dr_create_ns(struct mlx5_flow_root_namespace *ns) 647 { 648 ns->fs_dr_domain.dr_domain = 649 mlx5dr_domain_create(ns->dev, 650 MLX5DR_DOMAIN_TYPE_FDB); 651 if (!ns->fs_dr_domain.dr_domain) { 652 mlx5_core_err(ns->dev, "Failed to create dr flow namespace\n"); 653 return -EOPNOTSUPP; 654 } 655 return 0; 656 } 657 658 static int mlx5_cmd_dr_destroy_ns(struct mlx5_flow_root_namespace *ns) 659 { 660 return mlx5dr_domain_destroy(ns->fs_dr_domain.dr_domain); 661 } 662 663 bool mlx5_fs_dr_is_supported(struct mlx5_core_dev *dev) 664 { 665 return mlx5dr_is_supported(dev); 666 } 667 668 static const struct mlx5_flow_cmds mlx5_flow_cmds_dr = { 669 .create_flow_table = mlx5_cmd_dr_create_flow_table, 670 .destroy_flow_table = mlx5_cmd_dr_destroy_flow_table, 671 .modify_flow_table = mlx5_cmd_dr_modify_flow_table, 672 .create_flow_group = mlx5_cmd_dr_create_flow_group, 673 .destroy_flow_group = mlx5_cmd_dr_destroy_flow_group, 674 .create_fte = mlx5_cmd_dr_create_fte, 675 .update_fte = mlx5_cmd_dr_update_fte, 676 .delete_fte = mlx5_cmd_dr_delete_fte, 677 .update_root_ft = mlx5_cmd_dr_update_root_ft, 678 .packet_reformat_alloc = mlx5_cmd_dr_packet_reformat_alloc, 679 .packet_reformat_dealloc = mlx5_cmd_dr_packet_reformat_dealloc, 680 .modify_header_alloc = mlx5_cmd_dr_modify_header_alloc, 681 .modify_header_dealloc = mlx5_cmd_dr_modify_header_dealloc, 682 .set_peer = mlx5_cmd_dr_set_peer, 683 .create_ns = mlx5_cmd_dr_create_ns, 684 .destroy_ns = mlx5_cmd_dr_destroy_ns, 685 }; 686 687 const struct mlx5_flow_cmds *mlx5_fs_cmd_get_dr_cmds(void) 688 { 689 return &mlx5_flow_cmds_dr; 690 } 691