1 // SPDX-License-Identifier: GPL-2.0+
2 /* Microchip VCAP API
3  *
4  * Copyright (c) 2022 Microchip Technology Inc. and its subsidiaries.
5  */
6 
7 #include <net/tc_act/tc_gate.h>
8 #include <net/tcp.h>
9 
10 #include "sparx5_tc.h"
11 #include "vcap_api.h"
12 #include "vcap_api_client.h"
13 #include "vcap_tc.h"
14 #include "sparx5_main.h"
15 #include "sparx5_vcap_impl.h"
16 
17 #define SPX5_MAX_RULE_SIZE 13 /* allows X1, X2, X4, X6 and X12 rules */
18 
19 /* Collect keysets and type ids for multiple rules per size */
20 struct sparx5_wildcard_rule {
21 	bool selected;
22 	u8 value;
23 	u8 mask;
24 	enum vcap_keyfield_set keyset;
25 };
26 
27 struct sparx5_multiple_rules {
28 	struct sparx5_wildcard_rule rule[SPX5_MAX_RULE_SIZE];
29 };
30 
31 struct sparx5_tc_flower_template {
32 	struct list_head list; /* for insertion in the list of templates */
33 	int cid; /* chain id */
34 	enum vcap_keyfield_set orig; /* keyset used before the template */
35 	enum vcap_keyfield_set keyset; /* new keyset used by template */
36 	u16 l3_proto; /* protocol specified in the template */
37 };
38 
39 /* SparX-5 VCAP fragment types:
40  * 0 = no fragment, 1 = initial fragment,
41  * 2 = suspicious fragment, 3 = valid follow-up fragment
42  */
43 enum {                   /* key / mask */
44 	FRAG_NOT   = 0x03, /* 0 / 3 */
45 	FRAG_SOME  = 0x11, /* 1 / 1 */
46 	FRAG_FIRST = 0x13, /* 1 / 3 */
47 	FRAG_LATER = 0x33, /* 3 / 3 */
48 	FRAG_INVAL = 0xff, /* invalid */
49 };
50 
51 /* Flower fragment flag to VCAP fragment type mapping */
52 static const u8 sparx5_vcap_frag_map[4][4] = {		  /* is_frag */
53 	{ FRAG_INVAL, FRAG_INVAL, FRAG_INVAL, FRAG_FIRST }, /* 0/0 */
54 	{ FRAG_NOT,   FRAG_NOT,   FRAG_INVAL, FRAG_INVAL }, /* 0/1 */
55 	{ FRAG_INVAL, FRAG_INVAL, FRAG_INVAL, FRAG_INVAL }, /* 1/0 */
56 	{ FRAG_SOME,  FRAG_LATER, FRAG_INVAL, FRAG_FIRST }  /* 1/1 */
57 	/* 0/0	      0/1	  1/0	      1/1 <-- first_frag */
58 };
59 
60 static int
sparx5_tc_flower_es0_tpid(struct vcap_tc_flower_parse_usage * st)61 sparx5_tc_flower_es0_tpid(struct vcap_tc_flower_parse_usage *st)
62 {
63 	int err = 0;
64 
65 	switch (st->tpid) {
66 	case ETH_P_8021Q:
67 		err = vcap_rule_add_key_u32(st->vrule,
68 					    VCAP_KF_8021Q_TPID,
69 					    SPX5_TPID_SEL_8100, ~0);
70 		break;
71 	case ETH_P_8021AD:
72 		err = vcap_rule_add_key_u32(st->vrule,
73 					    VCAP_KF_8021Q_TPID,
74 					    SPX5_TPID_SEL_88A8, ~0);
75 		break;
76 	default:
77 		NL_SET_ERR_MSG_MOD(st->fco->common.extack,
78 				   "Invalid vlan proto");
79 		err = -EINVAL;
80 		break;
81 	}
82 	return err;
83 }
84 
85 static int
sparx5_tc_flower_handler_basic_usage(struct vcap_tc_flower_parse_usage * st)86 sparx5_tc_flower_handler_basic_usage(struct vcap_tc_flower_parse_usage *st)
87 {
88 	struct flow_match_basic mt;
89 	int err = 0;
90 
91 	flow_rule_match_basic(st->frule, &mt);
92 
93 	if (mt.mask->n_proto) {
94 		st->l3_proto = be16_to_cpu(mt.key->n_proto);
95 		if (!sparx5_vcap_is_known_etype(st->admin, st->l3_proto)) {
96 			err = vcap_rule_add_key_u32(st->vrule, VCAP_KF_ETYPE,
97 						    st->l3_proto, ~0);
98 			if (err)
99 				goto out;
100 		} else if (st->l3_proto == ETH_P_IP) {
101 			err = vcap_rule_add_key_bit(st->vrule, VCAP_KF_IP4_IS,
102 						    VCAP_BIT_1);
103 			if (err)
104 				goto out;
105 		} else if (st->l3_proto == ETH_P_IPV6) {
106 			err = vcap_rule_add_key_bit(st->vrule, VCAP_KF_IP4_IS,
107 						    VCAP_BIT_0);
108 			if (err)
109 				goto out;
110 			if (st->admin->vtype == VCAP_TYPE_IS0) {
111 				err = vcap_rule_add_key_bit(st->vrule,
112 							    VCAP_KF_IP_SNAP_IS,
113 							    VCAP_BIT_1);
114 				if (err)
115 					goto out;
116 			}
117 		}
118 	}
119 
120 	if (mt.mask->ip_proto) {
121 		st->l4_proto = mt.key->ip_proto;
122 		if (st->l4_proto == IPPROTO_TCP) {
123 			err = vcap_rule_add_key_bit(st->vrule,
124 						    VCAP_KF_TCP_IS,
125 						    VCAP_BIT_1);
126 			if (err)
127 				goto out;
128 		} else if (st->l4_proto == IPPROTO_UDP) {
129 			err = vcap_rule_add_key_bit(st->vrule,
130 						    VCAP_KF_TCP_IS,
131 						    VCAP_BIT_0);
132 			if (err)
133 				goto out;
134 			if (st->admin->vtype == VCAP_TYPE_IS0) {
135 				err = vcap_rule_add_key_bit(st->vrule,
136 							    VCAP_KF_TCP_UDP_IS,
137 							    VCAP_BIT_1);
138 				if (err)
139 					goto out;
140 			}
141 		} else {
142 			err = vcap_rule_add_key_u32(st->vrule,
143 						    VCAP_KF_L3_IP_PROTO,
144 						    st->l4_proto, ~0);
145 			if (err)
146 				goto out;
147 		}
148 	}
149 
150 	st->used_keys |= BIT_ULL(FLOW_DISSECTOR_KEY_BASIC);
151 
152 	return err;
153 
154 out:
155 	NL_SET_ERR_MSG_MOD(st->fco->common.extack, "ip_proto parse error");
156 	return err;
157 }
158 
159 static int
sparx5_tc_flower_handler_control_usage(struct vcap_tc_flower_parse_usage * st)160 sparx5_tc_flower_handler_control_usage(struct vcap_tc_flower_parse_usage *st)
161 {
162 	struct flow_match_control mt;
163 	u32 value, mask;
164 	int err = 0;
165 
166 	flow_rule_match_control(st->frule, &mt);
167 
168 	if (mt.mask->flags) {
169 		u8 is_frag_key = !!(mt.key->flags & FLOW_DIS_IS_FRAGMENT);
170 		u8 is_frag_mask = !!(mt.mask->flags & FLOW_DIS_IS_FRAGMENT);
171 		u8 is_frag_idx = (is_frag_key << 1) | is_frag_mask;
172 
173 		u8 first_frag_key = !!(mt.key->flags & FLOW_DIS_FIRST_FRAG);
174 		u8 first_frag_mask = !!(mt.mask->flags & FLOW_DIS_FIRST_FRAG);
175 		u8 first_frag_idx = (first_frag_key << 1) | first_frag_mask;
176 
177 		/* Lookup verdict based on the 2 + 2 input bits */
178 		u8 vdt = sparx5_vcap_frag_map[is_frag_idx][first_frag_idx];
179 
180 		if (vdt == FRAG_INVAL) {
181 			NL_SET_ERR_MSG_MOD(st->fco->common.extack,
182 					   "Match on invalid fragment flag combination");
183 			return -EINVAL;
184 		}
185 
186 		/* Extract VCAP fragment key and mask from verdict */
187 		value = (vdt >> 4) & 0x3;
188 		mask = vdt & 0x3;
189 
190 		err = vcap_rule_add_key_u32(st->vrule,
191 					    VCAP_KF_L3_FRAGMENT_TYPE,
192 					    value, mask);
193 		if (err)
194 			goto out;
195 	}
196 
197 	st->used_keys |= BIT_ULL(FLOW_DISSECTOR_KEY_CONTROL);
198 
199 	return err;
200 
201 out:
202 	NL_SET_ERR_MSG_MOD(st->fco->common.extack, "ip_frag parse error");
203 	return err;
204 }
205 
206 static int
sparx5_tc_flower_handler_cvlan_usage(struct vcap_tc_flower_parse_usage * st)207 sparx5_tc_flower_handler_cvlan_usage(struct vcap_tc_flower_parse_usage *st)
208 {
209 	if (st->admin->vtype != VCAP_TYPE_IS0) {
210 		NL_SET_ERR_MSG_MOD(st->fco->common.extack,
211 				   "cvlan not supported in this VCAP");
212 		return -EINVAL;
213 	}
214 
215 	return vcap_tc_flower_handler_cvlan_usage(st);
216 }
217 
218 static int
sparx5_tc_flower_handler_vlan_usage(struct vcap_tc_flower_parse_usage * st)219 sparx5_tc_flower_handler_vlan_usage(struct vcap_tc_flower_parse_usage *st)
220 {
221 	enum vcap_key_field vid_key = VCAP_KF_8021Q_VID_CLS;
222 	enum vcap_key_field pcp_key = VCAP_KF_8021Q_PCP_CLS;
223 	int err;
224 
225 	if (st->admin->vtype == VCAP_TYPE_IS0) {
226 		vid_key = VCAP_KF_8021Q_VID0;
227 		pcp_key = VCAP_KF_8021Q_PCP0;
228 	}
229 
230 	err = vcap_tc_flower_handler_vlan_usage(st, vid_key, pcp_key);
231 	if (err)
232 		return err;
233 
234 	if (st->admin->vtype == VCAP_TYPE_ES0 && st->tpid)
235 		err = sparx5_tc_flower_es0_tpid(st);
236 
237 	return err;
238 }
239 
240 static int (*sparx5_tc_flower_usage_handlers[])(struct vcap_tc_flower_parse_usage *st) = {
241 	[FLOW_DISSECTOR_KEY_ETH_ADDRS] = vcap_tc_flower_handler_ethaddr_usage,
242 	[FLOW_DISSECTOR_KEY_IPV4_ADDRS] = vcap_tc_flower_handler_ipv4_usage,
243 	[FLOW_DISSECTOR_KEY_IPV6_ADDRS] = vcap_tc_flower_handler_ipv6_usage,
244 	[FLOW_DISSECTOR_KEY_CONTROL] = sparx5_tc_flower_handler_control_usage,
245 	[FLOW_DISSECTOR_KEY_PORTS] = vcap_tc_flower_handler_portnum_usage,
246 	[FLOW_DISSECTOR_KEY_BASIC] = sparx5_tc_flower_handler_basic_usage,
247 	[FLOW_DISSECTOR_KEY_CVLAN] = sparx5_tc_flower_handler_cvlan_usage,
248 	[FLOW_DISSECTOR_KEY_VLAN] = sparx5_tc_flower_handler_vlan_usage,
249 	[FLOW_DISSECTOR_KEY_TCP] = vcap_tc_flower_handler_tcp_usage,
250 	[FLOW_DISSECTOR_KEY_ARP] = vcap_tc_flower_handler_arp_usage,
251 	[FLOW_DISSECTOR_KEY_IP] = vcap_tc_flower_handler_ip_usage,
252 };
253 
sparx5_tc_use_dissectors(struct vcap_tc_flower_parse_usage * st,struct vcap_admin * admin,struct vcap_rule * vrule)254 static int sparx5_tc_use_dissectors(struct vcap_tc_flower_parse_usage *st,
255 				    struct vcap_admin *admin,
256 				    struct vcap_rule *vrule)
257 {
258 	int idx, err = 0;
259 
260 	for (idx = 0; idx < ARRAY_SIZE(sparx5_tc_flower_usage_handlers); ++idx) {
261 		if (!flow_rule_match_key(st->frule, idx))
262 			continue;
263 		if (!sparx5_tc_flower_usage_handlers[idx])
264 			continue;
265 		err = sparx5_tc_flower_usage_handlers[idx](st);
266 		if (err)
267 			return err;
268 	}
269 
270 	if (st->frule->match.dissector->used_keys ^ st->used_keys) {
271 		NL_SET_ERR_MSG_MOD(st->fco->common.extack,
272 				   "Unsupported match item");
273 		return -ENOENT;
274 	}
275 
276 	return err;
277 }
278 
sparx5_tc_flower_action_check(struct vcap_control * vctrl,struct net_device * ndev,struct flow_cls_offload * fco,bool ingress)279 static int sparx5_tc_flower_action_check(struct vcap_control *vctrl,
280 					 struct net_device *ndev,
281 					 struct flow_cls_offload *fco,
282 					 bool ingress)
283 {
284 	struct flow_rule *rule = flow_cls_offload_flow_rule(fco);
285 	struct flow_action_entry *actent, *last_actent = NULL;
286 	struct flow_action *act = &rule->action;
287 	u64 action_mask = 0;
288 	int idx;
289 
290 	if (!flow_action_has_entries(act)) {
291 		NL_SET_ERR_MSG_MOD(fco->common.extack, "No actions");
292 		return -EINVAL;
293 	}
294 
295 	if (!flow_action_basic_hw_stats_check(act, fco->common.extack))
296 		return -EOPNOTSUPP;
297 
298 	flow_action_for_each(idx, actent, act) {
299 		if (action_mask & BIT(actent->id)) {
300 			NL_SET_ERR_MSG_MOD(fco->common.extack,
301 					   "More actions of the same type");
302 			return -EINVAL;
303 		}
304 		action_mask |= BIT(actent->id);
305 		last_actent = actent; /* Save last action for later check */
306 	}
307 
308 	/* Check if last action is a goto
309 	 * The last chain/lookup does not need to have a goto action
310 	 */
311 	if (last_actent->id == FLOW_ACTION_GOTO) {
312 		/* Check if the destination chain is in one of the VCAPs */
313 		if (!vcap_is_next_lookup(vctrl, fco->common.chain_index,
314 					 last_actent->chain_index)) {
315 			NL_SET_ERR_MSG_MOD(fco->common.extack,
316 					   "Invalid goto chain");
317 			return -EINVAL;
318 		}
319 	} else if (!vcap_is_last_chain(vctrl, fco->common.chain_index,
320 				       ingress)) {
321 		NL_SET_ERR_MSG_MOD(fco->common.extack,
322 				   "Last action must be 'goto'");
323 		return -EINVAL;
324 	}
325 
326 	/* Catch unsupported combinations of actions */
327 	if (action_mask & BIT(FLOW_ACTION_TRAP) &&
328 	    action_mask & BIT(FLOW_ACTION_ACCEPT)) {
329 		NL_SET_ERR_MSG_MOD(fco->common.extack,
330 				   "Cannot combine pass and trap action");
331 		return -EOPNOTSUPP;
332 	}
333 
334 	if (action_mask & BIT(FLOW_ACTION_VLAN_PUSH) &&
335 	    action_mask & BIT(FLOW_ACTION_VLAN_POP)) {
336 		NL_SET_ERR_MSG_MOD(fco->common.extack,
337 				   "Cannot combine vlan push and pop action");
338 		return -EOPNOTSUPP;
339 	}
340 
341 	if (action_mask & BIT(FLOW_ACTION_VLAN_PUSH) &&
342 	    action_mask & BIT(FLOW_ACTION_VLAN_MANGLE)) {
343 		NL_SET_ERR_MSG_MOD(fco->common.extack,
344 				   "Cannot combine vlan push and modify action");
345 		return -EOPNOTSUPP;
346 	}
347 
348 	if (action_mask & BIT(FLOW_ACTION_VLAN_POP) &&
349 	    action_mask & BIT(FLOW_ACTION_VLAN_MANGLE)) {
350 		NL_SET_ERR_MSG_MOD(fco->common.extack,
351 				   "Cannot combine vlan pop and modify action");
352 		return -EOPNOTSUPP;
353 	}
354 
355 	return 0;
356 }
357 
358 /* Add a rule counter action */
sparx5_tc_add_rule_counter(struct vcap_admin * admin,struct vcap_rule * vrule)359 static int sparx5_tc_add_rule_counter(struct vcap_admin *admin,
360 				      struct vcap_rule *vrule)
361 {
362 	int err;
363 
364 	switch (admin->vtype) {
365 	case VCAP_TYPE_IS0:
366 		break;
367 	case VCAP_TYPE_ES0:
368 		err = vcap_rule_mod_action_u32(vrule, VCAP_AF_ESDX,
369 					       vrule->id);
370 		if (err)
371 			return err;
372 		vcap_rule_set_counter_id(vrule, vrule->id);
373 		break;
374 	case VCAP_TYPE_IS2:
375 	case VCAP_TYPE_ES2:
376 		err = vcap_rule_mod_action_u32(vrule, VCAP_AF_CNT_ID,
377 					       vrule->id);
378 		if (err)
379 			return err;
380 		vcap_rule_set_counter_id(vrule, vrule->id);
381 		break;
382 	default:
383 		pr_err("%s:%d: vcap type: %d not supported\n",
384 		       __func__, __LINE__, admin->vtype);
385 		break;
386 	}
387 	return 0;
388 }
389 
390 /* Collect all port keysets and apply the first of them, possibly wildcarded */
sparx5_tc_select_protocol_keyset(struct net_device * ndev,struct vcap_rule * vrule,struct vcap_admin * admin,u16 l3_proto,struct sparx5_multiple_rules * multi)391 static int sparx5_tc_select_protocol_keyset(struct net_device *ndev,
392 					    struct vcap_rule *vrule,
393 					    struct vcap_admin *admin,
394 					    u16 l3_proto,
395 					    struct sparx5_multiple_rules *multi)
396 {
397 	struct sparx5_port *port = netdev_priv(ndev);
398 	struct vcap_keyset_list portkeysetlist = {};
399 	enum vcap_keyfield_set portkeysets[10] = {};
400 	struct vcap_keyset_list matches = {};
401 	enum vcap_keyfield_set keysets[10];
402 	int idx, jdx, err = 0, count = 0;
403 	struct sparx5_wildcard_rule *mru;
404 	const struct vcap_set *kinfo;
405 	struct vcap_control *vctrl;
406 
407 	vctrl = port->sparx5->vcap_ctrl;
408 
409 	/* Find the keysets that the rule can use */
410 	matches.keysets = keysets;
411 	matches.max = ARRAY_SIZE(keysets);
412 	if (!vcap_rule_find_keysets(vrule, &matches))
413 		return -EINVAL;
414 
415 	/* Find the keysets that the port configuration supports */
416 	portkeysetlist.max = ARRAY_SIZE(portkeysets);
417 	portkeysetlist.keysets = portkeysets;
418 	err = sparx5_vcap_get_port_keyset(ndev,
419 					  admin, vrule->vcap_chain_id,
420 					  l3_proto,
421 					  &portkeysetlist);
422 	if (err)
423 		return err;
424 
425 	/* Find the intersection of the two sets of keyset */
426 	for (idx = 0; idx < portkeysetlist.cnt; ++idx) {
427 		kinfo = vcap_keyfieldset(vctrl, admin->vtype,
428 					 portkeysetlist.keysets[idx]);
429 		if (!kinfo)
430 			continue;
431 
432 		/* Find a port keyset that matches the required keys
433 		 * If there are multiple keysets then compose a type id mask
434 		 */
435 		for (jdx = 0; jdx < matches.cnt; ++jdx) {
436 			if (portkeysetlist.keysets[idx] != matches.keysets[jdx])
437 				continue;
438 
439 			mru = &multi->rule[kinfo->sw_per_item];
440 			if (!mru->selected) {
441 				mru->selected = true;
442 				mru->keyset = portkeysetlist.keysets[idx];
443 				mru->value = kinfo->type_id;
444 			}
445 			mru->value &= kinfo->type_id;
446 			mru->mask |= kinfo->type_id;
447 			++count;
448 		}
449 	}
450 	if (count == 0)
451 		return -EPROTO;
452 
453 	if (l3_proto == ETH_P_ALL && count < portkeysetlist.cnt)
454 		return -ENOENT;
455 
456 	for (idx = 0; idx < SPX5_MAX_RULE_SIZE; ++idx) {
457 		mru = &multi->rule[idx];
458 		if (!mru->selected)
459 			continue;
460 
461 		/* Align the mask to the combined value */
462 		mru->mask ^= mru->value;
463 	}
464 
465 	/* Set the chosen keyset on the rule and set a wildcarded type if there
466 	 * are more than one keyset
467 	 */
468 	for (idx = 0; idx < SPX5_MAX_RULE_SIZE; ++idx) {
469 		mru = &multi->rule[idx];
470 		if (!mru->selected)
471 			continue;
472 
473 		vcap_set_rule_set_keyset(vrule, mru->keyset);
474 		if (count > 1)
475 			/* Some keysets do not have a type field */
476 			vcap_rule_mod_key_u32(vrule, VCAP_KF_TYPE,
477 					      mru->value,
478 					      ~mru->mask);
479 		mru->selected = false; /* mark as done */
480 		break; /* Stop here and add more rules later */
481 	}
482 	return err;
483 }
484 
sparx5_tc_add_rule_copy(struct vcap_control * vctrl,struct flow_cls_offload * fco,struct vcap_rule * erule,struct vcap_admin * admin,struct sparx5_wildcard_rule * rule)485 static int sparx5_tc_add_rule_copy(struct vcap_control *vctrl,
486 				   struct flow_cls_offload *fco,
487 				   struct vcap_rule *erule,
488 				   struct vcap_admin *admin,
489 				   struct sparx5_wildcard_rule *rule)
490 {
491 	enum vcap_key_field keylist[] = {
492 		VCAP_KF_IF_IGR_PORT_MASK,
493 		VCAP_KF_IF_IGR_PORT_MASK_SEL,
494 		VCAP_KF_IF_IGR_PORT_MASK_RNG,
495 		VCAP_KF_LOOKUP_FIRST_IS,
496 		VCAP_KF_TYPE,
497 	};
498 	struct vcap_rule *vrule;
499 	int err;
500 
501 	/* Add an extra rule with a special user and the new keyset */
502 	erule->user = VCAP_USER_TC_EXTRA;
503 	vrule = vcap_copy_rule(erule);
504 	if (IS_ERR(vrule))
505 		return PTR_ERR(vrule);
506 
507 	/* Link the new rule to the existing rule with the cookie */
508 	vrule->cookie = erule->cookie;
509 	vcap_filter_rule_keys(vrule, keylist, ARRAY_SIZE(keylist), true);
510 	err = vcap_set_rule_set_keyset(vrule, rule->keyset);
511 	if (err) {
512 		pr_err("%s:%d: could not set keyset %s in rule: %u\n",
513 		       __func__, __LINE__,
514 		       vcap_keyset_name(vctrl, rule->keyset),
515 		       vrule->id);
516 		goto out;
517 	}
518 
519 	/* Some keysets do not have a type field, so ignore return value */
520 	vcap_rule_mod_key_u32(vrule, VCAP_KF_TYPE, rule->value, ~rule->mask);
521 
522 	err = vcap_set_rule_set_actionset(vrule, erule->actionset);
523 	if (err)
524 		goto out;
525 
526 	err = sparx5_tc_add_rule_counter(admin, vrule);
527 	if (err)
528 		goto out;
529 
530 	err = vcap_val_rule(vrule, ETH_P_ALL);
531 	if (err) {
532 		pr_err("%s:%d: could not validate rule: %u\n",
533 		       __func__, __LINE__, vrule->id);
534 		vcap_set_tc_exterr(fco, vrule);
535 		goto out;
536 	}
537 	err = vcap_add_rule(vrule);
538 	if (err) {
539 		pr_err("%s:%d: could not add rule: %u\n",
540 		       __func__, __LINE__, vrule->id);
541 		goto out;
542 	}
543 out:
544 	vcap_free_rule(vrule);
545 	return err;
546 }
547 
sparx5_tc_add_remaining_rules(struct vcap_control * vctrl,struct flow_cls_offload * fco,struct vcap_rule * erule,struct vcap_admin * admin,struct sparx5_multiple_rules * multi)548 static int sparx5_tc_add_remaining_rules(struct vcap_control *vctrl,
549 					 struct flow_cls_offload *fco,
550 					 struct vcap_rule *erule,
551 					 struct vcap_admin *admin,
552 					 struct sparx5_multiple_rules *multi)
553 {
554 	int idx, err = 0;
555 
556 	for (idx = 0; idx < SPX5_MAX_RULE_SIZE; ++idx) {
557 		if (!multi->rule[idx].selected)
558 			continue;
559 
560 		err = sparx5_tc_add_rule_copy(vctrl, fco, erule, admin,
561 					      &multi->rule[idx]);
562 		if (err)
563 			break;
564 	}
565 	return err;
566 }
567 
568 /* Add the actionset that is the default for the VCAP type */
sparx5_tc_set_actionset(struct vcap_admin * admin,struct vcap_rule * vrule)569 static int sparx5_tc_set_actionset(struct vcap_admin *admin,
570 				   struct vcap_rule *vrule)
571 {
572 	enum vcap_actionfield_set aset;
573 	int err = 0;
574 
575 	switch (admin->vtype) {
576 	case VCAP_TYPE_IS0:
577 		aset = VCAP_AFS_CLASSIFICATION;
578 		break;
579 	case VCAP_TYPE_IS2:
580 		aset = VCAP_AFS_BASE_TYPE;
581 		break;
582 	case VCAP_TYPE_ES0:
583 		aset = VCAP_AFS_ES0;
584 		break;
585 	case VCAP_TYPE_ES2:
586 		aset = VCAP_AFS_BASE_TYPE;
587 		break;
588 	default:
589 		pr_err("%s:%d: %s\n", __func__, __LINE__, "Invalid VCAP type");
590 		return -EINVAL;
591 	}
592 	/* Do not overwrite any current actionset */
593 	if (vrule->actionset == VCAP_AFS_NO_VALUE)
594 		err = vcap_set_rule_set_actionset(vrule, aset);
595 	return err;
596 }
597 
598 /* Add the VCAP key to match on for a rule target value */
sparx5_tc_add_rule_link_target(struct vcap_admin * admin,struct vcap_rule * vrule,int target_cid)599 static int sparx5_tc_add_rule_link_target(struct vcap_admin *admin,
600 					  struct vcap_rule *vrule,
601 					  int target_cid)
602 {
603 	int link_val = target_cid % VCAP_CID_LOOKUP_SIZE;
604 	int err;
605 
606 	if (!link_val)
607 		return 0;
608 
609 	switch (admin->vtype) {
610 	case VCAP_TYPE_IS0:
611 		/* Add NXT_IDX key for chaining rules between IS0 instances */
612 		err = vcap_rule_add_key_u32(vrule, VCAP_KF_LOOKUP_GEN_IDX_SEL,
613 					    1, /* enable */
614 					    ~0);
615 		if (err)
616 			return err;
617 		return vcap_rule_add_key_u32(vrule, VCAP_KF_LOOKUP_GEN_IDX,
618 					     link_val, /* target */
619 					     ~0);
620 	case VCAP_TYPE_IS2:
621 		/* Add PAG key for chaining rules from IS0 */
622 		return vcap_rule_add_key_u32(vrule, VCAP_KF_LOOKUP_PAG,
623 					     link_val, /* target */
624 					     ~0);
625 	case VCAP_TYPE_ES0:
626 	case VCAP_TYPE_ES2:
627 		/* Add ISDX key for chaining rules from IS0 */
628 		return vcap_rule_add_key_u32(vrule, VCAP_KF_ISDX_CLS, link_val,
629 					     ~0);
630 	default:
631 		break;
632 	}
633 	return 0;
634 }
635 
636 /* Add the VCAP action that adds a target value to a rule */
sparx5_tc_add_rule_link(struct vcap_control * vctrl,struct vcap_admin * admin,struct vcap_rule * vrule,int from_cid,int to_cid)637 static int sparx5_tc_add_rule_link(struct vcap_control *vctrl,
638 				   struct vcap_admin *admin,
639 				   struct vcap_rule *vrule,
640 				   int from_cid, int to_cid)
641 {
642 	struct vcap_admin *to_admin = vcap_find_admin(vctrl, to_cid);
643 	int diff, err = 0;
644 
645 	if (!to_admin) {
646 		pr_err("%s:%d: unsupported chain direction: %d\n",
647 		       __func__, __LINE__, to_cid);
648 		return -EINVAL;
649 	}
650 
651 	diff = vcap_chain_offset(vctrl, from_cid, to_cid);
652 	if (!diff)
653 		return 0;
654 
655 	if (admin->vtype == VCAP_TYPE_IS0 &&
656 	    to_admin->vtype == VCAP_TYPE_IS0) {
657 		/* Between IS0 instances the G_IDX value is used */
658 		err = vcap_rule_add_action_u32(vrule, VCAP_AF_NXT_IDX, diff);
659 		if (err)
660 			goto out;
661 		err = vcap_rule_add_action_u32(vrule, VCAP_AF_NXT_IDX_CTRL,
662 					       1); /* Replace */
663 		if (err)
664 			goto out;
665 	} else if (admin->vtype == VCAP_TYPE_IS0 &&
666 		   to_admin->vtype == VCAP_TYPE_IS2) {
667 		/* Between IS0 and IS2 the PAG value is used */
668 		err = vcap_rule_add_action_u32(vrule, VCAP_AF_PAG_VAL, diff);
669 		if (err)
670 			goto out;
671 		err = vcap_rule_add_action_u32(vrule,
672 					       VCAP_AF_PAG_OVERRIDE_MASK,
673 					       0xff);
674 		if (err)
675 			goto out;
676 	} else if (admin->vtype == VCAP_TYPE_IS0 &&
677 		   (to_admin->vtype == VCAP_TYPE_ES0 ||
678 		    to_admin->vtype == VCAP_TYPE_ES2)) {
679 		/* Between IS0 and ES0/ES2 the ISDX value is used */
680 		err = vcap_rule_add_action_u32(vrule, VCAP_AF_ISDX_VAL,
681 					       diff);
682 		if (err)
683 			goto out;
684 		err = vcap_rule_add_action_bit(vrule,
685 					       VCAP_AF_ISDX_ADD_REPLACE_SEL,
686 					       VCAP_BIT_1);
687 		if (err)
688 			goto out;
689 	} else {
690 		pr_err("%s:%d: unsupported chain destination: %d\n",
691 		       __func__, __LINE__, to_cid);
692 		err = -EOPNOTSUPP;
693 	}
694 out:
695 	return err;
696 }
697 
sparx5_tc_flower_parse_act_gate(struct sparx5_psfp_sg * sg,struct flow_action_entry * act,struct netlink_ext_ack * extack)698 static int sparx5_tc_flower_parse_act_gate(struct sparx5_psfp_sg *sg,
699 					   struct flow_action_entry *act,
700 					   struct netlink_ext_ack *extack)
701 {
702 	int i;
703 
704 	if (act->gate.prio < -1 || act->gate.prio > SPX5_PSFP_SG_MAX_IPV) {
705 		NL_SET_ERR_MSG_MOD(extack, "Invalid gate priority");
706 		return -EINVAL;
707 	}
708 
709 	if (act->gate.cycletime < SPX5_PSFP_SG_MIN_CYCLE_TIME_NS ||
710 	    act->gate.cycletime > SPX5_PSFP_SG_MAX_CYCLE_TIME_NS) {
711 		NL_SET_ERR_MSG_MOD(extack, "Invalid gate cycletime");
712 		return -EINVAL;
713 	}
714 
715 	if (act->gate.cycletimeext > SPX5_PSFP_SG_MAX_CYCLE_TIME_NS) {
716 		NL_SET_ERR_MSG_MOD(extack, "Invalid gate cycletimeext");
717 		return -EINVAL;
718 	}
719 
720 	if (act->gate.num_entries >= SPX5_PSFP_GCE_CNT) {
721 		NL_SET_ERR_MSG_MOD(extack, "Invalid number of gate entries");
722 		return -EINVAL;
723 	}
724 
725 	sg->gate_state = true;
726 	sg->ipv = act->gate.prio;
727 	sg->num_entries = act->gate.num_entries;
728 	sg->cycletime = act->gate.cycletime;
729 	sg->cycletimeext = act->gate.cycletimeext;
730 
731 	for (i = 0; i < sg->num_entries; i++) {
732 		sg->gce[i].gate_state = !!act->gate.entries[i].gate_state;
733 		sg->gce[i].interval = act->gate.entries[i].interval;
734 		sg->gce[i].ipv = act->gate.entries[i].ipv;
735 		sg->gce[i].maxoctets = act->gate.entries[i].maxoctets;
736 	}
737 
738 	return 0;
739 }
740 
sparx5_tc_flower_parse_act_police(struct sparx5_policer * pol,struct flow_action_entry * act,struct netlink_ext_ack * extack)741 static int sparx5_tc_flower_parse_act_police(struct sparx5_policer *pol,
742 					     struct flow_action_entry *act,
743 					     struct netlink_ext_ack *extack)
744 {
745 	pol->type = SPX5_POL_SERVICE;
746 	pol->rate = div_u64(act->police.rate_bytes_ps, 1000) * 8;
747 	pol->burst = act->police.burst;
748 	pol->idx = act->hw_index;
749 
750 	/* rate is now in kbit */
751 	if (pol->rate > DIV_ROUND_UP(SPX5_SDLB_GROUP_RATE_MAX, 1000)) {
752 		NL_SET_ERR_MSG_MOD(extack, "Maximum rate exceeded");
753 		return -EINVAL;
754 	}
755 
756 	if (act->police.exceed.act_id != FLOW_ACTION_DROP) {
757 		NL_SET_ERR_MSG_MOD(extack, "Offload not supported when exceed action is not drop");
758 		return -EOPNOTSUPP;
759 	}
760 
761 	if (act->police.notexceed.act_id != FLOW_ACTION_PIPE &&
762 	    act->police.notexceed.act_id != FLOW_ACTION_ACCEPT) {
763 		NL_SET_ERR_MSG_MOD(extack, "Offload not supported when conform action is not pipe or ok");
764 		return -EOPNOTSUPP;
765 	}
766 
767 	return 0;
768 }
769 
sparx5_tc_flower_psfp_setup(struct sparx5 * sparx5,struct vcap_rule * vrule,int sg_idx,int pol_idx,struct sparx5_psfp_sg * sg,struct sparx5_psfp_fm * fm,struct sparx5_psfp_sf * sf)770 static int sparx5_tc_flower_psfp_setup(struct sparx5 *sparx5,
771 				       struct vcap_rule *vrule, int sg_idx,
772 				       int pol_idx, struct sparx5_psfp_sg *sg,
773 				       struct sparx5_psfp_fm *fm,
774 				       struct sparx5_psfp_sf *sf)
775 {
776 	u32 psfp_sfid = 0, psfp_fmid = 0, psfp_sgid = 0;
777 	int ret;
778 
779 	/* Must always have a stream gate - max sdu (filter option) is evaluated
780 	 * after frames have passed the gate, so in case of only a policer, we
781 	 * allocate a stream gate that is always open.
782 	 */
783 	if (sg_idx < 0) {
784 		sg_idx = sparx5_pool_idx_to_id(SPX5_PSFP_SG_OPEN);
785 		sg->ipv = 0; /* Disabled */
786 		sg->cycletime = SPX5_PSFP_SG_CYCLE_TIME_DEFAULT;
787 		sg->num_entries = 1;
788 		sg->gate_state = 1; /* Open */
789 		sg->gate_enabled = 1;
790 		sg->gce[0].gate_state = 1;
791 		sg->gce[0].interval = SPX5_PSFP_SG_CYCLE_TIME_DEFAULT;
792 		sg->gce[0].ipv = 0;
793 		sg->gce[0].maxoctets = 0; /* Disabled */
794 	}
795 
796 	ret = sparx5_psfp_sg_add(sparx5, sg_idx, sg, &psfp_sgid);
797 	if (ret < 0)
798 		return ret;
799 
800 	if (pol_idx >= 0) {
801 		/* Add new flow-meter */
802 		ret = sparx5_psfp_fm_add(sparx5, pol_idx, fm, &psfp_fmid);
803 		if (ret < 0)
804 			return ret;
805 	}
806 
807 	/* Map stream filter to stream gate */
808 	sf->sgid = psfp_sgid;
809 
810 	/* Add new stream-filter and map it to a steam gate */
811 	ret = sparx5_psfp_sf_add(sparx5, sf, &psfp_sfid);
812 	if (ret < 0)
813 		return ret;
814 
815 	/* Streams are classified by ISDX - map ISDX 1:1 to sfid for now. */
816 	sparx5_isdx_conf_set(sparx5, psfp_sfid, psfp_sfid, psfp_fmid);
817 
818 	ret = vcap_rule_add_action_bit(vrule, VCAP_AF_ISDX_ADD_REPLACE_SEL,
819 				       VCAP_BIT_1);
820 	if (ret)
821 		return ret;
822 
823 	ret = vcap_rule_add_action_u32(vrule, VCAP_AF_ISDX_VAL, psfp_sfid);
824 	if (ret)
825 		return ret;
826 
827 	return 0;
828 }
829 
830 /* Handle the action trap for a VCAP rule */
sparx5_tc_action_trap(struct vcap_admin * admin,struct vcap_rule * vrule,struct flow_cls_offload * fco)831 static int sparx5_tc_action_trap(struct vcap_admin *admin,
832 				 struct vcap_rule *vrule,
833 				 struct flow_cls_offload *fco)
834 {
835 	int err = 0;
836 
837 	switch (admin->vtype) {
838 	case VCAP_TYPE_IS2:
839 		err = vcap_rule_add_action_bit(vrule,
840 					       VCAP_AF_CPU_COPY_ENA,
841 					       VCAP_BIT_1);
842 		if (err)
843 			break;
844 		err = vcap_rule_add_action_u32(vrule,
845 					       VCAP_AF_CPU_QUEUE_NUM, 0);
846 		if (err)
847 			break;
848 		err = vcap_rule_add_action_u32(vrule,
849 					       VCAP_AF_MASK_MODE,
850 					       SPX5_PMM_REPLACE_ALL);
851 		break;
852 	case VCAP_TYPE_ES0:
853 		err = vcap_rule_add_action_u32(vrule,
854 					       VCAP_AF_FWD_SEL,
855 					       SPX5_FWSEL_REDIRECT_TO_LOOPBACK);
856 		break;
857 	case VCAP_TYPE_ES2:
858 		err = vcap_rule_add_action_bit(vrule,
859 					       VCAP_AF_CPU_COPY_ENA,
860 					       VCAP_BIT_1);
861 		if (err)
862 			break;
863 		err = vcap_rule_add_action_u32(vrule,
864 					       VCAP_AF_CPU_QUEUE_NUM, 0);
865 		break;
866 	default:
867 		NL_SET_ERR_MSG_MOD(fco->common.extack,
868 				   "Trap action not supported in this VCAP");
869 		err = -EOPNOTSUPP;
870 		break;
871 	}
872 	return err;
873 }
874 
sparx5_tc_action_vlan_pop(struct vcap_admin * admin,struct vcap_rule * vrule,struct flow_cls_offload * fco,u16 tpid)875 static int sparx5_tc_action_vlan_pop(struct vcap_admin *admin,
876 				     struct vcap_rule *vrule,
877 				     struct flow_cls_offload *fco,
878 				     u16 tpid)
879 {
880 	int err = 0;
881 
882 	switch (admin->vtype) {
883 	case VCAP_TYPE_ES0:
884 		break;
885 	default:
886 		NL_SET_ERR_MSG_MOD(fco->common.extack,
887 				   "VLAN pop action not supported in this VCAP");
888 		return -EOPNOTSUPP;
889 	}
890 
891 	switch (tpid) {
892 	case ETH_P_8021Q:
893 	case ETH_P_8021AD:
894 		err = vcap_rule_add_action_u32(vrule,
895 					       VCAP_AF_PUSH_OUTER_TAG,
896 					       SPX5_OTAG_UNTAG);
897 		break;
898 	default:
899 		NL_SET_ERR_MSG_MOD(fco->common.extack,
900 				   "Invalid vlan proto");
901 		err = -EINVAL;
902 	}
903 	return err;
904 }
905 
sparx5_tc_action_vlan_modify(struct vcap_admin * admin,struct vcap_rule * vrule,struct flow_cls_offload * fco,struct flow_action_entry * act,u16 tpid)906 static int sparx5_tc_action_vlan_modify(struct vcap_admin *admin,
907 					struct vcap_rule *vrule,
908 					struct flow_cls_offload *fco,
909 					struct flow_action_entry *act,
910 					u16 tpid)
911 {
912 	int err = 0;
913 
914 	switch (admin->vtype) {
915 	case VCAP_TYPE_ES0:
916 		err = vcap_rule_add_action_u32(vrule,
917 					       VCAP_AF_PUSH_OUTER_TAG,
918 					       SPX5_OTAG_TAG_A);
919 		if (err)
920 			return err;
921 		break;
922 	default:
923 		NL_SET_ERR_MSG_MOD(fco->common.extack,
924 				   "VLAN modify action not supported in this VCAP");
925 		return -EOPNOTSUPP;
926 	}
927 
928 	switch (tpid) {
929 	case ETH_P_8021Q:
930 		err = vcap_rule_add_action_u32(vrule,
931 					       VCAP_AF_TAG_A_TPID_SEL,
932 					       SPX5_TPID_A_8100);
933 		break;
934 	case ETH_P_8021AD:
935 		err = vcap_rule_add_action_u32(vrule,
936 					       VCAP_AF_TAG_A_TPID_SEL,
937 					       SPX5_TPID_A_88A8);
938 		break;
939 	default:
940 		NL_SET_ERR_MSG_MOD(fco->common.extack,
941 				   "Invalid vlan proto");
942 		err = -EINVAL;
943 	}
944 	if (err)
945 		return err;
946 
947 	err = vcap_rule_add_action_u32(vrule,
948 				       VCAP_AF_TAG_A_VID_SEL,
949 				       SPX5_VID_A_VAL);
950 	if (err)
951 		return err;
952 
953 	err = vcap_rule_add_action_u32(vrule,
954 				       VCAP_AF_VID_A_VAL,
955 				       act->vlan.vid);
956 	if (err)
957 		return err;
958 
959 	err = vcap_rule_add_action_u32(vrule,
960 				       VCAP_AF_TAG_A_PCP_SEL,
961 				       SPX5_PCP_A_VAL);
962 	if (err)
963 		return err;
964 
965 	err = vcap_rule_add_action_u32(vrule,
966 				       VCAP_AF_PCP_A_VAL,
967 				       act->vlan.prio);
968 	if (err)
969 		return err;
970 
971 	return vcap_rule_add_action_u32(vrule,
972 					VCAP_AF_TAG_A_DEI_SEL,
973 					SPX5_DEI_A_CLASSIFIED);
974 }
975 
sparx5_tc_action_vlan_push(struct vcap_admin * admin,struct vcap_rule * vrule,struct flow_cls_offload * fco,struct flow_action_entry * act,u16 tpid)976 static int sparx5_tc_action_vlan_push(struct vcap_admin *admin,
977 				      struct vcap_rule *vrule,
978 				      struct flow_cls_offload *fco,
979 				      struct flow_action_entry *act,
980 				      u16 tpid)
981 {
982 	u16 act_tpid = be16_to_cpu(act->vlan.proto);
983 	int err = 0;
984 
985 	switch (admin->vtype) {
986 	case VCAP_TYPE_ES0:
987 		break;
988 	default:
989 		NL_SET_ERR_MSG_MOD(fco->common.extack,
990 				   "VLAN push action not supported in this VCAP");
991 		return -EOPNOTSUPP;
992 	}
993 
994 	if (tpid == ETH_P_8021AD) {
995 		NL_SET_ERR_MSG_MOD(fco->common.extack,
996 				   "Cannot push on double tagged frames");
997 		return -EOPNOTSUPP;
998 	}
999 
1000 	err = sparx5_tc_action_vlan_modify(admin, vrule, fco, act, act_tpid);
1001 	if (err)
1002 		return err;
1003 
1004 	switch (act_tpid) {
1005 	case ETH_P_8021Q:
1006 		break;
1007 	case ETH_P_8021AD:
1008 		/* Push classified tag as inner tag */
1009 		err = vcap_rule_add_action_u32(vrule,
1010 					       VCAP_AF_PUSH_INNER_TAG,
1011 					       SPX5_ITAG_PUSH_B_TAG);
1012 		if (err)
1013 			break;
1014 		err = vcap_rule_add_action_u32(vrule,
1015 					       VCAP_AF_TAG_B_TPID_SEL,
1016 					       SPX5_TPID_B_CLASSIFIED);
1017 		break;
1018 	default:
1019 		NL_SET_ERR_MSG_MOD(fco->common.extack,
1020 				   "Invalid vlan proto");
1021 		err = -EINVAL;
1022 	}
1023 	return err;
1024 }
1025 
1026 /* Remove rule keys that may prevent templates from matching a keyset */
sparx5_tc_flower_simplify_rule(struct vcap_admin * admin,struct vcap_rule * vrule,u16 l3_proto)1027 static void sparx5_tc_flower_simplify_rule(struct vcap_admin *admin,
1028 					   struct vcap_rule *vrule,
1029 					   u16 l3_proto)
1030 {
1031 	switch (admin->vtype) {
1032 	case VCAP_TYPE_IS0:
1033 		vcap_rule_rem_key(vrule, VCAP_KF_ETYPE);
1034 		switch (l3_proto) {
1035 		case ETH_P_IP:
1036 			break;
1037 		case ETH_P_IPV6:
1038 			vcap_rule_rem_key(vrule, VCAP_KF_IP_SNAP_IS);
1039 			break;
1040 		default:
1041 			break;
1042 		}
1043 		break;
1044 	case VCAP_TYPE_ES2:
1045 		switch (l3_proto) {
1046 		case ETH_P_IP:
1047 			if (vrule->keyset == VCAP_KFS_IP4_OTHER)
1048 				vcap_rule_rem_key(vrule, VCAP_KF_TCP_IS);
1049 			break;
1050 		case ETH_P_IPV6:
1051 			if (vrule->keyset == VCAP_KFS_IP6_STD)
1052 				vcap_rule_rem_key(vrule, VCAP_KF_TCP_IS);
1053 			vcap_rule_rem_key(vrule, VCAP_KF_IP4_IS);
1054 			break;
1055 		default:
1056 			break;
1057 		}
1058 		break;
1059 	case VCAP_TYPE_IS2:
1060 		switch (l3_proto) {
1061 		case ETH_P_IP:
1062 		case ETH_P_IPV6:
1063 			vcap_rule_rem_key(vrule, VCAP_KF_IP4_IS);
1064 			break;
1065 		default:
1066 			break;
1067 		}
1068 		break;
1069 	default:
1070 		break;
1071 	}
1072 }
1073 
sparx5_tc_flower_use_template(struct net_device * ndev,struct flow_cls_offload * fco,struct vcap_admin * admin,struct vcap_rule * vrule)1074 static bool sparx5_tc_flower_use_template(struct net_device *ndev,
1075 					  struct flow_cls_offload *fco,
1076 					  struct vcap_admin *admin,
1077 					  struct vcap_rule *vrule)
1078 {
1079 	struct sparx5_port *port = netdev_priv(ndev);
1080 	struct sparx5_tc_flower_template *ftp;
1081 
1082 	list_for_each_entry(ftp, &port->tc_templates, list) {
1083 		if (ftp->cid != fco->common.chain_index)
1084 			continue;
1085 
1086 		vcap_set_rule_set_keyset(vrule, ftp->keyset);
1087 		sparx5_tc_flower_simplify_rule(admin, vrule, ftp->l3_proto);
1088 		return true;
1089 	}
1090 	return false;
1091 }
1092 
sparx5_tc_flower_replace(struct net_device * ndev,struct flow_cls_offload * fco,struct vcap_admin * admin,bool ingress)1093 static int sparx5_tc_flower_replace(struct net_device *ndev,
1094 				    struct flow_cls_offload *fco,
1095 				    struct vcap_admin *admin,
1096 				    bool ingress)
1097 {
1098 	struct sparx5_psfp_sf sf = { .max_sdu = SPX5_PSFP_SF_MAX_SDU };
1099 	struct netlink_ext_ack *extack = fco->common.extack;
1100 	int err, idx, tc_sg_idx = -1, tc_pol_idx = -1;
1101 	struct vcap_tc_flower_parse_usage state = {
1102 		.fco = fco,
1103 		.l3_proto = ETH_P_ALL,
1104 		.admin = admin,
1105 	};
1106 	struct sparx5_port *port = netdev_priv(ndev);
1107 	struct sparx5_multiple_rules multi = {};
1108 	struct sparx5 *sparx5 = port->sparx5;
1109 	struct sparx5_psfp_sg sg = { 0 };
1110 	struct sparx5_psfp_fm fm = { 0 };
1111 	struct flow_action_entry *act;
1112 	struct vcap_control *vctrl;
1113 	struct flow_rule *frule;
1114 	struct vcap_rule *vrule;
1115 
1116 	vctrl = port->sparx5->vcap_ctrl;
1117 
1118 	err = sparx5_tc_flower_action_check(vctrl, ndev, fco, ingress);
1119 	if (err)
1120 		return err;
1121 
1122 	vrule = vcap_alloc_rule(vctrl, ndev, fco->common.chain_index, VCAP_USER_TC,
1123 				fco->common.prio, 0);
1124 	if (IS_ERR(vrule))
1125 		return PTR_ERR(vrule);
1126 
1127 	vrule->cookie = fco->cookie;
1128 
1129 	state.vrule = vrule;
1130 	state.frule = flow_cls_offload_flow_rule(fco);
1131 	err = sparx5_tc_use_dissectors(&state, admin, vrule);
1132 	if (err)
1133 		goto out;
1134 
1135 	err = sparx5_tc_add_rule_counter(admin, vrule);
1136 	if (err)
1137 		goto out;
1138 
1139 	err = sparx5_tc_add_rule_link_target(admin, vrule,
1140 					     fco->common.chain_index);
1141 	if (err)
1142 		goto out;
1143 
1144 	frule = flow_cls_offload_flow_rule(fco);
1145 	flow_action_for_each(idx, act, &frule->action) {
1146 		switch (act->id) {
1147 		case FLOW_ACTION_GATE: {
1148 			err = sparx5_tc_flower_parse_act_gate(&sg, act, extack);
1149 			if (err < 0)
1150 				goto out;
1151 
1152 			tc_sg_idx = act->hw_index;
1153 
1154 			break;
1155 		}
1156 		case FLOW_ACTION_POLICE: {
1157 			err = sparx5_tc_flower_parse_act_police(&fm.pol, act,
1158 								extack);
1159 			if (err < 0)
1160 				goto out;
1161 
1162 			tc_pol_idx = fm.pol.idx;
1163 			sf.max_sdu = act->police.mtu;
1164 
1165 			break;
1166 		}
1167 		case FLOW_ACTION_TRAP:
1168 			err = sparx5_tc_action_trap(admin, vrule, fco);
1169 			if (err)
1170 				goto out;
1171 			break;
1172 		case FLOW_ACTION_ACCEPT:
1173 			err = sparx5_tc_set_actionset(admin, vrule);
1174 			if (err)
1175 				goto out;
1176 			break;
1177 		case FLOW_ACTION_GOTO:
1178 			err = sparx5_tc_set_actionset(admin, vrule);
1179 			if (err)
1180 				goto out;
1181 			sparx5_tc_add_rule_link(vctrl, admin, vrule,
1182 						fco->common.chain_index,
1183 						act->chain_index);
1184 			break;
1185 		case FLOW_ACTION_VLAN_POP:
1186 			err = sparx5_tc_action_vlan_pop(admin, vrule, fco,
1187 							state.tpid);
1188 			if (err)
1189 				goto out;
1190 			break;
1191 		case FLOW_ACTION_VLAN_PUSH:
1192 			err = sparx5_tc_action_vlan_push(admin, vrule, fco,
1193 							 act, state.tpid);
1194 			if (err)
1195 				goto out;
1196 			break;
1197 		case FLOW_ACTION_VLAN_MANGLE:
1198 			err = sparx5_tc_action_vlan_modify(admin, vrule, fco,
1199 							   act, state.tpid);
1200 			if (err)
1201 				goto out;
1202 			break;
1203 		default:
1204 			NL_SET_ERR_MSG_MOD(fco->common.extack,
1205 					   "Unsupported TC action");
1206 			err = -EOPNOTSUPP;
1207 			goto out;
1208 		}
1209 	}
1210 
1211 	/* Setup PSFP */
1212 	if (tc_sg_idx >= 0 || tc_pol_idx >= 0) {
1213 		err = sparx5_tc_flower_psfp_setup(sparx5, vrule, tc_sg_idx,
1214 						  tc_pol_idx, &sg, &fm, &sf);
1215 		if (err)
1216 			goto out;
1217 	}
1218 
1219 	if (!sparx5_tc_flower_use_template(ndev, fco, admin, vrule)) {
1220 		err = sparx5_tc_select_protocol_keyset(ndev, vrule, admin,
1221 						       state.l3_proto, &multi);
1222 		if (err) {
1223 			NL_SET_ERR_MSG_MOD(fco->common.extack,
1224 					   "No matching port keyset for filter protocol and keys");
1225 			goto out;
1226 		}
1227 	}
1228 
1229 	/* provide the l3 protocol to guide the keyset selection */
1230 	err = vcap_val_rule(vrule, state.l3_proto);
1231 	if (err) {
1232 		vcap_set_tc_exterr(fco, vrule);
1233 		goto out;
1234 	}
1235 	err = vcap_add_rule(vrule);
1236 	if (err)
1237 		NL_SET_ERR_MSG_MOD(fco->common.extack,
1238 				   "Could not add the filter");
1239 
1240 	if (state.l3_proto == ETH_P_ALL)
1241 		err = sparx5_tc_add_remaining_rules(vctrl, fco, vrule, admin,
1242 						    &multi);
1243 
1244 out:
1245 	vcap_free_rule(vrule);
1246 	return err;
1247 }
1248 
sparx5_tc_free_psfp_resources(struct sparx5 * sparx5,struct vcap_rule * vrule)1249 static void sparx5_tc_free_psfp_resources(struct sparx5 *sparx5,
1250 					  struct vcap_rule *vrule)
1251 {
1252 	struct vcap_client_actionfield *afield;
1253 	u32 isdx, sfid, sgid, fmid;
1254 
1255 	/* Check if VCAP_AF_ISDX_VAL action is set for this rule - and if
1256 	 * it is used for stream and/or flow-meter classification.
1257 	 */
1258 	afield = vcap_find_actionfield(vrule, VCAP_AF_ISDX_VAL);
1259 	if (!afield)
1260 		return;
1261 
1262 	isdx = afield->data.u32.value;
1263 	sfid = sparx5_psfp_isdx_get_sf(sparx5, isdx);
1264 
1265 	if (!sfid)
1266 		return;
1267 
1268 	fmid = sparx5_psfp_isdx_get_fm(sparx5, isdx);
1269 	sgid = sparx5_psfp_sf_get_sg(sparx5, sfid);
1270 
1271 	if (fmid && sparx5_psfp_fm_del(sparx5, fmid) < 0)
1272 		pr_err("%s:%d Could not delete invalid fmid: %d", __func__,
1273 		       __LINE__, fmid);
1274 
1275 	if (sgid && sparx5_psfp_sg_del(sparx5, sgid) < 0)
1276 		pr_err("%s:%d Could not delete invalid sgid: %d", __func__,
1277 		       __LINE__, sgid);
1278 
1279 	if (sparx5_psfp_sf_del(sparx5, sfid) < 0)
1280 		pr_err("%s:%d Could not delete invalid sfid: %d", __func__,
1281 		       __LINE__, sfid);
1282 
1283 	sparx5_isdx_conf_set(sparx5, isdx, 0, 0);
1284 }
1285 
sparx5_tc_free_rule_resources(struct net_device * ndev,struct vcap_control * vctrl,int rule_id)1286 static int sparx5_tc_free_rule_resources(struct net_device *ndev,
1287 					 struct vcap_control *vctrl,
1288 					 int rule_id)
1289 {
1290 	struct sparx5_port *port = netdev_priv(ndev);
1291 	struct sparx5 *sparx5 = port->sparx5;
1292 	struct vcap_rule *vrule;
1293 	int ret = 0;
1294 
1295 	vrule = vcap_get_rule(vctrl, rule_id);
1296 	if (IS_ERR(vrule))
1297 		return -EINVAL;
1298 
1299 	sparx5_tc_free_psfp_resources(sparx5, vrule);
1300 
1301 	vcap_free_rule(vrule);
1302 	return ret;
1303 }
1304 
sparx5_tc_flower_destroy(struct net_device * ndev,struct flow_cls_offload * fco,struct vcap_admin * admin)1305 static int sparx5_tc_flower_destroy(struct net_device *ndev,
1306 				    struct flow_cls_offload *fco,
1307 				    struct vcap_admin *admin)
1308 {
1309 	struct sparx5_port *port = netdev_priv(ndev);
1310 	int err = -ENOENT, count = 0, rule_id;
1311 	struct vcap_control *vctrl;
1312 
1313 	vctrl = port->sparx5->vcap_ctrl;
1314 	while (true) {
1315 		rule_id = vcap_lookup_rule_by_cookie(vctrl, fco->cookie);
1316 		if (rule_id <= 0)
1317 			break;
1318 		if (count == 0) {
1319 			/* Resources are attached to the first rule of
1320 			 * a set of rules. Only works if the rules are
1321 			 * in the correct order.
1322 			 */
1323 			err = sparx5_tc_free_rule_resources(ndev, vctrl,
1324 							    rule_id);
1325 			if (err)
1326 				pr_err("%s:%d: could not free resources %d\n",
1327 				       __func__, __LINE__, rule_id);
1328 		}
1329 		err = vcap_del_rule(vctrl, ndev, rule_id);
1330 		if (err) {
1331 			pr_err("%s:%d: could not delete rule %d\n",
1332 			       __func__, __LINE__, rule_id);
1333 			break;
1334 		}
1335 	}
1336 	return err;
1337 }
1338 
sparx5_tc_flower_stats(struct net_device * ndev,struct flow_cls_offload * fco,struct vcap_admin * admin)1339 static int sparx5_tc_flower_stats(struct net_device *ndev,
1340 				  struct flow_cls_offload *fco,
1341 				  struct vcap_admin *admin)
1342 {
1343 	struct sparx5_port *port = netdev_priv(ndev);
1344 	struct vcap_counter ctr = {};
1345 	struct vcap_control *vctrl;
1346 	ulong lastused = 0;
1347 	int err;
1348 
1349 	vctrl = port->sparx5->vcap_ctrl;
1350 	err = vcap_get_rule_count_by_cookie(vctrl, &ctr, fco->cookie);
1351 	if (err)
1352 		return err;
1353 	flow_stats_update(&fco->stats, 0x0, ctr.value, 0, lastused,
1354 			  FLOW_ACTION_HW_STATS_IMMEDIATE);
1355 	return err;
1356 }
1357 
sparx5_tc_flower_template_create(struct net_device * ndev,struct flow_cls_offload * fco,struct vcap_admin * admin)1358 static int sparx5_tc_flower_template_create(struct net_device *ndev,
1359 					    struct flow_cls_offload *fco,
1360 					    struct vcap_admin *admin)
1361 {
1362 	struct sparx5_port *port = netdev_priv(ndev);
1363 	struct vcap_tc_flower_parse_usage state = {
1364 		.fco = fco,
1365 		.l3_proto = ETH_P_ALL,
1366 		.admin = admin,
1367 	};
1368 	struct sparx5_tc_flower_template *ftp;
1369 	struct vcap_keyset_list kslist = {};
1370 	enum vcap_keyfield_set keysets[10];
1371 	struct vcap_control *vctrl;
1372 	struct vcap_rule *vrule;
1373 	int count, err;
1374 
1375 	if (admin->vtype == VCAP_TYPE_ES0) {
1376 		pr_err("%s:%d: %s\n", __func__, __LINE__,
1377 		       "VCAP does not support templates");
1378 		return -EINVAL;
1379 	}
1380 
1381 	count = vcap_admin_rule_count(admin, fco->common.chain_index);
1382 	if (count > 0) {
1383 		pr_err("%s:%d: %s\n", __func__, __LINE__,
1384 		       "Filters are already present");
1385 		return -EBUSY;
1386 	}
1387 
1388 	ftp = kzalloc(sizeof(*ftp), GFP_KERNEL);
1389 	if (!ftp)
1390 		return -ENOMEM;
1391 
1392 	ftp->cid = fco->common.chain_index;
1393 	ftp->orig = VCAP_KFS_NO_VALUE;
1394 	ftp->keyset = VCAP_KFS_NO_VALUE;
1395 
1396 	vctrl = port->sparx5->vcap_ctrl;
1397 	vrule = vcap_alloc_rule(vctrl, ndev, fco->common.chain_index,
1398 				VCAP_USER_TC, fco->common.prio, 0);
1399 	if (IS_ERR(vrule)) {
1400 		err = PTR_ERR(vrule);
1401 		goto err_rule;
1402 	}
1403 
1404 	state.vrule = vrule;
1405 	state.frule = flow_cls_offload_flow_rule(fco);
1406 	err = sparx5_tc_use_dissectors(&state, admin, vrule);
1407 	if (err) {
1408 		pr_err("%s:%d: key error: %d\n", __func__, __LINE__, err);
1409 		goto out;
1410 	}
1411 
1412 	ftp->l3_proto = state.l3_proto;
1413 
1414 	sparx5_tc_flower_simplify_rule(admin, vrule, state.l3_proto);
1415 
1416 	/* Find the keysets that the rule can use */
1417 	kslist.keysets = keysets;
1418 	kslist.max = ARRAY_SIZE(keysets);
1419 	if (!vcap_rule_find_keysets(vrule, &kslist)) {
1420 		pr_err("%s:%d: %s\n", __func__, __LINE__,
1421 		       "Could not find a suitable keyset");
1422 		err = -ENOENT;
1423 		goto out;
1424 	}
1425 
1426 	ftp->keyset = vcap_select_min_rule_keyset(vctrl, admin->vtype, &kslist);
1427 	kslist.cnt = 0;
1428 	sparx5_vcap_set_port_keyset(ndev, admin, fco->common.chain_index,
1429 				    state.l3_proto,
1430 				    ftp->keyset,
1431 				    &kslist);
1432 
1433 	if (kslist.cnt > 0)
1434 		ftp->orig = kslist.keysets[0];
1435 
1436 	/* Store new template */
1437 	list_add_tail(&ftp->list, &port->tc_templates);
1438 	vcap_free_rule(vrule);
1439 	return 0;
1440 
1441 out:
1442 	vcap_free_rule(vrule);
1443 err_rule:
1444 	kfree(ftp);
1445 	return err;
1446 }
1447 
sparx5_tc_flower_template_destroy(struct net_device * ndev,struct flow_cls_offload * fco,struct vcap_admin * admin)1448 static int sparx5_tc_flower_template_destroy(struct net_device *ndev,
1449 					     struct flow_cls_offload *fco,
1450 					     struct vcap_admin *admin)
1451 {
1452 	struct sparx5_port *port = netdev_priv(ndev);
1453 	struct sparx5_tc_flower_template *ftp, *tmp;
1454 	int err = -ENOENT;
1455 
1456 	/* Rules using the template are removed by the tc framework */
1457 	list_for_each_entry_safe(ftp, tmp, &port->tc_templates, list) {
1458 		if (ftp->cid != fco->common.chain_index)
1459 			continue;
1460 
1461 		sparx5_vcap_set_port_keyset(ndev, admin,
1462 					    fco->common.chain_index,
1463 					    ftp->l3_proto, ftp->orig,
1464 					    NULL);
1465 		list_del(&ftp->list);
1466 		kfree(ftp);
1467 		break;
1468 	}
1469 	return err;
1470 }
1471 
sparx5_tc_flower(struct net_device * ndev,struct flow_cls_offload * fco,bool ingress)1472 int sparx5_tc_flower(struct net_device *ndev, struct flow_cls_offload *fco,
1473 		     bool ingress)
1474 {
1475 	struct sparx5_port *port = netdev_priv(ndev);
1476 	struct vcap_control *vctrl;
1477 	struct vcap_admin *admin;
1478 	int err = -EINVAL;
1479 
1480 	/* Get vcap instance from the chain id */
1481 	vctrl = port->sparx5->vcap_ctrl;
1482 	admin = vcap_find_admin(vctrl, fco->common.chain_index);
1483 	if (!admin) {
1484 		NL_SET_ERR_MSG_MOD(fco->common.extack, "Invalid chain");
1485 		return err;
1486 	}
1487 
1488 	switch (fco->command) {
1489 	case FLOW_CLS_REPLACE:
1490 		return sparx5_tc_flower_replace(ndev, fco, admin, ingress);
1491 	case FLOW_CLS_DESTROY:
1492 		return sparx5_tc_flower_destroy(ndev, fco, admin);
1493 	case FLOW_CLS_STATS:
1494 		return sparx5_tc_flower_stats(ndev, fco, admin);
1495 	case FLOW_CLS_TMPLT_CREATE:
1496 		return sparx5_tc_flower_template_create(ndev, fco, admin);
1497 	case FLOW_CLS_TMPLT_DESTROY:
1498 		return sparx5_tc_flower_template_destroy(ndev, fco, admin);
1499 	default:
1500 		return -EOPNOTSUPP;
1501 	}
1502 }
1503