]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/bhyve/net_backends.c
bhyve: Allocate struct vm_exit on the stack in vm_loop.
[FreeBSD/FreeBSD.git] / usr.sbin / bhyve / net_backends.c
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2019 Vincenzo Maffione <vmaffione@FreeBSD.org>
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
19  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
20  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
21  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
22  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
24  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
25  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  *
27  * $FreeBSD$
28  */
29
30 /*
31  * This file implements multiple network backends (tap, netmap, ...),
32  * to be used by network frontends such as virtio-net and e1000.
33  * The API to access the backend (e.g. send/receive packets, negotiate
34  * features) is exported by net_backends.h.
35  */
36
37 #include <sys/cdefs.h>
38 __FBSDID("$FreeBSD$");
39
40 #include <sys/types.h>          /* u_short etc */
41 #ifndef WITHOUT_CAPSICUM
42 #include <sys/capsicum.h>
43 #endif
44 #include <sys/ioctl.h>
45 #include <sys/mman.h>
46 #include <sys/uio.h>
47
48 #include <net/if.h>
49 #if defined(INET6) || defined(INET)
50 #include <net/if_tap.h>
51 #endif
52 #include <net/netmap.h>
53 #include <net/netmap_virt.h>
54 #define NETMAP_WITH_LIBS
55 #include <net/netmap_user.h>
56
57 #ifndef WITHOUT_CAPSICUM
58 #include <capsicum_helpers.h>
59 #endif
60 #include <err.h>
61 #include <errno.h>
62 #include <fcntl.h>
63 #include <stdio.h>
64 #include <stdlib.h>
65 #include <stdint.h>
66 #include <string.h>
67 #include <unistd.h>
68 #include <sysexits.h>
69 #include <assert.h>
70 #include <pthread.h>
71 #include <pthread_np.h>
72 #include <poll.h>
73 #include <assert.h>
74
75 #ifdef NETGRAPH
76 #include <sys/param.h>
77 #include <sys/sysctl.h>
78 #include <netgraph.h>
79 #endif
80
81 #include "config.h"
82 #include "debug.h"
83 #include "iov.h"
84 #include "mevent.h"
85 #include "net_backends.h"
86 #include "pci_emul.h"
87
88 #include <sys/linker_set.h>
89
90 /*
91  * Each network backend registers a set of function pointers that are
92  * used to implement the net backends API.
93  * This might need to be exposed if we implement backends in separate files.
94  */
95 struct net_backend {
96         const char *prefix;     /* prefix matching this backend */
97
98         /*
99          * Routines used to initialize and cleanup the resources needed
100          * by a backend. The cleanup function is used internally,
101          * and should not be called by the frontend.
102          */
103         int (*init)(struct net_backend *be, const char *devname,
104             nvlist_t *nvl, net_be_rxeof_t cb, void *param);
105         void (*cleanup)(struct net_backend *be);
106
107         /*
108          * Called to serve a guest transmit request. The scatter-gather
109          * vector provided by the caller has 'iovcnt' elements and contains
110          * the packet to send.
111          */
112         ssize_t (*send)(struct net_backend *be, const struct iovec *iov,
113             int iovcnt);
114
115         /*
116          * Get the length of the next packet that can be received from
117          * the backend. If no packets are currently available, this
118          * function returns 0.
119          */
120         ssize_t (*peek_recvlen)(struct net_backend *be);
121
122         /*
123          * Called to receive a packet from the backend. When the function
124          * returns a positive value 'len', the scatter-gather vector
125          * provided by the caller contains a packet with such length.
126          * The function returns 0 if the backend doesn't have a new packet to
127          * receive.
128          */
129         ssize_t (*recv)(struct net_backend *be, const struct iovec *iov,
130             int iovcnt);
131
132         /*
133          * Ask the backend to enable or disable receive operation in the
134          * backend. On return from a disable operation, it is guaranteed
135          * that the receive callback won't be called until receive is
136          * enabled again. Note however that it is up to the caller to make
137          * sure that netbe_recv() is not currently being executed by another
138          * thread.
139          */
140         void (*recv_enable)(struct net_backend *be);
141         void (*recv_disable)(struct net_backend *be);
142
143         /*
144          * Ask the backend for the virtio-net features it is able to
145          * support. Possible features are TSO, UFO and checksum offloading
146          * in both rx and tx direction and for both IPv4 and IPv6.
147          */
148         uint64_t (*get_cap)(struct net_backend *be);
149
150         /*
151          * Tell the backend to enable/disable the specified virtio-net
152          * features (capabilities).
153          */
154         int (*set_cap)(struct net_backend *be, uint64_t features,
155             unsigned int vnet_hdr_len);
156
157         struct pci_vtnet_softc *sc;
158         int fd;
159
160         /*
161          * Length of the virtio-net header used by the backend and the
162          * frontend, respectively. A zero value means that the header
163          * is not used.
164          */
165         unsigned int be_vnet_hdr_len;
166         unsigned int fe_vnet_hdr_len;
167
168         /* Size of backend-specific private data. */
169         size_t priv_size;
170
171         /* Backend-specific private data follows. */
172 };
173
174 #define NET_BE_PRIV(be)         ((void *)((be) + 1))
175 #define NET_BE_SIZE(be)         (sizeof(*be) + (be)->priv_size)
176
177 SET_DECLARE(net_backend_set, struct net_backend);
178
179 #define VNET_HDR_LEN    sizeof(struct virtio_net_rxhdr)
180
181 #define WPRINTF(params) PRINTLN params
182
183 /*
184  * The tap backend
185  */
186
187 #if defined(INET6) || defined(INET)
188 static const int pf_list[] = {
189 #if defined(INET6)
190         PF_INET6,
191 #endif
192 #if defined(INET)
193         PF_INET,
194 #endif
195 };
196 #endif
197
198 struct tap_priv {
199         struct mevent *mevp;
200         /*
201          * A bounce buffer that allows us to implement the peek_recvlen
202          * callback. In the future we may get the same information from
203          * the kevent data.
204          */
205         char bbuf[1 << 16];
206         ssize_t bbuflen;
207 };
208
209 static void
210 tap_cleanup(struct net_backend *be)
211 {
212         struct tap_priv *priv = NET_BE_PRIV(be);
213
214         if (priv->mevp) {
215                 mevent_delete(priv->mevp);
216         }
217         if (be->fd != -1) {
218                 close(be->fd);
219                 be->fd = -1;
220         }
221 }
222
223 static int
224 tap_init(struct net_backend *be, const char *devname,
225     nvlist_t *nvl __unused, net_be_rxeof_t cb, void *param)
226 {
227         struct tap_priv *priv = NET_BE_PRIV(be);
228         char tbuf[80];
229         int opt = 1;
230 #if defined(INET6) || defined(INET)
231         struct ifreq ifrq;
232         int s;
233 #endif
234 #ifndef WITHOUT_CAPSICUM
235         cap_rights_t rights;
236 #endif
237
238         if (cb == NULL) {
239                 WPRINTF(("TAP backend requires non-NULL callback"));
240                 return (-1);
241         }
242
243         strcpy(tbuf, "/dev/");
244         strlcat(tbuf, devname, sizeof(tbuf));
245
246         be->fd = open(tbuf, O_RDWR);
247         if (be->fd == -1) {
248                 WPRINTF(("open of tap device %s failed", tbuf));
249                 goto error;
250         }
251
252         /*
253          * Set non-blocking and register for read
254          * notifications with the event loop
255          */
256         if (ioctl(be->fd, FIONBIO, &opt) < 0) {
257                 WPRINTF(("tap device O_NONBLOCK failed"));
258                 goto error;
259         }
260
261 #if defined(INET6) || defined(INET)
262         /*
263          * Try to UP the interface rather than relying on
264          * net.link.tap.up_on_open.
265           */
266         bzero(&ifrq, sizeof(ifrq));
267         if (ioctl(be->fd, TAPGIFNAME, &ifrq) < 0) {
268                 WPRINTF(("Could not get interface name"));
269                 goto error;
270         }
271
272         s = -1;
273         for (size_t i = 0; s == -1 && i < nitems(pf_list); i++)
274                 s = socket(pf_list[i], SOCK_DGRAM, 0);
275         if (s == -1) {
276                 WPRINTF(("Could open socket"));
277                 goto error;
278         }
279
280         if (ioctl(s, SIOCGIFFLAGS, &ifrq) < 0) {
281                 (void)close(s);
282                 WPRINTF(("Could not get interface flags"));
283                 goto error;
284         }
285         ifrq.ifr_flags |= IFF_UP;
286         if (ioctl(s, SIOCSIFFLAGS, &ifrq) < 0) {
287                 (void)close(s);
288                 WPRINTF(("Could not set interface flags"));
289                 goto error;
290         }
291         (void)close(s);
292 #endif
293
294 #ifndef WITHOUT_CAPSICUM
295         cap_rights_init(&rights, CAP_EVENT, CAP_READ, CAP_WRITE);
296         if (caph_rights_limit(be->fd, &rights) == -1)
297                 errx(EX_OSERR, "Unable to apply rights for sandbox");
298 #endif
299
300         memset(priv->bbuf, 0, sizeof(priv->bbuf));
301         priv->bbuflen = 0;
302
303         priv->mevp = mevent_add_disabled(be->fd, EVF_READ, cb, param);
304         if (priv->mevp == NULL) {
305                 WPRINTF(("Could not register event"));
306                 goto error;
307         }
308
309         return (0);
310
311 error:
312         tap_cleanup(be);
313         return (-1);
314 }
315
316 /*
317  * Called to send a buffer chain out to the tap device
318  */
319 static ssize_t
320 tap_send(struct net_backend *be, const struct iovec *iov, int iovcnt)
321 {
322         return (writev(be->fd, iov, iovcnt));
323 }
324
325 static ssize_t
326 tap_peek_recvlen(struct net_backend *be)
327 {
328         struct tap_priv *priv = NET_BE_PRIV(be);
329         ssize_t ret;
330
331         if (priv->bbuflen > 0) {
332                 /*
333                  * We already have a packet in the bounce buffer.
334                  * Just return its length.
335                  */
336                 return priv->bbuflen;
337         }
338
339         /*
340          * Read the next packet (if any) into the bounce buffer, so
341          * that we get to know its length and we can return that
342          * to the caller.
343          */
344         ret = read(be->fd, priv->bbuf, sizeof(priv->bbuf));
345         if (ret < 0 && errno == EWOULDBLOCK) {
346                 return (0);
347         }
348
349         if (ret > 0)
350                 priv->bbuflen = ret;
351
352         return (ret);
353 }
354
355 static ssize_t
356 tap_recv(struct net_backend *be, const struct iovec *iov, int iovcnt)
357 {
358         struct tap_priv *priv = NET_BE_PRIV(be);
359         ssize_t ret;
360
361         if (priv->bbuflen > 0) {
362                 /*
363                  * A packet is available in the bounce buffer, so
364                  * we read it from there.
365                  */
366                 ret = buf_to_iov(priv->bbuf, priv->bbuflen,
367                     iov, iovcnt, 0);
368
369                 /* Mark the bounce buffer as empty. */
370                 priv->bbuflen = 0;
371
372                 return (ret);
373         }
374
375         ret = readv(be->fd, iov, iovcnt);
376         if (ret < 0 && errno == EWOULDBLOCK) {
377                 return (0);
378         }
379
380         return (ret);
381 }
382
383 static void
384 tap_recv_enable(struct net_backend *be)
385 {
386         struct tap_priv *priv = NET_BE_PRIV(be);
387
388         mevent_enable(priv->mevp);
389 }
390
391 static void
392 tap_recv_disable(struct net_backend *be)
393 {
394         struct tap_priv *priv = NET_BE_PRIV(be);
395
396         mevent_disable(priv->mevp);
397 }
398
399 static uint64_t
400 tap_get_cap(struct net_backend *be __unused)
401 {
402
403         return (0); /* no capabilities for now */
404 }
405
406 static int
407 tap_set_cap(struct net_backend *be __unused, uint64_t features,
408     unsigned vnet_hdr_len)
409 {
410
411         return ((features || vnet_hdr_len) ? -1 : 0);
412 }
413
414 static struct net_backend tap_backend = {
415         .prefix = "tap",
416         .priv_size = sizeof(struct tap_priv),
417         .init = tap_init,
418         .cleanup = tap_cleanup,
419         .send = tap_send,
420         .peek_recvlen = tap_peek_recvlen,
421         .recv = tap_recv,
422         .recv_enable = tap_recv_enable,
423         .recv_disable = tap_recv_disable,
424         .get_cap = tap_get_cap,
425         .set_cap = tap_set_cap,
426 };
427
428 /* A clone of the tap backend, with a different prefix. */
429 static struct net_backend vmnet_backend = {
430         .prefix = "vmnet",
431         .priv_size = sizeof(struct tap_priv),
432         .init = tap_init,
433         .cleanup = tap_cleanup,
434         .send = tap_send,
435         .peek_recvlen = tap_peek_recvlen,
436         .recv = tap_recv,
437         .recv_enable = tap_recv_enable,
438         .recv_disable = tap_recv_disable,
439         .get_cap = tap_get_cap,
440         .set_cap = tap_set_cap,
441 };
442
443 DATA_SET(net_backend_set, tap_backend);
444 DATA_SET(net_backend_set, vmnet_backend);
445
446 #ifdef NETGRAPH
447
448 /*
449  * Netgraph backend
450  */
451
452 #define NG_SBUF_MAX_SIZE (4 * 1024 * 1024)
453
454 static int
455 ng_init(struct net_backend *be, const char *devname __unused,
456          nvlist_t *nvl, net_be_rxeof_t cb, void *param)
457 {
458         struct tap_priv *p = NET_BE_PRIV(be);
459         struct ngm_connect ngc;
460         const char *value, *nodename;
461         int sbsz;
462         int ctrl_sock;
463         int flags;
464         unsigned long maxsbsz;
465         size_t msbsz;
466 #ifndef WITHOUT_CAPSICUM
467         cap_rights_t rights;
468 #endif
469
470         if (cb == NULL) {
471                 WPRINTF(("Netgraph backend requires non-NULL callback"));
472                 return (-1);
473         }
474
475         be->fd = -1;
476
477         memset(&ngc, 0, sizeof(ngc));
478
479         value = get_config_value_node(nvl, "path");
480         if (value == NULL) {
481                 WPRINTF(("path must be provided"));
482                 return (-1);
483         }
484         strncpy(ngc.path, value, NG_PATHSIZ - 1);
485
486         value = get_config_value_node(nvl, "hook");
487         if (value == NULL)
488                 value = "vmlink";
489         strncpy(ngc.ourhook, value, NG_HOOKSIZ - 1);
490
491         value = get_config_value_node(nvl, "peerhook");
492         if (value == NULL) {
493                 WPRINTF(("peer hook must be provided"));
494                 return (-1);
495         }
496         strncpy(ngc.peerhook, value, NG_HOOKSIZ - 1);
497
498         nodename = get_config_value_node(nvl, "socket");
499         if (NgMkSockNode(nodename,
500                 &ctrl_sock, &be->fd) < 0) {
501                 WPRINTF(("can't get Netgraph sockets"));
502                 return (-1);
503         }
504
505         if (NgSendMsg(ctrl_sock, ".",
506                 NGM_GENERIC_COOKIE,
507                 NGM_CONNECT, &ngc, sizeof(ngc)) < 0) {
508                 WPRINTF(("can't connect to node"));
509                 close(ctrl_sock);
510                 goto error;
511         }
512
513         close(ctrl_sock);
514
515         flags = fcntl(be->fd, F_GETFL);
516
517         if (flags < 0) {
518                 WPRINTF(("can't get socket flags"));
519                 goto error;
520         }
521
522         if (fcntl(be->fd, F_SETFL, flags | O_NONBLOCK) < 0) {
523                 WPRINTF(("can't set O_NONBLOCK flag"));
524                 goto error;
525         }
526
527         /*
528          * The default ng_socket(4) buffer's size is too low.
529          * Calculate the minimum value between NG_SBUF_MAX_SIZE
530          * and kern.ipc.maxsockbuf.
531          */
532         msbsz = sizeof(maxsbsz);
533         if (sysctlbyname("kern.ipc.maxsockbuf", &maxsbsz, &msbsz,
534                 NULL, 0) < 0) {
535                 WPRINTF(("can't get 'kern.ipc.maxsockbuf' value"));
536                 goto error;
537         }
538
539         /*
540          * We can't set the socket buffer size to kern.ipc.maxsockbuf value,
541          * as it takes into account the mbuf(9) overhead.
542          */
543         maxsbsz = maxsbsz * MCLBYTES / (MSIZE + MCLBYTES);
544
545         sbsz = MIN(NG_SBUF_MAX_SIZE, maxsbsz);
546
547         if (setsockopt(be->fd, SOL_SOCKET, SO_SNDBUF, &sbsz,
548                 sizeof(sbsz)) < 0) {
549                 WPRINTF(("can't set TX buffer size"));
550                 goto error;
551         }
552
553         if (setsockopt(be->fd, SOL_SOCKET, SO_RCVBUF, &sbsz,
554                 sizeof(sbsz)) < 0) {
555                 WPRINTF(("can't set RX buffer size"));
556                 goto error;
557         }
558
559 #ifndef WITHOUT_CAPSICUM
560         cap_rights_init(&rights, CAP_EVENT, CAP_READ, CAP_WRITE);
561         if (caph_rights_limit(be->fd, &rights) == -1)
562                 errx(EX_OSERR, "Unable to apply rights for sandbox");
563 #endif
564
565         memset(p->bbuf, 0, sizeof(p->bbuf));
566         p->bbuflen = 0;
567
568         p->mevp = mevent_add_disabled(be->fd, EVF_READ, cb, param);
569         if (p->mevp == NULL) {
570                 WPRINTF(("Could not register event"));
571                 goto error;
572         }
573
574         return (0);
575
576 error:
577         tap_cleanup(be);
578         return (-1);
579 }
580
581 static struct net_backend ng_backend = {
582         .prefix = "netgraph",
583         .priv_size = sizeof(struct tap_priv),
584         .init = ng_init,
585         .cleanup = tap_cleanup,
586         .send = tap_send,
587         .peek_recvlen = tap_peek_recvlen,
588         .recv = tap_recv,
589         .recv_enable = tap_recv_enable,
590         .recv_disable = tap_recv_disable,
591         .get_cap = tap_get_cap,
592         .set_cap = tap_set_cap,
593 };
594
595 DATA_SET(net_backend_set, ng_backend);
596
597 #endif /* NETGRAPH */
598
599 /*
600  * The netmap backend
601  */
602
603 /* The virtio-net features supported by netmap. */
604 #define NETMAP_FEATURES (VIRTIO_NET_F_CSUM | VIRTIO_NET_F_HOST_TSO4 | \
605                 VIRTIO_NET_F_HOST_TSO6 | VIRTIO_NET_F_HOST_UFO | \
606                 VIRTIO_NET_F_GUEST_CSUM | VIRTIO_NET_F_GUEST_TSO4 | \
607                 VIRTIO_NET_F_GUEST_TSO6 | VIRTIO_NET_F_GUEST_UFO)
608
609 struct netmap_priv {
610         char ifname[IFNAMSIZ];
611         struct nm_desc *nmd;
612         uint16_t memid;
613         struct netmap_ring *rx;
614         struct netmap_ring *tx;
615         struct mevent *mevp;
616         net_be_rxeof_t cb;
617         void *cb_param;
618 };
619
620 static void
621 nmreq_init(struct nmreq *req, char *ifname)
622 {
623
624         memset(req, 0, sizeof(*req));
625         strlcpy(req->nr_name, ifname, sizeof(req->nr_name));
626         req->nr_version = NETMAP_API;
627 }
628
629 static int
630 netmap_set_vnet_hdr_len(struct net_backend *be, int vnet_hdr_len)
631 {
632         int err;
633         struct nmreq req;
634         struct netmap_priv *priv = NET_BE_PRIV(be);
635
636         nmreq_init(&req, priv->ifname);
637         req.nr_cmd = NETMAP_BDG_VNET_HDR;
638         req.nr_arg1 = vnet_hdr_len;
639         err = ioctl(be->fd, NIOCREGIF, &req);
640         if (err) {
641                 WPRINTF(("Unable to set vnet header length %d",
642                                 vnet_hdr_len));
643                 return (err);
644         }
645
646         be->be_vnet_hdr_len = vnet_hdr_len;
647
648         return (0);
649 }
650
651 static int
652 netmap_has_vnet_hdr_len(struct net_backend *be, unsigned vnet_hdr_len)
653 {
654         unsigned prev_hdr_len = be->be_vnet_hdr_len;
655         int ret;
656
657         if (vnet_hdr_len == prev_hdr_len) {
658                 return (1);
659         }
660
661         ret = netmap_set_vnet_hdr_len(be, vnet_hdr_len);
662         if (ret) {
663                 return (0);
664         }
665
666         netmap_set_vnet_hdr_len(be, prev_hdr_len);
667
668         return (1);
669 }
670
671 static uint64_t
672 netmap_get_cap(struct net_backend *be)
673 {
674
675         return (netmap_has_vnet_hdr_len(be, VNET_HDR_LEN) ?
676             NETMAP_FEATURES : 0);
677 }
678
679 static int
680 netmap_set_cap(struct net_backend *be, uint64_t features __unused,
681     unsigned vnet_hdr_len)
682 {
683
684         return (netmap_set_vnet_hdr_len(be, vnet_hdr_len));
685 }
686
687 static int
688 netmap_init(struct net_backend *be, const char *devname,
689     nvlist_t *nvl __unused, net_be_rxeof_t cb, void *param)
690 {
691         struct netmap_priv *priv = NET_BE_PRIV(be);
692
693         strlcpy(priv->ifname, devname, sizeof(priv->ifname));
694         priv->ifname[sizeof(priv->ifname) - 1] = '\0';
695
696         priv->nmd = nm_open(priv->ifname, NULL, NETMAP_NO_TX_POLL, NULL);
697         if (priv->nmd == NULL) {
698                 WPRINTF(("Unable to nm_open(): interface '%s', errno (%s)",
699                         devname, strerror(errno)));
700                 return (-1);
701         }
702
703         priv->memid = priv->nmd->req.nr_arg2;
704         priv->tx = NETMAP_TXRING(priv->nmd->nifp, 0);
705         priv->rx = NETMAP_RXRING(priv->nmd->nifp, 0);
706         priv->cb = cb;
707         priv->cb_param = param;
708         be->fd = priv->nmd->fd;
709
710         priv->mevp = mevent_add_disabled(be->fd, EVF_READ, cb, param);
711         if (priv->mevp == NULL) {
712                 WPRINTF(("Could not register event"));
713                 return (-1);
714         }
715
716         return (0);
717 }
718
719 static void
720 netmap_cleanup(struct net_backend *be)
721 {
722         struct netmap_priv *priv = NET_BE_PRIV(be);
723
724         if (priv->mevp) {
725                 mevent_delete(priv->mevp);
726         }
727         if (priv->nmd) {
728                 nm_close(priv->nmd);
729         }
730         be->fd = -1;
731 }
732
733 static ssize_t
734 netmap_send(struct net_backend *be, const struct iovec *iov,
735             int iovcnt)
736 {
737         struct netmap_priv *priv = NET_BE_PRIV(be);
738         struct netmap_ring *ring;
739         ssize_t totlen = 0;
740         int nm_buf_size;
741         int nm_buf_len;
742         uint32_t head;
743         uint8_t *nm_buf;
744         int j;
745
746         ring = priv->tx;
747         head = ring->head;
748         if (head == ring->tail) {
749                 WPRINTF(("No space, drop %zu bytes", count_iov(iov, iovcnt)));
750                 goto txsync;
751         }
752         nm_buf = NETMAP_BUF(ring, ring->slot[head].buf_idx);
753         nm_buf_size = ring->nr_buf_size;
754         nm_buf_len = 0;
755
756         for (j = 0; j < iovcnt; j++) {
757                 uint8_t *iov_frag_buf = iov[j].iov_base;
758                 int iov_frag_size = iov[j].iov_len;
759
760                 totlen += iov_frag_size;
761
762                 /*
763                  * Split each iovec fragment over more netmap slots, if
764                  * necessary.
765                  */
766                 for (;;) {
767                         int copylen;
768
769                         copylen = iov_frag_size < nm_buf_size ? iov_frag_size : nm_buf_size;
770                         memcpy(nm_buf, iov_frag_buf, copylen);
771
772                         iov_frag_buf += copylen;
773                         iov_frag_size -= copylen;
774                         nm_buf += copylen;
775                         nm_buf_size -= copylen;
776                         nm_buf_len += copylen;
777
778                         if (iov_frag_size == 0) {
779                                 break;
780                         }
781
782                         ring->slot[head].len = nm_buf_len;
783                         ring->slot[head].flags = NS_MOREFRAG;
784                         head = nm_ring_next(ring, head);
785                         if (head == ring->tail) {
786                                 /*
787                                  * We ran out of netmap slots while
788                                  * splitting the iovec fragments.
789                                  */
790                                 WPRINTF(("No space, drop %zu bytes",
791                                    count_iov(iov, iovcnt)));
792                                 goto txsync;
793                         }
794                         nm_buf = NETMAP_BUF(ring, ring->slot[head].buf_idx);
795                         nm_buf_size = ring->nr_buf_size;
796                         nm_buf_len = 0;
797                 }
798         }
799
800         /* Complete the last slot, which must not have NS_MOREFRAG set. */
801         ring->slot[head].len = nm_buf_len;
802         ring->slot[head].flags = 0;
803         head = nm_ring_next(ring, head);
804
805         /* Now update ring->head and ring->cur. */
806         ring->head = ring->cur = head;
807 txsync:
808         ioctl(be->fd, NIOCTXSYNC, NULL);
809
810         return (totlen);
811 }
812
813 static ssize_t
814 netmap_peek_recvlen(struct net_backend *be)
815 {
816         struct netmap_priv *priv = NET_BE_PRIV(be);
817         struct netmap_ring *ring = priv->rx;
818         uint32_t head = ring->head;
819         ssize_t totlen = 0;
820
821         while (head != ring->tail) {
822                 struct netmap_slot *slot = ring->slot + head;
823
824                 totlen += slot->len;
825                 if ((slot->flags & NS_MOREFRAG) == 0)
826                         break;
827                 head = nm_ring_next(ring, head);
828         }
829
830         return (totlen);
831 }
832
833 static ssize_t
834 netmap_recv(struct net_backend *be, const struct iovec *iov, int iovcnt)
835 {
836         struct netmap_priv *priv = NET_BE_PRIV(be);
837         struct netmap_slot *slot = NULL;
838         struct netmap_ring *ring;
839         uint8_t *iov_frag_buf;
840         int iov_frag_size;
841         ssize_t totlen = 0;
842         uint32_t head;
843
844         assert(iovcnt);
845
846         ring = priv->rx;
847         head = ring->head;
848         iov_frag_buf = iov->iov_base;
849         iov_frag_size = iov->iov_len;
850
851         do {
852                 uint8_t *nm_buf;
853                 int nm_buf_len;
854
855                 if (head == ring->tail) {
856                         return (0);
857                 }
858
859                 slot = ring->slot + head;
860                 nm_buf = NETMAP_BUF(ring, slot->buf_idx);
861                 nm_buf_len = slot->len;
862
863                 for (;;) {
864                         int copylen = nm_buf_len < iov_frag_size ?
865                             nm_buf_len : iov_frag_size;
866
867                         memcpy(iov_frag_buf, nm_buf, copylen);
868                         nm_buf += copylen;
869                         nm_buf_len -= copylen;
870                         iov_frag_buf += copylen;
871                         iov_frag_size -= copylen;
872                         totlen += copylen;
873
874                         if (nm_buf_len == 0) {
875                                 break;
876                         }
877
878                         iov++;
879                         iovcnt--;
880                         if (iovcnt == 0) {
881                                 /* No space to receive. */
882                                 WPRINTF(("Short iov, drop %zd bytes",
883                                     totlen));
884                                 return (-ENOSPC);
885                         }
886                         iov_frag_buf = iov->iov_base;
887                         iov_frag_size = iov->iov_len;
888                 }
889
890                 head = nm_ring_next(ring, head);
891
892         } while (slot->flags & NS_MOREFRAG);
893
894         /* Release slots to netmap. */
895         ring->head = ring->cur = head;
896
897         return (totlen);
898 }
899
900 static void
901 netmap_recv_enable(struct net_backend *be)
902 {
903         struct netmap_priv *priv = NET_BE_PRIV(be);
904
905         mevent_enable(priv->mevp);
906 }
907
908 static void
909 netmap_recv_disable(struct net_backend *be)
910 {
911         struct netmap_priv *priv = NET_BE_PRIV(be);
912
913         mevent_disable(priv->mevp);
914 }
915
916 static struct net_backend netmap_backend = {
917         .prefix = "netmap",
918         .priv_size = sizeof(struct netmap_priv),
919         .init = netmap_init,
920         .cleanup = netmap_cleanup,
921         .send = netmap_send,
922         .peek_recvlen = netmap_peek_recvlen,
923         .recv = netmap_recv,
924         .recv_enable = netmap_recv_enable,
925         .recv_disable = netmap_recv_disable,
926         .get_cap = netmap_get_cap,
927         .set_cap = netmap_set_cap,
928 };
929
930 /* A clone of the netmap backend, with a different prefix. */
931 static struct net_backend vale_backend = {
932         .prefix = "vale",
933         .priv_size = sizeof(struct netmap_priv),
934         .init = netmap_init,
935         .cleanup = netmap_cleanup,
936         .send = netmap_send,
937         .peek_recvlen = netmap_peek_recvlen,
938         .recv = netmap_recv,
939         .recv_enable = netmap_recv_enable,
940         .recv_disable = netmap_recv_disable,
941         .get_cap = netmap_get_cap,
942         .set_cap = netmap_set_cap,
943 };
944
945 DATA_SET(net_backend_set, netmap_backend);
946 DATA_SET(net_backend_set, vale_backend);
947
948 int
949 netbe_legacy_config(nvlist_t *nvl, const char *opts)
950 {
951         char *backend, *cp;
952
953         if (opts == NULL)
954                 return (0);
955
956         cp = strchr(opts, ',');
957         if (cp == NULL) {
958                 set_config_value_node(nvl, "backend", opts);
959                 return (0);
960         }
961         backend = strndup(opts, cp - opts);
962         set_config_value_node(nvl, "backend", backend);
963         free(backend);
964         return (pci_parse_legacy_config(nvl, cp + 1));
965 }
966
967 /*
968  * Initialize a backend and attach to the frontend.
969  * This is called during frontend initialization.
970  *  @ret is a pointer to the backend to be initialized
971  *  @devname is the backend-name as supplied on the command line,
972  *      e.g. -s 2:0,frontend-name,backend-name[,other-args]
973  *  @cb is the receive callback supplied by the frontend,
974  *      and it is invoked in the event loop when a receive
975  *      event is generated in the hypervisor,
976  *  @param is a pointer to the frontend, and normally used as
977  *      the argument for the callback.
978  */
979 int
980 netbe_init(struct net_backend **ret, nvlist_t *nvl, net_be_rxeof_t cb,
981     void *param)
982 {
983         struct net_backend **pbe, *nbe, *tbe = NULL;
984         const char *value, *type;
985         char *devname;
986         int err;
987
988         value = get_config_value_node(nvl, "backend");
989         if (value == NULL) {
990                 return (-1);
991         }
992         devname = strdup(value);
993
994         /*
995          * Use the type given by configuration if exists; otherwise
996          * use the prefix of the backend as the type.
997          */
998         type = get_config_value_node(nvl, "type");
999         if (type == NULL)
1000                 type = devname;
1001
1002         /*
1003          * Find the network backend that matches the user-provided
1004          * device name. net_backend_set is built using a linker set.
1005          */
1006         SET_FOREACH(pbe, net_backend_set) {
1007                 if (strncmp(type, (*pbe)->prefix,
1008                     strlen((*pbe)->prefix)) == 0) {
1009                         tbe = *pbe;
1010                         assert(tbe->init != NULL);
1011                         assert(tbe->cleanup != NULL);
1012                         assert(tbe->send != NULL);
1013                         assert(tbe->recv != NULL);
1014                         assert(tbe->get_cap != NULL);
1015                         assert(tbe->set_cap != NULL);
1016                         break;
1017                 }
1018         }
1019
1020         *ret = NULL;
1021         if (tbe == NULL) {
1022                 free(devname);
1023                 return (EINVAL);
1024         }
1025
1026         nbe = calloc(1, NET_BE_SIZE(tbe));
1027         *nbe = *tbe;    /* copy the template */
1028         nbe->fd = -1;
1029         nbe->sc = param;
1030         nbe->be_vnet_hdr_len = 0;
1031         nbe->fe_vnet_hdr_len = 0;
1032
1033         /* Initialize the backend. */
1034         err = nbe->init(nbe, devname, nvl, cb, param);
1035         if (err) {
1036                 free(devname);
1037                 free(nbe);
1038                 return (err);
1039         }
1040
1041         *ret = nbe;
1042         free(devname);
1043
1044         return (0);
1045 }
1046
1047 void
1048 netbe_cleanup(struct net_backend *be)
1049 {
1050
1051         if (be != NULL) {
1052                 be->cleanup(be);
1053                 free(be);
1054         }
1055 }
1056
1057 uint64_t
1058 netbe_get_cap(struct net_backend *be)
1059 {
1060
1061         assert(be != NULL);
1062         return (be->get_cap(be));
1063 }
1064
1065 int
1066 netbe_set_cap(struct net_backend *be, uint64_t features,
1067               unsigned vnet_hdr_len)
1068 {
1069         int ret;
1070
1071         assert(be != NULL);
1072
1073         /* There are only three valid lengths, i.e., 0, 10 and 12. */
1074         if (vnet_hdr_len && vnet_hdr_len != VNET_HDR_LEN
1075                 && vnet_hdr_len != (VNET_HDR_LEN - sizeof(uint16_t)))
1076                 return (-1);
1077
1078         be->fe_vnet_hdr_len = vnet_hdr_len;
1079
1080         ret = be->set_cap(be, features, vnet_hdr_len);
1081         assert(be->be_vnet_hdr_len == 0 ||
1082                be->be_vnet_hdr_len == be->fe_vnet_hdr_len);
1083
1084         return (ret);
1085 }
1086
1087 ssize_t
1088 netbe_send(struct net_backend *be, const struct iovec *iov, int iovcnt)
1089 {
1090
1091         return (be->send(be, iov, iovcnt));
1092 }
1093
1094 ssize_t
1095 netbe_peek_recvlen(struct net_backend *be)
1096 {
1097
1098         return (be->peek_recvlen(be));
1099 }
1100
1101 /*
1102  * Try to read a packet from the backend, without blocking.
1103  * If no packets are available, return 0. In case of success, return
1104  * the length of the packet just read. Return -1 in case of errors.
1105  */
1106 ssize_t
1107 netbe_recv(struct net_backend *be, const struct iovec *iov, int iovcnt)
1108 {
1109
1110         return (be->recv(be, iov, iovcnt));
1111 }
1112
1113 /*
1114  * Read a packet from the backend and discard it.
1115  * Returns the size of the discarded packet or zero if no packet was available.
1116  * A negative error code is returned in case of read error.
1117  */
1118 ssize_t
1119 netbe_rx_discard(struct net_backend *be)
1120 {
1121         /*
1122          * MP note: the dummybuf is only used to discard frames,
1123          * so there is no need for it to be per-vtnet or locked.
1124          * We only make it large enough for TSO-sized segment.
1125          */
1126         static uint8_t dummybuf[65536 + 64];
1127         struct iovec iov;
1128
1129         iov.iov_base = dummybuf;
1130         iov.iov_len = sizeof(dummybuf);
1131
1132         return netbe_recv(be, &iov, 1);
1133 }
1134
1135 void
1136 netbe_rx_disable(struct net_backend *be)
1137 {
1138
1139         return be->recv_disable(be);
1140 }
1141
1142 void
1143 netbe_rx_enable(struct net_backend *be)
1144 {
1145
1146         return be->recv_enable(be);
1147 }
1148
1149 size_t
1150 netbe_get_vnet_hdr_len(struct net_backend *be)
1151 {
1152
1153         return (be->be_vnet_hdr_len);
1154 }