]> Git Repo - J-linux.git/blob - drivers/net/ethernet/microchip/vcap/vcap_tc.c
Merge tag 'for-netdev' of https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf...
[J-linux.git] / drivers / net / ethernet / microchip / vcap / vcap_tc.c
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
14 enum 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
21 enum vcap_arp_opcode {
22         VCAP_ARP_OP_RESERVED,
23         VCAP_ARP_OP_REQUEST,
24         VCAP_ARP_OP_REPLY,
25 };
26
27 int 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
57 out:
58         NL_SET_ERR_MSG_MOD(st->fco->common.extack, "eth_addr parse error");
59         return err;
60 }
61 EXPORT_SYMBOL_GPL(vcap_tc_flower_handler_ethaddr_usage);
62
63 int 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
93 out:
94         NL_SET_ERR_MSG_MOD(st->fco->common.extack, "ipv4_addr parse error");
95         return err;
96 }
97 EXPORT_SYMBOL_GPL(vcap_tc_flower_handler_ipv4_usage);
98
99 int 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;
129 out:
130         NL_SET_ERR_MSG_MOD(st->fco->common.extack, "ipv6_addr parse error");
131         return err;
132 }
133 EXPORT_SYMBOL_GPL(vcap_tc_flower_handler_ipv6_usage);
134
135 int 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
165 out:
166         NL_SET_ERR_MSG_MOD(st->fco->common.extack, "port parse error");
167         return err;
168 }
169 EXPORT_SYMBOL_GPL(vcap_tc_flower_handler_portnum_usage);
170
171 int 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;
207 out:
208         NL_SET_ERR_MSG_MOD(st->fco->common.extack, "cvlan parse error");
209         return err;
210 }
211 EXPORT_SYMBOL_GPL(vcap_tc_flower_handler_cvlan_usage);
212
213 int 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;
244 out:
245         NL_SET_ERR_MSG_MOD(st->fco->common.extack, "vlan parse error");
246         return err;
247 }
248 EXPORT_SYMBOL_GPL(vcap_tc_flower_handler_vlan_usage);
249
250 int 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
320 out:
321         NL_SET_ERR_MSG_MOD(st->fco->common.extack, "tcp_flags parse error");
322         return err;
323 }
324 EXPORT_SYMBOL_GPL(vcap_tc_flower_handler_tcp_usage);
325
326 int 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
383 out:
384         NL_SET_ERR_MSG_MOD(st->fco->common.extack, "arp parse error");
385         return err;
386 }
387 EXPORT_SYMBOL_GPL(vcap_tc_flower_handler_arp_usage);
388
389 int 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
408 out:
409         NL_SET_ERR_MSG_MOD(st->fco->common.extack, "ip_tos parse error");
410         return err;
411 }
412 EXPORT_SYMBOL_GPL(vcap_tc_flower_handler_ip_usage);
This page took 0.058951 seconds and 4 git commands to generate.