Port -net tap to QemuOpts

Some parameters are not valid with fd=. Rather than having a separate
parameter description table for validating fd=, it's easir to just
check for those invalid parameters later.

Note, the need to possible lookup a file descriptor name from the
monitor is the reason why all these init functions are passed a Monitor
pointer.

Signed-off-by: Mark McLoughlin <markmc@redhat.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
This commit is contained in:
Mark McLoughlin 2009-10-06 12:17:08 +01:00 committed by Anthony Liguori
parent ec302ffdfd
commit 8a1c523551
1 changed files with 140 additions and 90 deletions

230
net.c
View File

@ -1365,31 +1365,24 @@ static void tap_send(void *opaque)
*/
#define TAP_DEFAULT_SNDBUF 1024*1024
static int tap_set_sndbuf(TAPState *s, const char *sndbuf_str)
static int tap_set_sndbuf(TAPState *s, QemuOpts *opts)
{
int sndbuf = TAP_DEFAULT_SNDBUF;
if (sndbuf_str) {
sndbuf = atoi(sndbuf_str);
}
int sndbuf;
sndbuf = qemu_opt_get_size(opts, "sndbuf", TAP_DEFAULT_SNDBUF);
if (!sndbuf) {
sndbuf = INT_MAX;
}
if (ioctl(s->fd, TUNSETSNDBUF, &sndbuf) == -1 && sndbuf_str) {
if (ioctl(s->fd, TUNSETSNDBUF, &sndbuf) == -1 && qemu_opt_get(opts, "sndbuf")) {
qemu_error("TUNSETSNDBUF ioctl failed: %s\n", strerror(errno));
return -1;
}
return 0;
}
#else
static int tap_set_sndbuf(TAPState *s, const char *sndbuf_str)
static int tap_set_sndbuf(TAPState *s, QemuOpts *opts)
{
if (sndbuf_str) {
qemu_error("No '-net tap,sndbuf=<nbytes>' support available\n");
return -1;
}
return 0;
}
#endif /* TUNSETSNDBUF */
@ -2554,6 +2547,94 @@ static int net_init_slirp(QemuOpts *opts, Monitor *mon)
return ret;
}
#ifdef _WIN32
static int net_init_tap_win32(QemuOpts *opts, Monitor *mon)
{
VLANState *vlan;
const char *name;
const char *ifname;
vlan = qemu_find_vlan(qemu_opt_get_number(opts, "vlan", 0), 1);
name = qemu_opt_get(opts, "name");
ifname = qemu_opt_get(opts, "ifname");
if (!ifname) {
qemu_error("tap: no interface name\n");
return -1;
}
if (tap_win32_init(vlan, "tap", name, ifname) == -1) {
return -1;
}
vlan->nb_host_devs++;
return 0;
}
#elif !defined(_AIX)
static int net_init_tap(QemuOpts *opts, Monitor *mon)
{
VLANState *vlan;
const char *name;
TAPState *s;
vlan = qemu_find_vlan(qemu_opt_get_number(opts, "vlan", 0), 1);
name = qemu_opt_get(opts, "name");
if (qemu_opt_get(opts, "fd")) {
int fd;
if (qemu_opt_get(opts, "ifname") ||
qemu_opt_get(opts, "script") ||
qemu_opt_get(opts, "downscript")) {
qemu_error("ifname=, script= and downscript= is invalid with fd=\n");
return -1;
}
fd = net_handle_fd_param(mon, qemu_opt_get(opts, "fd"));
if (fd == -1) {
return -1;
}
fcntl(fd, F_SETFL, O_NONBLOCK);
s = net_tap_fd_init(vlan, "tap", name, fd);
if (!s) {
close(fd);
}
} else {
const char *ifname, *script, *downscript;
ifname = qemu_opt_get(opts, "ifname");
script = qemu_opt_get(opts, "script");
downscript = qemu_opt_get(opts, "downscript");
if (!script) {
script = DEFAULT_NETWORK_SCRIPT;
}
if (!downscript) {
downscript = DEFAULT_NETWORK_DOWN_SCRIPT;
}
s = net_tap_init(vlan, "tap", name, ifname, script, downscript);
}
if (!s) {
return -1;
}
if (tap_set_sndbuf(s, opts) < 0) {
return -1;
}
vlan->nb_host_devs++;
return 0;
}
#endif
#define NET_COMMON_PARAMS_DESC \
{ \
.name = "type", \
@ -2670,6 +2751,51 @@ static struct {
},
{ /* end of list */ }
},
#endif
#ifdef _WIN32
}, {
.type = "tap",
.init = net_init_tap_win32,
.desc = {
NET_COMMON_PARAMS_DESC,
{
.name = "ifname",
.type = QEMU_OPT_STRING,
.help = "interface name",
},
{ /* end of list */ }
},
#elif !defined(_AIX)
}, {
.type = "tap",
.init = net_init_tap,
.desc = {
NET_COMMON_PARAMS_DESC,
{
.name = "fd",
.type = QEMU_OPT_STRING,
.help = "file descriptor of an already opened tap",
}, {
.name = "ifname",
.type = QEMU_OPT_STRING,
.help = "interface name",
}, {
.name = "script",
.type = QEMU_OPT_STRING,
.help = "script to initialize the interface",
}, {
.name = "downscript",
.type = QEMU_OPT_STRING,
.help = "script to shut down the interface",
#ifdef TUNSETSNDBUF
}, {
.name = "sndbuf",
.type = QEMU_OPT_SIZE,
.help = "send buffer limit"
#endif
},
{ /* end of list */ }
},
#endif
},
{ /* end of list */ }
@ -2713,7 +2839,8 @@ int net_client_init(Monitor *mon, const char *device, const char *p)
if (!strcmp(device, "none") ||
!strcmp(device, "nic") ||
!strcmp(device, "user")) {
!strcmp(device, "user") ||
!strcmp(device, "tap")) {
QemuOpts *opts;
opts = qemu_opts_parse(&qemu_net_opts, p, NULL);
@ -2751,83 +2878,6 @@ int net_client_init(Monitor *mon, const char *device, const char *p)
ret = slirp_guestfwd(QTAILQ_FIRST(&slirp_stacks), p, 1);
}
} else
#endif
#ifdef _WIN32
if (!strcmp(device, "tap")) {
static const char * const tap_params[] = {
"vlan", "name", "ifname", NULL
};
char ifname[64];
if (check_params(buf, sizeof(buf), tap_params, p) < 0) {
qemu_error("invalid parameter '%s' in '%s'\n", buf, p);
ret = -1;
goto out;
}
if (get_param_value(ifname, sizeof(ifname), "ifname", p) <= 0) {
qemu_error("tap: no interface name\n");
ret = -1;
goto out;
}
vlan->nb_host_devs++;
ret = tap_win32_init(vlan, device, name, ifname);
} else
#elif defined (_AIX)
#else
if (!strcmp(device, "tap")) {
char ifname[64], chkbuf[64];
char setup_script[1024], down_script[1024];
TAPState *s;
int fd;
vlan->nb_host_devs++;
if (get_param_value(buf, sizeof(buf), "fd", p) > 0) {
static const char * const fd_params[] = {
"vlan", "name", "fd", "sndbuf", NULL
};
ret = -1;
if (check_params(chkbuf, sizeof(chkbuf), fd_params, p) < 0) {
qemu_error("invalid parameter '%s' in '%s'\n", chkbuf, p);
goto out;
}
fd = net_handle_fd_param(mon, buf);
if (fd == -1) {
goto out;
}
fcntl(fd, F_SETFL, O_NONBLOCK);
s = net_tap_fd_init(vlan, device, name, fd);
if (!s) {
close(fd);
}
} else {
static const char * const tap_params[] = {
"vlan", "name", "ifname", "script", "downscript", "sndbuf", NULL
};
if (check_params(chkbuf, sizeof(chkbuf), tap_params, p) < 0) {
qemu_error("invalid parameter '%s' in '%s'\n", chkbuf, p);
ret = -1;
goto out;
}
if (get_param_value(ifname, sizeof(ifname), "ifname", p) <= 0) {
ifname[0] = '\0';
}
if (get_param_value(setup_script, sizeof(setup_script), "script", p) == 0) {
pstrcpy(setup_script, sizeof(setup_script), DEFAULT_NETWORK_SCRIPT);
}
if (get_param_value(down_script, sizeof(down_script), "downscript", p) == 0) {
pstrcpy(down_script, sizeof(down_script), DEFAULT_NETWORK_DOWN_SCRIPT);
}
s = net_tap_init(vlan, device, name, ifname, setup_script, down_script);
}
if (s != NULL) {
const char *sndbuf_str = NULL;
if (get_param_value(buf, sizeof(buf), "sndbuf", p)) {
sndbuf_str = buf;
}
ret = tap_set_sndbuf(s, sndbuf_str);
} else {
ret = -1;
}
} else
#endif
if (!strcmp(device, "socket")) {
char chkbuf[64];