xref: /qemu/net/tap.c (revision 7a4e543d)
1 /*
2  * QEMU System Emulator
3  *
4  * Copyright (c) 2003-2008 Fabrice Bellard
5  * Copyright (c) 2009 Red Hat, Inc.
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a copy
8  * of this software and associated documentation files (the "Software"), to deal
9  * in the Software without restriction, including without limitation the rights
10  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11  * copies of the Software, and to permit persons to whom the Software is
12  * furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included in
15  * all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23  * THE SOFTWARE.
24  */
25 
26 #include "qemu/osdep.h"
27 #include "tap_int.h"
28 
29 
30 #include <sys/ioctl.h>
31 #include <sys/wait.h>
32 #include <sys/socket.h>
33 #include <net/if.h>
34 
35 #include "net/net.h"
36 #include "clients.h"
37 #include "monitor/monitor.h"
38 #include "sysemu/sysemu.h"
39 #include "qemu-common.h"
40 #include "qemu/error-report.h"
41 
42 #include "net/tap.h"
43 
44 #include "net/vhost_net.h"
45 
46 typedef struct TAPState {
47     NetClientState nc;
48     int fd;
49     char down_script[1024];
50     char down_script_arg[128];
51     uint8_t buf[NET_BUFSIZE];
52     bool read_poll;
53     bool write_poll;
54     bool using_vnet_hdr;
55     bool has_ufo;
56     bool enabled;
57     VHostNetState *vhost_net;
58     unsigned host_vnet_hdr_len;
59 } TAPState;
60 
61 static void launch_script(const char *setup_script, const char *ifname,
62                           int fd, Error **errp);
63 
64 static void tap_send(void *opaque);
65 static void tap_writable(void *opaque);
66 
67 static void tap_update_fd_handler(TAPState *s)
68 {
69     qemu_set_fd_handler(s->fd,
70                         s->read_poll && s->enabled ? tap_send : NULL,
71                         s->write_poll && s->enabled ? tap_writable : NULL,
72                         s);
73 }
74 
75 static void tap_read_poll(TAPState *s, bool enable)
76 {
77     s->read_poll = enable;
78     tap_update_fd_handler(s);
79 }
80 
81 static void tap_write_poll(TAPState *s, bool enable)
82 {
83     s->write_poll = enable;
84     tap_update_fd_handler(s);
85 }
86 
87 static void tap_writable(void *opaque)
88 {
89     TAPState *s = opaque;
90 
91     tap_write_poll(s, false);
92 
93     qemu_flush_queued_packets(&s->nc);
94 }
95 
96 static ssize_t tap_write_packet(TAPState *s, const struct iovec *iov, int iovcnt)
97 {
98     ssize_t len;
99 
100     do {
101         len = writev(s->fd, iov, iovcnt);
102     } while (len == -1 && errno == EINTR);
103 
104     if (len == -1 && errno == EAGAIN) {
105         tap_write_poll(s, true);
106         return 0;
107     }
108 
109     return len;
110 }
111 
112 static ssize_t tap_receive_iov(NetClientState *nc, const struct iovec *iov,
113                                int iovcnt)
114 {
115     TAPState *s = DO_UPCAST(TAPState, nc, nc);
116     const struct iovec *iovp = iov;
117     struct iovec iov_copy[iovcnt + 1];
118     struct virtio_net_hdr_mrg_rxbuf hdr = { };
119 
120     if (s->host_vnet_hdr_len && !s->using_vnet_hdr) {
121         iov_copy[0].iov_base = &hdr;
122         iov_copy[0].iov_len =  s->host_vnet_hdr_len;
123         memcpy(&iov_copy[1], iov, iovcnt * sizeof(*iov));
124         iovp = iov_copy;
125         iovcnt++;
126     }
127 
128     return tap_write_packet(s, iovp, iovcnt);
129 }
130 
131 static ssize_t tap_receive_raw(NetClientState *nc, const uint8_t *buf, size_t size)
132 {
133     TAPState *s = DO_UPCAST(TAPState, nc, nc);
134     struct iovec iov[2];
135     int iovcnt = 0;
136     struct virtio_net_hdr_mrg_rxbuf hdr = { };
137 
138     if (s->host_vnet_hdr_len) {
139         iov[iovcnt].iov_base = &hdr;
140         iov[iovcnt].iov_len  = s->host_vnet_hdr_len;
141         iovcnt++;
142     }
143 
144     iov[iovcnt].iov_base = (char *)buf;
145     iov[iovcnt].iov_len  = size;
146     iovcnt++;
147 
148     return tap_write_packet(s, iov, iovcnt);
149 }
150 
151 static ssize_t tap_receive(NetClientState *nc, const uint8_t *buf, size_t size)
152 {
153     TAPState *s = DO_UPCAST(TAPState, nc, nc);
154     struct iovec iov[1];
155 
156     if (s->host_vnet_hdr_len && !s->using_vnet_hdr) {
157         return tap_receive_raw(nc, buf, size);
158     }
159 
160     iov[0].iov_base = (char *)buf;
161     iov[0].iov_len  = size;
162 
163     return tap_write_packet(s, iov, 1);
164 }
165 
166 #ifndef __sun__
167 ssize_t tap_read_packet(int tapfd, uint8_t *buf, int maxlen)
168 {
169     return read(tapfd, buf, maxlen);
170 }
171 #endif
172 
173 static void tap_send_completed(NetClientState *nc, ssize_t len)
174 {
175     TAPState *s = DO_UPCAST(TAPState, nc, nc);
176     tap_read_poll(s, true);
177 }
178 
179 static void tap_send(void *opaque)
180 {
181     TAPState *s = opaque;
182     int size;
183     int packets = 0;
184 
185     while (true) {
186         uint8_t *buf = s->buf;
187 
188         size = tap_read_packet(s->fd, s->buf, sizeof(s->buf));
189         if (size <= 0) {
190             break;
191         }
192 
193         if (s->host_vnet_hdr_len && !s->using_vnet_hdr) {
194             buf  += s->host_vnet_hdr_len;
195             size -= s->host_vnet_hdr_len;
196         }
197 
198         size = qemu_send_packet_async(&s->nc, buf, size, tap_send_completed);
199         if (size == 0) {
200             tap_read_poll(s, false);
201             break;
202         } else if (size < 0) {
203             break;
204         }
205 
206         /*
207          * When the host keeps receiving more packets while tap_send() is
208          * running we can hog the QEMU global mutex.  Limit the number of
209          * packets that are processed per tap_send() callback to prevent
210          * stalling the guest.
211          */
212         packets++;
213         if (packets >= 50) {
214             break;
215         }
216     }
217 }
218 
219 static bool tap_has_ufo(NetClientState *nc)
220 {
221     TAPState *s = DO_UPCAST(TAPState, nc, nc);
222 
223     assert(nc->info->type == NET_CLIENT_OPTIONS_KIND_TAP);
224 
225     return s->has_ufo;
226 }
227 
228 static bool tap_has_vnet_hdr(NetClientState *nc)
229 {
230     TAPState *s = DO_UPCAST(TAPState, nc, nc);
231 
232     assert(nc->info->type == NET_CLIENT_OPTIONS_KIND_TAP);
233 
234     return !!s->host_vnet_hdr_len;
235 }
236 
237 static bool tap_has_vnet_hdr_len(NetClientState *nc, int len)
238 {
239     TAPState *s = DO_UPCAST(TAPState, nc, nc);
240 
241     assert(nc->info->type == NET_CLIENT_OPTIONS_KIND_TAP);
242 
243     return !!tap_probe_vnet_hdr_len(s->fd, len);
244 }
245 
246 static void tap_set_vnet_hdr_len(NetClientState *nc, int len)
247 {
248     TAPState *s = DO_UPCAST(TAPState, nc, nc);
249 
250     assert(nc->info->type == NET_CLIENT_OPTIONS_KIND_TAP);
251     assert(len == sizeof(struct virtio_net_hdr_mrg_rxbuf) ||
252            len == sizeof(struct virtio_net_hdr));
253 
254     tap_fd_set_vnet_hdr_len(s->fd, len);
255     s->host_vnet_hdr_len = len;
256 }
257 
258 static void tap_using_vnet_hdr(NetClientState *nc, bool using_vnet_hdr)
259 {
260     TAPState *s = DO_UPCAST(TAPState, nc, nc);
261 
262     assert(nc->info->type == NET_CLIENT_OPTIONS_KIND_TAP);
263     assert(!!s->host_vnet_hdr_len == using_vnet_hdr);
264 
265     s->using_vnet_hdr = using_vnet_hdr;
266 }
267 
268 static int tap_set_vnet_le(NetClientState *nc, bool is_le)
269 {
270     TAPState *s = DO_UPCAST(TAPState, nc, nc);
271 
272     return tap_fd_set_vnet_le(s->fd, is_le);
273 }
274 
275 static int tap_set_vnet_be(NetClientState *nc, bool is_be)
276 {
277     TAPState *s = DO_UPCAST(TAPState, nc, nc);
278 
279     return tap_fd_set_vnet_be(s->fd, is_be);
280 }
281 
282 static void tap_set_offload(NetClientState *nc, int csum, int tso4,
283                      int tso6, int ecn, int ufo)
284 {
285     TAPState *s = DO_UPCAST(TAPState, nc, nc);
286     if (s->fd < 0) {
287         return;
288     }
289 
290     tap_fd_set_offload(s->fd, csum, tso4, tso6, ecn, ufo);
291 }
292 
293 static void tap_cleanup(NetClientState *nc)
294 {
295     TAPState *s = DO_UPCAST(TAPState, nc, nc);
296     Error *err = NULL;
297 
298     if (s->vhost_net) {
299         vhost_net_cleanup(s->vhost_net);
300         s->vhost_net = NULL;
301     }
302 
303     qemu_purge_queued_packets(nc);
304 
305     if (s->down_script[0]) {
306         launch_script(s->down_script, s->down_script_arg, s->fd, &err);
307         if (err) {
308             error_report_err(err);
309         }
310     }
311 
312     tap_read_poll(s, false);
313     tap_write_poll(s, false);
314     close(s->fd);
315     s->fd = -1;
316 }
317 
318 static void tap_poll(NetClientState *nc, bool enable)
319 {
320     TAPState *s = DO_UPCAST(TAPState, nc, nc);
321     tap_read_poll(s, enable);
322     tap_write_poll(s, enable);
323 }
324 
325 int tap_get_fd(NetClientState *nc)
326 {
327     TAPState *s = DO_UPCAST(TAPState, nc, nc);
328     assert(nc->info->type == NET_CLIENT_OPTIONS_KIND_TAP);
329     return s->fd;
330 }
331 
332 /* fd support */
333 
334 static NetClientInfo net_tap_info = {
335     .type = NET_CLIENT_OPTIONS_KIND_TAP,
336     .size = sizeof(TAPState),
337     .receive = tap_receive,
338     .receive_raw = tap_receive_raw,
339     .receive_iov = tap_receive_iov,
340     .poll = tap_poll,
341     .cleanup = tap_cleanup,
342     .has_ufo = tap_has_ufo,
343     .has_vnet_hdr = tap_has_vnet_hdr,
344     .has_vnet_hdr_len = tap_has_vnet_hdr_len,
345     .using_vnet_hdr = tap_using_vnet_hdr,
346     .set_offload = tap_set_offload,
347     .set_vnet_hdr_len = tap_set_vnet_hdr_len,
348     .set_vnet_le = tap_set_vnet_le,
349     .set_vnet_be = tap_set_vnet_be,
350 };
351 
352 static TAPState *net_tap_fd_init(NetClientState *peer,
353                                  const char *model,
354                                  const char *name,
355                                  int fd,
356                                  int vnet_hdr)
357 {
358     NetClientState *nc;
359     TAPState *s;
360 
361     nc = qemu_new_net_client(&net_tap_info, peer, model, name);
362 
363     s = DO_UPCAST(TAPState, nc, nc);
364 
365     s->fd = fd;
366     s->host_vnet_hdr_len = vnet_hdr ? sizeof(struct virtio_net_hdr) : 0;
367     s->using_vnet_hdr = false;
368     s->has_ufo = tap_probe_has_ufo(s->fd);
369     s->enabled = true;
370     tap_set_offload(&s->nc, 0, 0, 0, 0, 0);
371     /*
372      * Make sure host header length is set correctly in tap:
373      * it might have been modified by another instance of qemu.
374      */
375     if (tap_probe_vnet_hdr_len(s->fd, s->host_vnet_hdr_len)) {
376         tap_fd_set_vnet_hdr_len(s->fd, s->host_vnet_hdr_len);
377     }
378     tap_read_poll(s, true);
379     s->vhost_net = NULL;
380     return s;
381 }
382 
383 static void launch_script(const char *setup_script, const char *ifname,
384                           int fd, Error **errp)
385 {
386     int pid, status;
387     char *args[3];
388     char **parg;
389 
390     /* try to launch network script */
391     pid = fork();
392     if (pid < 0) {
393         error_setg_errno(errp, errno, "could not launch network script %s",
394                          setup_script);
395         return;
396     }
397     if (pid == 0) {
398         int open_max = sysconf(_SC_OPEN_MAX), i;
399 
400         for (i = 3; i < open_max; i++) {
401             if (i != fd) {
402                 close(i);
403             }
404         }
405         parg = args;
406         *parg++ = (char *)setup_script;
407         *parg++ = (char *)ifname;
408         *parg = NULL;
409         execv(setup_script, args);
410         _exit(1);
411     } else {
412         while (waitpid(pid, &status, 0) != pid) {
413             /* loop */
414         }
415 
416         if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
417             return;
418         }
419         error_setg(errp, "network script %s failed with status %d",
420                    setup_script, status);
421     }
422 }
423 
424 static int recv_fd(int c)
425 {
426     int fd;
427     uint8_t msgbuf[CMSG_SPACE(sizeof(fd))];
428     struct msghdr msg = {
429         .msg_control = msgbuf,
430         .msg_controllen = sizeof(msgbuf),
431     };
432     struct cmsghdr *cmsg;
433     struct iovec iov;
434     uint8_t req[1];
435     ssize_t len;
436 
437     cmsg = CMSG_FIRSTHDR(&msg);
438     cmsg->cmsg_level = SOL_SOCKET;
439     cmsg->cmsg_type = SCM_RIGHTS;
440     cmsg->cmsg_len = CMSG_LEN(sizeof(fd));
441     msg.msg_controllen = cmsg->cmsg_len;
442 
443     iov.iov_base = req;
444     iov.iov_len = sizeof(req);
445 
446     msg.msg_iov = &iov;
447     msg.msg_iovlen = 1;
448 
449     len = recvmsg(c, &msg, 0);
450     if (len > 0) {
451         memcpy(&fd, CMSG_DATA(cmsg), sizeof(fd));
452         return fd;
453     }
454 
455     return len;
456 }
457 
458 static int net_bridge_run_helper(const char *helper, const char *bridge,
459                                  Error **errp)
460 {
461     sigset_t oldmask, mask;
462     int pid, status;
463     char *args[5];
464     char **parg;
465     int sv[2];
466 
467     sigemptyset(&mask);
468     sigaddset(&mask, SIGCHLD);
469     sigprocmask(SIG_BLOCK, &mask, &oldmask);
470 
471     if (socketpair(PF_UNIX, SOCK_STREAM, 0, sv) == -1) {
472         error_setg_errno(errp, errno, "socketpair() failed");
473         return -1;
474     }
475 
476     /* try to launch bridge helper */
477     pid = fork();
478     if (pid < 0) {
479         error_setg_errno(errp, errno, "Can't fork bridge helper");
480         return -1;
481     }
482     if (pid == 0) {
483         int open_max = sysconf(_SC_OPEN_MAX), i;
484         char fd_buf[6+10];
485         char br_buf[6+IFNAMSIZ] = {0};
486         char helper_cmd[PATH_MAX + sizeof(fd_buf) + sizeof(br_buf) + 15];
487 
488         for (i = 3; i < open_max; i++) {
489             if (i != sv[1]) {
490                 close(i);
491             }
492         }
493 
494         snprintf(fd_buf, sizeof(fd_buf), "%s%d", "--fd=", sv[1]);
495 
496         if (strrchr(helper, ' ') || strrchr(helper, '\t')) {
497             /* assume helper is a command */
498 
499             if (strstr(helper, "--br=") == NULL) {
500                 snprintf(br_buf, sizeof(br_buf), "%s%s", "--br=", bridge);
501             }
502 
503             snprintf(helper_cmd, sizeof(helper_cmd), "%s %s %s %s",
504                      helper, "--use-vnet", fd_buf, br_buf);
505 
506             parg = args;
507             *parg++ = (char *)"sh";
508             *parg++ = (char *)"-c";
509             *parg++ = helper_cmd;
510             *parg++ = NULL;
511 
512             execv("/bin/sh", args);
513         } else {
514             /* assume helper is just the executable path name */
515 
516             snprintf(br_buf, sizeof(br_buf), "%s%s", "--br=", bridge);
517 
518             parg = args;
519             *parg++ = (char *)helper;
520             *parg++ = (char *)"--use-vnet";
521             *parg++ = fd_buf;
522             *parg++ = br_buf;
523             *parg++ = NULL;
524 
525             execv(helper, args);
526         }
527         _exit(1);
528 
529     } else {
530         int fd;
531         int saved_errno;
532 
533         close(sv[1]);
534 
535         do {
536             fd = recv_fd(sv[0]);
537         } while (fd == -1 && errno == EINTR);
538         saved_errno = errno;
539 
540         close(sv[0]);
541 
542         while (waitpid(pid, &status, 0) != pid) {
543             /* loop */
544         }
545         sigprocmask(SIG_SETMASK, &oldmask, NULL);
546         if (fd < 0) {
547             error_setg_errno(errp, saved_errno,
548                              "failed to recv file descriptor");
549             return -1;
550         }
551         if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
552             error_setg(errp, "bridge helper failed");
553             return -1;
554         }
555         return fd;
556     }
557 }
558 
559 int net_init_bridge(const NetClientOptions *opts, const char *name,
560                     NetClientState *peer, Error **errp)
561 {
562     const NetdevBridgeOptions *bridge;
563     const char *helper, *br;
564     TAPState *s;
565     int fd, vnet_hdr;
566 
567     assert(opts->type == NET_CLIENT_OPTIONS_KIND_BRIDGE);
568     bridge = opts->u.bridge;
569 
570     helper = bridge->has_helper ? bridge->helper : DEFAULT_BRIDGE_HELPER;
571     br     = bridge->has_br     ? bridge->br     : DEFAULT_BRIDGE_INTERFACE;
572 
573     fd = net_bridge_run_helper(helper, br, errp);
574     if (fd == -1) {
575         return -1;
576     }
577 
578     fcntl(fd, F_SETFL, O_NONBLOCK);
579     vnet_hdr = tap_probe_vnet_hdr(fd);
580     s = net_tap_fd_init(peer, "bridge", name, fd, vnet_hdr);
581 
582     snprintf(s->nc.info_str, sizeof(s->nc.info_str), "helper=%s,br=%s", helper,
583              br);
584 
585     return 0;
586 }
587 
588 static int net_tap_init(const NetdevTapOptions *tap, int *vnet_hdr,
589                         const char *setup_script, char *ifname,
590                         size_t ifname_sz, int mq_required, Error **errp)
591 {
592     Error *err = NULL;
593     int fd, vnet_hdr_required;
594 
595     if (tap->has_vnet_hdr) {
596         *vnet_hdr = tap->vnet_hdr;
597         vnet_hdr_required = *vnet_hdr;
598     } else {
599         *vnet_hdr = 1;
600         vnet_hdr_required = 0;
601     }
602 
603     TFR(fd = tap_open(ifname, ifname_sz, vnet_hdr, vnet_hdr_required,
604                       mq_required, errp));
605     if (fd < 0) {
606         return -1;
607     }
608 
609     if (setup_script &&
610         setup_script[0] != '\0' &&
611         strcmp(setup_script, "no") != 0) {
612         launch_script(setup_script, ifname, fd, &err);
613         if (err) {
614             error_propagate(errp, err);
615             close(fd);
616             return -1;
617         }
618     }
619 
620     return fd;
621 }
622 
623 #define MAX_TAP_QUEUES 1024
624 
625 static void net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer,
626                              const char *model, const char *name,
627                              const char *ifname, const char *script,
628                              const char *downscript, const char *vhostfdname,
629                              int vnet_hdr, int fd, Error **errp)
630 {
631     Error *err = NULL;
632     TAPState *s = net_tap_fd_init(peer, model, name, fd, vnet_hdr);
633     int vhostfd;
634 
635     tap_set_sndbuf(s->fd, tap, &err);
636     if (err) {
637         error_propagate(errp, err);
638         return;
639     }
640 
641     if (tap->has_fd || tap->has_fds) {
642         snprintf(s->nc.info_str, sizeof(s->nc.info_str), "fd=%d", fd);
643     } else if (tap->has_helper) {
644         snprintf(s->nc.info_str, sizeof(s->nc.info_str), "helper=%s",
645                  tap->helper);
646     } else {
647         snprintf(s->nc.info_str, sizeof(s->nc.info_str),
648                  "ifname=%s,script=%s,downscript=%s", ifname, script,
649                  downscript);
650 
651         if (strcmp(downscript, "no") != 0) {
652             snprintf(s->down_script, sizeof(s->down_script), "%s", downscript);
653             snprintf(s->down_script_arg, sizeof(s->down_script_arg),
654                      "%s", ifname);
655         }
656     }
657 
658     if (tap->has_vhost ? tap->vhost :
659         vhostfdname || (tap->has_vhostforce && tap->vhostforce)) {
660         VhostNetOptions options;
661 
662         options.backend_type = VHOST_BACKEND_TYPE_KERNEL;
663         options.net_backend = &s->nc;
664 
665         if (tap->has_vhostfd || tap->has_vhostfds) {
666             vhostfd = monitor_fd_param(cur_mon, vhostfdname, &err);
667             if (vhostfd == -1) {
668                 error_propagate(errp, err);
669                 return;
670             }
671         } else {
672             vhostfd = open("/dev/vhost-net", O_RDWR);
673             if (vhostfd < 0) {
674                 error_setg_errno(errp, errno,
675                                  "tap: open vhost char device failed");
676                 return;
677             }
678         }
679         options.opaque = (void *)(uintptr_t)vhostfd;
680 
681         s->vhost_net = vhost_net_init(&options);
682         if (!s->vhost_net) {
683             error_setg(errp,
684                        "vhost-net requested but could not be initialized");
685             return;
686         }
687     } else if (tap->has_vhostfd || tap->has_vhostfds) {
688         error_setg(errp, "vhostfd= is not valid without vhost");
689     }
690 }
691 
692 static int get_fds(char *str, char *fds[], int max)
693 {
694     char *ptr = str, *this;
695     size_t len = strlen(str);
696     int i = 0;
697 
698     while (i < max && ptr < str + len) {
699         this = strchr(ptr, ':');
700 
701         if (this == NULL) {
702             fds[i] = g_strdup(ptr);
703         } else {
704             fds[i] = g_strndup(ptr, this - ptr);
705         }
706 
707         i++;
708         if (this == NULL) {
709             break;
710         } else {
711             ptr = this + 1;
712         }
713     }
714 
715     return i;
716 }
717 
718 int net_init_tap(const NetClientOptions *opts, const char *name,
719                  NetClientState *peer, Error **errp)
720 {
721     const NetdevTapOptions *tap;
722     int fd, vnet_hdr = 0, i = 0, queues;
723     /* for the no-fd, no-helper case */
724     const char *script = NULL; /* suppress wrong "uninit'd use" gcc warning */
725     const char *downscript = NULL;
726     Error *err = NULL;
727     const char *vhostfdname;
728     char ifname[128];
729 
730     assert(opts->type == NET_CLIENT_OPTIONS_KIND_TAP);
731     tap = opts->u.tap;
732     queues = tap->has_queues ? tap->queues : 1;
733     vhostfdname = tap->has_vhostfd ? tap->vhostfd : NULL;
734 
735     /* QEMU vlans does not support multiqueue tap, in this case peer is set.
736      * For -netdev, peer is always NULL. */
737     if (peer && (tap->has_queues || tap->has_fds || tap->has_vhostfds)) {
738         error_setg(errp, "Multiqueue tap cannot be used with QEMU vlans");
739         return -1;
740     }
741 
742     if (tap->has_fd) {
743         if (tap->has_ifname || tap->has_script || tap->has_downscript ||
744             tap->has_vnet_hdr || tap->has_helper || tap->has_queues ||
745             tap->has_fds || tap->has_vhostfds) {
746             error_setg(errp, "ifname=, script=, downscript=, vnet_hdr=, "
747                        "helper=, queues=, fds=, and vhostfds= "
748                        "are invalid with fd=");
749             return -1;
750         }
751 
752         fd = monitor_fd_param(cur_mon, tap->fd, &err);
753         if (fd == -1) {
754             error_propagate(errp, err);
755             return -1;
756         }
757 
758         fcntl(fd, F_SETFL, O_NONBLOCK);
759 
760         vnet_hdr = tap_probe_vnet_hdr(fd);
761 
762         net_init_tap_one(tap, peer, "tap", name, NULL,
763                          script, downscript,
764                          vhostfdname, vnet_hdr, fd, &err);
765         if (err) {
766             error_propagate(errp, err);
767             return -1;
768         }
769     } else if (tap->has_fds) {
770         char *fds[MAX_TAP_QUEUES];
771         char *vhost_fds[MAX_TAP_QUEUES];
772         int nfds, nvhosts;
773 
774         if (tap->has_ifname || tap->has_script || tap->has_downscript ||
775             tap->has_vnet_hdr || tap->has_helper || tap->has_queues ||
776             tap->has_vhostfd) {
777             error_setg(errp, "ifname=, script=, downscript=, vnet_hdr=, "
778                        "helper=, queues=, and vhostfd= "
779                        "are invalid with fds=");
780             return -1;
781         }
782 
783         nfds = get_fds(tap->fds, fds, MAX_TAP_QUEUES);
784         if (tap->has_vhostfds) {
785             nvhosts = get_fds(tap->vhostfds, vhost_fds, MAX_TAP_QUEUES);
786             if (nfds != nvhosts) {
787                 error_setg(errp, "The number of fds passed does not match "
788                            "the number of vhostfds passed");
789                 return -1;
790             }
791         }
792 
793         for (i = 0; i < nfds; i++) {
794             fd = monitor_fd_param(cur_mon, fds[i], &err);
795             if (fd == -1) {
796                 error_propagate(errp, err);
797                 return -1;
798             }
799 
800             fcntl(fd, F_SETFL, O_NONBLOCK);
801 
802             if (i == 0) {
803                 vnet_hdr = tap_probe_vnet_hdr(fd);
804             } else if (vnet_hdr != tap_probe_vnet_hdr(fd)) {
805                 error_setg(errp,
806                            "vnet_hdr not consistent across given tap fds");
807                 return -1;
808             }
809 
810             net_init_tap_one(tap, peer, "tap", name, ifname,
811                              script, downscript,
812                              tap->has_vhostfds ? vhost_fds[i] : NULL,
813                              vnet_hdr, fd, &err);
814             if (err) {
815                 error_propagate(errp, err);
816                 return -1;
817             }
818         }
819     } else if (tap->has_helper) {
820         if (tap->has_ifname || tap->has_script || tap->has_downscript ||
821             tap->has_vnet_hdr || tap->has_queues || tap->has_vhostfds) {
822             error_setg(errp, "ifname=, script=, downscript=, vnet_hdr=, "
823                        "queues=, and vhostfds= are invalid with helper=");
824             return -1;
825         }
826 
827         fd = net_bridge_run_helper(tap->helper, DEFAULT_BRIDGE_INTERFACE,
828                                    errp);
829         if (fd == -1) {
830             return -1;
831         }
832 
833         fcntl(fd, F_SETFL, O_NONBLOCK);
834         vnet_hdr = tap_probe_vnet_hdr(fd);
835 
836         net_init_tap_one(tap, peer, "bridge", name, ifname,
837                          script, downscript, vhostfdname,
838                          vnet_hdr, fd, &err);
839         if (err) {
840             error_propagate(errp, err);
841             close(fd);
842             return -1;
843         }
844     } else {
845         if (tap->has_vhostfds) {
846             error_setg(errp, "vhostfds= is invalid if fds= wasn't specified");
847             return -1;
848         }
849         script = tap->has_script ? tap->script : DEFAULT_NETWORK_SCRIPT;
850         downscript = tap->has_downscript ? tap->downscript :
851             DEFAULT_NETWORK_DOWN_SCRIPT;
852 
853         if (tap->has_ifname) {
854             pstrcpy(ifname, sizeof ifname, tap->ifname);
855         } else {
856             ifname[0] = '\0';
857         }
858 
859         for (i = 0; i < queues; i++) {
860             fd = net_tap_init(tap, &vnet_hdr, i >= 1 ? "no" : script,
861                               ifname, sizeof ifname, queues > 1, errp);
862             if (fd == -1) {
863                 return -1;
864             }
865 
866             if (queues > 1 && i == 0 && !tap->has_ifname) {
867                 if (tap_fd_get_ifname(fd, ifname)) {
868                     error_setg(errp, "Fail to get ifname");
869                     close(fd);
870                     return -1;
871                 }
872             }
873 
874             net_init_tap_one(tap, peer, "tap", name, ifname,
875                              i >= 1 ? "no" : script,
876                              i >= 1 ? "no" : downscript,
877                              vhostfdname, vnet_hdr, fd, &err);
878             if (err) {
879                 error_propagate(errp, err);
880                 close(fd);
881                 return -1;
882             }
883         }
884     }
885 
886     return 0;
887 }
888 
889 VHostNetState *tap_get_vhost_net(NetClientState *nc)
890 {
891     TAPState *s = DO_UPCAST(TAPState, nc, nc);
892     assert(nc->info->type == NET_CLIENT_OPTIONS_KIND_TAP);
893     return s->vhost_net;
894 }
895 
896 int tap_enable(NetClientState *nc)
897 {
898     TAPState *s = DO_UPCAST(TAPState, nc, nc);
899     int ret;
900 
901     if (s->enabled) {
902         return 0;
903     } else {
904         ret = tap_fd_enable(s->fd);
905         if (ret == 0) {
906             s->enabled = true;
907             tap_update_fd_handler(s);
908         }
909         return ret;
910     }
911 }
912 
913 int tap_disable(NetClientState *nc)
914 {
915     TAPState *s = DO_UPCAST(TAPState, nc, nc);
916     int ret;
917 
918     if (s->enabled == 0) {
919         return 0;
920     } else {
921         ret = tap_fd_disable(s->fd);
922         if (ret == 0) {
923             qemu_purge_queued_packets(nc);
924             s->enabled = false;
925             tap_update_fd_handler(s);
926         }
927         return ret;
928     }
929 }
930