xref: /linux/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.c (revision bf4afc53b77aeaa48b5409da5c8da6bb4eff7f43)
1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
2 /* Copyright (c) 2021 Mellanox Technologies. */
3 
4 #include <linux/build_bug.h>
5 #include <linux/list.h>
6 #include <linux/notifier.h>
7 #include <net/netevent.h>
8 #include <net/switchdev.h>
9 #include "lib/devcom.h"
10 #include "bridge.h"
11 #include "eswitch.h"
12 #include "bridge_priv.h"
13 #define CREATE_TRACE_POINTS
14 #include "diag/bridge_tracepoint.h"
15 
16 static const struct rhashtable_params fdb_ht_params = {
17 	.key_offset = offsetof(struct mlx5_esw_bridge_fdb_entry, key),
18 	.key_len = sizeof(struct mlx5_esw_bridge_fdb_key),
19 	.head_offset = offsetof(struct mlx5_esw_bridge_fdb_entry, ht_node),
20 	.automatic_shrinking = true,
21 };
22 
23 static void
mlx5_esw_bridge_fdb_offload_notify(struct net_device * dev,const unsigned char * addr,u16 vid,unsigned long val)24 mlx5_esw_bridge_fdb_offload_notify(struct net_device *dev, const unsigned char *addr, u16 vid,
25 				   unsigned long val)
26 {
27 	struct switchdev_notifier_fdb_info send_info = {};
28 
29 	send_info.addr = addr;
30 	send_info.vid = vid;
31 	send_info.offloaded = true;
32 	call_switchdev_notifiers(val, dev, &send_info.info, NULL);
33 }
34 
35 static void
mlx5_esw_bridge_fdb_del_notify(struct mlx5_esw_bridge_fdb_entry * entry)36 mlx5_esw_bridge_fdb_del_notify(struct mlx5_esw_bridge_fdb_entry *entry)
37 {
38 	if (!(entry->flags & (MLX5_ESW_BRIDGE_FLAG_ADDED_BY_USER | MLX5_ESW_BRIDGE_FLAG_PEER)))
39 		mlx5_esw_bridge_fdb_offload_notify(entry->dev, entry->key.addr,
40 						   entry->key.vid,
41 						   SWITCHDEV_FDB_DEL_TO_BRIDGE);
42 }
43 
mlx5_esw_bridge_pkt_reformat_vlan_pop_supported(struct mlx5_eswitch * esw)44 static bool mlx5_esw_bridge_pkt_reformat_vlan_pop_supported(struct mlx5_eswitch *esw)
45 {
46 	return BIT(MLX5_CAP_ESW_FLOWTABLE_FDB(esw->dev, reformat_remove)) &&
47 		MLX5_CAP_GEN_2(esw->dev, max_reformat_remove_size) >= sizeof(struct vlan_hdr) &&
48 		MLX5_CAP_GEN_2(esw->dev, max_reformat_remove_offset) >=
49 		offsetof(struct vlan_ethhdr, h_vlan_proto);
50 }
51 
52 static struct mlx5_pkt_reformat *
mlx5_esw_bridge_pkt_reformat_vlan_pop_create(struct mlx5_eswitch * esw)53 mlx5_esw_bridge_pkt_reformat_vlan_pop_create(struct mlx5_eswitch *esw)
54 {
55 	struct mlx5_pkt_reformat_params reformat_params = {};
56 
57 	reformat_params.type = MLX5_REFORMAT_TYPE_REMOVE_HDR;
58 	reformat_params.param_0 = MLX5_REFORMAT_CONTEXT_ANCHOR_MAC_START;
59 	reformat_params.param_1 = offsetof(struct vlan_ethhdr, h_vlan_proto);
60 	reformat_params.size = sizeof(struct vlan_hdr);
61 	return mlx5_packet_reformat_alloc(esw->dev, &reformat_params, MLX5_FLOW_NAMESPACE_FDB);
62 }
63 
64 struct mlx5_flow_table *
mlx5_esw_bridge_table_create(int max_fte,u32 level,struct mlx5_eswitch * esw)65 mlx5_esw_bridge_table_create(int max_fte, u32 level, struct mlx5_eswitch *esw)
66 {
67 	struct mlx5_flow_table_attr ft_attr = {};
68 	struct mlx5_core_dev *dev = esw->dev;
69 	struct mlx5_flow_namespace *ns;
70 	struct mlx5_flow_table *fdb;
71 
72 	ns = mlx5_get_flow_namespace(dev, MLX5_FLOW_NAMESPACE_FDB);
73 	if (!ns) {
74 		esw_warn(dev, "Failed to get FDB namespace\n");
75 		return ERR_PTR(-ENOENT);
76 	}
77 
78 	ft_attr.flags = MLX5_FLOW_TABLE_TUNNEL_EN_REFORMAT;
79 	ft_attr.max_fte = max_fte;
80 	ft_attr.level = level;
81 	ft_attr.prio = FDB_BR_OFFLOAD;
82 	fdb = mlx5_create_flow_table(ns, &ft_attr);
83 	if (IS_ERR(fdb))
84 		esw_warn(dev, "Failed to create bridge FDB Table (err=%pe)\n",
85 			 fdb);
86 
87 	return fdb;
88 }
89 
90 static struct mlx5_flow_group *
mlx5_esw_bridge_ingress_vlan_proto_fg_create(unsigned int from,unsigned int to,u16 vlan_proto,struct mlx5_eswitch * esw,struct mlx5_flow_table * ingress_ft)91 mlx5_esw_bridge_ingress_vlan_proto_fg_create(unsigned int from, unsigned int to, u16 vlan_proto,
92 					     struct mlx5_eswitch *esw,
93 					     struct mlx5_flow_table *ingress_ft)
94 {
95 	int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
96 	struct mlx5_flow_group *fg;
97 	u32 *in, *match;
98 
99 	in = kvzalloc(inlen, GFP_KERNEL);
100 	if (!in)
101 		return ERR_PTR(-ENOMEM);
102 
103 	MLX5_SET(create_flow_group_in, in, match_criteria_enable,
104 		 MLX5_MATCH_OUTER_HEADERS | MLX5_MATCH_MISC_PARAMETERS_2);
105 	match = MLX5_ADDR_OF(create_flow_group_in, in, match_criteria);
106 
107 	MLX5_SET_TO_ONES(fte_match_param, match, outer_headers.smac_47_16);
108 	MLX5_SET_TO_ONES(fte_match_param, match, outer_headers.smac_15_0);
109 	if (vlan_proto == ETH_P_8021Q)
110 		MLX5_SET_TO_ONES(fte_match_param, match, outer_headers.cvlan_tag);
111 	else if (vlan_proto == ETH_P_8021AD)
112 		MLX5_SET_TO_ONES(fte_match_param, match, outer_headers.svlan_tag);
113 	MLX5_SET_TO_ONES(fte_match_param, match, outer_headers.first_vid);
114 
115 	MLX5_SET(fte_match_param, match, misc_parameters_2.metadata_reg_c_0,
116 		 mlx5_eswitch_get_vport_metadata_mask());
117 
118 	MLX5_SET(create_flow_group_in, in, start_flow_index, from);
119 	MLX5_SET(create_flow_group_in, in, end_flow_index, to);
120 
121 	fg = mlx5_create_flow_group(ingress_ft, in);
122 	kvfree(in);
123 	if (IS_ERR(fg))
124 		esw_warn(esw->dev,
125 			 "Failed to create VLAN(proto=%x) flow group for bridge ingress table (err=%pe)\n",
126 			 vlan_proto, fg);
127 
128 	return fg;
129 }
130 
131 static struct mlx5_flow_group *
mlx5_esw_bridge_ingress_vlan_fg_create(struct mlx5_eswitch * esw,struct mlx5_flow_table * ingress_ft)132 mlx5_esw_bridge_ingress_vlan_fg_create(struct mlx5_eswitch *esw,
133 				       struct mlx5_flow_table *ingress_ft)
134 {
135 	unsigned int from = MLX5_ESW_BRIDGE_INGRESS_TABLE_VLAN_GRP_IDX_FROM;
136 	unsigned int to = MLX5_ESW_BRIDGE_INGRESS_TABLE_VLAN_GRP_IDX_TO;
137 
138 	return mlx5_esw_bridge_ingress_vlan_proto_fg_create(from, to, ETH_P_8021Q, esw, ingress_ft);
139 }
140 
141 static struct mlx5_flow_group *
mlx5_esw_bridge_ingress_qinq_fg_create(struct mlx5_eswitch * esw,struct mlx5_flow_table * ingress_ft)142 mlx5_esw_bridge_ingress_qinq_fg_create(struct mlx5_eswitch *esw,
143 				       struct mlx5_flow_table *ingress_ft)
144 {
145 	unsigned int from = MLX5_ESW_BRIDGE_INGRESS_TABLE_QINQ_GRP_IDX_FROM;
146 	unsigned int to = MLX5_ESW_BRIDGE_INGRESS_TABLE_QINQ_GRP_IDX_TO;
147 
148 	return mlx5_esw_bridge_ingress_vlan_proto_fg_create(from, to, ETH_P_8021AD, esw,
149 							    ingress_ft);
150 }
151 
152 static struct mlx5_flow_group *
mlx5_esw_bridge_ingress_vlan_proto_filter_fg_create(unsigned int from,unsigned int to,u16 vlan_proto,struct mlx5_eswitch * esw,struct mlx5_flow_table * ingress_ft)153 mlx5_esw_bridge_ingress_vlan_proto_filter_fg_create(unsigned int from, unsigned int to,
154 						    u16 vlan_proto, struct mlx5_eswitch *esw,
155 						    struct mlx5_flow_table *ingress_ft)
156 {
157 	int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
158 	struct mlx5_flow_group *fg;
159 	u32 *in, *match;
160 
161 	in = kvzalloc(inlen, GFP_KERNEL);
162 	if (!in)
163 		return ERR_PTR(-ENOMEM);
164 
165 	MLX5_SET(create_flow_group_in, in, match_criteria_enable,
166 		 MLX5_MATCH_OUTER_HEADERS | MLX5_MATCH_MISC_PARAMETERS_2);
167 	match = MLX5_ADDR_OF(create_flow_group_in, in, match_criteria);
168 
169 	MLX5_SET_TO_ONES(fte_match_param, match, outer_headers.smac_47_16);
170 	MLX5_SET_TO_ONES(fte_match_param, match, outer_headers.smac_15_0);
171 	if (vlan_proto == ETH_P_8021Q)
172 		MLX5_SET_TO_ONES(fte_match_param, match, outer_headers.cvlan_tag);
173 	else if (vlan_proto == ETH_P_8021AD)
174 		MLX5_SET_TO_ONES(fte_match_param, match, outer_headers.svlan_tag);
175 	MLX5_SET(fte_match_param, match, misc_parameters_2.metadata_reg_c_0,
176 		 mlx5_eswitch_get_vport_metadata_mask());
177 
178 	MLX5_SET(create_flow_group_in, in, start_flow_index, from);
179 	MLX5_SET(create_flow_group_in, in, end_flow_index, to);
180 
181 	fg = mlx5_create_flow_group(ingress_ft, in);
182 	if (IS_ERR(fg))
183 		esw_warn(esw->dev,
184 			 "Failed to create bridge ingress table VLAN filter flow group (err=%pe)\n",
185 			 fg);
186 	kvfree(in);
187 	return fg;
188 }
189 
190 static struct mlx5_flow_group *
mlx5_esw_bridge_ingress_vlan_filter_fg_create(struct mlx5_eswitch * esw,struct mlx5_flow_table * ingress_ft)191 mlx5_esw_bridge_ingress_vlan_filter_fg_create(struct mlx5_eswitch *esw,
192 					      struct mlx5_flow_table *ingress_ft)
193 {
194 	unsigned int from = MLX5_ESW_BRIDGE_INGRESS_TABLE_VLAN_FILTER_GRP_IDX_FROM;
195 	unsigned int to = MLX5_ESW_BRIDGE_INGRESS_TABLE_VLAN_FILTER_GRP_IDX_TO;
196 
197 	return mlx5_esw_bridge_ingress_vlan_proto_filter_fg_create(from, to, ETH_P_8021Q, esw,
198 								   ingress_ft);
199 }
200 
201 static struct mlx5_flow_group *
mlx5_esw_bridge_ingress_qinq_filter_fg_create(struct mlx5_eswitch * esw,struct mlx5_flow_table * ingress_ft)202 mlx5_esw_bridge_ingress_qinq_filter_fg_create(struct mlx5_eswitch *esw,
203 					      struct mlx5_flow_table *ingress_ft)
204 {
205 	unsigned int from = MLX5_ESW_BRIDGE_INGRESS_TABLE_QINQ_FILTER_GRP_IDX_FROM;
206 	unsigned int to = MLX5_ESW_BRIDGE_INGRESS_TABLE_QINQ_FILTER_GRP_IDX_TO;
207 
208 	return mlx5_esw_bridge_ingress_vlan_proto_filter_fg_create(from, to, ETH_P_8021AD, esw,
209 								   ingress_ft);
210 }
211 
212 static struct mlx5_flow_group *
mlx5_esw_bridge_ingress_mac_fg_create(struct mlx5_eswitch * esw,struct mlx5_flow_table * ingress_ft)213 mlx5_esw_bridge_ingress_mac_fg_create(struct mlx5_eswitch *esw, struct mlx5_flow_table *ingress_ft)
214 {
215 	int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
216 	struct mlx5_flow_group *fg;
217 	u32 *in, *match;
218 
219 	in = kvzalloc(inlen, GFP_KERNEL);
220 	if (!in)
221 		return ERR_PTR(-ENOMEM);
222 
223 	MLX5_SET(create_flow_group_in, in, match_criteria_enable,
224 		 MLX5_MATCH_OUTER_HEADERS | MLX5_MATCH_MISC_PARAMETERS_2);
225 	match = MLX5_ADDR_OF(create_flow_group_in, in, match_criteria);
226 
227 	MLX5_SET_TO_ONES(fte_match_param, match, outer_headers.smac_47_16);
228 	MLX5_SET_TO_ONES(fte_match_param, match, outer_headers.smac_15_0);
229 
230 	MLX5_SET(fte_match_param, match, misc_parameters_2.metadata_reg_c_0,
231 		 mlx5_eswitch_get_vport_metadata_mask());
232 
233 	MLX5_SET(create_flow_group_in, in, start_flow_index,
234 		 MLX5_ESW_BRIDGE_INGRESS_TABLE_MAC_GRP_IDX_FROM);
235 	MLX5_SET(create_flow_group_in, in, end_flow_index,
236 		 MLX5_ESW_BRIDGE_INGRESS_TABLE_MAC_GRP_IDX_TO);
237 
238 	fg = mlx5_create_flow_group(ingress_ft, in);
239 	if (IS_ERR(fg))
240 		esw_warn(esw->dev,
241 			 "Failed to create MAC flow group for bridge ingress table (err=%pe)\n",
242 			 fg);
243 
244 	kvfree(in);
245 	return fg;
246 }
247 
248 static struct mlx5_flow_group *
mlx5_esw_bridge_egress_vlan_proto_fg_create(unsigned int from,unsigned int to,u16 vlan_proto,struct mlx5_eswitch * esw,struct mlx5_flow_table * egress_ft)249 mlx5_esw_bridge_egress_vlan_proto_fg_create(unsigned int from, unsigned int to, u16 vlan_proto,
250 					    struct mlx5_eswitch *esw,
251 					    struct mlx5_flow_table *egress_ft)
252 {
253 	int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
254 	struct mlx5_flow_group *fg;
255 	u32 *in, *match;
256 
257 	in = kvzalloc(inlen, GFP_KERNEL);
258 	if (!in)
259 		return ERR_PTR(-ENOMEM);
260 
261 	MLX5_SET(create_flow_group_in, in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS);
262 	match = MLX5_ADDR_OF(create_flow_group_in, in, match_criteria);
263 
264 	MLX5_SET_TO_ONES(fte_match_param, match, outer_headers.dmac_47_16);
265 	MLX5_SET_TO_ONES(fte_match_param, match, outer_headers.dmac_15_0);
266 	if (vlan_proto == ETH_P_8021Q)
267 		MLX5_SET_TO_ONES(fte_match_param, match, outer_headers.cvlan_tag);
268 	else if (vlan_proto == ETH_P_8021AD)
269 		MLX5_SET_TO_ONES(fte_match_param, match, outer_headers.svlan_tag);
270 	MLX5_SET_TO_ONES(fte_match_param, match, outer_headers.first_vid);
271 
272 	MLX5_SET(create_flow_group_in, in, start_flow_index, from);
273 	MLX5_SET(create_flow_group_in, in, end_flow_index, to);
274 
275 	fg = mlx5_create_flow_group(egress_ft, in);
276 	if (IS_ERR(fg))
277 		esw_warn(esw->dev,
278 			 "Failed to create VLAN flow group for bridge egress table (err=%pe)\n",
279 			 fg);
280 	kvfree(in);
281 	return fg;
282 }
283 
284 static struct mlx5_flow_group *
mlx5_esw_bridge_egress_vlan_fg_create(struct mlx5_eswitch * esw,struct mlx5_flow_table * egress_ft)285 mlx5_esw_bridge_egress_vlan_fg_create(struct mlx5_eswitch *esw, struct mlx5_flow_table *egress_ft)
286 {
287 	unsigned int from = MLX5_ESW_BRIDGE_EGRESS_TABLE_VLAN_GRP_IDX_FROM;
288 	unsigned int to = MLX5_ESW_BRIDGE_EGRESS_TABLE_VLAN_GRP_IDX_TO;
289 
290 	return mlx5_esw_bridge_egress_vlan_proto_fg_create(from, to, ETH_P_8021Q, esw, egress_ft);
291 }
292 
293 static struct mlx5_flow_group *
mlx5_esw_bridge_egress_qinq_fg_create(struct mlx5_eswitch * esw,struct mlx5_flow_table * egress_ft)294 mlx5_esw_bridge_egress_qinq_fg_create(struct mlx5_eswitch *esw,
295 				      struct mlx5_flow_table *egress_ft)
296 {
297 	unsigned int from = MLX5_ESW_BRIDGE_EGRESS_TABLE_QINQ_GRP_IDX_FROM;
298 	unsigned int to = MLX5_ESW_BRIDGE_EGRESS_TABLE_QINQ_GRP_IDX_TO;
299 
300 	return mlx5_esw_bridge_egress_vlan_proto_fg_create(from, to, ETH_P_8021AD, esw, egress_ft);
301 }
302 
303 static struct mlx5_flow_group *
mlx5_esw_bridge_egress_mac_fg_create(struct mlx5_eswitch * esw,struct mlx5_flow_table * egress_ft)304 mlx5_esw_bridge_egress_mac_fg_create(struct mlx5_eswitch *esw, struct mlx5_flow_table *egress_ft)
305 {
306 	int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
307 	struct mlx5_flow_group *fg;
308 	u32 *in, *match;
309 
310 	in = kvzalloc(inlen, GFP_KERNEL);
311 	if (!in)
312 		return ERR_PTR(-ENOMEM);
313 
314 	MLX5_SET(create_flow_group_in, in, match_criteria_enable, MLX5_MATCH_OUTER_HEADERS);
315 	match = MLX5_ADDR_OF(create_flow_group_in, in, match_criteria);
316 
317 	MLX5_SET_TO_ONES(fte_match_param, match, outer_headers.dmac_47_16);
318 	MLX5_SET_TO_ONES(fte_match_param, match, outer_headers.dmac_15_0);
319 
320 	MLX5_SET(create_flow_group_in, in, start_flow_index,
321 		 MLX5_ESW_BRIDGE_EGRESS_TABLE_MAC_GRP_IDX_FROM);
322 	MLX5_SET(create_flow_group_in, in, end_flow_index,
323 		 MLX5_ESW_BRIDGE_EGRESS_TABLE_MAC_GRP_IDX_TO);
324 
325 	fg = mlx5_create_flow_group(egress_ft, in);
326 	if (IS_ERR(fg))
327 		esw_warn(esw->dev,
328 			 "Failed to create bridge egress table MAC flow group (err=%pe)\n",
329 			 fg);
330 	kvfree(in);
331 	return fg;
332 }
333 
334 static struct mlx5_flow_group *
mlx5_esw_bridge_egress_miss_fg_create(struct mlx5_eswitch * esw,struct mlx5_flow_table * egress_ft)335 mlx5_esw_bridge_egress_miss_fg_create(struct mlx5_eswitch *esw, struct mlx5_flow_table *egress_ft)
336 {
337 	int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
338 	struct mlx5_flow_group *fg;
339 	u32 *in, *match;
340 
341 	in = kvzalloc(inlen, GFP_KERNEL);
342 	if (!in)
343 		return ERR_PTR(-ENOMEM);
344 
345 	MLX5_SET(create_flow_group_in, in, match_criteria_enable, MLX5_MATCH_MISC_PARAMETERS_2);
346 	match = MLX5_ADDR_OF(create_flow_group_in, in, match_criteria);
347 
348 	MLX5_SET(fte_match_param, match, misc_parameters_2.metadata_reg_c_1, ESW_TUN_MASK);
349 
350 	MLX5_SET(create_flow_group_in, in, start_flow_index,
351 		 MLX5_ESW_BRIDGE_EGRESS_TABLE_MISS_GRP_IDX_FROM);
352 	MLX5_SET(create_flow_group_in, in, end_flow_index,
353 		 MLX5_ESW_BRIDGE_EGRESS_TABLE_MISS_GRP_IDX_TO);
354 
355 	fg = mlx5_create_flow_group(egress_ft, in);
356 	if (IS_ERR(fg))
357 		esw_warn(esw->dev,
358 			 "Failed to create bridge egress table miss flow group (err=%pe)\n",
359 			 fg);
360 	kvfree(in);
361 	return fg;
362 }
363 
364 static int
mlx5_esw_bridge_ingress_table_init(struct mlx5_esw_bridge_offloads * br_offloads)365 mlx5_esw_bridge_ingress_table_init(struct mlx5_esw_bridge_offloads *br_offloads)
366 {
367 	struct mlx5_flow_group *mac_fg, *qinq_filter_fg, *qinq_fg, *vlan_filter_fg, *vlan_fg;
368 	struct mlx5_flow_table *ingress_ft, *skip_ft;
369 	struct mlx5_eswitch *esw = br_offloads->esw;
370 	int err;
371 
372 	if (!mlx5_eswitch_vport_match_metadata_enabled(esw))
373 		return -EOPNOTSUPP;
374 
375 	ingress_ft = mlx5_esw_bridge_table_create(MLX5_ESW_BRIDGE_INGRESS_TABLE_SIZE,
376 						  MLX5_ESW_BRIDGE_LEVEL_INGRESS_TABLE,
377 						  esw);
378 	if (IS_ERR(ingress_ft))
379 		return PTR_ERR(ingress_ft);
380 
381 	skip_ft = mlx5_esw_bridge_table_create(MLX5_ESW_BRIDGE_SKIP_TABLE_SIZE,
382 					       MLX5_ESW_BRIDGE_LEVEL_SKIP_TABLE,
383 					       esw);
384 	if (IS_ERR(skip_ft)) {
385 		err = PTR_ERR(skip_ft);
386 		goto err_skip_tbl;
387 	}
388 
389 	vlan_fg = mlx5_esw_bridge_ingress_vlan_fg_create(esw, ingress_ft);
390 	if (IS_ERR(vlan_fg)) {
391 		err = PTR_ERR(vlan_fg);
392 		goto err_vlan_fg;
393 	}
394 
395 	vlan_filter_fg = mlx5_esw_bridge_ingress_vlan_filter_fg_create(esw, ingress_ft);
396 	if (IS_ERR(vlan_filter_fg)) {
397 		err = PTR_ERR(vlan_filter_fg);
398 		goto err_vlan_filter_fg;
399 	}
400 
401 	qinq_fg = mlx5_esw_bridge_ingress_qinq_fg_create(esw, ingress_ft);
402 	if (IS_ERR(qinq_fg)) {
403 		err = PTR_ERR(qinq_fg);
404 		goto err_qinq_fg;
405 	}
406 
407 	qinq_filter_fg = mlx5_esw_bridge_ingress_qinq_filter_fg_create(esw, ingress_ft);
408 	if (IS_ERR(qinq_filter_fg)) {
409 		err = PTR_ERR(qinq_filter_fg);
410 		goto err_qinq_filter_fg;
411 	}
412 
413 	mac_fg = mlx5_esw_bridge_ingress_mac_fg_create(esw, ingress_ft);
414 	if (IS_ERR(mac_fg)) {
415 		err = PTR_ERR(mac_fg);
416 		goto err_mac_fg;
417 	}
418 
419 	br_offloads->ingress_ft = ingress_ft;
420 	br_offloads->skip_ft = skip_ft;
421 	br_offloads->ingress_vlan_fg = vlan_fg;
422 	br_offloads->ingress_vlan_filter_fg = vlan_filter_fg;
423 	br_offloads->ingress_qinq_fg = qinq_fg;
424 	br_offloads->ingress_qinq_filter_fg = qinq_filter_fg;
425 	br_offloads->ingress_mac_fg = mac_fg;
426 	return 0;
427 
428 err_mac_fg:
429 	mlx5_destroy_flow_group(qinq_filter_fg);
430 err_qinq_filter_fg:
431 	mlx5_destroy_flow_group(qinq_fg);
432 err_qinq_fg:
433 	mlx5_destroy_flow_group(vlan_filter_fg);
434 err_vlan_filter_fg:
435 	mlx5_destroy_flow_group(vlan_fg);
436 err_vlan_fg:
437 	mlx5_destroy_flow_table(skip_ft);
438 err_skip_tbl:
439 	mlx5_destroy_flow_table(ingress_ft);
440 	return err;
441 }
442 
443 static void
mlx5_esw_bridge_ingress_table_cleanup(struct mlx5_esw_bridge_offloads * br_offloads)444 mlx5_esw_bridge_ingress_table_cleanup(struct mlx5_esw_bridge_offloads *br_offloads)
445 {
446 	mlx5_destroy_flow_group(br_offloads->ingress_mac_fg);
447 	br_offloads->ingress_mac_fg = NULL;
448 	mlx5_destroy_flow_group(br_offloads->ingress_qinq_filter_fg);
449 	br_offloads->ingress_qinq_filter_fg = NULL;
450 	mlx5_destroy_flow_group(br_offloads->ingress_qinq_fg);
451 	br_offloads->ingress_qinq_fg = NULL;
452 	mlx5_destroy_flow_group(br_offloads->ingress_vlan_filter_fg);
453 	br_offloads->ingress_vlan_filter_fg = NULL;
454 	mlx5_destroy_flow_group(br_offloads->ingress_vlan_fg);
455 	br_offloads->ingress_vlan_fg = NULL;
456 	mlx5_destroy_flow_table(br_offloads->skip_ft);
457 	br_offloads->skip_ft = NULL;
458 	mlx5_destroy_flow_table(br_offloads->ingress_ft);
459 	br_offloads->ingress_ft = NULL;
460 }
461 
462 static struct mlx5_flow_handle *
463 mlx5_esw_bridge_egress_miss_flow_create(struct mlx5_flow_table *egress_ft,
464 					struct mlx5_flow_table *skip_ft,
465 					struct mlx5_pkt_reformat *pkt_reformat);
466 
467 static int
mlx5_esw_bridge_egress_table_init(struct mlx5_esw_bridge_offloads * br_offloads,struct mlx5_esw_bridge * bridge)468 mlx5_esw_bridge_egress_table_init(struct mlx5_esw_bridge_offloads *br_offloads,
469 				  struct mlx5_esw_bridge *bridge)
470 {
471 	struct mlx5_flow_group *miss_fg = NULL, *mac_fg, *vlan_fg, *qinq_fg;
472 	struct mlx5_pkt_reformat *miss_pkt_reformat = NULL;
473 	struct mlx5_flow_handle *miss_handle = NULL;
474 	struct mlx5_eswitch *esw = br_offloads->esw;
475 	struct mlx5_flow_table *egress_ft;
476 	int err;
477 
478 	egress_ft = mlx5_esw_bridge_table_create(MLX5_ESW_BRIDGE_EGRESS_TABLE_SIZE,
479 						 MLX5_ESW_BRIDGE_LEVEL_EGRESS_TABLE,
480 						 esw);
481 	if (IS_ERR(egress_ft))
482 		return PTR_ERR(egress_ft);
483 
484 	vlan_fg = mlx5_esw_bridge_egress_vlan_fg_create(esw, egress_ft);
485 	if (IS_ERR(vlan_fg)) {
486 		err = PTR_ERR(vlan_fg);
487 		goto err_vlan_fg;
488 	}
489 
490 	qinq_fg = mlx5_esw_bridge_egress_qinq_fg_create(esw, egress_ft);
491 	if (IS_ERR(qinq_fg)) {
492 		err = PTR_ERR(qinq_fg);
493 		goto err_qinq_fg;
494 	}
495 
496 	mac_fg = mlx5_esw_bridge_egress_mac_fg_create(esw, egress_ft);
497 	if (IS_ERR(mac_fg)) {
498 		err = PTR_ERR(mac_fg);
499 		goto err_mac_fg;
500 	}
501 
502 	if (mlx5_esw_bridge_pkt_reformat_vlan_pop_supported(esw)) {
503 		miss_fg = mlx5_esw_bridge_egress_miss_fg_create(esw, egress_ft);
504 		if (IS_ERR(miss_fg)) {
505 			esw_warn(esw->dev, "Failed to create miss flow group (err=%pe)\n",
506 				 miss_fg);
507 			miss_fg = NULL;
508 			goto skip_miss_flow;
509 		}
510 
511 		miss_pkt_reformat = mlx5_esw_bridge_pkt_reformat_vlan_pop_create(esw);
512 		if (IS_ERR(miss_pkt_reformat)) {
513 			esw_warn(esw->dev,
514 				 "Failed to alloc packet reformat REMOVE_HEADER (err=%pe)\n",
515 				 miss_pkt_reformat);
516 			miss_pkt_reformat = NULL;
517 			mlx5_destroy_flow_group(miss_fg);
518 			miss_fg = NULL;
519 			goto skip_miss_flow;
520 		}
521 
522 		miss_handle = mlx5_esw_bridge_egress_miss_flow_create(egress_ft,
523 								      br_offloads->skip_ft,
524 								      miss_pkt_reformat);
525 		if (IS_ERR(miss_handle)) {
526 			esw_warn(esw->dev, "Failed to create miss flow (err=%pe)\n",
527 				 miss_handle);
528 			miss_handle = NULL;
529 			mlx5_packet_reformat_dealloc(esw->dev, miss_pkt_reformat);
530 			miss_pkt_reformat = NULL;
531 			mlx5_destroy_flow_group(miss_fg);
532 			miss_fg = NULL;
533 			goto skip_miss_flow;
534 		}
535 	}
536 skip_miss_flow:
537 
538 	bridge->egress_ft = egress_ft;
539 	bridge->egress_vlan_fg = vlan_fg;
540 	bridge->egress_qinq_fg = qinq_fg;
541 	bridge->egress_mac_fg = mac_fg;
542 	bridge->egress_miss_fg = miss_fg;
543 	bridge->egress_miss_pkt_reformat = miss_pkt_reformat;
544 	bridge->egress_miss_handle = miss_handle;
545 	return 0;
546 
547 err_mac_fg:
548 	mlx5_destroy_flow_group(qinq_fg);
549 err_qinq_fg:
550 	mlx5_destroy_flow_group(vlan_fg);
551 err_vlan_fg:
552 	mlx5_destroy_flow_table(egress_ft);
553 	return err;
554 }
555 
556 static void
mlx5_esw_bridge_egress_table_cleanup(struct mlx5_esw_bridge * bridge)557 mlx5_esw_bridge_egress_table_cleanup(struct mlx5_esw_bridge *bridge)
558 {
559 	if (bridge->egress_miss_handle)
560 		mlx5_del_flow_rules(bridge->egress_miss_handle);
561 	if (bridge->egress_miss_pkt_reformat)
562 		mlx5_packet_reformat_dealloc(bridge->br_offloads->esw->dev,
563 					     bridge->egress_miss_pkt_reformat);
564 	if (bridge->egress_miss_fg)
565 		mlx5_destroy_flow_group(bridge->egress_miss_fg);
566 	mlx5_destroy_flow_group(bridge->egress_mac_fg);
567 	mlx5_destroy_flow_group(bridge->egress_qinq_fg);
568 	mlx5_destroy_flow_group(bridge->egress_vlan_fg);
569 	mlx5_destroy_flow_table(bridge->egress_ft);
570 }
571 
572 static struct mlx5_flow_handle *
mlx5_esw_bridge_ingress_flow_with_esw_create(u16 vport_num,const unsigned char * addr,struct mlx5_esw_bridge_vlan * vlan,struct mlx5_fc * counter,struct mlx5_esw_bridge * bridge,struct mlx5_eswitch * esw)573 mlx5_esw_bridge_ingress_flow_with_esw_create(u16 vport_num, const unsigned char *addr,
574 					     struct mlx5_esw_bridge_vlan *vlan,
575 					     struct mlx5_fc *counter,
576 					     struct mlx5_esw_bridge *bridge,
577 					     struct mlx5_eswitch *esw)
578 {
579 	struct mlx5_esw_bridge_offloads *br_offloads = bridge->br_offloads;
580 	struct mlx5_flow_act flow_act = {
581 		.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST | MLX5_FLOW_CONTEXT_ACTION_COUNT,
582 		.flags = FLOW_ACT_NO_APPEND,
583 	};
584 	struct mlx5_flow_destination dests[2] = {};
585 	struct mlx5_flow_spec *rule_spec;
586 	struct mlx5_flow_handle *handle;
587 	u8 *smac_v, *smac_c;
588 
589 	rule_spec = kvzalloc_obj(*rule_spec);
590 	if (!rule_spec)
591 		return ERR_PTR(-ENOMEM);
592 
593 	rule_spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS | MLX5_MATCH_MISC_PARAMETERS_2;
594 
595 	smac_v = MLX5_ADDR_OF(fte_match_param, rule_spec->match_value,
596 			      outer_headers.smac_47_16);
597 	ether_addr_copy(smac_v, addr);
598 	smac_c = MLX5_ADDR_OF(fte_match_param, rule_spec->match_criteria,
599 			      outer_headers.smac_47_16);
600 	eth_broadcast_addr(smac_c);
601 
602 	MLX5_SET(fte_match_param, rule_spec->match_criteria,
603 		 misc_parameters_2.metadata_reg_c_0, mlx5_eswitch_get_vport_metadata_mask());
604 	MLX5_SET(fte_match_param, rule_spec->match_value, misc_parameters_2.metadata_reg_c_0,
605 		 mlx5_eswitch_get_vport_metadata_for_match(esw, vport_num));
606 
607 	if (vlan && vlan->pkt_reformat_push) {
608 		flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT |
609 			MLX5_FLOW_CONTEXT_ACTION_MOD_HDR;
610 		flow_act.pkt_reformat = vlan->pkt_reformat_push;
611 		flow_act.modify_hdr = vlan->pkt_mod_hdr_push_mark;
612 	} else if (vlan) {
613 		if (bridge->vlan_proto == ETH_P_8021Q) {
614 			MLX5_SET_TO_ONES(fte_match_param, rule_spec->match_criteria,
615 					 outer_headers.cvlan_tag);
616 			MLX5_SET_TO_ONES(fte_match_param, rule_spec->match_value,
617 					 outer_headers.cvlan_tag);
618 		} else if (bridge->vlan_proto == ETH_P_8021AD) {
619 			MLX5_SET_TO_ONES(fte_match_param, rule_spec->match_criteria,
620 					 outer_headers.svlan_tag);
621 			MLX5_SET_TO_ONES(fte_match_param, rule_spec->match_value,
622 					 outer_headers.svlan_tag);
623 		}
624 		MLX5_SET_TO_ONES(fte_match_param, rule_spec->match_criteria,
625 				 outer_headers.first_vid);
626 		MLX5_SET(fte_match_param, rule_spec->match_value, outer_headers.first_vid,
627 			 vlan->vid);
628 	}
629 
630 	dests[0].type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
631 	dests[0].ft = bridge->egress_ft;
632 	dests[1].type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
633 	dests[1].counter = counter;
634 
635 	handle = mlx5_add_flow_rules(br_offloads->ingress_ft, rule_spec, &flow_act, dests,
636 				     ARRAY_SIZE(dests));
637 
638 	kvfree(rule_spec);
639 	return handle;
640 }
641 
642 static struct mlx5_flow_handle *
mlx5_esw_bridge_ingress_flow_create(u16 vport_num,const unsigned char * addr,struct mlx5_esw_bridge_vlan * vlan,struct mlx5_fc * counter,struct mlx5_esw_bridge * bridge)643 mlx5_esw_bridge_ingress_flow_create(u16 vport_num, const unsigned char *addr,
644 				    struct mlx5_esw_bridge_vlan *vlan,
645 				    struct mlx5_fc *counter,
646 				    struct mlx5_esw_bridge *bridge)
647 {
648 	return mlx5_esw_bridge_ingress_flow_with_esw_create(vport_num, addr, vlan, counter,
649 							    bridge, bridge->br_offloads->esw);
650 }
651 
652 static struct mlx5_flow_handle *
mlx5_esw_bridge_ingress_flow_peer_create(u16 vport_num,u16 esw_owner_vhca_id,const unsigned char * addr,struct mlx5_esw_bridge_vlan * vlan,struct mlx5_fc * counter,struct mlx5_esw_bridge * bridge)653 mlx5_esw_bridge_ingress_flow_peer_create(u16 vport_num, u16 esw_owner_vhca_id,
654 					 const unsigned char *addr,
655 					 struct mlx5_esw_bridge_vlan *vlan,
656 					 struct mlx5_fc *counter,
657 					 struct mlx5_esw_bridge *bridge)
658 {
659 	struct mlx5_devcom_comp_dev *devcom = bridge->br_offloads->esw->devcom, *pos;
660 	struct mlx5_eswitch *tmp, *peer_esw = NULL;
661 	static struct mlx5_flow_handle *handle;
662 
663 	if (!mlx5_devcom_for_each_peer_begin(devcom))
664 		return ERR_PTR(-ENODEV);
665 
666 	mlx5_devcom_for_each_peer_entry(devcom, tmp, pos) {
667 		if (mlx5_esw_is_owner(tmp, vport_num, esw_owner_vhca_id)) {
668 			peer_esw = tmp;
669 			break;
670 		}
671 	}
672 
673 	if (!peer_esw) {
674 		handle = ERR_PTR(-ENODEV);
675 		goto out;
676 	}
677 
678 	handle = mlx5_esw_bridge_ingress_flow_with_esw_create(vport_num, addr, vlan, counter,
679 							      bridge, peer_esw);
680 
681 out:
682 	mlx5_devcom_for_each_peer_end(devcom);
683 	return handle;
684 }
685 
686 static struct mlx5_flow_handle *
mlx5_esw_bridge_ingress_filter_flow_create(u16 vport_num,const unsigned char * addr,struct mlx5_esw_bridge * bridge)687 mlx5_esw_bridge_ingress_filter_flow_create(u16 vport_num, const unsigned char *addr,
688 					   struct mlx5_esw_bridge *bridge)
689 {
690 	struct mlx5_esw_bridge_offloads *br_offloads = bridge->br_offloads;
691 	struct mlx5_flow_destination dest = {
692 		.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE,
693 		.ft = br_offloads->skip_ft,
694 	};
695 	struct mlx5_flow_act flow_act = {
696 		.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST,
697 		.flags = FLOW_ACT_NO_APPEND,
698 	};
699 	struct mlx5_flow_spec *rule_spec;
700 	struct mlx5_flow_handle *handle;
701 	u8 *smac_v, *smac_c;
702 
703 	rule_spec = kvzalloc_obj(*rule_spec);
704 	if (!rule_spec)
705 		return ERR_PTR(-ENOMEM);
706 
707 	rule_spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS | MLX5_MATCH_MISC_PARAMETERS_2;
708 
709 	smac_v = MLX5_ADDR_OF(fte_match_param, rule_spec->match_value,
710 			      outer_headers.smac_47_16);
711 	ether_addr_copy(smac_v, addr);
712 	smac_c = MLX5_ADDR_OF(fte_match_param, rule_spec->match_criteria,
713 			      outer_headers.smac_47_16);
714 	eth_broadcast_addr(smac_c);
715 
716 	MLX5_SET(fte_match_param, rule_spec->match_criteria,
717 		 misc_parameters_2.metadata_reg_c_0, mlx5_eswitch_get_vport_metadata_mask());
718 	MLX5_SET(fte_match_param, rule_spec->match_value, misc_parameters_2.metadata_reg_c_0,
719 		 mlx5_eswitch_get_vport_metadata_for_match(br_offloads->esw, vport_num));
720 
721 	if (bridge->vlan_proto == ETH_P_8021Q) {
722 		MLX5_SET_TO_ONES(fte_match_param, rule_spec->match_criteria,
723 				 outer_headers.cvlan_tag);
724 		MLX5_SET_TO_ONES(fte_match_param, rule_spec->match_value,
725 				 outer_headers.cvlan_tag);
726 	} else if (bridge->vlan_proto == ETH_P_8021AD) {
727 		MLX5_SET_TO_ONES(fte_match_param, rule_spec->match_criteria,
728 				 outer_headers.svlan_tag);
729 		MLX5_SET_TO_ONES(fte_match_param, rule_spec->match_value,
730 				 outer_headers.svlan_tag);
731 	}
732 
733 	handle = mlx5_add_flow_rules(br_offloads->ingress_ft, rule_spec, &flow_act, &dest, 1);
734 
735 	kvfree(rule_spec);
736 	return handle;
737 }
738 
739 static struct mlx5_flow_handle *
mlx5_esw_bridge_egress_flow_create(u16 vport_num,u16 esw_owner_vhca_id,const unsigned char * addr,struct mlx5_esw_bridge_vlan * vlan,struct mlx5_esw_bridge * bridge)740 mlx5_esw_bridge_egress_flow_create(u16 vport_num, u16 esw_owner_vhca_id, const unsigned char *addr,
741 				   struct mlx5_esw_bridge_vlan *vlan,
742 				   struct mlx5_esw_bridge *bridge)
743 {
744 	struct mlx5_flow_destination dest = {
745 		.type = MLX5_FLOW_DESTINATION_TYPE_VPORT,
746 		.vport.num = vport_num,
747 	};
748 	struct mlx5_flow_act flow_act = {
749 		.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST,
750 		.flags = FLOW_ACT_NO_APPEND,
751 	};
752 	struct mlx5_flow_spec *rule_spec;
753 	struct mlx5_flow_handle *handle;
754 	u8 *dmac_v, *dmac_c;
755 
756 	rule_spec = kvzalloc_obj(*rule_spec);
757 	if (!rule_spec)
758 		return ERR_PTR(-ENOMEM);
759 
760 	if (MLX5_CAP_ESW_FLOWTABLE(bridge->br_offloads->esw->dev, flow_source) &&
761 	    vport_num == MLX5_VPORT_UPLINK)
762 		rule_spec->flow_context.flow_source =
763 			MLX5_FLOW_CONTEXT_FLOW_SOURCE_LOCAL_VPORT;
764 	rule_spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS;
765 
766 	dmac_v = MLX5_ADDR_OF(fte_match_param, rule_spec->match_value,
767 			      outer_headers.dmac_47_16);
768 	ether_addr_copy(dmac_v, addr);
769 	dmac_c = MLX5_ADDR_OF(fte_match_param, rule_spec->match_criteria,
770 			      outer_headers.dmac_47_16);
771 	eth_broadcast_addr(dmac_c);
772 
773 	if (vlan) {
774 		if (vlan->pkt_reformat_pop) {
775 			flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT;
776 			flow_act.pkt_reformat = vlan->pkt_reformat_pop;
777 		}
778 
779 		if (bridge->vlan_proto == ETH_P_8021Q) {
780 			MLX5_SET_TO_ONES(fte_match_param, rule_spec->match_criteria,
781 					 outer_headers.cvlan_tag);
782 			MLX5_SET_TO_ONES(fte_match_param, rule_spec->match_value,
783 					 outer_headers.cvlan_tag);
784 		} else if (bridge->vlan_proto == ETH_P_8021AD) {
785 			MLX5_SET_TO_ONES(fte_match_param, rule_spec->match_criteria,
786 					 outer_headers.svlan_tag);
787 			MLX5_SET_TO_ONES(fte_match_param, rule_spec->match_value,
788 					 outer_headers.svlan_tag);
789 		}
790 		MLX5_SET_TO_ONES(fte_match_param, rule_spec->match_criteria,
791 				 outer_headers.first_vid);
792 		MLX5_SET(fte_match_param, rule_spec->match_value, outer_headers.first_vid,
793 			 vlan->vid);
794 	}
795 
796 	if (MLX5_CAP_ESW(bridge->br_offloads->esw->dev, merged_eswitch)) {
797 		dest.vport.flags = MLX5_FLOW_DEST_VPORT_VHCA_ID;
798 		dest.vport.vhca_id = esw_owner_vhca_id;
799 	}
800 	handle = mlx5_add_flow_rules(bridge->egress_ft, rule_spec, &flow_act, &dest, 1);
801 
802 	kvfree(rule_spec);
803 	return handle;
804 }
805 
806 static struct mlx5_flow_handle *
mlx5_esw_bridge_egress_miss_flow_create(struct mlx5_flow_table * egress_ft,struct mlx5_flow_table * skip_ft,struct mlx5_pkt_reformat * pkt_reformat)807 mlx5_esw_bridge_egress_miss_flow_create(struct mlx5_flow_table *egress_ft,
808 					struct mlx5_flow_table *skip_ft,
809 					struct mlx5_pkt_reformat *pkt_reformat)
810 {
811 	struct mlx5_flow_destination dest = {
812 		.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE,
813 		.ft = skip_ft,
814 	};
815 	struct mlx5_flow_act flow_act = {
816 		.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST |
817 		MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT,
818 		.flags = FLOW_ACT_NO_APPEND,
819 		.pkt_reformat = pkt_reformat,
820 	};
821 	struct mlx5_flow_spec *rule_spec;
822 	struct mlx5_flow_handle *handle;
823 
824 	rule_spec = kvzalloc_obj(*rule_spec);
825 	if (!rule_spec)
826 		return ERR_PTR(-ENOMEM);
827 
828 	rule_spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS_2;
829 
830 	MLX5_SET(fte_match_param, rule_spec->match_criteria,
831 		 misc_parameters_2.metadata_reg_c_1, ESW_TUN_MASK);
832 	MLX5_SET(fte_match_param, rule_spec->match_value, misc_parameters_2.metadata_reg_c_1,
833 		 ESW_TUN_BRIDGE_INGRESS_PUSH_VLAN_MARK);
834 
835 	handle = mlx5_add_flow_rules(egress_ft, rule_spec, &flow_act, &dest, 1);
836 
837 	kvfree(rule_spec);
838 	return handle;
839 }
840 
mlx5_esw_bridge_create(struct net_device * br_netdev,struct mlx5_esw_bridge_offloads * br_offloads)841 static struct mlx5_esw_bridge *mlx5_esw_bridge_create(struct net_device *br_netdev,
842 						      struct mlx5_esw_bridge_offloads *br_offloads)
843 {
844 	struct mlx5_esw_bridge *bridge;
845 	int err;
846 
847 	bridge = kvzalloc_obj(*bridge);
848 	if (!bridge)
849 		return ERR_PTR(-ENOMEM);
850 
851 	bridge->br_offloads = br_offloads;
852 	err = mlx5_esw_bridge_egress_table_init(br_offloads, bridge);
853 	if (err)
854 		goto err_egress_tbl;
855 
856 	err = rhashtable_init(&bridge->fdb_ht, &fdb_ht_params);
857 	if (err)
858 		goto err_fdb_ht;
859 
860 	err = mlx5_esw_bridge_mdb_init(bridge);
861 	if (err)
862 		goto err_mdb_ht;
863 
864 	INIT_LIST_HEAD(&bridge->fdb_list);
865 	bridge->ifindex = br_netdev->ifindex;
866 	bridge->refcnt = 1;
867 	bridge->ageing_time = clock_t_to_jiffies(BR_DEFAULT_AGEING_TIME);
868 	bridge->vlan_proto = ETH_P_8021Q;
869 	list_add(&bridge->list, &br_offloads->bridges);
870 	mlx5_esw_bridge_debugfs_init(br_netdev, bridge);
871 
872 	return bridge;
873 
874 err_mdb_ht:
875 	rhashtable_destroy(&bridge->fdb_ht);
876 err_fdb_ht:
877 	mlx5_esw_bridge_egress_table_cleanup(bridge);
878 err_egress_tbl:
879 	kvfree(bridge);
880 	return ERR_PTR(err);
881 }
882 
mlx5_esw_bridge_get(struct mlx5_esw_bridge * bridge)883 static void mlx5_esw_bridge_get(struct mlx5_esw_bridge *bridge)
884 {
885 	bridge->refcnt++;
886 }
887 
mlx5_esw_bridge_put(struct mlx5_esw_bridge_offloads * br_offloads,struct mlx5_esw_bridge * bridge)888 static void mlx5_esw_bridge_put(struct mlx5_esw_bridge_offloads *br_offloads,
889 				struct mlx5_esw_bridge *bridge)
890 {
891 	if (--bridge->refcnt)
892 		return;
893 
894 	mlx5_esw_bridge_debugfs_cleanup(bridge);
895 	mlx5_esw_bridge_egress_table_cleanup(bridge);
896 	mlx5_esw_bridge_mcast_disable(bridge);
897 	list_del(&bridge->list);
898 	mlx5_esw_bridge_mdb_cleanup(bridge);
899 	rhashtable_destroy(&bridge->fdb_ht);
900 	kvfree(bridge);
901 
902 	if (list_empty(&br_offloads->bridges))
903 		mlx5_esw_bridge_ingress_table_cleanup(br_offloads);
904 }
905 
906 static struct mlx5_esw_bridge *
mlx5_esw_bridge_lookup(struct net_device * br_netdev,struct mlx5_esw_bridge_offloads * br_offloads)907 mlx5_esw_bridge_lookup(struct net_device *br_netdev, struct mlx5_esw_bridge_offloads *br_offloads)
908 {
909 	struct mlx5_esw_bridge *bridge;
910 
911 	ASSERT_RTNL();
912 
913 	list_for_each_entry(bridge, &br_offloads->bridges, list) {
914 		if (bridge->ifindex == br_netdev->ifindex) {
915 			mlx5_esw_bridge_get(bridge);
916 			return bridge;
917 		}
918 	}
919 
920 	if (!br_offloads->ingress_ft) {
921 		int err = mlx5_esw_bridge_ingress_table_init(br_offloads);
922 
923 		if (err)
924 			return ERR_PTR(err);
925 	}
926 
927 	bridge = mlx5_esw_bridge_create(br_netdev, br_offloads);
928 	if (IS_ERR(bridge) && list_empty(&br_offloads->bridges))
929 		mlx5_esw_bridge_ingress_table_cleanup(br_offloads);
930 	return bridge;
931 }
932 
mlx5_esw_bridge_port_key_from_data(u16 vport_num,u16 esw_owner_vhca_id)933 static unsigned long mlx5_esw_bridge_port_key_from_data(u16 vport_num, u16 esw_owner_vhca_id)
934 {
935 	return vport_num | (unsigned long)esw_owner_vhca_id << sizeof(vport_num) * BITS_PER_BYTE;
936 }
937 
mlx5_esw_bridge_port_key(struct mlx5_esw_bridge_port * port)938 unsigned long mlx5_esw_bridge_port_key(struct mlx5_esw_bridge_port *port)
939 {
940 	return mlx5_esw_bridge_port_key_from_data(port->vport_num, port->esw_owner_vhca_id);
941 }
942 
mlx5_esw_bridge_port_insert(struct mlx5_esw_bridge_port * port,struct mlx5_esw_bridge_offloads * br_offloads)943 static int mlx5_esw_bridge_port_insert(struct mlx5_esw_bridge_port *port,
944 				       struct mlx5_esw_bridge_offloads *br_offloads)
945 {
946 	return xa_insert(&br_offloads->ports, mlx5_esw_bridge_port_key(port), port, GFP_KERNEL);
947 }
948 
949 static struct mlx5_esw_bridge_port *
mlx5_esw_bridge_port_lookup(u16 vport_num,u16 esw_owner_vhca_id,struct mlx5_esw_bridge_offloads * br_offloads)950 mlx5_esw_bridge_port_lookup(u16 vport_num, u16 esw_owner_vhca_id,
951 			    struct mlx5_esw_bridge_offloads *br_offloads)
952 {
953 	return xa_load(&br_offloads->ports, mlx5_esw_bridge_port_key_from_data(vport_num,
954 									       esw_owner_vhca_id));
955 }
956 
mlx5_esw_bridge_port_erase(struct mlx5_esw_bridge_port * port,struct mlx5_esw_bridge_offloads * br_offloads)957 static void mlx5_esw_bridge_port_erase(struct mlx5_esw_bridge_port *port,
958 				       struct mlx5_esw_bridge_offloads *br_offloads)
959 {
960 	xa_erase(&br_offloads->ports, mlx5_esw_bridge_port_key(port));
961 }
962 
963 static struct mlx5_esw_bridge *
mlx5_esw_bridge_from_port_lookup(u16 vport_num,u16 esw_owner_vhca_id,struct mlx5_esw_bridge_offloads * br_offloads)964 mlx5_esw_bridge_from_port_lookup(u16 vport_num, u16 esw_owner_vhca_id,
965 				 struct mlx5_esw_bridge_offloads *br_offloads)
966 {
967 	struct mlx5_esw_bridge_port *port;
968 
969 	port = mlx5_esw_bridge_port_lookup(vport_num, esw_owner_vhca_id, br_offloads);
970 	if (!port)
971 		return NULL;
972 
973 	return port->bridge;
974 }
975 
mlx5_esw_bridge_fdb_entry_refresh(struct mlx5_esw_bridge_fdb_entry * entry)976 static void mlx5_esw_bridge_fdb_entry_refresh(struct mlx5_esw_bridge_fdb_entry *entry)
977 {
978 	trace_mlx5_esw_bridge_fdb_entry_refresh(entry);
979 
980 	mlx5_esw_bridge_fdb_offload_notify(entry->dev, entry->key.addr,
981 					   entry->key.vid,
982 					   SWITCHDEV_FDB_ADD_TO_BRIDGE);
983 }
984 
985 static void
mlx5_esw_bridge_fdb_entry_cleanup(struct mlx5_esw_bridge_fdb_entry * entry,struct mlx5_esw_bridge * bridge)986 mlx5_esw_bridge_fdb_entry_cleanup(struct mlx5_esw_bridge_fdb_entry *entry,
987 				  struct mlx5_esw_bridge *bridge)
988 {
989 	trace_mlx5_esw_bridge_fdb_entry_cleanup(entry);
990 
991 	rhashtable_remove_fast(&bridge->fdb_ht, &entry->ht_node, fdb_ht_params);
992 	mlx5_del_flow_rules(entry->egress_handle);
993 	if (entry->filter_handle)
994 		mlx5_del_flow_rules(entry->filter_handle);
995 	mlx5_del_flow_rules(entry->ingress_handle);
996 	mlx5_fc_destroy(bridge->br_offloads->esw->dev, entry->ingress_counter);
997 	list_del(&entry->vlan_list);
998 	list_del(&entry->list);
999 	kvfree(entry);
1000 }
1001 
1002 static void
mlx5_esw_bridge_fdb_entry_notify_and_cleanup(struct mlx5_esw_bridge_fdb_entry * entry,struct mlx5_esw_bridge * bridge)1003 mlx5_esw_bridge_fdb_entry_notify_and_cleanup(struct mlx5_esw_bridge_fdb_entry *entry,
1004 					     struct mlx5_esw_bridge *bridge)
1005 {
1006 	mlx5_esw_bridge_fdb_del_notify(entry);
1007 	mlx5_esw_bridge_fdb_entry_cleanup(entry, bridge);
1008 }
1009 
mlx5_esw_bridge_fdb_flush(struct mlx5_esw_bridge * bridge)1010 static void mlx5_esw_bridge_fdb_flush(struct mlx5_esw_bridge *bridge)
1011 {
1012 	struct mlx5_esw_bridge_fdb_entry *entry, *tmp;
1013 
1014 	list_for_each_entry_safe(entry, tmp, &bridge->fdb_list, list)
1015 		mlx5_esw_bridge_fdb_entry_notify_and_cleanup(entry, bridge);
1016 }
1017 
1018 static struct mlx5_esw_bridge_vlan *
mlx5_esw_bridge_vlan_lookup(u16 vid,struct mlx5_esw_bridge_port * port)1019 mlx5_esw_bridge_vlan_lookup(u16 vid, struct mlx5_esw_bridge_port *port)
1020 {
1021 	return xa_load(&port->vlans, vid);
1022 }
1023 
1024 static int
mlx5_esw_bridge_vlan_push_create(u16 vlan_proto,struct mlx5_esw_bridge_vlan * vlan,struct mlx5_eswitch * esw)1025 mlx5_esw_bridge_vlan_push_create(u16 vlan_proto, struct mlx5_esw_bridge_vlan *vlan,
1026 				 struct mlx5_eswitch *esw)
1027 {
1028 	struct {
1029 		__be16	h_vlan_proto;
1030 		__be16	h_vlan_TCI;
1031 	} vlan_hdr = { htons(vlan_proto), htons(vlan->vid) };
1032 	struct mlx5_pkt_reformat_params reformat_params = {};
1033 	struct mlx5_pkt_reformat *pkt_reformat;
1034 
1035 	if (!BIT(MLX5_CAP_ESW_FLOWTABLE_FDB(esw->dev, reformat_insert)) ||
1036 	    MLX5_CAP_GEN_2(esw->dev, max_reformat_insert_size) < sizeof(vlan_hdr) ||
1037 	    MLX5_CAP_GEN_2(esw->dev, max_reformat_insert_offset) <
1038 	    offsetof(struct vlan_ethhdr, h_vlan_proto)) {
1039 		esw_warn(esw->dev, "Packet reformat INSERT_HEADER is not supported\n");
1040 		return -EOPNOTSUPP;
1041 	}
1042 
1043 	reformat_params.type = MLX5_REFORMAT_TYPE_INSERT_HDR;
1044 	reformat_params.param_0 = MLX5_REFORMAT_CONTEXT_ANCHOR_MAC_START;
1045 	reformat_params.param_1 = offsetof(struct vlan_ethhdr, h_vlan_proto);
1046 	reformat_params.size = sizeof(vlan_hdr);
1047 	reformat_params.data = &vlan_hdr;
1048 	pkt_reformat = mlx5_packet_reformat_alloc(esw->dev,
1049 						  &reformat_params,
1050 						  MLX5_FLOW_NAMESPACE_FDB);
1051 	if (IS_ERR(pkt_reformat)) {
1052 		esw_warn(esw->dev, "Failed to alloc packet reformat INSERT_HEADER (err=%pe)\n",
1053 			 pkt_reformat);
1054 		return PTR_ERR(pkt_reformat);
1055 	}
1056 
1057 	vlan->pkt_reformat_push = pkt_reformat;
1058 	return 0;
1059 }
1060 
1061 static void
mlx5_esw_bridge_vlan_push_cleanup(struct mlx5_esw_bridge_vlan * vlan,struct mlx5_eswitch * esw)1062 mlx5_esw_bridge_vlan_push_cleanup(struct mlx5_esw_bridge_vlan *vlan, struct mlx5_eswitch *esw)
1063 {
1064 	mlx5_packet_reformat_dealloc(esw->dev, vlan->pkt_reformat_push);
1065 	vlan->pkt_reformat_push = NULL;
1066 }
1067 
1068 static int
mlx5_esw_bridge_vlan_pop_create(struct mlx5_esw_bridge_vlan * vlan,struct mlx5_eswitch * esw)1069 mlx5_esw_bridge_vlan_pop_create(struct mlx5_esw_bridge_vlan *vlan, struct mlx5_eswitch *esw)
1070 {
1071 	struct mlx5_pkt_reformat *pkt_reformat;
1072 
1073 	if (!mlx5_esw_bridge_pkt_reformat_vlan_pop_supported(esw)) {
1074 		esw_warn(esw->dev, "Packet reformat REMOVE_HEADER is not supported\n");
1075 		return -EOPNOTSUPP;
1076 	}
1077 
1078 	pkt_reformat = mlx5_esw_bridge_pkt_reformat_vlan_pop_create(esw);
1079 	if (IS_ERR(pkt_reformat)) {
1080 		esw_warn(esw->dev, "Failed to alloc packet reformat REMOVE_HEADER (err=%pe)\n",
1081 			 pkt_reformat);
1082 		return PTR_ERR(pkt_reformat);
1083 	}
1084 
1085 	vlan->pkt_reformat_pop = pkt_reformat;
1086 	return 0;
1087 }
1088 
1089 static void
mlx5_esw_bridge_vlan_pop_cleanup(struct mlx5_esw_bridge_vlan * vlan,struct mlx5_eswitch * esw)1090 mlx5_esw_bridge_vlan_pop_cleanup(struct mlx5_esw_bridge_vlan *vlan, struct mlx5_eswitch *esw)
1091 {
1092 	mlx5_packet_reformat_dealloc(esw->dev, vlan->pkt_reformat_pop);
1093 	vlan->pkt_reformat_pop = NULL;
1094 }
1095 
1096 static int
mlx5_esw_bridge_vlan_push_mark_create(struct mlx5_esw_bridge_vlan * vlan,struct mlx5_eswitch * esw)1097 mlx5_esw_bridge_vlan_push_mark_create(struct mlx5_esw_bridge_vlan *vlan, struct mlx5_eswitch *esw)
1098 {
1099 	u8 action[MLX5_UN_SZ_BYTES(set_add_copy_action_in_auto)] = {};
1100 	struct mlx5_modify_hdr *pkt_mod_hdr;
1101 
1102 	MLX5_SET(set_action_in, action, action_type, MLX5_ACTION_TYPE_SET);
1103 	MLX5_SET(set_action_in, action, field, MLX5_ACTION_IN_FIELD_METADATA_REG_C_1);
1104 	MLX5_SET(set_action_in, action, offset, 8);
1105 	MLX5_SET(set_action_in, action, length, ESW_TUN_OPTS_BITS + ESW_TUN_ID_BITS);
1106 	MLX5_SET(set_action_in, action, data, ESW_TUN_BRIDGE_INGRESS_PUSH_VLAN);
1107 
1108 	pkt_mod_hdr = mlx5_modify_header_alloc(esw->dev, MLX5_FLOW_NAMESPACE_FDB, 1, action);
1109 	if (IS_ERR(pkt_mod_hdr))
1110 		return PTR_ERR(pkt_mod_hdr);
1111 
1112 	vlan->pkt_mod_hdr_push_mark = pkt_mod_hdr;
1113 	return 0;
1114 }
1115 
1116 static void
mlx5_esw_bridge_vlan_push_mark_cleanup(struct mlx5_esw_bridge_vlan * vlan,struct mlx5_eswitch * esw)1117 mlx5_esw_bridge_vlan_push_mark_cleanup(struct mlx5_esw_bridge_vlan *vlan, struct mlx5_eswitch *esw)
1118 {
1119 	mlx5_modify_header_dealloc(esw->dev, vlan->pkt_mod_hdr_push_mark);
1120 	vlan->pkt_mod_hdr_push_mark = NULL;
1121 }
1122 
1123 static int
mlx5_esw_bridge_vlan_push_pop_fhs_create(u16 vlan_proto,struct mlx5_esw_bridge_port * port,struct mlx5_esw_bridge_vlan * vlan)1124 mlx5_esw_bridge_vlan_push_pop_fhs_create(u16 vlan_proto, struct mlx5_esw_bridge_port *port,
1125 					 struct mlx5_esw_bridge_vlan *vlan)
1126 {
1127 	return mlx5_esw_bridge_vlan_mcast_init(vlan_proto, port, vlan);
1128 }
1129 
1130 static void
mlx5_esw_bridge_vlan_push_pop_fhs_cleanup(struct mlx5_esw_bridge_vlan * vlan)1131 mlx5_esw_bridge_vlan_push_pop_fhs_cleanup(struct mlx5_esw_bridge_vlan *vlan)
1132 {
1133 	mlx5_esw_bridge_vlan_mcast_cleanup(vlan);
1134 }
1135 
1136 static int
mlx5_esw_bridge_vlan_push_pop_create(u16 vlan_proto,u16 flags,struct mlx5_esw_bridge_port * port,struct mlx5_esw_bridge_vlan * vlan,struct mlx5_eswitch * esw)1137 mlx5_esw_bridge_vlan_push_pop_create(u16 vlan_proto, u16 flags, struct mlx5_esw_bridge_port *port,
1138 				     struct mlx5_esw_bridge_vlan *vlan, struct mlx5_eswitch *esw)
1139 {
1140 	int err;
1141 
1142 	if (flags & BRIDGE_VLAN_INFO_PVID) {
1143 		err = mlx5_esw_bridge_vlan_push_create(vlan_proto, vlan, esw);
1144 		if (err)
1145 			return err;
1146 
1147 		err = mlx5_esw_bridge_vlan_push_mark_create(vlan, esw);
1148 		if (err)
1149 			goto err_vlan_push_mark;
1150 	}
1151 
1152 	if (flags & BRIDGE_VLAN_INFO_UNTAGGED) {
1153 		err = mlx5_esw_bridge_vlan_pop_create(vlan, esw);
1154 		if (err)
1155 			goto err_vlan_pop;
1156 
1157 		err = mlx5_esw_bridge_vlan_push_pop_fhs_create(vlan_proto, port, vlan);
1158 		if (err)
1159 			goto err_vlan_pop_fhs;
1160 	}
1161 
1162 	return 0;
1163 
1164 err_vlan_pop_fhs:
1165 	mlx5_esw_bridge_vlan_pop_cleanup(vlan, esw);
1166 err_vlan_pop:
1167 	if (vlan->pkt_mod_hdr_push_mark)
1168 		mlx5_esw_bridge_vlan_push_mark_cleanup(vlan, esw);
1169 err_vlan_push_mark:
1170 	if (vlan->pkt_reformat_push)
1171 		mlx5_esw_bridge_vlan_push_cleanup(vlan, esw);
1172 	return err;
1173 }
1174 
1175 static struct mlx5_esw_bridge_vlan *
mlx5_esw_bridge_vlan_create(u16 vlan_proto,u16 vid,u16 flags,struct mlx5_esw_bridge_port * port,struct mlx5_eswitch * esw)1176 mlx5_esw_bridge_vlan_create(u16 vlan_proto, u16 vid, u16 flags, struct mlx5_esw_bridge_port *port,
1177 			    struct mlx5_eswitch *esw)
1178 {
1179 	struct mlx5_esw_bridge_vlan *vlan;
1180 	int err;
1181 
1182 	vlan = kvzalloc_obj(*vlan);
1183 	if (!vlan)
1184 		return ERR_PTR(-ENOMEM);
1185 
1186 	vlan->vid = vid;
1187 	vlan->flags = flags;
1188 	INIT_LIST_HEAD(&vlan->fdb_list);
1189 
1190 	err = mlx5_esw_bridge_vlan_push_pop_create(vlan_proto, flags, port, vlan, esw);
1191 	if (err)
1192 		goto err_vlan_push_pop;
1193 
1194 	err = xa_insert(&port->vlans, vid, vlan, GFP_KERNEL);
1195 	if (err)
1196 		goto err_xa_insert;
1197 
1198 	trace_mlx5_esw_bridge_vlan_create(vlan);
1199 	return vlan;
1200 
1201 err_xa_insert:
1202 	if (vlan->mcast_handle)
1203 		mlx5_esw_bridge_vlan_push_pop_fhs_cleanup(vlan);
1204 	if (vlan->pkt_reformat_pop)
1205 		mlx5_esw_bridge_vlan_pop_cleanup(vlan, esw);
1206 	if (vlan->pkt_mod_hdr_push_mark)
1207 		mlx5_esw_bridge_vlan_push_mark_cleanup(vlan, esw);
1208 	if (vlan->pkt_reformat_push)
1209 		mlx5_esw_bridge_vlan_push_cleanup(vlan, esw);
1210 err_vlan_push_pop:
1211 	kvfree(vlan);
1212 	return ERR_PTR(err);
1213 }
1214 
mlx5_esw_bridge_vlan_erase(struct mlx5_esw_bridge_port * port,struct mlx5_esw_bridge_vlan * vlan)1215 static void mlx5_esw_bridge_vlan_erase(struct mlx5_esw_bridge_port *port,
1216 				       struct mlx5_esw_bridge_vlan *vlan)
1217 {
1218 	xa_erase(&port->vlans, vlan->vid);
1219 }
1220 
mlx5_esw_bridge_vlan_flush(struct mlx5_esw_bridge_port * port,struct mlx5_esw_bridge_vlan * vlan,struct mlx5_esw_bridge * bridge)1221 static void mlx5_esw_bridge_vlan_flush(struct mlx5_esw_bridge_port *port,
1222 				       struct mlx5_esw_bridge_vlan *vlan,
1223 				       struct mlx5_esw_bridge *bridge)
1224 {
1225 	struct mlx5_eswitch *esw = bridge->br_offloads->esw;
1226 	struct mlx5_esw_bridge_fdb_entry *entry, *tmp;
1227 
1228 	list_for_each_entry_safe(entry, tmp, &vlan->fdb_list, vlan_list)
1229 		mlx5_esw_bridge_fdb_entry_notify_and_cleanup(entry, bridge);
1230 	mlx5_esw_bridge_port_mdb_vlan_flush(port, vlan);
1231 
1232 	if (vlan->mcast_handle)
1233 		mlx5_esw_bridge_vlan_push_pop_fhs_cleanup(vlan);
1234 	if (vlan->pkt_reformat_pop)
1235 		mlx5_esw_bridge_vlan_pop_cleanup(vlan, esw);
1236 	if (vlan->pkt_mod_hdr_push_mark)
1237 		mlx5_esw_bridge_vlan_push_mark_cleanup(vlan, esw);
1238 	if (vlan->pkt_reformat_push)
1239 		mlx5_esw_bridge_vlan_push_cleanup(vlan, esw);
1240 }
1241 
mlx5_esw_bridge_vlan_cleanup(struct mlx5_esw_bridge_port * port,struct mlx5_esw_bridge_vlan * vlan,struct mlx5_esw_bridge * bridge)1242 static void mlx5_esw_bridge_vlan_cleanup(struct mlx5_esw_bridge_port *port,
1243 					 struct mlx5_esw_bridge_vlan *vlan,
1244 					 struct mlx5_esw_bridge *bridge)
1245 {
1246 	trace_mlx5_esw_bridge_vlan_cleanup(vlan);
1247 	mlx5_esw_bridge_vlan_flush(port, vlan, bridge);
1248 	mlx5_esw_bridge_vlan_erase(port, vlan);
1249 	kvfree(vlan);
1250 }
1251 
mlx5_esw_bridge_port_vlans_flush(struct mlx5_esw_bridge_port * port,struct mlx5_esw_bridge * bridge)1252 static void mlx5_esw_bridge_port_vlans_flush(struct mlx5_esw_bridge_port *port,
1253 					     struct mlx5_esw_bridge *bridge)
1254 {
1255 	struct mlx5_esw_bridge_vlan *vlan;
1256 	unsigned long index;
1257 
1258 	xa_for_each(&port->vlans, index, vlan)
1259 		mlx5_esw_bridge_vlan_cleanup(port, vlan, bridge);
1260 }
1261 
mlx5_esw_bridge_port_vlans_recreate(struct mlx5_esw_bridge_port * port,struct mlx5_esw_bridge * bridge)1262 static int mlx5_esw_bridge_port_vlans_recreate(struct mlx5_esw_bridge_port *port,
1263 					       struct mlx5_esw_bridge *bridge)
1264 {
1265 	struct mlx5_esw_bridge_offloads *br_offloads = bridge->br_offloads;
1266 	struct mlx5_esw_bridge_vlan *vlan;
1267 	unsigned long i;
1268 	int err;
1269 
1270 	xa_for_each(&port->vlans, i, vlan) {
1271 		mlx5_esw_bridge_vlan_flush(port, vlan, bridge);
1272 		err = mlx5_esw_bridge_vlan_push_pop_create(bridge->vlan_proto, vlan->flags, port,
1273 							   vlan, br_offloads->esw);
1274 		if (err) {
1275 			esw_warn(br_offloads->esw->dev,
1276 				 "Failed to create VLAN=%u(proto=%x) push/pop actions (vport=%u,err=%d)\n",
1277 				 vlan->vid, bridge->vlan_proto, port->vport_num,
1278 				 err);
1279 			return err;
1280 		}
1281 	}
1282 
1283 	return 0;
1284 }
1285 
1286 static int
mlx5_esw_bridge_vlans_recreate(struct mlx5_esw_bridge * bridge)1287 mlx5_esw_bridge_vlans_recreate(struct mlx5_esw_bridge *bridge)
1288 {
1289 	struct mlx5_esw_bridge_offloads *br_offloads = bridge->br_offloads;
1290 	struct mlx5_esw_bridge_port *port;
1291 	unsigned long i;
1292 	int err;
1293 
1294 	xa_for_each(&br_offloads->ports, i, port) {
1295 		if (port->bridge != bridge)
1296 			continue;
1297 
1298 		err = mlx5_esw_bridge_port_vlans_recreate(port, bridge);
1299 		if (err)
1300 			return err;
1301 	}
1302 
1303 	return 0;
1304 }
1305 
1306 static struct mlx5_esw_bridge_vlan *
mlx5_esw_bridge_port_vlan_lookup(u16 vid,u16 vport_num,u16 esw_owner_vhca_id,struct mlx5_esw_bridge * bridge,struct mlx5_eswitch * esw)1307 mlx5_esw_bridge_port_vlan_lookup(u16 vid, u16 vport_num, u16 esw_owner_vhca_id,
1308 				 struct mlx5_esw_bridge *bridge, struct mlx5_eswitch *esw)
1309 {
1310 	struct mlx5_esw_bridge_port *port;
1311 	struct mlx5_esw_bridge_vlan *vlan;
1312 
1313 	port = mlx5_esw_bridge_port_lookup(vport_num, esw_owner_vhca_id, bridge->br_offloads);
1314 	if (!port) {
1315 		/* FDB is added asynchronously on wq while port might have been deleted
1316 		 * concurrently. Report on 'info' logging level and skip the FDB offload.
1317 		 */
1318 		esw_info(esw->dev, "Failed to lookup bridge port (vport=%u)\n", vport_num);
1319 		return ERR_PTR(-EINVAL);
1320 	}
1321 
1322 	vlan = mlx5_esw_bridge_vlan_lookup(vid, port);
1323 	if (!vlan) {
1324 		/* FDB is added asynchronously on wq while vlan might have been deleted
1325 		 * concurrently. Report on 'info' logging level and skip the FDB offload.
1326 		 */
1327 		esw_info(esw->dev, "Failed to lookup bridge port vlan metadata (vport=%u)\n",
1328 			 vport_num);
1329 		return ERR_PTR(-EINVAL);
1330 	}
1331 
1332 	return vlan;
1333 }
1334 
1335 static struct mlx5_esw_bridge_fdb_entry *
mlx5_esw_bridge_fdb_lookup(struct mlx5_esw_bridge * bridge,const unsigned char * addr,u16 vid)1336 mlx5_esw_bridge_fdb_lookup(struct mlx5_esw_bridge *bridge,
1337 			   const unsigned char *addr, u16 vid)
1338 {
1339 	struct mlx5_esw_bridge_fdb_key key = {};
1340 
1341 	ether_addr_copy(key.addr, addr);
1342 	key.vid = vid;
1343 	return rhashtable_lookup_fast(&bridge->fdb_ht, &key, fdb_ht_params);
1344 }
1345 
1346 static struct mlx5_esw_bridge_fdb_entry *
mlx5_esw_bridge_fdb_entry_init(struct net_device * dev,u16 vport_num,u16 esw_owner_vhca_id,const unsigned char * addr,u16 vid,bool added_by_user,bool peer,struct mlx5_eswitch * esw,struct mlx5_esw_bridge * bridge)1347 mlx5_esw_bridge_fdb_entry_init(struct net_device *dev, u16 vport_num, u16 esw_owner_vhca_id,
1348 			       const unsigned char *addr, u16 vid, bool added_by_user, bool peer,
1349 			       struct mlx5_eswitch *esw, struct mlx5_esw_bridge *bridge)
1350 {
1351 	struct mlx5_esw_bridge_vlan *vlan = NULL;
1352 	struct mlx5_esw_bridge_fdb_entry *entry;
1353 	struct mlx5_flow_handle *handle;
1354 	struct mlx5_fc *counter;
1355 	int err;
1356 
1357 	if (bridge->flags & MLX5_ESW_BRIDGE_VLAN_FILTERING_FLAG && vid) {
1358 		vlan = mlx5_esw_bridge_port_vlan_lookup(vid, vport_num, esw_owner_vhca_id, bridge,
1359 							esw);
1360 		if (IS_ERR(vlan))
1361 			return ERR_CAST(vlan);
1362 	}
1363 
1364 	entry = mlx5_esw_bridge_fdb_lookup(bridge, addr, vid);
1365 	if (entry)
1366 		mlx5_esw_bridge_fdb_entry_notify_and_cleanup(entry, bridge);
1367 
1368 	entry = kvzalloc_obj(*entry);
1369 	if (!entry)
1370 		return ERR_PTR(-ENOMEM);
1371 
1372 	ether_addr_copy(entry->key.addr, addr);
1373 	entry->key.vid = vid;
1374 	entry->dev = dev;
1375 	entry->vport_num = vport_num;
1376 	entry->esw_owner_vhca_id = esw_owner_vhca_id;
1377 	entry->lastuse = jiffies;
1378 	if (added_by_user)
1379 		entry->flags |= MLX5_ESW_BRIDGE_FLAG_ADDED_BY_USER;
1380 	if (peer)
1381 		entry->flags |= MLX5_ESW_BRIDGE_FLAG_PEER;
1382 
1383 	counter = mlx5_fc_create(esw->dev, true);
1384 	if (IS_ERR(counter)) {
1385 		err = PTR_ERR(counter);
1386 		goto err_ingress_fc_create;
1387 	}
1388 	entry->ingress_counter = counter;
1389 
1390 	handle = peer ?
1391 		mlx5_esw_bridge_ingress_flow_peer_create(vport_num, esw_owner_vhca_id,
1392 							 addr, vlan, counter, bridge) :
1393 		mlx5_esw_bridge_ingress_flow_create(vport_num, addr, vlan,
1394 						    counter, bridge);
1395 	if (IS_ERR(handle)) {
1396 		err = PTR_ERR(handle);
1397 		esw_warn(esw->dev, "Failed to create ingress flow(vport=%u,err=%d,peer=%d)\n",
1398 			 vport_num, err, peer);
1399 		goto err_ingress_flow_create;
1400 	}
1401 	entry->ingress_handle = handle;
1402 
1403 	if (bridge->flags & MLX5_ESW_BRIDGE_VLAN_FILTERING_FLAG) {
1404 		handle = mlx5_esw_bridge_ingress_filter_flow_create(vport_num, addr, bridge);
1405 		if (IS_ERR(handle)) {
1406 			err = PTR_ERR(handle);
1407 			esw_warn(esw->dev, "Failed to create ingress filter(vport=%u,err=%d)\n",
1408 				 vport_num, err);
1409 			goto err_ingress_filter_flow_create;
1410 		}
1411 		entry->filter_handle = handle;
1412 	}
1413 
1414 	handle = mlx5_esw_bridge_egress_flow_create(vport_num, esw_owner_vhca_id, addr, vlan,
1415 						    bridge);
1416 	if (IS_ERR(handle)) {
1417 		err = PTR_ERR(handle);
1418 		esw_warn(esw->dev, "Failed to create egress flow(vport=%u,err=%d)\n",
1419 			 vport_num, err);
1420 		goto err_egress_flow_create;
1421 	}
1422 	entry->egress_handle = handle;
1423 
1424 	err = rhashtable_insert_fast(&bridge->fdb_ht, &entry->ht_node, fdb_ht_params);
1425 	if (err) {
1426 		esw_warn(esw->dev, "Failed to insert FDB flow(vport=%u,err=%d)\n", vport_num, err);
1427 		goto err_ht_init;
1428 	}
1429 
1430 	if (vlan)
1431 		list_add(&entry->vlan_list, &vlan->fdb_list);
1432 	else
1433 		INIT_LIST_HEAD(&entry->vlan_list);
1434 	list_add(&entry->list, &bridge->fdb_list);
1435 
1436 	trace_mlx5_esw_bridge_fdb_entry_init(entry);
1437 	return entry;
1438 
1439 err_ht_init:
1440 	mlx5_del_flow_rules(entry->egress_handle);
1441 err_egress_flow_create:
1442 	if (entry->filter_handle)
1443 		mlx5_del_flow_rules(entry->filter_handle);
1444 err_ingress_filter_flow_create:
1445 	mlx5_del_flow_rules(entry->ingress_handle);
1446 err_ingress_flow_create:
1447 	mlx5_fc_destroy(esw->dev, entry->ingress_counter);
1448 err_ingress_fc_create:
1449 	kvfree(entry);
1450 	return ERR_PTR(err);
1451 }
1452 
mlx5_esw_bridge_ageing_time_set(u16 vport_num,u16 esw_owner_vhca_id,unsigned long ageing_time,struct mlx5_esw_bridge_offloads * br_offloads)1453 int mlx5_esw_bridge_ageing_time_set(u16 vport_num, u16 esw_owner_vhca_id, unsigned long ageing_time,
1454 				    struct mlx5_esw_bridge_offloads *br_offloads)
1455 {
1456 	struct mlx5_esw_bridge *bridge;
1457 
1458 	bridge = mlx5_esw_bridge_from_port_lookup(vport_num, esw_owner_vhca_id, br_offloads);
1459 	if (!bridge)
1460 		return -EINVAL;
1461 
1462 	bridge->ageing_time = clock_t_to_jiffies(ageing_time);
1463 	return 0;
1464 }
1465 
mlx5_esw_bridge_vlan_filtering_set(u16 vport_num,u16 esw_owner_vhca_id,bool enable,struct mlx5_esw_bridge_offloads * br_offloads)1466 int mlx5_esw_bridge_vlan_filtering_set(u16 vport_num, u16 esw_owner_vhca_id, bool enable,
1467 				       struct mlx5_esw_bridge_offloads *br_offloads)
1468 {
1469 	struct mlx5_esw_bridge *bridge;
1470 	bool filtering;
1471 
1472 	bridge = mlx5_esw_bridge_from_port_lookup(vport_num, esw_owner_vhca_id, br_offloads);
1473 	if (!bridge)
1474 		return -EINVAL;
1475 
1476 	filtering = bridge->flags & MLX5_ESW_BRIDGE_VLAN_FILTERING_FLAG;
1477 	if (filtering == enable)
1478 		return 0;
1479 
1480 	mlx5_esw_bridge_fdb_flush(bridge);
1481 	mlx5_esw_bridge_mdb_flush(bridge);
1482 	if (enable)
1483 		bridge->flags |= MLX5_ESW_BRIDGE_VLAN_FILTERING_FLAG;
1484 	else
1485 		bridge->flags &= ~MLX5_ESW_BRIDGE_VLAN_FILTERING_FLAG;
1486 
1487 	return 0;
1488 }
1489 
mlx5_esw_bridge_vlan_proto_set(u16 vport_num,u16 esw_owner_vhca_id,u16 proto,struct mlx5_esw_bridge_offloads * br_offloads)1490 int mlx5_esw_bridge_vlan_proto_set(u16 vport_num, u16 esw_owner_vhca_id, u16 proto,
1491 				   struct mlx5_esw_bridge_offloads *br_offloads)
1492 {
1493 	struct mlx5_esw_bridge *bridge;
1494 
1495 	bridge = mlx5_esw_bridge_from_port_lookup(vport_num, esw_owner_vhca_id,
1496 						  br_offloads);
1497 	if (!bridge)
1498 		return -EINVAL;
1499 
1500 	if (bridge->vlan_proto == proto)
1501 		return 0;
1502 	if (proto != ETH_P_8021Q && proto != ETH_P_8021AD) {
1503 		esw_warn(br_offloads->esw->dev, "Can't set unsupported VLAN protocol %x", proto);
1504 		return -EOPNOTSUPP;
1505 	}
1506 
1507 	mlx5_esw_bridge_fdb_flush(bridge);
1508 	mlx5_esw_bridge_mdb_flush(bridge);
1509 	bridge->vlan_proto = proto;
1510 	mlx5_esw_bridge_vlans_recreate(bridge);
1511 
1512 	return 0;
1513 }
1514 
mlx5_esw_bridge_mcast_set(u16 vport_num,u16 esw_owner_vhca_id,bool enable,struct mlx5_esw_bridge_offloads * br_offloads)1515 int mlx5_esw_bridge_mcast_set(u16 vport_num, u16 esw_owner_vhca_id, bool enable,
1516 			      struct mlx5_esw_bridge_offloads *br_offloads)
1517 {
1518 	struct mlx5_eswitch *esw = br_offloads->esw;
1519 	struct mlx5_esw_bridge *bridge;
1520 	int err = 0;
1521 	bool mcast;
1522 
1523 	if (!(MLX5_CAP_ESW_FLOWTABLE((esw)->dev, fdb_multi_path_any_table) ||
1524 	      MLX5_CAP_ESW_FLOWTABLE((esw)->dev, fdb_multi_path_any_table_limit_regc)) ||
1525 	    !MLX5_CAP_ESW_FLOWTABLE((esw)->dev, fdb_uplink_hairpin) ||
1526 	    !MLX5_CAP_ESW_FLOWTABLE_FDB((esw)->dev, ignore_flow_level))
1527 		return -EOPNOTSUPP;
1528 
1529 	bridge = mlx5_esw_bridge_from_port_lookup(vport_num, esw_owner_vhca_id, br_offloads);
1530 	if (!bridge)
1531 		return -EINVAL;
1532 
1533 	mcast = bridge->flags & MLX5_ESW_BRIDGE_MCAST_FLAG;
1534 	if (mcast == enable)
1535 		return 0;
1536 
1537 	if (enable)
1538 		err = mlx5_esw_bridge_mcast_enable(bridge);
1539 	else
1540 		mlx5_esw_bridge_mcast_disable(bridge);
1541 
1542 	return err;
1543 }
1544 
mlx5_esw_bridge_vport_init(u16 vport_num,u16 esw_owner_vhca_id,u16 flags,struct mlx5_esw_bridge_offloads * br_offloads,struct mlx5_esw_bridge * bridge)1545 static int mlx5_esw_bridge_vport_init(u16 vport_num, u16 esw_owner_vhca_id, u16 flags,
1546 				      struct mlx5_esw_bridge_offloads *br_offloads,
1547 				      struct mlx5_esw_bridge *bridge)
1548 {
1549 	struct mlx5_eswitch *esw = br_offloads->esw;
1550 	struct mlx5_esw_bridge_port *port;
1551 	int err;
1552 
1553 	port = kvzalloc_obj(*port);
1554 	if (!port)
1555 		return -ENOMEM;
1556 
1557 	port->vport_num = vport_num;
1558 	port->esw_owner_vhca_id = esw_owner_vhca_id;
1559 	port->bridge = bridge;
1560 	port->flags |= flags;
1561 	xa_init(&port->vlans);
1562 
1563 	err = mlx5_esw_bridge_port_mcast_init(port);
1564 	if (err) {
1565 		esw_warn(esw->dev,
1566 			 "Failed to initialize port multicast (vport=%u,esw_owner_vhca_id=%u,err=%d)\n",
1567 			 port->vport_num, port->esw_owner_vhca_id, err);
1568 		goto err_port_mcast;
1569 	}
1570 
1571 	err = mlx5_esw_bridge_port_insert(port, br_offloads);
1572 	if (err) {
1573 		esw_warn(esw->dev,
1574 			 "Failed to insert port metadata (vport=%u,esw_owner_vhca_id=%u,err=%d)\n",
1575 			 port->vport_num, port->esw_owner_vhca_id, err);
1576 		goto err_port_insert;
1577 	}
1578 	trace_mlx5_esw_bridge_vport_init(port);
1579 
1580 	return 0;
1581 
1582 err_port_insert:
1583 	mlx5_esw_bridge_port_mcast_cleanup(port);
1584 err_port_mcast:
1585 	kvfree(port);
1586 	return err;
1587 }
1588 
mlx5_esw_bridge_vport_cleanup(struct mlx5_esw_bridge_offloads * br_offloads,struct mlx5_esw_bridge_port * port)1589 static int mlx5_esw_bridge_vport_cleanup(struct mlx5_esw_bridge_offloads *br_offloads,
1590 					 struct mlx5_esw_bridge_port *port)
1591 {
1592 	u16 vport_num = port->vport_num, esw_owner_vhca_id = port->esw_owner_vhca_id;
1593 	struct mlx5_esw_bridge *bridge = port->bridge;
1594 	struct mlx5_esw_bridge_fdb_entry *entry, *tmp;
1595 
1596 	list_for_each_entry_safe(entry, tmp, &bridge->fdb_list, list)
1597 		if (entry->vport_num == vport_num && entry->esw_owner_vhca_id == esw_owner_vhca_id)
1598 			mlx5_esw_bridge_fdb_entry_cleanup(entry, bridge);
1599 
1600 	trace_mlx5_esw_bridge_vport_cleanup(port);
1601 	mlx5_esw_bridge_port_vlans_flush(port, bridge);
1602 	mlx5_esw_bridge_port_mcast_cleanup(port);
1603 	mlx5_esw_bridge_port_erase(port, br_offloads);
1604 	kvfree(port);
1605 	mlx5_esw_bridge_put(br_offloads, bridge);
1606 	return 0;
1607 }
1608 
mlx5_esw_bridge_vport_link_with_flags(struct net_device * br_netdev,u16 vport_num,u16 esw_owner_vhca_id,u16 flags,struct mlx5_esw_bridge_offloads * br_offloads,struct netlink_ext_ack * extack)1609 static int mlx5_esw_bridge_vport_link_with_flags(struct net_device *br_netdev, u16 vport_num,
1610 						 u16 esw_owner_vhca_id, u16 flags,
1611 						 struct mlx5_esw_bridge_offloads *br_offloads,
1612 						 struct netlink_ext_ack *extack)
1613 {
1614 	struct mlx5_esw_bridge *bridge;
1615 	int err;
1616 
1617 	bridge = mlx5_esw_bridge_lookup(br_netdev, br_offloads);
1618 	if (IS_ERR(bridge)) {
1619 		NL_SET_ERR_MSG_MOD(extack, "Error checking for existing bridge with same ifindex");
1620 		return PTR_ERR(bridge);
1621 	}
1622 
1623 	err = mlx5_esw_bridge_vport_init(vport_num, esw_owner_vhca_id, flags, br_offloads, bridge);
1624 	if (err) {
1625 		NL_SET_ERR_MSG_MOD(extack, "Error initializing port");
1626 		goto err_vport;
1627 	}
1628 	return 0;
1629 
1630 err_vport:
1631 	mlx5_esw_bridge_put(br_offloads, bridge);
1632 	return err;
1633 }
1634 
mlx5_esw_bridge_vport_link(struct net_device * br_netdev,u16 vport_num,u16 esw_owner_vhca_id,struct mlx5_esw_bridge_offloads * br_offloads,struct netlink_ext_ack * extack)1635 int mlx5_esw_bridge_vport_link(struct net_device *br_netdev, u16 vport_num, u16 esw_owner_vhca_id,
1636 			       struct mlx5_esw_bridge_offloads *br_offloads,
1637 			       struct netlink_ext_ack *extack)
1638 {
1639 	return mlx5_esw_bridge_vport_link_with_flags(br_netdev, vport_num, esw_owner_vhca_id, 0,
1640 						     br_offloads, extack);
1641 }
1642 
mlx5_esw_bridge_vport_unlink(struct net_device * br_netdev,u16 vport_num,u16 esw_owner_vhca_id,struct mlx5_esw_bridge_offloads * br_offloads,struct netlink_ext_ack * extack)1643 int mlx5_esw_bridge_vport_unlink(struct net_device *br_netdev, u16 vport_num,
1644 				 u16 esw_owner_vhca_id,
1645 				 struct mlx5_esw_bridge_offloads *br_offloads,
1646 				 struct netlink_ext_ack *extack)
1647 {
1648 	struct mlx5_esw_bridge_port *port;
1649 	int err;
1650 
1651 	port = mlx5_esw_bridge_port_lookup(vport_num, esw_owner_vhca_id, br_offloads);
1652 	if (!port) {
1653 		NL_SET_ERR_MSG_MOD(extack, "Port is not attached to any bridge");
1654 		return -EINVAL;
1655 	}
1656 	if (port->bridge->ifindex != br_netdev->ifindex) {
1657 		NL_SET_ERR_MSG_MOD(extack, "Port is attached to another bridge");
1658 		return -EINVAL;
1659 	}
1660 
1661 	err = mlx5_esw_bridge_vport_cleanup(br_offloads, port);
1662 	if (err)
1663 		NL_SET_ERR_MSG_MOD(extack, "Port cleanup failed");
1664 	return err;
1665 }
1666 
mlx5_esw_bridge_vport_peer_link(struct net_device * br_netdev,u16 vport_num,u16 esw_owner_vhca_id,struct mlx5_esw_bridge_offloads * br_offloads,struct netlink_ext_ack * extack)1667 int mlx5_esw_bridge_vport_peer_link(struct net_device *br_netdev, u16 vport_num,
1668 				    u16 esw_owner_vhca_id,
1669 				    struct mlx5_esw_bridge_offloads *br_offloads,
1670 				    struct netlink_ext_ack *extack)
1671 {
1672 	if (!MLX5_CAP_ESW(br_offloads->esw->dev, merged_eswitch))
1673 		return 0;
1674 
1675 	return mlx5_esw_bridge_vport_link_with_flags(br_netdev, vport_num, esw_owner_vhca_id,
1676 						     MLX5_ESW_BRIDGE_PORT_FLAG_PEER,
1677 						     br_offloads, extack);
1678 }
1679 
mlx5_esw_bridge_vport_peer_unlink(struct net_device * br_netdev,u16 vport_num,u16 esw_owner_vhca_id,struct mlx5_esw_bridge_offloads * br_offloads,struct netlink_ext_ack * extack)1680 int mlx5_esw_bridge_vport_peer_unlink(struct net_device *br_netdev, u16 vport_num,
1681 				      u16 esw_owner_vhca_id,
1682 				      struct mlx5_esw_bridge_offloads *br_offloads,
1683 				      struct netlink_ext_ack *extack)
1684 {
1685 	return mlx5_esw_bridge_vport_unlink(br_netdev, vport_num, esw_owner_vhca_id, br_offloads,
1686 					    extack);
1687 }
1688 
mlx5_esw_bridge_port_vlan_add(u16 vport_num,u16 esw_owner_vhca_id,u16 vid,u16 flags,struct mlx5_esw_bridge_offloads * br_offloads,struct netlink_ext_ack * extack)1689 int mlx5_esw_bridge_port_vlan_add(u16 vport_num, u16 esw_owner_vhca_id, u16 vid, u16 flags,
1690 				  struct mlx5_esw_bridge_offloads *br_offloads,
1691 				  struct netlink_ext_ack *extack)
1692 {
1693 	struct mlx5_esw_bridge_port *port;
1694 	struct mlx5_esw_bridge_vlan *vlan;
1695 
1696 	port = mlx5_esw_bridge_port_lookup(vport_num, esw_owner_vhca_id, br_offloads);
1697 	if (!port)
1698 		return -EINVAL;
1699 
1700 	vlan = mlx5_esw_bridge_vlan_lookup(vid, port);
1701 	if (vlan) {
1702 		if (vlan->flags == flags)
1703 			return 0;
1704 		mlx5_esw_bridge_vlan_cleanup(port, vlan, port->bridge);
1705 	}
1706 
1707 	vlan = mlx5_esw_bridge_vlan_create(port->bridge->vlan_proto, vid, flags, port,
1708 					   br_offloads->esw);
1709 	if (IS_ERR(vlan)) {
1710 		NL_SET_ERR_MSG_MOD(extack, "Failed to create VLAN entry");
1711 		return PTR_ERR(vlan);
1712 	}
1713 	return 0;
1714 }
1715 
mlx5_esw_bridge_port_vlan_del(u16 vport_num,u16 esw_owner_vhca_id,u16 vid,struct mlx5_esw_bridge_offloads * br_offloads)1716 void mlx5_esw_bridge_port_vlan_del(u16 vport_num, u16 esw_owner_vhca_id, u16 vid,
1717 				   struct mlx5_esw_bridge_offloads *br_offloads)
1718 {
1719 	struct mlx5_esw_bridge_port *port;
1720 	struct mlx5_esw_bridge_vlan *vlan;
1721 
1722 	port = mlx5_esw_bridge_port_lookup(vport_num, esw_owner_vhca_id, br_offloads);
1723 	if (!port)
1724 		return;
1725 
1726 	vlan = mlx5_esw_bridge_vlan_lookup(vid, port);
1727 	if (!vlan)
1728 		return;
1729 	mlx5_esw_bridge_vlan_cleanup(port, vlan, port->bridge);
1730 }
1731 
mlx5_esw_bridge_fdb_update_used(struct net_device * dev,u16 vport_num,u16 esw_owner_vhca_id,struct mlx5_esw_bridge_offloads * br_offloads,struct switchdev_notifier_fdb_info * fdb_info)1732 void mlx5_esw_bridge_fdb_update_used(struct net_device *dev, u16 vport_num, u16 esw_owner_vhca_id,
1733 				     struct mlx5_esw_bridge_offloads *br_offloads,
1734 				     struct switchdev_notifier_fdb_info *fdb_info)
1735 {
1736 	struct mlx5_esw_bridge_fdb_entry *entry;
1737 	struct mlx5_esw_bridge *bridge;
1738 
1739 	bridge = mlx5_esw_bridge_from_port_lookup(vport_num, esw_owner_vhca_id, br_offloads);
1740 	if (!bridge)
1741 		return;
1742 
1743 	entry = mlx5_esw_bridge_fdb_lookup(bridge, fdb_info->addr, fdb_info->vid);
1744 	if (!entry) {
1745 		esw_debug(br_offloads->esw->dev,
1746 			  "FDB update entry with specified key not found (MAC=%pM,vid=%u,vport=%u)\n",
1747 			  fdb_info->addr, fdb_info->vid, vport_num);
1748 		return;
1749 	}
1750 
1751 	entry->lastuse = jiffies;
1752 }
1753 
mlx5_esw_bridge_fdb_mark_deleted(struct net_device * dev,u16 vport_num,u16 esw_owner_vhca_id,struct mlx5_esw_bridge_offloads * br_offloads,struct switchdev_notifier_fdb_info * fdb_info)1754 void mlx5_esw_bridge_fdb_mark_deleted(struct net_device *dev, u16 vport_num, u16 esw_owner_vhca_id,
1755 				      struct mlx5_esw_bridge_offloads *br_offloads,
1756 				      struct switchdev_notifier_fdb_info *fdb_info)
1757 {
1758 	struct mlx5_esw_bridge_fdb_entry *entry;
1759 	struct mlx5_esw_bridge *bridge;
1760 
1761 	bridge = mlx5_esw_bridge_from_port_lookup(vport_num, esw_owner_vhca_id, br_offloads);
1762 	if (!bridge)
1763 		return;
1764 
1765 	entry = mlx5_esw_bridge_fdb_lookup(bridge, fdb_info->addr, fdb_info->vid);
1766 	if (!entry) {
1767 		esw_debug(br_offloads->esw->dev,
1768 			  "FDB mark deleted entry with specified key not found (MAC=%pM,vid=%u,vport=%u)\n",
1769 			  fdb_info->addr, fdb_info->vid, vport_num);
1770 		return;
1771 	}
1772 
1773 	entry->flags |= MLX5_ESW_BRIDGE_FLAG_DELETED;
1774 }
1775 
mlx5_esw_bridge_fdb_create(struct net_device * dev,u16 vport_num,u16 esw_owner_vhca_id,struct mlx5_esw_bridge_offloads * br_offloads,struct switchdev_notifier_fdb_info * fdb_info)1776 void mlx5_esw_bridge_fdb_create(struct net_device *dev, u16 vport_num, u16 esw_owner_vhca_id,
1777 				struct mlx5_esw_bridge_offloads *br_offloads,
1778 				struct switchdev_notifier_fdb_info *fdb_info)
1779 {
1780 	struct mlx5_esw_bridge_fdb_entry *entry;
1781 	struct mlx5_esw_bridge_port *port;
1782 	struct mlx5_esw_bridge *bridge;
1783 
1784 	port = mlx5_esw_bridge_port_lookup(vport_num, esw_owner_vhca_id, br_offloads);
1785 	if (!port)
1786 		return;
1787 
1788 	bridge = port->bridge;
1789 	entry = mlx5_esw_bridge_fdb_entry_init(dev, vport_num, esw_owner_vhca_id, fdb_info->addr,
1790 					       fdb_info->vid, fdb_info->added_by_user,
1791 					       port->flags & MLX5_ESW_BRIDGE_PORT_FLAG_PEER,
1792 					       br_offloads->esw, bridge);
1793 	if (IS_ERR(entry))
1794 		return;
1795 
1796 	if (entry->flags & MLX5_ESW_BRIDGE_FLAG_ADDED_BY_USER)
1797 		mlx5_esw_bridge_fdb_offload_notify(dev, entry->key.addr, entry->key.vid,
1798 						   SWITCHDEV_FDB_OFFLOADED);
1799 	else if (!(entry->flags & MLX5_ESW_BRIDGE_FLAG_PEER))
1800 		/* Take over dynamic entries to prevent kernel bridge from aging them out. */
1801 		mlx5_esw_bridge_fdb_offload_notify(dev, entry->key.addr, entry->key.vid,
1802 						   SWITCHDEV_FDB_ADD_TO_BRIDGE);
1803 }
1804 
mlx5_esw_bridge_fdb_remove(struct net_device * dev,u16 vport_num,u16 esw_owner_vhca_id,struct mlx5_esw_bridge_offloads * br_offloads,struct switchdev_notifier_fdb_info * fdb_info)1805 void mlx5_esw_bridge_fdb_remove(struct net_device *dev, u16 vport_num, u16 esw_owner_vhca_id,
1806 				struct mlx5_esw_bridge_offloads *br_offloads,
1807 				struct switchdev_notifier_fdb_info *fdb_info)
1808 {
1809 	struct mlx5_eswitch *esw = br_offloads->esw;
1810 	struct mlx5_esw_bridge_fdb_entry *entry;
1811 	struct mlx5_esw_bridge *bridge;
1812 
1813 	bridge = mlx5_esw_bridge_from_port_lookup(vport_num, esw_owner_vhca_id, br_offloads);
1814 	if (!bridge)
1815 		return;
1816 
1817 	entry = mlx5_esw_bridge_fdb_lookup(bridge, fdb_info->addr, fdb_info->vid);
1818 	if (!entry) {
1819 		esw_debug(esw->dev,
1820 			  "FDB remove entry with specified key not found (MAC=%pM,vid=%u,vport=%u)\n",
1821 			  fdb_info->addr, fdb_info->vid, vport_num);
1822 		return;
1823 	}
1824 
1825 	mlx5_esw_bridge_fdb_entry_notify_and_cleanup(entry, bridge);
1826 }
1827 
mlx5_esw_bridge_update(struct mlx5_esw_bridge_offloads * br_offloads)1828 void mlx5_esw_bridge_update(struct mlx5_esw_bridge_offloads *br_offloads)
1829 {
1830 	struct mlx5_esw_bridge_fdb_entry *entry, *tmp;
1831 	struct mlx5_esw_bridge *bridge;
1832 
1833 	list_for_each_entry(bridge, &br_offloads->bridges, list) {
1834 		list_for_each_entry_safe(entry, tmp, &bridge->fdb_list, list) {
1835 			unsigned long lastuse =
1836 				(unsigned long)mlx5_fc_query_lastuse(entry->ingress_counter);
1837 
1838 			if (entry->flags & (MLX5_ESW_BRIDGE_FLAG_ADDED_BY_USER |
1839 					    MLX5_ESW_BRIDGE_FLAG_DELETED))
1840 				continue;
1841 
1842 			if (time_after(lastuse, entry->lastuse))
1843 				mlx5_esw_bridge_fdb_entry_refresh(entry);
1844 			else if (!(entry->flags & MLX5_ESW_BRIDGE_FLAG_PEER) &&
1845 				 time_is_before_jiffies(entry->lastuse + bridge->ageing_time))
1846 				mlx5_esw_bridge_fdb_entry_notify_and_cleanup(entry, bridge);
1847 		}
1848 	}
1849 }
1850 
mlx5_esw_bridge_port_mdb_add(struct net_device * dev,u16 vport_num,u16 esw_owner_vhca_id,const unsigned char * addr,u16 vid,struct mlx5_esw_bridge_offloads * br_offloads,struct netlink_ext_ack * extack)1851 int mlx5_esw_bridge_port_mdb_add(struct net_device *dev, u16 vport_num, u16 esw_owner_vhca_id,
1852 				 const unsigned char *addr, u16 vid,
1853 				 struct mlx5_esw_bridge_offloads *br_offloads,
1854 				 struct netlink_ext_ack *extack)
1855 {
1856 	struct mlx5_esw_bridge_vlan *vlan;
1857 	struct mlx5_esw_bridge_port *port;
1858 	struct mlx5_esw_bridge *bridge;
1859 	int err;
1860 
1861 	port = mlx5_esw_bridge_port_lookup(vport_num, esw_owner_vhca_id, br_offloads);
1862 	if (!port) {
1863 		esw_warn(br_offloads->esw->dev,
1864 			 "Failed to lookup bridge port to add MDB (MAC=%pM,vport=%u)\n",
1865 			 addr, vport_num);
1866 		NL_SET_ERR_MSG_FMT_MOD(extack,
1867 				       "Failed to lookup bridge port to add MDB (MAC=%pM,vport=%u)",
1868 				       addr, vport_num);
1869 		return -EINVAL;
1870 	}
1871 
1872 	bridge = port->bridge;
1873 	if (bridge->flags & MLX5_ESW_BRIDGE_VLAN_FILTERING_FLAG && vid) {
1874 		vlan = mlx5_esw_bridge_vlan_lookup(vid, port);
1875 		if (!vlan) {
1876 			esw_warn(br_offloads->esw->dev,
1877 				 "Failed to lookup bridge port vlan metadata to create MDB (MAC=%pM,vid=%u,vport=%u)\n",
1878 				 addr, vid, vport_num);
1879 			NL_SET_ERR_MSG_FMT_MOD(extack,
1880 					       "Failed to lookup vlan metadata for MDB (MAC=%pM,vid=%u,vport=%u)",
1881 					       addr, vid, vport_num);
1882 			return -EINVAL;
1883 		}
1884 	}
1885 
1886 	err = mlx5_esw_bridge_port_mdb_attach(dev, port, addr, vid);
1887 	if (err) {
1888 		NL_SET_ERR_MSG_FMT_MOD(extack, "Failed to add MDB (MAC=%pM,vid=%u,vport=%u)",
1889 				       addr, vid, vport_num);
1890 		return err;
1891 	}
1892 
1893 	return 0;
1894 }
1895 
mlx5_esw_bridge_port_mdb_del(struct net_device * dev,u16 vport_num,u16 esw_owner_vhca_id,const unsigned char * addr,u16 vid,struct mlx5_esw_bridge_offloads * br_offloads)1896 void mlx5_esw_bridge_port_mdb_del(struct net_device *dev, u16 vport_num, u16 esw_owner_vhca_id,
1897 				  const unsigned char *addr, u16 vid,
1898 				  struct mlx5_esw_bridge_offloads *br_offloads)
1899 {
1900 	struct mlx5_esw_bridge_port *port;
1901 
1902 	port = mlx5_esw_bridge_port_lookup(vport_num, esw_owner_vhca_id, br_offloads);
1903 	if (!port)
1904 		return;
1905 
1906 	mlx5_esw_bridge_port_mdb_detach(dev, port, addr, vid);
1907 }
1908 
mlx5_esw_bridge_flush(struct mlx5_esw_bridge_offloads * br_offloads)1909 static void mlx5_esw_bridge_flush(struct mlx5_esw_bridge_offloads *br_offloads)
1910 {
1911 	struct mlx5_esw_bridge_port *port;
1912 	unsigned long i;
1913 
1914 	xa_for_each(&br_offloads->ports, i, port)
1915 		mlx5_esw_bridge_vport_cleanup(br_offloads, port);
1916 
1917 	WARN_ONCE(!list_empty(&br_offloads->bridges),
1918 		  "Cleaning up bridge offloads while still having bridges attached\n");
1919 }
1920 
mlx5_esw_bridge_init(struct mlx5_eswitch * esw)1921 struct mlx5_esw_bridge_offloads *mlx5_esw_bridge_init(struct mlx5_eswitch *esw)
1922 {
1923 	struct mlx5_esw_bridge_offloads *br_offloads;
1924 
1925 	ASSERT_RTNL();
1926 
1927 	br_offloads = kvzalloc_obj(*br_offloads);
1928 	if (!br_offloads)
1929 		return ERR_PTR(-ENOMEM);
1930 
1931 	INIT_LIST_HEAD(&br_offloads->bridges);
1932 	xa_init(&br_offloads->ports);
1933 	br_offloads->esw = esw;
1934 	esw->br_offloads = br_offloads;
1935 	mlx5_esw_bridge_debugfs_offloads_init(br_offloads);
1936 
1937 	return br_offloads;
1938 }
1939 
mlx5_esw_bridge_cleanup(struct mlx5_eswitch * esw)1940 void mlx5_esw_bridge_cleanup(struct mlx5_eswitch *esw)
1941 {
1942 	struct mlx5_esw_bridge_offloads *br_offloads = esw->br_offloads;
1943 
1944 	ASSERT_RTNL();
1945 
1946 	if (!br_offloads)
1947 		return;
1948 
1949 	mlx5_esw_bridge_flush(br_offloads);
1950 	WARN_ON(!xa_empty(&br_offloads->ports));
1951 	mlx5_esw_bridge_debugfs_offloads_cleanup(br_offloads);
1952 
1953 	esw->br_offloads = NULL;
1954 	kvfree(br_offloads);
1955 }
1956