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