Statistics
| Branch: | Revision:

root / net / tap.c @ 1faac1f7

History | View | Annotate | Download (11.2 kB)

1 5281d757 Mark McLoughlin
/*
2 5281d757 Mark McLoughlin
 * QEMU System Emulator
3 5281d757 Mark McLoughlin
 *
4 5281d757 Mark McLoughlin
 * Copyright (c) 2003-2008 Fabrice Bellard
5 5281d757 Mark McLoughlin
 * Copyright (c) 2009 Red Hat, Inc.
6 5281d757 Mark McLoughlin
 *
7 5281d757 Mark McLoughlin
 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 5281d757 Mark McLoughlin
 * of this software and associated documentation files (the "Software"), to deal
9 5281d757 Mark McLoughlin
 * in the Software without restriction, including without limitation the rights
10 5281d757 Mark McLoughlin
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 5281d757 Mark McLoughlin
 * copies of the Software, and to permit persons to whom the Software is
12 5281d757 Mark McLoughlin
 * furnished to do so, subject to the following conditions:
13 5281d757 Mark McLoughlin
 *
14 5281d757 Mark McLoughlin
 * The above copyright notice and this permission notice shall be included in
15 5281d757 Mark McLoughlin
 * all copies or substantial portions of the Software.
16 5281d757 Mark McLoughlin
 *
17 5281d757 Mark McLoughlin
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 5281d757 Mark McLoughlin
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 5281d757 Mark McLoughlin
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 5281d757 Mark McLoughlin
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 5281d757 Mark McLoughlin
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 5281d757 Mark McLoughlin
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 5281d757 Mark McLoughlin
 * THE SOFTWARE.
24 5281d757 Mark McLoughlin
 */
25 5281d757 Mark McLoughlin
26 5281d757 Mark McLoughlin
#include "net/tap.h"
27 5281d757 Mark McLoughlin
28 5281d757 Mark McLoughlin
#include "config-host.h"
29 5281d757 Mark McLoughlin
30 5281d757 Mark McLoughlin
#include <signal.h>
31 5281d757 Mark McLoughlin
#include <sys/ioctl.h>
32 5281d757 Mark McLoughlin
#include <sys/stat.h>
33 5281d757 Mark McLoughlin
#include <sys/wait.h>
34 5281d757 Mark McLoughlin
#include <net/if.h>
35 5281d757 Mark McLoughlin
36 5281d757 Mark McLoughlin
#include "net.h"
37 5281d757 Mark McLoughlin
#include "sysemu.h"
38 5281d757 Mark McLoughlin
#include "qemu-char.h"
39 5281d757 Mark McLoughlin
#include "qemu-common.h"
40 5281d757 Mark McLoughlin
41 5281d757 Mark McLoughlin
#include "net/tap-linux.h"
42 5281d757 Mark McLoughlin
43 5281d757 Mark McLoughlin
/* Maximum GSO packet size (64k) plus plenty of room for
44 5281d757 Mark McLoughlin
 * the ethernet and virtio_net headers
45 5281d757 Mark McLoughlin
 */
