* [Qemu-devel] [PATCH 0/2] Marry slirp and qemu character device.
@ 2008-12-29 14:39 Gleb Natapov
2008-12-29 14:39 ` [Qemu-devel] [PATCH 1/2] Redirect slirp traffic to/from " Gleb Natapov
2008-12-29 14:39 ` [Qemu-devel] [PATCH 2/2] Add vmchannel command line option Gleb Natapov
0 siblings, 2 replies; 3+ messages in thread
From: Gleb Natapov @ 2008-12-29 14:39 UTC (permalink / raw)
To: qemu-devel
Trap TCP connection to special IP/port inside slirp and redirect its
traffic to a qemu character device. This is needed for communication
between host and guest management agents. I am also planning to add an
option to slirp networking to disable connection to outside world through
it. This way tap will be used for general networking and slirp will be
used for secure guest<->host communication.
---
Gleb Natapov (2):
Add vmchannel command line option.
Redirect slirp traffic to/from qemu character device.
slirp/libslirp.h | 5 ++-
slirp/main.h | 1 +
slirp/misc.c | 2 +
slirp/sbuf.c | 2 +
slirp/slirp.c | 57 +++++++++++++++++++++++++++++++
slirp/socket.c | 99 +++++++++++++++++++++++++++++++++++++++++++-----------
slirp/socket.h | 2 +
slirp/tcp_subr.c | 5 +++
vl.c | 75 ++++++++++++++++++++++++++++++++++++++++-
9 files changed, 223 insertions(+), 25 deletions(-)
--
Gleb.
^ permalink raw reply [flat|nested] 3+ messages in thread
* [Qemu-devel] [PATCH 1/2] Redirect slirp traffic to/from qemu character device.
2008-12-29 14:39 [Qemu-devel] [PATCH 0/2] Marry slirp and qemu character device Gleb Natapov
@ 2008-12-29 14:39 ` Gleb Natapov
2008-12-29 14:39 ` [Qemu-devel] [PATCH 2/2] Add vmchannel command line option Gleb Natapov
1 sibling, 0 replies; 3+ messages in thread
From: Gleb Natapov @ 2008-12-29 14:39 UTC (permalink / raw)
To: qemu-devel
Signed-off-by: Gleb Natapov <gleb@redhat.com>
---
slirp/libslirp.h | 5 ++-
slirp/main.h | 1 +
slirp/misc.c | 2 +
slirp/sbuf.c | 2 +
slirp/slirp.c | 57 +++++++++++++++++++++++++++++++
slirp/socket.c | 99 +++++++++++++++++++++++++++++++++++++++++++-----------
slirp/socket.h | 2 +
slirp/tcp_subr.c | 5 +++
8 files changed, 149 insertions(+), 24 deletions(-)
diff --git a/slirp/libslirp.h b/slirp/libslirp.h
index 7e4cfa9..16a817a 100644
--- a/slirp/libslirp.h
+++ b/slirp/libslirp.h
@@ -20,13 +20,16 @@ void slirp_output(const uint8_t *pkt, int pkt_len);
int slirp_redir(int is_udp, int host_port,
struct in_addr guest_addr, int guest_port);
-int slirp_add_exec(int do_pty, const char *args, int addr_low_byte,
+int slirp_add_exec(int do_pty, const void *args, int addr_low_byte,
int guest_port);
extern const char *tftp_prefix;
extern char slirp_hostname[33];
void slirp_stats(void);
+void slirp_socket_recv(int addr_low_byte, int guest_port, const uint8_t *buf,
+ int size);
+size_t slirp_socket_can_recv(int addr_low_byte, int guest_port);
#ifdef __cplusplus
}
diff --git a/slirp/main.h b/slirp/main.h
index c01adda..3ef2996 100644
--- a/slirp/main.h
+++ b/slirp/main.h
@@ -51,3 +51,4 @@ extern uint8_t client_ethaddr[6];
#endif
void if_encap(const uint8_t *ip_data, int ip_data_len);
+ssize_t slirp_send(struct socket *so, const void *buf, size_t len, int flags);
diff --git a/slirp/misc.c b/slirp/misc.c
index 9ff3176..1ec8b55 100644
--- a/slirp/misc.c
+++ b/slirp/misc.c
@@ -169,7 +169,7 @@ add_exec(ex_ptr, do_pty, exec, addr, port)
(*ex_ptr)->ex_fport = port;
(*ex_ptr)->ex_addr = addr;
(*ex_ptr)->ex_pty = do_pty;
- (*ex_ptr)->ex_exec = strdup(exec);
+ (*ex_ptr)->ex_exec = (do_pty == 3) ? exec : strdup(exec);
(*ex_ptr)->ex_next = tmp_ptr;
return 0;
}
diff --git a/slirp/sbuf.c b/slirp/sbuf.c
index b0e0838..2e6e2b2 100644
--- a/slirp/sbuf.c
+++ b/slirp/sbuf.c
@@ -108,7 +108,7 @@ sbappend(so, m)
* ottherwise it'll arrive out of order, and hence corrupt
*/
if (!so->so_rcv.sb_cc)
- ret = send(so->s, m->m_data, m->m_len, 0);
+ ret = slirp_send(so, m->m_data, m->m_len, 0);
if (ret <= 0) {
/*
diff --git a/slirp/slirp.c b/slirp/slirp.c
index 17b40e2..378d3e8 100644
--- a/slirp/slirp.c
+++ b/slirp/slirp.c
@@ -736,9 +736,64 @@ int slirp_redir(int is_udp, int host_port,
return 0;
}
-int slirp_add_exec(int do_pty, const char *args, int addr_low_byte,
+int slirp_add_exec(int do_pty, const void *args, int addr_low_byte,
int guest_port)
{
return add_exec(&exec_list, do_pty, (char *)args,
addr_low_byte, htons(guest_port));
}
+
+ssize_t slirp_send(struct socket *so, const void *buf, size_t len, int flags)
+{
+ if (so->s == -1) {
+ qemu_chr_write(so->extra, buf, len);
+ return len;
+ }
+
+ return send(so->s, buf, len, flags);
+}
+
+static struct socket *slirp_find_ctl_socket(int addr_low_byte, int guest_port)
+{
+ struct socket *so;
+
+ for (so = tcb.so_next; so != &tcb; so = so->so_next) {
+ if ((so->so_faddr.s_addr & htonl(0xffffff00)) ==
+ special_addr.s_addr
+ && (ntohl(so->so_faddr.s_addr) & 0xff) ==
+ addr_low_byte
+ && htons(so->so_fport) == guest_port)
+ return so;
+ }
+
+ return NULL;
+}
+
+size_t slirp_socket_can_recv(int addr_low_byte, int guest_port)
+{
+ struct iovec iov[2];
+ struct socket *so = slirp_find_ctl_socket(addr_low_byte, guest_port);
+
+ if (!so || so->so_state & SS_NOFDREF)
+ return 0;
+
+ if (!CONN_CANFRCV(so) || so->so_snd.sb_cc >= (so->so_snd.sb_datalen/2))
+ return 0;
+
+ return sopreprbuf(so, iov, NULL);
+}
+
+void slirp_socket_recv(int addr_low_byte, int guest_port, const uint8_t *buf,
+ int size)
+{
+ int ret;
+ struct socket *so = slirp_find_ctl_socket(addr_low_byte, guest_port);
+
+ if (!so)
+ return;
+
+ ret = soreadbuf(so, buf, size);
+
+ if (ret > 0)
+ tcp_output(sototcpcb(so));
+}
diff --git a/slirp/socket.c b/slirp/socket.c
index 00694e2..a45be82 100644
--- a/slirp/socket.c
+++ b/slirp/socket.c
@@ -91,31 +91,21 @@ sofree(so)
free(so);
}
-/*
- * Read from so's socket into sb_snd, updating all relevant sbuf fields
- * NOTE: This will only be called if it is select()ed for reading, so
- * a read() of 0 (or less) means it's disconnected
- */
-int
-soread(so)
- struct socket *so;
+size_t sopreprbuf(struct socket *so, struct iovec *iov, int *np)
{
- int n, nn, lss, total;
+ int n, lss, total;
struct sbuf *sb = &so->so_snd;
int len = sb->sb_datalen - sb->sb_cc;
- struct iovec iov[2];
int mss = so->so_tcpcb->t_maxseg;
- DEBUG_CALL("soread");
+ DEBUG_CALL("sopreprbuf");
DEBUG_ARG("so = %lx", (long )so);
- /*
- * No need to check if there's enough room to read.
- * soread wouldn't have been called if there weren't
- */
-
len = sb->sb_datalen - sb->sb_cc;
+ if (len <= 0)
+ return 0;
+
iov[0].iov_base = sb->sb_wptr;
iov[1].iov_base = NULL;
iov[1].iov_len = 0;
@@ -156,6 +146,33 @@ soread(so)
n = 1;
}
}
+ if (np)
+ *np = n;
+
+ return iov[0].iov_len + (n - 1) * iov[1].iov_len;
+}
+
+/*
+ * Read from so's socket into sb_snd, updating all relevant sbuf fields
+ * NOTE: This will only be called if it is select()ed for reading, so
+ * a read() of 0 (or less) means it's disconnected
+ */
+int
+soread(so)
+ struct socket *so;
+{
+ int n, nn;
+ struct sbuf *sb = &so->so_snd;
+ struct iovec iov[2];
+
+ DEBUG_CALL("soread");
+ DEBUG_ARG("so = %lx", (long )so);
+
+ /*
+ * No need to check if there's enough room to read.
+ * soread wouldn't have been called if there weren't
+ */
+ sopreprbuf(so, iov, &n);
#ifdef HAVE_READV
nn = readv(so->s, (struct iovec *)iov, n);
@@ -202,6 +219,48 @@ soread(so)
return nn;
}
+int soreadbuf(struct socket *so, const char *buf, int size)
+{
+ int n, nn, copy = size;
+ struct sbuf *sb = &so->so_snd;
+ struct iovec iov[2];
+
+ DEBUG_CALL("soreadbuf");
+ DEBUG_ARG("so = %lx", (long )so);
+
+ /*
+ * No need to check if there's enough room to read.
+ * soread wouldn't have been called if there weren't
+ */
+ if (sopreprbuf(so, iov, &n) < size)
+ goto err;
+
+ nn = MIN(iov[0].iov_len, copy);
+ memcpy(iov[0].iov_base, buf, nn);
+
+ copy -= nn;
+ buf += nn;
+
+ if (copy == 0)
+ goto done;
+
+ memcpy(iov[1].iov_base, buf, copy);
+
+done:
+ /* Update fields */
+ sb->sb_cc += size;
+ sb->sb_wptr += size;
+ if (sb->sb_wptr >= (sb->sb_data + sb->sb_datalen))
+ sb->sb_wptr -= sb->sb_datalen;
+ return size;
+err:
+
+ sofcantrcvmore(so);
+ tcp_sockclosed(sototcpcb(so));
+ fprintf(stderr, "soreadbuf buffer to small");
+ return -1;
+}
+
/*
* Get urgent data
*
@@ -255,7 +314,7 @@ sosendoob(so)
if (sb->sb_rptr < sb->sb_wptr) {
/* We can send it directly */
- n = send(so->s, sb->sb_rptr, so->so_urgc, (MSG_OOB)); /* |MSG_DONTWAIT)); */
+ n = slirp_send(so, sb->sb_rptr, so->so_urgc, (MSG_OOB)); /* |MSG_DONTWAIT)); */
so->so_urgc -= n;
DEBUG_MISC((dfd, " --- sent %d bytes urgent data, %d urgent bytes left\n", n, so->so_urgc));
@@ -276,7 +335,7 @@ sosendoob(so)
so->so_urgc -= n;
len += n;
}
- n = send(so->s, buff, len, (MSG_OOB)); /* |MSG_DONTWAIT)); */
+ n = slirp_send(so, buff, len, (MSG_OOB)); /* |MSG_DONTWAIT)); */
#ifdef DEBUG
if (n != len)
DEBUG_ERROR((dfd, "Didn't send all data urgently XXXXX\n"));
@@ -348,7 +407,7 @@ sowrite(so)
DEBUG_MISC((dfd, " ... wrote nn = %d bytes\n", nn));
#else
- nn = send(so->s, iov[0].iov_base, iov[0].iov_len,0);
+ nn = slirp_send(so, iov[0].iov_base, iov[0].iov_len,0);
#endif
/* This should never happen, but people tell me it does *shrug* */
if (nn < 0 && (errno == EAGAIN || errno == EINTR))
@@ -365,7 +424,7 @@ sowrite(so)
#ifndef HAVE_READV
if (n == 2 && nn == iov[0].iov_len) {
int ret;
- ret = send(so->s, iov[1].iov_base, iov[1].iov_len,0);
+ ret = slirp_send(so, iov[1].iov_base, iov[1].iov_len,0);
if (ret > 0)
nn += ret;
}
diff --git a/slirp/socket.h b/slirp/socket.h
index 5edea90..72b473d 100644
--- a/slirp/socket.h
+++ b/slirp/socket.h
@@ -87,5 +87,7 @@ void soisfconnecting _P((register struct socket *));
void soisfconnected _P((register struct socket *));
void soisfdisconnected _P((struct socket *));
void sofwdrain _P((struct socket *));
+size_t sopreprbuf(struct socket *so, struct iovec *iov, int *np);
+int soreadbuf(struct socket *so, const char *buf, int size);
#endif /* _SOCKET_H_ */
diff --git a/slirp/tcp_subr.c b/slirp/tcp_subr.c
index bce07a6..12abebe 100644
--- a/slirp/tcp_subr.c
+++ b/slirp/tcp_subr.c
@@ -1281,6 +1281,11 @@ tcp_ctl(so)
for (ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
if (ex_ptr->ex_fport == so->so_fport &&
command == ex_ptr->ex_addr) {
+ if (ex_ptr->ex_pty == 3) {
+ so->s = -1;
+ so->extra = ex_ptr->ex_exec;
+ return 1;
+ }
do_pty = ex_ptr->ex_pty;
goto do_exec;
}
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [Qemu-devel] [PATCH 2/2] Add vmchannel command line option.
2008-12-29 14:39 [Qemu-devel] [PATCH 0/2] Marry slirp and qemu character device Gleb Natapov
2008-12-29 14:39 ` [Qemu-devel] [PATCH 1/2] Redirect slirp traffic to/from " Gleb Natapov
@ 2008-12-29 14:39 ` Gleb Natapov
1 sibling, 0 replies; 3+ messages in thread
From: Gleb Natapov @ 2008-12-29 14:39 UTC (permalink / raw)
To: qemu-devel
Signed-off-by: Gleb Natapov <gleb@redhat.com>
---
vl.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 74 insertions(+), 1 deletions(-)
diff --git a/vl.c b/vl.c
index 07740f5..f9dc31a 100644
--- a/vl.c
+++ b/vl.c
@@ -207,6 +207,13 @@ static int full_screen = 0;
static int no_frame = 0;
#endif
int no_quit = 0;
+#if defined(CONFIG_SLIRP)
+#define MAX_VMCHANNEL_DEVICES 4
+struct VMChannel {
+ CharDriverState *hd;
+ int port;
+} vmchannel_hds[MAX_VMCHANNEL_DEVICES];
+#endif
CharDriverState *serial_hds[MAX_SERIAL_PORTS];
CharDriverState *parallel_hds[MAX_PARALLEL_PORTS];
#ifdef TARGET_I386
@@ -3932,6 +3939,9 @@ static void help(int exitcode)
"-monitor dev redirect the monitor to char device 'dev'\n"
"-serial dev redirect the serial port to char device 'dev'\n"
"-parallel dev redirect the parallel port to char device 'dev'\n"
+#if defined(CONFIG_SLIRP)
+ "-vmchannel di:DI,dev redirect the vmchannel device with device id DI, to char device 'dev'\n"
+#endif
"-pidfile file Write PID to 'file'\n"
"-S freeze CPU at startup (use 'c' to start execution)\n"
"-s wait gdb connection to port\n"
@@ -4046,6 +4056,9 @@ enum {
QEMU_OPTION_monitor,
QEMU_OPTION_serial,
QEMU_OPTION_parallel,
+#if defined(CONFIG_SLIRP)
+ QEMU_OPTION_vmchannel,
+#endif
QEMU_OPTION_loadvm,
QEMU_OPTION_full_screen,
QEMU_OPTION_no_frame,
@@ -4155,6 +4168,9 @@ static const QEMUOption qemu_options[] = {
{ "monitor", HAS_ARG, QEMU_OPTION_monitor },
{ "serial", HAS_ARG, QEMU_OPTION_serial },
{ "parallel", HAS_ARG, QEMU_OPTION_parallel },
+#if defined(CONFIG_SLIRP)
+ { "vmchannel", 1, QEMU_OPTION_vmchannel },
+#endif
{ "loadvm", HAS_ARG, QEMU_OPTION_loadvm },
{ "full-screen", 0, QEMU_OPTION_full_screen },
#ifdef CONFIG_SDL
@@ -4453,6 +4469,20 @@ static void termsig_setup(void)
#endif
+#if defined(CONFIG_SLIRP)
+static int vmchannel_can_read(void *opaque)
+{
+ struct VMChannel *vmc = (struct VMChannel*)opaque;
+ return slirp_socket_can_recv(4, vmc->port);
+}
+
+static void vmchannel_read(void *opaque, const uint8_t *buf, int size)
+{
+ struct VMChannel *vmc = (struct VMChannel*)opaque;
+ slirp_socket_recv(4, vmc->port, buf, size);
+}
+#endif
+
int main(int argc, char **argv, char **envp)
{
#ifdef CONFIG_GDBSTUB
@@ -4480,6 +4510,8 @@ int main(int argc, char **argv, char **envp)
int serial_device_index;
const char *parallel_devices[MAX_PARALLEL_PORTS];
int parallel_device_index;
+ char *vmchannel_devices[MAX_VMCHANNEL_DEVICES];
+ int vmchannel_device_index;
const char *loadvm = NULL;
QEMUMachine *machine;
const char *cpu_model;
@@ -4553,6 +4585,10 @@ int main(int argc, char **argv, char **envp)
parallel_devices[i] = NULL;
parallel_device_index = 0;
+ for(i = 0; i < MAX_VMCHANNEL_DEVICES; i++)
+ vmchannel_devices[i] = NULL;
+ vmchannel_device_index = 0;
+
usb_devices_index = 0;
nb_net_clients = 0;
@@ -4947,7 +4983,15 @@ int main(int argc, char **argv, char **envp)
parallel_devices[parallel_device_index] = optarg;
parallel_device_index++;
break;
- case QEMU_OPTION_loadvm:
+#if defined(CONFIG_SLIRP)
+ case QEMU_OPTION_vmchannel:
+ if (vmchannel_device_index >= MAX_VMCHANNEL_DEVICES) {
+ fprintf(stderr, "qemu: too many vmchannel devices\n");
+ exit(1);
+ }
+ vmchannel_devices[vmchannel_device_index++] = optarg;
+#endif
+ case QEMU_OPTION_loadvm:
loadvm = optarg;
break;
case QEMU_OPTION_full_screen:
@@ -5452,6 +5496,35 @@ int main(int argc, char **argv, char **envp)
}
}
+#if defined(CONFIG_SLIRP)
+ for(i = 0; i < vmchannel_device_index; i++) {
+ char *devname = vmchannel_devices[i];
+ long port;
+ char name[20];
+
+ if (!devname)
+ continue;
+
+ port = strtol(devname, &devname, 10);
+ devname++;
+ if (port < 1 || port > 65535) {
+ fprintf(stderr, "vmchannel: wrong port number\n");
+ exit(1);
+ }
+ snprintf(name, 20, "vmchannel%ld\n", port);
+ vmchannel_hds[i].hd = qemu_chr_open(name, devname);
+ if (!vmchannel_hds[i].hd) {
+ fprintf(stderr, "qemu: could not open vmchannel device '%s'\n",
+ devname);
+ exit(1);
+ }
+ vmchannel_hds[i].port = port;
+ slirp_add_exec(3, vmchannel_hds[i].hd, 4, port);
+ qemu_chr_add_handlers(vmchannel_hds[i].hd, vmchannel_can_read,
+ vmchannel_read, NULL, &vmchannel_hds[i]);
+ }
+#endif
+
machine->init(ram_size, vga_ram_size, boot_devices, ds,
kernel_filename, kernel_cmdline, initrd_filename, cpu_model);
^ permalink raw reply related [flat|nested] 3+ messages in thread
end of thread, other threads:[~2008-12-29 14:38 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-12-29 14:39 [Qemu-devel] [PATCH 0/2] Marry slirp and qemu character device Gleb Natapov
2008-12-29 14:39 ` [Qemu-devel] [PATCH 1/2] Redirect slirp traffic to/from " Gleb Natapov
2008-12-29 14:39 ` [Qemu-devel] [PATCH 2/2] Add vmchannel command line option Gleb Natapov
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).