Statistics
| Branch: | Revision:

root / net / tap.c @ 95d528a2

History | View | Annotate | Download (11.7 kB)

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 "net/tap.h"
27

    
28
#include "config-host.h"
29

    
30
#include <signal.h>
31
#include <sys/ioctl.h>
32
#include <sys/stat.h>
33
#include <sys/wait.h>
34
#include <sys/socket.h>
35
#include <net/if.h>
36

    
37
#include "net.h"
38
#include "sysemu.h"
39
#include "qemu-char.h"
40
#include "qemu-common.h"
41
#include "qemu-error.h"
42

    
43
#include "net/tap-linux.h"
44

    
45
/* Maximum GSO packet size (64k) plus plenty of room for
46
 * the ethernet and virtio_net headers
47
 */
48
#define TAP_BUFSIZE (4096 + 65536)
49

    
50
typedef struct TAPState {
51
    VLANClientState nc;
52
    int fd;
53
    char down_script[1024];
54
    char down_script_arg[128];
55
    uint8_t buf[TAP_BUFSIZE];
56
    unsigned int read_poll : 1;
57
    unsigned int write_poll : 1;
58
    unsigned int has_vnet_hdr : 1;
59
    unsigned int using_vnet_hdr : 1;
60
    unsigned int has_ufo: 1;
61
} TAPState;
62

    
63
static int launch_script(const char *setup_script, const char *ifname, int fd);
64

    
65
static int tap_can_send(void *opaque);
66
static void tap_send(void *opaque);
67
static void tap_writable(void *opaque);
68

    
69
static void tap_update_fd_handler(TAPState *s)
70
{
71
    qemu_set_fd_handler2(s->fd,
72
                         s->read_poll  ? tap_can_send : NULL,
73
                         s->read_poll  ? tap_send     : NULL,
74
                         s->write_poll ? tap_writable : NULL,
75
                         s);
76
}
77

    
78
static void tap_read_poll(TAPState *s, int enable)
79
{
80
    s->read_poll = !!enable;
81
    tap_update_fd_handler(s);
82
}
83

    
84
static void tap_write_poll(TAPState *s, int enable)
85
{
86
    s->write_poll = !!enable;
87
    tap_update_fd_handler(s);
88
}
89

    
90
static void tap_writable(void *opaque)
91
{
92
    TAPState *s = opaque;
93

    
94
    tap_write_poll(s, 0);
95

    
96
    qemu_flush_queued_packets(&s->nc);
97
}
98

    
99
static ssize_t tap_write_packet(TAPState *s, const struct iovec *iov, int iovcnt)
100
{
101
    ssize_t len;
102

    
103
    do {
104
        len = writev(s->fd, iov, iovcnt);
105
    } while (len == -1 && errno == EINTR);
106

    
107
    if (len == -1 && errno == EAGAIN) {
108
        tap_write_poll(s, 1);
109
        return 0;
110
    }
111

    
112
    return len;
113
}
114

    
115
static ssize_t tap_receive_iov(VLANClientState *nc, const struct iovec *iov,
116
                               int iovcnt)