46 5281d757 Mark McLoughlin
#define TAP_BUFSIZE (4096 + 65536)
47 5281d757 Mark McLoughlin
48 5281d757 Mark McLoughlin
typedef struct TAPState {
49 5281d757 Mark McLoughlin
    VLANClientState *vc;
50 5281d757 Mark McLoughlin
    int fd;
51 5281d757 Mark McLoughlin
    char down_script[1024];
52 5281d757 Mark McLoughlin
    char down_script_arg[128];
53 5281d757 Mark McLoughlin
    uint8_t buf[TAP_BUFSIZE];
54 5281d757 Mark McLoughlin
    unsigned int read_poll : 1;
55 5281d757 Mark McLoughlin
    unsigned int write_poll : 1;
56 5281d757 Mark McLoughlin
    unsigned int has_vnet_hdr : 1;
57 5281d757 Mark McLoughlin
    unsigned int using_vnet_hdr : 1;
58 5281d757 Mark McLoughlin
    unsigned int has_ufo: 1;
59 5281d757 Mark McLoughlin
} TAPState;
60 5281d757 Mark McLoughlin
61 5281d757 Mark McLoughlin
static int launch_script(const char *setup_script, const char *ifname, int fd);
62 5281d757 Mark McLoughlin
63 5281d757 Mark McLoughlin
static int tap_can_send(void *opaque);
64 5281d757 Mark McLoughlin
static void tap_send(void *opaque);
65 5281d757 Mark McLoughlin
static void tap_writable(void *opaque);
66 5281d757 Mark McLoughlin
67 5281d757 Mark McLoughlin
static void tap_update_fd_handler(TAPState *s)
68 5281d757 Mark McLoughlin
{
69 5281d757 Mark McLoughlin
    qemu_set_fd_handler2(s->fd,
70 5281d757 Mark McLoughlin
                         s->read_poll  ? tap_can_send : NULL,
71 5281d757 Mark McLoughlin
                         s->read_poll  ? tap_send     : NULL,
72 5281d757 Mark McLoughlin
                         s->write_poll ? tap_writable : NULL,
73 5281d757 Mark McLoughlin
                         s);
74 5281d757 Mark McLoughlin
}
75 5281d757 Mark McLoughlin
76 5281d757 Mark McLoughlin
static void tap_read_poll(TAPState *s, int enable)
77 5281d757 Mark McLoughlin
{
78 5281d757 Mark McLoughlin
    s->read_poll = !!enable;
79 5281d757 Mark McLoughlin
    tap_update_fd_handler(s);
80 5281d757 Mark McLoughlin
}
81 5281d757 Mark McLoughlin
82 5281d757 Mark McLoughlin
static void tap_write_poll(TAPState *s, int enable)
83 5281d757 Mark McLoughlin
{
84 5281d757 Mark McLoughlin
    s->write_poll = !!enable;
85 5281d757 Mark McLoughlin
    tap_update_fd_handler(s);
86 5281d757 Mark McLoughlin
}
87 5281d757 Mark McLoughlin
88 5281d757 Mark McLoughlin
static void tap_writable(void *opaque)
89 5281d757 Mark McLoughlin
{
90 5281d757 Mark McLoughlin
    TAPState *s = opaque;
91 5281d757 Mark McLoughlin
92 5281d757 Mark McLoughlin
    tap_write_poll(s, 0);
93 5281d757 Mark McLoughlin
94 5281d757 Mark McLoughlin
    qemu_flush_queued_packets(s->vc);
95 5281d757 Mark McLoughlin
}
96 5281d757 Mark McLoughlin
97 5281d757 Mark McLoughlin
static ssize_t tap_write_packet(TAPState *s, const struct iovec *iov, int iovcnt)
98 5281d757 Mark McLoughlin
{
99 5281d757 Mark McLoughlin
    ssize_t len;
100 5281d757 Mark McLoughlin
101 5281d757 Mark McLoughlin
    do {
102 5281d757 Mark McLoughlin
        len = writev(s->fd, iov, iovcnt);
103 5281d757 Mark McLoughlin
    } while (len == -1 && errno == EINTR);
104 5281d757 Mark McLoughlin
105 5281d757 Mark McLoughlin
    if (len == -1 && errno == EAGAIN) {
106 5281d757 Mark McLoughlin
        tap_write_poll(s, 1);
107 5281d757 Mark McLoughlin
        return 0;
108 5281d757 Mark McLoughlin
    }
109 5281d757 Mark McLoughlin
110 5281d757 Mark McLoughlin
    return len;
111 5281d757 Mark McLoughlin
}
112 5281d757 Mark McLoughlin
113 5281d757 Mark McLoughlin
static ssize_t tap_receive_iov(VLANClientState *vc, const struct iovec *iov,
114 5281d757 Mark McLoughlin
                               int iovcnt)
