nfp: extend flower matching capabilities
[linux-2.6-microblaze.git] / drivers / net / ethernet / netronome / nfp / flower / match.c
1 /*
2  * Copyright (C) 2017 Netronome Systems, Inc.
3  *
4  * This software is dual licensed under the GNU General License Version 2,
5  * June 1991 as shown in the file COPYING in the top-level directory of this
6  * source tree or the BSD 2-Clause License provided below.  You have the
7  * option to license this software under the complete terms of either license.
8  *
9  * The BSD 2-Clause License:
10  *
11  *     Redistribution and use in source and binary forms, with or
12  *     without modification, are permitted provided that the following
13  *     conditions are met:
14  *
15  *      1. Redistributions of source code must retain the above
16  *         copyright notice, this list of conditions and the following
17  *         disclaimer.
18  *
19  *      2. Redistributions in binary form must reproduce the above
20  *         copyright notice, this list of conditions and the following
21  *         disclaimer in the documentation and/or other materials
22  *         provided with the distribution.
23  *
24  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
28  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
29  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
30  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31  * SOFTWARE.
32  */
33
34 #include <linux/bitfield.h>
35 #include <net/pkt_cls.h>
36
37 #include "cmsg.h"
38 #include "main.h"
39
40 static void
41 nfp_flower_compile_meta_tci(struct nfp_flower_meta_two *frame,
42                             struct tc_cls_flower_offload *flow, u8 key_type,
43                             bool mask_version)
44 {
45         struct flow_dissector_key_vlan *flow_vlan;
46         u16 tmp_tci;
47
48         /* Populate the metadata frame. */
49         frame->nfp_flow_key_layer = key_type;
50         frame->mask_id = ~0;
51
52         if (mask_version) {
53                 frame->tci = cpu_to_be16(~0);
54                 return;
55         }
56
57         flow_vlan = skb_flow_dissector_target(flow->dissector,
58                                               FLOW_DISSECTOR_KEY_VLAN,
59                                               flow->key);
60
61         /* Populate the tci field. */
62         if (!flow_vlan->vlan_id) {
63                 tmp_tci = 0;
64         } else {
65                 tmp_tci = FIELD_PREP(NFP_FLOWER_MASK_VLAN_PRIO,
66                                      flow_vlan->vlan_priority) |
67                           FIELD_PREP(NFP_FLOWER_MASK_VLAN_VID,
68                                      flow_vlan->vlan_id) |
69                           NFP_FLOWER_MASK_VLAN_CFI;
70         }
71         frame->tci = cpu_to_be16(tmp_tci);
72 }
73
74 static void
75 nfp_flower_compile_meta(struct nfp_flower_meta_one *frame, u8 key_type)
76 {
77         frame->nfp_flow_key_layer = key_type;
78         frame->mask_id = 0;
79         frame->reserved = 0;
80 }
81
82 static int
83 nfp_flower_compile_port(struct nfp_flower_in_port *frame, u32 cmsg_port,
84                         bool mask_version)
85 {
86         if (mask_version) {
87                 frame->in_port = cpu_to_be32(~0);
88                 return 0;
89         }
90
91         frame->in_port = cpu_to_be32(cmsg_port);
92
93         return 0;
94 }
95
96 static void
97 nfp_flower_compile_mac(struct nfp_flower_mac_mpls *frame,
98                        struct tc_cls_flower_offload *flow,
99                        bool mask_version)
100 {
101         struct fl_flow_key *target = mask_version ? flow->mask : flow->key;
102         struct flow_dissector_key_eth_addrs *flow_mac;
103
104         flow_mac = skb_flow_dissector_target(flow->dissector,
105                                              FLOW_DISSECTOR_KEY_ETH_ADDRS,
106                                              target);
107
108         memset(frame, 0, sizeof(struct nfp_flower_mac_mpls));
109
110         /* Populate mac frame. */
111         ether_addr_copy(frame->mac_dst, &flow_mac->dst[0]);
112         ether_addr_copy(frame->mac_src, &flow_mac->src[0]);
113
114         if (mask_version)
115                 frame->mpls_lse = cpu_to_be32(~0);
116 }
117
118 static void
119 nfp_flower_compile_tport(struct nfp_flower_tp_ports *frame,
120                          struct tc_cls_flower_offload *flow,
121                          bool mask_version)
122 {
123         struct fl_flow_key *target = mask_version ? flow->mask : flow->key;
124         struct flow_dissector_key_ports *flow_tp;
125
126         flow_tp = skb_flow_dissector_target(flow->dissector,
127                                             FLOW_DISSECTOR_KEY_PORTS,
128                                             target);
129
130         frame->port_src = flow_tp->src;
131         frame->port_dst = flow_tp->dst;
132 }
133
134 static void
135 nfp_flower_compile_ipv4(struct nfp_flower_ipv4 *frame,
136                         struct tc_cls_flower_offload *flow,
137                         bool mask_version)
138 {
139         struct fl_flow_key *target = mask_version ? flow->mask : flow->key;
140         struct flow_dissector_key_ipv4_addrs *flow_ipv4;
141         struct flow_dissector_key_basic *flow_basic;
142
143         flow_ipv4 = skb_flow_dissector_target(flow->dissector,
144                                               FLOW_DISSECTOR_KEY_IPV4_ADDRS,
145                                               target);
146
147         flow_basic = skb_flow_dissector_target(flow->dissector,
148                                                FLOW_DISSECTOR_KEY_BASIC,
149                                                target);
150
151         /* Populate IPv4 frame. */
152         frame->reserved = 0;
153         frame->ipv4_src = flow_ipv4->src;
154         frame->ipv4_dst = flow_ipv4->dst;
155         frame->proto = flow_basic->ip_proto;
156         /* Wildcard TOS/TTL for now. */
157         frame->tos = 0;
158         frame->ttl = 0;
159 }
160
161 static void
162 nfp_flower_compile_ipv6(struct nfp_flower_ipv6 *frame,
163                         struct tc_cls_flower_offload *flow,
164                         bool mask_version)
165 {
166         struct fl_flow_key *target = mask_version ? flow->mask : flow->key;
167         struct flow_dissector_key_ipv6_addrs *flow_ipv6;
168         struct flow_dissector_key_basic *flow_basic;
169
170         flow_ipv6 = skb_flow_dissector_target(flow->dissector,
171                                               FLOW_DISSECTOR_KEY_IPV6_ADDRS,
172                                               target);
173
174         flow_basic = skb_flow_dissector_target(flow->dissector,
175                                                FLOW_DISSECTOR_KEY_BASIC,
176                                                target);
177
178         /* Populate IPv6 frame. */
179         frame->reserved = 0;
180         frame->ipv6_src = flow_ipv6->src;
181         frame->ipv6_dst = flow_ipv6->dst;
182         frame->proto = flow_basic->ip_proto;
183         /* Wildcard LABEL/TOS/TTL for now. */
184         frame->ipv6_flow_label_exthdr = 0;
185         frame->tos = 0;
186         frame->ttl = 0;
187 }
188
189 int nfp_flower_compile_flow_match(struct tc_cls_flower_offload *flow,
190                                   struct nfp_fl_key_ls *key_ls,
191                                   struct net_device *netdev,
192                                   struct nfp_fl_payload *nfp_flow)
193 {
194         int err;
195         u8 *ext;
196         u8 *msk;
197
198         memset(nfp_flow->unmasked_data, 0, key_ls->key_size);
199         memset(nfp_flow->mask_data, 0, key_ls->key_size);
200
201         ext = nfp_flow->unmasked_data;
202         msk = nfp_flow->mask_data;
203         if (NFP_FLOWER_LAYER_PORT & key_ls->key_layer) {
204                 /* Populate Exact Metadata. */
205                 nfp_flower_compile_meta_tci((struct nfp_flower_meta_two *)ext,
206                                             flow, key_ls->key_layer, false);
207                 /* Populate Mask Metadata. */
208                 nfp_flower_compile_meta_tci((struct nfp_flower_meta_two *)msk,
209                                             flow, key_ls->key_layer, true);
210                 ext += sizeof(struct nfp_flower_meta_two);
211                 msk += sizeof(struct nfp_flower_meta_two);
212
213                 /* Populate Exact Port data. */
214                 err = nfp_flower_compile_port((struct nfp_flower_in_port *)ext,
215                                               nfp_repr_get_port_id(netdev),
216                                               false);
217                 if (err)
218                         return err;
219
220                 /* Populate Mask Port Data. */
221                 err = nfp_flower_compile_port((struct nfp_flower_in_port *)msk,
222                                               nfp_repr_get_port_id(netdev),
223                                               true);
224                 if (err)
225                         return err;
226
227                 ext += sizeof(struct nfp_flower_in_port);
228                 msk += sizeof(struct nfp_flower_in_port);
229         } else {
230                 /* Populate Exact Metadata. */
231                 nfp_flower_compile_meta((struct nfp_flower_meta_one *)ext,
232                                         key_ls->key_layer);
233                 /* Populate Mask Metadata. */
234                 nfp_flower_compile_meta((struct nfp_flower_meta_one *)msk,
235                                         key_ls->key_layer);
236                 ext += sizeof(struct nfp_flower_meta_one);
237                 msk += sizeof(struct nfp_flower_meta_one);
238         }
239
240         if (NFP_FLOWER_LAYER_META & key_ls->key_layer) {
241                 /* Additional Metadata Fields.
242                  * Currently unsupported.
243                  */
244                 return -EOPNOTSUPP;
245         }
246
247         if (NFP_FLOWER_LAYER_MAC & key_ls->key_layer) {
248                 /* Populate Exact MAC Data. */
249                 nfp_flower_compile_mac((struct nfp_flower_mac_mpls *)ext,
250                                        flow, false);
251                 /* Populate Mask MAC Data. */
252                 nfp_flower_compile_mac((struct nfp_flower_mac_mpls *)msk,
253                                        flow, true);
254                 ext += sizeof(struct nfp_flower_mac_mpls);
255                 msk += sizeof(struct nfp_flower_mac_mpls);
256         }
257
258         if (NFP_FLOWER_LAYER_TP & key_ls->key_layer) {
259                 /* Populate Exact TP Data. */
260                 nfp_flower_compile_tport((struct nfp_flower_tp_ports *)ext,
261                                          flow, false);
262                 /* Populate Mask TP Data. */
263                 nfp_flower_compile_tport((struct nfp_flower_tp_ports *)msk,
264                                          flow, true);
265                 ext += sizeof(struct nfp_flower_tp_ports);
266                 msk += sizeof(struct nfp_flower_tp_ports);
267         }
268
269         if (NFP_FLOWER_LAYER_IPV4 & key_ls->key_layer) {
270                 /* Populate Exact IPv4 Data. */
271                 nfp_flower_compile_ipv4((struct nfp_flower_ipv4 *)ext,
272                                         flow, false);
273                 /* Populate Mask IPv4 Data. */
274                 nfp_flower_compile_ipv4((struct nfp_flower_ipv4 *)msk,
275                                         flow, true);
276                 ext += sizeof(struct nfp_flower_ipv4);
277                 msk += sizeof(struct nfp_flower_ipv4);
278         }
279
280         if (NFP_FLOWER_LAYER_IPV6 & key_ls->key_layer) {
281                 /* Populate Exact IPv4 Data. */
282                 nfp_flower_compile_ipv6((struct nfp_flower_ipv6 *)ext,
283                                         flow, false);
284                 /* Populate Mask IPv4 Data. */
285                 nfp_flower_compile_ipv6((struct nfp_flower_ipv6 *)msk,
286                                         flow, true);
287                 ext += sizeof(struct nfp_flower_ipv6);
288                 msk += sizeof(struct nfp_flower_ipv6);
289         }
290
291         return 0;
292 }