117
{
118
    TAPState *s = DO_UPCAST(TAPState, nc, nc);
119
    const struct iovec *iovp = iov;
120
    struct iovec iov_copy[iovcnt + 1];
121
    struct virtio_net_hdr hdr = { 0, };
122

    
123
    if (s->has_vnet_hdr && !s->using_vnet_hdr) {
124
        iov_copy[0].iov_base = &hdr;
125
        iov_copy[0].iov_len =  sizeof(hdr);
126
        memcpy(&iov_copy[1], iov, iovcnt * sizeof(*iov));
127
        iovp = iov_copy;
128
        iovcnt++;
129
    }
130

    
131
    return tap_write_packet(s, iovp, iovcnt);
132
}
133

    
134
static ssize_t tap_receive_raw(VLANClientState *nc, const uint8_t *buf, size_t size)
135
{
136
    TAPState *s = DO_UPCAST(TAPState, nc, nc);
137
    struct iovec iov[2];
138
    int iovcnt = 0;
139
    struct virtio_net_hdr hdr = { 0, };
140

    
141
    if (s->has_vnet_hdr) {
142
        iov[iovcnt].iov_base = &hdr;
143
        iov[iovcnt].iov_len  = sizeof(hdr);
144
        iovcnt++;
145
    }
146

    
147
    iov[iovcnt].iov_base = (char *)buf;
148
    iov[iovcnt].iov_len  = size;
149
    iovcnt++;
150

    
151
    return tap_write_packet(s, iov, iovcnt);
152
}
153

    
154
static ssize_t tap_receive(VLANClientState *nc, const uint8_t *buf, size_t size)
155
{
156
    TAPState *s = DO_UPCAST(TAPState, nc, nc);
157
    struct iovec iov[1];
158

    
159
    if (s->has_vnet_hdr && !s->using_vnet_hdr) {
160
        return tap_receive_raw(nc, buf, size);
161
    }
162

    
163
    iov[0].iov_base = (char *)buf;
164
    iov[0].iov_len  = size;
165

    
166
    return tap_write_packet(s, iov, 1);
167
}
168

    
169
static int tap_can_send(void *opaque)
170
{
171
    TAPState *s = opaque;
172

    
173
    return qemu_can_send_packet(&s->nc);
174
}
175

    
176
#ifndef __sun__
177
ssize_t tap_read_packet(int tapfd, uint8_t *buf, int maxlen)
178
{
179
    return read(tapfd, buf, maxlen);
180
}
181
#endif
182

    
183
static void tap_send_completed(VLANClientState *nc, ssize_t len)
184
{
185
    TAPState *s = DO_UPCAST(TAPState, nc, nc);
186
    tap_read_poll(s, 1);
187
}
188

    
189
static void tap_send(void *opaque)
190
{
191
    TAPState *s = opaque;
192
    int size;
193

    
194
    do {
195
        uint8_t *buf = s->buf;
196

    
197
        size = tap_read_packet(s->fd, s->buf, sizeof(s->buf));
198
        if (size <= 0) {
199
            break;
200
        }
201

    
202
        if (s->has_vnet_hdr && !s->using_vnet_hdr) {
203
            buf  += sizeof(struct virtio_net_hdr);
204
            size -= sizeof(struct virtio_net_hdr);
205
        }
206

    
207
        size = qemu_send_packet_async(&s->nc, buf, size, tap_send_completed);
208
        if (size == 0) {
209
            tap_read_poll(s, 0);
210
        }
211
    } while (size > 0 && qemu_can_send_packet(&s->nc));
212
}
213

    
214
int tap_has_ufo(VLANClientState *nc)
215
{
216
    TAPState *s = DO_UPCAST(TAPState, nc, nc);
217

    
218
    assert(nc->info->type == NET_CLIENT_TYPE_TAP);
219

    
220
    return s->has_ufo;
221
}
222

    
223
int tap_has_vnet_hdr(VLANClientState *nc)
224
{
225
    TAPState *s = DO_UPCAST(TAPState, nc, nc);
226

    
227
    assert(nc->info->type == NET_CLIENT_TYPE_TAP);
228

    
229
    return s->has_vnet_hdr;
230
}
231

    
232
void tap_using_vnet_hdr(VLANClientState *nc, int using_vnet_hdr)
233
{
234
    TAPState *s = DO_UPCAST(TAPState, nc, nc);
235

    
236
    using_vnet_hdr = using_vnet_hdr != 0;
237

    
238
    assert(nc->info->type == NET_CLIENT_TYPE_TAP);
239
    assert(s->has_vnet_hdr == using_vnet_hdr);
240

    
241
    s->using_vnet_hdr = using_vnet_hdr;
242
}
243

    
244
void tap_set_offload(VLANClientState *nc, int csum, int tso4,
245
                     int tso6, int ecn, int ufo)