115 5281d757 Mark McLoughlin
{
116 5281d757 Mark McLoughlin
    TAPState *s = vc->opaque;
117 5281d757 Mark McLoughlin
    const struct iovec *iovp = iov;
118 5281d757 Mark McLoughlin
    struct iovec iov_copy[iovcnt + 1];
119 5281d757 Mark McLoughlin
    struct virtio_net_hdr hdr = { 0, };
120 5281d757 Mark McLoughlin
121 5281d757 Mark McLoughlin
    if (s->has_vnet_hdr && !s->using_vnet_hdr) {
122 5281d757 Mark McLoughlin
        iov_copy[0].iov_base = &hdr;
123 5281d757 Mark McLoughlin
        iov_copy[0].iov_len =  sizeof(hdr);
124 5281d757 Mark McLoughlin
        memcpy(&iov_copy[1], iov, iovcnt * sizeof(*iov));
125 5281d757 Mark McLoughlin
        iovp = iov_copy;
126 5281d757 Mark McLoughlin
        iovcnt++;
127 5281d757 Mark McLoughlin
    }
128 5281d757 Mark McLoughlin
129 5281d757 Mark McLoughlin
    return tap_write_packet(s, iovp, iovcnt);
130 5281d757 Mark McLoughlin
}
131 5281d757 Mark McLoughlin
132 5281d757 Mark McLoughlin
static ssize_t tap_receive_raw(VLANClientState *vc, const uint8_t *buf, size_t size)
133 5281d757 Mark McLoughlin
{
134 5281d757 Mark McLoughlin
    TAPState *s = vc->opaque;
135 5281d757 Mark McLoughlin
    struct iovec iov[2];
136 5281d757 Mark McLoughlin
    int iovcnt = 0;
137 5281d757 Mark McLoughlin
    struct virtio_net_hdr hdr = { 0, };
138 5281d757 Mark McLoughlin
139 5281d757 Mark McLoughlin
    if (s->has_vnet_hdr) {
140 5281d757 Mark McLoughlin
        iov[iovcnt].iov_base = &hdr;
141 5281d757 Mark McLoughlin
        iov[iovcnt].iov_len  = sizeof(hdr);
142 5281d757 Mark McLoughlin
        iovcnt++;
143 5281d757 Mark McLoughlin
    }
144 5281d757 Mark McLoughlin
145 5281d757 Mark McLoughlin
    iov[iovcnt].iov_base = (char *)buf;
146 5281d757 Mark McLoughlin
    iov[iovcnt].iov_len  = size;
147 5281d757 Mark McLoughlin
    iovcnt++;
148 5281d757 Mark McLoughlin
149 5281d757 Mark McLoughlin
    return tap_write_packet(s, iov, iovcnt);
150 5281d757 Mark McLoughlin
}
151 5281d757 Mark McLoughlin
152 5281d757 Mark McLoughlin
static ssize_t tap_receive(VLANClientState *vc, const uint8_t *buf, size_t size)
153 5281d757 Mark McLoughlin
{
154 5281d757 Mark McLoughlin
    TAPState *s = vc->opaque;
155 5281d757 Mark McLoughlin
    struct iovec iov[1];
156 5281d757 Mark McLoughlin
157 5281d757 Mark McLoughlin
    if (s->has_vnet_hdr && !s->using_vnet_hdr) {
158 5281d757 Mark McLoughlin
        return tap_receive_raw(vc, buf, size);
159 5281d757 Mark McLoughlin
    }
160 5281d757 Mark McLoughlin
161 5281d757 Mark McLoughlin
    iov[0].iov_base = (char *)buf;
162 5281d757 Mark McLoughlin
    iov[0].iov_len  = size;
163 5281d757 Mark McLoughlin
164 5281d757 Mark McLoughlin
    return tap_write_packet(s, iov, 1);
165 5281d757 Mark McLoughlin
}
166 5281d757 Mark McLoughlin
167 5281d757 Mark McLoughlin
static int tap_can_send(void *opaque)
168 5281d757 Mark McLoughlin
{
169 5281d757 Mark McLoughlin
    TAPState *s = opaque;
170 5281d757 Mark McLoughlin
171 5281d757 Mark McLoughlin
    return qemu_can_send_packet(s->vc);
172 5281d757 Mark McLoughlin
}
173 5281d757 Mark McLoughlin
174 966ea5ec Mark McLoughlin
#ifndef __sun__
175 966ea5ec Mark McLoughlin
ssize_t tap_read_packet(int tapfd, uint8_t *buf, int maxlen)
176 5281d757 Mark McLoughlin
{
177 5281d757 Mark McLoughlin
    return read(tapfd, buf, maxlen);
178 5281d757 Mark McLoughlin
}
179 5281d757 Mark McLoughlin
#endif
180 5281d757 Mark McLoughlin
181 5281d757 Mark McLoughlin
static void tap_send_completed(VLANClientState *vc, ssize_t len)
182 5281d757 Mark McLoughlin
{
183 5281d757 Mark McLoughlin
    TAPState *s = vc->opaque;
184 5281d757 Mark McLoughlin
    tap_read_poll(s, 1);
185 5281d757 Mark McLoughlin
}
186 5281d757 Mark McLoughlin
187 5281d757 Mark McLoughlin
static void tap_send(void *opaque)
188 5281d757 Mark McLoughlin
{
189 5281d757 Mark McLoughlin
    TAPState *s = opaque;
190 5281d757 Mark McLoughlin
    int size;
191 5281d757 Mark McLoughlin
192 5281d757 Mark McLoughlin
    do {
193 5281d757 Mark McLoughlin
        uint8_t *buf = s->buf;
194 5281d757 Mark McLoughlin
195 5281d757 Mark McLoughlin
        size = tap_read_packet(s->fd, s->buf, sizeof(s->buf));
196 5281d757 Mark McLoughlin
        if (size <= 0) {
197 5281d757 Mark McLoughlin
            break;
198 5281d757 Mark McLoughlin
        }
199 5281d757 Mark McLoughlin
200 5281d757 Mark McLoughlin
        if (s->has_vnet_hdr && !s->using_vnet_hdr) {
201 5281d757 Mark McLoughlin
            buf  += sizeof(struct virtio_net_hdr);
202 5281d757 Mark McLoughlin
            size -= sizeof(struct virtio_net_hdr);
203 5281d757 Mark McLoughlin
        }
204 5281d757 Mark McLoughlin
205 5281d757 Mark McLoughlin
        size = qemu_send_packet_async(s->vc, buf, size, tap_send_completed);
206 5281d757 Mark McLoughlin
        if (size == 0) {
207 5281d757 Mark McLoughlin
            tap_read_poll(s, 0);
208 5281d757 Mark McLoughlin
        }
209 5281d757 Mark McLoughlin
    } while (size > 0);
210 5281d757 Mark McLoughlin
}
211 5281d757 Mark McLoughlin
212 5281d757 Mark McLoughlin
int tap_has_ufo(VLANClientState *vc)
213 5281d757 Mark McLoughlin
{
214 5281d757 Mark McLoughlin
    TAPState *s = vc->opaque;
215 5281d757 Mark McLoughlin
216 5281d757 Mark McLoughlin
    assert(vc->type == NET_CLIENT_TYPE_TAP);
217 5281d757 Mark McLoughlin
218 5281d757 Mark McLoughlin
    return s->has_ufo;
219 5281d757 Mark McLoughlin
}
220 5281d757 Mark McLoughlin
221 5281d757 Mark McLoughlin
int tap_has_vnet_hdr(VLANClientState *vc)
222 5281d757 Mark McLoughlin
{
223 5281d757 Mark McLoughlin
    TAPState *s = vc->opaque;
224 5281d757 Mark McLoughlin
225 5281d757 Mark McLoughlin
    assert(vc->type == NET_CLIENT_TYPE_TAP);
226 5281d757 Mark McLoughlin
227 5281d757 Mark McLoughlin
    return s->has_vnet_hdr;
228 5281d757 Mark McLoughlin
}
229 5281d757 Mark McLoughlin
230 5281d757 Mark McLoughlin
void tap_using_vnet_hdr(VLANClientState *vc, int using_vnet_hdr)
231 5281d757 Mark McLoughlin
{
232 5281d757 Mark McLoughlin
    TAPState *s = vc->opaque;
233 5281d757 Mark McLoughlin
234 5281d757 Mark McLoughlin
    using_vnet_hdr = using_vnet_hdr != 0;
235 5281d757 Mark McLoughlin
236 5281d757 Mark McLoughlin
    assert(vc->type == NET_CLIENT_TYPE_TAP);
237 5281d757 Mark McLoughlin
    assert(s->has_vnet_hdr == using_vnet_hdr);
238 5281d757 Mark McLoughlin
239 5281d757 Mark McLoughlin
    s->using_vnet_hdr = using_vnet_hdr;
240 5281d757 Mark McLoughlin
}
241 5281d757 Mark McLoughlin
242 5281d757 Mark McLoughlin
void tap_set_offload(VLANClientState *vc, int csum, int tso4,
243 5281d757 Mark McLoughlin
                     int tso6, int ecn, int ufo)
