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