Merge branch 'nvme-4.18' of git://git.infradead.org/nvme into for-linus
[sfrench/cifs-2.6.git] / arch / um / drivers / vector_transports.c
1 /*
2  * Copyright (C) 2017 - Cambridge Greys Limited
3  * Copyright (C) 2011 - 2014 Cisco Systems Inc
4  * Licensed under the GPL.
5  */
6
7 #include <linux/etherdevice.h>
8 #include <linux/netdevice.h>
9 #include <linux/skbuff.h>
10 #include <linux/slab.h>
11 #include <asm/byteorder.h>
12 #include <uapi/linux/ip.h>
13 #include <uapi/linux/virtio_net.h>
14 #include <linux/virtio_net.h>
15 #include <linux/virtio_byteorder.h>
16 #include <linux/netdev_features.h>
17 #include "vector_user.h"
18 #include "vector_kern.h"
19
20 #define GOOD_LINEAR 512
21 #define GSO_ERROR "Incoming GSO frames and GRO disabled on the interface"
22
23 struct gre_minimal_header {
24         uint16_t header;
25         uint16_t arptype;
26 };
27
28
29 struct uml_gre_data {
30         uint32_t rx_key;
31         uint32_t tx_key;
32         uint32_t sequence;
33
34         bool ipv6;
35         bool has_sequence;
36         bool pin_sequence;
37         bool checksum;
38         bool key;
39         struct gre_minimal_header expected_header;
40
41         uint32_t checksum_offset;
42         uint32_t key_offset;
43         uint32_t sequence_offset;
44
45 };
46
47 struct uml_l2tpv3_data {
48         uint64_t rx_cookie;
49         uint64_t tx_cookie;
50         uint64_t rx_session;
51         uint64_t tx_session;
52         uint32_t counter;
53
54         bool udp;
55         bool ipv6;
56         bool has_counter;
57         bool pin_counter;
58         bool cookie;
59         bool cookie_is_64;
60
61         uint32_t cookie_offset;
62         uint32_t session_offset;
63         uint32_t counter_offset;
64 };
65
66 static int l2tpv3_form_header(uint8_t *header,
67         struct sk_buff *skb, struct vector_private *vp)
68 {
69         struct uml_l2tpv3_data *td = vp->transport_data;
70         uint32_t *counter;
71
72         if (td->udp)
73                 *(uint32_t *) header = cpu_to_be32(L2TPV3_DATA_PACKET);
74         (*(uint32_t *) (header + td->session_offset)) = td->tx_session;
75
76         if (td->cookie) {
77                 if (td->cookie_is_64)
78                         (*(uint64_t *)(header + td->cookie_offset)) =
79                                 td->tx_cookie;
80                 else
81                         (*(uint32_t *)(header + td->cookie_offset)) =
82                                 td->tx_cookie;
83         }
84         if (td->has_counter) {
85                 counter = (uint32_t *)(header + td->counter_offset);
86                 if (td->pin_counter) {
87                         *counter = 0;
88                 } else {
89                         td->counter++;
90                         *counter = cpu_to_be32(td->counter);
91                 }
92         }
93         return 0;
94 }
95
96 static int gre_form_header(uint8_t *header,
97                 struct sk_buff *skb, struct vector_private *vp)
98 {
99         struct uml_gre_data *td = vp->transport_data;
100         uint32_t *sequence;
101         *((uint32_t *) header) = *((uint32_t *) &td->expected_header);
102         if (td->key)
103                 (*(uint32_t *) (header + td->key_offset)) = td->tx_key;
104         if (td->has_sequence) {
105                 sequence = (uint32_t *)(header + td->sequence_offset);
106                 if (td->pin_sequence)
107                         *sequence = 0;
108                 else
109                         *sequence = cpu_to_be32(++td->sequence);
110         }
111         return 0;
112 }
113
114 static int raw_form_header(uint8_t *header,
115                 struct sk_buff *skb, struct vector_private *vp)
116 {
117         struct virtio_net_hdr *vheader = (struct virtio_net_hdr *) header;
118
119         virtio_net_hdr_from_skb(
120                 skb,
121                 vheader,
122                 virtio_legacy_is_little_endian(),
123                 false,
124                 0
125         );
126
127         return 0;
128 }
129
130 static int l2tpv3_verify_header(
131         uint8_t *header, struct sk_buff *skb, struct vector_private *vp)
132 {
133         struct uml_l2tpv3_data *td = vp->transport_data;
134         uint32_t *session;
135         uint64_t cookie;
136
137         if ((!td->udp) && (!td->ipv6))
138                 header += sizeof(struct iphdr) /* fix for ipv4 raw */;
139
140         /* we do not do a strict check for "data" packets as per
141          * the RFC spec because the pure IP spec does not have
142          * that anyway.
143          */
144
145         if (td->cookie) {
146                 if (td->cookie_is_64)
147                         cookie = *(uint64_t *)(header + td->cookie_offset);
148                 else
149                         cookie = *(uint32_t *)(header + td->cookie_offset);
150                 if (cookie != td->rx_cookie) {
151                         if (net_ratelimit())
152                                 netdev_err(vp->dev, "uml_l2tpv3: unknown cookie id");
153                         return -1;
154                 }
155         }
156         session = (uint32_t *) (header + td->session_offset);
157         if (*session != td->rx_session) {
158                 if (net_ratelimit())
159                         netdev_err(vp->dev, "uml_l2tpv3: session mismatch");
160                 return -1;
161         }
162         return 0;
163 }
164
165 static int gre_verify_header(
166         uint8_t *header, struct sk_buff *skb, struct vector_private *vp)
167 {
168
169         uint32_t key;
170         struct uml_gre_data *td = vp->transport_data;
171
172         if (!td->ipv6)
173                 header += sizeof(struct iphdr) /* fix for ipv4 raw */;
174
175         if (*((uint32_t *) header) != *((uint32_t *) &td->expected_header)) {
176                 if (net_ratelimit())
177                         netdev_err(vp->dev, "header type disagreement, expecting %0x, got %0x",
178                                 *((uint32_t *) &td->expected_header),
179                                 *((uint32_t *) header)
180                         );
181                 return -1;
182         }
183
184         if (td->key) {
185                 key = (*(uint32_t *)(header + td->key_offset));
186                 if (key != td->rx_key) {
187                         if (net_ratelimit())
188                                 netdev_err(vp->dev, "unknown key id %0x, expecting %0x",
189                                                 key, td->rx_key);
190                         return -1;
191                 }
192         }
193         return 0;
194 }
195
196 static int raw_verify_header(
197         uint8_t *header, struct sk_buff *skb, struct vector_private *vp)
198 {
199         struct virtio_net_hdr *vheader = (struct virtio_net_hdr *) header;
200
201         if ((vheader->gso_type != VIRTIO_NET_HDR_GSO_NONE) &&
202                 (vp->req_size != 65536)) {
203                 if (net_ratelimit())
204                         netdev_err(
205                                 vp->dev,
206                                 GSO_ERROR
207                 );
208         }
209         if ((vheader->flags & VIRTIO_NET_HDR_F_DATA_VALID) > 0)
210                 return 1;
211
212         virtio_net_hdr_to_skb(skb, vheader, virtio_legacy_is_little_endian());
213         return 0;
214 }
215
216 static bool get_uint_param(
217         struct arglist *def, char *param, unsigned int *result)
218 {
219         char *arg = uml_vector_fetch_arg(def, param);
220
221         if (arg != NULL) {
222                 if (kstrtoint(arg, 0, result) == 0)
223                         return true;
224         }
225         return false;
226 }
227
228 static bool get_ulong_param(
229         struct arglist *def, char *param, unsigned long *result)
230 {
231         char *arg = uml_vector_fetch_arg(def, param);
232
233         if (arg != NULL) {
234                 if (kstrtoul(arg, 0, result) == 0)
235                         return true;
236                 return true;
237         }
238         return false;
239 }
240
241 static int build_gre_transport_data(struct vector_private *vp)
242 {
243         struct uml_gre_data *td;
244         int temp_int;
245         int temp_rx;
246         int temp_tx;
247
248         vp->transport_data = kmalloc(sizeof(struct uml_gre_data), GFP_KERNEL);
249         if (vp->transport_data == NULL)
250                 return -ENOMEM;
251         td = vp->transport_data;
252         td->sequence = 0;
253
254         td->expected_header.arptype = GRE_IRB;
255         td->expected_header.header = 0;
256
257         vp->form_header = &gre_form_header;
258         vp->verify_header = &gre_verify_header;
259         vp->header_size = 4;
260         td->key_offset = 4;
261         td->sequence_offset = 4;
262         td->checksum_offset = 4;
263
264         td->ipv6 = false;
265         if (get_uint_param(vp->parsed, "v6", &temp_int)) {
266                 if (temp_int > 0)
267                         td->ipv6 = true;
268         }
269         td->key = false;
270         if (get_uint_param(vp->parsed, "rx_key", &temp_rx)) {
271                 if (get_uint_param(vp->parsed, "tx_key", &temp_tx)) {
272                         td->key = true;
273                         td->expected_header.header |= GRE_MODE_KEY;
274                         td->rx_key = cpu_to_be32(temp_rx);
275                         td->tx_key = cpu_to_be32(temp_tx);
276                         vp->header_size += 4;
277                         td->sequence_offset += 4;
278                 } else {
279                         return -EINVAL;
280                 }
281         }
282
283         td->sequence = false;
284         if (get_uint_param(vp->parsed, "sequence", &temp_int)) {
285                 if (temp_int > 0) {
286                         vp->header_size += 4;
287                         td->has_sequence = true;
288                         td->expected_header.header |= GRE_MODE_SEQUENCE;
289                         if (get_uint_param(
290                                 vp->parsed, "pin_sequence", &temp_int)) {
291                                 if (temp_int > 0)
292                                         td->pin_sequence = true;
293                         }
294                 }
295         }
296         vp->rx_header_size = vp->header_size;
297         if (!td->ipv6)
298                 vp->rx_header_size += sizeof(struct iphdr);
299         return 0;
300 }
301
302 static int build_l2tpv3_transport_data(struct vector_private *vp)
303 {
304
305         struct uml_l2tpv3_data *td;
306         int temp_int, temp_rxs, temp_txs;
307         unsigned long temp_rx;
308         unsigned long temp_tx;
309
310         vp->transport_data = kmalloc(
311                 sizeof(struct uml_l2tpv3_data), GFP_KERNEL);
312
313         if (vp->transport_data == NULL)
314                 return -ENOMEM;
315
316         td = vp->transport_data;
317
318         vp->form_header = &l2tpv3_form_header;
319         vp->verify_header = &l2tpv3_verify_header;
320         td->counter = 0;
321
322         vp->header_size = 4;
323         td->session_offset = 0;
324         td->cookie_offset = 4;
325         td->counter_offset = 4;
326
327
328         td->ipv6 = false;
329         if (get_uint_param(vp->parsed, "v6", &temp_int)) {
330                 if (temp_int > 0)
331                         td->ipv6 = true;
332         }
333
334         if (get_uint_param(vp->parsed, "rx_session", &temp_rxs)) {
335                 if (get_uint_param(vp->parsed, "tx_session", &temp_txs)) {
336                         td->tx_session = cpu_to_be32(temp_txs);
337                         td->rx_session = cpu_to_be32(temp_rxs);
338                 } else {
339                         return -EINVAL;
340                 }
341         } else {
342                 return -EINVAL;
343         }
344
345         td->cookie_is_64  = false;
346         if (get_uint_param(vp->parsed, "cookie64", &temp_int)) {
347                 if (temp_int > 0)
348                         td->cookie_is_64  = true;
349         }
350         td->cookie = false;
351         if (get_ulong_param(vp->parsed, "rx_cookie", &temp_rx)) {
352                 if (get_ulong_param(vp->parsed, "tx_cookie", &temp_tx)) {
353                         td->cookie = true;
354                         if (td->cookie_is_64) {
355                                 td->rx_cookie = cpu_to_be64(temp_rx);
356                                 td->tx_cookie = cpu_to_be64(temp_tx);
357                                 vp->header_size += 8;
358                                 td->counter_offset += 8;
359                         } else {
360                                 td->rx_cookie = cpu_to_be32(temp_rx);
361                                 td->tx_cookie = cpu_to_be32(temp_tx);
362                                 vp->header_size += 4;
363                                 td->counter_offset += 4;
364                         }
365                 } else {
366                         return -EINVAL;
367                 }
368         }
369
370         td->has_counter = false;
371         if (get_uint_param(vp->parsed, "counter", &temp_int)) {
372                 if (temp_int > 0) {
373                         td->has_counter = true;
374                         vp->header_size += 4;
375                         if (get_uint_param(
376                                 vp->parsed, "pin_counter", &temp_int)) {
377                                 if (temp_int > 0)
378                                         td->pin_counter = true;
379                         }
380                 }
381         }
382
383         if (get_uint_param(vp->parsed, "udp", &temp_int)) {
384                 if (temp_int > 0) {
385                         td->udp = true;
386                         vp->header_size += 4;
387                         td->counter_offset += 4;
388                         td->session_offset += 4;
389                         td->cookie_offset += 4;
390                 }
391         }
392
393         vp->rx_header_size = vp->header_size;
394         if ((!td->ipv6) && (!td->udp))
395                 vp->rx_header_size += sizeof(struct iphdr);
396
397         return 0;
398 }
399
400 static int build_raw_transport_data(struct vector_private *vp)
401 {
402         if (uml_raw_enable_vnet_headers(vp->fds->rx_fd)) {
403                 if (!uml_raw_enable_vnet_headers(vp->fds->tx_fd))
404                         return -1;
405                 vp->form_header = &raw_form_header;
406                 vp->verify_header = &raw_verify_header;
407                 vp->header_size = sizeof(struct virtio_net_hdr);
408                 vp->rx_header_size = sizeof(struct virtio_net_hdr);
409                 vp->dev->hw_features |= (NETIF_F_TSO | NETIF_F_GRO);
410                 vp->dev->features |=
411                         (NETIF_F_RXCSUM | NETIF_F_HW_CSUM |
412                                 NETIF_F_TSO | NETIF_F_GRO);
413                 netdev_info(
414                         vp->dev,
415                         "raw: using vnet headers for tso and tx/rx checksum"
416                 );
417         }
418         return 0;
419 }
420
421 static int build_tap_transport_data(struct vector_private *vp)
422 {
423         if (uml_raw_enable_vnet_headers(vp->fds->rx_fd)) {
424                 vp->form_header = &raw_form_header;
425                 vp->verify_header = &raw_verify_header;
426                 vp->header_size = sizeof(struct virtio_net_hdr);
427                 vp->rx_header_size = sizeof(struct virtio_net_hdr);
428                 vp->dev->hw_features |=
429                         (NETIF_F_TSO | NETIF_F_GSO | NETIF_F_GRO);
430                 vp->dev->features |=
431                         (NETIF_F_RXCSUM | NETIF_F_HW_CSUM |
432                                 NETIF_F_TSO | NETIF_F_GSO | NETIF_F_GRO);
433                 netdev_info(
434                         vp->dev,
435                         "tap/raw: using vnet headers for tso and tx/rx checksum"
436                 );
437         } else {
438                 return 0; /* do not try to enable tap too if raw failed */
439         }
440         if (uml_tap_enable_vnet_headers(vp->fds->tx_fd))
441                 return 0;
442         return -1;
443 }
444
445 int build_transport_data(struct vector_private *vp)
446 {
447         char *transport = uml_vector_fetch_arg(vp->parsed, "transport");
448
449         if (strncmp(transport, TRANS_GRE, TRANS_GRE_LEN) == 0)
450                 return build_gre_transport_data(vp);
451         if (strncmp(transport, TRANS_L2TPV3, TRANS_L2TPV3_LEN) == 0)
452                 return build_l2tpv3_transport_data(vp);
453         if (strncmp(transport, TRANS_RAW, TRANS_RAW_LEN) == 0)
454                 return build_raw_transport_data(vp);
455         if (strncmp(transport, TRANS_TAP, TRANS_TAP_LEN) == 0)
456                 return build_tap_transport_data(vp);
457         return 0;
458 }
459