244 5281d757 Mark McLoughlin
{
245 5281d757 Mark McLoughlin
    TAPState *s = vc->opaque;
246 5281d757 Mark McLoughlin
247 1faac1f7 Mark McLoughlin
    return tap_fd_set_offload(s->fd, csum, tso4, tso6, ecn, ufo);
248 5281d757 Mark McLoughlin
}
249 5281d757 Mark McLoughlin
250 5281d757 Mark McLoughlin
static void tap_cleanup(VLANClientState *vc)
251 5281d757 Mark McLoughlin
{
252 5281d757 Mark McLoughlin
    TAPState *s = vc->opaque;
253 5281d757 Mark McLoughlin
254 5281d757 Mark McLoughlin
    qemu_purge_queued_packets(vc);
255 5281d757 Mark McLoughlin
256 5281d757 Mark McLoughlin
    if (s->down_script[0])
257 5281d757 Mark McLoughlin
        launch_script(s->down_script, s->down_script_arg, s->fd);
258 5281d757 Mark McLoughlin
259 5281d757 Mark McLoughlin
    tap_read_poll(s, 0);
260 5281d757 Mark McLoughlin
    tap_write_poll(s, 0);
261 5281d757 Mark McLoughlin
    close(s->fd);
262 5281d757 Mark McLoughlin
    qemu_free(s);
263 5281d757 Mark McLoughlin
}
264 5281d757 Mark McLoughlin
265 5281d757 Mark McLoughlin
/* fd support */
266 5281d757 Mark McLoughlin
267 5281d757 Mark McLoughlin
static TAPState *net_tap_fd_init(VLANState *vlan,
268 5281d757 Mark McLoughlin
                                 const char *model,
269 5281d757 Mark McLoughlin
                                 const char *name,
270 5281d757 Mark McLoughlin
                                 int fd,
271 5281d757 Mark McLoughlin
                                 int vnet_hdr)
