xref: /linux/drivers/net/ethernet/mscc/ocelot_flower.c (revision 621cde16e49b3ecf7d59a8106a20aaebfb4a59a9)
1 // SPDX-License-Identifier: (GPL-2.0 OR MIT)
2 /* Microsemi Ocelot Switch driver
3  * Copyright (c) 2019 Microsemi Corporation
4  */
5 
6 #include <net/pkt_cls.h>
7 #include <net/tc_act/tc_gact.h>
8 #include <soc/mscc/ocelot_vcap.h>
9 #include "ocelot_police.h"
10 #include "ocelot_vcap.h"
11 
12 /* Arbitrarily chosen constants for encoding the VCAP block and lookup number
13  * into the chain number. This is UAPI.
14  */
15 #define VCAP_BLOCK			10000
16 #define VCAP_LOOKUP			1000
17 #define VCAP_IS1_NUM_LOOKUPS		3
18 #define VCAP_IS2_NUM_LOOKUPS		2
19 #define VCAP_IS2_NUM_PAG		256
20 #define VCAP_IS1_CHAIN(lookup)		\
21 	(1 * VCAP_BLOCK + (lookup) * VCAP_LOOKUP)
22 #define VCAP_IS2_CHAIN(lookup, pag)	\
23 	(2 * VCAP_BLOCK + (lookup) * VCAP_LOOKUP + (pag))
24 /* PSFP chain and block ID */
25 #define PSFP_BLOCK_ID			OCELOT_NUM_VCAP_BLOCKS
26 #define OCELOT_PSFP_CHAIN		(3 * VCAP_BLOCK)
27 
ocelot_chain_to_block(int chain,bool ingress)28 static int ocelot_chain_to_block(int chain, bool ingress)
29 {
30 	int lookup, pag;
31 
32 	if (!ingress) {
33 		if (chain == 0)
34 			return VCAP_ES0;
35 		return -EOPNOTSUPP;
36 	}
37 
38 	/* Backwards compatibility with older, single-chain tc-flower
39 	 * offload support in Ocelot
40 	 */
41 	if (chain == 0)
42 		return VCAP_IS2;
43 
44 	for (lookup = 0; lookup < VCAP_IS1_NUM_LOOKUPS; lookup++)
45 		if (chain == VCAP_IS1_CHAIN(lookup))
46 			return VCAP_IS1;
47 
48 	for (lookup = 0; lookup < VCAP_IS2_NUM_LOOKUPS; lookup++)
49 		for (pag = 0; pag < VCAP_IS2_NUM_PAG; pag++)
50 			if (chain == VCAP_IS2_CHAIN(lookup, pag))
51 				return VCAP_IS2;
52 
53 	if (chain == OCELOT_PSFP_CHAIN)
54 		return PSFP_BLOCK_ID;
55 
56 	return -EOPNOTSUPP;
57 }
58 
59 /* Caller must ensure this is a valid IS1 or IS2 chain first,
60  * by calling ocelot_chain_to_block.
61  */
ocelot_chain_to_lookup(int chain)62 static int ocelot_chain_to_lookup(int chain)
63 {
64 	/* Backwards compatibility with older, single-chain tc-flower
65 	 * offload support in Ocelot
66 	 */
67 	if (chain == 0)
68 		return 0;
69 
70 	return (chain / VCAP_LOOKUP) % 10;
71 }
72 
73 /* Caller must ensure this is a valid IS2 chain first,
74  * by calling ocelot_chain_to_block.
75  */
ocelot_chain_to_pag(int chain)76 static int ocelot_chain_to_pag(int chain)
77 {
78 	int lookup;
79 
80 	/* Backwards compatibility with older, single-chain tc-flower
81 	 * offload support in Ocelot
82 	 */
83 	if (chain == 0)
84 		return 0;
85 
86 	lookup = ocelot_chain_to_lookup(chain);
87 
88 	/* calculate PAG value as chain index relative to the first PAG */
89 	return chain - VCAP_IS2_CHAIN(lookup, 0);
90 }
91 
ocelot_is_goto_target_valid(int goto_target,int chain,bool ingress)92 static bool ocelot_is_goto_target_valid(int goto_target, int chain,
93 					bool ingress)
94 {
95 	int pag;
96 
97 	/* Can't offload GOTO in VCAP ES0 */
98 	if (!ingress)
99 		return (goto_target < 0);
100 
101 	/* Non-optional GOTOs */
102 	if (chain == 0)
103 		/* VCAP IS1 can be skipped, either partially or completely */
104 		return (goto_target == VCAP_IS1_CHAIN(0) ||
105 			goto_target == VCAP_IS1_CHAIN(1) ||
106 			goto_target == VCAP_IS1_CHAIN(2) ||
107 			goto_target == VCAP_IS2_CHAIN(0, 0) ||
108 			goto_target == VCAP_IS2_CHAIN(1, 0) ||
109 			goto_target == OCELOT_PSFP_CHAIN);
110 
111 	if (chain == VCAP_IS1_CHAIN(0))
112 		return (goto_target == VCAP_IS1_CHAIN(1));
113 
114 	if (chain == VCAP_IS1_CHAIN(1))
115 		return (goto_target == VCAP_IS1_CHAIN(2));
116 
117 	/* Lookup 2 of VCAP IS1 can really support non-optional GOTOs,
118 	 * using a Policy Association Group (PAG) value, which is an 8-bit
119 	 * value encoding a VCAP IS2 target chain.
120 	 */
121 	if (chain == VCAP_IS1_CHAIN(2)) {
122 		for (pag = 0; pag < VCAP_IS2_NUM_PAG; pag++)
123 			if (goto_target == VCAP_IS2_CHAIN(0, pag))
124 				return true;
125 
126 		return false;
127 	}
128 
129 	/* Non-optional GOTO from VCAP IS2 lookup 0 to lookup 1.
130 	 * We cannot change the PAG at this point.
131 	 */
132 	for (pag = 0; pag < VCAP_IS2_NUM_PAG; pag++)
133 		if (chain == VCAP_IS2_CHAIN(0, pag))
134 			return (goto_target == VCAP_IS2_CHAIN(1, pag));
135 
136 	/* VCAP IS2 lookup 1 can goto to PSFP block if hardware support */
137 	for (pag = 0; pag < VCAP_IS2_NUM_PAG; pag++)
138 		if (chain == VCAP_IS2_CHAIN(1, pag))
139 			return (goto_target == OCELOT_PSFP_CHAIN);
140 
141 	return false;
142 }
143 
144 static struct ocelot_vcap_filter *
ocelot_find_vcap_filter_that_points_at(struct ocelot * ocelot,int chain)145 ocelot_find_vcap_filter_that_points_at(struct ocelot *ocelot, int chain)
146 {
147 	struct ocelot_vcap_filter *filter;
148 	struct ocelot_vcap_block *block;
149 	int block_id;
150 
151 	block_id = ocelot_chain_to_block(chain, true);
152 	if (block_id < 0)
153 		return NULL;
154 
155 	if (block_id == VCAP_IS2) {
156 		block = &ocelot->block[VCAP_IS1];
157 
158 		list_for_each_entry(filter, &block->rules, list)
159 			if (filter->type == OCELOT_VCAP_FILTER_PAG &&
160 			    filter->goto_target == chain)
161 				return filter;
162 	}
163 
164 	list_for_each_entry(filter, &ocelot->dummy_rules, list)
165 		if (filter->goto_target == chain)
166 			return filter;
167 
168 	return NULL;
169 }
170 
171 static int
ocelot_flower_parse_ingress_vlan_modify(struct ocelot * ocelot,int port,struct ocelot_vcap_filter * filter,const struct flow_action_entry * a,struct netlink_ext_ack * extack)172 ocelot_flower_parse_ingress_vlan_modify(struct ocelot *ocelot, int port,
173 					struct ocelot_vcap_filter *filter,
174 					const struct flow_action_entry *a,
175 					struct netlink_ext_ack *extack)
176 {
177 	struct ocelot_port *ocelot_port = ocelot->ports[port];
178 
179 	if (filter->goto_target != -1) {
180 		NL_SET_ERR_MSG_MOD(extack,
181 				   "Last action must be GOTO");
182 		return -EOPNOTSUPP;
183 	}
184 
185 	if (!ocelot_port->vlan_aware) {
186 		NL_SET_ERR_MSG_MOD(extack,
187 				   "Can only modify VLAN under VLAN aware bridge");
188 		return -EOPNOTSUPP;
189 	}
190 
191 	filter->action.vid_replace_ena = true;
192 	filter->action.pcp_dei_ena = true;
193 	filter->action.vid = a->vlan.vid;
194 	filter->action.pcp = a->vlan.prio;
195 	filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
196 
197 	return 0;
198 }
199 
200 static int
ocelot_flower_parse_egress_vlan_modify(struct ocelot_vcap_filter * filter,const struct flow_action_entry * a,struct netlink_ext_ack * extack)201 ocelot_flower_parse_egress_vlan_modify(struct ocelot_vcap_filter *filter,
202 				       const struct flow_action_entry *a,
203 				       struct netlink_ext_ack *extack)
204 {
205 	enum ocelot_tag_tpid_sel tpid;
206 
207 	switch (ntohs(a->vlan.proto)) {
208 	case ETH_P_8021Q:
209 		tpid = OCELOT_TAG_TPID_SEL_8021Q;
210 		break;
211 	case ETH_P_8021AD:
212 		tpid = OCELOT_TAG_TPID_SEL_8021AD;
213 		break;
214 	default:
215 		NL_SET_ERR_MSG_MOD(extack,
216 				   "Cannot modify custom TPID");
217 		return -EOPNOTSUPP;
218 	}
219 
220 	filter->action.tag_a_tpid_sel = tpid;
221 	filter->action.push_outer_tag = OCELOT_ES0_TAG;
222 	filter->action.tag_a_vid_sel = OCELOT_ES0_VID_PLUS_CLASSIFIED_VID;
223 	filter->action.vid_a_val = a->vlan.vid;
224 	filter->action.pcp_a_val = a->vlan.prio;
225 	filter->action.tag_a_pcp_sel = OCELOT_ES0_PCP;
226 	filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
227 
228 	return 0;
229 }
230 
ocelot_flower_parse_action(struct ocelot * ocelot,int port,bool ingress,struct flow_cls_offload * f,struct ocelot_vcap_filter * filter)231 static int ocelot_flower_parse_action(struct ocelot *ocelot, int port,
232 				      bool ingress, struct flow_cls_offload *f,
233 				      struct ocelot_vcap_filter *filter)
234 {
235 	const struct flow_action *action = &f->rule->action;
236 	struct netlink_ext_ack *extack = f->common.extack;
237 	bool allow_missing_goto_target = false;
238 	const struct flow_action_entry *a;
239 	enum ocelot_tag_tpid_sel tpid;
240 	int i, chain, egress_port;
241 	u32 pol_ix, pol_max;
242 	u64 rate;
243 	int err;
244 
245 	if (!flow_action_basic_hw_stats_check(&f->rule->action,
246 					      f->common.extack))
247 		return -EOPNOTSUPP;
248 
249 	chain = f->common.chain_index;
250 	filter->block_id = ocelot_chain_to_block(chain, ingress);
251 	if (filter->block_id < 0) {
252 		NL_SET_ERR_MSG_MOD(extack, "Cannot offload to this chain");
253 		return -EOPNOTSUPP;
254 	}
255 	if (filter->block_id == VCAP_IS1 || filter->block_id == VCAP_IS2)
256 		filter->lookup = ocelot_chain_to_lookup(chain);
257 	if (filter->block_id == VCAP_IS2)
258 		filter->pag = ocelot_chain_to_pag(chain);
259 
260 	filter->goto_target = -1;
261 	filter->type = OCELOT_VCAP_FILTER_DUMMY;
262 
263 	flow_action_for_each(i, a, action) {
264 		switch (a->id) {
265 		case FLOW_ACTION_DROP:
266 			if (filter->block_id != VCAP_IS2) {
267 				NL_SET_ERR_MSG_MOD(extack,
268 						   "Drop action can only be offloaded to VCAP IS2");
269 				return -EOPNOTSUPP;
270 			}
271 			if (filter->goto_target != -1) {
272 				NL_SET_ERR_MSG_MOD(extack,
273 						   "Last action must be GOTO");
274 				return -EOPNOTSUPP;
275 			}
276 			filter->action.mask_mode = OCELOT_MASK_MODE_PERMIT_DENY;
277 			filter->action.port_mask = 0;
278 			filter->action.police_ena = true;
279 			filter->action.pol_ix = OCELOT_POLICER_DISCARD;
280 			filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
281 			break;
282 		case FLOW_ACTION_ACCEPT:
283 			if (filter->block_id != VCAP_ES0 &&
284 			    filter->block_id != VCAP_IS1 &&
285 			    filter->block_id != VCAP_IS2) {
286 				NL_SET_ERR_MSG_MOD(extack,
287 						   "Accept action can only be offloaded to VCAP chains");
288 				return -EOPNOTSUPP;
289 			}
290 			if (filter->block_id != VCAP_ES0 &&
291 			    filter->goto_target != -1) {
292 				NL_SET_ERR_MSG_MOD(extack,
293 						   "Last action must be GOTO");
294 				return -EOPNOTSUPP;
295 			}
296 			filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
297 			break;
298 		case FLOW_ACTION_TRAP:
299 			if (filter->block_id != VCAP_IS2 ||
300 			    filter->lookup != 0) {
301 				NL_SET_ERR_MSG_MOD(extack,
302 						   "Trap action can only be offloaded to VCAP IS2 lookup 0");
303 				return -EOPNOTSUPP;
304 			}
305 			if (filter->goto_target != -1) {
306 				NL_SET_ERR_MSG_MOD(extack,
307 						   "Last action must be GOTO");
308 				return -EOPNOTSUPP;
309 			}
310 			filter->action.mask_mode = OCELOT_MASK_MODE_PERMIT_DENY;
311 			filter->action.port_mask = 0;
312 			filter->action.cpu_copy_ena = true;
313 			filter->action.cpu_qu_num = 0;
314 			filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
315 			filter->is_trap = true;
316 			break;
317 		case FLOW_ACTION_POLICE:
318 			if (filter->block_id == PSFP_BLOCK_ID) {
319 				filter->type = OCELOT_PSFP_FILTER_OFFLOAD;
320 				break;
321 			}
322 			if (filter->block_id != VCAP_IS2 ||
323 			    filter->lookup != 0) {
324 				NL_SET_ERR_MSG_MOD(extack,
325 						   "Police action can only be offloaded to VCAP IS2 lookup 0 or PSFP");
326 				return -EOPNOTSUPP;
327 			}
328 			if (filter->goto_target != -1) {
329 				NL_SET_ERR_MSG_MOD(extack,
330 						   "Last action must be GOTO");
331 				return -EOPNOTSUPP;
332 			}
333 
334 			err = ocelot_policer_validate(action, a, extack);
335 			if (err)
336 				return err;
337 
338 			filter->action.police_ena = true;
339 
340 			pol_ix = a->hw_index + ocelot->vcap_pol.base;
341 			pol_max = ocelot->vcap_pol.max;
342 
343 			if (ocelot->vcap_pol.max2 && pol_ix > pol_max) {
344 				pol_ix += ocelot->vcap_pol.base2 - pol_max - 1;
345 				pol_max = ocelot->vcap_pol.max2;
346 			}
347 
348 			if (pol_ix >= pol_max)
349 				return -EINVAL;
350 
351 			filter->action.pol_ix = pol_ix;
352 
353 			rate = a->police.rate_bytes_ps;
354 			filter->action.pol.rate = div_u64(rate, 1000) * 8;
355 			filter->action.pol.burst = a->police.burst;
356 			filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
357 			break;
358 		case FLOW_ACTION_REDIRECT:
359 			if (filter->block_id != VCAP_IS2) {
360 				NL_SET_ERR_MSG_MOD(extack,
361 						   "Redirect action can only be offloaded to VCAP IS2");
362 				return -EOPNOTSUPP;
363 			}
364 			if (filter->goto_target != -1) {
365 				NL_SET_ERR_MSG_MOD(extack,
366 						   "Last action must be GOTO");
367 				return -EOPNOTSUPP;
368 			}
369 			egress_port = ocelot->ops->netdev_to_port(a->dev);
370 			if (egress_port < 0) {
371 				NL_SET_ERR_MSG_MOD(extack,
372 						   "Destination not an ocelot port");
373 				return -EOPNOTSUPP;
374 			}
375 			filter->action.mask_mode = OCELOT_MASK_MODE_REDIRECT;
376 			filter->action.port_mask = BIT(egress_port);
377 			filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
378 			break;
379 		case FLOW_ACTION_MIRRED:
380 			if (filter->block_id != VCAP_IS2) {
381 				NL_SET_ERR_MSG_MOD(extack,
382 						   "Mirror action can only be offloaded to VCAP IS2");
383 				return -EOPNOTSUPP;
384 			}
385 			if (filter->goto_target != -1) {
386 				NL_SET_ERR_MSG_MOD(extack,
387 						   "Last action must be GOTO");
388 				return -EOPNOTSUPP;
389 			}
390 			egress_port = ocelot->ops->netdev_to_port(a->dev);
391 			if (egress_port < 0) {
392 				NL_SET_ERR_MSG_MOD(extack,
393 						   "Destination not an ocelot port");
394 				return -EOPNOTSUPP;
395 			}
396 			filter->egress_port.value = egress_port;
397 			filter->action.mirror_ena = true;
398 			filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
399 			break;
400 		case FLOW_ACTION_VLAN_POP:
401 			if (filter->block_id != VCAP_IS1) {
402 				NL_SET_ERR_MSG_MOD(extack,
403 						   "VLAN pop action can only be offloaded to VCAP IS1");
404 				return -EOPNOTSUPP;
405 			}
406 			if (filter->goto_target != -1) {
407 				NL_SET_ERR_MSG_MOD(extack,
408 						   "Last action must be GOTO");
409 				return -EOPNOTSUPP;
410 			}
411 			filter->action.vlan_pop_cnt_ena = true;
412 			filter->action.vlan_pop_cnt++;
413 			if (filter->action.vlan_pop_cnt > 2) {
414 				NL_SET_ERR_MSG_MOD(extack,
415 						   "Cannot pop more than 2 VLAN headers");
416 				return -EOPNOTSUPP;
417 			}
418 			filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
419 			break;
420 		case FLOW_ACTION_VLAN_MANGLE:
421 			if (filter->block_id == VCAP_IS1) {
422 				err = ocelot_flower_parse_ingress_vlan_modify(ocelot, port,
423 									      filter, a,
424 									      extack);
425 			} else if (filter->block_id == VCAP_ES0) {
426 				err = ocelot_flower_parse_egress_vlan_modify(filter, a,
427 									     extack);
428 			} else {
429 				NL_SET_ERR_MSG_MOD(extack,
430 						   "VLAN modify action can only be offloaded to VCAP IS1 or ES0");
431 				err = -EOPNOTSUPP;
432 			}
433 			if (err)
434 				return err;
435 			break;
436 		case FLOW_ACTION_PRIORITY:
437 			if (filter->block_id != VCAP_IS1) {
438 				NL_SET_ERR_MSG_MOD(extack,
439 						   "Priority action can only be offloaded to VCAP IS1");
440 				return -EOPNOTSUPP;
441 			}
442 			if (filter->goto_target != -1) {
443 				NL_SET_ERR_MSG_MOD(extack,
444 						   "Last action must be GOTO");
445 				return -EOPNOTSUPP;
446 			}
447 			filter->action.qos_ena = true;
448 			filter->action.qos_val = a->priority;
449 			filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
450 			break;
451 		case FLOW_ACTION_GOTO:
452 			filter->goto_target = a->chain_index;
453 
454 			if (filter->block_id == VCAP_IS1 && filter->lookup == 2) {
455 				int pag = ocelot_chain_to_pag(filter->goto_target);
456 
457 				filter->action.pag_override_mask = 0xff;
458 				filter->action.pag_val = pag;
459 				filter->type = OCELOT_VCAP_FILTER_PAG;
460 			}
461 			break;
462 		case FLOW_ACTION_VLAN_PUSH:
463 			if (filter->block_id != VCAP_ES0) {
464 				NL_SET_ERR_MSG_MOD(extack,
465 						   "VLAN push action can only be offloaded to VCAP ES0");
466 				return -EOPNOTSUPP;
467 			}
468 			switch (ntohs(a->vlan.proto)) {
469 			case ETH_P_8021Q:
470 				tpid = OCELOT_TAG_TPID_SEL_8021Q;
471 				break;
472 			case ETH_P_8021AD:
473 				tpid = OCELOT_TAG_TPID_SEL_8021AD;
474 				break;
475 			default:
476 				NL_SET_ERR_MSG_MOD(extack,
477 						   "Cannot push custom TPID");
478 				return -EOPNOTSUPP;
479 			}
480 			filter->action.tag_a_tpid_sel = tpid;
481 			filter->action.push_outer_tag = OCELOT_ES0_TAG;
482 			filter->action.tag_a_vid_sel = OCELOT_ES0_VID;
483 			filter->action.vid_a_val = a->vlan.vid;
484 			filter->action.pcp_a_val = a->vlan.prio;
485 			filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
486 			break;
487 		case FLOW_ACTION_GATE:
488 			if (filter->block_id != PSFP_BLOCK_ID) {
489 				NL_SET_ERR_MSG_MOD(extack,
490 						   "Gate action can only be offloaded to PSFP chain");
491 				return -EOPNOTSUPP;
492 			}
493 			filter->type = OCELOT_PSFP_FILTER_OFFLOAD;
494 			break;
495 		default:
496 			NL_SET_ERR_MSG_MOD(extack, "Cannot offload action");
497 			return -EOPNOTSUPP;
498 		}
499 	}
500 
501 	if (filter->goto_target == -1) {
502 		if ((filter->block_id == VCAP_IS2 && filter->lookup == 1) ||
503 		    chain == 0 || filter->block_id == PSFP_BLOCK_ID) {
504 			allow_missing_goto_target = true;
505 		} else {
506 			NL_SET_ERR_MSG_MOD(extack, "Missing GOTO action");
507 			return -EOPNOTSUPP;
508 		}
509 	}
510 
511 	if (!ocelot_is_goto_target_valid(filter->goto_target, chain, ingress) &&
512 	    !allow_missing_goto_target) {
513 		NL_SET_ERR_MSG_MOD(extack, "Cannot offload this GOTO target");
514 		return -EOPNOTSUPP;
515 	}
516 
517 	return 0;
518 }
519 
ocelot_flower_parse_indev(struct ocelot * ocelot,int port,struct flow_cls_offload * f,struct ocelot_vcap_filter * filter)520 static int ocelot_flower_parse_indev(struct ocelot *ocelot, int port,
521 				     struct flow_cls_offload *f,
522 				     struct ocelot_vcap_filter *filter)
523 {
524 	struct flow_rule *rule = flow_cls_offload_flow_rule(f);
525 	const struct vcap_props *vcap = &ocelot->vcap[VCAP_ES0];
526 	int key_length = vcap->keys[VCAP_ES0_IGR_PORT].length;
527 	struct netlink_ext_ack *extack = f->common.extack;
528 	struct net_device *dev, *indev;
529 	struct flow_match_meta match;
530 	int ingress_port;
531 
532 	flow_rule_match_meta(rule, &match);
533 
534 	if (!match.mask->ingress_ifindex)
535 		return 0;
536 
537 	if (match.mask->ingress_ifindex != 0xFFFFFFFF) {
538 		NL_SET_ERR_MSG_MOD(extack, "Unsupported ingress ifindex mask");
539 		return -EOPNOTSUPP;
540 	}
541 
542 	dev = ocelot->ops->port_to_netdev(ocelot, port);
543 	if (!dev)
544 		return -EINVAL;
545 
546 	indev = __dev_get_by_index(dev_net(dev), match.key->ingress_ifindex);
547 	if (!indev) {
548 		NL_SET_ERR_MSG_MOD(extack,
549 				   "Can't find the ingress port to match on");
550 		return -ENOENT;
551 	}
552 
553 	ingress_port = ocelot->ops->netdev_to_port(indev);
554 	if (ingress_port < 0) {
555 		NL_SET_ERR_MSG_MOD(extack,
556 				   "Can only offload an ocelot ingress port");
557 		return -EOPNOTSUPP;
558 	}
559 	if (ingress_port == port) {
560 		NL_SET_ERR_MSG_MOD(extack,
561 				   "Ingress port is equal to the egress port");
562 		return -EINVAL;
563 	}
564 
565 	filter->ingress_port.value = ingress_port;
566 	filter->ingress_port.mask = GENMASK(key_length - 1, 0);
567 
568 	return 0;
569 }
570 
571 static int
ocelot_flower_parse_key(struct ocelot * ocelot,int port,bool ingress,struct flow_cls_offload * f,struct ocelot_vcap_filter * filter)572 ocelot_flower_parse_key(struct ocelot *ocelot, int port, bool ingress,
573 			struct flow_cls_offload *f,
574 			struct ocelot_vcap_filter *filter)
575 {
576 	struct flow_rule *rule = flow_cls_offload_flow_rule(f);
577 	struct flow_dissector *dissector = rule->match.dissector;
578 	struct netlink_ext_ack *extack = f->common.extack;
579 	u16 proto = ntohs(f->common.protocol);
580 	bool match_protocol = true;
581 	int ret;
582 
583 	if (dissector->used_keys &
584 	    ~(BIT_ULL(FLOW_DISSECTOR_KEY_CONTROL) |
585 	      BIT_ULL(FLOW_DISSECTOR_KEY_BASIC) |
586 	      BIT_ULL(FLOW_DISSECTOR_KEY_META) |
587 	      BIT_ULL(FLOW_DISSECTOR_KEY_PORTS) |
588 	      BIT_ULL(FLOW_DISSECTOR_KEY_VLAN) |
589 	      BIT_ULL(FLOW_DISSECTOR_KEY_IPV4_ADDRS) |
590 	      BIT_ULL(FLOW_DISSECTOR_KEY_IPV6_ADDRS) |
591 	      BIT_ULL(FLOW_DISSECTOR_KEY_ETH_ADDRS))) {
592 		return -EOPNOTSUPP;
593 	}
594 
595 	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_META)) {
596 		struct flow_match_meta match;
597 
598 		flow_rule_match_meta(rule, &match);
599 		if (match.mask->l2_miss) {
600 			NL_SET_ERR_MSG_MOD(extack, "Can't match on \"l2_miss\"");
601 			return -EOPNOTSUPP;
602 		}
603 	}
604 
605 	/* For VCAP ES0 (egress rewriter) we can match on the ingress port */
606 	if (!ingress) {
607 		ret = ocelot_flower_parse_indev(ocelot, port, f, filter);
608 		if (ret)
609 			return ret;
610 	}
611 
612 	if (flow_rule_match_has_control_flags(rule, extack))
613 		return -EOPNOTSUPP;
614 
615 	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_VLAN)) {
616 		struct flow_match_vlan match;
617 
618 		flow_rule_match_vlan(rule, &match);
619 		filter->key_type = OCELOT_VCAP_KEY_ANY;
620 		filter->vlan.vid.value = match.key->vlan_id;
621 		filter->vlan.vid.mask = match.mask->vlan_id;
622 		filter->vlan.pcp.value[0] = match.key->vlan_priority;
623 		filter->vlan.pcp.mask[0] = match.mask->vlan_priority;
624 		match_protocol = false;
625 	}
626 
627 	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ETH_ADDRS)) {
628 		struct flow_match_eth_addrs match;
629 
630 		if (filter->block_id == VCAP_ES0) {
631 			NL_SET_ERR_MSG_MOD(extack,
632 					   "VCAP ES0 cannot match on MAC address");
633 			return -EOPNOTSUPP;
634 		}
635 
636 		/* The hw support mac matches only for MAC_ETYPE key,
637 		 * therefore if other matches(port, tcp flags, etc) are added
638 		 * then just bail out
639 		 */
640 		if ((dissector->used_keys &
641 		    (BIT_ULL(FLOW_DISSECTOR_KEY_ETH_ADDRS) |
642 		     BIT_ULL(FLOW_DISSECTOR_KEY_BASIC) |
643 		     BIT_ULL(FLOW_DISSECTOR_KEY_CONTROL))) !=
644 		    (BIT_ULL(FLOW_DISSECTOR_KEY_ETH_ADDRS) |
645 		     BIT_ULL(FLOW_DISSECTOR_KEY_BASIC) |
646 		     BIT_ULL(FLOW_DISSECTOR_KEY_CONTROL)))
647 			return -EOPNOTSUPP;
648 
649 		flow_rule_match_eth_addrs(rule, &match);
650 
651 		if (filter->block_id == VCAP_IS1 &&
652 		    !is_zero_ether_addr(match.mask->dst)) {
653 			NL_SET_ERR_MSG_MOD(extack,
654 					   "Key type S1_NORMAL cannot match on destination MAC");
655 			return -EOPNOTSUPP;
656 		}
657 
658 		filter->key_type = OCELOT_VCAP_KEY_ETYPE;
659 		ether_addr_copy(filter->key.etype.dmac.value,
660 				match.key->dst);
661 		ether_addr_copy(filter->key.etype.smac.value,
662 				match.key->src);
663 		ether_addr_copy(filter->key.etype.dmac.mask,
664 				match.mask->dst);
665 		ether_addr_copy(filter->key.etype.smac.mask,
666 				match.mask->src);
667 		goto finished_key_parsing;
668 	}
669 
670 	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) {
671 		struct flow_match_basic match;
672 
673 		flow_rule_match_basic(rule, &match);
674 		if (ntohs(match.key->n_proto) == ETH_P_IP) {
675 			if (filter->block_id == VCAP_ES0) {
676 				NL_SET_ERR_MSG_MOD(extack,
677 						   "VCAP ES0 cannot match on IP protocol");
678 				return -EOPNOTSUPP;
679 			}
680 
681 			filter->key_type = OCELOT_VCAP_KEY_IPV4;
682 			filter->key.ipv4.proto.value[0] =
683 				match.key->ip_proto;
684 			filter->key.ipv4.proto.mask[0] =
685 				match.mask->ip_proto;
686 			match_protocol = false;
687 		}
688 		if (ntohs(match.key->n_proto) == ETH_P_IPV6) {
689 			if (filter->block_id == VCAP_ES0) {
690 				NL_SET_ERR_MSG_MOD(extack,
691 						   "VCAP ES0 cannot match on IP protocol");
692 				return -EOPNOTSUPP;
693 			}
694 
695 			filter->key_type = OCELOT_VCAP_KEY_IPV6;
696 			filter->key.ipv6.proto.value[0] =
697 				match.key->ip_proto;
698 			filter->key.ipv6.proto.mask[0] =
699 				match.mask->ip_proto;
700 			match_protocol = false;
701 		}
702 	}
703 
704 	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV4_ADDRS) &&
705 	    proto == ETH_P_IP) {
706 		struct flow_match_ipv4_addrs match;
707 		u8 *tmp;
708 
709 		if (filter->block_id == VCAP_ES0) {
710 			NL_SET_ERR_MSG_MOD(extack,
711 					   "VCAP ES0 cannot match on IP address");
712 			return -EOPNOTSUPP;
713 		}
714 
715 		flow_rule_match_ipv4_addrs(rule, &match);
716 
717 		if (filter->block_id == VCAP_IS1 && *(u32 *)&match.mask->dst) {
718 			NL_SET_ERR_MSG_MOD(extack,
719 					   "Key type S1_NORMAL cannot match on destination IP");
720 			return -EOPNOTSUPP;
721 		}
722 
723 		tmp = &filter->key.ipv4.sip.value.addr[0];
724 		memcpy(tmp, &match.key->src, 4);
725 
726 		tmp = &filter->key.ipv4.sip.mask.addr[0];
727 		memcpy(tmp, &match.mask->src, 4);
728 
729 		tmp = &filter->key.ipv4.dip.value.addr[0];
730 		memcpy(tmp, &match.key->dst, 4);
731 
732 		tmp = &filter->key.ipv4.dip.mask.addr[0];
733 		memcpy(tmp, &match.mask->dst, 4);
734 		match_protocol = false;
735 	}
736 
737 	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV6_ADDRS) &&
738 	    proto == ETH_P_IPV6) {
739 		return -EOPNOTSUPP;
740 	}
741 
742 	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_PORTS)) {
743 		struct flow_match_ports match;
744 
745 		if (filter->block_id == VCAP_ES0) {
746 			NL_SET_ERR_MSG_MOD(extack,
747 					   "VCAP ES0 cannot match on L4 ports");
748 			return -EOPNOTSUPP;
749 		}
750 
751 		flow_rule_match_ports(rule, &match);
752 		filter->key.ipv4.sport.value = ntohs(match.key->src);
753 		filter->key.ipv4.sport.mask = ntohs(match.mask->src);
754 		filter->key.ipv4.dport.value = ntohs(match.key->dst);
755 		filter->key.ipv4.dport.mask = ntohs(match.mask->dst);
756 		match_protocol = false;
757 	}
758 
759 finished_key_parsing:
760 	if (match_protocol && proto != ETH_P_ALL) {
761 		if (filter->block_id == VCAP_ES0) {
762 			NL_SET_ERR_MSG_MOD(extack,
763 					   "VCAP ES0 cannot match on L2 proto");
764 			return -EOPNOTSUPP;
765 		}
766 
767 		/* TODO: support SNAP, LLC etc */
768 		if (proto < ETH_P_802_3_MIN)
769 			return -EOPNOTSUPP;
770 		filter->key_type = OCELOT_VCAP_KEY_ETYPE;
771 		*(__be16 *)filter->key.etype.etype.value = htons(proto);
772 		*(__be16 *)filter->key.etype.etype.mask = htons(0xffff);
773 	}
774 	/* else, a filter of type OCELOT_VCAP_KEY_ANY is implicitly added */
775 
776 	return 0;
777 }
778 
ocelot_flower_parse(struct ocelot * ocelot,int port,bool ingress,struct flow_cls_offload * f,struct ocelot_vcap_filter * filter)779 static int ocelot_flower_parse(struct ocelot *ocelot, int port, bool ingress,
780 			       struct flow_cls_offload *f,
781 			       struct ocelot_vcap_filter *filter)
782 {
783 	int ret;
784 
785 	filter->prio = f->common.prio;
786 	filter->id.cookie = f->cookie;
787 	filter->id.tc_offload = true;
788 
789 	ret = ocelot_flower_parse_action(ocelot, port, ingress, f, filter);
790 	if (ret)
791 		return ret;
792 
793 	/* PSFP filter need to parse key by stream identification function. */
794 	if (filter->type == OCELOT_PSFP_FILTER_OFFLOAD)
795 		return 0;
796 
797 	return ocelot_flower_parse_key(ocelot, port, ingress, f, filter);
798 }
799 
800 static struct ocelot_vcap_filter
ocelot_vcap_filter_create(struct ocelot * ocelot,int port,bool ingress,struct flow_cls_offload * f)801 *ocelot_vcap_filter_create(struct ocelot *ocelot, int port, bool ingress,
802 			   struct flow_cls_offload *f)
803 {
804 	struct ocelot_vcap_filter *filter;
805 
806 	filter = kzalloc(sizeof(*filter), GFP_KERNEL);
807 	if (!filter)
808 		return NULL;
809 
810 	if (ingress) {
811 		filter->ingress_port_mask = BIT(port);
812 	} else {
813 		const struct vcap_props *vcap = &ocelot->vcap[VCAP_ES0];
814 		int key_length = vcap->keys[VCAP_ES0_EGR_PORT].length;
815 
816 		filter->egress_port.value = port;
817 		filter->egress_port.mask = GENMASK(key_length - 1, 0);
818 	}
819 
820 	return filter;
821 }
822 
ocelot_vcap_dummy_filter_add(struct ocelot * ocelot,struct ocelot_vcap_filter * filter)823 static int ocelot_vcap_dummy_filter_add(struct ocelot *ocelot,
824 					struct ocelot_vcap_filter *filter)
825 {
826 	list_add(&filter->list, &ocelot->dummy_rules);
827 
828 	return 0;
829 }
830 
ocelot_vcap_dummy_filter_del(struct ocelot * ocelot,struct ocelot_vcap_filter * filter)831 static int ocelot_vcap_dummy_filter_del(struct ocelot *ocelot,
832 					struct ocelot_vcap_filter *filter)
833 {
834 	list_del(&filter->list);
835 	kfree(filter);
836 
837 	return 0;
838 }
839 
840 /* If we have an egress VLAN modification rule, we need to actually write the
841  * delta between the input VLAN (from the key) and the output VLAN (from the
842  * action), but the action was parsed first. So we need to patch the delta into
843  * the action here.
844  */
845 static int
ocelot_flower_patch_es0_vlan_modify(struct ocelot_vcap_filter * filter,struct netlink_ext_ack * extack)846 ocelot_flower_patch_es0_vlan_modify(struct ocelot_vcap_filter *filter,
847 				    struct netlink_ext_ack *extack)
848 {
849 	if (filter->block_id != VCAP_ES0 ||
850 	    filter->action.tag_a_vid_sel != OCELOT_ES0_VID_PLUS_CLASSIFIED_VID)
851 		return 0;
852 
853 	if (filter->vlan.vid.mask != VLAN_VID_MASK) {
854 		NL_SET_ERR_MSG_MOD(extack,
855 				   "VCAP ES0 VLAN rewriting needs a full VLAN in the key");
856 		return -EOPNOTSUPP;
857 	}
858 
859 	filter->action.vid_a_val -= filter->vlan.vid.value;
860 	filter->action.vid_a_val &= VLAN_VID_MASK;
861 
862 	return 0;
863 }
864 
ocelot_cls_flower_replace(struct ocelot * ocelot,int port,struct flow_cls_offload * f,bool ingress)865 int ocelot_cls_flower_replace(struct ocelot *ocelot, int port,
866 			      struct flow_cls_offload *f, bool ingress)
867 {
868 	struct netlink_ext_ack *extack = f->common.extack;
869 	struct ocelot_vcap_filter *filter;
870 	int chain = f->common.chain_index;
871 	int block_id, ret;
872 
873 	if (chain && !ocelot_find_vcap_filter_that_points_at(ocelot, chain)) {
874 		NL_SET_ERR_MSG_MOD(extack, "No default GOTO action points to this chain");
875 		return -EOPNOTSUPP;
876 	}
877 
878 	block_id = ocelot_chain_to_block(chain, ingress);
879 	if (block_id < 0) {
880 		NL_SET_ERR_MSG_MOD(extack, "Cannot offload to this chain");
881 		return -EOPNOTSUPP;
882 	}
883 
884 	filter = ocelot_vcap_block_find_filter_by_id(&ocelot->block[block_id],
885 						     f->cookie, true);
886 	if (filter) {
887 		/* Filter already exists on other ports */
888 		if (!ingress) {
889 			NL_SET_ERR_MSG_MOD(extack, "VCAP ES0 does not support shared filters");
890 			return -EOPNOTSUPP;
891 		}
892 
893 		filter->ingress_port_mask |= BIT(port);
894 
895 		return ocelot_vcap_filter_replace(ocelot, filter);
896 	}
897 
898 	/* Filter didn't exist, create it now */
899 	filter = ocelot_vcap_filter_create(ocelot, port, ingress, f);
900 	if (!filter)
901 		return -ENOMEM;
902 
903 	ret = ocelot_flower_parse(ocelot, port, ingress, f, filter);
904 	if (ret) {
905 		kfree(filter);
906 		return ret;
907 	}
908 
909 	ret = ocelot_flower_patch_es0_vlan_modify(filter, extack);
910 	if (ret) {
911 		kfree(filter);
912 		return ret;
913 	}
914 
915 	/* The non-optional GOTOs for the TCAM skeleton don't need
916 	 * to be actually offloaded.
917 	 */
918 	if (filter->type == OCELOT_VCAP_FILTER_DUMMY)
919 		return ocelot_vcap_dummy_filter_add(ocelot, filter);
920 
921 	if (filter->type == OCELOT_PSFP_FILTER_OFFLOAD) {
922 		kfree(filter);
923 		if (ocelot->ops->psfp_filter_add)
924 			return ocelot->ops->psfp_filter_add(ocelot, port, f);
925 
926 		NL_SET_ERR_MSG_MOD(extack, "PSFP chain is not supported in HW");
927 		return -EOPNOTSUPP;
928 	}
929 
930 	return ocelot_vcap_filter_add(ocelot, filter, f->common.extack);
931 }
932 EXPORT_SYMBOL_GPL(ocelot_cls_flower_replace);
933 
ocelot_cls_flower_destroy(struct ocelot * ocelot,int port,struct flow_cls_offload * f,bool ingress)934 int ocelot_cls_flower_destroy(struct ocelot *ocelot, int port,
935 			      struct flow_cls_offload *f, bool ingress)
936 {
937 	struct ocelot_vcap_filter *filter;
938 	struct ocelot_vcap_block *block;
939 	int block_id;
940 
941 	block_id = ocelot_chain_to_block(f->common.chain_index, ingress);
942 	if (block_id < 0)
943 		return 0;
944 
945 	if (block_id == PSFP_BLOCK_ID) {
946 		if (ocelot->ops->psfp_filter_del)
947 			return ocelot->ops->psfp_filter_del(ocelot, f);
948 
949 		return -EOPNOTSUPP;
950 	}
951 
952 	block = &ocelot->block[block_id];
953 
954 	filter = ocelot_vcap_block_find_filter_by_id(block, f->cookie, true);
955 	if (!filter)
956 		return 0;
957 
958 	if (filter->type == OCELOT_VCAP_FILTER_DUMMY)
959 		return ocelot_vcap_dummy_filter_del(ocelot, filter);
960 
961 	if (ingress) {
962 		filter->ingress_port_mask &= ~BIT(port);
963 		if (filter->ingress_port_mask)
964 			return ocelot_vcap_filter_replace(ocelot, filter);
965 	}
966 
967 	return ocelot_vcap_filter_del(ocelot, filter);
968 }
969 EXPORT_SYMBOL_GPL(ocelot_cls_flower_destroy);
970 
ocelot_cls_flower_stats(struct ocelot * ocelot,int port,struct flow_cls_offload * f,bool ingress)971 int ocelot_cls_flower_stats(struct ocelot *ocelot, int port,
972 			    struct flow_cls_offload *f, bool ingress)
973 {
974 	struct ocelot_vcap_filter *filter;
975 	struct ocelot_vcap_block *block;
976 	struct flow_stats stats = {0};
977 	int block_id, ret;
978 
979 	block_id = ocelot_chain_to_block(f->common.chain_index, ingress);
980 	if (block_id < 0)
981 		return 0;
982 
983 	if (block_id == PSFP_BLOCK_ID) {
984 		if (ocelot->ops->psfp_stats_get) {
985 			ret = ocelot->ops->psfp_stats_get(ocelot, f, &stats);
986 			if (ret)
987 				return ret;
988 
989 			goto stats_update;
990 		}
991 
992 		return -EOPNOTSUPP;
993 	}
994 
995 	block = &ocelot->block[block_id];
996 
997 	filter = ocelot_vcap_block_find_filter_by_id(block, f->cookie, true);
998 	if (!filter || filter->type == OCELOT_VCAP_FILTER_DUMMY)
999 		return 0;
1000 
1001 	ret = ocelot_vcap_filter_stats_update(ocelot, filter);
1002 	if (ret)
1003 		return ret;
1004 
1005 	stats.pkts = filter->stats.pkts;
1006 
1007 stats_update:
1008 	flow_stats_update(&f->stats, 0x0, stats.pkts, stats.drops, 0x0,
1009 			  FLOW_ACTION_HW_STATS_IMMEDIATE);
1010 	return 0;
1011 }
1012 EXPORT_SYMBOL_GPL(ocelot_cls_flower_stats);
1013