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