Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  1// SPDX-License-Identifier: GPL-2.0+
  2/* Microchip VCAP TC
  3 *
  4 * Copyright (c) 2023 Microchip Technology Inc. and its subsidiaries.
  5 */
  6
  7#include <net/flow_offload.h>
  8#include <net/ipv6.h>
  9#include <net/tcp.h>
 10
 11#include "vcap_api_client.h"
 12#include "vcap_tc.h"
 13
 14enum vcap_is2_arp_opcode {
 15	VCAP_IS2_ARP_REQUEST,
 16	VCAP_IS2_ARP_REPLY,
 17	VCAP_IS2_RARP_REQUEST,
 18	VCAP_IS2_RARP_REPLY,
 19};
 20
 21enum vcap_arp_opcode {
 22	VCAP_ARP_OP_RESERVED,
 23	VCAP_ARP_OP_REQUEST,
 24	VCAP_ARP_OP_REPLY,
 25};
 26
 27int vcap_tc_flower_handler_ethaddr_usage(struct vcap_tc_flower_parse_usage *st)
 28{
 29	enum vcap_key_field smac_key = VCAP_KF_L2_SMAC;
 30	enum vcap_key_field dmac_key = VCAP_KF_L2_DMAC;
 31	struct flow_match_eth_addrs match;
 32	struct vcap_u48_key smac, dmac;
 33	int err = 0;
 34
 35	flow_rule_match_eth_addrs(st->frule, &match);
 36
 37	if (!is_zero_ether_addr(match.mask->src)) {
 38		vcap_netbytes_copy(smac.value, match.key->src, ETH_ALEN);
 39		vcap_netbytes_copy(smac.mask, match.mask->src, ETH_ALEN);
 40		err = vcap_rule_add_key_u48(st->vrule, smac_key, &smac);
 41		if (err)
 42			goto out;
 43	}
 44
 45	if (!is_zero_ether_addr(match.mask->dst)) {
 46		vcap_netbytes_copy(dmac.value, match.key->dst, ETH_ALEN);
 47		vcap_netbytes_copy(dmac.mask, match.mask->dst, ETH_ALEN);
 48		err = vcap_rule_add_key_u48(st->vrule, dmac_key, &dmac);
 49		if (err)
 50			goto out;
 51	}
 52
 53	st->used_keys |= BIT_ULL(FLOW_DISSECTOR_KEY_ETH_ADDRS);
 54
 55	return err;
 56
 57out:
 58	NL_SET_ERR_MSG_MOD(st->fco->common.extack, "eth_addr parse error");
 59	return err;
 60}
 61EXPORT_SYMBOL_GPL(vcap_tc_flower_handler_ethaddr_usage);
 62
 63int vcap_tc_flower_handler_ipv4_usage(struct vcap_tc_flower_parse_usage *st)
 64{
 65	int err = 0;
 66
 67	if (st->l3_proto == ETH_P_IP) {
 68		struct flow_match_ipv4_addrs mt;
 69
 70		flow_rule_match_ipv4_addrs(st->frule, &mt);
 71		if (mt.mask->src) {
 72			err = vcap_rule_add_key_u32(st->vrule,
 73						    VCAP_KF_L3_IP4_SIP,
 74						    be32_to_cpu(mt.key->src),
 75						    be32_to_cpu(mt.mask->src));
 76			if (err)
 77				goto out;
 78		}
 79		if (mt.mask->dst) {
 80			err = vcap_rule_add_key_u32(st->vrule,
 81						    VCAP_KF_L3_IP4_DIP,
 82						    be32_to_cpu(mt.key->dst),
 83						    be32_to_cpu(mt.mask->dst));
 84			if (err)
 85				goto out;
 86		}
 87	}
 88
 89	st->used_keys |= BIT_ULL(FLOW_DISSECTOR_KEY_IPV4_ADDRS);
 90
 91	return err;
 92
 93out:
 94	NL_SET_ERR_MSG_MOD(st->fco->common.extack, "ipv4_addr parse error");
 95	return err;
 96}
 97EXPORT_SYMBOL_GPL(vcap_tc_flower_handler_ipv4_usage);
 98
 99int vcap_tc_flower_handler_ipv6_usage(struct vcap_tc_flower_parse_usage *st)
