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>
9 #include "ocelot_ace.h"
11 struct ocelot_port_block {
12 struct ocelot_acl_block *block;
13 struct ocelot_port *port;
16 static u16 get_prio(u32 prio)
18 /* prio starts from 0x1000 while the ids starts from 0 */
22 static int ocelot_flower_parse_action(struct flow_cls_offload *f,
23 struct ocelot_ace_rule *rule)
25 const struct flow_action_entry *a;
28 if (f->rule->action.num_entries != 1)
31 flow_action_for_each(i, a, &f->rule->action) {
33 case FLOW_ACTION_DROP:
34 rule->action = OCELOT_ACL_ACTION_DROP;
36 case FLOW_ACTION_TRAP:
37 rule->action = OCELOT_ACL_ACTION_TRAP;
47 static int ocelot_flower_parse(struct flow_cls_offload *f,
48 struct ocelot_ace_rule *ocelot_rule)
50 struct flow_rule *rule = flow_cls_offload_flow_rule(f);
51 struct flow_dissector *dissector = rule->match.dissector;
53 if (dissector->used_keys &
54 ~(BIT(FLOW_DISSECTOR_KEY_CONTROL) |
55 BIT(FLOW_DISSECTOR_KEY_BASIC) |
56 BIT(FLOW_DISSECTOR_KEY_PORTS) |
57 BIT(FLOW_DISSECTOR_KEY_VLAN) |
58 BIT(FLOW_DISSECTOR_KEY_IPV4_ADDRS) |
59 BIT(FLOW_DISSECTOR_KEY_IPV6_ADDRS) |
60 BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS))) {
64 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CONTROL)) {
65 struct flow_match_control match;
67 flow_rule_match_control(rule, &match);
70 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ETH_ADDRS)) {
71 struct flow_match_eth_addrs match;
72 u16 proto = ntohs(f->common.protocol);
74 /* The hw support mac matches only for MAC_ETYPE key,
75 * therefore if other matches(port, tcp flags, etc) are added
78 if ((dissector->used_keys &
79 (BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS) |
80 BIT(FLOW_DISSECTOR_KEY_BASIC) |
81 BIT(FLOW_DISSECTOR_KEY_CONTROL))) !=
82 (BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS) |
83 BIT(FLOW_DISSECTOR_KEY_BASIC) |
84 BIT(FLOW_DISSECTOR_KEY_CONTROL)))
87 if (proto == ETH_P_IP ||
88 proto == ETH_P_IPV6 ||
92 flow_rule_match_eth_addrs(rule, &match);
93 ocelot_rule->type = OCELOT_ACE_TYPE_ETYPE;
94 ether_addr_copy(ocelot_rule->frame.etype.dmac.value,
96 ether_addr_copy(ocelot_rule->frame.etype.smac.value,
98 ether_addr_copy(ocelot_rule->frame.etype.dmac.mask,
100 ether_addr_copy(ocelot_rule->frame.etype.smac.mask,
102 goto finished_key_parsing;
105 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) {
106 struct flow_match_basic match;
108 flow_rule_match_basic(rule, &match);
109 if (ntohs(match.key->n_proto) == ETH_P_IP) {
110 ocelot_rule->type = OCELOT_ACE_TYPE_IPV4;
111 ocelot_rule->frame.ipv4.proto.value[0] =
113 ocelot_rule->frame.ipv4.proto.mask[0] =
114 match.mask->ip_proto;
116 if (ntohs(match.key->n_proto) == ETH_P_IPV6) {
117 ocelot_rule->type = OCELOT_ACE_TYPE_IPV6;
118 ocelot_rule->frame.ipv6.proto.value[0] =
120 ocelot_rule->frame.ipv6.proto.mask[0] =
121 match.mask->ip_proto;
125 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV4_ADDRS) &&
126 ntohs(f->common.protocol) == ETH_P_IP) {
127 struct flow_match_ipv4_addrs match;
130 flow_rule_match_ipv4_addrs(rule, &match);
131 tmp = &ocelot_rule->frame.ipv4.sip.value.addr[0];
132 memcpy(tmp, &match.key->src, 4);
134 tmp = &ocelot_rule->frame.ipv4.sip.mask.addr[0];
135 memcpy(tmp, &match.mask->src, 4);
137 tmp = &ocelot_rule->frame.ipv4.dip.value.addr[0];
138 memcpy(tmp, &match.key->dst, 4);
140 tmp = &ocelot_rule->frame.ipv4.dip.mask.addr[0];
141 memcpy(tmp, &match.mask->dst, 4);
144 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV6_ADDRS) &&
145 ntohs(f->common.protocol) == ETH_P_IPV6) {
149 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_PORTS)) {
150 struct flow_match_ports match;
152 flow_rule_match_ports(rule, &match);
153 ocelot_rule->frame.ipv4.sport.value = ntohs(match.key->src);
154 ocelot_rule->frame.ipv4.sport.mask = ntohs(match.mask->src);
155 ocelot_rule->frame.ipv4.dport.value = ntohs(match.key->dst);
156 ocelot_rule->frame.ipv4.dport.mask = ntohs(match.mask->dst);
159 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_VLAN)) {
160 struct flow_match_vlan match;
162 flow_rule_match_vlan(rule, &match);
163 ocelot_rule->type = OCELOT_ACE_TYPE_ANY;
164 ocelot_rule->vlan.vid.value = match.key->vlan_id;
165 ocelot_rule->vlan.vid.mask = match.mask->vlan_id;
166 ocelot_rule->vlan.pcp.value[0] = match.key->vlan_priority;
167 ocelot_rule->vlan.pcp.mask[0] = match.mask->vlan_priority;
170 finished_key_parsing:
171 ocelot_rule->prio = get_prio(f->common.prio);
172 ocelot_rule->id = f->cookie;
173 return ocelot_flower_parse_action(f, ocelot_rule);
177 struct ocelot_ace_rule *ocelot_ace_rule_create(struct flow_cls_offload *f,
178 struct ocelot_port_block *block)
180 struct ocelot_ace_rule *rule;
182 rule = kzalloc(sizeof(*rule), GFP_KERNEL);
186 rule->port = block->port;
187 rule->chip_port = block->port->chip_port;
191 static int ocelot_flower_replace(struct flow_cls_offload *f,
192 struct ocelot_port_block *port_block)
194 struct ocelot_ace_rule *rule;
197 rule = ocelot_ace_rule_create(f, port_block);
201 ret = ocelot_flower_parse(f, rule);
207 ret = ocelot_ace_rule_offload_add(rule);
211 port_block->port->tc.offload_cnt++;
215 static int ocelot_flower_destroy(struct flow_cls_offload *f,
216 struct ocelot_port_block *port_block)
218 struct ocelot_ace_rule rule;
221 rule.prio = get_prio(f->common.prio);
222 rule.port = port_block->port;
225 ret = ocelot_ace_rule_offload_del(&rule);
229 port_block->port->tc.offload_cnt--;
233 static int ocelot_flower_stats_update(struct flow_cls_offload *f,
234 struct ocelot_port_block *port_block)
236 struct ocelot_ace_rule rule;
239 rule.prio = get_prio(f->common.prio);
240 rule.port = port_block->port;
242 ret = ocelot_ace_rule_stats_update(&rule);
246 flow_stats_update(&f->stats, 0x0, rule.stats.pkts, 0x0);
250 static int ocelot_setup_tc_cls_flower(struct flow_cls_offload *f,
251 struct ocelot_port_block *port_block)
253 switch (f->command) {
254 case FLOW_CLS_REPLACE:
255 return ocelot_flower_replace(f, port_block);
256 case FLOW_CLS_DESTROY:
257 return ocelot_flower_destroy(f, port_block);
259 return ocelot_flower_stats_update(f, port_block);
265 static int ocelot_setup_tc_block_cb_flower(enum tc_setup_type type,
266 void *type_data, void *cb_priv)
268 struct ocelot_port_block *port_block = cb_priv;
270 if (!tc_cls_can_offload_and_chain0(port_block->port->dev, type_data))
274 case TC_SETUP_CLSFLOWER:
275 return ocelot_setup_tc_cls_flower(type_data, cb_priv);
276 case TC_SETUP_CLSMATCHALL:
283 static struct ocelot_port_block*
284 ocelot_port_block_create(struct ocelot_port *port)
286 struct ocelot_port_block *port_block;
288 port_block = kzalloc(sizeof(*port_block), GFP_KERNEL);
292 port_block->port = port;
297 static void ocelot_port_block_destroy(struct ocelot_port_block *block)
302 static void ocelot_tc_block_unbind(void *cb_priv)
304 struct ocelot_port_block *port_block = cb_priv;
306 ocelot_port_block_destroy(port_block);
309 int ocelot_setup_tc_block_flower_bind(struct ocelot_port *port,
310 struct flow_block_offload *f)
312 struct ocelot_port_block *port_block;
313 struct flow_block_cb *block_cb;
316 if (f->binder_type == FLOW_BLOCK_BINDER_TYPE_CLSACT_EGRESS)
319 block_cb = flow_block_cb_lookup(f, ocelot_setup_tc_block_cb_flower,
322 port_block = ocelot_port_block_create(port);
326 block_cb = flow_block_cb_alloc(f->net,
327 ocelot_setup_tc_block_cb_flower,
329 ocelot_tc_block_unbind);
330 if (IS_ERR(block_cb)) {
331 ret = PTR_ERR(block_cb);
332 goto err_cb_register;
334 flow_block_cb_add(block_cb, f);
335 list_add_tail(&block_cb->driver_list, f->driver_block_list);
337 port_block = flow_block_cb_priv(block_cb);
340 flow_block_cb_incref(block_cb);
344 ocelot_port_block_destroy(port_block);
349 void ocelot_setup_tc_block_flower_unbind(struct ocelot_port *port,
350 struct flow_block_offload *f)
352 struct flow_block_cb *block_cb;
354 block_cb = flow_block_cb_lookup(f, ocelot_setup_tc_block_cb_flower,
359 if (!flow_block_cb_decref(block_cb)) {
360 flow_block_cb_remove(block_cb, f);
361 list_del(&block_cb->driver_list);