272 5281d757 Mark McLoughlin
{
273 5281d757 Mark McLoughlin
    TAPState *s;
274 5281d757 Mark McLoughlin
    unsigned int offload;
275 5281d757 Mark McLoughlin
276 5281d757 Mark McLoughlin
    s = qemu_mallocz(sizeof(TAPState));
277 5281d757 Mark McLoughlin
    s->fd = fd;
278 5281d757 Mark McLoughlin
    s->has_vnet_hdr = vnet_hdr != 0;
279 5281d757 Mark McLoughlin
    s->using_vnet_hdr = 0;
280 5281d757 Mark McLoughlin
    s->vc = qemu_new_vlan_client(NET_CLIENT_TYPE_TAP,
281 5281d757 Mark McLoughlin
                                 vlan, NULL, model, name, NULL,
282 5281d757 Mark McLoughlin
                                 tap_receive, tap_receive_raw,
283 5281d757 Mark McLoughlin
                                 tap_receive_iov, tap_cleanup, s);
284 5281d757 Mark McLoughlin
    s->has_ufo = 0;
285 5281d757 Mark McLoughlin
    /* Check if tap supports UFO */
286 5281d757 Mark McLoughlin
    offload = TUN_F_CSUM | TUN_F_UFO;
287 5281d757 Mark McLoughlin
    if (ioctl(s->fd, TUNSETOFFLOAD, offload) == 0)
288 5281d757 Mark McLoughlin
       s->has_ufo = 1;
289 5281d757 Mark McLoughlin
    tap_set_offload(s->vc, 0, 0, 0, 0, 0);
290 5281d757 Mark McLoughlin
    tap_read_poll(s, 1);
291 5281d757 Mark McLoughlin
    return s;
292 5281d757 Mark McLoughlin
}
293 5281d757 Mark McLoughlin
294 5281d757 Mark McLoughlin
static int launch_script(const char *setup_script, const char *ifname, int fd)
295 5281d757 Mark McLoughlin
{
296 5281d757 Mark McLoughlin
    sigset_t oldmask, mask;
297 5281d757 Mark McLoughlin
    int pid, status;
298 5281d757 Mark McLoughlin
    char *args[3];
299 5281d757 Mark McLoughlin
    char **parg;
300 5281d757 Mark McLoughlin
301 5281d757 Mark McLoughlin
    sigemptyset(&mask);
302 5281d757 Mark McLoughlin
    sigaddset(&mask, SIGCHLD);
303 5281d757 Mark McLoughlin
    sigprocmask(SIG_BLOCK, &mask, &oldmask);
304 5281d757 Mark McLoughlin
305 5281d757 Mark McLoughlin
    /* try to launch network script */
306 5281d757 Mark McLoughlin
    pid = fork();
307 5281d757 Mark McLoughlin
    if (pid == 0) {
308 5281d757 Mark McLoughlin
        int open_max = sysconf(_SC_OPEN_MAX), i;
309 5281d757 Mark McLoughlin
310 5281d757 Mark McLoughlin
        for (i = 0; i < open_max; i++) {
311 5281d757 Mark McLoughlin
            if (i != STDIN_FILENO &&
312 5281d757 Mark McLoughlin
                i != STDOUT_FILENO &&
313 5281d757 Mark McLoughlin
                i != STDERR_FILENO &&
314 5281d757 Mark McLoughlin
                i != fd) {
315 5281d757 Mark McLoughlin
                close(i);
316 5281d757 Mark McLoughlin
            }
317 5281d757 Mark McLoughlin
        }
318 5281d757 Mark McLoughlin
        parg = args;
319 5281d757 Mark McLoughlin
        *parg++ = (char *)setup_script;
320 5281d757 Mark McLoughlin
        *parg++ = (char *)ifname;
321 5281d757 Mark McLoughlin
        *parg++ = NULL;
322 5281d757 Mark McLoughlin
        execv(setup_script, args);
323 5281d757 Mark McLoughlin
        _exit(1);
324 5281d757 Mark McLoughlin
    } else if (pid > 0) {
325 5281d757 Mark McLoughlin
        while (waitpid(pid, &status, 0) != pid) {
326 5281d757 Mark McLoughlin
            /* loop */
327 5281d757 Mark McLoughlin
        }
328 5281d757 Mark McLoughlin
        sigprocmask(SIG_SETMASK, &oldmask, NULL);
329 5281d757 Mark McLoughlin
330 5281d757 Mark McLoughlin
        if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
331 5281d757 Mark McLoughlin
            return 0;
332 5281d757 Mark McLoughlin
        }
333 5281d757 Mark McLoughlin
    }
