1 // SPDX-License-Identifier: (GPL-2.0 OR MIT)
2 /* Microsemi Ocelot Switch driver
3  * Copyright (c) 2019 Microsemi Corporation
4  */
5 
6 #include <net/pkt_cls.h>
7 #include <net/tc_act/tc_gact.h>
8 
9 #include "ocelot_ace.h"
10 
11 static int ocelot_flower_parse_action(struct flow_cls_offload *f,
12 				      struct ocelot_ace_rule *ace)
13 {
14 	const struct flow_action_entry *a;
15 	s64 burst;
16 	u64 rate;
17 	int i;
18 
19 	if (!flow_offload_has_one_action(&f->rule->action))
20 		return -EOPNOTSUPP;
21 
22 	if (!flow_action_basic_hw_stats_check(&f->rule->action,
23 					      f->common.extack))
24 		return -EOPNOTSUPP;
25 
26 	flow_action_for_each(i, a, &f->rule->action) {
27 		switch (a->id) {
28 		case FLOW_ACTION_DROP:
29 			ace->action = OCELOT_ACL_ACTION_DROP;
30 			break;
31 		case FLOW_ACTION_TRAP:
32 			ace->action = OCELOT_ACL_ACTION_TRAP;
33 			break;
34 		case FLOW_ACTION_POLICE:
35 			ace->action = OCELOT_ACL_ACTION_POLICE;
36 			rate = a->police.rate_bytes_ps;
37 			ace->pol.rate = div_u64(rate, 1000) * 8;
38 			burst = rate * PSCHED_NS2TICKS(a->police.burst);
39 			ace->pol.burst = div_u64(burst, PSCHED_TICKS_PER_SEC);
40 			break;
41 		default:
42 			return -EOPNOTSUPP;
43 		}
44 	}
45 
46 	return 0;
47 }
48 
49 static int ocelot_flower_parse(struct flow_cls_offload *f,
50 			       struct ocelot_ace_rule *ace)
51 {
52 	struct flow_rule *rule = flow_cls_offload_flow_rule(f);
53 	struct flow_dissector *dissector = rule->match.dissector;
54 
55 	if (dissector->used_keys &
56 	    ~(BIT(FLOW_DISSECTOR_KEY_CONTROL) |
57 	      BIT(FLOW_DISSECTOR_KEY_BASIC) |
58 	      BIT(FLOW_DISSECTOR_KEY_PORTS) |
59 	      BIT(FLOW_DISSECTOR_KEY_VLAN) |
60 	      BIT(FLOW_DISSECTOR_KEY_IPV4_ADDRS) |
61 	      BIT(FLOW_DISSECTOR_KEY_IPV6_ADDRS) |
62 	      BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS))) {
63 		return -EOPNOTSUPP;
64 	}
65 
66 	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CONTROL)) {
67 		struct flow_match_control match;
68 
69 		flow_rule_match_control(rule, &match);
70 	}
71 
72 	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ETH_ADDRS)) {
73 		struct flow_match_eth_addrs match;
74 		u16 proto = ntohs(f->common.protocol);
75 
76 		/* The hw support mac matches only for MAC_ETYPE key,
77 		 * therefore if other matches(port, tcp flags, etc) are added
78 		 * then just bail out
79 		 */
80 		if ((dissector->used_keys &
81 		    (BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS) |
82 		     BIT(FLOW_DISSECTOR_KEY_BASIC) |
83 		     BIT(FLOW_DISSECTOR_KEY_CONTROL))) !=
84 		    (BIT(FLOW_DISSECTOR_KEY_ETH_ADDRS) |
85 		     BIT(FLOW_DISSECTOR_KEY_BASIC) |
86 		     BIT(FLOW_DISSECTOR_KEY_CONTROL)))
87 			return -EOPNOTSUPP;
88 
89 		if (proto == ETH_P_IP ||
90 		    proto == ETH_P_IPV6 ||
91 		    proto == ETH_P_ARP)
92 			return -EOPNOTSUPP;
93 
94 		flow_rule_match_eth_addrs(rule, &match);
95 		ace->type = OCELOT_ACE_TYPE_ETYPE;
96 		ether_addr_copy(ace->frame.etype.dmac.value,
97 				match.key->dst);
98 		ether_addr_copy(ace->frame.etype.smac.value,
99 				match.key->src);
100 		ether_addr_copy(ace->frame.etype.dmac.mask,
101 				match.mask->dst);
102 		ether_addr_copy(ace->frame.etype.smac.mask,
103 				match.mask->src);
104 		goto finished_key_parsing;
105 	}
106 
107 	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) {
108 		struct flow_match_basic match;
109 
110 		flow_rule_match_basic(rule, &match);
111 		if (ntohs(match.key->n_proto) == ETH_P_IP) {
112 			ace->type = OCELOT_ACE_TYPE_IPV4;
113 			ace->frame.ipv4.proto.value[0] =
114 				match.key->ip_proto;
115 			ace->frame.ipv4.proto.mask[0] =
116 				match.mask->ip_proto;
117 		}
118 		if (ntohs(match.key->n_proto) == ETH_P_IPV6) {
119 			ace->type = OCELOT_ACE_TYPE_IPV6;
120 			ace->frame.ipv6.proto.value[0] =
121 				match.key->ip_proto;
122 			ace->frame.ipv6.proto.mask[0] =
123 				match.mask->ip_proto;
124 		}
125 	}
126 
127 	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV4_ADDRS) &&
128 	    ntohs(f->common.protocol) == ETH_P_IP) {
129 		struct flow_match_ipv4_addrs match;
130 		u8 *tmp;
131 
132 		flow_rule_match_ipv4_addrs(rule, &match);
133 		tmp = &ace->frame.ipv4.sip.value.addr[0];
134 		memcpy(tmp, &match.key->src, 4);
135 
136 		tmp = &ace->frame.ipv4.sip.mask.addr[0];
137 		memcpy(tmp, &match.mask->src, 4);
138 
139 		tmp = &ace->frame.ipv4.dip.value.addr[0];
140 		memcpy(tmp, &match.key->dst, 4);
141 
142 		tmp = &ace->frame.ipv4.dip.mask.addr[0];
143 		memcpy(tmp, &match.mask->dst, 4);
144 	}
145 
146 	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV6_ADDRS) &&
147 	    ntohs(f->common.protocol) == ETH_P_IPV6) {
148 		return -EOPNOTSUPP;
149 	}
150 
151 	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_PORTS)) {
152 		struct flow_match_ports match;
153 
154 		flow_rule_match_ports(rule, &match);
155 		ace->frame.ipv4.sport.value = ntohs(match.key->src);
156 		ace->frame.ipv4.sport.mask = ntohs(match.mask->src);
157 		ace->frame.ipv4.dport.value = ntohs(match.key->dst);
158 		ace->frame.ipv4.dport.mask = ntohs(match.mask->dst);
159 	}
160 
161 	if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_VLAN)) {
162 		struct flow_match_vlan match;
163 
164 		flow_rule_match_vlan(rule, &match);
165 		ace->type = OCELOT_ACE_TYPE_ANY;
166 		ace->vlan.vid.value = match.key->vlan_id;
167 		ace->vlan.vid.mask = match.mask->vlan_id;
168 		ace->vlan.pcp.value[0] = match.key->vlan_priority;
169 		ace->vlan.pcp.mask[0] = match.mask->vlan_priority;
170 	}
171 
172 finished_key_parsing:
173 	ace->prio = f->common.prio;
174 	ace->id = f->cookie;
175 	return ocelot_flower_parse_action(f, ace);
176 }
177 
178 static
179 struct ocelot_ace_rule *ocelot_ace_rule_create(struct ocelot *ocelot, int port,
180 					       struct flow_cls_offload *f)
181 {
182 	struct ocelot_ace_rule *ace;
183 
184 	ace = kzalloc(sizeof(*ace), GFP_KERNEL);
185 	if (!ace)
186 		return NULL;
187 
188 	ace->ingress_port_mask = BIT(port);
189 	return ace;
190 }
191 
192 int ocelot_cls_flower_replace(struct ocelot *ocelot, int port,
193 			      struct flow_cls_offload *f, bool ingress)
194 {
195 	struct ocelot_ace_rule *ace;
196 	int ret;
197 
198 	ace = ocelot_ace_rule_create(ocelot, port, f);
199 	if (!ace)
200 		return -ENOMEM;
201 
202 	ret = ocelot_flower_parse(f, ace);
203 	if (ret) {
204 		kfree(ace);
205 		return ret;
206 	}
207 
208 	return ocelot_ace_rule_offload_add(ocelot, ace);
209 }
210 EXPORT_SYMBOL_GPL(ocelot_cls_flower_replace);
211 
212 int ocelot_cls_flower_destroy(struct ocelot *ocelot, int port,
213 			      struct flow_cls_offload *f, bool ingress)
214 {
215 	struct ocelot_ace_rule ace;
216 
217 	ace.prio = f->common.prio;
218 	ace.id = f->cookie;
219 
220 	return ocelot_ace_rule_offload_del(ocelot, &ace);
221 }
222 EXPORT_SYMBOL_GPL(ocelot_cls_flower_destroy);
223 
224 int ocelot_cls_flower_stats(struct ocelot *ocelot, int port,
225 			    struct flow_cls_offload *f, bool ingress)
226 {
227 	struct ocelot_ace_rule ace;
228 	int ret;
229 
230 	ace.prio = f->common.prio;
231 	ace.id = f->cookie;
232 	ret = ocelot_ace_rule_stats_update(ocelot, &ace);
233 	if (ret)
234 		return ret;
235 
236 	flow_stats_update(&f->stats, 0x0, ace.stats.pkts, 0x0,
237 			  FLOW_ACTION_HW_STATS_IMMEDIATE);
238 	return 0;
239 }
240 EXPORT_SYMBOL_GPL(ocelot_cls_flower_stats);
241 
242 int ocelot_setup_tc_cls_flower(struct ocelot_port_private *priv,
243 			       struct flow_cls_offload *f,
244 			       bool ingress)
245 {
246 	struct ocelot *ocelot = priv->port.ocelot;
247 	int port = priv->chip_port;
248 
249 	if (!ingress)
250 		return -EOPNOTSUPP;
251 
252 	switch (f->command) {
253 	case FLOW_CLS_REPLACE:
254 		return ocelot_cls_flower_replace(ocelot, port, f, ingress);
255 	case FLOW_CLS_DESTROY:
256 		return ocelot_cls_flower_destroy(ocelot, port, f, ingress);
257 	case FLOW_CLS_STATS:
258 		return ocelot_cls_flower_stats(ocelot, port, f, ingress);
259 	default:
260 		return -EOPNOTSUPP;
261 	}
262 }
263