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