334 5281d757 Mark McLoughlin
    fprintf(stderr, "%s: could not launch network script\n", setup_script);
335 5281d757 Mark McLoughlin
    return -1;
336 5281d757 Mark McLoughlin
}
337 5281d757 Mark McLoughlin
338 5281d757 Mark McLoughlin
static int net_tap_init(QemuOpts *opts, int *vnet_hdr)
339 5281d757 Mark McLoughlin
{
340 5281d757 Mark McLoughlin
    int fd, vnet_hdr_required;
341 5281d757 Mark McLoughlin
    char ifname[128] = {0,};
342 5281d757 Mark McLoughlin
    const char *setup_script;
343 5281d757 Mark McLoughlin
344 5281d757 Mark McLoughlin
    if (qemu_opt_get(opts, "ifname")) {
345 5281d757 Mark McLoughlin
        pstrcpy(ifname, sizeof(ifname), qemu_opt_get(opts, "ifname"));
346 5281d757 Mark McLoughlin
    }
347 5281d757 Mark McLoughlin
348 5281d757 Mark McLoughlin
    *vnet_hdr = qemu_opt_get_bool(opts, "vnet_hdr", 1);
349 5281d757 Mark McLoughlin
    if (qemu_opt_get(opts, "vnet_hdr")) {
350 5281d757 Mark McLoughlin
        vnet_hdr_required = *vnet_hdr;
351 5281d757 Mark McLoughlin
    } else {
352 5281d757 Mark McLoughlin
        vnet_hdr_required = 0;
353 5281d757 Mark McLoughlin
    }
354 5281d757 Mark McLoughlin
355 5281d757 Mark McLoughlin
    TFR(fd = tap_open(ifname, sizeof(ifname), vnet_hdr, vnet_hdr_required));
356 5281d757 Mark McLoughlin
    if (fd < 0) {
357 5281d757 Mark McLoughlin
        return -1;
358 5281d757 Mark McLoughlin
    }
359 5281d757 Mark McLoughlin
360 5281d757 Mark McLoughlin
    setup_script = qemu_opt_get(opts, "script");
361 5281d757 Mark McLoughlin
    if (setup_script &&
362 5281d757 Mark McLoughlin
        setup_script[0] != '\0' &&
363 5281d757 Mark McLoughlin
        strcmp(setup_script, "no") != 0 &&
364 5281d757 Mark McLoughlin
        launch_script(setup_script, ifname, fd)) {
365 5281d757 Mark McLoughlin
        close(fd);
366 5281d757 Mark McLoughlin
        return -1;
367 5281d757 Mark McLoughlin
    }
368 5281d757 Mark McLoughlin
369 5281d757 Mark McLoughlin
    qemu_opt_set(opts, "ifname", ifname);
370 5281d757 Mark McLoughlin
371 5281d757 Mark McLoughlin
    return fd;
372 5281d757 Mark McLoughlin
}
373 5281d757 Mark McLoughlin
374 5281d757 Mark McLoughlin
int net_init_tap(QemuOpts *opts, Monitor *mon, const char *name, VLANState *vlan)
375 5281d757 Mark McLoughlin
{
376 5281d757 Mark McLoughlin
    TAPState *s;
377 5281d757 Mark McLoughlin
    int fd, vnet_hdr;
378 5281d757 Mark McLoughlin
379 5281d757 Mark McLoughlin
    if (qemu_opt_get(opts, "fd")) {
380 5281d757 Mark McLoughlin
        if (qemu_opt_get(opts, "ifname") ||
381 5281d757 Mark McLoughlin
            qemu_opt_get(opts, "script") ||
382 5281d757 Mark McLoughlin
            qemu_opt_get(opts, "downscript") ||
383 5281d757 Mark McLoughlin
            qemu_opt_get(opts, "vnet_hdr")) {
384 5281d757 Mark McLoughlin
            qemu_error("ifname=, script=, downscript= and vnet_hdr= is invalid with fd=\n");
385 5281d757 Mark McLoughlin
            return -1;
386 5281d757 Mark McLoughlin
        }
387 5281d757 Mark McLoughlin
388 5281d757 Mark McLoughlin
        fd = net_handle_fd_param(mon, qemu_opt_get(opts, "fd"));
389 5281d757 Mark McLoughlin
        if (fd == -1) {
390 5281d757 Mark McLoughlin
            return -1;
391 5281d757 Mark McLoughlin
        }
392 5281d757 Mark McLoughlin
393 5281d757 Mark McLoughlin
        fcntl(fd, F_SETFL, O_NONBLOCK);
394 5281d757 Mark McLoughlin
395 5281d757 Mark McLoughlin
        vnet_hdr = tap_probe_vnet_hdr(fd);
396 5281d757 Mark McLoughlin
    } else {
397 5281d757 Mark McLoughlin
        if (!qemu_opt_get(opts, "script")) {
398 5281d757 Mark McLoughlin
            qemu_opt_set(opts, "script", DEFAULT_NETWORK_SCRIPT);
399 5281d757 Mark McLoughlin
        }
400 5281d757 Mark McLoughlin
401 5281d757 Mark McLoughlin
        if (!qemu_opt_get(opts, "downscript")) {
402 5281d757 Mark McLoughlin
            qemu_opt_set(opts, "downscript", DEFAULT_NETWORK_DOWN_SCRIPT);
403 5281d757 Mark McLoughlin
        }
404 5281d757 Mark McLoughlin
405 5281d757 Mark McLoughlin
        fd = net_tap_init(opts, &vnet_hdr);
406 5281d757 Mark McLoughlin
    }
407 5281d757 Mark McLoughlin
408 5281d757 Mark McLoughlin
    s = net_tap_fd_init(vlan, "tap", name, fd, vnet_hdr);
409 5281d757 Mark McLoughlin
    if (!s) {
410 5281d757 Mark McLoughlin
        close(fd);
411 5281d757 Mark McLoughlin
        return -1;
412 5281d757 Mark McLoughlin
    }
413 5281d757 Mark McLoughlin
414 15ac913b Mark McLoughlin
    if (tap_set_sndbuf(s->fd, opts) < 0) {
415 5281d757 Mark McLoughlin
        return -1;
416 5281d757 Mark McLoughlin
    }
417 5281d757 Mark McLoughlin
418 5281d757 Mark McLoughlin
    if (qemu_opt_get(opts, "fd")) {
419 5281d757 Mark McLoughlin
        snprintf(s->vc->info_str, sizeof(s->vc->info_str), "fd=%d", fd);
420 5281d757 Mark McLoughlin
    } else {
421 5281d757 Mark McLoughlin
        const char *ifname, *script, *downscript;
422 5281d757 Mark McLoughlin
423 5281d757 Mark McLoughlin
        ifname     = qemu_opt_get(opts, "ifname");
424 5281d757 Mark McLoughlin
        script     = qemu_opt_get(opts, "script");
425 5281d757 Mark McLoughlin
        downscript = qemu_opt_get(opts, "downscript");
426 5281d757 Mark McLoughlin
427 5281d757 Mark McLoughlin
        snprintf(s->vc->info_str, sizeof(s->vc->info_str),
428 5281d757 Mark McLoughlin
                 "ifname=%s,script=%s,downscript=%s",
429 5281d757 Mark McLoughlin
                 ifname, script, downscript);
430 5281d757 Mark McLoughlin
431 5281d757 Mark McLoughlin
        if (strcmp(downscript, "no") != 0) {
432 5281d757 Mark McLoughlin
            snprintf(s->down_script, sizeof(s->down_script), "%s", downscript);
433 5281d757 Mark McLoughlin
            snprintf(s->down_script_arg, sizeof(s->down_script_arg), "%s", ifname);
434 5281d757 Mark McLoughlin
        }
435 5281d757 Mark McLoughlin
    }
436 5281d757 Mark McLoughlin
437 5281d757 Mark McLoughlin
    if (vlan) {
438 5281d757 Mark McLoughlin
        vlan->nb_host_devs++;
439 5281d757 Mark McLoughlin
    }
440 5281d757 Mark McLoughlin
441 5281d757 Mark McLoughlin
    return 0;
442 5281d757 Mark McLoughlin
}