100{
101	int err = 0;
102
103	if (st->l3_proto == ETH_P_IPV6) {
104		struct flow_match_ipv6_addrs mt;
105		struct vcap_u128_key sip;
106		struct vcap_u128_key dip;
107
108		flow_rule_match_ipv6_addrs(st->frule, &mt);
109		/* Check if address masks are non-zero */
110		if (!ipv6_addr_any(&mt.mask->src)) {
111			vcap_netbytes_copy(sip.value, mt.key->src.s6_addr, 16);
112			vcap_netbytes_copy(sip.mask, mt.mask->src.s6_addr, 16);
113			err = vcap_rule_add_key_u128(st->vrule,
114						     VCAP_KF_L3_IP6_SIP, &sip);
115			if (err)
116				goto out;
117		}
118		if (!ipv6_addr_any(&mt.mask->dst)) {
119			vcap_netbytes_copy(dip.value, mt.key->dst.s6_addr, 16);
120			vcap_netbytes_copy(dip.mask, mt.mask->dst.s6_addr, 16);
121			err = vcap_rule_add_key_u128(st->vrule,
122						     VCAP_KF_L3_IP6_DIP, &dip);
123			if (err)
124				goto out;
125		}
126	}
127	st->used_keys |= BIT_ULL(FLOW_DISSECTOR_KEY_IPV6_ADDRS);
128	return err;
129out:
130	NL_SET_ERR_MSG_MOD(st->fco->common.extack, "ipv6_addr parse error");
131	return err;
132}
133EXPORT_SYMBOL_GPL(vcap_tc_flower_handler_ipv6_usage);
134
135int vcap_tc_flower_handler_portnum_usage(struct vcap_tc_flower_parse_usage *st)
136{
137	struct flow_match_ports mt;
138	u16 value, mask;
139	int err = 0;
140
141	flow_rule_match_ports(st->frule, &mt);
142
143	if (mt.mask->src) {
144		value = be16_to_cpu(mt.key->src);
145		mask = be16_to_cpu(mt.mask->src);
146		err = vcap_rule_add_key_u32(st->vrule, VCAP_KF_L4_SPORT, value,
147					    mask);
148		if (err)
149			goto out;
150	}
151
152	if (mt.mask->dst) {
153		value = be16_to_cpu(mt.key->dst);
154		mask = be16_to_cpu(mt.mask->dst);
155		err = vcap_rule_add_key_u32(st->vrule, VCAP_KF_L4_DPORT, value,
156					    mask);
157		if (err)
158			goto out;
159	}
160
161	st->used_keys |= BIT_ULL(FLOW_DISSECTOR_KEY_PORTS);
162
163	return err;
164
165out:
166	NL_SET_ERR_MSG_MOD(st->fco->common.extack, "port parse error");
167	return err;
168}
169EXPORT_SYMBOL_GPL(vcap_tc_flower_handler_portnum_usage);
170
171int vcap_tc_flower_handler_cvlan_usage(struct vcap_tc_flower_parse_usage *st)
172{
173	enum vcap_key_field vid_key = VCAP_KF_8021Q_VID0;
174	enum vcap_key_field pcp_key = VCAP_KF_8021Q_PCP0;
175	struct flow_match_vlan mt;
176	u16 tpid;
177	int err;
178
179	flow_rule_match_cvlan(st->frule, &mt);
180
181	tpid = be16_to_cpu(mt.key->vlan_tpid);
182
183	if (tpid == ETH_P_8021Q) {
184		vid_key = VCAP_KF_8021Q_VID1;
185		pcp_key = VCAP_KF_8021Q_PCP1;
186	}
187
188	if (mt.mask->vlan_id) {
189		err = vcap_rule_add_key_u32(st->vrule, vid_key,
190					    mt.key->vlan_id,
191					    mt.mask->vlan_id);
192		if (err)
193			goto out;
194	}
195
196	if (mt.mask->vlan_priority) {
197		err = vcap_rule_add_key_u32(st->vrule, pcp_key,
198					    mt.key->vlan_priority,
199					    mt.mask->vlan_priority);
200		if (err)
201			goto out;
202	}
203
204	st->used_keys |= BIT_ULL(FLOW_DISSECTOR_KEY_CVLAN);
205
206	return 0;
207out:
208	NL_SET_ERR_MSG_MOD(st->fco->common.extack, "cvlan parse error");
209	return err;
210}
211EXPORT_SYMBOL_GPL(vcap_tc_flower_handler_cvlan_usage);
212
213int vcap_tc_flower_handler_vlan_usage(struct vcap_tc_flower_parse_usage *st,
214				      enum vcap_key_field vid_key,
215				      enum vcap_key_field pcp_key)
216{
217	struct flow_match_vlan mt;
218	int err;
219
220	flow_rule_match_vlan(st->frule, &mt);
221
222	if (mt.mask->vlan_id) {
223		err = vcap_rule_add_key_u32(st->vrule, vid_key,
224					    mt.key->vlan_id,
225					    mt.mask->vlan_id);
226		if (err)
227			goto out;
228	}
229
230	if (mt.mask->vlan_priority) {
231		err = vcap_rule_add_key_u32(st->vrule, pcp_key,
232					    mt.key->vlan_priority,
233					    mt.mask->vlan_priority);
234		if (err)
235			goto out;
236	}
237
238	if (mt.mask->vlan_tpid)
239		st->tpid = be16_to_cpu(mt.key->vlan_tpid);
240
241	st->used_keys |= BIT_ULL(FLOW_DISSECTOR_KEY_VLAN);
242
243	return 0;
244out:
245	NL_SET_ERR_MSG_MOD(st->fco->common.extack, "vlan parse error");
246	return err;
247}
248EXPORT_SYMBOL_GPL(vcap_tc_flower_handler_vlan_usage);
249
250int vcap_tc_flower_handler_tcp_usage(struct vcap_tc_flower_parse_usage *st)
251{
252	struct flow_match_tcp mt;
253	u16 tcp_flags_mask;
254	u16 tcp_flags_key;
255	enum vcap_bit val;
256	int err = 0;
257
258	flow_rule_match_tcp(st->frule, &mt);
259	tcp_flags_key = be16_to_cpu(mt.key->flags);
260	tcp_flags_mask = be16_to_cpu(mt.mask->flags);
261
262	if (tcp_flags_mask & TCPHDR_FIN) {
263		val = VCAP_BIT_0;
264		if (tcp_flags_key & TCPHDR_FIN)
265			val = VCAP_BIT_1;
266		err = vcap_rule_add_key_bit(st->vrule, VCAP_KF_L4_FIN, val);
267		if (err)
268			goto out;
269	}
270
271	if (tcp_flags_mask & TCPHDR_SYN) {
272		val = VCAP_BIT_0;
273		if (tcp_flags_key & TCPHDR_SYN)
274			val = VCAP_BIT_1;
275		err = vcap_rule_add_key_bit(st->vrule, VCAP_KF_L4_SYN, val);
276		if (err)
277			goto out;
278	}
279
280	if (tcp_flags_mask & TCPHDR_RST) {
281		val = VCAP_BIT_0;
282		if (tcp_flags_key & TCPHDR_RST)
283			val = VCAP_BIT_1;
284		err = vcap_rule_add_key_bit(st->vrule, VCAP_KF_L4_RST, val);
285		if (err)
286			goto out;
287	}
288
289	if (tcp_flags_mask & TCPHDR_PSH) {
290		val = VCAP_BIT_0;
291		if (tcp_flags_key & TCPHDR_PSH)
292			val = VCAP_BIT_1;
293		err = vcap_rule_add_key_bit(st->vrule, VCAP_KF_L4_PSH, val);
294		if (err)
295			goto out;
296	}
297
298	if (tcp_flags_mask & TCPHDR_ACK) {
299		val = VCAP_BIT_0;
300		if (tcp_flags_key & TCPHDR_ACK)
301			val = VCAP_BIT_1;
302		err = vcap_rule_add_key_bit(st->vrule, VCAP_KF_L4_ACK, val);
303		if (err)
304			goto out;
305	}
306
307	if (tcp_flags_mask & TCPHDR_URG) {
308		val = VCAP_BIT_0;
309		if (tcp_flags_key & TCPHDR_URG)
310			val = VCAP_BIT_1;
311		err = vcap_rule_add_key_bit(st->vrule, VCAP_KF_L4_URG, val);
312		if (err)
313			goto out;
314	}
315
316	st->used_keys |= BIT_ULL(FLOW_DISSECTOR_KEY_TCP);
317
318	return err;
319
320out:
321	NL_SET_ERR_MSG_MOD(st->fco->common.extack, "tcp_flags parse error");
322	return err;
323}
324EXPORT_SYMBOL_GPL(vcap_tc_flower_handler_tcp_usage);
325
326int vcap_tc_flower_handler_arp_usage(struct vcap_tc_flower_parse_usage *st)
327{
328	struct flow_match_arp mt;
329	u16 value, mask;
330	u32 ipval, ipmsk;
331	int err;
332
333	flow_rule_match_arp(st->frule, &mt);
334
335	if (mt.mask->op) {
336		mask = 0x3;
337		if (st->l3_proto == ETH_P_ARP) {
338			value = mt.key->op == VCAP_ARP_OP_REQUEST ?
339					VCAP_IS2_ARP_REQUEST :
340					VCAP_IS2_ARP_REPLY;
341		} else { /* RARP */
342			value = mt.key->op == VCAP_ARP_OP_REQUEST ?
343					VCAP_IS2_RARP_REQUEST :
344					VCAP_IS2_RARP_REPLY;
345		}
346		err = vcap_rule_add_key_u32(st->vrule, VCAP_KF_ARP_OPCODE,
347					    value, mask);
348		if (err)
349			goto out;
350	}
351
352	/* The IS2 ARP keyset does not support ARP hardware addresses */
353	if (!is_zero_ether_addr(mt.mask->sha) ||
354	    !is_zero_ether_addr(mt.mask->tha)) {
355		err = -EINVAL;
356		goto out;
357	}
358
359	if (mt.mask->sip) {
360		ipval = be32_to_cpu((__force __be32)mt.key->sip);
361		ipmsk = be32_to_cpu((__force __be32)mt.mask->sip);
362
363		err = vcap_rule_add_key_u32(st->vrule, VCAP_KF_L3_IP4_SIP,
364					    ipval, ipmsk);
365		if (err)
366			goto out;
367	}
368
369	if (mt.mask->tip) {
370		ipval = be32_to_cpu((__force __be32)mt.key->tip);
371		ipmsk = be32_to_cpu((__force __be32)mt.mask->tip);
372
373		err = vcap_rule_add_key_u32(st->vrule, VCAP_KF_L3_IP4_DIP,
374					    ipval, ipmsk);
375		if (err)
376			goto out;
377	}
378
379	st->used_keys |= BIT_ULL(FLOW_DISSECTOR_KEY_ARP);
380
381	return 0;
382
383out:
384	NL_SET_ERR_MSG_MOD(st->fco->common.extack, "arp parse error");
385	return err;
386}
387EXPORT_SYMBOL_GPL(vcap_tc_flower_handler_arp_usage);
388
389int vcap_tc_flower_handler_ip_usage(struct vcap_tc_flower_parse_usage *st)
390{
391	struct flow_match_ip mt;
392	int err = 0;
393
394	flow_rule_match_ip(st->frule, &mt);
395
396	if (mt.mask->tos) {
397		err = vcap_rule_add_key_u32(st->vrule, VCAP_KF_L3_TOS,
398					    mt.key->tos,
399					    mt.mask->tos);
400		if (err)
401			goto out;
402	}
403
404	st->used_keys |= BIT_ULL(FLOW_DISSECTOR_KEY_IP);
405
406	return err;
407
408out:
409	NL_SET_ERR_MSG_MOD(st->fco->common.extack, "ip_tos parse error");
410	return err;
411}
412EXPORT_SYMBOL_GPL(vcap_tc_flower_handler_ip_usage);