1b55b3538SParav Pandit // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
2b55b3538SParav Pandit /* Copyright (c) 2021 Mellanox Technologies Ltd */
3b55b3538SParav Pandit 
4b55b3538SParav Pandit #include <linux/etherdevice.h>
5b55b3538SParav Pandit #include <linux/mlx5/driver.h>
6b55b3538SParav Pandit #include <linux/mlx5/mlx5_ifc.h>
7b55b3538SParav Pandit #include <linux/mlx5/vport.h>
8b55b3538SParav Pandit #include <linux/mlx5/fs.h>
9b55b3538SParav Pandit #include "esw/acl/lgcy.h"
10b55b3538SParav Pandit #include "esw/legacy.h"
11b55b3538SParav Pandit #include "mlx5_core.h"
12b55b3538SParav Pandit #include "eswitch.h"
13b55b3538SParav Pandit #include "fs_core.h"
14*0c9d8765SPaul Blakey #include "fs_ft_pool.h"
152d116e3eSDmytro Linkin #include "esw/qos.h"
16b55b3538SParav Pandit 
17b55b3538SParav Pandit enum {
18b55b3538SParav Pandit 	LEGACY_VEPA_PRIO = 0,
19b55b3538SParav Pandit 	LEGACY_FDB_PRIO,
20b55b3538SParav Pandit };
21b55b3538SParav Pandit 
22b55b3538SParav Pandit static int esw_create_legacy_vepa_table(struct mlx5_eswitch *esw)
23b55b3538SParav Pandit {
24b55b3538SParav Pandit 	struct mlx5_flow_table_attr ft_attr = {};
25b55b3538SParav Pandit 	struct mlx5_core_dev *dev = esw->dev;
26b55b3538SParav Pandit 	struct mlx5_flow_namespace *root_ns;
27b55b3538SParav Pandit 	struct mlx5_flow_table *fdb;
28b55b3538SParav Pandit 	int err;
29b55b3538SParav Pandit 
30b55b3538SParav Pandit 	root_ns = mlx5_get_fdb_sub_ns(dev, 0);
31b55b3538SParav Pandit 	if (!root_ns) {
32b55b3538SParav Pandit 		esw_warn(dev, "Failed to get FDB flow namespace\n");
33b55b3538SParav Pandit 		return -EOPNOTSUPP;
34b55b3538SParav Pandit 	}
35b55b3538SParav Pandit 
36b55b3538SParav Pandit 	/* num FTE 2, num FG 2 */
37b55b3538SParav Pandit 	ft_attr.prio = LEGACY_VEPA_PRIO;
38b55b3538SParav Pandit 	ft_attr.max_fte = 2;
39b55b3538SParav Pandit 	ft_attr.autogroup.max_num_groups = 2;
40b55b3538SParav Pandit 	fdb = mlx5_create_auto_grouped_flow_table(root_ns, &ft_attr);
41b55b3538SParav Pandit 	if (IS_ERR(fdb)) {
42b55b3538SParav Pandit 		err = PTR_ERR(fdb);
43b55b3538SParav Pandit 		esw_warn(dev, "Failed to create VEPA FDB err %d\n", err);
44b55b3538SParav Pandit 		return err;
45b55b3538SParav Pandit 	}
46b55b3538SParav Pandit 	esw->fdb_table.legacy.vepa_fdb = fdb;
47b55b3538SParav Pandit 
48b55b3538SParav Pandit 	return 0;
49b55b3538SParav Pandit }
50b55b3538SParav Pandit 
51b55b3538SParav Pandit static void esw_destroy_legacy_fdb_table(struct mlx5_eswitch *esw)
52b55b3538SParav Pandit {
53b55b3538SParav Pandit 	esw_debug(esw->dev, "Destroy FDB Table\n");
54b55b3538SParav Pandit 	if (!esw->fdb_table.legacy.fdb)
55b55b3538SParav Pandit 		return;
56b55b3538SParav Pandit 
57b55b3538SParav Pandit 	if (esw->fdb_table.legacy.promisc_grp)
58b55b3538SParav Pandit 		mlx5_destroy_flow_group(esw->fdb_table.legacy.promisc_grp);
59b55b3538SParav Pandit 	if (esw->fdb_table.legacy.allmulti_grp)
60b55b3538SParav Pandit 		mlx5_destroy_flow_group(esw->fdb_table.legacy.allmulti_grp);
61b55b3538SParav Pandit 	if (esw->fdb_table.legacy.addr_grp)
62b55b3538SParav Pandit 		mlx5_destroy_flow_group(esw->fdb_table.legacy.addr_grp);
63b55b3538SParav Pandit 	mlx5_destroy_flow_table(esw->fdb_table.legacy.fdb);
64b55b3538SParav Pandit 
65b55b3538SParav Pandit 	esw->fdb_table.legacy.fdb = NULL;
66b55b3538SParav Pandit 	esw->fdb_table.legacy.addr_grp = NULL;
67b55b3538SParav Pandit 	esw->fdb_table.legacy.allmulti_grp = NULL;
68b55b3538SParav Pandit 	esw->fdb_table.legacy.promisc_grp = NULL;
69b55b3538SParav Pandit 	atomic64_set(&esw->user_count, 0);
70b55b3538SParav Pandit }
71b55b3538SParav Pandit 
72b55b3538SParav Pandit static int esw_create_legacy_fdb_table(struct mlx5_eswitch *esw)
73b55b3538SParav Pandit {
74b55b3538SParav Pandit 	int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
75b55b3538SParav Pandit 	struct mlx5_flow_table_attr ft_attr = {};
76b55b3538SParav Pandit 	struct mlx5_core_dev *dev = esw->dev;
77b55b3538SParav Pandit 	struct mlx5_flow_namespace *root_ns;
78b55b3538SParav Pandit 	struct mlx5_flow_table *fdb;
79b55b3538SParav Pandit 	struct mlx5_flow_group *g;
80b55b3538SParav Pandit 	void *match_criteria;
81b55b3538SParav Pandit 	int table_size;
82b55b3538SParav Pandit 	u32 *flow_group_in;
83b55b3538SParav Pandit 	u8 *dmac;
84b55b3538SParav Pandit 	int err = 0;
85b55b3538SParav Pandit 
86b55b3538SParav Pandit 	esw_debug(dev, "Create FDB log_max_size(%d)\n",
87b55b3538SParav Pandit 		  MLX5_CAP_ESW_FLOWTABLE_FDB(dev, log_max_ft_size));
88b55b3538SParav Pandit 
89b55b3538SParav Pandit 	root_ns = mlx5_get_fdb_sub_ns(dev, 0);
90b55b3538SParav Pandit 	if (!root_ns) {
91b55b3538SParav Pandit 		esw_warn(dev, "Failed to get FDB flow namespace\n");
92b55b3538SParav Pandit 		return -EOPNOTSUPP;
93b55b3538SParav Pandit 	}
94b55b3538SParav Pandit 
95b55b3538SParav Pandit 	flow_group_in = kvzalloc(inlen, GFP_KERNEL);
96b55b3538SParav Pandit 	if (!flow_group_in)
97b55b3538SParav Pandit 		return -ENOMEM;
98b55b3538SParav Pandit 
99*0c9d8765SPaul Blakey 	ft_attr.max_fte = POOL_NEXT_SIZE;
100b55b3538SParav Pandit 	ft_attr.prio = LEGACY_FDB_PRIO;
101b55b3538SParav Pandit 	fdb = mlx5_create_flow_table(root_ns, &ft_attr);
102b55b3538SParav Pandit 	if (IS_ERR(fdb)) {
103b55b3538SParav Pandit 		err = PTR_ERR(fdb);
104b55b3538SParav Pandit 		esw_warn(dev, "Failed to create FDB Table err %d\n", err);
105b55b3538SParav Pandit 		goto out;
106b55b3538SParav Pandit 	}
107b55b3538SParav Pandit 	esw->fdb_table.legacy.fdb = fdb;
108*0c9d8765SPaul Blakey 	table_size = fdb->max_fte;
109b55b3538SParav Pandit 
110b55b3538SParav Pandit 	/* Addresses group : Full match unicast/multicast addresses */
111b55b3538SParav Pandit 	MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable,
112b55b3538SParav Pandit 		 MLX5_MATCH_OUTER_HEADERS);
113b55b3538SParav Pandit 	match_criteria = MLX5_ADDR_OF(create_flow_group_in, flow_group_in, match_criteria);
114b55b3538SParav Pandit 	dmac = MLX5_ADDR_OF(fte_match_param, match_criteria, outer_headers.dmac_47_16);
115b55b3538SParav Pandit 	MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 0);
116b55b3538SParav Pandit 	/* Preserve 2 entries for allmulti and promisc rules*/
117b55b3538SParav Pandit 	MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, table_size - 3);
118b55b3538SParav Pandit 	eth_broadcast_addr(dmac);
119b55b3538SParav Pandit 	g = mlx5_create_flow_group(fdb, flow_group_in);
120b55b3538SParav Pandit 	if (IS_ERR(g)) {
121b55b3538SParav Pandit 		err = PTR_ERR(g);
122b55b3538SParav Pandit 		esw_warn(dev, "Failed to create flow group err(%d)\n", err);
123b55b3538SParav Pandit 		goto out;
124b55b3538SParav Pandit 	}
125b55b3538SParav Pandit 	esw->fdb_table.legacy.addr_grp = g;
126b55b3538SParav Pandit 
127b55b3538SParav Pandit 	/* Allmulti group : One rule that forwards any mcast traffic */
128b55b3538SParav Pandit 	MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable,
129b55b3538SParav Pandit 		 MLX5_MATCH_OUTER_HEADERS);
130b55b3538SParav Pandit 	MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, table_size - 2);
131b55b3538SParav Pandit 	MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, table_size - 2);
132b55b3538SParav Pandit 	eth_zero_addr(dmac);
133b55b3538SParav Pandit 	dmac[0] = 0x01;
134b55b3538SParav Pandit 	g = mlx5_create_flow_group(fdb, flow_group_in);
135b55b3538SParav Pandit 	if (IS_ERR(g)) {
136b55b3538SParav Pandit 		err = PTR_ERR(g);
137b55b3538SParav Pandit 		esw_warn(dev, "Failed to create allmulti flow group err(%d)\n", err);
138b55b3538SParav Pandit 		goto out;
139b55b3538SParav Pandit 	}
140b55b3538SParav Pandit 	esw->fdb_table.legacy.allmulti_grp = g;
141b55b3538SParav Pandit 
142b55b3538SParav Pandit 	/* Promiscuous group :
143b55b3538SParav Pandit 	 * One rule that forward all unmatched traffic from previous groups
144b55b3538SParav Pandit 	 */
145b55b3538SParav Pandit 	eth_zero_addr(dmac);
146b55b3538SParav Pandit 	MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable,
147b55b3538SParav Pandit 		 MLX5_MATCH_MISC_PARAMETERS);
148b55b3538SParav Pandit 	MLX5_SET_TO_ONES(fte_match_param, match_criteria, misc_parameters.source_port);
149b55b3538SParav Pandit 	MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, table_size - 1);
150b55b3538SParav Pandit 	MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, table_size - 1);
151b55b3538SParav Pandit 	g = mlx5_create_flow_group(fdb, flow_group_in);
152b55b3538SParav Pandit 	if (IS_ERR(g)) {
153b55b3538SParav Pandit 		err = PTR_ERR(g);
154b55b3538SParav Pandit 		esw_warn(dev, "Failed to create promisc flow group err(%d)\n", err);
155b55b3538SParav Pandit 		goto out;
156b55b3538SParav Pandit 	}
157b55b3538SParav Pandit 	esw->fdb_table.legacy.promisc_grp = g;
158b55b3538SParav Pandit 
159b55b3538SParav Pandit out:
160b55b3538SParav Pandit 	if (err)
161b55b3538SParav Pandit 		esw_destroy_legacy_fdb_table(esw);
162b55b3538SParav Pandit 
163b55b3538SParav Pandit 	kvfree(flow_group_in);
164b55b3538SParav Pandit 	return err;
165b55b3538SParav Pandit }
166b55b3538SParav Pandit 
167b55b3538SParav Pandit static void esw_destroy_legacy_vepa_table(struct mlx5_eswitch *esw)
168b55b3538SParav Pandit {
169b55b3538SParav Pandit 	esw_debug(esw->dev, "Destroy VEPA Table\n");
170b55b3538SParav Pandit 	if (!esw->fdb_table.legacy.vepa_fdb)
171b55b3538SParav Pandit 		return;
172b55b3538SParav Pandit 
173b55b3538SParav Pandit 	mlx5_destroy_flow_table(esw->fdb_table.legacy.vepa_fdb);
174b55b3538SParav Pandit 	esw->fdb_table.legacy.vepa_fdb = NULL;
175b55b3538SParav Pandit }
176b55b3538SParav Pandit 
177b55b3538SParav Pandit static int esw_create_legacy_table(struct mlx5_eswitch *esw)
178b55b3538SParav Pandit {
179b55b3538SParav Pandit 	int err;
180b55b3538SParav Pandit 
181b55b3538SParav Pandit 	memset(&esw->fdb_table.legacy, 0, sizeof(struct legacy_fdb));
182b55b3538SParav Pandit 	atomic64_set(&esw->user_count, 0);
183b55b3538SParav Pandit 
184b55b3538SParav Pandit 	err = esw_create_legacy_vepa_table(esw);
185b55b3538SParav Pandit 	if (err)
186b55b3538SParav Pandit 		return err;
187b55b3538SParav Pandit 
188b55b3538SParav Pandit 	err = esw_create_legacy_fdb_table(esw);
189b55b3538SParav Pandit 	if (err)
190b55b3538SParav Pandit 		esw_destroy_legacy_vepa_table(esw);
191b55b3538SParav Pandit 
192b55b3538SParav Pandit 	return err;
193b55b3538SParav Pandit }
194b55b3538SParav Pandit 
195b55b3538SParav Pandit static void esw_cleanup_vepa_rules(struct mlx5_eswitch *esw)
196b55b3538SParav Pandit {
197b55b3538SParav Pandit 	if (esw->fdb_table.legacy.vepa_uplink_rule)
198b55b3538SParav Pandit 		mlx5_del_flow_rules(esw->fdb_table.legacy.vepa_uplink_rule);
199b55b3538SParav Pandit 
200b55b3538SParav Pandit 	if (esw->fdb_table.legacy.vepa_star_rule)
201b55b3538SParav Pandit 		mlx5_del_flow_rules(esw->fdb_table.legacy.vepa_star_rule);
202b55b3538SParav Pandit 
203b55b3538SParav Pandit 	esw->fdb_table.legacy.vepa_uplink_rule = NULL;
204b55b3538SParav Pandit 	esw->fdb_table.legacy.vepa_star_rule = NULL;
205b55b3538SParav Pandit }
206b55b3538SParav Pandit 
207b55b3538SParav Pandit static void esw_destroy_legacy_table(struct mlx5_eswitch *esw)
208b55b3538SParav Pandit {
209b55b3538SParav Pandit 	esw_cleanup_vepa_rules(esw);
210b55b3538SParav Pandit 	esw_destroy_legacy_fdb_table(esw);
211b55b3538SParav Pandit 	esw_destroy_legacy_vepa_table(esw);
212b55b3538SParav Pandit }
213b55b3538SParav Pandit 
214b55b3538SParav Pandit #define MLX5_LEGACY_SRIOV_VPORT_EVENTS (MLX5_VPORT_UC_ADDR_CHANGE | \
215b55b3538SParav Pandit 					MLX5_VPORT_MC_ADDR_CHANGE | \
216b55b3538SParav Pandit 					MLX5_VPORT_PROMISC_CHANGE)
217b55b3538SParav Pandit 
218b55b3538SParav Pandit int esw_legacy_enable(struct mlx5_eswitch *esw)
219b55b3538SParav Pandit {
220b55b3538SParav Pandit 	struct mlx5_vport *vport;
22147dd7e60SParav Pandit 	unsigned long i;
22247dd7e60SParav Pandit 	int ret;
223b55b3538SParav Pandit 
224b55b3538SParav Pandit 	ret = esw_create_legacy_table(esw);
225b55b3538SParav Pandit 	if (ret)
226b55b3538SParav Pandit 		return ret;
227b55b3538SParav Pandit 
228b55b3538SParav Pandit 	mlx5_esw_for_each_vf_vport(esw, i, vport, esw->esw_funcs.num_vfs)
229b55b3538SParav Pandit 		vport->info.link_state = MLX5_VPORT_ADMIN_STATE_AUTO;
230b55b3538SParav Pandit 
231b55b3538SParav Pandit 	ret = mlx5_eswitch_enable_pf_vf_vports(esw, MLX5_LEGACY_SRIOV_VPORT_EVENTS);
232b55b3538SParav Pandit 	if (ret)
233b55b3538SParav Pandit 		esw_destroy_legacy_table(esw);
234b55b3538SParav Pandit 	return ret;
235b55b3538SParav Pandit }
236b55b3538SParav Pandit 
237b55b3538SParav Pandit void esw_legacy_disable(struct mlx5_eswitch *esw)
238b55b3538SParav Pandit {
239b55b3538SParav Pandit 	struct esw_mc_addr *mc_promisc;
240b55b3538SParav Pandit 
241b55b3538SParav Pandit 	mlx5_eswitch_disable_pf_vf_vports(esw);
242b55b3538SParav Pandit 
243b55b3538SParav Pandit 	mc_promisc = &esw->mc_promisc;
244b55b3538SParav Pandit 	if (mc_promisc->uplink_rule)
245b55b3538SParav Pandit 		mlx5_del_flow_rules(mc_promisc->uplink_rule);
246b55b3538SParav Pandit 
247b55b3538SParav Pandit 	esw_destroy_legacy_table(esw);
248b55b3538SParav Pandit }
249b55b3538SParav Pandit 
250b55b3538SParav Pandit static int _mlx5_eswitch_set_vepa_locked(struct mlx5_eswitch *esw,
251b55b3538SParav Pandit 					 u8 setting)
252b55b3538SParav Pandit {
253b55b3538SParav Pandit 	struct mlx5_flow_destination dest = {};
254b55b3538SParav Pandit 	struct mlx5_flow_act flow_act = {};
255b55b3538SParav Pandit 	struct mlx5_flow_handle *flow_rule;
256b55b3538SParav Pandit 	struct mlx5_flow_spec *spec;
257b55b3538SParav Pandit 	int err = 0;
258b55b3538SParav Pandit 	void *misc;
259b55b3538SParav Pandit 
260b55b3538SParav Pandit 	if (!setting) {
261b55b3538SParav Pandit 		esw_cleanup_vepa_rules(esw);
262b55b3538SParav Pandit 		return 0;
263b55b3538SParav Pandit 	}
264b55b3538SParav Pandit 
265b55b3538SParav Pandit 	if (esw->fdb_table.legacy.vepa_uplink_rule)
266b55b3538SParav Pandit 		return 0;
267b55b3538SParav Pandit 
268b55b3538SParav Pandit 	spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
269b55b3538SParav Pandit 	if (!spec)
270b55b3538SParav Pandit 		return -ENOMEM;
271b55b3538SParav Pandit 
272b55b3538SParav Pandit 	/* Uplink rule forward uplink traffic to FDB */
273b55b3538SParav Pandit 	misc = MLX5_ADDR_OF(fte_match_param, spec->match_value, misc_parameters);
274b55b3538SParav Pandit 	MLX5_SET(fte_match_set_misc, misc, source_port, MLX5_VPORT_UPLINK);
275b55b3538SParav Pandit 
276b55b3538SParav Pandit 	misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, misc_parameters);
277b55b3538SParav Pandit 	MLX5_SET_TO_ONES(fte_match_set_misc, misc, source_port);
278b55b3538SParav Pandit 
279b55b3538SParav Pandit 	spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS;
280b55b3538SParav Pandit 	dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
281b55b3538SParav Pandit 	dest.ft = esw->fdb_table.legacy.fdb;
282b55b3538SParav Pandit 	flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
283b55b3538SParav Pandit 	flow_rule = mlx5_add_flow_rules(esw->fdb_table.legacy.vepa_fdb, spec,
284b55b3538SParav Pandit 					&flow_act, &dest, 1);
285b55b3538SParav Pandit 	if (IS_ERR(flow_rule)) {
286b55b3538SParav Pandit 		err = PTR_ERR(flow_rule);
287b55b3538SParav Pandit 		goto out;
288b55b3538SParav Pandit 	} else {
289b55b3538SParav Pandit 		esw->fdb_table.legacy.vepa_uplink_rule = flow_rule;
290b55b3538SParav Pandit 	}
291b55b3538SParav Pandit 
292b55b3538SParav Pandit 	/* Star rule to forward all traffic to uplink vport */
293b55b3538SParav Pandit 	memset(&dest, 0, sizeof(dest));
294b55b3538SParav Pandit 	dest.type = MLX5_FLOW_DESTINATION_TYPE_VPORT;
295b55b3538SParav Pandit 	dest.vport.num = MLX5_VPORT_UPLINK;
296b55b3538SParav Pandit 	flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
297b55b3538SParav Pandit 	flow_rule = mlx5_add_flow_rules(esw->fdb_table.legacy.vepa_fdb, NULL,
298b55b3538SParav Pandit 					&flow_act, &dest, 1);
299b55b3538SParav Pandit 	if (IS_ERR(flow_rule)) {
300b55b3538SParav Pandit 		err = PTR_ERR(flow_rule);
301b55b3538SParav Pandit 		goto out;
302b55b3538SParav Pandit 	} else {
303b55b3538SParav Pandit 		esw->fdb_table.legacy.vepa_star_rule = flow_rule;
304b55b3538SParav Pandit 	}
305b55b3538SParav Pandit 
306b55b3538SParav Pandit out:
307b55b3538SParav Pandit 	kvfree(spec);
308b55b3538SParav Pandit 	if (err)
309b55b3538SParav Pandit 		esw_cleanup_vepa_rules(esw);
310b55b3538SParav Pandit 	return err;
311b55b3538SParav Pandit }
312b55b3538SParav Pandit 
313b55b3538SParav Pandit int mlx5_eswitch_set_vepa(struct mlx5_eswitch *esw, u8 setting)
314b55b3538SParav Pandit {
315b55b3538SParav Pandit 	int err = 0;
316b55b3538SParav Pandit 
317b55b3538SParav Pandit 	if (!esw)
318b55b3538SParav Pandit 		return -EOPNOTSUPP;
319b55b3538SParav Pandit 
320b55b3538SParav Pandit 	if (!mlx5_esw_allowed(esw))
321b55b3538SParav Pandit 		return -EPERM;
322b55b3538SParav Pandit 
323b55b3538SParav Pandit 	mutex_lock(&esw->state_lock);
324b55b3538SParav Pandit 	if (esw->mode != MLX5_ESWITCH_LEGACY) {
325b55b3538SParav Pandit 		err = -EOPNOTSUPP;
326b55b3538SParav Pandit 		goto out;
327b55b3538SParav Pandit 	}
328b55b3538SParav Pandit 
329b55b3538SParav Pandit 	err = _mlx5_eswitch_set_vepa_locked(esw, setting);
330b55b3538SParav Pandit 
331b55b3538SParav Pandit out:
332b55b3538SParav Pandit 	mutex_unlock(&esw->state_lock);
333b55b3538SParav Pandit 	return err;
334b55b3538SParav Pandit }
335b55b3538SParav Pandit 
336b55b3538SParav Pandit int mlx5_eswitch_get_vepa(struct mlx5_eswitch *esw, u8 *setting)
337b55b3538SParav Pandit {
338b55b3538SParav Pandit 	if (!esw)
339b55b3538SParav Pandit 		return -EOPNOTSUPP;
340b55b3538SParav Pandit 
341b55b3538SParav Pandit 	if (!mlx5_esw_allowed(esw))
342b55b3538SParav Pandit 		return -EPERM;
343b55b3538SParav Pandit 
344b55b3538SParav Pandit 	if (esw->mode != MLX5_ESWITCH_LEGACY)
345b55b3538SParav Pandit 		return -EOPNOTSUPP;
346b55b3538SParav Pandit 
347b55b3538SParav Pandit 	*setting = esw->fdb_table.legacy.vepa_uplink_rule ? 1 : 0;
348b55b3538SParav Pandit 	return 0;
349b55b3538SParav Pandit }
350b55b3538SParav Pandit 
351b55b3538SParav Pandit int esw_legacy_vport_acl_setup(struct mlx5_eswitch *esw, struct mlx5_vport *vport)
352b55b3538SParav Pandit {
353b55b3538SParav Pandit 	int ret;
354b55b3538SParav Pandit 
355b55b3538SParav Pandit 	/* Only non manager vports need ACL in legacy mode */
356b55b3538SParav Pandit 	if (mlx5_esw_is_manager_vport(esw, vport->vport))
357b55b3538SParav Pandit 		return 0;
358b55b3538SParav Pandit 
359b55b3538SParav Pandit 	ret = esw_acl_ingress_lgcy_setup(esw, vport);
360b55b3538SParav Pandit 	if (ret)
361b55b3538SParav Pandit 		goto ingress_err;
362b55b3538SParav Pandit 
363b55b3538SParav Pandit 	ret = esw_acl_egress_lgcy_setup(esw, vport);
364b55b3538SParav Pandit 	if (ret)
365b55b3538SParav Pandit 		goto egress_err;
366b55b3538SParav Pandit 
367b55b3538SParav Pandit 	return 0;
368b55b3538SParav Pandit 
369b55b3538SParav Pandit egress_err:
370b55b3538SParav Pandit 	esw_acl_ingress_lgcy_cleanup(esw, vport);
371b55b3538SParav Pandit ingress_err:
372b55b3538SParav Pandit 	return ret;
373b55b3538SParav Pandit }
374b55b3538SParav Pandit 
375b55b3538SParav Pandit void esw_legacy_vport_acl_cleanup(struct mlx5_eswitch *esw, struct mlx5_vport *vport)
376b55b3538SParav Pandit {
377b55b3538SParav Pandit 	if (mlx5_esw_is_manager_vport(esw, vport->vport))
378b55b3538SParav Pandit 		return;
379b55b3538SParav Pandit 
380b55b3538SParav Pandit 	esw_acl_egress_lgcy_cleanup(esw, vport);
381b55b3538SParav Pandit 	esw_acl_ingress_lgcy_cleanup(esw, vport);
382b55b3538SParav Pandit }
383b55b3538SParav Pandit 
384b55b3538SParav Pandit int mlx5_esw_query_vport_drop_stats(struct mlx5_core_dev *dev,
385b55b3538SParav Pandit 				    struct mlx5_vport *vport,
386b55b3538SParav Pandit 				    struct mlx5_vport_drop_stats *stats)
387b55b3538SParav Pandit {
388b55b3538SParav Pandit 	u64 rx_discard_vport_down, tx_discard_vport_down;
389b55b3538SParav Pandit 	struct mlx5_eswitch *esw = dev->priv.eswitch;
390b55b3538SParav Pandit 	u64 bytes = 0;
391b55b3538SParav Pandit 	int err = 0;
392b55b3538SParav Pandit 
393b55b3538SParav Pandit 	if (esw->mode != MLX5_ESWITCH_LEGACY)
394b55b3538SParav Pandit 		return 0;
395b55b3538SParav Pandit 
396b55b3538SParav Pandit 	mutex_lock(&esw->state_lock);
397b55b3538SParav Pandit 	if (!vport->enabled)
398b55b3538SParav Pandit 		goto unlock;
399b55b3538SParav Pandit 
400b55b3538SParav Pandit 	if (!IS_ERR_OR_NULL(vport->egress.legacy.drop_counter))
401b55b3538SParav Pandit 		mlx5_fc_query(dev, vport->egress.legacy.drop_counter,
402b55b3538SParav Pandit 			      &stats->rx_dropped, &bytes);
403b55b3538SParav Pandit 
404b55b3538SParav Pandit 	if (vport->ingress.legacy.drop_counter)
405b55b3538SParav Pandit 		mlx5_fc_query(dev, vport->ingress.legacy.drop_counter,
406b55b3538SParav Pandit 			      &stats->tx_dropped, &bytes);
407b55b3538SParav Pandit 
408b55b3538SParav Pandit 	if (!MLX5_CAP_GEN(dev, receive_discard_vport_down) &&
409b55b3538SParav Pandit 	    !MLX5_CAP_GEN(dev, transmit_discard_vport_down))
410b55b3538SParav Pandit 		goto unlock;
411b55b3538SParav Pandit 
412b55b3538SParav Pandit 	err = mlx5_query_vport_down_stats(dev, vport->vport, 1,
413b55b3538SParav Pandit 					  &rx_discard_vport_down,
414b55b3538SParav Pandit 					  &tx_discard_vport_down);
415b55b3538SParav Pandit 	if (err)
416b55b3538SParav Pandit 		goto unlock;
417b55b3538SParav Pandit 
418b55b3538SParav Pandit 	if (MLX5_CAP_GEN(dev, receive_discard_vport_down))
419b55b3538SParav Pandit 		stats->rx_dropped += rx_discard_vport_down;
420b55b3538SParav Pandit 	if (MLX5_CAP_GEN(dev, transmit_discard_vport_down))
421b55b3538SParav Pandit 		stats->tx_dropped += tx_discard_vport_down;
422b55b3538SParav Pandit 
423b55b3538SParav Pandit unlock:
424b55b3538SParav Pandit 	mutex_unlock(&esw->state_lock);
425b55b3538SParav Pandit 	return err;
426b55b3538SParav Pandit }
427b55b3538SParav Pandit 
428b55b3538SParav Pandit int mlx5_eswitch_set_vport_vlan(struct mlx5_eswitch *esw,
429b55b3538SParav Pandit 				u16 vport, u16 vlan, u8 qos)
430b55b3538SParav Pandit {
431b55b3538SParav Pandit 	u8 set_flags = 0;
432b55b3538SParav Pandit 	int err = 0;
433b55b3538SParav Pandit 
434b55b3538SParav Pandit 	if (!mlx5_esw_allowed(esw))
4357846665dSMaor Dickman 		return vlan ? -EPERM : 0;
436b55b3538SParav Pandit 
437b55b3538SParav Pandit 	if (vlan || qos)
438b55b3538SParav Pandit 		set_flags = SET_VLAN_STRIP | SET_VLAN_INSERT;
439b55b3538SParav Pandit 
440b55b3538SParav Pandit 	mutex_lock(&esw->state_lock);
441b55b3538SParav Pandit 	if (esw->mode != MLX5_ESWITCH_LEGACY) {
442b55b3538SParav Pandit 		if (!vlan)
443b55b3538SParav Pandit 			goto unlock; /* compatibility with libvirt */
444b55b3538SParav Pandit 
445b55b3538SParav Pandit 		err = -EOPNOTSUPP;
446b55b3538SParav Pandit 		goto unlock;
447b55b3538SParav Pandit 	}
448b55b3538SParav Pandit 
449b55b3538SParav Pandit 	err = __mlx5_eswitch_set_vport_vlan(esw, vport, vlan, qos, set_flags);
450b55b3538SParav Pandit 
451b55b3538SParav Pandit unlock:
452b55b3538SParav Pandit 	mutex_unlock(&esw->state_lock);
453b55b3538SParav Pandit 	return err;
454b55b3538SParav Pandit }
455b55b3538SParav Pandit 
456b55b3538SParav Pandit int mlx5_eswitch_set_vport_spoofchk(struct mlx5_eswitch *esw,
457b55b3538SParav Pandit 				    u16 vport, bool spoofchk)
458b55b3538SParav Pandit {
459b55b3538SParav Pandit 	struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport);
460b55b3538SParav Pandit 	bool pschk;
461b55b3538SParav Pandit 	int err = 0;
462b55b3538SParav Pandit 
463b55b3538SParav Pandit 	if (!mlx5_esw_allowed(esw))
464b55b3538SParav Pandit 		return -EPERM;
465b55b3538SParav Pandit 	if (IS_ERR(evport))
466b55b3538SParav Pandit 		return PTR_ERR(evport);
467b55b3538SParav Pandit 
468b55b3538SParav Pandit 	mutex_lock(&esw->state_lock);
469b55b3538SParav Pandit 	if (esw->mode != MLX5_ESWITCH_LEGACY) {
470b55b3538SParav Pandit 		err = -EOPNOTSUPP;
471b55b3538SParav Pandit 		goto unlock;
472b55b3538SParav Pandit 	}
473b55b3538SParav Pandit 	pschk = evport->info.spoofchk;
474b55b3538SParav Pandit 	evport->info.spoofchk = spoofchk;
475b55b3538SParav Pandit 	if (pschk && !is_valid_ether_addr(evport->info.mac))
476b55b3538SParav Pandit 		mlx5_core_warn(esw->dev,
477b55b3538SParav Pandit 			       "Spoofchk in set while MAC is invalid, vport(%d)\n",
478b55b3538SParav Pandit 			       evport->vport);
479b55b3538SParav Pandit 	if (evport->enabled && esw->mode == MLX5_ESWITCH_LEGACY)
480b55b3538SParav Pandit 		err = esw_acl_ingress_lgcy_setup(esw, evport);
481b55b3538SParav Pandit 	if (err)
482b55b3538SParav Pandit 		evport->info.spoofchk = pschk;
483b55b3538SParav Pandit 
484b55b3538SParav Pandit unlock:
485b55b3538SParav Pandit 	mutex_unlock(&esw->state_lock);
486b55b3538SParav Pandit 	return err;
487b55b3538SParav Pandit }
488b55b3538SParav Pandit 
489b55b3538SParav Pandit int mlx5_eswitch_set_vport_trust(struct mlx5_eswitch *esw,
490b55b3538SParav Pandit 				 u16 vport, bool setting)
491b55b3538SParav Pandit {
492b55b3538SParav Pandit 	struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport);
493b55b3538SParav Pandit 	int err = 0;
494b55b3538SParav Pandit 
495b55b3538SParav Pandit 	if (!mlx5_esw_allowed(esw))
496b55b3538SParav Pandit 		return -EPERM;
497b55b3538SParav Pandit 	if (IS_ERR(evport))
498b55b3538SParav Pandit 		return PTR_ERR(evport);
499b55b3538SParav Pandit 
500b55b3538SParav Pandit 	mutex_lock(&esw->state_lock);
501b55b3538SParav Pandit 	if (esw->mode != MLX5_ESWITCH_LEGACY) {
502b55b3538SParav Pandit 		err = -EOPNOTSUPP;
503b55b3538SParav Pandit 		goto unlock;
504b55b3538SParav Pandit 	}
505b55b3538SParav Pandit 	evport->info.trusted = setting;
506b55b3538SParav Pandit 	if (evport->enabled)
507b55b3538SParav Pandit 		esw_vport_change_handle_locked(evport);
508b55b3538SParav Pandit 
509b55b3538SParav Pandit unlock:
510b55b3538SParav Pandit 	mutex_unlock(&esw->state_lock);
511b55b3538SParav Pandit 	return err;
512b55b3538SParav Pandit }
5132d116e3eSDmytro Linkin 
5142d116e3eSDmytro Linkin int mlx5_eswitch_set_vport_rate(struct mlx5_eswitch *esw, u16 vport,
5152d116e3eSDmytro Linkin 				u32 max_rate, u32 min_rate)
5162d116e3eSDmytro Linkin {
5172d116e3eSDmytro Linkin 	struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport);
5182d116e3eSDmytro Linkin 	int err;
5192d116e3eSDmytro Linkin 
5202d116e3eSDmytro Linkin 	if (!mlx5_esw_allowed(esw))
5212d116e3eSDmytro Linkin 		return -EPERM;
5222d116e3eSDmytro Linkin 	if (IS_ERR(evport))
5232d116e3eSDmytro Linkin 		return PTR_ERR(evport);
5242d116e3eSDmytro Linkin 
5252d116e3eSDmytro Linkin 	mutex_lock(&esw->state_lock);
526d7df09f5SDmytro Linkin 	err = mlx5_esw_qos_set_vport_rate(esw, evport, max_rate, min_rate);
5272d116e3eSDmytro Linkin 	mutex_unlock(&esw->state_lock);
5282d116e3eSDmytro Linkin 	return err;
5292d116e3eSDmytro Linkin }
530