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