246
{
247
    TAPState *s = DO_UPCAST(TAPState, nc, nc);
248

    
249
    return tap_fd_set_offload(s->fd, csum, tso4, tso6, ecn, ufo);
250
}
251

    
252
static void tap_cleanup(VLANClientState *nc)
253
{
254
    TAPState *s = DO_UPCAST(TAPState, nc, nc);
255

    
256
    qemu_purge_queued_packets(nc);
257

    
258
    if (s->down_script[0])
259
        launch_script(s->down_script, s->down_script_arg, s->fd);
260

    
261
    tap_read_poll(s, 0);
262
    tap_write_poll(s, 0);
263
    close(s->fd);
264
}
265

    
266
static void tap_poll(VLANClientState *nc, bool enable)
267
{
268
    TAPState *s = DO_UPCAST(TAPState, nc, nc);
269
    tap_read_poll(s, enable);
270
    tap_write_poll(s, enable);
271
}
272

    
273
int tap_get_fd(VLANClientState *nc)
274
{
275
    TAPState *s = DO_UPCAST(TAPState, nc, nc);
276
    assert(nc->info->type == NET_CLIENT_TYPE_TAP);
277
    return s->fd;
278
}
279

    
280
/* fd support */
281

    
282
static NetClientInfo net_tap_info = {
283
    .type = NET_CLIENT_TYPE_TAP,
284
    .size = sizeof(TAPState),
285
    .receive = tap_receive,
286
    .receive_raw = tap_receive_raw,
287
    .receive_iov = tap_receive_iov,
288
    .poll = tap_poll,
289
    .cleanup = tap_cleanup,
290
};
291

    
292
static TAPState *net_tap_fd_init(VLANState *vlan,
293
                                 const char *model,
294
                                 const char *name,
295
                                 int fd,
296
                                 int vnet_hdr)
297
{
298
    VLANClientState *nc;
299
    TAPState *s;
300

    
301
    nc = qemu_new_net_client(&net_tap_info, vlan, NULL, model, name);
302

    
303
    s = DO_UPCAST(TAPState, nc, nc);
304

    
305
    s->fd = fd;
306
    s->has_vnet_hdr = vnet_hdr != 0;
307
    s->using_vnet_hdr = 0;
308
    s->has_ufo = tap_probe_has_ufo(s->fd);
309
    tap_set_offload(&s->nc, 0, 0, 0, 0, 0);
310
    tap_read_poll(s, 1);
311
    return s;
312
}
313

    
314
static int launch_script(const char *setup_script, const char *ifname, int fd)
315
{
316
    sigset_t oldmask, mask;
317
    int pid, status;
318
    char *args[3];
319
    char **parg;
320

    
321
    sigemptyset(&mask);
322
    sigaddset(&mask, SIGCHLD);
323
    sigprocmask(SIG_BLOCK, &mask, &oldmask);
324

    
325
    /* try to launch network script */
326
    pid = fork();
327
    if (pid == 0) {
328
        int open_max = sysconf(_SC_OPEN_MAX), i;
329

    
330
        for (i = 0; i < open_max; i++) {
331
            if (i != STDIN_FILENO &&
332
                i != STDOUT_FILENO &&
333
                i != STDERR_FILENO &&
334
                i != fd) {
335
                close(i);
336
            }
337
        }
338
        parg = args;
339
        *parg++ = (char *)setup_script;
340
        *parg++ = (char *)ifname;
341
        *parg++ = NULL;
342
        execv(setup_script, args);
343
        _exit(1);
344
    } else if (pid > 0) {
345
        while (waitpid(pid, &status, 0) != pid) {
346
            /* loop */
347
        }
348
        sigprocmask(SIG_SETMASK, &oldmask, NULL);
349

    
350
        if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
351
            return 0;
352
        }
353
    }
354
    fprintf(stderr, "%s: could not launch network script\n", setup_script);
355
    return -1;
