]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blob - drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
Merge tag 'mlx5-updates-2020-04-30' of git://git.kernel.org/pub/scm/linux/kernel...
[mirror_ubuntu-jammy-kernel.git] / drivers / net / ethernet / mellanox / mlx5 / core / eswitch.c
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/etherdevice.h>
34 #include <linux/mlx5/driver.h>
35 #include <linux/mlx5/mlx5_ifc.h>
36 #include <linux/mlx5/vport.h>
37 #include <linux/mlx5/fs.h>
38 #include "mlx5_core.h"
39 #include "lib/eq.h"
40 #include "eswitch.h"
41 #include "fs_core.h"
42 #include "devlink.h"
43 #include "ecpf.h"
44
45 enum {
46 MLX5_ACTION_NONE = 0,
47 MLX5_ACTION_ADD = 1,
48 MLX5_ACTION_DEL = 2,
49 };
50
51 /* Vport UC/MC hash node */
52 struct vport_addr {
53 struct l2addr_node node;
54 u8 action;
55 u16 vport;
56 struct mlx5_flow_handle *flow_rule;
57 bool mpfs; /* UC MAC was added to MPFs */
58 /* A flag indicating that mac was added due to mc promiscuous vport */
59 bool mc_promisc;
60 };
61
62 static void esw_destroy_legacy_fdb_table(struct mlx5_eswitch *esw);
63 static void esw_cleanup_vepa_rules(struct mlx5_eswitch *esw);
64
65 struct mlx5_vport *__must_check
66 mlx5_eswitch_get_vport(struct mlx5_eswitch *esw, u16 vport_num)
67 {
68 u16 idx;
69
70 if (!esw || !MLX5_CAP_GEN(esw->dev, vport_group_manager))
71 return ERR_PTR(-EPERM);
72
73 idx = mlx5_eswitch_vport_num_to_index(esw, vport_num);
74
75 if (idx > esw->total_vports - 1) {
76 esw_debug(esw->dev, "vport out of range: num(0x%x), idx(0x%x)\n",
77 vport_num, idx);
78 return ERR_PTR(-EINVAL);
79 }
80
81 return &esw->vports[idx];
82 }
83
84 static int arm_vport_context_events_cmd(struct mlx5_core_dev *dev, u16 vport,
85 u32 events_mask)
86 {
87 u32 in[MLX5_ST_SZ_DW(modify_nic_vport_context_in)] = {};
88 void *nic_vport_ctx;
89
90 MLX5_SET(modify_nic_vport_context_in, in,
91 opcode, MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT);
92 MLX5_SET(modify_nic_vport_context_in, in, field_select.change_event, 1);
93 MLX5_SET(modify_nic_vport_context_in, in, vport_number, vport);
94 MLX5_SET(modify_nic_vport_context_in, in, other_vport, 1);
95 nic_vport_ctx = MLX5_ADDR_OF(modify_nic_vport_context_in,
96 in, nic_vport_context);
97
98 MLX5_SET(nic_vport_context, nic_vport_ctx, arm_change_event, 1);
99
100 if (events_mask & MLX5_VPORT_UC_ADDR_CHANGE)
101 MLX5_SET(nic_vport_context, nic_vport_ctx,
102 event_on_uc_address_change, 1);
103 if (events_mask & MLX5_VPORT_MC_ADDR_CHANGE)
104 MLX5_SET(nic_vport_context, nic_vport_ctx,
105 event_on_mc_address_change, 1);
106 if (events_mask & MLX5_VPORT_PROMISC_CHANGE)
107 MLX5_SET(nic_vport_context, nic_vport_ctx,
108 event_on_promisc_change, 1);
109
110 return mlx5_cmd_exec_in(dev, modify_nic_vport_context, in);
111 }
112
113 /* E-Switch vport context HW commands */
114 int mlx5_eswitch_modify_esw_vport_context(struct mlx5_core_dev *dev, u16 vport,
115 bool other_vport, void *in)
116 {
117 MLX5_SET(modify_esw_vport_context_in, in, opcode,
118 MLX5_CMD_OP_MODIFY_ESW_VPORT_CONTEXT);
119 MLX5_SET(modify_esw_vport_context_in, in, vport_number, vport);
120 MLX5_SET(modify_esw_vport_context_in, in, other_vport, other_vport);
121 return mlx5_cmd_exec_in(dev, modify_esw_vport_context, in);
122 }
123
124 static int modify_esw_vport_cvlan(struct mlx5_core_dev *dev, u16 vport,
125 u16 vlan, u8 qos, u8 set_flags)
126 {
127 u32 in[MLX5_ST_SZ_DW(modify_esw_vport_context_in)] = {};
128
129 if (!MLX5_CAP_ESW(dev, vport_cvlan_strip) ||
130 !MLX5_CAP_ESW(dev, vport_cvlan_insert_if_not_exist))
131 return -EOPNOTSUPP;
132
133 esw_debug(dev, "Set Vport[%d] VLAN %d qos %d set=%x\n",
134 vport, vlan, qos, set_flags);
135
136 if (set_flags & SET_VLAN_STRIP)
137 MLX5_SET(modify_esw_vport_context_in, in,
138 esw_vport_context.vport_cvlan_strip, 1);
139
140 if (set_flags & SET_VLAN_INSERT) {
141 /* insert only if no vlan in packet */
142 MLX5_SET(modify_esw_vport_context_in, in,
143 esw_vport_context.vport_cvlan_insert, 1);
144
145 MLX5_SET(modify_esw_vport_context_in, in,
146 esw_vport_context.cvlan_pcp, qos);
147 MLX5_SET(modify_esw_vport_context_in, in,
148 esw_vport_context.cvlan_id, vlan);
149 }
150
151 MLX5_SET(modify_esw_vport_context_in, in,
152 field_select.vport_cvlan_strip, 1);
153 MLX5_SET(modify_esw_vport_context_in, in,
154 field_select.vport_cvlan_insert, 1);
155
156 return mlx5_eswitch_modify_esw_vport_context(dev, vport, true, in);
157 }
158
159 /* E-Switch FDB */
160 static struct mlx5_flow_handle *
161 __esw_fdb_set_vport_rule(struct mlx5_eswitch *esw, u16 vport, bool rx_rule,
162 u8 mac_c[ETH_ALEN], u8 mac_v[ETH_ALEN])
163 {
164 int match_header = (is_zero_ether_addr(mac_c) ? 0 :
165 MLX5_MATCH_OUTER_HEADERS);
166 struct mlx5_flow_handle *flow_rule = NULL;
167 struct mlx5_flow_act flow_act = {0};
168 struct mlx5_flow_destination dest = {};
169 struct mlx5_flow_spec *spec;
170 void *mv_misc = NULL;
171 void *mc_misc = NULL;
172 u8 *dmac_v = NULL;
173 u8 *dmac_c = NULL;
174
175 if (rx_rule)
176 match_header |= MLX5_MATCH_MISC_PARAMETERS;
177
178 spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
179 if (!spec)
180 return NULL;
181
182 dmac_v = MLX5_ADDR_OF(fte_match_param, spec->match_value,
183 outer_headers.dmac_47_16);
184 dmac_c = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
185 outer_headers.dmac_47_16);
186
187 if (match_header & MLX5_MATCH_OUTER_HEADERS) {
188 ether_addr_copy(dmac_v, mac_v);
189 ether_addr_copy(dmac_c, mac_c);
190 }
191
192 if (match_header & MLX5_MATCH_MISC_PARAMETERS) {
193 mv_misc = MLX5_ADDR_OF(fte_match_param, spec->match_value,
194 misc_parameters);
195 mc_misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
196 misc_parameters);
197 MLX5_SET(fte_match_set_misc, mv_misc, source_port, MLX5_VPORT_UPLINK);
198 MLX5_SET_TO_ONES(fte_match_set_misc, mc_misc, source_port);
199 }
200
201 dest.type = MLX5_FLOW_DESTINATION_TYPE_VPORT;
202 dest.vport.num = vport;
203
204 esw_debug(esw->dev,
205 "\tFDB add rule dmac_v(%pM) dmac_c(%pM) -> vport(%d)\n",
206 dmac_v, dmac_c, vport);
207 spec->match_criteria_enable = match_header;
208 flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
209 flow_rule =
210 mlx5_add_flow_rules(esw->fdb_table.legacy.fdb, spec,
211 &flow_act, &dest, 1);
212 if (IS_ERR(flow_rule)) {
213 esw_warn(esw->dev,
214 "FDB: Failed to add flow rule: dmac_v(%pM) dmac_c(%pM) -> vport(%d), err(%ld)\n",
215 dmac_v, dmac_c, vport, PTR_ERR(flow_rule));
216 flow_rule = NULL;
217 }
218
219 kvfree(spec);
220 return flow_rule;
221 }
222
223 static struct mlx5_flow_handle *
224 esw_fdb_set_vport_rule(struct mlx5_eswitch *esw, u8 mac[ETH_ALEN], u16 vport)
225 {
226 u8 mac_c[ETH_ALEN];
227
228 eth_broadcast_addr(mac_c);
229 return __esw_fdb_set_vport_rule(esw, vport, false, mac_c, mac);
230 }
231
232 static struct mlx5_flow_handle *
233 esw_fdb_set_vport_allmulti_rule(struct mlx5_eswitch *esw, u16 vport)
234 {
235 u8 mac_c[ETH_ALEN];
236 u8 mac_v[ETH_ALEN];
237
238 eth_zero_addr(mac_c);
239 eth_zero_addr(mac_v);
240 mac_c[0] = 0x01;
241 mac_v[0] = 0x01;
242 return __esw_fdb_set_vport_rule(esw, vport, false, mac_c, mac_v);
243 }
244
245 static struct mlx5_flow_handle *
246 esw_fdb_set_vport_promisc_rule(struct mlx5_eswitch *esw, u16 vport)
247 {
248 u8 mac_c[ETH_ALEN];
249 u8 mac_v[ETH_ALEN];
250
251 eth_zero_addr(mac_c);
252 eth_zero_addr(mac_v);
253 return __esw_fdb_set_vport_rule(esw, vport, true, mac_c, mac_v);
254 }
255
256 enum {
257 LEGACY_VEPA_PRIO = 0,
258 LEGACY_FDB_PRIO,
259 };
260
261 static int esw_create_legacy_vepa_table(struct mlx5_eswitch *esw)
262 {
263 struct mlx5_flow_table_attr ft_attr = {};
264 struct mlx5_core_dev *dev = esw->dev;
265 struct mlx5_flow_namespace *root_ns;
266 struct mlx5_flow_table *fdb;
267 int err;
268
269 root_ns = mlx5_get_fdb_sub_ns(dev, 0);
270 if (!root_ns) {
271 esw_warn(dev, "Failed to get FDB flow namespace\n");
272 return -EOPNOTSUPP;
273 }
274
275 /* num FTE 2, num FG 2 */
276 ft_attr.prio = LEGACY_VEPA_PRIO;
277 ft_attr.max_fte = 2;
278 ft_attr.autogroup.max_num_groups = 2;
279 fdb = mlx5_create_auto_grouped_flow_table(root_ns, &ft_attr);
280 if (IS_ERR(fdb)) {
281 err = PTR_ERR(fdb);
282 esw_warn(dev, "Failed to create VEPA FDB err %d\n", err);
283 return err;
284 }
285 esw->fdb_table.legacy.vepa_fdb = fdb;
286
287 return 0;
288 }
289
290 static int esw_create_legacy_fdb_table(struct mlx5_eswitch *esw)
291 {
292 int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
293 struct mlx5_flow_table_attr ft_attr = {};
294 struct mlx5_core_dev *dev = esw->dev;
295 struct mlx5_flow_namespace *root_ns;
296 struct mlx5_flow_table *fdb;
297 struct mlx5_flow_group *g;
298 void *match_criteria;
299 int table_size;
300 u32 *flow_group_in;
301 u8 *dmac;
302 int err = 0;
303
304 esw_debug(dev, "Create FDB log_max_size(%d)\n",
305 MLX5_CAP_ESW_FLOWTABLE_FDB(dev, log_max_ft_size));
306
307 root_ns = mlx5_get_fdb_sub_ns(dev, 0);
308 if (!root_ns) {
309 esw_warn(dev, "Failed to get FDB flow namespace\n");
310 return -EOPNOTSUPP;
311 }
312
313 flow_group_in = kvzalloc(inlen, GFP_KERNEL);
314 if (!flow_group_in)
315 return -ENOMEM;
316
317 table_size = BIT(MLX5_CAP_ESW_FLOWTABLE_FDB(dev, log_max_ft_size));
318 ft_attr.max_fte = table_size;
319 ft_attr.prio = LEGACY_FDB_PRIO;
320 fdb = mlx5_create_flow_table(root_ns, &ft_attr);
321 if (IS_ERR(fdb)) {
322 err = PTR_ERR(fdb);
323 esw_warn(dev, "Failed to create FDB Table err %d\n", err);
324 goto out;
325 }
326 esw->fdb_table.legacy.fdb = fdb;
327
328 /* Addresses group : Full match unicast/multicast addresses */
329 MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable,
330 MLX5_MATCH_OUTER_HEADERS);
331 match_criteria = MLX5_ADDR_OF(create_flow_group_in, flow_group_in, match_criteria);
332 dmac = MLX5_ADDR_OF(fte_match_param, match_criteria, outer_headers.dmac_47_16);
333 MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 0);
334 /* Preserve 2 entries for allmulti and promisc rules*/
335 MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, table_size - 3);
336 eth_broadcast_addr(dmac);
337 g = mlx5_create_flow_group(fdb, flow_group_in);
338 if (IS_ERR(g)) {
339 err = PTR_ERR(g);
340 esw_warn(dev, "Failed to create flow group err(%d)\n", err);
341 goto out;
342 }
343 esw->fdb_table.legacy.addr_grp = g;
344
345 /* Allmulti group : One rule that forwards any mcast traffic */
346 MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable,
347 MLX5_MATCH_OUTER_HEADERS);
348 MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, table_size - 2);
349 MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, table_size - 2);
350 eth_zero_addr(dmac);
351 dmac[0] = 0x01;
352 g = mlx5_create_flow_group(fdb, flow_group_in);
353 if (IS_ERR(g)) {
354 err = PTR_ERR(g);
355 esw_warn(dev, "Failed to create allmulti flow group err(%d)\n", err);
356 goto out;
357 }
358 esw->fdb_table.legacy.allmulti_grp = g;
359
360 /* Promiscuous group :
361 * One rule that forward all unmatched traffic from previous groups
362 */
363 eth_zero_addr(dmac);
364 MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable,
365 MLX5_MATCH_MISC_PARAMETERS);
366 MLX5_SET_TO_ONES(fte_match_param, match_criteria, misc_parameters.source_port);
367 MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, table_size - 1);
368 MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, table_size - 1);
369 g = mlx5_create_flow_group(fdb, flow_group_in);
370 if (IS_ERR(g)) {
371 err = PTR_ERR(g);
372 esw_warn(dev, "Failed to create promisc flow group err(%d)\n", err);
373 goto out;
374 }
375 esw->fdb_table.legacy.promisc_grp = g;
376
377 out:
378 if (err)
379 esw_destroy_legacy_fdb_table(esw);
380
381 kvfree(flow_group_in);
382 return err;
383 }
384
385 static void esw_destroy_legacy_vepa_table(struct mlx5_eswitch *esw)
386 {
387 esw_debug(esw->dev, "Destroy VEPA Table\n");
388 if (!esw->fdb_table.legacy.vepa_fdb)
389 return;
390
391 mlx5_destroy_flow_table(esw->fdb_table.legacy.vepa_fdb);
392 esw->fdb_table.legacy.vepa_fdb = NULL;
393 }
394
395 static void esw_destroy_legacy_fdb_table(struct mlx5_eswitch *esw)
396 {
397 esw_debug(esw->dev, "Destroy FDB Table\n");
398 if (!esw->fdb_table.legacy.fdb)
399 return;
400
401 if (esw->fdb_table.legacy.promisc_grp)
402 mlx5_destroy_flow_group(esw->fdb_table.legacy.promisc_grp);
403 if (esw->fdb_table.legacy.allmulti_grp)
404 mlx5_destroy_flow_group(esw->fdb_table.legacy.allmulti_grp);
405 if (esw->fdb_table.legacy.addr_grp)
406 mlx5_destroy_flow_group(esw->fdb_table.legacy.addr_grp);
407 mlx5_destroy_flow_table(esw->fdb_table.legacy.fdb);
408
409 esw->fdb_table.legacy.fdb = NULL;
410 esw->fdb_table.legacy.addr_grp = NULL;
411 esw->fdb_table.legacy.allmulti_grp = NULL;
412 esw->fdb_table.legacy.promisc_grp = NULL;
413 }
414
415 static int esw_create_legacy_table(struct mlx5_eswitch *esw)
416 {
417 int err;
418
419 memset(&esw->fdb_table.legacy, 0, sizeof(struct legacy_fdb));
420
421 err = esw_create_legacy_vepa_table(esw);
422 if (err)
423 return err;
424
425 err = esw_create_legacy_fdb_table(esw);
426 if (err)
427 esw_destroy_legacy_vepa_table(esw);
428
429 return err;
430 }
431
432 static void esw_destroy_legacy_table(struct mlx5_eswitch *esw)
433 {
434 esw_cleanup_vepa_rules(esw);
435 esw_destroy_legacy_fdb_table(esw);
436 esw_destroy_legacy_vepa_table(esw);
437 }
438
439 #define MLX5_LEGACY_SRIOV_VPORT_EVENTS (MLX5_VPORT_UC_ADDR_CHANGE | \
440 MLX5_VPORT_MC_ADDR_CHANGE | \
441 MLX5_VPORT_PROMISC_CHANGE)
442
443 static int esw_legacy_enable(struct mlx5_eswitch *esw)
444 {
445 struct mlx5_vport *vport;
446 int ret, i;
447
448 ret = esw_create_legacy_table(esw);
449 if (ret)
450 return ret;
451
452 mlx5_esw_for_each_vf_vport(esw, i, vport, esw->esw_funcs.num_vfs)
453 vport->info.link_state = MLX5_VPORT_ADMIN_STATE_AUTO;
454
455 ret = mlx5_eswitch_enable_pf_vf_vports(esw, MLX5_LEGACY_SRIOV_VPORT_EVENTS);
456 if (ret)
457 esw_destroy_legacy_table(esw);
458 return ret;
459 }
460
461 static void esw_legacy_disable(struct mlx5_eswitch *esw)
462 {
463 struct esw_mc_addr *mc_promisc;
464
465 mlx5_eswitch_disable_pf_vf_vports(esw);
466
467 mc_promisc = &esw->mc_promisc;
468 if (mc_promisc->uplink_rule)
469 mlx5_del_flow_rules(mc_promisc->uplink_rule);
470
471 esw_destroy_legacy_table(esw);
472 }
473
474 /* E-Switch vport UC/MC lists management */
475 typedef int (*vport_addr_action)(struct mlx5_eswitch *esw,
476 struct vport_addr *vaddr);
477
478 static int esw_add_uc_addr(struct mlx5_eswitch *esw, struct vport_addr *vaddr)
479 {
480 u8 *mac = vaddr->node.addr;
481 u16 vport = vaddr->vport;
482 int err;
483
484 /* Skip mlx5_mpfs_add_mac for eswitch_managers,
485 * it is already done by its netdev in mlx5e_execute_l2_action
486 */
487 if (mlx5_esw_is_manager_vport(esw, vport))
488 goto fdb_add;
489
490 err = mlx5_mpfs_add_mac(esw->dev, mac);
491 if (err) {
492 esw_warn(esw->dev,
493 "Failed to add L2 table mac(%pM) for vport(0x%x), err(%d)\n",
494 mac, vport, err);
495 return err;
496 }
497 vaddr->mpfs = true;
498
499 fdb_add:
500 /* SRIOV is enabled: Forward UC MAC to vport */
501 if (esw->fdb_table.legacy.fdb && esw->mode == MLX5_ESWITCH_LEGACY)
502 vaddr->flow_rule = esw_fdb_set_vport_rule(esw, mac, vport);
503
504 esw_debug(esw->dev, "\tADDED UC MAC: vport[%d] %pM fr(%p)\n",
505 vport, mac, vaddr->flow_rule);
506
507 return 0;
508 }
509
510 static int esw_del_uc_addr(struct mlx5_eswitch *esw, struct vport_addr *vaddr)
511 {
512 u8 *mac = vaddr->node.addr;
513 u16 vport = vaddr->vport;
514 int err = 0;
515
516 /* Skip mlx5_mpfs_del_mac for eswitch managers,
517 * it is already done by its netdev in mlx5e_execute_l2_action
518 */
519 if (!vaddr->mpfs || mlx5_esw_is_manager_vport(esw, vport))
520 goto fdb_del;
521
522 err = mlx5_mpfs_del_mac(esw->dev, mac);
523 if (err)
524 esw_warn(esw->dev,
525 "Failed to del L2 table mac(%pM) for vport(%d), err(%d)\n",
526 mac, vport, err);
527 vaddr->mpfs = false;
528
529 fdb_del:
530 if (vaddr->flow_rule)
531 mlx5_del_flow_rules(vaddr->flow_rule);
532 vaddr->flow_rule = NULL;
533
534 return 0;
535 }
536
537 static void update_allmulti_vports(struct mlx5_eswitch *esw,
538 struct vport_addr *vaddr,
539 struct esw_mc_addr *esw_mc)
540 {
541 u8 *mac = vaddr->node.addr;
542 struct mlx5_vport *vport;
543 u16 i, vport_num;
544
545 mlx5_esw_for_all_vports(esw, i, vport) {
546 struct hlist_head *vport_hash = vport->mc_list;
547 struct vport_addr *iter_vaddr =
548 l2addr_hash_find(vport_hash,
549 mac,
550 struct vport_addr);
551 vport_num = vport->vport;
552 if (IS_ERR_OR_NULL(vport->allmulti_rule) ||
553 vaddr->vport == vport_num)
554 continue;
555 switch (vaddr->action) {
556 case MLX5_ACTION_ADD:
557 if (iter_vaddr)
558 continue;
559 iter_vaddr = l2addr_hash_add(vport_hash, mac,
560 struct vport_addr,
561 GFP_KERNEL);
562 if (!iter_vaddr) {
563 esw_warn(esw->dev,
564 "ALL-MULTI: Failed to add MAC(%pM) to vport[%d] DB\n",
565 mac, vport_num);
566 continue;
567 }
568 iter_vaddr->vport = vport_num;
569 iter_vaddr->flow_rule =
570 esw_fdb_set_vport_rule(esw,
571 mac,
572 vport_num);
573 iter_vaddr->mc_promisc = true;
574 break;
575 case MLX5_ACTION_DEL:
576 if (!iter_vaddr)
577 continue;
578 mlx5_del_flow_rules(iter_vaddr->flow_rule);
579 l2addr_hash_del(iter_vaddr);
580 break;
581 }
582 }
583 }
584
585 static int esw_add_mc_addr(struct mlx5_eswitch *esw, struct vport_addr *vaddr)
586 {
587 struct hlist_head *hash = esw->mc_table;
588 struct esw_mc_addr *esw_mc;
589 u8 *mac = vaddr->node.addr;
590 u16 vport = vaddr->vport;
591
592 if (!esw->fdb_table.legacy.fdb)
593 return 0;
594
595 esw_mc = l2addr_hash_find(hash, mac, struct esw_mc_addr);
596 if (esw_mc)
597 goto add;
598
599 esw_mc = l2addr_hash_add(hash, mac, struct esw_mc_addr, GFP_KERNEL);
600 if (!esw_mc)
601 return -ENOMEM;
602
603 esw_mc->uplink_rule = /* Forward MC MAC to Uplink */
604 esw_fdb_set_vport_rule(esw, mac, MLX5_VPORT_UPLINK);
605
606 /* Add this multicast mac to all the mc promiscuous vports */
607 update_allmulti_vports(esw, vaddr, esw_mc);
608
609 add:
610 /* If the multicast mac is added as a result of mc promiscuous vport,
611 * don't increment the multicast ref count
612 */
613 if (!vaddr->mc_promisc)
614 esw_mc->refcnt++;
615
616 /* Forward MC MAC to vport */
617 vaddr->flow_rule = esw_fdb_set_vport_rule(esw, mac, vport);
618 esw_debug(esw->dev,
619 "\tADDED MC MAC: vport[%d] %pM fr(%p) refcnt(%d) uplinkfr(%p)\n",
620 vport, mac, vaddr->flow_rule,
621 esw_mc->refcnt, esw_mc->uplink_rule);
622 return 0;
623 }
624
625 static int esw_del_mc_addr(struct mlx5_eswitch *esw, struct vport_addr *vaddr)
626 {
627 struct hlist_head *hash = esw->mc_table;
628 struct esw_mc_addr *esw_mc;
629 u8 *mac = vaddr->node.addr;
630 u16 vport = vaddr->vport;
631
632 if (!esw->fdb_table.legacy.fdb)
633 return 0;
634
635 esw_mc = l2addr_hash_find(hash, mac, struct esw_mc_addr);
636 if (!esw_mc) {
637 esw_warn(esw->dev,
638 "Failed to find eswitch MC addr for MAC(%pM) vport(%d)",
639 mac, vport);
640 return -EINVAL;
641 }
642 esw_debug(esw->dev,
643 "\tDELETE MC MAC: vport[%d] %pM fr(%p) refcnt(%d) uplinkfr(%p)\n",
644 vport, mac, vaddr->flow_rule, esw_mc->refcnt,
645 esw_mc->uplink_rule);
646
647 if (vaddr->flow_rule)
648 mlx5_del_flow_rules(vaddr->flow_rule);
649 vaddr->flow_rule = NULL;
650
651 /* If the multicast mac is added as a result of mc promiscuous vport,
652 * don't decrement the multicast ref count.
653 */
654 if (vaddr->mc_promisc || (--esw_mc->refcnt > 0))
655 return 0;
656
657 /* Remove this multicast mac from all the mc promiscuous vports */
658 update_allmulti_vports(esw, vaddr, esw_mc);
659
660 if (esw_mc->uplink_rule)
661 mlx5_del_flow_rules(esw_mc->uplink_rule);
662
663 l2addr_hash_del(esw_mc);
664 return 0;
665 }
666
667 /* Apply vport UC/MC list to HW l2 table and FDB table */
668 static void esw_apply_vport_addr_list(struct mlx5_eswitch *esw,
669 struct mlx5_vport *vport, int list_type)
670 {
671 bool is_uc = list_type == MLX5_NVPRT_LIST_TYPE_UC;
672 vport_addr_action vport_addr_add;
673 vport_addr_action vport_addr_del;
674 struct vport_addr *addr;
675 struct l2addr_node *node;
676 struct hlist_head *hash;
677 struct hlist_node *tmp;
678 int hi;
679
680 vport_addr_add = is_uc ? esw_add_uc_addr :
681 esw_add_mc_addr;
682 vport_addr_del = is_uc ? esw_del_uc_addr :
683 esw_del_mc_addr;
684
685 hash = is_uc ? vport->uc_list : vport->mc_list;
686 for_each_l2hash_node(node, tmp, hash, hi) {
687 addr = container_of(node, struct vport_addr, node);
688 switch (addr->action) {
689 case MLX5_ACTION_ADD:
690 vport_addr_add(esw, addr);
691 addr->action = MLX5_ACTION_NONE;
692 break;
693 case MLX5_ACTION_DEL:
694 vport_addr_del(esw, addr);
695 l2addr_hash_del(addr);
696 break;
697 }
698 }
699 }
700
701 /* Sync vport UC/MC list from vport context */
702 static void esw_update_vport_addr_list(struct mlx5_eswitch *esw,
703 struct mlx5_vport *vport, int list_type)
704 {
705 bool is_uc = list_type == MLX5_NVPRT_LIST_TYPE_UC;
706 u8 (*mac_list)[ETH_ALEN];
707 struct l2addr_node *node;
708 struct vport_addr *addr;
709 struct hlist_head *hash;
710 struct hlist_node *tmp;
711 int size;
712 int err;
713 int hi;
714 int i;
715
716 size = is_uc ? MLX5_MAX_UC_PER_VPORT(esw->dev) :
717 MLX5_MAX_MC_PER_VPORT(esw->dev);
718
719 mac_list = kcalloc(size, ETH_ALEN, GFP_KERNEL);
720 if (!mac_list)
721 return;
722
723 hash = is_uc ? vport->uc_list : vport->mc_list;
724
725 for_each_l2hash_node(node, tmp, hash, hi) {
726 addr = container_of(node, struct vport_addr, node);
727 addr->action = MLX5_ACTION_DEL;
728 }
729
730 if (!vport->enabled)
731 goto out;
732
733 err = mlx5_query_nic_vport_mac_list(esw->dev, vport->vport, list_type,
734 mac_list, &size);
735 if (err)
736 goto out;
737 esw_debug(esw->dev, "vport[%d] context update %s list size (%d)\n",
738 vport->vport, is_uc ? "UC" : "MC", size);
739
740 for (i = 0; i < size; i++) {
741 if (is_uc && !is_valid_ether_addr(mac_list[i]))
742 continue;
743
744 if (!is_uc && !is_multicast_ether_addr(mac_list[i]))
745 continue;
746
747 addr = l2addr_hash_find(hash, mac_list[i], struct vport_addr);
748 if (addr) {
749 addr->action = MLX5_ACTION_NONE;
750 /* If this mac was previously added because of allmulti
751 * promiscuous rx mode, its now converted to be original
752 * vport mac.
753 */
754 if (addr->mc_promisc) {
755 struct esw_mc_addr *esw_mc =
756 l2addr_hash_find(esw->mc_table,
757 mac_list[i],
758 struct esw_mc_addr);
759 if (!esw_mc) {
760 esw_warn(esw->dev,
761 "Failed to MAC(%pM) in mcast DB\n",
762 mac_list[i]);
763 continue;
764 }
765 esw_mc->refcnt++;
766 addr->mc_promisc = false;
767 }
768 continue;
769 }
770
771 addr = l2addr_hash_add(hash, mac_list[i], struct vport_addr,
772 GFP_KERNEL);
773 if (!addr) {
774 esw_warn(esw->dev,
775 "Failed to add MAC(%pM) to vport[%d] DB\n",
776 mac_list[i], vport->vport);
777 continue;
778 }
779 addr->vport = vport->vport;
780 addr->action = MLX5_ACTION_ADD;
781 }
782 out:
783 kfree(mac_list);
784 }
785
786 /* Sync vport UC/MC list from vport context
787 * Must be called after esw_update_vport_addr_list
788 */
789 static void esw_update_vport_mc_promisc(struct mlx5_eswitch *esw,
790 struct mlx5_vport *vport)
791 {
792 struct l2addr_node *node;
793 struct vport_addr *addr;
794 struct hlist_head *hash;
795 struct hlist_node *tmp;
796 int hi;
797
798 hash = vport->mc_list;
799
800 for_each_l2hash_node(node, tmp, esw->mc_table, hi) {
801 u8 *mac = node->addr;
802
803 addr = l2addr_hash_find(hash, mac, struct vport_addr);
804 if (addr) {
805 if (addr->action == MLX5_ACTION_DEL)
806 addr->action = MLX5_ACTION_NONE;
807 continue;
808 }
809 addr = l2addr_hash_add(hash, mac, struct vport_addr,
810 GFP_KERNEL);
811 if (!addr) {
812 esw_warn(esw->dev,
813 "Failed to add allmulti MAC(%pM) to vport[%d] DB\n",
814 mac, vport->vport);
815 continue;
816 }
817 addr->vport = vport->vport;
818 addr->action = MLX5_ACTION_ADD;
819 addr->mc_promisc = true;
820 }
821 }
822
823 /* Apply vport rx mode to HW FDB table */
824 static void esw_apply_vport_rx_mode(struct mlx5_eswitch *esw,
825 struct mlx5_vport *vport,
826 bool promisc, bool mc_promisc)
827 {
828 struct esw_mc_addr *allmulti_addr = &esw->mc_promisc;
829
830 if (IS_ERR_OR_NULL(vport->allmulti_rule) != mc_promisc)
831 goto promisc;
832
833 if (mc_promisc) {
834 vport->allmulti_rule =
835 esw_fdb_set_vport_allmulti_rule(esw, vport->vport);
836 if (!allmulti_addr->uplink_rule)
837 allmulti_addr->uplink_rule =
838 esw_fdb_set_vport_allmulti_rule(esw,
839 MLX5_VPORT_UPLINK);
840 allmulti_addr->refcnt++;
841 } else if (vport->allmulti_rule) {
842 mlx5_del_flow_rules(vport->allmulti_rule);
843 vport->allmulti_rule = NULL;
844
845 if (--allmulti_addr->refcnt > 0)
846 goto promisc;
847
848 if (allmulti_addr->uplink_rule)
849 mlx5_del_flow_rules(allmulti_addr->uplink_rule);
850 allmulti_addr->uplink_rule = NULL;
851 }
852
853 promisc:
854 if (IS_ERR_OR_NULL(vport->promisc_rule) != promisc)
855 return;
856
857 if (promisc) {
858 vport->promisc_rule =
859 esw_fdb_set_vport_promisc_rule(esw, vport->vport);
860 } else if (vport->promisc_rule) {
861 mlx5_del_flow_rules(vport->promisc_rule);
862 vport->promisc_rule = NULL;
863 }
864 }
865
866 /* Sync vport rx mode from vport context */
867 static void esw_update_vport_rx_mode(struct mlx5_eswitch *esw,
868 struct mlx5_vport *vport)
869 {
870 int promisc_all = 0;
871 int promisc_uc = 0;
872 int promisc_mc = 0;
873 int err;
874
875 err = mlx5_query_nic_vport_promisc(esw->dev,
876 vport->vport,
877 &promisc_uc,
878 &promisc_mc,
879 &promisc_all);
880 if (err)
881 return;
882 esw_debug(esw->dev, "vport[%d] context update rx mode promisc_all=%d, all_multi=%d\n",
883 vport->vport, promisc_all, promisc_mc);
884
885 if (!vport->info.trusted || !vport->enabled) {
886 promisc_uc = 0;
887 promisc_mc = 0;
888 promisc_all = 0;
889 }
890
891 esw_apply_vport_rx_mode(esw, vport, promisc_all,
892 (promisc_all || promisc_mc));
893 }
894
895 static void esw_vport_change_handle_locked(struct mlx5_vport *vport)
896 {
897 struct mlx5_core_dev *dev = vport->dev;
898 struct mlx5_eswitch *esw = dev->priv.eswitch;
899 u8 mac[ETH_ALEN];
900
901 mlx5_query_nic_vport_mac_address(dev, vport->vport, true, mac);
902 esw_debug(dev, "vport[%d] Context Changed: perm mac: %pM\n",
903 vport->vport, mac);
904
905 if (vport->enabled_events & MLX5_VPORT_UC_ADDR_CHANGE) {
906 esw_update_vport_addr_list(esw, vport, MLX5_NVPRT_LIST_TYPE_UC);
907 esw_apply_vport_addr_list(esw, vport, MLX5_NVPRT_LIST_TYPE_UC);
908 }
909
910 if (vport->enabled_events & MLX5_VPORT_MC_ADDR_CHANGE)
911 esw_update_vport_addr_list(esw, vport, MLX5_NVPRT_LIST_TYPE_MC);
912
913 if (vport->enabled_events & MLX5_VPORT_PROMISC_CHANGE) {
914 esw_update_vport_rx_mode(esw, vport);
915 if (!IS_ERR_OR_NULL(vport->allmulti_rule))
916 esw_update_vport_mc_promisc(esw, vport);
917 }
918
919 if (vport->enabled_events & (MLX5_VPORT_PROMISC_CHANGE | MLX5_VPORT_MC_ADDR_CHANGE))
920 esw_apply_vport_addr_list(esw, vport, MLX5_NVPRT_LIST_TYPE_MC);
921
922 esw_debug(esw->dev, "vport[%d] Context Changed: Done\n", vport->vport);
923 if (vport->enabled)
924 arm_vport_context_events_cmd(dev, vport->vport,
925 vport->enabled_events);
926 }
927
928 static void esw_vport_change_handler(struct work_struct *work)
929 {
930 struct mlx5_vport *vport =
931 container_of(work, struct mlx5_vport, vport_change_handler);
932 struct mlx5_eswitch *esw = vport->dev->priv.eswitch;
933
934 mutex_lock(&esw->state_lock);
935 esw_vport_change_handle_locked(vport);
936 mutex_unlock(&esw->state_lock);
937 }
938
939 int esw_vport_enable_egress_acl(struct mlx5_eswitch *esw,
940 struct mlx5_vport *vport)
941 {
942 int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
943 struct mlx5_flow_group *vlan_grp = NULL;
944 struct mlx5_flow_group *drop_grp = NULL;
945 struct mlx5_core_dev *dev = esw->dev;
946 struct mlx5_flow_namespace *root_ns;
947 struct mlx5_flow_table *acl;
948 void *match_criteria;
949 u32 *flow_group_in;
950 /* The egress acl table contains 2 rules:
951 * 1)Allow traffic with vlan_tag=vst_vlan_id
952 * 2)Drop all other traffic.
953 */
954 int table_size = 2;
955 int err = 0;
956
957 if (!MLX5_CAP_ESW_EGRESS_ACL(dev, ft_support))
958 return -EOPNOTSUPP;
959
960 if (!IS_ERR_OR_NULL(vport->egress.acl))
961 return 0;
962
963 esw_debug(dev, "Create vport[%d] egress ACL log_max_size(%d)\n",
964 vport->vport, MLX5_CAP_ESW_EGRESS_ACL(dev, log_max_ft_size));
965
966 root_ns = mlx5_get_flow_vport_acl_namespace(dev, MLX5_FLOW_NAMESPACE_ESW_EGRESS,
967 mlx5_eswitch_vport_num_to_index(esw, vport->vport));
968 if (!root_ns) {
969 esw_warn(dev, "Failed to get E-Switch egress flow namespace for vport (%d)\n", vport->vport);
970 return -EOPNOTSUPP;
971 }
972
973 flow_group_in = kvzalloc(inlen, GFP_KERNEL);
974 if (!flow_group_in)
975 return -ENOMEM;
976
977 acl = mlx5_create_vport_flow_table(root_ns, 0, table_size, 0, vport->vport);
978 if (IS_ERR(acl)) {
979 err = PTR_ERR(acl);
980 esw_warn(dev, "Failed to create E-Switch vport[%d] egress flow Table, err(%d)\n",
981 vport->vport, err);
982 goto out;
983 }
984
985 MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS);
986 match_criteria = MLX5_ADDR_OF(create_flow_group_in, flow_group_in, match_criteria);
987 MLX5_SET_TO_ONES(fte_match_param, match_criteria, outer_headers.cvlan_tag);
988 MLX5_SET_TO_ONES(fte_match_param, match_criteria, outer_headers.first_vid);
989 MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 0);
990 MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, 0);
991
992 vlan_grp = mlx5_create_flow_group(acl, flow_group_in);
993 if (IS_ERR(vlan_grp)) {
994 err = PTR_ERR(vlan_grp);
995 esw_warn(dev, "Failed to create E-Switch vport[%d] egress allowed vlans flow group, err(%d)\n",
996 vport->vport, err);
997 goto out;
998 }
999
1000 memset(flow_group_in, 0, inlen);
1001 MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 1);
1002 MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, 1);
1003 drop_grp = mlx5_create_flow_group(acl, flow_group_in);
1004 if (IS_ERR(drop_grp)) {
1005 err = PTR_ERR(drop_grp);
1006 esw_warn(dev, "Failed to create E-Switch vport[%d] egress drop flow group, err(%d)\n",
1007 vport->vport, err);
1008 goto out;
1009 }
1010
1011 vport->egress.acl = acl;
1012 vport->egress.drop_grp = drop_grp;
1013 vport->egress.allowed_vlans_grp = vlan_grp;
1014 out:
1015 kvfree(flow_group_in);
1016 if (err && !IS_ERR_OR_NULL(vlan_grp))
1017 mlx5_destroy_flow_group(vlan_grp);
1018 if (err && !IS_ERR_OR_NULL(acl))
1019 mlx5_destroy_flow_table(acl);
1020 return err;
1021 }
1022
1023 void esw_vport_cleanup_egress_rules(struct mlx5_eswitch *esw,
1024 struct mlx5_vport *vport)
1025 {
1026 if (!IS_ERR_OR_NULL(vport->egress.allowed_vlan)) {
1027 mlx5_del_flow_rules(vport->egress.allowed_vlan);
1028 vport->egress.allowed_vlan = NULL;
1029 }
1030
1031 if (!IS_ERR_OR_NULL(vport->egress.legacy.drop_rule)) {
1032 mlx5_del_flow_rules(vport->egress.legacy.drop_rule);
1033 vport->egress.legacy.drop_rule = NULL;
1034 }
1035 }
1036
1037 void esw_vport_disable_egress_acl(struct mlx5_eswitch *esw,
1038 struct mlx5_vport *vport)
1039 {
1040 if (IS_ERR_OR_NULL(vport->egress.acl))
1041 return;
1042
1043 esw_debug(esw->dev, "Destroy vport[%d] E-Switch egress ACL\n", vport->vport);
1044
1045 esw_vport_cleanup_egress_rules(esw, vport);
1046 mlx5_destroy_flow_group(vport->egress.allowed_vlans_grp);
1047 mlx5_destroy_flow_group(vport->egress.drop_grp);
1048 mlx5_destroy_flow_table(vport->egress.acl);
1049 vport->egress.allowed_vlans_grp = NULL;
1050 vport->egress.drop_grp = NULL;
1051 vport->egress.acl = NULL;
1052 }
1053
1054 static int
1055 esw_vport_create_legacy_ingress_acl_groups(struct mlx5_eswitch *esw,
1056 struct mlx5_vport *vport)
1057 {
1058 int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
1059 struct mlx5_core_dev *dev = esw->dev;
1060 struct mlx5_flow_group *g;
1061 void *match_criteria;
1062 u32 *flow_group_in;
1063 int err;
1064
1065 flow_group_in = kvzalloc(inlen, GFP_KERNEL);
1066 if (!flow_group_in)
1067 return -ENOMEM;
1068
1069 match_criteria = MLX5_ADDR_OF(create_flow_group_in, flow_group_in, match_criteria);
1070
1071 MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS);
1072 MLX5_SET_TO_ONES(fte_match_param, match_criteria, outer_headers.cvlan_tag);
1073 MLX5_SET_TO_ONES(fte_match_param, match_criteria, outer_headers.smac_47_16);
1074 MLX5_SET_TO_ONES(fte_match_param, match_criteria, outer_headers.smac_15_0);
1075 MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 0);
1076 MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, 0);
1077
1078 g = mlx5_create_flow_group(vport->ingress.acl, flow_group_in);
1079 if (IS_ERR(g)) {
1080 err = PTR_ERR(g);
1081 esw_warn(dev, "vport[%d] ingress create untagged spoofchk flow group, err(%d)\n",
1082 vport->vport, err);
1083 goto spoof_err;
1084 }
1085 vport->ingress.legacy.allow_untagged_spoofchk_grp = g;
1086
1087 memset(flow_group_in, 0, inlen);
1088 MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS);
1089 MLX5_SET_TO_ONES(fte_match_param, match_criteria, outer_headers.cvlan_tag);
1090 MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 1);
1091 MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, 1);
1092
1093 g = mlx5_create_flow_group(vport->ingress.acl, flow_group_in);
1094 if (IS_ERR(g)) {
1095 err = PTR_ERR(g);
1096 esw_warn(dev, "vport[%d] ingress create untagged flow group, err(%d)\n",
1097 vport->vport, err);
1098 goto untagged_err;
1099 }
1100 vport->ingress.legacy.allow_untagged_only_grp = g;
1101
1102 memset(flow_group_in, 0, inlen);
1103 MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS);
1104 MLX5_SET_TO_ONES(fte_match_param, match_criteria, outer_headers.smac_47_16);
1105 MLX5_SET_TO_ONES(fte_match_param, match_criteria, outer_headers.smac_15_0);
1106 MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 2);
1107 MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, 2);
1108
1109 g = mlx5_create_flow_group(vport->ingress.acl, flow_group_in);
1110 if (IS_ERR(g)) {
1111 err = PTR_ERR(g);
1112 esw_warn(dev, "vport[%d] ingress create spoofchk flow group, err(%d)\n",
1113 vport->vport, err);
1114 goto allow_spoof_err;
1115 }
1116 vport->ingress.legacy.allow_spoofchk_only_grp = g;
1117
1118 memset(flow_group_in, 0, inlen);
1119 MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 3);
1120 MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, 3);
1121
1122 g = mlx5_create_flow_group(vport->ingress.acl, flow_group_in);
1123 if (IS_ERR(g)) {
1124 err = PTR_ERR(g);
1125 esw_warn(dev, "vport[%d] ingress create drop flow group, err(%d)\n",
1126 vport->vport, err);
1127 goto drop_err;
1128 }
1129 vport->ingress.legacy.drop_grp = g;
1130 kvfree(flow_group_in);
1131 return 0;
1132
1133 drop_err:
1134 if (!IS_ERR_OR_NULL(vport->ingress.legacy.allow_spoofchk_only_grp)) {
1135 mlx5_destroy_flow_group(vport->ingress.legacy.allow_spoofchk_only_grp);
1136 vport->ingress.legacy.allow_spoofchk_only_grp = NULL;
1137 }
1138 allow_spoof_err:
1139 if (!IS_ERR_OR_NULL(vport->ingress.legacy.allow_untagged_only_grp)) {
1140 mlx5_destroy_flow_group(vport->ingress.legacy.allow_untagged_only_grp);
1141 vport->ingress.legacy.allow_untagged_only_grp = NULL;
1142 }
1143 untagged_err:
1144 if (!IS_ERR_OR_NULL(vport->ingress.legacy.allow_untagged_spoofchk_grp)) {
1145 mlx5_destroy_flow_group(vport->ingress.legacy.allow_untagged_spoofchk_grp);
1146 vport->ingress.legacy.allow_untagged_spoofchk_grp = NULL;
1147 }
1148 spoof_err:
1149 kvfree(flow_group_in);
1150 return err;
1151 }
1152
1153 int esw_vport_create_ingress_acl_table(struct mlx5_eswitch *esw,
1154 struct mlx5_vport *vport, int table_size)
1155 {
1156 struct mlx5_core_dev *dev = esw->dev;
1157 struct mlx5_flow_namespace *root_ns;
1158 struct mlx5_flow_table *acl;
1159 int vport_index;
1160 int err;
1161
1162 if (!MLX5_CAP_ESW_INGRESS_ACL(dev, ft_support))
1163 return -EOPNOTSUPP;
1164
1165 esw_debug(dev, "Create vport[%d] ingress ACL log_max_size(%d)\n",
1166 vport->vport, MLX5_CAP_ESW_INGRESS_ACL(dev, log_max_ft_size));
1167
1168 vport_index = mlx5_eswitch_vport_num_to_index(esw, vport->vport);
1169 root_ns = mlx5_get_flow_vport_acl_namespace(dev, MLX5_FLOW_NAMESPACE_ESW_INGRESS,
1170 vport_index);
1171 if (!root_ns) {
1172 esw_warn(dev, "Failed to get E-Switch ingress flow namespace for vport (%d)\n",
1173 vport->vport);
1174 return -EOPNOTSUPP;
1175 }
1176
1177 acl = mlx5_create_vport_flow_table(root_ns, 0, table_size, 0, vport->vport);
1178 if (IS_ERR(acl)) {
1179 err = PTR_ERR(acl);
1180 esw_warn(dev, "vport[%d] ingress create flow Table, err(%d)\n",
1181 vport->vport, err);
1182 return err;
1183 }
1184 vport->ingress.acl = acl;
1185 return 0;
1186 }
1187
1188 void esw_vport_destroy_ingress_acl_table(struct mlx5_vport *vport)
1189 {
1190 if (!vport->ingress.acl)
1191 return;
1192
1193 mlx5_destroy_flow_table(vport->ingress.acl);
1194 vport->ingress.acl = NULL;
1195 }
1196
1197 void esw_vport_cleanup_ingress_rules(struct mlx5_eswitch *esw,
1198 struct mlx5_vport *vport)
1199 {
1200 if (vport->ingress.legacy.drop_rule) {
1201 mlx5_del_flow_rules(vport->ingress.legacy.drop_rule);
1202 vport->ingress.legacy.drop_rule = NULL;
1203 }
1204
1205 if (vport->ingress.allow_rule) {
1206 mlx5_del_flow_rules(vport->ingress.allow_rule);
1207 vport->ingress.allow_rule = NULL;
1208 }
1209 }
1210
1211 static void esw_vport_disable_legacy_ingress_acl(struct mlx5_eswitch *esw,
1212 struct mlx5_vport *vport)
1213 {
1214 if (!vport->ingress.acl)
1215 return;
1216
1217 esw_debug(esw->dev, "Destroy vport[%d] E-Switch ingress ACL\n", vport->vport);
1218
1219 esw_vport_cleanup_ingress_rules(esw, vport);
1220 if (vport->ingress.legacy.allow_spoofchk_only_grp) {
1221 mlx5_destroy_flow_group(vport->ingress.legacy.allow_spoofchk_only_grp);
1222 vport->ingress.legacy.allow_spoofchk_only_grp = NULL;
1223 }
1224 if (vport->ingress.legacy.allow_untagged_only_grp) {
1225 mlx5_destroy_flow_group(vport->ingress.legacy.allow_untagged_only_grp);
1226 vport->ingress.legacy.allow_untagged_only_grp = NULL;
1227 }
1228 if (vport->ingress.legacy.allow_untagged_spoofchk_grp) {
1229 mlx5_destroy_flow_group(vport->ingress.legacy.allow_untagged_spoofchk_grp);
1230 vport->ingress.legacy.allow_untagged_spoofchk_grp = NULL;
1231 }
1232 if (vport->ingress.legacy.drop_grp) {
1233 mlx5_destroy_flow_group(vport->ingress.legacy.drop_grp);
1234 vport->ingress.legacy.drop_grp = NULL;
1235 }
1236 esw_vport_destroy_ingress_acl_table(vport);
1237 }
1238
1239 static int esw_vport_ingress_config(struct mlx5_eswitch *esw,
1240 struct mlx5_vport *vport)
1241 {
1242 struct mlx5_fc *counter = vport->ingress.legacy.drop_counter;
1243 struct mlx5_flow_destination drop_ctr_dst = {0};
1244 struct mlx5_flow_destination *dst = NULL;
1245 struct mlx5_flow_act flow_act = {0};
1246 struct mlx5_flow_spec *spec = NULL;
1247 int dest_num = 0;
1248 int err = 0;
1249 u8 *smac_v;
1250
1251 /* The ingress acl table contains 4 groups
1252 * (2 active rules at the same time -
1253 * 1 allow rule from one of the first 3 groups.
1254 * 1 drop rule from the last group):
1255 * 1)Allow untagged traffic with smac=original mac.
1256 * 2)Allow untagged traffic.
1257 * 3)Allow traffic with smac=original mac.
1258 * 4)Drop all other traffic.
1259 */
1260 int table_size = 4;
1261
1262 esw_vport_cleanup_ingress_rules(esw, vport);
1263
1264 if (!vport->info.vlan && !vport->info.qos && !vport->info.spoofchk) {
1265 esw_vport_disable_legacy_ingress_acl(esw, vport);
1266 return 0;
1267 }
1268
1269 if (!vport->ingress.acl) {
1270 err = esw_vport_create_ingress_acl_table(esw, vport, table_size);
1271 if (err) {
1272 esw_warn(esw->dev,
1273 "vport[%d] enable ingress acl err (%d)\n",
1274 err, vport->vport);
1275 return err;
1276 }
1277
1278 err = esw_vport_create_legacy_ingress_acl_groups(esw, vport);
1279 if (err)
1280 goto out;
1281 }
1282
1283 esw_debug(esw->dev,
1284 "vport[%d] configure ingress rules, vlan(%d) qos(%d)\n",
1285 vport->vport, vport->info.vlan, vport->info.qos);
1286
1287 spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
1288 if (!spec) {
1289 err = -ENOMEM;
1290 goto out;
1291 }
1292
1293 if (vport->info.vlan || vport->info.qos)
1294 MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, outer_headers.cvlan_tag);
1295
1296 if (vport->info.spoofchk) {
1297 MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, outer_headers.smac_47_16);
1298 MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, outer_headers.smac_15_0);
1299 smac_v = MLX5_ADDR_OF(fte_match_param,
1300 spec->match_value,
1301 outer_headers.smac_47_16);
1302 ether_addr_copy(smac_v, vport->info.mac);
1303 }
1304
1305 spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS;
1306 flow_act.action = MLX5_FLOW_CONTEXT_ACTION_ALLOW;
1307 vport->ingress.allow_rule =
1308 mlx5_add_flow_rules(vport->ingress.acl, spec,
1309 &flow_act, NULL, 0);
1310 if (IS_ERR(vport->ingress.allow_rule)) {
1311 err = PTR_ERR(vport->ingress.allow_rule);
1312 esw_warn(esw->dev,
1313 "vport[%d] configure ingress allow rule, err(%d)\n",
1314 vport->vport, err);
1315 vport->ingress.allow_rule = NULL;
1316 goto out;
1317 }
1318
1319 flow_act.action = MLX5_FLOW_CONTEXT_ACTION_DROP;
1320
1321 /* Attach drop flow counter */
1322 if (counter) {
1323 flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_COUNT;
1324 drop_ctr_dst.type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
1325 drop_ctr_dst.counter_id = mlx5_fc_id(counter);
1326 dst = &drop_ctr_dst;
1327 dest_num++;
1328 }
1329 vport->ingress.legacy.drop_rule =
1330 mlx5_add_flow_rules(vport->ingress.acl, NULL,
1331 &flow_act, dst, dest_num);
1332 if (IS_ERR(vport->ingress.legacy.drop_rule)) {
1333 err = PTR_ERR(vport->ingress.legacy.drop_rule);
1334 esw_warn(esw->dev,
1335 "vport[%d] configure ingress drop rule, err(%d)\n",
1336 vport->vport, err);
1337 vport->ingress.legacy.drop_rule = NULL;
1338 goto out;
1339 }
1340 kvfree(spec);
1341 return 0;
1342
1343 out:
1344 esw_vport_disable_legacy_ingress_acl(esw, vport);
1345 kvfree(spec);
1346 return err;
1347 }
1348
1349 int mlx5_esw_create_vport_egress_acl_vlan(struct mlx5_eswitch *esw,
1350 struct mlx5_vport *vport,
1351 u16 vlan_id, u32 flow_action)
1352 {
1353 struct mlx5_flow_act flow_act = {};
1354 struct mlx5_flow_spec *spec;
1355 int err = 0;
1356
1357 if (vport->egress.allowed_vlan)
1358 return -EEXIST;
1359
1360 spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
1361 if (!spec)
1362 return -ENOMEM;
1363
1364 MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, outer_headers.cvlan_tag);
1365 MLX5_SET_TO_ONES(fte_match_param, spec->match_value, outer_headers.cvlan_tag);
1366 MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, outer_headers.first_vid);
1367 MLX5_SET(fte_match_param, spec->match_value, outer_headers.first_vid, vlan_id);
1368
1369 spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS;
1370 flow_act.action = flow_action;
1371 vport->egress.allowed_vlan =
1372 mlx5_add_flow_rules(vport->egress.acl, spec,
1373 &flow_act, NULL, 0);
1374 if (IS_ERR(vport->egress.allowed_vlan)) {
1375 err = PTR_ERR(vport->egress.allowed_vlan);
1376 esw_warn(esw->dev,
1377 "vport[%d] configure egress vlan rule failed, err(%d)\n",
1378 vport->vport, err);
1379 vport->egress.allowed_vlan = NULL;
1380 }
1381
1382 kvfree(spec);
1383 return err;
1384 }
1385
1386 static int esw_vport_egress_config(struct mlx5_eswitch *esw,
1387 struct mlx5_vport *vport)
1388 {
1389 struct mlx5_fc *counter = vport->egress.legacy.drop_counter;
1390 struct mlx5_flow_destination drop_ctr_dst = {0};
1391 struct mlx5_flow_destination *dst = NULL;
1392 struct mlx5_flow_act flow_act = {0};
1393 int dest_num = 0;
1394 int err = 0;
1395
1396 esw_vport_cleanup_egress_rules(esw, vport);
1397
1398 if (!vport->info.vlan && !vport->info.qos) {
1399 esw_vport_disable_egress_acl(esw, vport);
1400 return 0;
1401 }
1402
1403 err = esw_vport_enable_egress_acl(esw, vport);
1404 if (err) {
1405 mlx5_core_warn(esw->dev,
1406 "failed to enable egress acl (%d) on vport[%d]\n",
1407 err, vport->vport);
1408 return err;
1409 }
1410
1411 esw_debug(esw->dev,
1412 "vport[%d] configure egress rules, vlan(%d) qos(%d)\n",
1413 vport->vport, vport->info.vlan, vport->info.qos);
1414
1415 /* Allowed vlan rule */
1416 err = mlx5_esw_create_vport_egress_acl_vlan(esw, vport, vport->info.vlan,
1417 MLX5_FLOW_CONTEXT_ACTION_ALLOW);
1418 if (err)
1419 return err;
1420
1421 flow_act.action = MLX5_FLOW_CONTEXT_ACTION_DROP;
1422
1423 /* Attach egress drop flow counter */
1424 if (counter) {
1425 flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_COUNT;
1426 drop_ctr_dst.type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
1427 drop_ctr_dst.counter_id = mlx5_fc_id(counter);
1428 dst = &drop_ctr_dst;
1429 dest_num++;
1430 }
1431 vport->egress.legacy.drop_rule =
1432 mlx5_add_flow_rules(vport->egress.acl, NULL,
1433 &flow_act, dst, dest_num);
1434 if (IS_ERR(vport->egress.legacy.drop_rule)) {
1435 err = PTR_ERR(vport->egress.legacy.drop_rule);
1436 esw_warn(esw->dev,
1437 "vport[%d] configure egress drop rule failed, err(%d)\n",
1438 vport->vport, err);
1439 vport->egress.legacy.drop_rule = NULL;
1440 }
1441
1442 return err;
1443 }
1444
1445 static bool element_type_supported(struct mlx5_eswitch *esw, int type)
1446 {
1447 const struct mlx5_core_dev *dev = esw->dev;
1448
1449 switch (type) {
1450 case SCHEDULING_CONTEXT_ELEMENT_TYPE_TSAR:
1451 return MLX5_CAP_QOS(dev, esw_element_type) &
1452 ELEMENT_TYPE_CAP_MASK_TASR;
1453 case SCHEDULING_CONTEXT_ELEMENT_TYPE_VPORT:
1454 return MLX5_CAP_QOS(dev, esw_element_type) &
1455 ELEMENT_TYPE_CAP_MASK_VPORT;
1456 case SCHEDULING_CONTEXT_ELEMENT_TYPE_VPORT_TC:
1457 return MLX5_CAP_QOS(dev, esw_element_type) &
1458 ELEMENT_TYPE_CAP_MASK_VPORT_TC;
1459 case SCHEDULING_CONTEXT_ELEMENT_TYPE_PARA_VPORT_TC:
1460 return MLX5_CAP_QOS(dev, esw_element_type) &
1461 ELEMENT_TYPE_CAP_MASK_PARA_VPORT_TC;
1462 }
1463 return false;
1464 }
1465
1466 /* Vport QoS management */
1467 static void esw_create_tsar(struct mlx5_eswitch *esw)
1468 {
1469 u32 tsar_ctx[MLX5_ST_SZ_DW(scheduling_context)] = {0};
1470 struct mlx5_core_dev *dev = esw->dev;
1471 __be32 *attr;
1472 int err;
1473
1474 if (!MLX5_CAP_GEN(dev, qos) || !MLX5_CAP_QOS(dev, esw_scheduling))
1475 return;
1476
1477 if (!element_type_supported(esw, SCHEDULING_CONTEXT_ELEMENT_TYPE_TSAR))
1478 return;
1479
1480 if (esw->qos.enabled)
1481 return;
1482
1483 MLX5_SET(scheduling_context, tsar_ctx, element_type,
1484 SCHEDULING_CONTEXT_ELEMENT_TYPE_TSAR);
1485
1486 attr = MLX5_ADDR_OF(scheduling_context, tsar_ctx, element_attributes);
1487 *attr = cpu_to_be32(TSAR_ELEMENT_TSAR_TYPE_DWRR << 16);
1488
1489 err = mlx5_create_scheduling_element_cmd(dev,
1490 SCHEDULING_HIERARCHY_E_SWITCH,
1491 tsar_ctx,
1492 &esw->qos.root_tsar_id);
1493 if (err) {
1494 esw_warn(esw->dev, "E-Switch create TSAR failed (%d)\n", err);
1495 return;
1496 }
1497
1498 esw->qos.enabled = true;
1499 }
1500
1501 static void esw_destroy_tsar(struct mlx5_eswitch *esw)
1502 {
1503 int err;
1504
1505 if (!esw->qos.enabled)
1506 return;
1507
1508 err = mlx5_destroy_scheduling_element_cmd(esw->dev,
1509 SCHEDULING_HIERARCHY_E_SWITCH,
1510 esw->qos.root_tsar_id);
1511 if (err)
1512 esw_warn(esw->dev, "E-Switch destroy TSAR failed (%d)\n", err);
1513
1514 esw->qos.enabled = false;
1515 }
1516
1517 static int esw_vport_enable_qos(struct mlx5_eswitch *esw,
1518 struct mlx5_vport *vport,
1519 u32 initial_max_rate, u32 initial_bw_share)
1520 {
1521 u32 sched_ctx[MLX5_ST_SZ_DW(scheduling_context)] = {0};
1522 struct mlx5_core_dev *dev = esw->dev;
1523 void *vport_elem;
1524 int err = 0;
1525
1526 if (!esw->qos.enabled || !MLX5_CAP_GEN(dev, qos) ||
1527 !MLX5_CAP_QOS(dev, esw_scheduling))
1528 return 0;
1529
1530 if (vport->qos.enabled)
1531 return -EEXIST;
1532
1533 MLX5_SET(scheduling_context, sched_ctx, element_type,
1534 SCHEDULING_CONTEXT_ELEMENT_TYPE_VPORT);
1535 vport_elem = MLX5_ADDR_OF(scheduling_context, sched_ctx,
1536 element_attributes);
1537 MLX5_SET(vport_element, vport_elem, vport_number, vport->vport);
1538 MLX5_SET(scheduling_context, sched_ctx, parent_element_id,
1539 esw->qos.root_tsar_id);
1540 MLX5_SET(scheduling_context, sched_ctx, max_average_bw,
1541 initial_max_rate);
1542 MLX5_SET(scheduling_context, sched_ctx, bw_share, initial_bw_share);
1543
1544 err = mlx5_create_scheduling_element_cmd(dev,
1545 SCHEDULING_HIERARCHY_E_SWITCH,
1546 sched_ctx,
1547 &vport->qos.esw_tsar_ix);
1548 if (err) {
1549 esw_warn(esw->dev, "E-Switch create TSAR vport element failed (vport=%d,err=%d)\n",
1550 vport->vport, err);
1551 return err;
1552 }
1553
1554 vport->qos.enabled = true;
1555 return 0;
1556 }
1557
1558 static void esw_vport_disable_qos(struct mlx5_eswitch *esw,
1559 struct mlx5_vport *vport)
1560 {
1561 int err;
1562
1563 if (!vport->qos.enabled)
1564 return;
1565
1566 err = mlx5_destroy_scheduling_element_cmd(esw->dev,
1567 SCHEDULING_HIERARCHY_E_SWITCH,
1568 vport->qos.esw_tsar_ix);
1569 if (err)
1570 esw_warn(esw->dev, "E-Switch destroy TSAR vport element failed (vport=%d,err=%d)\n",
1571 vport->vport, err);
1572
1573 vport->qos.enabled = false;
1574 }
1575
1576 static int esw_vport_qos_config(struct mlx5_eswitch *esw,
1577 struct mlx5_vport *vport,
1578 u32 max_rate, u32 bw_share)
1579 {
1580 u32 sched_ctx[MLX5_ST_SZ_DW(scheduling_context)] = {0};
1581 struct mlx5_core_dev *dev = esw->dev;
1582 void *vport_elem;
1583 u32 bitmask = 0;
1584 int err = 0;
1585
1586 if (!MLX5_CAP_GEN(dev, qos) || !MLX5_CAP_QOS(dev, esw_scheduling))
1587 return -EOPNOTSUPP;
1588
1589 if (!vport->qos.enabled)
1590 return -EIO;
1591
1592 MLX5_SET(scheduling_context, sched_ctx, element_type,
1593 SCHEDULING_CONTEXT_ELEMENT_TYPE_VPORT);
1594 vport_elem = MLX5_ADDR_OF(scheduling_context, sched_ctx,
1595 element_attributes);
1596 MLX5_SET(vport_element, vport_elem, vport_number, vport->vport);
1597 MLX5_SET(scheduling_context, sched_ctx, parent_element_id,
1598 esw->qos.root_tsar_id);
1599 MLX5_SET(scheduling_context, sched_ctx, max_average_bw,
1600 max_rate);
1601 MLX5_SET(scheduling_context, sched_ctx, bw_share, bw_share);
1602 bitmask |= MODIFY_SCHEDULING_ELEMENT_IN_MODIFY_BITMASK_MAX_AVERAGE_BW;
1603 bitmask |= MODIFY_SCHEDULING_ELEMENT_IN_MODIFY_BITMASK_BW_SHARE;
1604
1605 err = mlx5_modify_scheduling_element_cmd(dev,
1606 SCHEDULING_HIERARCHY_E_SWITCH,
1607 sched_ctx,
1608 vport->qos.esw_tsar_ix,
1609 bitmask);
1610 if (err) {
1611 esw_warn(esw->dev, "E-Switch modify TSAR vport element failed (vport=%d,err=%d)\n",
1612 vport->vport, err);
1613 return err;
1614 }
1615
1616 return 0;
1617 }
1618
1619 int mlx5_esw_modify_vport_rate(struct mlx5_eswitch *esw, u16 vport_num,
1620 u32 rate_mbps)
1621 {
1622 u32 ctx[MLX5_ST_SZ_DW(scheduling_context)] = {};
1623 struct mlx5_vport *vport;
1624
1625 vport = mlx5_eswitch_get_vport(esw, vport_num);
1626 MLX5_SET(scheduling_context, ctx, max_average_bw, rate_mbps);
1627
1628 return mlx5_modify_scheduling_element_cmd(esw->dev,
1629 SCHEDULING_HIERARCHY_E_SWITCH,
1630 ctx,
1631 vport->qos.esw_tsar_ix,
1632 MODIFY_SCHEDULING_ELEMENT_IN_MODIFY_BITMASK_MAX_AVERAGE_BW);
1633 }
1634
1635 static void node_guid_gen_from_mac(u64 *node_guid, u8 mac[ETH_ALEN])
1636 {
1637 ((u8 *)node_guid)[7] = mac[0];
1638 ((u8 *)node_guid)[6] = mac[1];
1639 ((u8 *)node_guid)[5] = mac[2];
1640 ((u8 *)node_guid)[4] = 0xff;
1641 ((u8 *)node_guid)[3] = 0xfe;
1642 ((u8 *)node_guid)[2] = mac[3];
1643 ((u8 *)node_guid)[1] = mac[4];
1644 ((u8 *)node_guid)[0] = mac[5];
1645 }
1646
1647 static int esw_vport_create_legacy_acl_tables(struct mlx5_eswitch *esw,
1648 struct mlx5_vport *vport)
1649 {
1650 int ret;
1651
1652 /* Only non manager vports need ACL in legacy mode */
1653 if (mlx5_esw_is_manager_vport(esw, vport->vport))
1654 return 0;
1655
1656 if (MLX5_CAP_ESW_INGRESS_ACL(esw->dev, flow_counter)) {
1657 vport->ingress.legacy.drop_counter = mlx5_fc_create(esw->dev, false);
1658 if (IS_ERR(vport->ingress.legacy.drop_counter)) {
1659 esw_warn(esw->dev,
1660 "vport[%d] configure ingress drop rule counter failed\n",
1661 vport->vport);
1662 vport->ingress.legacy.drop_counter = NULL;
1663 }
1664 }
1665
1666 ret = esw_vport_ingress_config(esw, vport);
1667 if (ret)
1668 goto ingress_err;
1669
1670 if (MLX5_CAP_ESW_EGRESS_ACL(esw->dev, flow_counter)) {
1671 vport->egress.legacy.drop_counter = mlx5_fc_create(esw->dev, false);
1672 if (IS_ERR(vport->egress.legacy.drop_counter)) {
1673 esw_warn(esw->dev,
1674 "vport[%d] configure egress drop rule counter failed\n",
1675 vport->vport);
1676 vport->egress.legacy.drop_counter = NULL;
1677 }
1678 }
1679
1680 ret = esw_vport_egress_config(esw, vport);
1681 if (ret)
1682 goto egress_err;
1683
1684 return 0;
1685
1686 egress_err:
1687 esw_vport_disable_legacy_ingress_acl(esw, vport);
1688 mlx5_fc_destroy(esw->dev, vport->egress.legacy.drop_counter);
1689 vport->egress.legacy.drop_counter = NULL;
1690
1691 ingress_err:
1692 mlx5_fc_destroy(esw->dev, vport->ingress.legacy.drop_counter);
1693 vport->ingress.legacy.drop_counter = NULL;
1694 return ret;
1695 }
1696
1697 static int esw_vport_setup_acl(struct mlx5_eswitch *esw,
1698 struct mlx5_vport *vport)
1699 {
1700 if (esw->mode == MLX5_ESWITCH_LEGACY)
1701 return esw_vport_create_legacy_acl_tables(esw, vport);
1702 else
1703 return esw_vport_create_offloads_acl_tables(esw, vport);
1704 }
1705
1706 static void esw_vport_destroy_legacy_acl_tables(struct mlx5_eswitch *esw,
1707 struct mlx5_vport *vport)
1708
1709 {
1710 if (mlx5_esw_is_manager_vport(esw, vport->vport))
1711 return;
1712
1713 esw_vport_disable_egress_acl(esw, vport);
1714 mlx5_fc_destroy(esw->dev, vport->egress.legacy.drop_counter);
1715 vport->egress.legacy.drop_counter = NULL;
1716
1717 esw_vport_disable_legacy_ingress_acl(esw, vport);
1718 mlx5_fc_destroy(esw->dev, vport->ingress.legacy.drop_counter);
1719 vport->ingress.legacy.drop_counter = NULL;
1720 }
1721
1722 static void esw_vport_cleanup_acl(struct mlx5_eswitch *esw,
1723 struct mlx5_vport *vport)
1724 {
1725 if (esw->mode == MLX5_ESWITCH_LEGACY)
1726 esw_vport_destroy_legacy_acl_tables(esw, vport);
1727 else
1728 esw_vport_destroy_offloads_acl_tables(esw, vport);
1729 }
1730
1731 static int esw_vport_setup(struct mlx5_eswitch *esw, struct mlx5_vport *vport)
1732 {
1733 u16 vport_num = vport->vport;
1734 int flags;
1735 int err;
1736
1737 err = esw_vport_setup_acl(esw, vport);
1738 if (err)
1739 return err;
1740
1741 /* Attach vport to the eswitch rate limiter */
1742 esw_vport_enable_qos(esw, vport, vport->info.max_rate, vport->qos.bw_share);
1743
1744 if (mlx5_esw_is_manager_vport(esw, vport_num))
1745 return 0;
1746
1747 mlx5_modify_vport_admin_state(esw->dev,
1748 MLX5_VPORT_STATE_OP_MOD_ESW_VPORT,
1749 vport_num, 1,
1750 vport->info.link_state);
1751
1752 /* Host PF has its own mac/guid. */
1753 if (vport_num) {
1754 mlx5_modify_nic_vport_mac_address(esw->dev, vport_num,
1755 vport->info.mac);
1756 mlx5_modify_nic_vport_node_guid(esw->dev, vport_num,
1757 vport->info.node_guid);
1758 }
1759
1760 flags = (vport->info.vlan || vport->info.qos) ?
1761 SET_VLAN_STRIP | SET_VLAN_INSERT : 0;
1762 modify_esw_vport_cvlan(esw->dev, vport_num, vport->info.vlan,
1763 vport->info.qos, flags);
1764
1765 return 0;
1766 }
1767
1768 /* Don't cleanup vport->info, it's needed to restore vport configuration */
1769 static void esw_vport_cleanup(struct mlx5_eswitch *esw, struct mlx5_vport *vport)
1770 {
1771 u16 vport_num = vport->vport;
1772
1773 if (!mlx5_esw_is_manager_vport(esw, vport_num))
1774 mlx5_modify_vport_admin_state(esw->dev,
1775 MLX5_VPORT_STATE_OP_MOD_ESW_VPORT,
1776 vport_num, 1,
1777 MLX5_VPORT_ADMIN_STATE_DOWN);
1778
1779 esw_vport_disable_qos(esw, vport);
1780 esw_vport_cleanup_acl(esw, vport);
1781 }
1782
1783 static int esw_enable_vport(struct mlx5_eswitch *esw, u16 vport_num,
1784 enum mlx5_eswitch_vport_event enabled_events)
1785 {
1786 struct mlx5_vport *vport;
1787 int ret;
1788
1789 vport = mlx5_eswitch_get_vport(esw, vport_num);
1790
1791 mutex_lock(&esw->state_lock);
1792 WARN_ON(vport->enabled);
1793
1794 esw_debug(esw->dev, "Enabling VPORT(%d)\n", vport_num);
1795
1796 ret = esw_vport_setup(esw, vport);
1797 if (ret)
1798 goto done;
1799
1800 /* Sync with current vport context */
1801 vport->enabled_events = enabled_events;
1802 vport->enabled = true;
1803
1804 /* Esw manager is trusted by default. Host PF (vport 0) is trusted as well
1805 * in smartNIC as it's a vport group manager.
1806 */
1807 if (mlx5_esw_is_manager_vport(esw, vport_num) ||
1808 (!vport_num && mlx5_core_is_ecpf(esw->dev)))
1809 vport->info.trusted = true;
1810
1811 esw_vport_change_handle_locked(vport);
1812
1813 esw->enabled_vports++;
1814 esw_debug(esw->dev, "Enabled VPORT(%d)\n", vport_num);
1815 done:
1816 mutex_unlock(&esw->state_lock);
1817 return ret;
1818 }
1819
1820 static void esw_disable_vport(struct mlx5_eswitch *esw, u16 vport_num)
1821 {
1822 struct mlx5_vport *vport;
1823
1824 vport = mlx5_eswitch_get_vport(esw, vport_num);
1825
1826 mutex_lock(&esw->state_lock);
1827 if (!vport->enabled)
1828 goto done;
1829
1830 esw_debug(esw->dev, "Disabling vport(%d)\n", vport_num);
1831 /* Mark this vport as disabled to discard new events */
1832 vport->enabled = false;
1833
1834 /* Disable events from this vport */
1835 arm_vport_context_events_cmd(esw->dev, vport->vport, 0);
1836 /* We don't assume VFs will cleanup after themselves.
1837 * Calling vport change handler while vport is disabled will cleanup
1838 * the vport resources.
1839 */
1840 esw_vport_change_handle_locked(vport);
1841 vport->enabled_events = 0;
1842 esw_vport_cleanup(esw, vport);
1843 esw->enabled_vports--;
1844
1845 done:
1846 mutex_unlock(&esw->state_lock);
1847 }
1848
1849 static int eswitch_vport_event(struct notifier_block *nb,
1850 unsigned long type, void *data)
1851 {
1852 struct mlx5_eswitch *esw = mlx5_nb_cof(nb, struct mlx5_eswitch, nb);
1853 struct mlx5_eqe *eqe = data;
1854 struct mlx5_vport *vport;
1855 u16 vport_num;
1856
1857 vport_num = be16_to_cpu(eqe->data.vport_change.vport_num);
1858 vport = mlx5_eswitch_get_vport(esw, vport_num);
1859 if (!IS_ERR(vport))
1860 queue_work(esw->work_queue, &vport->vport_change_handler);
1861 return NOTIFY_OK;
1862 }
1863
1864 /**
1865 * mlx5_esw_query_functions - Returns raw output about functions state
1866 * @dev: Pointer to device to query
1867 *
1868 * mlx5_esw_query_functions() allocates and returns functions changed
1869 * raw output memory pointer from device on success. Otherwise returns ERR_PTR.
1870 * Caller must free the memory using kvfree() when valid pointer is returned.
1871 */
1872 const u32 *mlx5_esw_query_functions(struct mlx5_core_dev *dev)
1873 {
1874 int outlen = MLX5_ST_SZ_BYTES(query_esw_functions_out);
1875 u32 in[MLX5_ST_SZ_DW(query_esw_functions_in)] = {};
1876 u32 *out;
1877 int err;
1878
1879 out = kvzalloc(outlen, GFP_KERNEL);
1880 if (!out)
1881 return ERR_PTR(-ENOMEM);
1882
1883 MLX5_SET(query_esw_functions_in, in, opcode,
1884 MLX5_CMD_OP_QUERY_ESW_FUNCTIONS);
1885
1886 err = mlx5_cmd_exec_inout(dev, query_esw_functions, in, out);
1887 if (!err)
1888 return out;
1889
1890 kvfree(out);
1891 return ERR_PTR(err);
1892 }
1893
1894 static void mlx5_eswitch_event_handlers_register(struct mlx5_eswitch *esw)
1895 {
1896 MLX5_NB_INIT(&esw->nb, eswitch_vport_event, NIC_VPORT_CHANGE);
1897 mlx5_eq_notifier_register(esw->dev, &esw->nb);
1898
1899 if (esw->mode == MLX5_ESWITCH_OFFLOADS && mlx5_eswitch_is_funcs_handler(esw->dev)) {
1900 MLX5_NB_INIT(&esw->esw_funcs.nb, mlx5_esw_funcs_changed_handler,
1901 ESW_FUNCTIONS_CHANGED);
1902 mlx5_eq_notifier_register(esw->dev, &esw->esw_funcs.nb);
1903 }
1904 }
1905
1906 static void mlx5_eswitch_event_handlers_unregister(struct mlx5_eswitch *esw)
1907 {
1908 if (esw->mode == MLX5_ESWITCH_OFFLOADS && mlx5_eswitch_is_funcs_handler(esw->dev))
1909 mlx5_eq_notifier_unregister(esw->dev, &esw->esw_funcs.nb);
1910
1911 mlx5_eq_notifier_unregister(esw->dev, &esw->nb);
1912
1913 flush_workqueue(esw->work_queue);
1914 }
1915
1916 static void mlx5_eswitch_clear_vf_vports_info(struct mlx5_eswitch *esw)
1917 {
1918 struct mlx5_vport *vport;
1919 int i;
1920
1921 mlx5_esw_for_each_vf_vport(esw, i, vport, esw->esw_funcs.num_vfs) {
1922 memset(&vport->info, 0, sizeof(vport->info));
1923 vport->info.link_state = MLX5_VPORT_ADMIN_STATE_AUTO;
1924 }
1925 }
1926
1927 /* Public E-Switch API */
1928 #define ESW_ALLOWED(esw) ((esw) && MLX5_ESWITCH_MANAGER((esw)->dev))
1929
1930 int mlx5_eswitch_load_vport(struct mlx5_eswitch *esw, u16 vport_num,
1931 enum mlx5_eswitch_vport_event enabled_events)
1932 {
1933 int err;
1934
1935 err = esw_enable_vport(esw, vport_num, enabled_events);
1936 if (err)
1937 return err;
1938
1939 err = esw_offloads_load_rep(esw, vport_num);
1940 if (err)
1941 goto err_rep;
1942
1943 return err;
1944
1945 err_rep:
1946 esw_disable_vport(esw, vport_num);
1947 return err;
1948 }
1949
1950 void mlx5_eswitch_unload_vport(struct mlx5_eswitch *esw, u16 vport_num)
1951 {
1952 esw_offloads_unload_rep(esw, vport_num);
1953 esw_disable_vport(esw, vport_num);
1954 }
1955
1956 void mlx5_eswitch_unload_vf_vports(struct mlx5_eswitch *esw, u16 num_vfs)
1957 {
1958 int i;
1959
1960 mlx5_esw_for_each_vf_vport_num_reverse(esw, i, num_vfs)
1961 mlx5_eswitch_unload_vport(esw, i);
1962 }
1963
1964 int mlx5_eswitch_load_vf_vports(struct mlx5_eswitch *esw, u16 num_vfs,
1965 enum mlx5_eswitch_vport_event enabled_events)
1966 {
1967 int err;
1968 int i;
1969
1970 mlx5_esw_for_each_vf_vport_num(esw, i, num_vfs) {
1971 err = mlx5_eswitch_load_vport(esw, i, enabled_events);
1972 if (err)
1973 goto vf_err;
1974 }
1975
1976 return 0;
1977
1978 vf_err:
1979 mlx5_eswitch_unload_vf_vports(esw, i - 1);
1980 return err;
1981 }
1982
1983 /* mlx5_eswitch_enable_pf_vf_vports() enables vports of PF, ECPF and VFs
1984 * whichever are present on the eswitch.
1985 */
1986 int
1987 mlx5_eswitch_enable_pf_vf_vports(struct mlx5_eswitch *esw,
1988 enum mlx5_eswitch_vport_event enabled_events)
1989 {
1990 int ret;
1991
1992 /* Enable PF vport */
1993 ret = mlx5_eswitch_load_vport(esw, MLX5_VPORT_PF, enabled_events);
1994 if (ret)
1995 return ret;
1996
1997 /* Enable ECPF vport */
1998 if (mlx5_ecpf_vport_exists(esw->dev)) {
1999 ret = mlx5_eswitch_load_vport(esw, MLX5_VPORT_ECPF, enabled_events);
2000 if (ret)
2001 goto ecpf_err;
2002 }
2003
2004 /* Enable VF vports */
2005 ret = mlx5_eswitch_load_vf_vports(esw, esw->esw_funcs.num_vfs,
2006 enabled_events);
2007 if (ret)
2008 goto vf_err;
2009 return 0;
2010
2011 vf_err:
2012 if (mlx5_ecpf_vport_exists(esw->dev))
2013 mlx5_eswitch_unload_vport(esw, MLX5_VPORT_ECPF);
2014
2015 ecpf_err:
2016 mlx5_eswitch_unload_vport(esw, MLX5_VPORT_PF);
2017 return ret;
2018 }
2019
2020 /* mlx5_eswitch_disable_pf_vf_vports() disables vports of PF, ECPF and VFs
2021 * whichever are previously enabled on the eswitch.
2022 */
2023 void mlx5_eswitch_disable_pf_vf_vports(struct mlx5_eswitch *esw)
2024 {
2025 mlx5_eswitch_unload_vf_vports(esw, esw->esw_funcs.num_vfs);
2026
2027 if (mlx5_ecpf_vport_exists(esw->dev))
2028 mlx5_eswitch_unload_vport(esw, MLX5_VPORT_ECPF);
2029
2030 mlx5_eswitch_unload_vport(esw, MLX5_VPORT_PF);
2031 }
2032
2033 static void mlx5_eswitch_get_devlink_param(struct mlx5_eswitch *esw)
2034 {
2035 struct devlink *devlink = priv_to_devlink(esw->dev);
2036 union devlink_param_value val;
2037 int err;
2038
2039 err = devlink_param_driverinit_value_get(devlink,
2040 MLX5_DEVLINK_PARAM_ID_ESW_LARGE_GROUP_NUM,
2041 &val);
2042 if (!err) {
2043 esw->params.large_group_num = val.vu32;
2044 } else {
2045 esw_warn(esw->dev,
2046 "Devlink can't get param fdb_large_groups, uses default (%d).\n",
2047 ESW_OFFLOADS_DEFAULT_NUM_GROUPS);
2048 esw->params.large_group_num = ESW_OFFLOADS_DEFAULT_NUM_GROUPS;
2049 }
2050 }
2051
2052 static void
2053 mlx5_eswitch_update_num_of_vfs(struct mlx5_eswitch *esw, int num_vfs)
2054 {
2055 const u32 *out;
2056
2057 WARN_ON_ONCE(esw->mode != MLX5_ESWITCH_NONE);
2058
2059 if (num_vfs < 0)
2060 return;
2061
2062 if (!mlx5_core_is_ecpf_esw_manager(esw->dev)) {
2063 esw->esw_funcs.num_vfs = num_vfs;
2064 return;
2065 }
2066
2067 out = mlx5_esw_query_functions(esw->dev);
2068 if (IS_ERR(out))
2069 return;
2070
2071 esw->esw_funcs.num_vfs = MLX5_GET(query_esw_functions_out, out,
2072 host_params_context.host_num_of_vfs);
2073 kvfree(out);
2074 }
2075
2076 /**
2077 * mlx5_eswitch_enable_locked - Enable eswitch
2078 * @esw: Pointer to eswitch
2079 * @mode: Eswitch mode to enable
2080 * @num_vfs: Enable eswitch for given number of VFs. This is optional.
2081 * Valid value are 0, > 0 and MLX5_ESWITCH_IGNORE_NUM_VFS.
2082 * Caller should pass num_vfs > 0 when enabling eswitch for
2083 * vf vports. Caller should pass num_vfs = 0, when eswitch
2084 * is enabled without sriov VFs or when caller
2085 * is unaware of the sriov state of the host PF on ECPF based
2086 * eswitch. Caller should pass < 0 when num_vfs should be
2087 * completely ignored. This is typically the case when eswitch
2088 * is enabled without sriov regardless of PF/ECPF system.
2089 * mlx5_eswitch_enable_locked() Enables eswitch in either legacy or offloads
2090 * mode. If num_vfs >=0 is provided, it setup VF related eswitch vports.
2091 * It returns 0 on success or error code on failure.
2092 */
2093 int mlx5_eswitch_enable_locked(struct mlx5_eswitch *esw, int mode, int num_vfs)
2094 {
2095 int err;
2096
2097 lockdep_assert_held(&esw->mode_lock);
2098
2099 if (!MLX5_CAP_ESW_FLOWTABLE_FDB(esw->dev, ft_support)) {
2100 esw_warn(esw->dev, "FDB is not supported, aborting ...\n");
2101 return -EOPNOTSUPP;
2102 }
2103
2104 if (!MLX5_CAP_ESW_INGRESS_ACL(esw->dev, ft_support))
2105 esw_warn(esw->dev, "ingress ACL is not supported by FW\n");
2106
2107 if (!MLX5_CAP_ESW_EGRESS_ACL(esw->dev, ft_support))
2108 esw_warn(esw->dev, "engress ACL is not supported by FW\n");
2109
2110 mlx5_eswitch_get_devlink_param(esw);
2111
2112 mlx5_eswitch_update_num_of_vfs(esw, num_vfs);
2113
2114 esw_create_tsar(esw);
2115
2116 esw->mode = mode;
2117
2118 mlx5_lag_update(esw->dev);
2119
2120 if (mode == MLX5_ESWITCH_LEGACY) {
2121 err = esw_legacy_enable(esw);
2122 } else {
2123 mlx5_reload_interface(esw->dev, MLX5_INTERFACE_PROTOCOL_ETH);
2124 mlx5_reload_interface(esw->dev, MLX5_INTERFACE_PROTOCOL_IB);
2125 err = esw_offloads_enable(esw);
2126 }
2127
2128 if (err)
2129 goto abort;
2130
2131 mlx5_eswitch_event_handlers_register(esw);
2132
2133 esw_info(esw->dev, "Enable: mode(%s), nvfs(%d), active vports(%d)\n",
2134 mode == MLX5_ESWITCH_LEGACY ? "LEGACY" : "OFFLOADS",
2135 esw->esw_funcs.num_vfs, esw->enabled_vports);
2136
2137 return 0;
2138
2139 abort:
2140 esw->mode = MLX5_ESWITCH_NONE;
2141
2142 if (mode == MLX5_ESWITCH_OFFLOADS) {
2143 mlx5_reload_interface(esw->dev, MLX5_INTERFACE_PROTOCOL_IB);
2144 mlx5_reload_interface(esw->dev, MLX5_INTERFACE_PROTOCOL_ETH);
2145 }
2146
2147 return err;
2148 }
2149
2150 /**
2151 * mlx5_eswitch_enable - Enable eswitch
2152 * @esw: Pointer to eswitch
2153 * @num_vfs: Enable eswitch swich for given number of VFs.
2154 * Caller must pass num_vfs > 0 when enabling eswitch for
2155 * vf vports.
2156 * mlx5_eswitch_enable() returns 0 on success or error code on failure.
2157 */
2158 int mlx5_eswitch_enable(struct mlx5_eswitch *esw, int num_vfs)
2159 {
2160 int ret;
2161
2162 if (!ESW_ALLOWED(esw))
2163 return 0;
2164
2165 mutex_lock(&esw->mode_lock);
2166 ret = mlx5_eswitch_enable_locked(esw, MLX5_ESWITCH_LEGACY, num_vfs);
2167 mutex_unlock(&esw->mode_lock);
2168 return ret;
2169 }
2170
2171 void mlx5_eswitch_disable_locked(struct mlx5_eswitch *esw, bool clear_vf)
2172 {
2173 int old_mode;
2174
2175 lockdep_assert_held_write(&esw->mode_lock);
2176
2177 if (esw->mode == MLX5_ESWITCH_NONE)
2178 return;
2179
2180 esw_info(esw->dev, "Disable: mode(%s), nvfs(%d), active vports(%d)\n",
2181 esw->mode == MLX5_ESWITCH_LEGACY ? "LEGACY" : "OFFLOADS",
2182 esw->esw_funcs.num_vfs, esw->enabled_vports);
2183
2184 mlx5_eswitch_event_handlers_unregister(esw);
2185
2186 if (esw->mode == MLX5_ESWITCH_LEGACY)
2187 esw_legacy_disable(esw);
2188 else if (esw->mode == MLX5_ESWITCH_OFFLOADS)
2189 esw_offloads_disable(esw);
2190
2191 esw_destroy_tsar(esw);
2192
2193 old_mode = esw->mode;
2194 esw->mode = MLX5_ESWITCH_NONE;
2195
2196 mlx5_lag_update(esw->dev);
2197
2198 if (old_mode == MLX5_ESWITCH_OFFLOADS) {
2199 mlx5_reload_interface(esw->dev, MLX5_INTERFACE_PROTOCOL_IB);
2200 mlx5_reload_interface(esw->dev, MLX5_INTERFACE_PROTOCOL_ETH);
2201 }
2202 if (clear_vf)
2203 mlx5_eswitch_clear_vf_vports_info(esw);
2204 }
2205
2206 void mlx5_eswitch_disable(struct mlx5_eswitch *esw, bool clear_vf)
2207 {
2208 if (!ESW_ALLOWED(esw))
2209 return;
2210
2211 mutex_lock(&esw->mode_lock);
2212 mlx5_eswitch_disable_locked(esw, clear_vf);
2213 mutex_unlock(&esw->mode_lock);
2214 }
2215
2216 int mlx5_eswitch_init(struct mlx5_core_dev *dev)
2217 {
2218 struct mlx5_eswitch *esw;
2219 struct mlx5_vport *vport;
2220 int total_vports;
2221 int err, i;
2222
2223 if (!MLX5_VPORT_MANAGER(dev))
2224 return 0;
2225
2226 total_vports = mlx5_eswitch_get_total_vports(dev);
2227
2228 esw_info(dev,
2229 "Total vports %d, per vport: max uc(%d) max mc(%d)\n",
2230 total_vports,
2231 MLX5_MAX_UC_PER_VPORT(dev),
2232 MLX5_MAX_MC_PER_VPORT(dev));
2233
2234 esw = kzalloc(sizeof(*esw), GFP_KERNEL);
2235 if (!esw)
2236 return -ENOMEM;
2237
2238 esw->dev = dev;
2239 esw->manager_vport = mlx5_eswitch_manager_vport(dev);
2240 esw->first_host_vport = mlx5_eswitch_first_host_vport_num(dev);
2241
2242 esw->work_queue = create_singlethread_workqueue("mlx5_esw_wq");
2243 if (!esw->work_queue) {
2244 err = -ENOMEM;
2245 goto abort;
2246 }
2247
2248 esw->vports = kcalloc(total_vports, sizeof(struct mlx5_vport),
2249 GFP_KERNEL);
2250 if (!esw->vports) {
2251 err = -ENOMEM;
2252 goto abort;
2253 }
2254
2255 esw->total_vports = total_vports;
2256
2257 err = esw_offloads_init_reps(esw);
2258 if (err)
2259 goto abort;
2260
2261 mutex_init(&esw->offloads.encap_tbl_lock);
2262 hash_init(esw->offloads.encap_tbl);
2263 mutex_init(&esw->offloads.mod_hdr.lock);
2264 hash_init(esw->offloads.mod_hdr.hlist);
2265 atomic64_set(&esw->offloads.num_flows, 0);
2266 mutex_init(&esw->state_lock);
2267 mutex_init(&esw->mode_lock);
2268
2269 mlx5_esw_for_all_vports(esw, i, vport) {
2270 vport->vport = mlx5_eswitch_index_to_vport_num(esw, i);
2271 vport->info.link_state = MLX5_VPORT_ADMIN_STATE_AUTO;
2272 vport->dev = dev;
2273 INIT_WORK(&vport->vport_change_handler,
2274 esw_vport_change_handler);
2275 }
2276
2277 esw->enabled_vports = 0;
2278 esw->mode = MLX5_ESWITCH_NONE;
2279 esw->offloads.inline_mode = MLX5_INLINE_MODE_NONE;
2280
2281 dev->priv.eswitch = esw;
2282 return 0;
2283 abort:
2284 if (esw->work_queue)
2285 destroy_workqueue(esw->work_queue);
2286 esw_offloads_cleanup_reps(esw);
2287 kfree(esw->vports);
2288 kfree(esw);
2289 return err;
2290 }
2291
2292 void mlx5_eswitch_cleanup(struct mlx5_eswitch *esw)
2293 {
2294 if (!esw || !MLX5_VPORT_MANAGER(esw->dev))
2295 return;
2296
2297 esw_info(esw->dev, "cleanup\n");
2298
2299 esw->dev->priv.eswitch = NULL;
2300 destroy_workqueue(esw->work_queue);
2301 esw_offloads_cleanup_reps(esw);
2302 mutex_destroy(&esw->mode_lock);
2303 mutex_destroy(&esw->state_lock);
2304 mutex_destroy(&esw->offloads.mod_hdr.lock);
2305 mutex_destroy(&esw->offloads.encap_tbl_lock);
2306 kfree(esw->vports);
2307 kfree(esw);
2308 }
2309
2310 /* Vport Administration */
2311 int mlx5_eswitch_set_vport_mac(struct mlx5_eswitch *esw,
2312 u16 vport, u8 mac[ETH_ALEN])
2313 {
2314 struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport);
2315 u64 node_guid;
2316 int err = 0;
2317
2318 if (IS_ERR(evport))
2319 return PTR_ERR(evport);
2320 if (is_multicast_ether_addr(mac))
2321 return -EINVAL;
2322
2323 mutex_lock(&esw->state_lock);
2324
2325 if (evport->info.spoofchk && !is_valid_ether_addr(mac))
2326 mlx5_core_warn(esw->dev,
2327 "Set invalid MAC while spoofchk is on, vport(%d)\n",
2328 vport);
2329
2330 err = mlx5_modify_nic_vport_mac_address(esw->dev, vport, mac);
2331 if (err) {
2332 mlx5_core_warn(esw->dev,
2333 "Failed to mlx5_modify_nic_vport_mac vport(%d) err=(%d)\n",
2334 vport, err);
2335 goto unlock;
2336 }
2337
2338 node_guid_gen_from_mac(&node_guid, mac);
2339 err = mlx5_modify_nic_vport_node_guid(esw->dev, vport, node_guid);
2340 if (err)
2341 mlx5_core_warn(esw->dev,
2342 "Failed to set vport %d node guid, err = %d. RDMA_CM will not function properly for this VF.\n",
2343 vport, err);
2344
2345 ether_addr_copy(evport->info.mac, mac);
2346 evport->info.node_guid = node_guid;
2347 if (evport->enabled && esw->mode == MLX5_ESWITCH_LEGACY)
2348 err = esw_vport_ingress_config(esw, evport);
2349
2350 unlock:
2351 mutex_unlock(&esw->state_lock);
2352 return err;
2353 }
2354
2355 int mlx5_eswitch_set_vport_state(struct mlx5_eswitch *esw,
2356 u16 vport, int link_state)
2357 {
2358 struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport);
2359 int err = 0;
2360
2361 if (!ESW_ALLOWED(esw))
2362 return -EPERM;
2363 if (IS_ERR(evport))
2364 return PTR_ERR(evport);
2365
2366 mutex_lock(&esw->state_lock);
2367
2368 err = mlx5_modify_vport_admin_state(esw->dev,
2369 MLX5_VPORT_STATE_OP_MOD_ESW_VPORT,
2370 vport, 1, link_state);
2371 if (err) {
2372 mlx5_core_warn(esw->dev,
2373 "Failed to set vport %d link state, err = %d",
2374 vport, err);
2375 goto unlock;
2376 }
2377
2378 evport->info.link_state = link_state;
2379
2380 unlock:
2381 mutex_unlock(&esw->state_lock);
2382 return err;
2383 }
2384
2385 int mlx5_eswitch_get_vport_config(struct mlx5_eswitch *esw,
2386 u16 vport, struct ifla_vf_info *ivi)
2387 {
2388 struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport);
2389
2390 if (IS_ERR(evport))
2391 return PTR_ERR(evport);
2392
2393 memset(ivi, 0, sizeof(*ivi));
2394 ivi->vf = vport - 1;
2395
2396 mutex_lock(&esw->state_lock);
2397 ether_addr_copy(ivi->mac, evport->info.mac);
2398 ivi->linkstate = evport->info.link_state;
2399 ivi->vlan = evport->info.vlan;
2400 ivi->qos = evport->info.qos;
2401 ivi->spoofchk = evport->info.spoofchk;
2402 ivi->trusted = evport->info.trusted;
2403 ivi->min_tx_rate = evport->info.min_rate;
2404 ivi->max_tx_rate = evport->info.max_rate;
2405 mutex_unlock(&esw->state_lock);
2406
2407 return 0;
2408 }
2409
2410 int __mlx5_eswitch_set_vport_vlan(struct mlx5_eswitch *esw,
2411 u16 vport, u16 vlan, u8 qos, u8 set_flags)
2412 {
2413 struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport);
2414 int err = 0;
2415
2416 if (!ESW_ALLOWED(esw))
2417 return -EPERM;
2418 if (IS_ERR(evport))
2419 return PTR_ERR(evport);
2420 if (vlan > 4095 || qos > 7)
2421 return -EINVAL;
2422
2423 err = modify_esw_vport_cvlan(esw->dev, vport, vlan, qos, set_flags);
2424 if (err)
2425 return err;
2426
2427 evport->info.vlan = vlan;
2428 evport->info.qos = qos;
2429 if (evport->enabled && esw->mode == MLX5_ESWITCH_LEGACY) {
2430 err = esw_vport_ingress_config(esw, evport);
2431 if (err)
2432 return err;
2433 err = esw_vport_egress_config(esw, evport);
2434 }
2435
2436 return err;
2437 }
2438
2439 int mlx5_eswitch_set_vport_vlan(struct mlx5_eswitch *esw,
2440 u16 vport, u16 vlan, u8 qos)
2441 {
2442 u8 set_flags = 0;
2443 int err;
2444
2445 if (vlan || qos)
2446 set_flags = SET_VLAN_STRIP | SET_VLAN_INSERT;
2447
2448 mutex_lock(&esw->state_lock);
2449 err = __mlx5_eswitch_set_vport_vlan(esw, vport, vlan, qos, set_flags);
2450 mutex_unlock(&esw->state_lock);
2451
2452 return err;
2453 }
2454
2455 int mlx5_eswitch_set_vport_spoofchk(struct mlx5_eswitch *esw,
2456 u16 vport, bool spoofchk)
2457 {
2458 struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport);
2459 bool pschk;
2460 int err = 0;
2461
2462 if (!ESW_ALLOWED(esw))
2463 return -EPERM;
2464 if (IS_ERR(evport))
2465 return PTR_ERR(evport);
2466
2467 mutex_lock(&esw->state_lock);
2468 pschk = evport->info.spoofchk;
2469 evport->info.spoofchk = spoofchk;
2470 if (pschk && !is_valid_ether_addr(evport->info.mac))
2471 mlx5_core_warn(esw->dev,
2472 "Spoofchk in set while MAC is invalid, vport(%d)\n",
2473 evport->vport);
2474 if (evport->enabled && esw->mode == MLX5_ESWITCH_LEGACY)
2475 err = esw_vport_ingress_config(esw, evport);
2476 if (err)
2477 evport->info.spoofchk = pschk;
2478 mutex_unlock(&esw->state_lock);
2479
2480 return err;
2481 }
2482
2483 static void esw_cleanup_vepa_rules(struct mlx5_eswitch *esw)
2484 {
2485 if (esw->fdb_table.legacy.vepa_uplink_rule)
2486 mlx5_del_flow_rules(esw->fdb_table.legacy.vepa_uplink_rule);
2487
2488 if (esw->fdb_table.legacy.vepa_star_rule)
2489 mlx5_del_flow_rules(esw->fdb_table.legacy.vepa_star_rule);
2490
2491 esw->fdb_table.legacy.vepa_uplink_rule = NULL;
2492 esw->fdb_table.legacy.vepa_star_rule = NULL;
2493 }
2494
2495 static int _mlx5_eswitch_set_vepa_locked(struct mlx5_eswitch *esw,
2496 u8 setting)
2497 {
2498 struct mlx5_flow_destination dest = {};
2499 struct mlx5_flow_act flow_act = {};
2500 struct mlx5_flow_handle *flow_rule;
2501 struct mlx5_flow_spec *spec;
2502 int err = 0;
2503 void *misc;
2504
2505 if (!setting) {
2506 esw_cleanup_vepa_rules(esw);
2507 return 0;
2508 }
2509
2510 if (esw->fdb_table.legacy.vepa_uplink_rule)
2511 return 0;
2512
2513 spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
2514 if (!spec)
2515 return -ENOMEM;
2516
2517 /* Uplink rule forward uplink traffic to FDB */
2518 misc = MLX5_ADDR_OF(fte_match_param, spec->match_value, misc_parameters);
2519 MLX5_SET(fte_match_set_misc, misc, source_port, MLX5_VPORT_UPLINK);
2520
2521 misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, misc_parameters);
2522 MLX5_SET_TO_ONES(fte_match_set_misc, misc, source_port);
2523
2524 spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS;
2525 dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
2526 dest.ft = esw->fdb_table.legacy.fdb;
2527 flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
2528 flow_rule = mlx5_add_flow_rules(esw->fdb_table.legacy.vepa_fdb, spec,
2529 &flow_act, &dest, 1);
2530 if (IS_ERR(flow_rule)) {
2531 err = PTR_ERR(flow_rule);
2532 goto out;
2533 } else {
2534 esw->fdb_table.legacy.vepa_uplink_rule = flow_rule;
2535 }
2536
2537 /* Star rule to forward all traffic to uplink vport */
2538 memset(&dest, 0, sizeof(dest));
2539 dest.type = MLX5_FLOW_DESTINATION_TYPE_VPORT;
2540 dest.vport.num = MLX5_VPORT_UPLINK;
2541 flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
2542 flow_rule = mlx5_add_flow_rules(esw->fdb_table.legacy.vepa_fdb, NULL,
2543 &flow_act, &dest, 1);
2544 if (IS_ERR(flow_rule)) {
2545 err = PTR_ERR(flow_rule);
2546 goto out;
2547 } else {
2548 esw->fdb_table.legacy.vepa_star_rule = flow_rule;
2549 }
2550
2551 out:
2552 kvfree(spec);
2553 if (err)
2554 esw_cleanup_vepa_rules(esw);
2555 return err;
2556 }
2557
2558 int mlx5_eswitch_set_vepa(struct mlx5_eswitch *esw, u8 setting)
2559 {
2560 int err = 0;
2561
2562 if (!esw)
2563 return -EOPNOTSUPP;
2564
2565 if (!ESW_ALLOWED(esw))
2566 return -EPERM;
2567
2568 mutex_lock(&esw->state_lock);
2569 if (esw->mode != MLX5_ESWITCH_LEGACY) {
2570 err = -EOPNOTSUPP;
2571 goto out;
2572 }
2573
2574 err = _mlx5_eswitch_set_vepa_locked(esw, setting);
2575
2576 out:
2577 mutex_unlock(&esw->state_lock);
2578 return err;
2579 }
2580
2581 int mlx5_eswitch_get_vepa(struct mlx5_eswitch *esw, u8 *setting)
2582 {
2583 if (!esw)
2584 return -EOPNOTSUPP;
2585
2586 if (!ESW_ALLOWED(esw))
2587 return -EPERM;
2588
2589 if (esw->mode != MLX5_ESWITCH_LEGACY)
2590 return -EOPNOTSUPP;
2591
2592 *setting = esw->fdb_table.legacy.vepa_uplink_rule ? 1 : 0;
2593 return 0;
2594 }
2595
2596 int mlx5_eswitch_set_vport_trust(struct mlx5_eswitch *esw,
2597 u16 vport, bool setting)
2598 {
2599 struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport);
2600
2601 if (!ESW_ALLOWED(esw))
2602 return -EPERM;
2603 if (IS_ERR(evport))
2604 return PTR_ERR(evport);
2605
2606 mutex_lock(&esw->state_lock);
2607 evport->info.trusted = setting;
2608 if (evport->enabled)
2609 esw_vport_change_handle_locked(evport);
2610 mutex_unlock(&esw->state_lock);
2611
2612 return 0;
2613 }
2614
2615 static u32 calculate_vports_min_rate_divider(struct mlx5_eswitch *esw)
2616 {
2617 u32 fw_max_bw_share = MLX5_CAP_QOS(esw->dev, max_tsar_bw_share);
2618 struct mlx5_vport *evport;
2619 u32 max_guarantee = 0;
2620 int i;
2621
2622 mlx5_esw_for_all_vports(esw, i, evport) {
2623 if (!evport->enabled || evport->info.min_rate < max_guarantee)
2624 continue;
2625 max_guarantee = evport->info.min_rate;
2626 }
2627
2628 return max_t(u32, max_guarantee / fw_max_bw_share, 1);
2629 }
2630
2631 static int normalize_vports_min_rate(struct mlx5_eswitch *esw, u32 divider)
2632 {
2633 u32 fw_max_bw_share = MLX5_CAP_QOS(esw->dev, max_tsar_bw_share);
2634 struct mlx5_vport *evport;
2635 u32 vport_max_rate;
2636 u32 vport_min_rate;
2637 u32 bw_share;
2638 int err;
2639 int i;
2640
2641 mlx5_esw_for_all_vports(esw, i, evport) {
2642 if (!evport->enabled)
2643 continue;
2644 vport_min_rate = evport->info.min_rate;
2645 vport_max_rate = evport->info.max_rate;
2646 bw_share = MLX5_MIN_BW_SHARE;
2647
2648 if (vport_min_rate)
2649 bw_share = MLX5_RATE_TO_BW_SHARE(vport_min_rate,
2650 divider,
2651 fw_max_bw_share);
2652
2653 if (bw_share == evport->qos.bw_share)
2654 continue;
2655
2656 err = esw_vport_qos_config(esw, evport, vport_max_rate,
2657 bw_share);
2658 if (!err)
2659 evport->qos.bw_share = bw_share;
2660 else
2661 return err;
2662 }
2663
2664 return 0;
2665 }
2666
2667 int mlx5_eswitch_set_vport_rate(struct mlx5_eswitch *esw, u16 vport,
2668 u32 max_rate, u32 min_rate)
2669 {
2670 struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport);
2671 u32 fw_max_bw_share;
2672 u32 previous_min_rate;
2673 u32 divider;
2674 bool min_rate_supported;
2675 bool max_rate_supported;
2676 int err = 0;
2677
2678 if (!ESW_ALLOWED(esw))
2679 return -EPERM;
2680 if (IS_ERR(evport))
2681 return PTR_ERR(evport);
2682
2683 fw_max_bw_share = MLX5_CAP_QOS(esw->dev, max_tsar_bw_share);
2684 min_rate_supported = MLX5_CAP_QOS(esw->dev, esw_bw_share) &&
2685 fw_max_bw_share >= MLX5_MIN_BW_SHARE;
2686 max_rate_supported = MLX5_CAP_QOS(esw->dev, esw_rate_limit);
2687
2688 if ((min_rate && !min_rate_supported) || (max_rate && !max_rate_supported))
2689 return -EOPNOTSUPP;
2690
2691 mutex_lock(&esw->state_lock);
2692
2693 if (min_rate == evport->info.min_rate)
2694 goto set_max_rate;
2695
2696 previous_min_rate = evport->info.min_rate;
2697 evport->info.min_rate = min_rate;
2698 divider = calculate_vports_min_rate_divider(esw);
2699 err = normalize_vports_min_rate(esw, divider);
2700 if (err) {
2701 evport->info.min_rate = previous_min_rate;
2702 goto unlock;
2703 }
2704
2705 set_max_rate:
2706 if (max_rate == evport->info.max_rate)
2707 goto unlock;
2708
2709 err = esw_vport_qos_config(esw, evport, max_rate, evport->qos.bw_share);
2710 if (!err)
2711 evport->info.max_rate = max_rate;
2712
2713 unlock:
2714 mutex_unlock(&esw->state_lock);
2715 return err;
2716 }
2717
2718 static int mlx5_eswitch_query_vport_drop_stats(struct mlx5_core_dev *dev,
2719 struct mlx5_vport *vport,
2720 struct mlx5_vport_drop_stats *stats)
2721 {
2722 struct mlx5_eswitch *esw = dev->priv.eswitch;
2723 u64 rx_discard_vport_down, tx_discard_vport_down;
2724 u64 bytes = 0;
2725 int err = 0;
2726
2727 if (esw->mode != MLX5_ESWITCH_LEGACY)
2728 return 0;
2729
2730 mutex_lock(&esw->state_lock);
2731 if (!vport->enabled)
2732 goto unlock;
2733
2734 if (vport->egress.legacy.drop_counter)
2735 mlx5_fc_query(dev, vport->egress.legacy.drop_counter,
2736 &stats->rx_dropped, &bytes);
2737
2738 if (vport->ingress.legacy.drop_counter)
2739 mlx5_fc_query(dev, vport->ingress.legacy.drop_counter,
2740 &stats->tx_dropped, &bytes);
2741
2742 if (!MLX5_CAP_GEN(dev, receive_discard_vport_down) &&
2743 !MLX5_CAP_GEN(dev, transmit_discard_vport_down))
2744 goto unlock;
2745
2746 err = mlx5_query_vport_down_stats(dev, vport->vport, 1,
2747 &rx_discard_vport_down,
2748 &tx_discard_vport_down);
2749 if (err)
2750 goto unlock;
2751
2752 if (MLX5_CAP_GEN(dev, receive_discard_vport_down))
2753 stats->rx_dropped += rx_discard_vport_down;
2754 if (MLX5_CAP_GEN(dev, transmit_discard_vport_down))
2755 stats->tx_dropped += tx_discard_vport_down;
2756
2757 unlock:
2758 mutex_unlock(&esw->state_lock);
2759 return err;
2760 }
2761
2762 int mlx5_eswitch_get_vport_stats(struct mlx5_eswitch *esw,
2763 u16 vport_num,
2764 struct ifla_vf_stats *vf_stats)
2765 {
2766 struct mlx5_vport *vport = mlx5_eswitch_get_vport(esw, vport_num);
2767 int outlen = MLX5_ST_SZ_BYTES(query_vport_counter_out);
2768 u32 in[MLX5_ST_SZ_DW(query_vport_counter_in)] = {};
2769 struct mlx5_vport_drop_stats stats = {};
2770 int err = 0;
2771 u32 *out;
2772
2773 if (IS_ERR(vport))
2774 return PTR_ERR(vport);
2775
2776 out = kvzalloc(outlen, GFP_KERNEL);
2777 if (!out)
2778 return -ENOMEM;
2779
2780 MLX5_SET(query_vport_counter_in, in, opcode,
2781 MLX5_CMD_OP_QUERY_VPORT_COUNTER);
2782 MLX5_SET(query_vport_counter_in, in, op_mod, 0);
2783 MLX5_SET(query_vport_counter_in, in, vport_number, vport->vport);
2784 MLX5_SET(query_vport_counter_in, in, other_vport, 1);
2785
2786 err = mlx5_cmd_exec_inout(esw->dev, query_vport_counter, in, out);
2787 if (err)
2788 goto free_out;
2789
2790 #define MLX5_GET_CTR(p, x) \
2791 MLX5_GET64(query_vport_counter_out, p, x)
2792
2793 memset(vf_stats, 0, sizeof(*vf_stats));
2794 vf_stats->rx_packets =
2795 MLX5_GET_CTR(out, received_eth_unicast.packets) +
2796 MLX5_GET_CTR(out, received_ib_unicast.packets) +
2797 MLX5_GET_CTR(out, received_eth_multicast.packets) +
2798 MLX5_GET_CTR(out, received_ib_multicast.packets) +
2799 MLX5_GET_CTR(out, received_eth_broadcast.packets);
2800
2801 vf_stats->rx_bytes =
2802 MLX5_GET_CTR(out, received_eth_unicast.octets) +
2803 MLX5_GET_CTR(out, received_ib_unicast.octets) +
2804 MLX5_GET_CTR(out, received_eth_multicast.octets) +
2805 MLX5_GET_CTR(out, received_ib_multicast.octets) +
2806 MLX5_GET_CTR(out, received_eth_broadcast.octets);
2807
2808 vf_stats->tx_packets =
2809 MLX5_GET_CTR(out, transmitted_eth_unicast.packets) +
2810 MLX5_GET_CTR(out, transmitted_ib_unicast.packets) +
2811 MLX5_GET_CTR(out, transmitted_eth_multicast.packets) +
2812 MLX5_GET_CTR(out, transmitted_ib_multicast.packets) +
2813 MLX5_GET_CTR(out, transmitted_eth_broadcast.packets);
2814
2815 vf_stats->tx_bytes =
2816 MLX5_GET_CTR(out, transmitted_eth_unicast.octets) +
2817 MLX5_GET_CTR(out, transmitted_ib_unicast.octets) +
2818 MLX5_GET_CTR(out, transmitted_eth_multicast.octets) +
2819 MLX5_GET_CTR(out, transmitted_ib_multicast.octets) +
2820 MLX5_GET_CTR(out, transmitted_eth_broadcast.octets);
2821
2822 vf_stats->multicast =
2823 MLX5_GET_CTR(out, received_eth_multicast.packets) +
2824 MLX5_GET_CTR(out, received_ib_multicast.packets);
2825
2826 vf_stats->broadcast =
2827 MLX5_GET_CTR(out, received_eth_broadcast.packets);
2828
2829 err = mlx5_eswitch_query_vport_drop_stats(esw->dev, vport, &stats);
2830 if (err)
2831 goto free_out;
2832 vf_stats->rx_dropped = stats.rx_dropped;
2833 vf_stats->tx_dropped = stats.tx_dropped;
2834
2835 free_out:
2836 kvfree(out);
2837 return err;
2838 }
2839
2840 u8 mlx5_eswitch_mode(struct mlx5_eswitch *esw)
2841 {
2842 return ESW_ALLOWED(esw) ? esw->mode : MLX5_ESWITCH_NONE;
2843 }
2844 EXPORT_SYMBOL_GPL(mlx5_eswitch_mode);
2845
2846 enum devlink_eswitch_encap_mode
2847 mlx5_eswitch_get_encap_mode(const struct mlx5_core_dev *dev)
2848 {
2849 struct mlx5_eswitch *esw;
2850
2851 esw = dev->priv.eswitch;
2852 return ESW_ALLOWED(esw) ? esw->offloads.encap :
2853 DEVLINK_ESWITCH_ENCAP_MODE_NONE;
2854 }
2855 EXPORT_SYMBOL(mlx5_eswitch_get_encap_mode);
2856
2857 bool mlx5_esw_lag_prereq(struct mlx5_core_dev *dev0, struct mlx5_core_dev *dev1)
2858 {
2859 if ((dev0->priv.eswitch->mode == MLX5_ESWITCH_NONE &&
2860 dev1->priv.eswitch->mode == MLX5_ESWITCH_NONE) ||
2861 (dev0->priv.eswitch->mode == MLX5_ESWITCH_OFFLOADS &&
2862 dev1->priv.eswitch->mode == MLX5_ESWITCH_OFFLOADS))
2863 return true;
2864
2865 return false;
2866 }
2867
2868 bool mlx5_esw_multipath_prereq(struct mlx5_core_dev *dev0,
2869 struct mlx5_core_dev *dev1)
2870 {
2871 return (dev0->priv.eswitch->mode == MLX5_ESWITCH_OFFLOADS &&
2872 dev1->priv.eswitch->mode == MLX5_ESWITCH_OFFLOADS);
2873 }
2874
2875