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