356
}
357

    
358
static int net_tap_init(QemuOpts *opts, int *vnet_hdr)
359
{
360
    int fd, vnet_hdr_required;
361
    char ifname[128] = {0,};
362
    const char *setup_script;
363

    
364
    if (qemu_opt_get(opts, "ifname")) {
365
        pstrcpy(ifname, sizeof(ifname), qemu_opt_get(opts, "ifname"));
366
    }
367

    
368
    *vnet_hdr = qemu_opt_get_bool(opts, "vnet_hdr", 1);
369
    if (qemu_opt_get(opts, "vnet_hdr")) {
370
        vnet_hdr_required = *vnet_hdr;
371
    } else {
372
        vnet_hdr_required = 0;
373
    }
374

    
375
    TFR(fd = tap_open(ifname, sizeof(ifname), vnet_hdr, vnet_hdr_required));
376
    if (fd < 0) {
377
        return -1;
378
    }
379

    
380
    setup_script = qemu_opt_get(opts, "script");
381
    if (setup_script &&
382
        setup_script[0] != '\0' &&
383
        strcmp(setup_script, "no") != 0 &&
384
        launch_script(setup_script, ifname, fd)) {
385
        close(fd);
386
        return -1;
387
    }
388

    
389
    qemu_opt_set(opts, "ifname", ifname);
390

    
391
    return fd;
392
}
393

    
394
int net_init_tap(QemuOpts *opts, Monitor *mon, const char *name, VLANState *vlan)
395
{
396
    TAPState *s;
397
    int fd, vnet_hdr = 0;
398

    
399
    if (qemu_opt_get(opts, "fd")) {
400
        if (qemu_opt_get(opts, "ifname") ||
401
            qemu_opt_get(opts, "script") ||
402
            qemu_opt_get(opts, "downscript") ||
403
            qemu_opt_get(opts, "vnet_hdr")) {
404
            error_report("ifname=, script=, downscript= and vnet_hdr= is invalid with fd=");
405
            return -1;
406
        }
407

    
408
        fd = net_handle_fd_param(mon, qemu_opt_get(opts, "fd"));
409
        if (fd == -1) {
410
            return -1;
411
        }
412

    
413
        fcntl(fd, F_SETFL, O_NONBLOCK);
414

    
415
        vnet_hdr = tap_probe_vnet_hdr(fd);
416
    } else {
417
        if (!qemu_opt_get(opts, "script")) {
418
            qemu_opt_set(opts, "script", DEFAULT_NETWORK_SCRIPT);
419
        }
420

    
421
        if (!qemu_opt_get(opts, "downscript")) {
422
            qemu_opt_set(opts, "downscript", DEFAULT_NETWORK_DOWN_SCRIPT);
423
        }
424

    
425
        fd = net_tap_init(opts, &vnet_hdr);
426
        if (fd == -1) {
427
            return -1;
428
        }
429
    }
430

    
431
    s = net_tap_fd_init(vlan, "tap", name, fd, vnet_hdr);
432
    if (!s) {
433
        close(fd);
434
        return -1;
435
    }
436

    
437
    if (tap_set_sndbuf(s->fd, opts) < 0) {
438
        return -1;
439
    }
440

    
441
    if (qemu_opt_get(opts, "fd")) {
442
        snprintf(s->nc.info_str, sizeof(s->nc.info_str), "fd=%d", fd);
443
    } else {
444
        const char *ifname, *script, *downscript;
445

    
446
        ifname     = qemu_opt_get(opts, "ifname");
447
        script     = qemu_opt_get(opts, "script");
448
        downscript = qemu_opt_get(opts, "downscript");
449

    
450
        snprintf(s->nc.info_str, sizeof(s->nc.info_str),
451
                 "ifname=%s,script=%s,downscript=%s",
452
                 ifname, script, downscript);
453

    
454
        if (strcmp(downscript, "no") != 0) {
455
            snprintf(s->down_script, sizeof(s->down_script), "%s", downscript);
456
            snprintf(s->down_script_arg, sizeof(s->down_script_arg), "%s", ifname);
457
        }
458
    }
459

    
460
    return 0;
461
}