xref: /linux/drivers/net/ethernet/mscc/ocelot_flower.c (revision f72aa1b276281b4e4f75261af8425bc99d903f3e)
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 
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  */
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  */
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 
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 *
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
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
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 
231 static int
232 ocelot_flower_parse_egress_port(struct ocelot *ocelot, struct flow_cls_offload *f,
233 				const struct flow_action_entry *a, bool mirror,
234 				struct netlink_ext_ack *extack)
235 {
236 	const char *act_string = mirror ? "mirror" : "redirect";
237 	int egress_port = ocelot->ops->netdev_to_port(a->dev);
238 	enum flow_action_id offloadable_act_id;
239 
240 	offloadable_act_id = mirror ? FLOW_ACTION_MIRRED : FLOW_ACTION_REDIRECT;
241 
242 	/* Mirroring towards foreign interfaces is handled in software */
243 	if (egress_port < 0 || a->id != offloadable_act_id) {
244 		if (f->common.skip_sw) {
245 			NL_SET_ERR_MSG_FMT(extack,
246 					   "Can only %s to %s if filter also runs in software",
247 					   act_string, egress_port < 0 ?
248 					   "CPU" : "ingress of ocelot port");
249 			return -EOPNOTSUPP;
250 		}
251 		egress_port = ocelot->num_phys_ports;
252 	}
253 
254 	return egress_port;
255 }
256 
257 static int ocelot_flower_parse_action(struct ocelot *ocelot, int port,
258 				      bool ingress, struct flow_cls_offload *f,
259 				      struct ocelot_vcap_filter *filter)
260 {
261 	const struct flow_action *action = &f->rule->action;
262 	struct netlink_ext_ack *extack = f->common.extack;
263 	bool allow_missing_goto_target = false;
264 	const struct flow_action_entry *a;
265 	enum ocelot_tag_tpid_sel tpid;
266 	int i, chain, egress_port;
267 	u32 pol_ix, pol_max;
268 	u64 rate;
269 	int err;
270 
271 	if (!flow_action_basic_hw_stats_check(&f->rule->action,
272 					      f->common.extack))
273 		return -EOPNOTSUPP;
274 
275 	chain = f->common.chain_index;
276 	filter->block_id = ocelot_chain_to_block(chain, ingress);
277 	if (filter->block_id < 0) {
278 		NL_SET_ERR_MSG_MOD(extack, "Cannot offload to this chain");
279 		return -EOPNOTSUPP;
280 	}
281 	if (filter->block_id == VCAP_IS1 || filter->block_id == VCAP_IS2)
282 		filter->lookup = ocelot_chain_to_lookup(chain);
283 	if (filter->block_id == VCAP_IS2)
284 		filter->pag = ocelot_chain_to_pag(chain);
285 
286 	filter->goto_target = -1;
287 	filter->type = OCELOT_VCAP_FILTER_DUMMY;
288 
289 	flow_action_for_each(i, a, action) {
290 		switch (a->id) {
291 		case FLOW_ACTION_DROP:
292 			if (filter->block_id != VCAP_IS2) {
293 				NL_SET_ERR_MSG_MOD(extack,
294 						   "Drop action can only be offloaded to VCAP IS2");
295 				return -EOPNOTSUPP;
296 			}
297 			if (filter->goto_target != -1) {
298 				NL_SET_ERR_MSG_MOD(extack,
299 						   "Last action must be GOTO");
300 				return -EOPNOTSUPP;
301 			}
302 			filter->action.mask_mode = OCELOT_MASK_MODE_PERMIT_DENY;
303 			filter->action.port_mask = 0;
304 			filter->action.police_ena = true;
305 			filter->action.pol_ix = OCELOT_POLICER_DISCARD;
306 			filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
307 			break;
308 		case FLOW_ACTION_ACCEPT:
309 			if (filter->block_id != VCAP_ES0 &&
310 			    filter->block_id != VCAP_IS1 &&
311 			    filter->block_id != VCAP_IS2) {
312 				NL_SET_ERR_MSG_MOD(extack,
313 						   "Accept action can only be offloaded to VCAP chains");
314 				return -EOPNOTSUPP;
315 			}
316 			if (filter->block_id != VCAP_ES0 &&
317 			    filter->goto_target != -1) {
318 				NL_SET_ERR_MSG_MOD(extack,
319 						   "Last action must be GOTO");
320 				return -EOPNOTSUPP;
321 			}
322 			filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
323 			break;
324 		case FLOW_ACTION_TRAP:
325 			if (filter->block_id != VCAP_IS2 ||
326 			    filter->lookup != 0) {
327 				NL_SET_ERR_MSG_MOD(extack,
328 						   "Trap action can only be offloaded to VCAP IS2 lookup 0");
329 				return -EOPNOTSUPP;
330 			}
331 			if (filter->goto_target != -1) {
332 				NL_SET_ERR_MSG_MOD(extack,
333 						   "Last action must be GOTO");
334 				return -EOPNOTSUPP;
335 			}
336 			filter->action.mask_mode = OCELOT_MASK_MODE_PERMIT_DENY;
337 			filter->action.port_mask = 0;
338 			filter->action.cpu_copy_ena = true;
339 			filter->action.cpu_qu_num = 0;
340 			filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
341 			filter->is_trap = true;
342 			break;
343 		case FLOW_ACTION_POLICE:
344 			if (filter->block_id == PSFP_BLOCK_ID) {
345 				filter->type = OCELOT_PSFP_FILTER_OFFLOAD;
346 				break;
347 			}
348 			if (filter->block_id != VCAP_IS2 ||
349 			    filter->lookup != 0) {
350 				NL_SET_ERR_MSG_MOD(extack,
351 						   "Police action can only be offloaded to VCAP IS2 lookup 0 or PSFP");
352 				return -EOPNOTSUPP;
353 			}
354 			if (filter->goto_target != -1) {
355 				NL_SET_ERR_MSG_MOD(extack,
356 						   "Last action must be GOTO");
357 				return -EOPNOTSUPP;
358 			}
359 
360 			err = ocelot_policer_validate(action, a, extack);
361 			if (err)
362 				return err;
363 
364 			filter->action.police_ena = true;
365 
366 			pol_ix = a->hw_index + ocelot->vcap_pol.base;
367 			pol_max = ocelot->vcap_pol.max;
368 
369 			if (ocelot->vcap_pol.max2 && pol_ix > pol_max) {
370 				pol_ix += ocelot->vcap_pol.base2 - pol_max - 1;
371 				pol_max = ocelot->vcap_pol.max2;
372 			}
373 
374 			if (pol_ix >= pol_max)
375 				return -EINVAL;
376 
377 			filter->action.pol_ix = pol_ix;
378 
379 			rate = a->police.rate_bytes_ps;
380 			filter->action.pol.rate = div_u64(rate, 1000) * 8;
381 			filter->action.pol.burst = a->police.burst;
382 			filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
383 			break;
384 		case FLOW_ACTION_REDIRECT:
385 		case FLOW_ACTION_REDIRECT_INGRESS:
386 			if (filter->block_id != VCAP_IS2) {
387 				NL_SET_ERR_MSG_MOD(extack,
388 						   "Redirect action can only be offloaded to VCAP IS2");
389 				return -EOPNOTSUPP;
390 			}
391 			if (filter->goto_target != -1) {
392 				NL_SET_ERR_MSG_MOD(extack,
393 						   "Last action must be GOTO");
394 				return -EOPNOTSUPP;
395 			}
396 
397 			egress_port = ocelot_flower_parse_egress_port(ocelot, f,
398 								      a, false,
399 								      extack);
400 			if (egress_port < 0)
401 				return egress_port;
402 
403 			filter->action.mask_mode = OCELOT_MASK_MODE_REDIRECT;
404 			filter->action.port_mask = BIT(egress_port);
405 			filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
406 			break;
407 		case FLOW_ACTION_MIRRED:
408 		case FLOW_ACTION_MIRRED_INGRESS:
409 			if (filter->block_id != VCAP_IS2) {
410 				NL_SET_ERR_MSG_MOD(extack,
411 						   "Mirror action can only be offloaded to VCAP IS2");
412 				return -EOPNOTSUPP;
413 			}
414 			if (filter->goto_target != -1) {
415 				NL_SET_ERR_MSG_MOD(extack,
416 						   "Last action must be GOTO");
417 				return -EOPNOTSUPP;
418 			}
419 
420 			egress_port = ocelot_flower_parse_egress_port(ocelot, f,
421 								      a, true,
422 								      extack);
423 			if (egress_port < 0)
424 				return egress_port;
425 
426 			filter->egress_port.value = egress_port;
427 			filter->action.mirror_ena = true;
428 			filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
429 			break;
430 		case FLOW_ACTION_VLAN_POP:
431 			if (filter->block_id != VCAP_IS1) {
432 				NL_SET_ERR_MSG_MOD(extack,
433 						   "VLAN pop action can only be offloaded to VCAP IS1");
434 				return -EOPNOTSUPP;
435 			}
436 			if (filter->goto_target != -1) {
437 				NL_SET_ERR_MSG_MOD(extack,
438 						   "Last action must be GOTO");
439 				return -EOPNOTSUPP;
440 			}
441 			filter->action.vlan_pop_cnt_ena = true;
442 			filter->action.vlan_pop_cnt++;
443 			if (filter->action.vlan_pop_cnt > 2) {
444 				NL_SET_ERR_MSG_MOD(extack,
445 						   "Cannot pop more than 2 VLAN headers");
446 				return -EOPNOTSUPP;
447 			}
448 			filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
449 			break;
450 		case FLOW_ACTION_VLAN_MANGLE:
451 			if (filter->block_id == VCAP_IS1) {
452 				err = ocelot_flower_parse_ingress_vlan_modify(ocelot, port,
453 									      filter, a,
454 									      extack);
455 			} else if (filter->block_id == VCAP_ES0) {
456 				err = ocelot_flower_parse_egress_vlan_modify(filter, a,
457 									     extack);
458 			} else {
459 				NL_SET_ERR_MSG_MOD(extack,
460 						   "VLAN modify action can only be offloaded to VCAP IS1 or ES0");
461 				err = -EOPNOTSUPP;
462 			}
463 			if (err)
464 				return err;
465 			break;
466 		case FLOW_ACTION_PRIORITY:
467 			if (filter->block_id != VCAP_IS1) {
468 				NL_SET_ERR_MSG_MOD(extack,
469 						   "Priority action can only be offloaded to VCAP IS1");
470 				return -EOPNOTSUPP;
471 			}
472 			if (filter->goto_target != -1) {
473 				NL_SET_ERR_MSG_MOD(extack,
474 						   "Last action must be GOTO");
475 				return -EOPNOTSUPP;
476 			}
477 			filter->action.qos_ena = true;
478 			filter->action.qos_val = a->priority;
479 			filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
480 			break;
481 		case FLOW_ACTION_GOTO:
482 			filter->goto_target = a->chain_index;
483 
484 			if (filter->block_id == VCAP_IS1 && filter->lookup == 2) {
485 				int pag = ocelot_chain_to_pag(filter->goto_target);
486 
487 				filter->action.pag_override_mask = 0xff;
488 				filter->action.pag_val = pag;
489 				filter->type = OCELOT_VCAP_FILTER_PAG;
490 			}
491 			break;
492 		case FLOW_ACTION_VLAN_PUSH:
493 			if (filter->block_id != VCAP_ES0) {
494 				NL_SET_ERR_MSG_MOD(extack,
495 						   "VLAN push action can only be offloaded to VCAP ES0");
496 				return -EOPNOTSUPP;
497 			}
498 			switch (ntohs(a->vlan.proto)) {
499 			case ETH_P_8021Q:
500 				tpid = OCELOT_TAG_TPID_SEL_8021Q;
501 				break;
502 			case ETH_P_8021AD:
503 				tpid = OCELOT_TAG_TPID_SEL_8021AD;
504 				break;
505 			default:
506 				NL_SET_ERR_MSG_MOD(extack,
507 						   "Cannot push custom TPID");
508 				return -EOPNOTSUPP;
509 			}
510 			filter->action.tag_a_tpid_sel = tpid;
511 			filter->action.push_outer_tag = OCELOT_ES0_TAG;
512 			filter->action.tag_a_vid_sel = OCELOT_ES0_VID;
513 			filter->action.vid_a_val = a->vlan.vid;
514 			filter->action.pcp_a_val = a->vlan.prio;
515 			filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
516 			break;
517 		case FLOW_ACTION_GATE:
518 			if (filter->block_id != PSFP_BLOCK_ID) {
519 				NL_SET_ERR_MSG_MOD(extack,
520 						   "Gate action can only be offloaded to PSFP chain");
521 				return -EOPNOTSUPP;
522 			}
523 			filter->type = OCELOT_PSFP_FILTER_OFFLOAD;
524 			break;
525 		default:
526 			NL_SET_ERR_MSG_MOD(extack, "Cannot offload action");
527 			return -EOPNOTSUPP;
528 		}
529 	}
530 
531 	if (filter->goto_target == -1) {
532 		if ((filter->block_id == VCAP_IS2 && filter->lookup == 1) ||
533 		    chain == 0 || filter->block_id == PSFP_BLOCK_ID) {
534 			allow_missing_goto_target = true;
535 		} else {
536 			NL_SET_ERR_MSG_MOD(extack, "Missing GOTO action");
537 			return -EOPNOTSUPP;
538 		}
539 	}
540 
541 	if (!ocelot_is_goto_target_valid(filter->goto_target, chain, ingress) &&
542 	    !allow_missing_goto_target) {
543 		NL_SET_ERR_MSG_MOD(extack, "Cannot offload this GOTO target");
544 		return -EOPNOTSUPP;
545 	}
546 
547 	return 0;
548 }
549 
550 static int ocelot_flower_parse_indev(struct ocelot *ocelot, int port,
551 				     struct flow_cls_offload *f,
552 				     struct ocelot_vcap_filter *filter)
553 {
554 	struct flow_rule *rule = flow_cls_offload_flow_rule(f);
555 	const struct vcap_props *vcap = &ocelot->vcap[VCAP_ES0];
556 	int key_length = vcap->keys[VCAP_ES0_IGR_PORT].length;
557 	struct netlink_ext_ack *extack = f->common.extack;
558 	struct net_device *dev, *indev;
559 	struct flow_match_meta match;
560 	int ingress_port;
561 
562 	flow_rule_match_meta(rule, &match);
563 
564 	if (!match.mask->ingress_ifindex)
565 		return 0;
566 
567 	if (match.mask->ingress_ifindex != 0xFFFFFFFF) {
568 		NL_SET_ERR_MSG_MOD(extack, "Unsupported ingress ifindex mask");
569 		return -EOPNOTSUPP;
570 	}
571 
572 	dev = ocelot->ops->port_to_netdev(ocelot, port);
573 	if (!dev)
574 		return -EINVAL;
575 
576 	indev = __dev_get_by_index(dev_net(dev), match.key->ingress_ifindex);
577 	if (!indev) {
578 		NL_SET_ERR_MSG_MOD(extack,
579 				   "Can't find the ingress port to match on");
580 		return -ENOENT;
581 	}
582 
583 	ingress_port = ocelot->ops->netdev_to_port(indev);
584 	if (ingress_port < 0) {
585 		NL_SET_ERR_MSG_MOD(extack,
586 				   "Can only offload an ocelot ingress port");
587 		return -EOPNOTSUPP;
588 	}
589 	if (ingress_port == port) {
590 		NL_SET_ERR_MSG_MOD(extack,
591 				   "Ingress port is equal to the egress port");
592 		return -EINVAL;
593 	}
594 
595 	filter->ingress_port.value = ingress_port;
596 	filter->ingress_port.mask = GENMASK(key_length - 1, 0);
597 
598 	return 0;
599 }
600 
601 static int
602 ocelot_flower_parse_key(struct ocelot *ocelot, int port, bool ingress,
603 			struct flow_cls_offload *f,
604 			struct ocelot_vcap_filter *filter)
605 {
606 	struct flow_rule *rule = flow_cls_offload_flow_rule(f);
607 	struct flow_dissector *dissector = rule->match.dissector;
608 	struct netlink_ext_ack *extack = f->common.extack;
609 	u16 proto = ntohs(f->common.protocol);
610 	bool match_protocol = true;
611 	int ret;
612 
613 	if (dissector->used_keys &
614 	    ~(BIT_ULL(FLOW_DISSECTOR_KEY_CONTROL) |
615 	      BIT_ULL(FLOW_DISSECTOR_KEY_BASIC) |
616 	      BIT_ULL(FLOW_DISSECTOR_KEY_META) |
617 	      BIT_ULL(FLOW_DISSECTOR_KEY_PORTS) |
618 	      BIT_ULL(FLOW_DISSECTOR_KEY_VLAN) |
619 	      BIT_ULL(FLOW_DISSECTOR_KEY_IPV4_ADDRS) |
620 	      BIT_ULL(FLOW_DISSECTOR_KEY_IPV6_ADDRS) |
621 	      BIT_ULL(FLOW_DISSECTOR_KEY_ETH_ADDRS))) {
622 		return -EOPNOTSUPP;
623 	}
624 
625 	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_META)) {
626 		struct flow_match_meta match;
627 
628 		flow_rule_match_meta(rule, &match);
629 		if (match.mask->l2_miss) {
630 			NL_SET_ERR_MSG_MOD(extack, "Can't match on \"l2_miss\"");
631 			return -EOPNOTSUPP;
632 		}
633 	}
634 
635 	/* For VCAP ES0 (egress rewriter) we can match on the ingress port */
636 	if (!ingress) {
637 		ret = ocelot_flower_parse_indev(ocelot, port, f, filter);
638 		if (ret)
639 			return ret;
640 	}
641 
642 	if (flow_rule_match_has_control_flags(rule, extack))
643 		return -EOPNOTSUPP;
644 
645 	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_VLAN)) {
646 		struct flow_match_vlan match;
647 
648 		flow_rule_match_vlan(rule, &match);
649 		filter->key_type = OCELOT_VCAP_KEY_ANY;
650 		filter->vlan.vid.value = match.key->vlan_id;
651 		filter->vlan.vid.mask = match.mask->vlan_id;
652 		filter->vlan.pcp.value[0] = match.key->vlan_priority;
653 		filter->vlan.pcp.mask[0] = match.mask->vlan_priority;
654 		match_protocol = false;
655 	}
656 
657 	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ETH_ADDRS)) {
658 		struct flow_match_eth_addrs match;
659 
660 		if (filter->block_id == VCAP_ES0) {
661 			NL_SET_ERR_MSG_MOD(extack,
662 					   "VCAP ES0 cannot match on MAC address");
663 			return -EOPNOTSUPP;
664 		}
665 
666 		/* The hw support mac matches only for MAC_ETYPE key,
667 		 * therefore if other matches(port, tcp flags, etc) are added
668 		 * then just bail out
669 		 */
670 		if ((dissector->used_keys &
671 		    (BIT_ULL(FLOW_DISSECTOR_KEY_ETH_ADDRS) |
672 		     BIT_ULL(FLOW_DISSECTOR_KEY_BASIC) |
673 		     BIT_ULL(FLOW_DISSECTOR_KEY_CONTROL))) !=
674 		    (BIT_ULL(FLOW_DISSECTOR_KEY_ETH_ADDRS) |
675 		     BIT_ULL(FLOW_DISSECTOR_KEY_BASIC) |
676 		     BIT_ULL(FLOW_DISSECTOR_KEY_CONTROL)))
677 			return -EOPNOTSUPP;
678 
679 		flow_rule_match_eth_addrs(rule, &match);
680 
681 		if (filter->block_id == VCAP_IS1 &&
682 		    !is_zero_ether_addr(match.mask->dst)) {
683 			NL_SET_ERR_MSG_MOD(extack,
684 					   "Key type S1_NORMAL cannot match on destination MAC");
685 			return -EOPNOTSUPP;
686 		}
687 
688 		filter->key_type = OCELOT_VCAP_KEY_ETYPE;
689 		ether_addr_copy(filter->key.etype.dmac.value,
690 				match.key->dst);
691 		ether_addr_copy(filter->key.etype.smac.value,
692 				match.key->src);
693 		ether_addr_copy(filter->key.etype.dmac.mask,
694 				match.mask->dst);
695 		ether_addr_copy(filter->key.etype.smac.mask,
696 				match.mask->src);
697 		goto finished_key_parsing;
698 	}
699 
700 	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) {
701 		struct flow_match_basic match;
702 
703 		flow_rule_match_basic(rule, &match);
704 		if (ntohs(match.key->n_proto) == ETH_P_IP) {
705 			if (filter->block_id == VCAP_ES0) {
706 				NL_SET_ERR_MSG_MOD(extack,
707 						   "VCAP ES0 cannot match on IP protocol");
708 				return -EOPNOTSUPP;
709 			}
710 
711 			filter->key_type = OCELOT_VCAP_KEY_IPV4;
712 			filter->key.ipv4.proto.value[0] =
713 				match.key->ip_proto;
714 			filter->key.ipv4.proto.mask[0] =
715 				match.mask->ip_proto;
716 			match_protocol = false;
717 		}
718 		if (ntohs(match.key->n_proto) == ETH_P_IPV6) {
719 			if (filter->block_id == VCAP_ES0) {
720 				NL_SET_ERR_MSG_MOD(extack,
721 						   "VCAP ES0 cannot match on IP protocol");
722 				return -EOPNOTSUPP;
723 			}
724 
725 			filter->key_type = OCELOT_VCAP_KEY_IPV6;
726 			filter->key.ipv6.proto.value[0] =
727 				match.key->ip_proto;
728 			filter->key.ipv6.proto.mask[0] =
729 				match.mask->ip_proto;
730 			match_protocol = false;
731 		}
732 	}
733 
734 	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV4_ADDRS) &&
735 	    proto == ETH_P_IP) {
736 		struct flow_match_ipv4_addrs match;
737 		u8 *tmp;
738 
739 		if (filter->block_id == VCAP_ES0) {
740 			NL_SET_ERR_MSG_MOD(extack,
741 					   "VCAP ES0 cannot match on IP address");
742 			return -EOPNOTSUPP;
743 		}
744 
745 		flow_rule_match_ipv4_addrs(rule, &match);
746 
747 		if (filter->block_id == VCAP_IS1 && *(u32 *)&match.mask->dst) {
748 			NL_SET_ERR_MSG_MOD(extack,
749 					   "Key type S1_NORMAL cannot match on destination IP");
750 			return -EOPNOTSUPP;
751 		}
752 
753 		tmp = &filter->key.ipv4.sip.value.addr[0];
754 		memcpy(tmp, &match.key->src, 4);
755 
756 		tmp = &filter->key.ipv4.sip.mask.addr[0];
757 		memcpy(tmp, &match.mask->src, 4);
758 
759 		tmp = &filter->key.ipv4.dip.value.addr[0];
760 		memcpy(tmp, &match.key->dst, 4);
761 
762 		tmp = &filter->key.ipv4.dip.mask.addr[0];
763 		memcpy(tmp, &match.mask->dst, 4);
764 		match_protocol = false;
765 	}
766 
767 	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV6_ADDRS) &&
768 	    proto == ETH_P_IPV6) {
769 		return -EOPNOTSUPP;
770 	}
771 
772 	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_PORTS)) {
773 		struct flow_match_ports match;
774 
775 		if (filter->block_id == VCAP_ES0) {
776 			NL_SET_ERR_MSG_MOD(extack,
777 					   "VCAP ES0 cannot match on L4 ports");
778 			return -EOPNOTSUPP;
779 		}
780 
781 		flow_rule_match_ports(rule, &match);
782 		filter->key.ipv4.sport.value = ntohs(match.key->src);
783 		filter->key.ipv4.sport.mask = ntohs(match.mask->src);
784 		filter->key.ipv4.dport.value = ntohs(match.key->dst);
785 		filter->key.ipv4.dport.mask = ntohs(match.mask->dst);
786 		match_protocol = false;
787 	}
788 
789 finished_key_parsing:
790 	if (match_protocol && proto != ETH_P_ALL) {
791 		if (filter->block_id == VCAP_ES0) {
792 			NL_SET_ERR_MSG_MOD(extack,
793 					   "VCAP ES0 cannot match on L2 proto");
794 			return -EOPNOTSUPP;
795 		}
796 
797 		/* TODO: support SNAP, LLC etc */
798 		if (proto < ETH_P_802_3_MIN)
799 			return -EOPNOTSUPP;
800 		filter->key_type = OCELOT_VCAP_KEY_ETYPE;
801 		*(__be16 *)filter->key.etype.etype.value = htons(proto);
802 		*(__be16 *)filter->key.etype.etype.mask = htons(0xffff);
803 	}
804 	/* else, a filter of type OCELOT_VCAP_KEY_ANY is implicitly added */
805 
806 	return 0;
807 }
808 
809 static int ocelot_flower_parse(struct ocelot *ocelot, int port, bool ingress,
810 			       struct flow_cls_offload *f,
811 			       struct ocelot_vcap_filter *filter)
812 {
813 	int ret;
814 
815 	filter->prio = f->common.prio;
816 	filter->id.cookie = f->cookie;
817 	filter->id.tc_offload = true;
818 
819 	ret = ocelot_flower_parse_action(ocelot, port, ingress, f, filter);
820 	if (ret)
821 		return ret;
822 
823 	/* PSFP filter need to parse key by stream identification function. */
824 	if (filter->type == OCELOT_PSFP_FILTER_OFFLOAD)
825 		return 0;
826 
827 	return ocelot_flower_parse_key(ocelot, port, ingress, f, filter);
828 }
829 
830 static struct ocelot_vcap_filter
831 *ocelot_vcap_filter_create(struct ocelot *ocelot, int port, bool ingress,
832 			   struct flow_cls_offload *f)
833 {
834 	struct ocelot_vcap_filter *filter;
835 
836 	filter = kzalloc(sizeof(*filter), GFP_KERNEL);
837 	if (!filter)
838 		return NULL;
839 
840 	if (ingress) {
841 		filter->ingress_port_mask = BIT(port);
842 	} else {
843 		const struct vcap_props *vcap = &ocelot->vcap[VCAP_ES0];
844 		int key_length = vcap->keys[VCAP_ES0_EGR_PORT].length;
845 
846 		filter->egress_port.value = port;
847 		filter->egress_port.mask = GENMASK(key_length - 1, 0);
848 	}
849 
850 	return filter;
851 }
852 
853 static int ocelot_vcap_dummy_filter_add(struct ocelot *ocelot,
854 					struct ocelot_vcap_filter *filter)
855 {
856 	list_add(&filter->list, &ocelot->dummy_rules);
857 
858 	return 0;
859 }
860 
861 static int ocelot_vcap_dummy_filter_del(struct ocelot *ocelot,
862 					struct ocelot_vcap_filter *filter)
863 {
864 	list_del(&filter->list);
865 	kfree(filter);
866 
867 	return 0;
868 }
869 
870 /* If we have an egress VLAN modification rule, we need to actually write the
871  * delta between the input VLAN (from the key) and the output VLAN (from the
872  * action), but the action was parsed first. So we need to patch the delta into
873  * the action here.
874  */
875 static int
876 ocelot_flower_patch_es0_vlan_modify(struct ocelot_vcap_filter *filter,
877 				    struct netlink_ext_ack *extack)
878 {
879 	if (filter->block_id != VCAP_ES0 ||
880 	    filter->action.tag_a_vid_sel != OCELOT_ES0_VID_PLUS_CLASSIFIED_VID)
881 		return 0;
882 
883 	if (filter->vlan.vid.mask != VLAN_VID_MASK) {
884 		NL_SET_ERR_MSG_MOD(extack,
885 				   "VCAP ES0 VLAN rewriting needs a full VLAN in the key");
886 		return -EOPNOTSUPP;
887 	}
888 
889 	filter->action.vid_a_val -= filter->vlan.vid.value;
890 	filter->action.vid_a_val &= VLAN_VID_MASK;
891 
892 	return 0;
893 }
894 
895 int ocelot_cls_flower_replace(struct ocelot *ocelot, int port,
896 			      struct flow_cls_offload *f, bool ingress)
897 {
898 	struct netlink_ext_ack *extack = f->common.extack;
899 	struct ocelot_vcap_filter *filter;
900 	int chain = f->common.chain_index;
901 	int block_id, ret;
902 
903 	if (chain && !ocelot_find_vcap_filter_that_points_at(ocelot, chain)) {
904 		NL_SET_ERR_MSG_MOD(extack, "No default GOTO action points to this chain");
905 		return -EOPNOTSUPP;
906 	}
907 
908 	block_id = ocelot_chain_to_block(chain, ingress);
909 	if (block_id < 0) {
910 		NL_SET_ERR_MSG_MOD(extack, "Cannot offload to this chain");
911 		return -EOPNOTSUPP;
912 	}
913 
914 	filter = ocelot_vcap_block_find_filter_by_id(&ocelot->block[block_id],
915 						     f->cookie, true);
916 	if (filter) {
917 		/* Filter already exists on other ports */
918 		if (!ingress) {
919 			NL_SET_ERR_MSG_MOD(extack, "VCAP ES0 does not support shared filters");
920 			return -EOPNOTSUPP;
921 		}
922 
923 		filter->ingress_port_mask |= BIT(port);
924 
925 		return ocelot_vcap_filter_replace(ocelot, filter);
926 	}
927 
928 	/* Filter didn't exist, create it now */
929 	filter = ocelot_vcap_filter_create(ocelot, port, ingress, f);
930 	if (!filter)
931 		return -ENOMEM;
932 
933 	ret = ocelot_flower_parse(ocelot, port, ingress, f, filter);
934 	if (ret) {
935 		kfree(filter);
936 		return ret;
937 	}
938 
939 	ret = ocelot_flower_patch_es0_vlan_modify(filter, extack);
940 	if (ret) {
941 		kfree(filter);
942 		return ret;
943 	}
944 
945 	/* The non-optional GOTOs for the TCAM skeleton don't need
946 	 * to be actually offloaded.
947 	 */
948 	if (filter->type == OCELOT_VCAP_FILTER_DUMMY)
949 		return ocelot_vcap_dummy_filter_add(ocelot, filter);
950 
951 	if (filter->type == OCELOT_PSFP_FILTER_OFFLOAD) {
952 		kfree(filter);
953 		if (ocelot->ops->psfp_filter_add)
954 			return ocelot->ops->psfp_filter_add(ocelot, port, f);
955 
956 		NL_SET_ERR_MSG_MOD(extack, "PSFP chain is not supported in HW");
957 		return -EOPNOTSUPP;
958 	}
959 
960 	return ocelot_vcap_filter_add(ocelot, filter, f->common.extack);
961 }
962 EXPORT_SYMBOL_GPL(ocelot_cls_flower_replace);
963 
964 int ocelot_cls_flower_destroy(struct ocelot *ocelot, int port,
965 			      struct flow_cls_offload *f, bool ingress)
966 {
967 	struct ocelot_vcap_filter *filter;
968 	struct ocelot_vcap_block *block;
969 	int block_id;
970 
971 	block_id = ocelot_chain_to_block(f->common.chain_index, ingress);
972 	if (block_id < 0)
973 		return 0;
974 
975 	if (block_id == PSFP_BLOCK_ID) {
976 		if (ocelot->ops->psfp_filter_del)
977 			return ocelot->ops->psfp_filter_del(ocelot, f);
978 
979 		return -EOPNOTSUPP;
980 	}
981 
982 	block = &ocelot->block[block_id];
983 
984 	filter = ocelot_vcap_block_find_filter_by_id(block, f->cookie, true);
985 	if (!filter)
986 		return 0;
987 
988 	if (filter->type == OCELOT_VCAP_FILTER_DUMMY)
989 		return ocelot_vcap_dummy_filter_del(ocelot, filter);
990 
991 	if (ingress) {
992 		filter->ingress_port_mask &= ~BIT(port);
993 		if (filter->ingress_port_mask)
994 			return ocelot_vcap_filter_replace(ocelot, filter);
995 	}
996 
997 	return ocelot_vcap_filter_del(ocelot, filter);
998 }
999 EXPORT_SYMBOL_GPL(ocelot_cls_flower_destroy);
1000 
1001 int ocelot_cls_flower_stats(struct ocelot *ocelot, int port,
1002 			    struct flow_cls_offload *f, bool ingress)
1003 {
1004 	struct ocelot_vcap_filter *filter;
1005 	struct ocelot_vcap_block *block;
1006 	struct flow_stats stats = {0};
1007 	int block_id, ret;
1008 
1009 	block_id = ocelot_chain_to_block(f->common.chain_index, ingress);
1010 	if (block_id < 0)
1011 		return 0;
1012 
1013 	if (block_id == PSFP_BLOCK_ID) {
1014 		if (ocelot->ops->psfp_stats_get) {
1015 			ret = ocelot->ops->psfp_stats_get(ocelot, f, &stats);
1016 			if (ret)
1017 				return ret;
1018 
1019 			goto stats_update;
1020 		}
1021 
1022 		return -EOPNOTSUPP;
1023 	}
1024 
1025 	block = &ocelot->block[block_id];
1026 
1027 	filter = ocelot_vcap_block_find_filter_by_id(block, f->cookie, true);
1028 	if (!filter || filter->type == OCELOT_VCAP_FILTER_DUMMY)
1029 		return 0;
1030 
1031 	ret = ocelot_vcap_filter_stats_update(ocelot, filter);
1032 	if (ret)
1033 		return ret;
1034 
1035 	stats.pkts = filter->stats.pkts;
1036 
1037 stats_update:
1038 	flow_stats_update(&f->stats, 0x0, stats.pkts, stats.drops, 0x0,
1039 			  FLOW_ACTION_HW_STATS_IMMEDIATE);
1040 	return 0;
1041 }
1042 EXPORT_SYMBOL_GPL(ocelot_cls_flower_stats);
1043