1 // SPDX-License-Identifier: (GPL-2.0 OR MIT)
2 /* Microsemi Ocelot Switch driver
3 * Copyright (c) 2019 Microsemi Corporation
6 #include <net/pkt_cls.h>
7 #include <net/tc_act/tc_gact.h>
8 #include <soc/mscc/ocelot_vcap.h>
9 #include "ocelot_vcap.h"
11 /* Arbitrarily chosen constants for encoding the VCAP block and lookup number
12 * into the chain number. This is UAPI.
14 #define VCAP_BLOCK 10000
15 #define VCAP_LOOKUP 1000
16 #define VCAP_IS1_NUM_LOOKUPS 3
17 #define VCAP_IS2_NUM_LOOKUPS 2
18 #define VCAP_IS2_NUM_PAG 256
19 #define VCAP_IS1_CHAIN(lookup) \
20 (1 * VCAP_BLOCK + (lookup) * VCAP_LOOKUP)
21 #define VCAP_IS2_CHAIN(lookup, pag) \
22 (2 * VCAP_BLOCK + (lookup) * VCAP_LOOKUP + (pag))
23 /* PSFP chain and block ID */
24 #define PSFP_BLOCK_ID OCELOT_NUM_VCAP_BLOCKS
25 #define OCELOT_PSFP_CHAIN (3 * VCAP_BLOCK)
27 static int ocelot_chain_to_block(int chain, bool ingress)
37 /* Backwards compatibility with older, single-chain tc-flower
38 * offload support in Ocelot
43 for (lookup = 0; lookup < VCAP_IS1_NUM_LOOKUPS; lookup++)
44 if (chain == VCAP_IS1_CHAIN(lookup))
47 for (lookup = 0; lookup < VCAP_IS2_NUM_LOOKUPS; lookup++)
48 for (pag = 0; pag < VCAP_IS2_NUM_PAG; pag++)
49 if (chain == VCAP_IS2_CHAIN(lookup, pag))
52 if (chain == OCELOT_PSFP_CHAIN)
58 /* Caller must ensure this is a valid IS1 or IS2 chain first,
59 * by calling ocelot_chain_to_block.
61 static int ocelot_chain_to_lookup(int chain)
63 /* Backwards compatibility with older, single-chain tc-flower
64 * offload support in Ocelot
69 return (chain / VCAP_LOOKUP) % 10;
72 /* Caller must ensure this is a valid IS2 chain first,
73 * by calling ocelot_chain_to_block.
75 static int ocelot_chain_to_pag(int chain)
79 /* Backwards compatibility with older, single-chain tc-flower
80 * offload support in Ocelot
85 lookup = ocelot_chain_to_lookup(chain);
87 /* calculate PAG value as chain index relative to the first PAG */
88 return chain - VCAP_IS2_CHAIN(lookup, 0);
91 static bool ocelot_is_goto_target_valid(int goto_target, int chain,
96 /* Can't offload GOTO in VCAP ES0 */
98 return (goto_target < 0);
100 /* Non-optional GOTOs */
102 /* VCAP IS1 can be skipped, either partially or completely */
103 return (goto_target == VCAP_IS1_CHAIN(0) ||
104 goto_target == VCAP_IS1_CHAIN(1) ||
105 goto_target == VCAP_IS1_CHAIN(2) ||
106 goto_target == VCAP_IS2_CHAIN(0, 0) ||
107 goto_target == VCAP_IS2_CHAIN(1, 0) ||
108 goto_target == OCELOT_PSFP_CHAIN);
110 if (chain == VCAP_IS1_CHAIN(0))
111 return (goto_target == VCAP_IS1_CHAIN(1));
113 if (chain == VCAP_IS1_CHAIN(1))
114 return (goto_target == VCAP_IS1_CHAIN(2));
116 /* Lookup 2 of VCAP IS1 can really support non-optional GOTOs,
117 * using a Policy Association Group (PAG) value, which is an 8-bit
118 * value encoding a VCAP IS2 target chain.
120 if (chain == VCAP_IS1_CHAIN(2)) {
121 for (pag = 0; pag < VCAP_IS2_NUM_PAG; pag++)
122 if (goto_target == VCAP_IS2_CHAIN(0, pag))
128 /* Non-optional GOTO from VCAP IS2 lookup 0 to lookup 1.
129 * We cannot change the PAG at this point.
131 for (pag = 0; pag < VCAP_IS2_NUM_PAG; pag++)
132 if (chain == VCAP_IS2_CHAIN(0, pag))
133 return (goto_target == VCAP_IS2_CHAIN(1, pag));
135 /* VCAP IS2 lookup 1 can goto to PSFP block if hardware support */
136 for (pag = 0; pag < VCAP_IS2_NUM_PAG; pag++)
137 if (chain == VCAP_IS2_CHAIN(1, pag))
138 return (goto_target == OCELOT_PSFP_CHAIN);
143 static struct ocelot_vcap_filter *
144 ocelot_find_vcap_filter_that_points_at(struct ocelot *ocelot, int chain)
146 struct ocelot_vcap_filter *filter;
147 struct ocelot_vcap_block *block;
150 block_id = ocelot_chain_to_block(chain, true);
154 if (block_id == VCAP_IS2) {
155 block = &ocelot->block[VCAP_IS1];
157 list_for_each_entry(filter, &block->rules, list)
158 if (filter->type == OCELOT_VCAP_FILTER_PAG &&
159 filter->goto_target == chain)
163 list_for_each_entry(filter, &ocelot->dummy_rules, list)
164 if (filter->goto_target == chain)
171 ocelot_flower_parse_ingress_vlan_modify(struct ocelot *ocelot, int port,
172 struct ocelot_vcap_filter *filter,
173 const struct flow_action_entry *a,
174 struct netlink_ext_ack *extack)
176 struct ocelot_port *ocelot_port = ocelot->ports[port];
178 if (filter->goto_target != -1) {
179 NL_SET_ERR_MSG_MOD(extack,
180 "Last action must be GOTO");
184 if (!ocelot_port->vlan_aware) {
185 NL_SET_ERR_MSG_MOD(extack,
186 "Can only modify VLAN under VLAN aware bridge");
190 filter->action.vid_replace_ena = true;
191 filter->action.pcp_dei_ena = true;
192 filter->action.vid = a->vlan.vid;
193 filter->action.pcp = a->vlan.prio;
194 filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
200 ocelot_flower_parse_egress_vlan_modify(struct ocelot_vcap_filter *filter,
201 const struct flow_action_entry *a,
202 struct netlink_ext_ack *extack)
204 enum ocelot_tag_tpid_sel tpid;
206 switch (ntohs(a->vlan.proto)) {
208 tpid = OCELOT_TAG_TPID_SEL_8021Q;
211 tpid = OCELOT_TAG_TPID_SEL_8021AD;
214 NL_SET_ERR_MSG_MOD(extack,
215 "Cannot modify custom TPID");
219 filter->action.tag_a_tpid_sel = tpid;
220 filter->action.push_outer_tag = OCELOT_ES0_TAG;
221 filter->action.tag_a_vid_sel = OCELOT_ES0_VID_PLUS_CLASSIFIED_VID;
222 filter->action.vid_a_val = a->vlan.vid;
223 filter->action.pcp_a_val = a->vlan.prio;
224 filter->action.tag_a_pcp_sel = OCELOT_ES0_PCP;
225 filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
230 static int ocelot_flower_parse_action(struct ocelot *ocelot, int port,
231 bool ingress, struct flow_cls_offload *f,
232 struct ocelot_vcap_filter *filter)
234 struct netlink_ext_ack *extack = f->common.extack;
235 bool allow_missing_goto_target = false;
236 const struct flow_action_entry *a;
237 enum ocelot_tag_tpid_sel tpid;
238 int i, chain, egress_port;
243 if (!flow_action_basic_hw_stats_check(&f->rule->action,
247 chain = f->common.chain_index;
248 filter->block_id = ocelot_chain_to_block(chain, ingress);
249 if (filter->block_id < 0) {
250 NL_SET_ERR_MSG_MOD(extack, "Cannot offload to this chain");
253 if (filter->block_id == VCAP_IS1 || filter->block_id == VCAP_IS2)
254 filter->lookup = ocelot_chain_to_lookup(chain);
255 if (filter->block_id == VCAP_IS2)
256 filter->pag = ocelot_chain_to_pag(chain);
258 filter->goto_target = -1;
259 filter->type = OCELOT_VCAP_FILTER_DUMMY;
261 flow_action_for_each(i, a, &f->rule->action) {
263 case FLOW_ACTION_DROP:
264 if (filter->block_id != VCAP_IS2) {
265 NL_SET_ERR_MSG_MOD(extack,
266 "Drop action can only be offloaded to VCAP IS2");
269 if (filter->goto_target != -1) {
270 NL_SET_ERR_MSG_MOD(extack,
271 "Last action must be GOTO");
274 filter->action.mask_mode = OCELOT_MASK_MODE_PERMIT_DENY;
275 filter->action.port_mask = 0;
276 filter->action.police_ena = true;
277 filter->action.pol_ix = OCELOT_POLICER_DISCARD;
278 filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
280 case FLOW_ACTION_TRAP:
281 if (filter->block_id != VCAP_IS2) {
282 NL_SET_ERR_MSG_MOD(extack,
283 "Trap action can only be offloaded to VCAP IS2");
286 if (filter->goto_target != -1) {
287 NL_SET_ERR_MSG_MOD(extack,
288 "Last action must be GOTO");
291 filter->action.mask_mode = OCELOT_MASK_MODE_PERMIT_DENY;
292 filter->action.port_mask = 0;
293 filter->action.cpu_copy_ena = true;
294 filter->action.cpu_qu_num = 0;
295 filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
297 case FLOW_ACTION_POLICE:
298 if (filter->block_id == PSFP_BLOCK_ID) {
299 filter->type = OCELOT_PSFP_FILTER_OFFLOAD;
302 if (filter->block_id != VCAP_IS2 ||
303 filter->lookup != 0) {
304 NL_SET_ERR_MSG_MOD(extack,
305 "Police action can only be offloaded to VCAP IS2 lookup 0 or PSFP");
308 if (filter->goto_target != -1) {
309 NL_SET_ERR_MSG_MOD(extack,
310 "Last action must be GOTO");
313 if (a->police.rate_pkt_ps) {
314 NL_SET_ERR_MSG_MOD(extack,
315 "QoS offload not support packets per second");
318 filter->action.police_ena = true;
320 pol_ix = a->hw_index + ocelot->vcap_pol.base;
321 pol_max = ocelot->vcap_pol.max;
323 if (ocelot->vcap_pol.max2 && pol_ix > pol_max) {
324 pol_ix += ocelot->vcap_pol.base2 - pol_max - 1;
325 pol_max = ocelot->vcap_pol.max2;
328 if (pol_ix >= pol_max)
331 filter->action.pol_ix = pol_ix;
333 rate = a->police.rate_bytes_ps;
334 filter->action.pol.rate = div_u64(rate, 1000) * 8;
335 filter->action.pol.burst = a->police.burst;
336 filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
338 case FLOW_ACTION_REDIRECT:
339 if (filter->block_id != VCAP_IS2) {
340 NL_SET_ERR_MSG_MOD(extack,
341 "Redirect action can only be offloaded to VCAP IS2");
344 if (filter->goto_target != -1) {
345 NL_SET_ERR_MSG_MOD(extack,
346 "Last action must be GOTO");
349 egress_port = ocelot->ops->netdev_to_port(a->dev);
350 if (egress_port < 0) {
351 NL_SET_ERR_MSG_MOD(extack,
352 "Destination not an ocelot port");
355 filter->action.mask_mode = OCELOT_MASK_MODE_REDIRECT;
356 filter->action.port_mask = BIT(egress_port);
357 filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
359 case FLOW_ACTION_VLAN_POP:
360 if (filter->block_id != VCAP_IS1) {
361 NL_SET_ERR_MSG_MOD(extack,
362 "VLAN pop action can only be offloaded to VCAP IS1");
365 if (filter->goto_target != -1) {
366 NL_SET_ERR_MSG_MOD(extack,
367 "Last action must be GOTO");
370 filter->action.vlan_pop_cnt_ena = true;
371 filter->action.vlan_pop_cnt++;
372 if (filter->action.vlan_pop_cnt > 2) {
373 NL_SET_ERR_MSG_MOD(extack,
374 "Cannot pop more than 2 VLAN headers");
377 filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
379 case FLOW_ACTION_VLAN_MANGLE:
380 if (filter->block_id == VCAP_IS1) {
381 err = ocelot_flower_parse_ingress_vlan_modify(ocelot, port,
384 } else if (filter->block_id == VCAP_ES0) {
385 err = ocelot_flower_parse_egress_vlan_modify(filter, a,
388 NL_SET_ERR_MSG_MOD(extack,
389 "VLAN modify action can only be offloaded to VCAP IS1 or ES0");
395 case FLOW_ACTION_PRIORITY:
396 if (filter->block_id != VCAP_IS1) {
397 NL_SET_ERR_MSG_MOD(extack,
398 "Priority action can only be offloaded to VCAP IS1");
401 if (filter->goto_target != -1) {
402 NL_SET_ERR_MSG_MOD(extack,
403 "Last action must be GOTO");
406 filter->action.qos_ena = true;
407 filter->action.qos_val = a->priority;
408 filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
410 case FLOW_ACTION_GOTO:
411 filter->goto_target = a->chain_index;
413 if (filter->block_id == VCAP_IS1 && filter->lookup == 2) {
414 int pag = ocelot_chain_to_pag(filter->goto_target);
416 filter->action.pag_override_mask = 0xff;
417 filter->action.pag_val = pag;
418 filter->type = OCELOT_VCAP_FILTER_PAG;
421 case FLOW_ACTION_VLAN_PUSH:
422 if (filter->block_id != VCAP_ES0) {
423 NL_SET_ERR_MSG_MOD(extack,
424 "VLAN push action can only be offloaded to VCAP ES0");
427 switch (ntohs(a->vlan.proto)) {
429 tpid = OCELOT_TAG_TPID_SEL_8021Q;
432 tpid = OCELOT_TAG_TPID_SEL_8021AD;
435 NL_SET_ERR_MSG_MOD(extack,
436 "Cannot push custom TPID");
439 filter->action.tag_a_tpid_sel = tpid;
440 filter->action.push_outer_tag = OCELOT_ES0_TAG;
441 filter->action.tag_a_vid_sel = OCELOT_ES0_VID;
442 filter->action.vid_a_val = a->vlan.vid;
443 filter->action.pcp_a_val = a->vlan.prio;
444 filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
446 case FLOW_ACTION_GATE:
447 if (filter->block_id != PSFP_BLOCK_ID) {
448 NL_SET_ERR_MSG_MOD(extack,
449 "Gate action can only be offloaded to PSFP chain");
452 filter->type = OCELOT_PSFP_FILTER_OFFLOAD;
455 NL_SET_ERR_MSG_MOD(extack, "Cannot offload action");
460 if (filter->goto_target == -1) {
461 if ((filter->block_id == VCAP_IS2 && filter->lookup == 1) ||
462 chain == 0 || filter->block_id == PSFP_BLOCK_ID) {
463 allow_missing_goto_target = true;
465 NL_SET_ERR_MSG_MOD(extack, "Missing GOTO action");
470 if (!ocelot_is_goto_target_valid(filter->goto_target, chain, ingress) &&
471 !allow_missing_goto_target) {
472 NL_SET_ERR_MSG_MOD(extack, "Cannot offload this GOTO target");
479 static int ocelot_flower_parse_indev(struct ocelot *ocelot, int port,
480 struct flow_cls_offload *f,
481 struct ocelot_vcap_filter *filter)
483 struct flow_rule *rule = flow_cls_offload_flow_rule(f);
484 const struct vcap_props *vcap = &ocelot->vcap[VCAP_ES0];
485 int key_length = vcap->keys[VCAP_ES0_IGR_PORT].length;
486 struct netlink_ext_ack *extack = f->common.extack;
487 struct net_device *dev, *indev;
488 struct flow_match_meta match;
491 flow_rule_match_meta(rule, &match);
493 if (!match.mask->ingress_ifindex)
496 if (match.mask->ingress_ifindex != 0xFFFFFFFF) {
497 NL_SET_ERR_MSG_MOD(extack, "Unsupported ingress ifindex mask");
501 dev = ocelot->ops->port_to_netdev(ocelot, port);
505 indev = __dev_get_by_index(dev_net(dev), match.key->ingress_ifindex);
507 NL_SET_ERR_MSG_MOD(extack,
508 "Can't find the ingress port to match on");
512 ingress_port = ocelot->ops->netdev_to_port(indev);
513 if (ingress_port < 0) {
514 NL_SET_ERR_MSG_MOD(extack,
515 "Can only offload an ocelot ingress port");
518 if (ingress_port == port) {
519 NL_SET_ERR_MSG_MOD(extack,
520 "Ingress port is equal to the egress port");
524 filter->ingress_port.value = ingress_port;
525 filter->ingress_port.mask = GENMASK(key_length - 1, 0);
531 ocelot_flower_parse_key(struct ocelot *ocelot, int port, bool ingress,
532 struct flow_cls_offload *f,
533 struct ocelot_vcap_filter *filter)
535 struct flow_rule *rule = flow_cls_offload_flow_rule(f);
536 struct flow_dissector *dissector = rule->match.dissector;
537 struct netlink_ext_ack *extack = f->common.extack;
538 u16 proto = ntohs(f->common.protocol);
539 bool match_protocol = true;
542 if (dissector->used_keys &
543 ~(BIT(FLOW_DISSECTOR_KEY_CONTROL) |
544 BIT(FLOW_DISSECTOR_KEY_BASIC) |
545 BIT(FLOW_DISSECTOR_KEY_META) |
546 BIT(FLOW_DISSECTOR_KEY_PORTS) |
547 BIT(FLOW_DISSECTOR_KEY_VLAN) |
548 BIT(FLOW_DISSECTOR_KEY_IPV4_ADDRS) |
549 BIT(FLOW_DISSECTOR_KEY_IPV6_ADDRS) |
550 BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS))) {
554 /* For VCAP ES0 (egress rewriter) we can match on the ingress port */
556 ret = ocelot_flower_parse_indev(ocelot, port, f, filter);
561 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CONTROL)) {
562 struct flow_match_control match;
564 flow_rule_match_control(rule, &match);
567 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ETH_ADDRS)) {
568 struct flow_match_eth_addrs match;
570 if (filter->block_id == VCAP_ES0) {
571 NL_SET_ERR_MSG_MOD(extack,
572 "VCAP ES0 cannot match on MAC address");
576 /* The hw support mac matches only for MAC_ETYPE key,
577 * therefore if other matches(port, tcp flags, etc) are added
580 if ((dissector->used_keys &
581 (BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS) |
582 BIT(FLOW_DISSECTOR_KEY_BASIC) |
583 BIT(FLOW_DISSECTOR_KEY_CONTROL))) !=
584 (BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS) |
585 BIT(FLOW_DISSECTOR_KEY_BASIC) |
586 BIT(FLOW_DISSECTOR_KEY_CONTROL)))
589 flow_rule_match_eth_addrs(rule, &match);
591 if (filter->block_id == VCAP_IS1 &&
592 !is_zero_ether_addr(match.mask->dst)) {
593 NL_SET_ERR_MSG_MOD(extack,
594 "Key type S1_NORMAL cannot match on destination MAC");
598 filter->key_type = OCELOT_VCAP_KEY_ETYPE;
599 ether_addr_copy(filter->key.etype.dmac.value,
601 ether_addr_copy(filter->key.etype.smac.value,
603 ether_addr_copy(filter->key.etype.dmac.mask,
605 ether_addr_copy(filter->key.etype.smac.mask,
607 goto finished_key_parsing;
610 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) {
611 struct flow_match_basic match;
613 flow_rule_match_basic(rule, &match);
614 if (ntohs(match.key->n_proto) == ETH_P_IP) {
615 if (filter->block_id == VCAP_ES0) {
616 NL_SET_ERR_MSG_MOD(extack,
617 "VCAP ES0 cannot match on IP protocol");
621 filter->key_type = OCELOT_VCAP_KEY_IPV4;
622 filter->key.ipv4.proto.value[0] =
624 filter->key.ipv4.proto.mask[0] =
625 match.mask->ip_proto;
626 match_protocol = false;
628 if (ntohs(match.key->n_proto) == ETH_P_IPV6) {
629 if (filter->block_id == VCAP_ES0) {
630 NL_SET_ERR_MSG_MOD(extack,
631 "VCAP ES0 cannot match on IP protocol");
635 filter->key_type = OCELOT_VCAP_KEY_IPV6;
636 filter->key.ipv6.proto.value[0] =
638 filter->key.ipv6.proto.mask[0] =
639 match.mask->ip_proto;
640 match_protocol = false;
644 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV4_ADDRS) &&
646 struct flow_match_ipv4_addrs match;
649 if (filter->block_id == VCAP_ES0) {
650 NL_SET_ERR_MSG_MOD(extack,
651 "VCAP ES0 cannot match on IP address");
655 flow_rule_match_ipv4_addrs(rule, &match);
657 if (filter->block_id == VCAP_IS1 && *(u32 *)&match.mask->dst) {
658 NL_SET_ERR_MSG_MOD(extack,
659 "Key type S1_NORMAL cannot match on destination IP");
663 tmp = &filter->key.ipv4.sip.value.addr[0];
664 memcpy(tmp, &match.key->src, 4);
666 tmp = &filter->key.ipv4.sip.mask.addr[0];
667 memcpy(tmp, &match.mask->src, 4);
669 tmp = &filter->key.ipv4.dip.value.addr[0];
670 memcpy(tmp, &match.key->dst, 4);
672 tmp = &filter->key.ipv4.dip.mask.addr[0];
673 memcpy(tmp, &match.mask->dst, 4);
674 match_protocol = false;
677 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV6_ADDRS) &&
678 proto == ETH_P_IPV6) {
682 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_PORTS)) {
683 struct flow_match_ports match;
685 if (filter->block_id == VCAP_ES0) {
686 NL_SET_ERR_MSG_MOD(extack,
687 "VCAP ES0 cannot match on L4 ports");
691 flow_rule_match_ports(rule, &match);
692 filter->key.ipv4.sport.value = ntohs(match.key->src);
693 filter->key.ipv4.sport.mask = ntohs(match.mask->src);
694 filter->key.ipv4.dport.value = ntohs(match.key->dst);
695 filter->key.ipv4.dport.mask = ntohs(match.mask->dst);
696 match_protocol = false;
699 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_VLAN)) {
700 struct flow_match_vlan match;
702 flow_rule_match_vlan(rule, &match);
703 filter->key_type = OCELOT_VCAP_KEY_ANY;
704 filter->vlan.vid.value = match.key->vlan_id;
705 filter->vlan.vid.mask = match.mask->vlan_id;
706 filter->vlan.pcp.value[0] = match.key->vlan_priority;
707 filter->vlan.pcp.mask[0] = match.mask->vlan_priority;
708 match_protocol = false;
711 finished_key_parsing:
712 if (match_protocol && proto != ETH_P_ALL) {
713 if (filter->block_id == VCAP_ES0) {
714 NL_SET_ERR_MSG_MOD(extack,
715 "VCAP ES0 cannot match on L2 proto");
719 /* TODO: support SNAP, LLC etc */
720 if (proto < ETH_P_802_3_MIN)
722 filter->key_type = OCELOT_VCAP_KEY_ETYPE;
723 *(__be16 *)filter->key.etype.etype.value = htons(proto);
724 *(__be16 *)filter->key.etype.etype.mask = htons(0xffff);
726 /* else, a filter of type OCELOT_VCAP_KEY_ANY is implicitly added */
731 static int ocelot_flower_parse(struct ocelot *ocelot, int port, bool ingress,
732 struct flow_cls_offload *f,
733 struct ocelot_vcap_filter *filter)
737 filter->prio = f->common.prio;
738 filter->id.cookie = f->cookie;
739 filter->id.tc_offload = true;
741 ret = ocelot_flower_parse_action(ocelot, port, ingress, f, filter);
745 /* PSFP filter need to parse key by stream identification function. */
746 if (filter->type == OCELOT_PSFP_FILTER_OFFLOAD)
749 return ocelot_flower_parse_key(ocelot, port, ingress, f, filter);
752 static struct ocelot_vcap_filter
753 *ocelot_vcap_filter_create(struct ocelot *ocelot, int port, bool ingress,
754 struct flow_cls_offload *f)
756 struct ocelot_vcap_filter *filter;
758 filter = kzalloc(sizeof(*filter), GFP_KERNEL);
763 filter->ingress_port_mask = BIT(port);
765 const struct vcap_props *vcap = &ocelot->vcap[VCAP_ES0];
766 int key_length = vcap->keys[VCAP_ES0_EGR_PORT].length;
768 filter->egress_port.value = port;
769 filter->egress_port.mask = GENMASK(key_length - 1, 0);
775 static int ocelot_vcap_dummy_filter_add(struct ocelot *ocelot,
776 struct ocelot_vcap_filter *filter)
778 list_add(&filter->list, &ocelot->dummy_rules);
783 static int ocelot_vcap_dummy_filter_del(struct ocelot *ocelot,
784 struct ocelot_vcap_filter *filter)
786 list_del(&filter->list);
792 /* If we have an egress VLAN modification rule, we need to actually write the
793 * delta between the input VLAN (from the key) and the output VLAN (from the
794 * action), but the action was parsed first. So we need to patch the delta into
798 ocelot_flower_patch_es0_vlan_modify(struct ocelot_vcap_filter *filter,
799 struct netlink_ext_ack *extack)
801 if (filter->block_id != VCAP_ES0 ||
802 filter->action.tag_a_vid_sel != OCELOT_ES0_VID_PLUS_CLASSIFIED_VID)
805 if (filter->vlan.vid.mask != VLAN_VID_MASK) {
806 NL_SET_ERR_MSG_MOD(extack,
807 "VCAP ES0 VLAN rewriting needs a full VLAN in the key");
811 filter->action.vid_a_val -= filter->vlan.vid.value;
812 filter->action.vid_a_val &= VLAN_VID_MASK;
817 int ocelot_cls_flower_replace(struct ocelot *ocelot, int port,
818 struct flow_cls_offload *f, bool ingress)
820 struct netlink_ext_ack *extack = f->common.extack;
821 struct ocelot_vcap_filter *filter;
822 int chain = f->common.chain_index;
825 if (chain && !ocelot_find_vcap_filter_that_points_at(ocelot, chain)) {
826 NL_SET_ERR_MSG_MOD(extack, "No default GOTO action points to this chain");
830 block_id = ocelot_chain_to_block(chain, ingress);
832 NL_SET_ERR_MSG_MOD(extack, "Cannot offload to this chain");
836 filter = ocelot_vcap_block_find_filter_by_id(&ocelot->block[block_id],
839 /* Filter already exists on other ports */
841 NL_SET_ERR_MSG_MOD(extack, "VCAP ES0 does not support shared filters");
845 filter->ingress_port_mask |= BIT(port);
847 return ocelot_vcap_filter_replace(ocelot, filter);
850 /* Filter didn't exist, create it now */
851 filter = ocelot_vcap_filter_create(ocelot, port, ingress, f);
855 ret = ocelot_flower_parse(ocelot, port, ingress, f, filter);
861 ret = ocelot_flower_patch_es0_vlan_modify(filter, extack);
867 /* The non-optional GOTOs for the TCAM skeleton don't need
868 * to be actually offloaded.
870 if (filter->type == OCELOT_VCAP_FILTER_DUMMY)
871 return ocelot_vcap_dummy_filter_add(ocelot, filter);
873 if (filter->type == OCELOT_PSFP_FILTER_OFFLOAD) {
875 if (ocelot->ops->psfp_filter_add)
876 return ocelot->ops->psfp_filter_add(ocelot, port, f);
878 NL_SET_ERR_MSG_MOD(extack, "PSFP chain is not supported in HW");
882 return ocelot_vcap_filter_add(ocelot, filter, f->common.extack);
884 EXPORT_SYMBOL_GPL(ocelot_cls_flower_replace);
886 int ocelot_cls_flower_destroy(struct ocelot *ocelot, int port,
887 struct flow_cls_offload *f, bool ingress)
889 struct ocelot_vcap_filter *filter;
890 struct ocelot_vcap_block *block;
893 block_id = ocelot_chain_to_block(f->common.chain_index, ingress);
897 if (block_id == PSFP_BLOCK_ID) {
898 if (ocelot->ops->psfp_filter_del)
899 return ocelot->ops->psfp_filter_del(ocelot, f);
904 block = &ocelot->block[block_id];
906 filter = ocelot_vcap_block_find_filter_by_id(block, f->cookie, true);
910 if (filter->type == OCELOT_VCAP_FILTER_DUMMY)
911 return ocelot_vcap_dummy_filter_del(ocelot, filter);
914 filter->ingress_port_mask &= ~BIT(port);
915 if (filter->ingress_port_mask)
916 return ocelot_vcap_filter_replace(ocelot, filter);
919 return ocelot_vcap_filter_del(ocelot, filter);
921 EXPORT_SYMBOL_GPL(ocelot_cls_flower_destroy);
923 int ocelot_cls_flower_stats(struct ocelot *ocelot, int port,
924 struct flow_cls_offload *f, bool ingress)
926 struct ocelot_vcap_filter *filter;
927 struct ocelot_vcap_block *block;
928 struct flow_stats stats = {0};
931 block_id = ocelot_chain_to_block(f->common.chain_index, ingress);
935 if (block_id == PSFP_BLOCK_ID) {
936 if (ocelot->ops->psfp_stats_get) {
937 ret = ocelot->ops->psfp_stats_get(ocelot, f, &stats);
947 block = &ocelot->block[block_id];
949 filter = ocelot_vcap_block_find_filter_by_id(block, f->cookie, true);
950 if (!filter || filter->type == OCELOT_VCAP_FILTER_DUMMY)
953 ret = ocelot_vcap_filter_stats_update(ocelot, filter);
957 stats.pkts = filter->stats.pkts;
960 flow_stats_update(&f->stats, 0x0, stats.pkts, stats.drops, 0x0,
961 FLOW_ACTION_HW_STATS_IMMEDIATE);
964 EXPORT_SYMBOL_GPL(ocelot_cls_flower_stats);