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