qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [RFC][PATCH v2 00/19] virtproxy: host/guest communication layer
@ 2010-11-10 22:27 Michael Roth
  2010-11-10 22:27 ` [Qemu-devel] [RFC][PATCH v2 01/19] virtproxy: base data structures and constants Michael Roth
                   ` (19 more replies)
  0 siblings, 20 replies; 21+ messages in thread
From: Michael Roth @ 2010-11-10 22:27 UTC (permalink / raw)
  To: qemu-devel; +Cc: agl, abeekhof, mdroth, aliguori, ryanh, amit.shah

OVERVIEW:

Virtproxy proxies and multiplexes socket streams over a data channel between a host and a guest (currently network connections, emulated serial, or virtio-serial channels are supported). This allows for services such as guest data collection agents, host/guest file transfer, and event generation/handling to be implemented/deployed as basic socket-based daemons, independently of the actual data channel.

This code is intended to provide a channel-independent abstraction layer for communicating with a QEMU-specific guest agent (in particular, the virtagent RPC guest agent which will follow this in a seperate patchset), but may have general utility beyond this (for instance: ssh/sftp/other guest agents/etc over isa/virtio serial), and so is submitted here as a seperate patchset.

CHANGES IN V2:
 - host daemon deprecated, virtproxy now integrated into qemu via a virtproxy chardev. The command-line options have not yet been converted over so for now the virtproxy layer is no longer testable directly. This will be addressed soon. Virtagent will hook into this chardev via a boolean chardev option. That patchset will follow this one shortly.
 - deadlocking issue resolved

BUILD/USAGE INFO:
  # build guest daemon
  make qemu-vp
  ./qemu-vp -h

EXAMPLE USAGE:

note: oforward/iforward chardev options have not yet been converted over from original standalone host daemon implementation so this won't work till then. The examples however have been updated for reference.

 - Proxy http and ssh connections from a host to a guest over a virtio-serial connection:
    # start guest with virtio-serial. for example (RHEL6s13):
    qemu \
    -device virtio-serial \
    -chardev virtproxy,id=test0, \
             oforward=http:127.0.0.1:9080,oforward=ssh:127.0.0.1:22 \
    -device virtconsole,chardev=test0,name=test0 \
    ...
    # in the guest:
    ./qemu-vp -c virtserial-open:/dev/virtio-ports/test2:- -i http:127.0.0.1:80 \
              -i ssh:127.0.0.1:22

    # from host, access guest http server
    wget http://locahost:9080
    # from host, access guest ssh server
    ssh localhost -p 9022

By specifying -i and -o options in the host and guest, respectively, the channel can also be used to establish connections from a guest to a host.

KNOWN ISSUES:

 - Sync issues with virtio-serial: This may or may not be related to the issue above, but I noticed some cases where proxied ssh sessions from the guest to the host would "lag" by a few bytes. For instance typing "top" would result in "to" being displayed, and the "p" wouldn't show up till I hit another key. This could be related to how I'm handling the buffering, but I haven't been able to reproduce using a network-based channel. UPDATE: this issue seems to be fixed here:

    http://git.kernel.org/?p=linux/kernel/git/rusty/linux-2.6-for-linus.git;a=commit;h=6df7aadcd9290807c464675098b5dd2dc9da5075

TODO:

 - Better channel negotiation to gracefully handle guest reboots/disconnects/etc
 - Port qemu-vp -i/-o options to chardev options
 - Add monitor commands to add/remove virtproxy channels/oforwards/iforwards on the fly

 .gitignore          |    1 +
 Makefile            |    4 +-
 Makefile.target     |    2 +-
 configure           |    1 +
 qemu-char.c         |   43 +++
 qemu-vp.c           |  624 +++++++++++++++++++++++++++++++++++++
 roms/seabios        |    2 +-
 virtproxy-builtin.c |   38 +++
 virtproxy.c         |  863 +++++++++++++++++++++++++++++++++++++++++++++++++++
 virtproxy.h         |   47 +++
 10 files changed, 1622 insertions(+), 3 deletions(-)

^ permalink raw reply	[flat|nested] 21+ messages in thread

* [Qemu-devel] [RFC][PATCH v2 01/19] virtproxy: base data structures and constants
  2010-11-10 22:27 [Qemu-devel] [RFC][PATCH v2 00/19] virtproxy: host/guest communication layer Michael Roth
@ 2010-11-10 22:27 ` Michael Roth
  2010-11-10 22:27 ` [Qemu-devel] [RFC][PATCH v2 02/19] virtproxy: qemu-vp, standalone daemon skeleton Michael Roth
                   ` (18 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Michael Roth @ 2010-11-10 22:27 UTC (permalink / raw)
  To: qemu-devel; +Cc: agl, abeekhof, mdroth, aliguori, ryanh, amit.shah


Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 virtproxy.c |  136 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 virtproxy.h |   34 +++++++++++++++
 2 files changed, 170 insertions(+), 0 deletions(-)
 create mode 100644 virtproxy.c
 create mode 100644 virtproxy.h

diff --git a/virtproxy.c b/virtproxy.c
new file mode 100644
index 0000000..8f18d83
--- /dev/null
+++ b/virtproxy.c
@@ -0,0 +1,136 @@
+/*
+ * virt-proxy - host/guest communication layer
+ *
+ * Copyright IBM Corp. 2010
+ *
+ * Authors:
+ *  Michael Roth      <mdroth@linux.vnet.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#include "virtproxy.h"
+
+#define VP_SERVICE_ID_LEN 32    /* max length of service id string */
+#define VP_PKT_DATA_LEN 1024    /* max proxied bytes per VPPacket */
+#define VP_CONN_DATA_LEN 1024   /* max bytes conns can send at a time */
+#define VP_MAGIC 0x1F374059
+
+/* listening fd, one for each service we're forwarding to remote end */
+typedef struct VPOForward {
+    VPDriver *drv;
+    int listen_fd;
+    char service_id[VP_SERVICE_ID_LEN];
+    QLIST_ENTRY(VPOForward) next;
+} VPOForward;
+
+/* service_id->path/port mapping of each service forwarded from remote end */
+typedef struct VPIForward {
+    VPDriver *drv;
+    char service_id[VP_SERVICE_ID_LEN];
+    QemuOpts *socket_opts;
+    QLIST_ENTRY(VPIForward) next;
+} VPIForward;
+
+/* proxied client/server connected states */
+typedef struct VPConn {
+    VPDriver *drv;
+    int client_fd;
+    int server_fd;
+    enum {
+        VP_CONN_CLIENT = 1,
+        VP_CONN_SERVER,
+    } type;
+    enum {
+        VP_STATE_NEW = 1,   /* accept()'d and registered fd */
+        VP_STATE_INIT,      /* sent init pkt to remote end, waiting for ack */
+        VP_STATE_CONNECTED, /* client and server connected */
+    } state;
+    QLIST_ENTRY(VPConn) next;
+} VPConn;
+
+typedef struct VPControlMsg {
+    enum {
+        VP_CONTROL_CONNECT_INIT = 1,
+        VP_CONTROL_CONNECT_ACK,
+        VP_CONTROL_CLOSE,
+    } type;
+    union {
+        /* tell remote end connect to server and map client_fd to it */
+        struct {
+            int client_fd;
+            char service_id[VP_SERVICE_ID_LEN];
+        } connect_init;
+        /* tell remote end we've created the connection to the server,
+         * and give them the corresponding fd to use so we don't have
+         * to do a reverse lookup everytime
+         */
+        struct {
+            int client_fd;
+            int server_fd;
+        } connect_ack;
+        /* tell remote end to close fd in question, presumably because
+         * connection was closed on our end
+         */
+        struct {
+            int client_fd;
+            int server_fd;
+        } close;
+    } args;
+} VPControlMsg;
+
+typedef struct VPPacket {
+    enum {
+        VP_PKT_CONTROL = 1,
+        VP_PKT_CLIENT,
+        VP_PKT_SERVER,
+    } type;
+    union {
+        VPControlMsg msg;
+        struct {
+            int client_fd;
+            int server_fd;
+            int bytes;
+            char data[VP_PKT_DATA_LEN];
+        } proxied;
+    } payload;
+    int magic;
+} __attribute__((__packed__)) VPPacket;
+
+struct VPDriver {
+    enum vp_context ctx;
+    int channel_fd;
+    int listen_fd;
+    CharDriverState *chr;
+    char buf[sizeof(VPPacket)];
+    int buflen;
+    QLIST_HEAD(, VPOForward) oforwards;
+    QLIST_HEAD(, VPIForward) iforwards;
+    QLIST_HEAD(, VPConn) conns;
+};
+
+static QemuOptsList vp_socket_opts = {
+    .name = "vp_socket_opts",
+    .head = QTAILQ_HEAD_INITIALIZER(vp_socket_opts.head),
+    .desc = {
+        {
+            .name = "path",
+            .type = QEMU_OPT_STRING,
+        },{
+            .name = "host",
+            .type = QEMU_OPT_STRING,
+        },{
+            .name = "port",
+            .type = QEMU_OPT_STRING,
+        },{
+            .name = "ipv4",
+            .type = QEMU_OPT_BOOL,
+        },{
+            .name = "ipv6",
+            .type = QEMU_OPT_BOOL,
+        },
+        { /* end if list */ }
+    },
+};
diff --git a/virtproxy.h b/virtproxy.h
new file mode 100644
index 0000000..0203421
--- /dev/null
+++ b/virtproxy.h
@@ -0,0 +1,34 @@
+/*
+ * virt-proxy - host/guest communication layer
+ *
+ * Copyright IBM Corp. 2010
+ *
+ * Authors:
+ *  Michael Roth      <mdroth@linux.vnet.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#ifndef VIRTPROXY_H
+#define VIRTPROXY_H
+
+#include "qemu-common.h"
+#include "qemu-queue.h"
+
+typedef struct VPDriver VPDriver;
+
+/* wrappers for s/vp/qemu/ functions we need */
+int vp_send_all(int fd, const void *buf, int len1);
+int vp_set_fd_handler2(int fd,
+                         IOCanReadHandler *fd_read_poll,
+                         IOHandler *fd_read,
+                         IOHandler *fd_write,
+                         void *opaque);
+int vp_set_fd_handler(int fd,
+                        IOHandler *fd_read,
+                        IOHandler *fd_write,
+                        void *opaque);
+
+#endif /* VIRTPROXY_H */
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [Qemu-devel] [RFC][PATCH v2 02/19] virtproxy: qemu-vp, standalone daemon skeleton
  2010-11-10 22:27 [Qemu-devel] [RFC][PATCH v2 00/19] virtproxy: host/guest communication layer Michael Roth
  2010-11-10 22:27 ` [Qemu-devel] [RFC][PATCH v2 01/19] virtproxy: base data structures and constants Michael Roth
@ 2010-11-10 22:27 ` Michael Roth
  2010-11-10 22:27 ` [Qemu-devel] [RFC][PATCH v2 03/19] virtproxy: add debug functions for virtproxy core Michael Roth
                   ` (17 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Michael Roth @ 2010-11-10 22:27 UTC (permalink / raw)
  To: qemu-devel; +Cc: agl, abeekhof, mdroth, aliguori, ryanh, amit.shah

Daemon to be run in guest, or on host in standalone mode.
(re-)implements some qemu utility functions used by core virtproxy.c
code via wrapper functions. For built-in virtproxy code we will define
these wrapper functions in terms of qemu's built-in implementations.

Main logic will come in a later patch.

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 qemu-vp.c |  151 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 151 insertions(+), 0 deletions(-)
 create mode 100644 qemu-vp.c

diff --git a/qemu-vp.c b/qemu-vp.c
new file mode 100644
index 0000000..5075cdc
--- /dev/null
+++ b/qemu-vp.c
@@ -0,0 +1,151 @@
+/*
+ * virt-proxy - host/guest communication daemon
+ *
+ * Copyright IBM Corp. 2010
+ *
+ * Authors:
+ *  Michael Roth      <mdroth@linux.vnet.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#include "virtproxy.h"
+
+/* mirror qemu I/O-related code for standalone daemon */
+typedef struct IOHandlerRecord {
+    int fd;
+    IOCanReadHandler *fd_read_poll;
+    IOHandler *fd_read;
+    IOHandler *fd_write;
+    int deleted;
+    void *opaque;
+    /* temporary data */
+    struct pollfd *ufd;
+    QLIST_ENTRY(IOHandlerRecord) next;
+} IOHandlerRecord;
+
+static QLIST_HEAD(, IOHandlerRecord) io_handlers =
+    QLIST_HEAD_INITIALIZER(io_handlers);
+
+int vp_set_fd_handler2(int fd,
+                         IOCanReadHandler *fd_read_poll,
+                         IOHandler *fd_read,
+                         IOHandler *fd_write,
+                         void *opaque)
+{
+    IOHandlerRecord *ioh;
+
+    if (!fd_read && !fd_write) {
+        QLIST_FOREACH(ioh, &io_handlers, next) {
+            if (ioh->fd == fd) {
+                ioh->deleted = 1;
+                break;
+            }
+        }
+    } else {
+        QLIST_FOREACH(ioh, &io_handlers, next) {
+            if (ioh->fd == fd)
+                goto found;
+        }
+        ioh = qemu_mallocz(sizeof(IOHandlerRecord));
+        QLIST_INSERT_HEAD(&io_handlers, ioh, next);
+    found:
+        ioh->fd = fd;
+        ioh->fd_read_poll = fd_read_poll;
+        ioh->fd_read = fd_read;
+        ioh->fd_write = fd_write;
+        ioh->opaque = opaque;
+        ioh->deleted = 0;
+    }
+    return 0;
+}
+
+int vp_set_fd_handler(int fd,
+                        IOHandler *fd_read,
+                        IOHandler *fd_write,
+                        void *opaque)
+{
+    return vp_set_fd_handler2(fd, NULL, fd_read, fd_write, opaque);
+}
+
+int vp_send_all(int fd, const void *buf, int len1)
+{
+    int ret, len;
+
+    len = len1;
+    while (len > 0) {
+        ret = write(fd, buf, len);
+        if (ret < 0) {
+            if (errno != EINTR && errno != EAGAIN) {
+                warn("write() failed");
+                return -1;
+            }
+        } else if (ret == 0) {
+            break;
+        } else {
+            buf += ret;
+            len -= ret;
+        }
+    }
+    return len1 - len;
+}
+
+static void main_loop_wait(int nonblocking)
+{
+    IOHandlerRecord *ioh;
+    fd_set rfds, wfds, xfds;
+    int ret, nfds;
+    struct timeval tv;
+    int timeout = 1000;
+
+    if (nonblocking) {
+        timeout = 0;
+    }
+
+    /* poll any events */
+    nfds = -1;
+    FD_ZERO(&rfds);
+    FD_ZERO(&wfds);
+    FD_ZERO(&xfds);
+    QLIST_FOREACH(ioh, &io_handlers, next) {
+        if (ioh->deleted)
+            continue;
+        if (ioh->fd_read &&
+            (!ioh->fd_read_poll ||
+             ioh->fd_read_poll(ioh->opaque) != 0)) {
+            FD_SET(ioh->fd, &rfds);
+            if (ioh->fd > nfds)
+                nfds = ioh->fd;
+        }
+        if (ioh->fd_write) {
+            FD_SET(ioh->fd, &wfds);
+            if (ioh->fd > nfds)
+                nfds = ioh->fd;
+        }
+    }
+
+    tv.tv_sec = timeout / 1000;
+    tv.tv_usec = (timeout % 1000) * 1000;
+
+    ret = select(nfds + 1, &rfds, &wfds, &xfds, &tv);
+
+    if (ret > 0) {
+        IOHandlerRecord *pioh;
+
+        QLIST_FOREACH_SAFE(ioh, &io_handlers, next, pioh) {
+            if (ioh->deleted) {
+                QLIST_REMOVE(ioh, next);
+                qemu_free(ioh);
+                continue;
+            }
+            if (ioh->fd_read && FD_ISSET(ioh->fd, &rfds)) {
+                ioh->fd_read(ioh->opaque);
+            }
+            if (ioh->fd_write && FD_ISSET(ioh->fd, &wfds)) {
+                ioh->fd_write(ioh->opaque);
+            }
+        }
+    }
+}
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [Qemu-devel] [RFC][PATCH v2 03/19] virtproxy: add debug functions for virtproxy core
  2010-11-10 22:27 [Qemu-devel] [RFC][PATCH v2 00/19] virtproxy: host/guest communication layer Michael Roth
  2010-11-10 22:27 ` [Qemu-devel] [RFC][PATCH v2 01/19] virtproxy: base data structures and constants Michael Roth
  2010-11-10 22:27 ` [Qemu-devel] [RFC][PATCH v2 02/19] virtproxy: qemu-vp, standalone daemon skeleton Michael Roth
@ 2010-11-10 22:27 ` Michael Roth
  2010-11-10 22:28 ` [Qemu-devel] [RFC][PATCH v2 04/19] virtproxy: list look-up functions conns/oforwards/iforwards Michael Roth
                   ` (16 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Michael Roth @ 2010-11-10 22:27 UTC (permalink / raw)
  To: qemu-devel; +Cc: agl, abeekhof, mdroth, aliguori, ryanh, amit.shah


Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 virtproxy.c |   17 +++++++++++++++++
 1 files changed, 17 insertions(+), 0 deletions(-)

diff --git a/virtproxy.c b/virtproxy.c
index 8f18d83..3686c77 100644
--- a/virtproxy.c
+++ b/virtproxy.c
@@ -13,6 +13,23 @@
 
 #include "virtproxy.h"
 
+#define DEBUG_VP
+
+#ifdef DEBUG_VP
+#define TRACE(msg, ...) do { \
+    fprintf(stderr, "%s:%s():L%d: " msg "\n", \
+            __FILE__, __FUNCTION__, __LINE__, ## __VA_ARGS__); \
+} while(0)
+#else
+#define TRACE(msg, ...) \
+    do { } while (0)
+#endif
+
+#define LOG(msg, ...) do { \
+    fprintf(stderr, "%s:%s(): " msg "\n", \
+            __FILE__, __FUNCTION__, ## __VA_ARGS__); \
+} while(0)
+
 #define VP_SERVICE_ID_LEN 32    /* max length of service id string */
 #define VP_PKT_DATA_LEN 1024    /* max proxied bytes per VPPacket */
 #define VP_CONN_DATA_LEN 1024   /* max bytes conns can send at a time */
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [Qemu-devel] [RFC][PATCH v2 04/19] virtproxy: list look-up functions conns/oforwards/iforwards
  2010-11-10 22:27 [Qemu-devel] [RFC][PATCH v2 00/19] virtproxy: host/guest communication layer Michael Roth
                   ` (2 preceding siblings ...)
  2010-11-10 22:27 ` [Qemu-devel] [RFC][PATCH v2 03/19] virtproxy: add debug functions for virtproxy core Michael Roth
@ 2010-11-10 22:28 ` Michael Roth
  2010-11-10 22:28 ` [Qemu-devel] [RFC][PATCH v2 05/19] virtproxy, add vp_channel_send_all Michael Roth
                   ` (15 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Michael Roth @ 2010-11-10 22:28 UTC (permalink / raw)
  To: qemu-devel; +Cc: agl, abeekhof, mdroth, aliguori, ryanh, amit.shah


Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 virtproxy.c |   44 ++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 44 insertions(+), 0 deletions(-)

diff --git a/virtproxy.c b/virtproxy.c
index 3686c77..2cfd905 100644
--- a/virtproxy.c
+++ b/virtproxy.c
@@ -151,3 +151,47 @@ static QemuOptsList vp_socket_opts = {
         { /* end if list */ }
     },
 };
+
+/* get VPConn by fd, "client" denotes whether to look for client or server */
+static VPConn *get_conn(const VPDriver *drv, int fd, bool client)
+{
+    VPConn *c = NULL;
+    int cur_fd;
+
+    QLIST_FOREACH(c, &drv->conns, next) {
+        cur_fd = client ? c->client_fd : c->server_fd;
+        if (cur_fd == fd) {
+            return c;
+        }
+    }
+
+    return NULL;
+}
+
+/* get VPOForward by service_id */
+static VPOForward *get_oforward(const VPDriver *drv, const char *service_id)
+{
+    VPOForward *f = NULL;
+
+    QLIST_FOREACH(f, &drv->oforwards, next) {
+        if (strncmp(f->service_id, service_id, VP_SERVICE_ID_LEN) == 0) {
+            return f;
+        }
+    }
+
+    return NULL;
+}
+
+/* get VPIForward by service_id */
+static VPIForward *get_iforward(const VPDriver *drv, const char *service_id)
+{
+    VPIForward *f = NULL;
+
+    QLIST_FOREACH(f, &drv->iforwards, next) {
+        if (strncmp(f->service_id, service_id, VP_SERVICE_ID_LEN) == 0) {
+            return f;
+        }
+    }
+
+    return NULL;
+}
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [Qemu-devel] [RFC][PATCH v2 05/19] virtproxy, add vp_channel_send_all
  2010-11-10 22:27 [Qemu-devel] [RFC][PATCH v2 00/19] virtproxy: host/guest communication layer Michael Roth
                   ` (3 preceding siblings ...)
  2010-11-10 22:28 ` [Qemu-devel] [RFC][PATCH v2 04/19] virtproxy: list look-up functions conns/oforwards/iforwards Michael Roth
@ 2010-11-10 22:28 ` Michael Roth
  2010-11-10 22:28 ` [Qemu-devel] [RFC][PATCH v2 06/19] virtproxy: add accept handler for communication channel Michael Roth
                   ` (14 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Michael Roth @ 2010-11-10 22:28 UTC (permalink / raw)
  To: qemu-devel; +Cc: agl, abeekhof, mdroth, aliguori, ryanh, amit.shah

This handles sending of data to channel fd (qemu-vp in guest) or the
device associated with the virtproxy chardev for the host depending on
the context. vp_chr_read() wraps qemu_chr_read(), it'll be defined later
in virtproxy-builtin.c, and noop'd in the guest agent via qemu-vp.c.

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 virtproxy.c |   31 +++++++++++++++++++++++++++++++
 virtproxy.h |    1 +
 2 files changed, 32 insertions(+), 0 deletions(-)

diff --git a/virtproxy.c b/virtproxy.c
index 2cfd905..edca62e 100644
--- a/virtproxy.c
+++ b/virtproxy.c
@@ -152,6 +152,37 @@ static QemuOptsList vp_socket_opts = {
     },
 };
 
+static int vp_channel_send_all(VPDriver *drv, uint8_t *buf, int count)
+{
+    int ret;
+    CharDriverState *chr = drv->chr;
+
+    if (drv->chr != NULL) {
+        /* send data to guest via channel device's read handler */
+        vp_chr_read(chr, buf, count);
+        /* TODO: we assume here the full buffer was written to device
+         * due to the dev write handler being a void function.
+         * can we confirm? Do we need to?
+         */
+        ret = count;
+    } else if (drv->channel_fd != -1) {
+        /* send data to host via channel fd */
+        ret = vp_send_all(drv->channel_fd, buf, count);
+        if (ret == -1) {
+            LOG("error sending data");
+            goto out_bad;
+        }
+    } else {
+        LOG("driver in unknown state");
+        goto out_bad;
+    }
+
+    return ret;
+out_bad:
+    LOG("unable to send to channel");
+    return -1;
+}
+
 /* get VPConn by fd, "client" denotes whether to look for client or server */
 static VPConn *get_conn(const VPDriver *drv, int fd, bool client)
 {
diff --git a/virtproxy.h b/virtproxy.h
index 0203421..1a5e56a 100644
--- a/virtproxy.h
+++ b/virtproxy.h
@@ -30,5 +30,6 @@ int vp_set_fd_handler(int fd,
                         IOHandler *fd_read,
                         IOHandler *fd_write,
                         void *opaque);
+void vp_chr_read(CharDriverState *s, uint8_t *buf, int len);
 
 #endif /* VIRTPROXY_H */
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [Qemu-devel] [RFC][PATCH v2 06/19] virtproxy: add accept handler for communication channel
  2010-11-10 22:27 [Qemu-devel] [RFC][PATCH v2 00/19] virtproxy: host/guest communication layer Michael Roth
                   ` (4 preceding siblings ...)
  2010-11-10 22:28 ` [Qemu-devel] [RFC][PATCH v2 05/19] virtproxy, add vp_channel_send_all Michael Roth
@ 2010-11-10 22:28 ` Michael Roth
  2010-11-10 22:28 ` [Qemu-devel] [RFC][PATCH v2 07/19] virtproxy: add read " Michael Roth
                   ` (13 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Michael Roth @ 2010-11-10 22:28 UTC (permalink / raw)
  To: qemu-devel; +Cc: agl, abeekhof, mdroth, aliguori, ryanh, amit.shah

This accept()'s connections to the socket we told virt-proxy to listen
for the channel connection on and sets the appropriate read handler for
the resulting FD.

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 virtproxy.c |   37 +++++++++++++++++++++++++++++++++++++
 1 files changed, 37 insertions(+), 0 deletions(-)

diff --git a/virtproxy.c b/virtproxy.c
index edca62e..770b57b 100644
--- a/virtproxy.c
+++ b/virtproxy.c
@@ -199,6 +199,8 @@ static VPConn *get_conn(const VPDriver *drv, int fd, bool client)
     return NULL;
 }
 
+static void vp_channel_accept(void *opaque);
+
 /* get VPOForward by service_id */
 static VPOForward *get_oforward(const VPDriver *drv, const char *service_id)
 {
@@ -226,3 +228,38 @@ static VPIForward *get_iforward(const VPDriver *drv, const char *service_id)
 
     return NULL;
 }
+
+/* accept handler for communication channel
+ *
+ * accept()s connection to communication channel (for sockets), and sets
+ * up the read handler for resulting FD.
+ */
+static void vp_channel_accept(void *opaque)
+{
+    VPDriver *drv = opaque;
+    struct sockaddr_in saddr;
+    struct sockaddr *addr;
+    socklen_t len;
+    int fd;
+
+    TRACE("called with opaque: %p", drv);
+
+    for(;;) {
+        len = sizeof(saddr);
+        addr = (struct sockaddr *)&saddr;
+        fd = qemu_accept(drv->listen_fd, addr, &len);
+
+        if (fd < 0 && errno != EINTR) {
+            TRACE("accept() failed");
+            return;
+        } else if (fd >= 0) {
+            TRACE("accepted connection");
+            break;
+        }
+    }
+
+    drv->channel_fd = fd;
+    vp_set_fd_handler(drv->channel_fd, vp_channel_read, NULL, drv);
+    /* dont accept anymore connections until channel_fd is closed */
+    vp_set_fd_handler(drv->listen_fd, NULL, NULL, NULL);
+}
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [Qemu-devel] [RFC][PATCH v2 07/19] virtproxy: add read handler for communication channel
  2010-11-10 22:27 [Qemu-devel] [RFC][PATCH v2 00/19] virtproxy: host/guest communication layer Michael Roth
                   ` (5 preceding siblings ...)
  2010-11-10 22:28 ` [Qemu-devel] [RFC][PATCH v2 06/19] virtproxy: add accept handler for communication channel Michael Roth
@ 2010-11-10 22:28 ` Michael Roth
  2010-11-10 22:28 ` [Qemu-devel] [RFC][PATCH v2 08/19] virtproxy: add vp_new() VPDriver constructor Michael Roth
                   ` (12 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Michael Roth @ 2010-11-10 22:28 UTC (permalink / raw)
  To: qemu-devel; +Cc: agl, abeekhof, mdroth, aliguori, ryanh, amit.shah

Handle data coming in over the channel as VPPackets: Process control
messages and forward data from remote client/server connections to the
appropriate server/client FD on our end. We also provide here a helper
function to process a stream of packets from the channel.

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 virtproxy.c |   96 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 virtproxy.h |    3 ++
 2 files changed, 99 insertions(+), 0 deletions(-)

diff --git a/virtproxy.c b/virtproxy.c
index 770b57b..091a223 100644
--- a/virtproxy.c
+++ b/virtproxy.c
@@ -33,6 +33,7 @@
 #define VP_SERVICE_ID_LEN 32    /* max length of service id string */
 #define VP_PKT_DATA_LEN 1024    /* max proxied bytes per VPPacket */
 #define VP_CONN_DATA_LEN 1024   /* max bytes conns can send at a time */
+#define VP_CHAN_DATA_LEN 4096   /* max bytes channel can send at a time */
 #define VP_MAGIC 0x1F374059
 
 /* listening fd, one for each service we're forwarding to remote end */
@@ -152,6 +153,8 @@ static QemuOptsList vp_socket_opts = {
     },
 };
 
+static void vp_channel_read(void *opaque);
+
 static int vp_channel_send_all(VPDriver *drv, uint8_t *buf, int count)
 {
     int ret;
@@ -263,3 +266,96 @@ static void vp_channel_accept(void *opaque)
     /* dont accept anymore connections until channel_fd is closed */
     vp_set_fd_handler(drv->listen_fd, NULL, NULL, NULL);
 }
+
+/* process a stream of packets coming in from the channel */
+int vp_handle_packet_buf(VPDriver *drv, const void *buf, int count)
+{
+    VPPacket pkt;
+    int ret, buf_offset;
+    char *pkt_ptr;
+    const char *buf_ptr;
+
+    if (drv->buflen + count >= sizeof(VPPacket)) {
+        TRACE("initial packet, drv->buflen: %d", drv->buflen);
+        pkt_ptr = (char *)&pkt;
+        memcpy(pkt_ptr, drv->buf, drv->buflen);
+        pkt_ptr += drv->buflen;
+        memcpy(pkt_ptr, buf, sizeof(VPPacket) - drv->buflen);
+        /* handle first packet */
+        ret = vp_handle_packet(drv, &pkt);
+        if (ret != 0) {
+            LOG("error handling packet");
+        }
+        /* handle the rest of the buffer */
+        buf_offset = sizeof(VPPacket) - drv->buflen;
+        drv->buflen = 0;
+        buf_ptr = buf + buf_offset;
+        count -= buf_offset;
+        while (count > 0) {
+            if (count >= sizeof(VPPacket)) {
+                /* handle full packet */
+                TRACE("additional packet, drv->buflen: %d", drv->buflen);
+                memcpy((void *)&pkt, buf_ptr, sizeof(VPPacket));
+                ret = vp_handle_packet(drv, &pkt);
+                if (ret != 0) {
+                    LOG("error handling packet");
+                }
+                count -= sizeof(VPPacket);
+                buf_ptr += sizeof(VPPacket);
+            } else {
+                /* buffer the remainder */
+                TRACE("buffering packet, drv->buflen: %d", drv->buflen);
+                memcpy(drv->buf, buf_ptr, count);
+                drv->buflen = count;
+                break;
+            }
+        }
+    } else {
+        /* haven't got a full VPPacket yet, buffer for later */
+        TRACE("buffering packet, drv->buflen: %d", drv->buflen);
+        memcpy(drv->buf + drv->buflen, buf, count);
+        drv->buflen += count;
+    }
+    return 0;
+}
+
+/* read handler for communication channel
+ *
+ * de-multiplexes data coming in over the channel. for control messages
+ * we process them here, for data destined for a service or client we
+ * send it to the appropriate FD.
+ */
+static void vp_channel_read(void *opaque)
+{
+    VPDriver *drv = opaque;
+    int count, ret;
+    char buf[VP_CHAN_DATA_LEN];
+
+    TRACE("called with opaque: %p", drv);
+
+    count = read(drv->channel_fd, buf, sizeof(buf));
+
+    if (count == -1) {
+        LOG("read() failed: %s", strerror(errno));
+        return;
+    } else if (count == 0) {
+        /* TODO: channel closed, this probably shouldn't happen for guest-side
+         * serial/virtio-serial connections, but need to confirm and consider
+         * what should happen in this case. as it stands this virtproxy instance
+         * is basically defunct at this point, same goes for "client" instances
+         * of virtproxy where the remote end has hung-up.
+         */
+        LOG("channel connection closed");
+        vp_set_fd_handler(drv->channel_fd, NULL, NULL, drv);
+        drv->channel_fd = -1;
+        if (drv->listen_fd) {
+            vp_set_fd_handler(drv->listen_fd, vp_channel_accept, NULL, drv);
+        }
+        /* TODO: should close/remove/delete all existing VPConns here */
+    }
+
+    ret = vp_handle_packet_buf(drv, buf, count);
+    if (ret != 0) {
+        LOG("error handling packet stream");
+    }
+}
diff --git a/virtproxy.h b/virtproxy.h
index 1a5e56a..8fa0142 100644
--- a/virtproxy.h
+++ b/virtproxy.h
@@ -32,4 +32,7 @@ int vp_set_fd_handler(int fd,
                         void *opaque);
 void vp_chr_read(CharDriverState *s, uint8_t *buf, int len);
 
+/* virtproxy interface */
+int vp_handle_packet_buf(VPDriver *drv, const void *buf, int count);
+
 #endif /* VIRTPROXY_H */
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [Qemu-devel] [RFC][PATCH v2 08/19] virtproxy: add vp_new() VPDriver constructor
  2010-11-10 22:27 [Qemu-devel] [RFC][PATCH v2 00/19] virtproxy: host/guest communication layer Michael Roth
                   ` (6 preceding siblings ...)
  2010-11-10 22:28 ` [Qemu-devel] [RFC][PATCH v2 07/19] virtproxy: add read " Michael Roth
@ 2010-11-10 22:28 ` Michael Roth
  2010-11-10 22:28 ` [Qemu-devel] [RFC][PATCH v2 09/19] virtproxy: interfaces to set/remove/handle VPOForwards Michael Roth
                   ` (11 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Michael Roth @ 2010-11-10 22:28 UTC (permalink / raw)
  To: qemu-devel; +Cc: agl, abeekhof, mdroth, aliguori, ryanh, amit.shah


Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 virtproxy.c |   40 ++++++++++++++++++++++++++++++++++++++++
 virtproxy.h |    6 ++++++
 2 files changed, 46 insertions(+), 0 deletions(-)

diff --git a/virtproxy.c b/virtproxy.c
index 091a223..401d51c 100644
--- a/virtproxy.c
+++ b/virtproxy.c
@@ -359,3 +359,43 @@ static void vp_channel_read(void *opaque)
         LOG("error handling packet stream");
     }
 }
+
+VPDriver *vp_new(enum vp_context ctx, CharDriverState *s, int fd, bool listen)
+{
+    VPDriver *drv = NULL;
+
+    drv = qemu_mallocz(sizeof(VPDriver));
+    drv->listen_fd = -1;
+    drv->channel_fd = -1;
+    drv->chr = s;
+    drv->ctx = ctx;
+    QLIST_INIT(&drv->oforwards);
+    QLIST_INIT(&drv->conns);
+
+    if (ctx == VP_CTX_CHARDEV) {
+        if (drv->chr == NULL) {
+            LOG("invalid virtproxy chardev");
+            goto out_bad;
+        }
+    } else if (ctx == VP_CTX_FD) {
+        if (fd <= 0) {
+            LOG("invalid FD");
+            goto out_bad;
+        } else if (listen) {
+            /* provided FD is to be listened on for channel connection */
+            drv->listen_fd = fd;
+            vp_set_fd_handler(drv->listen_fd, vp_channel_accept, NULL, drv);
+        } else {
+            drv->channel_fd = fd;
+            vp_set_fd_handler(drv->channel_fd, vp_channel_read, NULL, drv);
+        }
+    } else {
+        LOG("invalid context");
+        goto out_bad;
+    }
+
+    return drv;
+out_bad:
+    qemu_free(drv);
+    return NULL;
+}
diff --git a/virtproxy.h b/virtproxy.h
index 8fa0142..7cd2f76 100644
--- a/virtproxy.h
+++ b/virtproxy.h
@@ -16,8 +16,13 @@
 
 #include "qemu-common.h"
 #include "qemu-queue.h"
+#include "qemu-char.h"
 
 typedef struct VPDriver VPDriver;
+enum vp_context {
+    VP_CTX_CHARDEV, /* in qemu/host, channel is a virtproxy chardev */
+    VP_CTX_FD,      /* in guest, channel is an FD */
+};
 
 /* wrappers for s/vp/qemu/ functions we need */
 int vp_send_all(int fd, const void *buf, int len1);
@@ -33,6 +38,7 @@ int vp_set_fd_handler(int fd,
 void vp_chr_read(CharDriverState *s, uint8_t *buf, int len);
 
 /* virtproxy interface */
+VPDriver *vp_new(enum vp_context ctx, CharDriverState *s, int fd, bool listen);
 int vp_handle_packet_buf(VPDriver *drv, const void *buf, int count);
 
 #endif /* VIRTPROXY_H */
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [Qemu-devel] [RFC][PATCH v2 09/19] virtproxy: interfaces to set/remove/handle VPOForwards
  2010-11-10 22:27 [Qemu-devel] [RFC][PATCH v2 00/19] virtproxy: host/guest communication layer Michael Roth
                   ` (7 preceding siblings ...)
  2010-11-10 22:28 ` [Qemu-devel] [RFC][PATCH v2 08/19] virtproxy: add vp_new() VPDriver constructor Michael Roth
@ 2010-11-10 22:28 ` Michael Roth
  2010-11-10 22:28 ` [Qemu-devel] [RFC][PATCH v2 10/19] virtproxy: add handler for data packets Michael Roth
                   ` (10 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Michael Roth @ 2010-11-10 22:28 UTC (permalink / raw)
  To: qemu-devel; +Cc: agl, abeekhof, mdroth, aliguori, ryanh, amit.shah

Functions to add listener FDs (oforwards) which set up proxied connections
to associated service, and the corresponding handler function to process
to new connections to said FDs and initialize new client connections to
the associated remote server over the channel

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 virtproxy.c |  104 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 virtproxy.h |    1 +
 2 files changed, 105 insertions(+), 0 deletions(-)

diff --git a/virtproxy.c b/virtproxy.c
index 401d51c..f189e2c 100644
--- a/virtproxy.c
+++ b/virtproxy.c
@@ -12,6 +12,7 @@
  */
 
 #include "virtproxy.h"
+#include "qemu_socket.h"
 
 #define DEBUG_VP
 
@@ -360,6 +361,71 @@ static void vp_channel_read(void *opaque)
     }
 }
 
+/* handler to accept() and init new client connections */
+static void vp_oforward_accept(void *opaque)
+{
+    VPOForward *f = opaque;
+    VPDriver *drv = f->drv;
+
+    struct sockaddr_in saddr;
+    struct sockaddr *addr;
+    socklen_t len;
+    int fd, ret;
+    VPConn *conn = NULL;
+    VPPacket pkt;
+    VPControlMsg msg;
+
+    TRACE("called with opaque: %p, drv: %p", f, drv);
+
+    for(;;) {
+        len = sizeof(saddr);
+        addr = (struct sockaddr *)&saddr;
+        fd = qemu_accept(f->listen_fd, addr, &len);
+
+        if (fd < 0 && errno != EINTR) {
+            TRACE("accept() failed");
+            return;
+        } else if (fd >= 0) {
+            TRACE("accepted connection");
+            break;
+        }
+    }
+
+    if (!drv->chr && drv->channel_fd == -1) {
+        TRACE("communication channel not open, closing connection");
+        closesocket(fd);
+        return;
+    }
+
+    /* send init packet over channel */
+    memset(&msg, 0, sizeof(VPControlMsg));
+    msg.type = VP_CONTROL_CONNECT_INIT;
+    msg.args.connect_init.client_fd = fd;
+    pstrcpy(msg.args.connect_init.service_id, VP_SERVICE_ID_LEN, f->service_id);
+
+    memset(&pkt, 0, sizeof(VPPacket));
+    pkt.type = VP_PKT_CONTROL;
+    pkt.payload.msg = msg;
+    pkt.magic = VP_MAGIC;
+
+    ret = vp_channel_send_all(drv, (uint8_t*)&pkt, sizeof(VPPacket));
+    if (ret == -1) {
+        LOG("error sending to channel");
+        return;
+    }
+
+    /* create new VPConn for client */
+    conn = qemu_mallocz(sizeof(VPConn));
+    conn->drv = drv;
+    conn->client_fd = fd;
+    conn->type = VP_CONN_CLIENT;
+    conn->state = VP_STATE_NEW;
+    QLIST_INSERT_HEAD(&drv->conns, conn, next);
+
+    socket_set_nonblock(fd);
+}
+
+/* create/init VPDriver object */
 VPDriver *vp_new(enum vp_context ctx, CharDriverState *s, int fd, bool listen)
 {
     VPDriver *drv = NULL;
@@ -399,3 +465,41 @@ out_bad:
     qemu_free(drv);
     return NULL;
 }
+
+/* set/modify/remove a service_id -> net/unix listening socket mapping
+ *
+ * "service_id" is a user-defined id for the service. this is what the
+ * client end will tag it's connections with so that the remote end can
+ * route it to the proper socket on the remote end.
+ *
+ * "fd" is a listen()'ing socket we want virtproxy to listen for new
+ * connections of this service type on. set "fd" to -1 to remove the 
+ * existing listening socket for this "service_id"
+ */
+int vp_set_oforward(VPDriver *drv, int fd, const char *service_id)
+{
+    VPOForward *f = get_oforward(drv, service_id);
+
+    if (fd == -1) {
+        if (f != NULL) {
+            vp_set_fd_handler(f->listen_fd, NULL, NULL, NULL);
+            QLIST_REMOVE(f, next);
+            qemu_free(f);
+        }
+        return 0;
+    }
+
+    if (f == NULL) {
+        f = qemu_mallocz(sizeof(VPOForward));
+        f->drv = drv;
+        strncpy(f->service_id, service_id, VP_SERVICE_ID_LEN);
+        QLIST_INSERT_HEAD(&drv->oforwards, f, next);
+    } else {
+        closesocket(f->listen_fd);
+    }
+
+    f->listen_fd = fd;
+    vp_set_fd_handler(f->listen_fd, vp_oforward_accept, NULL, f);
+
+    return 0;
+}
diff --git a/virtproxy.h b/virtproxy.h
index 7cd2f76..e901600 100644
--- a/virtproxy.h
+++ b/virtproxy.h
@@ -40,5 +40,6 @@ void vp_chr_read(CharDriverState *s, uint8_t *buf, int len);
 /* virtproxy interface */
 VPDriver *vp_new(enum vp_context ctx, CharDriverState *s, int fd, bool listen);
 int vp_handle_packet_buf(VPDriver *drv, const void *buf, int count);
+int vp_set_oforward(VPDriver *drv, int fd, const char *service_id);
 
 #endif /* VIRTPROXY_H */
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [Qemu-devel] [RFC][PATCH v2 10/19] virtproxy: add handler for data packets
  2010-11-10 22:27 [Qemu-devel] [RFC][PATCH v2 00/19] virtproxy: host/guest communication layer Michael Roth
                   ` (8 preceding siblings ...)
  2010-11-10 22:28 ` [Qemu-devel] [RFC][PATCH v2 09/19] virtproxy: interfaces to set/remove/handle VPOForwards Michael Roth
@ 2010-11-10 22:28 ` Michael Roth
  2010-11-10 22:28 ` [Qemu-devel] [RFC][PATCH v2 11/19] virtproxy: add handler for control packet Michael Roth
                   ` (9 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Michael Roth @ 2010-11-10 22:28 UTC (permalink / raw)
  To: qemu-devel; +Cc: agl, abeekhof, mdroth, aliguori, ryanh, amit.shah

Process VPPackets coming in from channel and send them to the
appropriate server/client connections.

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 virtproxy.c |   42 ++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 42 insertions(+), 0 deletions(-)

diff --git a/virtproxy.c b/virtproxy.c
index f189e2c..a0bbe7f 100644
--- a/virtproxy.c
+++ b/virtproxy.c
@@ -268,6 +268,48 @@ static void vp_channel_accept(void *opaque)
     vp_set_fd_handler(drv->listen_fd, NULL, NULL, NULL);
 }
 
+/* handle data packets
+ *
+ * process VPPackets containing data and send them to the corresponding
+ * FDs
+ */
+static int vp_handle_data_packet(void *drv, const VPPacket *pkt)
+{
+    int fd, ret;
+
+    TRACE("called with drv: %p", drv);
+
+    if (pkt->type == VP_PKT_CLIENT) {
+        TRACE("recieved client packet, client fd: %d, server fd: %d",
+              pkt->payload.proxied.client_fd, pkt->payload.proxied.server_fd);
+        fd = pkt->payload.proxied.server_fd;
+    } else if (pkt->type == VP_PKT_SERVER) {
+        TRACE("recieved server packet, client fd: %d, server fd: %d",
+              pkt->payload.proxied.client_fd, pkt->payload.proxied.server_fd);
+        fd = pkt->payload.proxied.client_fd;
+    } else {
+        TRACE("unknown packet type");
+        return -1;
+    }
+
+    /* TODO: proxied in non-blocking mode can causes us to spin here
+     * for slow servers/clients. need to use write()'s and maintain
+     * a per-conn write queue that we clear out before sending any
+     * more data to the fd
+     */
+    ret = vp_send_all(fd, (void *)pkt->payload.proxied.data,
+            pkt->payload.proxied.bytes);
+    if (ret == -1) {
+        LOG("error sending data over channel");
+        return -1;
+    } else if (ret != pkt->payload.proxied.bytes) {
+        TRACE("buffer full?");
+        return -1;
+    }
+
+    return 0;
+}
+
 /* process a stream of packets coming in from the channel */
 int vp_handle_packet_buf(VPDriver *drv, const void *buf, int count)
 {
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [Qemu-devel] [RFC][PATCH v2 11/19] virtproxy: add handler for control packet
  2010-11-10 22:27 [Qemu-devel] [RFC][PATCH v2 00/19] virtproxy: host/guest communication layer Michael Roth
                   ` (9 preceding siblings ...)
  2010-11-10 22:28 ` [Qemu-devel] [RFC][PATCH v2 10/19] virtproxy: add handler for data packets Michael Roth
@ 2010-11-10 22:28 ` Michael Roth
  2010-11-10 22:28 ` [Qemu-devel] [RFC][PATCH v2 12/19] virtproxy: add vp_handle_packet() Michael Roth
                   ` (8 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Michael Roth @ 2010-11-10 22:28 UTC (permalink / raw)
  To: qemu-devel; +Cc: agl, abeekhof, mdroth, aliguori, ryanh, amit.shah

Process control packets coming in over the channel. This entails setting
up/tearing down connections to local services initiated from the other
end of the channel.

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 virtproxy.c |  154 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 154 insertions(+), 0 deletions(-)

diff --git a/virtproxy.c b/virtproxy.c
index a0bbe7f..0cc8950 100644
--- a/virtproxy.c
+++ b/virtproxy.c
@@ -268,6 +268,160 @@ static void vp_channel_accept(void *opaque)
     vp_set_fd_handler(drv->listen_fd, NULL, NULL, NULL);
 }
 
+/* handle control packets
+ *
+ * process VPPackets containing control messages
+ */
+static int vp_handle_control_packet(VPDriver *drv, const VPPacket *pkt)
+{
+    const VPControlMsg *msg = &pkt->payload.msg;
+    int ret;
+
+    TRACE("called with drv: %p", drv);
+
+    switch (msg->type) {
+    case VP_CONTROL_CONNECT_INIT: {
+        int client_fd = msg->args.connect_init.client_fd;
+        int server_fd;
+        char service_id[VP_SERVICE_ID_LEN];
+        VPPacket resp_pkt;
+        VPConn *new_conn;
+        VPIForward *iforward;
+
+        pstrcpy(service_id, VP_SERVICE_ID_LEN,
+                 msg->args.connect_init.service_id);
+        TRACE("setting up connection for service id %s", service_id);
+
+        /* create server connection on behalf of remote end */
+        iforward = get_iforward(drv, service_id);
+        if (iforward == NULL) {
+            LOG("no forwarder configured for service id");
+            return -1;
+        }
+
+        qemu_opts_print(iforward->socket_opts, NULL);
+        if (qemu_opt_get(iforward->socket_opts, "host") != NULL) {
+            server_fd = inet_connect_opts(iforward->socket_opts);
+        } else if (qemu_opt_get(iforward->socket_opts, "path") != NULL) {
+            server_fd = unix_connect_opts(iforward->socket_opts);
+        } else {
+            LOG("unable to find listening socket host/addr info");
+            return -1;
+        }
+
+        if (server_fd == -1) {
+            LOG("failed to create connection to service with id %s",
+                service_id);
+        }
+        TRACE("server_fd: %d", server_fd);
+
+        new_conn = qemu_mallocz(sizeof(VPConn));
+        if (!new_conn) {
+            LOG("memory allocation failed");
+            return -1;
+        }
+
+        /* send a connect_ack back over the channel */
+        /* TODO: all fields should be explicitly set so we shouldn't
+         * need to memset. this might hurt if we beef up VPPacket size
+         */
+        memset(&resp_pkt, 0, sizeof(resp_pkt));
+        resp_pkt.type = VP_PKT_CONTROL;
+        resp_pkt.payload.msg.type = VP_CONTROL_CONNECT_ACK;
+        resp_pkt.payload.msg.args.connect_ack.server_fd = server_fd;
+        resp_pkt.payload.msg.args.connect_ack.client_fd = client_fd;
+        resp_pkt.magic = VP_MAGIC;
+
+        /* TODO: can this potentially block or cause a deadlock with
+         * the remote end? need to look into potentially buffering these
+         * if it looks like the remote end is waiting for us to read data
+         * off the channel.
+         */
+        if (!drv->chr && drv->channel_fd == -1) {
+            TRACE("channel no longer connected, ignoring packet");
+            return -1;
+        }
+
+        ret = vp_channel_send_all(drv, (void *)&resp_pkt, sizeof(resp_pkt));
+        if (ret == -1) {
+            LOG("error sending data over channel");
+            return -1;
+        }
+        if (ret != sizeof(resp_pkt)) {
+            TRACE("buffer full? %d bytes remaining", ret);
+            return -1;
+        }
+
+        /* add new VPConn to list and set a read handler for it */
+        new_conn->drv = drv;
+        new_conn->client_fd = client_fd;
+        new_conn->server_fd = server_fd;
+        new_conn->type = VP_CONN_SERVER;
+        new_conn->state = VP_STATE_CONNECTED;
+        QLIST_INSERT_HEAD(&drv->conns, new_conn, next);
+        vp_set_fd_handler(server_fd, vp_conn_read, NULL, new_conn);
+
+        break;
+    }
+    case VP_CONTROL_CONNECT_ACK: {
+        int client_fd = msg->args.connect_ack.client_fd;
+        int server_fd = msg->args.connect_ack.server_fd;
+        VPConn *conn;
+
+        TRACE("recieved ack from remote end for client fd %d", client_fd);
+
+        if (server_fd <= 0) {
+            LOG("remote end sent invalid server fd");
+            return -1;
+        }
+
+        conn = get_conn(drv, client_fd, true);
+
+        if (conn == NULL) {
+            LOG("failed to find connection with client_fd %d", client_fd);
+            return -1;
+        }
+
+        conn->server_fd = server_fd;
+        conn->state = VP_STATE_CONNECTED;
+        vp_set_fd_handler(client_fd, vp_conn_read, NULL, conn);
+
+        break;
+    }
+    case VP_CONTROL_CLOSE: {
+        int fd;
+        VPConn *conn;
+
+        TRACE("closing connection on behalf of remote end");
+
+        if (msg->args.close.client_fd >= 0) {
+            fd = msg->args.close.client_fd;
+            TRACE("recieved close msg from remote end for client fd %d", fd);
+            conn = get_conn(drv, fd, true);
+        } else if (msg->args.close.server_fd >= 0) {
+            fd = msg->args.close.server_fd;
+            TRACE("recieved close msg from remote end for server fd %d", fd);
+            conn = get_conn(drv, fd, false);
+        } else {
+            LOG("invalid fd");
+            return -1;
+        }
+
+        if (conn == NULL) {
+            LOG("failed to find conn with specified fd %d", fd);
+            return -1;
+        }
+
+        closesocket(fd);
+        vp_set_fd_handler(fd, NULL, NULL, conn);
+        QLIST_REMOVE(conn, next);
+        qemu_free(conn);
+        break;
+    }
+    }
+    return 0;
+}
+
 /* handle data packets
  *
  * process VPPackets containing data and send them to the corresponding
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [Qemu-devel] [RFC][PATCH v2 12/19] virtproxy: add vp_handle_packet()
  2010-11-10 22:27 [Qemu-devel] [RFC][PATCH v2 00/19] virtproxy: host/guest communication layer Michael Roth
                   ` (10 preceding siblings ...)
  2010-11-10 22:28 ` [Qemu-devel] [RFC][PATCH v2 11/19] virtproxy: add handler for control packet Michael Roth
@ 2010-11-10 22:28 ` Michael Roth
  2010-11-10 22:28 ` [Qemu-devel] [RFC][PATCH v2 13/19] virtproxy: interfaces to set/remove VPIForwards Michael Roth
                   ` (7 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Michael Roth @ 2010-11-10 22:28 UTC (permalink / raw)
  To: qemu-devel; +Cc: agl, abeekhof, mdroth, aliguori, ryanh, amit.shah


Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 virtproxy.c |   23 +++++++++++++++++++++++
 1 files changed, 23 insertions(+), 0 deletions(-)

diff --git a/virtproxy.c b/virtproxy.c
index 0cc8950..01a36c2 100644
--- a/virtproxy.c
+++ b/virtproxy.c
@@ -464,6 +464,29 @@ static int vp_handle_data_packet(void *drv, const VPPacket *pkt)
     return 0;
 }
 
+static inline int vp_handle_packet(VPDriver *drv, const VPPacket *pkt)
+{
+    int ret;
+
+    TRACE("called with drv: %p", drv);
+
+    if (pkt->magic != VP_MAGIC) {
+        LOG("invalid packet magic field");
+        return -1;
+    }
+
+    if (pkt->type == VP_PKT_CONTROL) {
+        ret = vp_handle_control_packet(drv, pkt);
+    } else if (pkt->type == VP_PKT_CLIENT || pkt->type == VP_PKT_SERVER) {
+        ret = vp_handle_data_packet(drv, pkt);
+    } else {
+        LOG("invalid packet type");
+        return -1;
+    }
+
+    return ret;
+}
+
 /* process a stream of packets coming in from the channel */
 int vp_handle_packet_buf(VPDriver *drv, const void *buf, int count)
 {
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [Qemu-devel] [RFC][PATCH v2 13/19] virtproxy: interfaces to set/remove VPIForwards
  2010-11-10 22:27 [Qemu-devel] [RFC][PATCH v2 00/19] virtproxy: host/guest communication layer Michael Roth
                   ` (11 preceding siblings ...)
  2010-11-10 22:28 ` [Qemu-devel] [RFC][PATCH v2 12/19] virtproxy: add vp_handle_packet() Michael Roth
@ 2010-11-10 22:28 ` Michael Roth
  2010-11-10 22:28 ` [Qemu-devel] [RFC][PATCH v2 14/19] virtproxy: add read handler for proxied connections Michael Roth
                   ` (6 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Michael Roth @ 2010-11-10 22:28 UTC (permalink / raw)
  To: qemu-devel; +Cc: agl, abeekhof, mdroth, aliguori, ryanh, amit.shah


Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 virtproxy.c |   59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 virtproxy.h |    2 ++
 2 files changed, 61 insertions(+), 0 deletions(-)

diff --git a/virtproxy.c b/virtproxy.c
index 01a36c2..b683ee6 100644
--- a/virtproxy.c
+++ b/virtproxy.c
@@ -722,3 +722,62 @@ int vp_set_oforward(VPDriver *drv, int fd, const char *service_id)
 
     return 0;
 }
+
+/* add/modify a service_id -> net/unix socket mapping
+ *
+ * "service_id" is a user-defined id for the service. this is what the
+ * remote end will use to proxy connections to a specific service on
+ * our end.
+ *
+ * if "port" is NULL, "addr" is the address of the net socket the
+ * service is running on. otherwise, addr is the path to the unix socket
+ * the service is running on.
+ *
+ * if "port" AND "addr" are NULL, find and remove the current iforward
+ * for this "service_id" if it exists.
+ *
+ * "ipv6" is a bool denoting whether or not to use ipv6
+ */
+int vp_set_iforward(VPDriver *drv, const char *service_id, const char *addr,
+                    const char *port, bool ipv6)
+{
+    VPIForward *f = get_iforward(drv, service_id);
+
+    if (addr == NULL && port == NULL) {
+        if (f != NULL) {
+            qemu_opts_del(f->socket_opts);
+            QLIST_REMOVE(f, next);
+            qemu_free(f);
+        }
+        return 0;
+    }
+
+    if (f == NULL) {
+        f = qemu_mallocz(sizeof(VPIForward));
+        f->drv = drv;
+        strncpy(f->service_id, service_id, VP_SERVICE_ID_LEN);
+        QLIST_INSERT_HEAD(&drv->iforwards, f, next);
+    } else {
+        qemu_opts_del(f->socket_opts);
+    }
+
+    /* stick socket-related options in a QemuOpts so we can
+     * utilize qemu socket utility functions directly
+     */
+    f->socket_opts = qemu_opts_create(&vp_socket_opts, NULL, 0);
+    if (port == NULL) {
+        /* no port given, assume unix path */
+        qemu_opt_set(f->socket_opts, "path", addr);
+    } else {
+        qemu_opt_set(f->socket_opts, "host", addr);
+        qemu_opt_set(f->socket_opts, "port", port);
+    }
+
+    if (ipv6) {
+        qemu_opt_set(f->socket_opts, "ipv6", "on");
+    } else {
+        qemu_opt_set(f->socket_opts, "ipv4", "on");
+    }
+
+    return 0;
+}
diff --git a/virtproxy.h b/virtproxy.h
index e901600..83cc905 100644
--- a/virtproxy.h
+++ b/virtproxy.h
@@ -41,5 +41,7 @@ void vp_chr_read(CharDriverState *s, uint8_t *buf, int len);
 VPDriver *vp_new(enum vp_context ctx, CharDriverState *s, int fd, bool listen);
 int vp_handle_packet_buf(VPDriver *drv, const void *buf, int count);
 int vp_set_oforward(VPDriver *drv, int fd, const char *service_id);
+int vp_set_iforward(VPDriver *drv, const char *service_id, const char *addr,
+                    const char *port, bool ipv6);
 
 #endif /* VIRTPROXY_H */
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [Qemu-devel] [RFC][PATCH v2 14/19] virtproxy: add read handler for proxied connections
  2010-11-10 22:27 [Qemu-devel] [RFC][PATCH v2 00/19] virtproxy: host/guest communication layer Michael Roth
                   ` (12 preceding siblings ...)
  2010-11-10 22:28 ` [Qemu-devel] [RFC][PATCH v2 13/19] virtproxy: interfaces to set/remove VPIForwards Michael Roth
@ 2010-11-10 22:28 ` Michael Roth
  2010-11-10 22:28 ` [Qemu-devel] [RFC][PATCH v2 15/19] virtproxy: add virtproxy-builtin.c for compat defs Michael Roth
                   ` (5 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Michael Roth @ 2010-11-10 22:28 UTC (permalink / raw)
  To: qemu-devel; +Cc: agl, abeekhof, mdroth, aliguori, ryanh, amit.shah

reads data from client/server connections as they become readable, then
sends the data over the channel

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 virtproxy.c |   80 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 80 insertions(+), 0 deletions(-)

diff --git a/virtproxy.c b/virtproxy.c
index b683ee6..1807c88 100644
--- a/virtproxy.c
+++ b/virtproxy.c
@@ -233,6 +233,86 @@ static VPIForward *get_iforward(const VPDriver *drv, const char *service_id)
     return NULL;
 }
 
+/* read handler for proxied connections */
+static void vp_conn_read(void *opaque)
+{
+    VPConn *conn = opaque;
+    VPDriver *drv = conn->drv;
+    VPPacket pkt;
+    char buf[VP_CONN_DATA_LEN];
+    int fd, count, ret;
+    bool client;
+
+    TRACE("called with opaque: %p, drv: %p", opaque, drv);
+
+    if (conn->state != VP_STATE_CONNECTED) {
+        LOG("invalid connection state");
+        return;
+    }
+
+    if (conn->type != VP_CONN_CLIENT && conn->type != VP_CONN_SERVER) {
+        LOG("invalid connection type");
+        return;
+    }
+
+    /* TODO: all fields should be explicitly set so we shouldn't
+     * need to memset. this might hurt if we beef up VPPacket size
+     */
+    memset(&pkt, 0, sizeof(VPPacket));
+    pkt.magic = VP_MAGIC;
+
+    if (conn->type == VP_CONN_CLIENT) {
+        client = true;
+        fd = conn->client_fd;
+    } else {
+        client = false;
+        fd = conn->server_fd;
+    }
+
+    count = read(fd, buf, VP_CONN_DATA_LEN);
+    if (count == -1) {
+        LOG("read() failed: %s", strerror(errno));
+        return;
+    } else if (count == 0) {
+        /* connection closed, tell remote end to clean up */
+        TRACE("connection closed");
+        pkt.type = VP_PKT_CONTROL;
+        pkt.payload.msg.type = VP_CONTROL_CLOSE;
+        if (client) {
+            /* we're closing the client, have remote close the server conn */
+            TRACE("closing connection for client fd %d", conn->client_fd);
+            pkt.payload.msg.args.close.client_fd = -1;
+            pkt.payload.msg.args.close.server_fd = conn->server_fd;
+        } else {
+            TRACE("closing connection for server fd %d", conn->server_fd);
+            pkt.payload.msg.args.close.server_fd = -1;
+            pkt.payload.msg.args.close.client_fd = conn->client_fd;;
+        }
+        /* clean up things on our end */
+        closesocket(fd);
+        vp_set_fd_handler(fd, NULL, NULL, NULL);
+        QLIST_REMOVE(conn, next);
+        qemu_free(conn);
+    } else {
+        TRACE("data read");
+        pkt.type = client ? VP_PKT_CLIENT : VP_PKT_SERVER;
+        pkt.payload.proxied.client_fd = conn->client_fd;
+        pkt.payload.proxied.server_fd = conn->server_fd;
+        memcpy(pkt.payload.proxied.data, buf, count);
+        pkt.payload.proxied.bytes = count;
+    }
+
+    ret = vp_channel_send_all(drv, (uint8_t*)&pkt, sizeof(VPPacket));
+    if (ret == -1) {
+        LOG("error sending data over channel");
+        return;
+    }
+    if (ret != sizeof(VPPacket)) {
+        TRACE("buffer full?");
+        return;
+    }
+}
+
 /* accept handler for communication channel
  *
  * accept()s connection to communication channel (for sockets), and sets
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [Qemu-devel] [RFC][PATCH v2 15/19] virtproxy: add virtproxy-builtin.c for compat defs
  2010-11-10 22:27 [Qemu-devel] [RFC][PATCH v2 00/19] virtproxy: host/guest communication layer Michael Roth
                   ` (13 preceding siblings ...)
  2010-11-10 22:28 ` [Qemu-devel] [RFC][PATCH v2 14/19] virtproxy: add read handler for proxied connections Michael Roth
@ 2010-11-10 22:28 ` Michael Roth
  2010-11-10 22:28 ` [Qemu-devel] [RFC][PATCH v2 16/19] virtproxy: qemu integration, add virtproxy chardev Michael Roth
                   ` (4 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Michael Roth @ 2010-11-10 22:28 UTC (permalink / raw)
  To: qemu-devel; +Cc: agl, abeekhof, mdroth, aliguori, ryanh, amit.shah

Virtproxy relies on routines defined within qemu-vp which mirror various
i/o related operations in qemu to provide similar functionality for the
guest daemon. When building virtproxy as part of qemu rather than
qemu-vp we need these definitions to provide those functions in terms of
the original qemu functions.

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 virtproxy-builtin.c |   38 ++++++++++++++++++++++++++++++++++++++
 1 files changed, 38 insertions(+), 0 deletions(-)
 create mode 100644 virtproxy-builtin.c

diff --git a/virtproxy-builtin.c b/virtproxy-builtin.c
new file mode 100644
index 0000000..71fc5bc
--- /dev/null
+++ b/virtproxy-builtin.c
@@ -0,0 +1,38 @@
+/*
+ * virt-proxy - host/guest communication layer builtin definitions
+ *
+ * Copyright IBM Corp. 2010
+ *
+ * Authors:
+ *  Adam Litke        <aglitke@linux.vnet.ibm.com>
+ *  Michael Roth      <mdroth@linux.vnet.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+/* the following are functions we define in terms of qemu when linked
+ * against qemu/vl.c. these will be added on an as-needed basis
+ */
+
+#include "qemu-char.h"
+#include "qemu_socket.h"
+#include "virtproxy.h"
+
+int vp_set_fd_handler(int fd,
+                        IOHandler *fd_read,
+                        IOHandler *fd_write,
+                        void *opaque)
+{
+    return qemu_set_fd_handler(fd, fd_read, fd_write, opaque);
+}
+
+int vp_send_all(int fd, const void *buf, int len)
+{
+    return send_all(fd, buf, len);
+}
+
+void vp_chr_read(CharDriverState *s, uint8_t *buf, int len) {
+    return qemu_chr_read(s, buf, len);
+}
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [Qemu-devel] [RFC][PATCH v2 16/19] virtproxy: qemu integration, add virtproxy chardev
  2010-11-10 22:27 [Qemu-devel] [RFC][PATCH v2 00/19] virtproxy: host/guest communication layer Michael Roth
                   ` (14 preceding siblings ...)
  2010-11-10 22:28 ` [Qemu-devel] [RFC][PATCH v2 15/19] virtproxy: add virtproxy-builtin.c for compat defs Michael Roth
@ 2010-11-10 22:28 ` Michael Roth
  2010-11-10 22:28 ` [Qemu-devel] [RFC][PATCH v2 17/19] virtproxy: qemu integration, add virtproxy to Makefile.targets Michael Roth
                   ` (3 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Michael Roth @ 2010-11-10 22:28 UTC (permalink / raw)
  To: qemu-devel; +Cc: agl, abeekhof, mdroth, aliguori, ryanh, amit.shah

This allows us to create a virtproxy instance via a chardev. It can now
be created with something like:

qemu -chardev virtproxy,id=vp1 \
     -device virtio-serial \
     -device virtserialport,chardev=vp1

In the future the ability to add oforwards/iforwards in the command-line
invocation and the monitor will be added. For now we leave it to users
of virtproxy (currently only virtagent) to set up the forwarding
sockets/ports they need via direct virtproxy API calls.

Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 qemu-char.c |   43 +++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 43 insertions(+), 0 deletions(-)

diff --git a/qemu-char.c b/qemu-char.c
index 88997f9..e318acb 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -1902,6 +1902,48 @@ return_err:
 }
 
 /***********************************************************/
+/* Virtproxy chardev driver */
+
+#include "virtproxy.h"
+
+static int vp_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
+{
+    VPDriver *drv = chr->opaque;
+    int ret;
+
+    fprintf(stderr, "called, opaque: %p\n", chr);
+
+    ret = vp_handle_packet_buf(drv, buf, len);
+    if (ret == -1) {
+        fprintf(stderr, "error handling data from virtproxy channel");
+    }
+
+    return 0;
+}
+
+static CharDriverState *qemu_chr_open_virtproxy(QemuOpts *opts)
+{
+    CharDriverState *chr = qemu_mallocz(sizeof(CharDriverState));
+    VPDriver *drv = vp_new(VP_CTX_CHARDEV, chr, 0, 0);
+
+    chr->opaque = drv;
+    chr->chr_write = vp_chr_write;
+
+    qemu_chr_generic_open(chr);
+
+    /* TODO: eventually we will parse opts here to configure
+     * basic host/guest socket/port forwarding functionality.
+     * for now we exist solely for use by the virtagent RPC
+     * client/server, which will add it's oforwards/iforwards
+     * using using virtproxy API calls directly
+     */
+
+    /* for "info chardev" monitor command */
+    chr->filename = NULL;
+    return chr;
+}
+
+/***********************************************************/
 /* TCP Net console */
 
 typedef struct {
@@ -2408,6 +2450,7 @@ static const struct {
     { .name = "udp",       .open = qemu_chr_open_udp },
     { .name = "msmouse",   .open = qemu_chr_open_msmouse },
     { .name = "vc",        .open = text_console_init },
+    { .name = "virtproxy", .open = qemu_chr_open_virtproxy },
 #ifdef _WIN32
     { .name = "file",      .open = qemu_chr_open_win_file_out },
     { .name = "pipe",      .open = qemu_chr_open_win_pipe },
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [Qemu-devel] [RFC][PATCH v2 17/19] virtproxy: qemu integration, add virtproxy to Makefile.targets
  2010-11-10 22:27 [Qemu-devel] [RFC][PATCH v2 00/19] virtproxy: host/guest communication layer Michael Roth
                   ` (15 preceding siblings ...)
  2010-11-10 22:28 ` [Qemu-devel] [RFC][PATCH v2 16/19] virtproxy: qemu integration, add virtproxy chardev Michael Roth
@ 2010-11-10 22:28 ` Michael Roth
  2010-11-10 22:28 ` [Qemu-devel] [RFC][PATCH v2 18/19] virtproxy: qemu-vp, main logic Michael Roth
                   ` (2 subsequent siblings)
  19 siblings, 0 replies; 21+ messages in thread
From: Michael Roth @ 2010-11-10 22:28 UTC (permalink / raw)
  To: qemu-devel; +Cc: agl, abeekhof, mdroth, aliguori, ryanh, amit.shah


Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 Makefile.target |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/Makefile.target b/Makefile.target
index 91e6e74..f08c435 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -164,7 +164,7 @@ endif #CONFIG_BSD_USER
 # System emulator target
 ifdef CONFIG_SOFTMMU
 
-obj-y = arch_init.o cpus.o monitor.o machine.o gdbstub.o balloon.o
+obj-y = arch_init.o cpus.o monitor.o machine.o gdbstub.o balloon.o virtproxy.o virtproxy-builtin.o
 # virtio has to be here due to weird dependency between PCI and virtio-net.
 # need to fix this properly
 obj-y += virtio-blk.o virtio-balloon.o virtio-net.o virtio-serial-bus.o
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [Qemu-devel] [RFC][PATCH v2 18/19] virtproxy: qemu-vp, main logic
  2010-11-10 22:27 [Qemu-devel] [RFC][PATCH v2 00/19] virtproxy: host/guest communication layer Michael Roth
                   ` (16 preceding siblings ...)
  2010-11-10 22:28 ` [Qemu-devel] [RFC][PATCH v2 17/19] virtproxy: qemu integration, add virtproxy to Makefile.targets Michael Roth
@ 2010-11-10 22:28 ` Michael Roth
  2010-11-10 22:28 ` [Qemu-devel] [RFC][PATCH v2 19/19] virtproxy: Makefile/configure changes to build qemu-vp Michael Roth
  2010-11-10 23:47 ` [Qemu-devel] [RFC][PATCH v2 00/19] virtproxy: host/guest communication layer Michael Roth
  19 siblings, 0 replies; 21+ messages in thread
From: Michael Roth @ 2010-11-10 22:28 UTC (permalink / raw)
  To: qemu-devel; +Cc: agl, abeekhof, mdroth, aliguori, ryanh, amit.shah


Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 qemu-vp.c |  475 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 474 insertions(+), 1 deletions(-)

diff --git a/qemu-vp.c b/qemu-vp.c
index 5075cdc..3a3762a 100644
--- a/qemu-vp.c
+++ b/qemu-vp.c
@@ -9,10 +9,54 @@
  * This work is licensed under the terms of the GNU GPL, version 2 or later.
  * See the COPYING file in the top-level directory.
  *
+ * QEMU System Emulator
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
  */
 
+#include <getopt.h>
+#include <err.h>
+#include "qemu-option.h"
+#include "qemu_socket.h"
 #include "virtproxy.h"
 
+static bool verbose_enabled = 0;
+#define DEBUG_ENABLED
+
+#ifdef DEBUG_ENABLED
+#define DEBUG(msg, ...) do { \
+    fprintf(stderr, "%s:%s():L%d: " msg "\n", \
+            __FILE__, __FUNCTION__, __LINE__, ## __VA_ARGS__); \
+} while(0)
+#else
+#define DEBUG(msg, ...) do {} while (0)
+#endif
+
+#define INFO(msg, ...) do { \
+    if (!verbose_enabled) { \
+        break; \
+    } \
+    warnx(msg, ## __VA_ARGS__); \
+} while(0)
+
 /* mirror qemu I/O-related code for standalone daemon */
 typedef struct IOHandlerRecord {
     int fd;
@@ -92,13 +136,19 @@ int vp_send_all(int fd, const void *buf, int len1)
     return len1 - len;
 }
 
+/* qemu_chr_read doesn't get used in guest so noop our wrapper function */
+void vp_chr_read(CharDriverState *s, uint8_t *buf, int len)
+{
+    return;
+}
+
 static void main_loop_wait(int nonblocking)
 {
     IOHandlerRecord *ioh;
     fd_set rfds, wfds, xfds;
     int ret, nfds;
     struct timeval tv;
-    int timeout = 1000;
+    int timeout = 100000;
 
     if (nonblocking) {
         timeout = 0;
@@ -149,3 +199,426 @@ static void main_loop_wait(int nonblocking)
         }
     }
 }
+
+#define VP_ARG_LEN 256
+
+static QemuOptsList vp_opts = {
+    .name = "vpargs",
+    .head = QTAILQ_HEAD_INITIALIZER(vp_opts.head),
+    .desc = {
+        {
+            .name = "service_id",
+            .type = QEMU_OPT_STRING,
+        },{
+            .name = "channel_method",
+            .type = QEMU_OPT_STRING,
+        },{
+            .name = "index",
+            .type = QEMU_OPT_NUMBER,
+        },{
+            .name = "path",
+            .type = QEMU_OPT_STRING,
+        },{
+            .name = "host",
+            .type = QEMU_OPT_STRING,
+        },{
+            .name = "port",
+            .type = QEMU_OPT_STRING,
+        },{
+            .name = "ipv4",
+            .type = QEMU_OPT_BOOL,
+        },{
+            .name = "ipv6",
+            .type = QEMU_OPT_BOOL,
+        },
+        { /* end if list */ }
+    },
+};
+
+typedef struct VPData {
+    QemuOpts *opts;
+    void *opaque;
+    QTAILQ_ENTRY(VPData) next;
+} VPData;
+
+static QTAILQ_HEAD(, VPData) iforwards;
+static QTAILQ_HEAD(, VPData) oforwards;
+static QTAILQ_HEAD(, VPData) channels;
+
+static void usage(const char *cmd)
+{
+    printf(
+"Usage: %s -c <channel_opts> [-c ... ] [-i <iforward_opts> ...] "
+"[-o <oforward_opts> ...]\n"
+"QEMU virt-proxy communication channel\n"
+"\n"
+"  -c, --channel    channel options of the form:\n"
+"                   <method>:<addr>:<port>[:channel_id]\n"
+"  -o, --oforward   oforward options of the form:\n"
+"                   <service_id>:<addr>:<port>[:channel_id]\n"
+"  -i, --iforward   iforward options of the form:\n"
+"                   <service_id>:<addr>:<port>[:channel_id]\n"
+"  -v, --verbose    display extra debugging information\n"
+"  -h, --help       display this help and exit\n"
+"\n"
+"  channels are used to establish a data connection between 2 end-points in\n"
+"  the host or the guest (connection method specified by <method>).\n"
+"  oforwards specify a socket to listen for new connections on, outgoing\n"
+"  data from which is tagged with <service_id> before being sent over the\n"
+"  channel. iforwards specify a socket to route incoming data/connections\n"
+"  with a specific <service_id> to. The positional parameters for\n"
+"  channels/iforwards/oforwards are:\n"
+"\n"
+"  <method>:     one of unix-connect, unix-listen, tcp-connect, tcp-listen,\n"
+"                virtserial-open\n"
+"  <addr>:       path of unix socket or virtserial port, or IP of host, to\n"
+"                connect/bind to\n"
+"  <port>:       port to bind/connect to, or '-' if addr is a path\n"
+"  <service_id>: an identifier used to properly route connections to the\n"
+"                corresponding host or guest daemon socket.\n"
+"  <channel_id>: numerical id to identify what channel to use for an iforward\n"
+"                or oforward. (default is 0)\n"
+"\n"
+"Report bugs to <mdroth@linux.vnet.ibm.com>\n"
+    , cmd);
+}
+
+static int vp_parse(QemuOpts *opts, const char *str, bool is_channel)
+{
+    /* TODO: use VP_SERVICE_ID_LEN, bring it into virtproxy.h */
+    char service_id[32];
+    char channel_method[32];
+    char index[10];
+    char *addr;
+    char port[33];
+    int pos, ret;
+
+    if (is_channel == false) {
+        /* parse service id */
+        ret = sscanf(str,"%32[^:]:%n",service_id,&pos);
+        if (ret != 1) {
+            warn("error parsing service id");
+            return -1;
+        }
+        qemu_opt_set(opts, "service_id", service_id);
+    } else {
+        /* parse connection type */
+        ret = sscanf(str,"%32[^:]:%n",channel_method,&pos);
+        if (ret != 1) {
+            warn("error parsing channel method");
+            return -1;
+        }
+        qemu_opt_set(opts, "channel_method", channel_method);
+    }
+    str += pos;
+    pos = 0;
+
+    /* parse path/addr and port */
+    if (str[0] == '[') {
+        /* ipv6 formatted */
+        ret = sscanf(str,"[%a[^]:]]:%32[^:]%n",&addr,port,&pos);
+        qemu_opt_set(opts, "ipv6", "on");
+    } else {
+        ret = sscanf(str,"%a[^:]:%32[^:]%n",&addr,port,&pos);
+        qemu_opt_set(opts, "ipv4", "on");
+    }
+
+    if (ret != 2) {
+        warnx("error parsing path/addr/port");
+        return -1;
+    } else if (port[0] == '-') {
+        /* no port given, assume unix path */
+        qemu_opt_set(opts, "path", addr);
+    } else {
+        qemu_opt_set(opts, "host", addr);
+        qemu_opt_set(opts, "port", port);
+        qemu_free(addr);
+    }
+    str += pos;
+    pos = 0;
+
+    if (str[0] == ':') {
+        /* parse optional index parameter */
+        ret = sscanf(str,":%10[^:]%n",index,&pos);
+    } else {
+        qemu_opt_set(opts, "index", "0");
+        return 0;
+    }
+
+    if (ret != 1) {
+        warnx("error parsing index");
+        return -1;
+    } else {
+        qemu_opt_set(opts, "index", index);
+    }
+    str += pos;
+    pos = 0;
+
+    return 0;
+}
+
+static VPDriver *get_channel_drv(int index) {
+    VPData *data;
+    VPDriver *drv;
+    int cindex;
+
+    QTAILQ_FOREACH(data, &channels, next) {
+        cindex = qemu_opt_get_number(data->opts, "index", 0);
+        if (cindex == index) {
+            drv = data->opaque;
+            return drv;
+        }
+    }
+
+    return NULL;
+}
+
+static int init_channels(void) {
+    VPDriver *drv;
+    VPData *channel_data;
+    const char *channel_method, *path;
+    int fd, ret;
+    bool listen;
+
+    if (QTAILQ_EMPTY(&channels)) {
+        warnx("no channel specified");
+        return -1;
+    }
+
+    channel_data = QTAILQ_FIRST(&channels);
+
+    /* TODO: add this support, optional idx param for -i/-o/-c
+     * args should suffice
+     */
+    if (QTAILQ_NEXT(channel_data, next) != NULL) {
+        warnx("multiple channels not currently supported, defaulting to first");
+    }
+
+    INFO("initializing channel...");
+    if (verbose_enabled) {
+        qemu_opts_print(channel_data->opts, NULL);
+    }
+
+    channel_method = qemu_opt_get(channel_data->opts, "channel_method");
+
+    if (strcmp(channel_method, "tcp-listen") == 0) {
+        fd = inet_listen_opts(channel_data->opts, 0);
+        listen = true;
+    } else if (strcmp(channel_method, "tcp-connect") == 0) {
+        fd = inet_connect_opts(channel_data->opts);
+        listen = false;
+    } else if (strcmp(channel_method, "unix-listen") == 0) {
+        fd = unix_listen_opts(channel_data->opts);
+        listen = true;
+    } else if (strcmp(channel_method, "unix-connect") == 0) {
+        fd = unix_connect_opts(channel_data->opts);
+        listen = false;
+    } else if (strcmp(channel_method, "virtserial-open") == 0) {
+        path = qemu_opt_get(channel_data->opts, "path");
+        fd = qemu_open(path, O_RDWR);
+        ret = fcntl(fd, F_GETFL);
+        ret = fcntl(fd, F_SETFL, ret | O_ASYNC);
+        if (ret < 0) {
+            warn("error setting flags for fd");
+            return -1;
+        }
+        listen = false;
+    } else {
+        warnx("invalid channel type: %s", channel_method);
+        return -1;
+    }
+
+    if (fd == -1) {
+        warn("error opening connection");
+        return -1;
+    }
+
+    drv = vp_new(VP_CTX_FD, NULL, fd, listen);
+    channel_data->opaque = drv;
+
+    return 0;
+}
+
+static int init_oforwards(void) {
+    VPDriver *drv;
+    VPData *oforward_data;
+    int index, ret, fd;
+    const char *service_id;
+
+    QTAILQ_FOREACH(oforward_data, &oforwards, next) {
+        INFO("initializing oforward...");
+        if (verbose_enabled) {
+            qemu_opts_print(oforward_data->opts, NULL);
+        }
+
+        index = qemu_opt_get_number(oforward_data->opts, "index", 0);
+        drv = get_channel_drv(index);
+        if (drv == NULL) {
+            warnx("unable to find channel with index: %d", index);
+            return -1;
+        }
+
+        if (qemu_opt_get(oforward_data->opts, "host") != NULL) {
+            fd = inet_listen_opts(oforward_data->opts, 0);
+        } else if (qemu_opt_get(oforward_data->opts, "path") != NULL) {
+            fd = unix_listen_opts(oforward_data->opts);
+        } else {
+            warnx("unable to find listening socket host/addr info");
+            return -1;
+        }
+
+        if (fd == -1) {
+            warnx("failed to create FD");
+            return -1;
+        }
+
+        service_id = qemu_opt_get(oforward_data->opts, "service_id");
+
+        if (service_id == NULL) {
+            warnx("no service_id specified");
+            return -1;
+        }
+
+        ret = vp_set_oforward(drv, fd, service_id);
+    }
+
+    return 0;
+}
+
+static int init_iforwards(void) {
+    VPDriver *drv;
+    VPData *iforward_data;
+    int index, ret;
+    const char *service_id, *addr, *port;
+    bool ipv6;
+
+    QTAILQ_FOREACH(iforward_data, &iforwards, next) {
+        INFO("initializing iforward...");
+        if (verbose_enabled) {
+            qemu_opts_print(iforward_data->opts, NULL);
+        }
+
+        index = qemu_opt_get_number(iforward_data->opts, "index", 0);
+        drv = get_channel_drv(index);
+        if (drv == NULL) {
+            warnx("unable to find channel with index: %d", index);
+            return -1;
+        }
+
+        service_id = qemu_opt_get(iforward_data->opts, "service_id");
+        if (service_id == NULL) {
+            warnx("no service_id specified");
+            return -1;
+        }
+
+        addr = qemu_opt_get(iforward_data->opts, "path");
+        port = NULL;
+
+        if (addr == NULL) {
+            /* map service to a network socket instead */
+            addr = qemu_opt_get(iforward_data->opts, "host");
+            port = qemu_opt_get(iforward_data->opts, "port");
+        }
+
+        ipv6 = qemu_opt_get_bool(iforward_data->opts, "ipv6", 0) ?
+               true : false;
+
+        ret = vp_set_iforward(drv, service_id, addr, port, ipv6);
+        if (ret != 0) {
+            warnx("error adding iforward");
+            return -1;
+        }
+    }
+
+    return 0;
+}
+
+int main(int argc, char **argv)
+{
+    const char *sopt = "hVvi:o:c:";
+    struct option lopt[] = {
+        { "help", 0, NULL, 'h' },
+        { "version", 0, NULL, 'V' },
+        { "verbose", 0, NULL, 'v' },
+        { "iforward", 0, NULL, 'i' },
+        { "oforward", 0, NULL, 'o' },
+        { "channel", 0, NULL, 'c' },
+        { NULL, 0, NULL, 0 }
+    };
+    int opt_ind = 0, ch, ret;
+    QTAILQ_INIT(&iforwards);
+    QTAILQ_INIT(&oforwards);
+    QTAILQ_INIT(&channels);
+
+    while ((ch = getopt_long(argc, argv, sopt, lopt, &opt_ind)) != -1) {
+        QemuOpts *opts;
+        VPData *data;
+        switch (ch) {
+        case 'i':
+            opts = qemu_opts_create(&vp_opts, NULL, 0);
+            ret = vp_parse(opts, optarg, 0);
+            if (ret) {
+                errx(EXIT_FAILURE, "error parsing arg: %s", optarg);
+            }
+            data = qemu_mallocz(sizeof(VPData));
+            data->opts = opts;
+            QTAILQ_INSERT_TAIL(&iforwards, data, next);
+            break;
+        case 'o':
+            opts = qemu_opts_create(&vp_opts, NULL, 0);
+            ret = vp_parse(opts, optarg, 0);
+            if (ret) {
+                errx(EXIT_FAILURE, "error parsing arg: %s", optarg);
+            }
+            data = qemu_mallocz(sizeof(VPData));
+            data->opts = opts;
+            QTAILQ_INSERT_TAIL(&oforwards, data, next);
+            break;
+        case 'c':
+            opts = qemu_opts_create(&vp_opts, NULL, 0);
+            ret = vp_parse(opts, optarg, 1);
+            if (ret) {
+                errx(EXIT_FAILURE, "error parsing arg: %s", optarg);
+            }
+            data = qemu_mallocz(sizeof(VPData));
+            data->opts = opts;
+            QTAILQ_INSERT_TAIL(&channels, data, next);
+            break;
+        case 'v':
+            verbose_enabled = 1;
+            break;
+        case 'h':
+            usage(argv[0]);
+            return 0;
+        case '?':
+            errx(EXIT_FAILURE, "Try '%s --help' for more information.",
+                 argv[0]);
+        }
+    }
+
+    ret = init_channels();
+    if (ret) {
+        errx(EXIT_FAILURE, "error initializing communication channel");
+    }
+
+    ret = init_oforwards();
+    if (ret) {
+        errx(EXIT_FAILURE,
+             "error initializing forwarders for outgoing connections");
+    }
+
+    ret = init_iforwards();
+    if (ret) {
+        errx(EXIT_FAILURE,
+             "error initializing service mappings for incoming connections");
+    }
+
+    /* main i/o loop */
+    for (;;) {
+        DEBUG("entering main_loop_wait()");
+        main_loop_wait(0);
+        DEBUG("left main_loop_wait()");
+    }
+
+    return 0;
+}
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [Qemu-devel] [RFC][PATCH v2 19/19] virtproxy: Makefile/configure changes to build qemu-vp
  2010-11-10 22:27 [Qemu-devel] [RFC][PATCH v2 00/19] virtproxy: host/guest communication layer Michael Roth
                   ` (17 preceding siblings ...)
  2010-11-10 22:28 ` [Qemu-devel] [RFC][PATCH v2 18/19] virtproxy: qemu-vp, main logic Michael Roth
@ 2010-11-10 22:28 ` Michael Roth
  2010-11-10 23:47 ` [Qemu-devel] [RFC][PATCH v2 00/19] virtproxy: host/guest communication layer Michael Roth
  19 siblings, 0 replies; 21+ messages in thread
From: Michael Roth @ 2010-11-10 22:28 UTC (permalink / raw)
  To: qemu-devel; +Cc: agl, abeekhof, mdroth, aliguori, ryanh, amit.shah


Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
 .gitignore |    1 +
 Makefile   |    4 +++-
 configure  |    1 +
 3 files changed, 5 insertions(+), 1 deletions(-)

diff --git a/.gitignore b/.gitignore
index a43e4d1..da307d2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -31,6 +31,7 @@ qemu-img-cmds.texi
 qemu-img-cmds.h
 qemu-io
 qemu-monitor.texi
+qemu-vp
 QMP/qmp-commands.txt
 .gdbinit
 *.a
diff --git a/Makefile b/Makefile
index 02698e9..a435ae1 100644
--- a/Makefile
+++ b/Makefile
@@ -129,7 +129,7 @@ version-obj-$(CONFIG_WIN32) += version.o
 ######################################################################
 
 qemu-img.o: qemu-img-cmds.h
-qemu-img.o qemu-tool.o qemu-nbd.o qemu-io.o: $(GENERATED_HEADERS)
+qemu-img.o qemu-tool.o qemu-nbd.o qemu-io.o virtproxy.o: $(GENERATED_HEADERS)
 
 qemu-img$(EXESUF): qemu-img.o qemu-tool.o qemu-error.o $(oslib-obj-y) $(trace-obj-y) $(block-obj-y) $(qobject-obj-y) $(version-obj-y) qemu-timer-common.o
 
@@ -137,6 +137,8 @@ qemu-nbd$(EXESUF): qemu-nbd.o qemu-tool.o qemu-error.o $(oslib-obj-y) $(trace-ob
 
 qemu-io$(EXESUF): qemu-io.o cmd.o qemu-tool.o qemu-error.o $(oslib-obj-y) $(trace-obj-y) $(block-obj-y) $(qobject-obj-y) $(version-obj-y) qemu-timer-common.o
 
+qemu-vp$(EXESUF): qemu-vp.o virtproxy.o qemu-tool.o qemu-error.o qemu-sockets.c $(oslib-obj-y) $(trace-obj-y) $(block-obj-y) $(qobject-obj-y) $(version-obj-y) qemu-timer-common.o
+
 qemu-img-cmds.h: $(SRC_PATH)/qemu-img-cmds.hx
 	$(call quiet-command,sh $(SRC_PATH)/hxtool -h < $< > $@,"  GEN   $@")
 
diff --git a/configure b/configure
index 7025d2b..01bde83 100755
--- a/configure
+++ b/configure
@@ -2250,6 +2250,7 @@ if test "$softmmu" = yes ; then
   tools="qemu-img\$(EXESUF) qemu-io\$(EXESUF) $tools"
   if [ "$linux" = "yes" -o "$bsd" = "yes" -o "$solaris" = "yes" ] ; then
       tools="qemu-nbd\$(EXESUF) $tools"
+      tools="qemu-vp\$(EXESUF) $tools"
     if [ "$check_utests" = "yes" ]; then
       tools="check-qint check-qstring check-qdict check-qlist $tools"
       tools="check-qfloat check-qjson $tools"
-- 
1.7.0.4

^ permalink raw reply related	[flat|nested] 21+ messages in thread

* Re: [Qemu-devel] [RFC][PATCH v2 00/19] virtproxy: host/guest communication layer
  2010-11-10 22:27 [Qemu-devel] [RFC][PATCH v2 00/19] virtproxy: host/guest communication layer Michael Roth
                   ` (18 preceding siblings ...)
  2010-11-10 22:28 ` [Qemu-devel] [RFC][PATCH v2 19/19] virtproxy: Makefile/configure changes to build qemu-vp Michael Roth
@ 2010-11-10 23:47 ` Michael Roth
  19 siblings, 0 replies; 21+ messages in thread
From: Michael Roth @ 2010-11-10 23:47 UTC (permalink / raw)
  To: Michael Roth; +Cc: agl, abeekhof, qemu-devel, aliguori, ryanh, amit.shah

On 11/10/2010 04:27 PM, Michael Roth wrote:
> OVERVIEW:
>
> Virtproxy proxies and multiplexes socket streams over a data channel between a host and a guest (currently network connections, emulated serial, or virtio-serial channels are supported). This allows for services such as guest data collection agents, host/guest file transfer, and event generation/handling to be implemented/deployed as basic socket-based daemons, independently of the actual data channel.
>
> This code is intended to provide a channel-independent abstraction layer for communicating with a QEMU-specific guest agent (in particular, the virtagent RPC guest agent which will follow this in a seperate patchset), but may have general utility beyond this (for instance: ssh/sftp/other guest agents/etc over isa/virtio serial), and so is submitted here as a seperate patchset.
>
> CHANGES IN V2:
>   - host daemon deprecated, virtproxy now integrated into qemu via a virtproxy chardev. The command-line options have not yet been converted over so for now the virtproxy layer is no longer testable directly. This will be addressed soon. Virtagent will hook into this chardev via a boolean chardev option. That patchset will follow this one shortly.
>   - deadlocking issue resolved
>
> BUILD/USAGE INFO:
>    # build guest daemon
>    make qemu-vp
>    ./qemu-vp -h
>
> EXAMPLE USAGE:
>
> note: oforward/iforward chardev options have not yet been converted over from original standalone host daemon implementation so this won't work till then. The examples however have been updated for reference.
>
>   - Proxy http and ssh connections from a host to a guest over a virtio-serial connection:
>      # start guest with virtio-serial. for example (RHEL6s13):
>      qemu \
>      -device virtio-serial \
>      -chardev virtproxy,id=test0, \
>               oforward=http:127.0.0.1:9080,oforward=ssh:127.0.0.1:22 \
>      -device virtconsole,chardev=test0,name=test0 \

-device virtserialport,chardev=test0,name=test0

^ permalink raw reply	[flat|nested] 21+ messages in thread

end of thread, other threads:[~2010-11-10 23:47 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-11-10 22:27 [Qemu-devel] [RFC][PATCH v2 00/19] virtproxy: host/guest communication layer Michael Roth
2010-11-10 22:27 ` [Qemu-devel] [RFC][PATCH v2 01/19] virtproxy: base data structures and constants Michael Roth
2010-11-10 22:27 ` [Qemu-devel] [RFC][PATCH v2 02/19] virtproxy: qemu-vp, standalone daemon skeleton Michael Roth
2010-11-10 22:27 ` [Qemu-devel] [RFC][PATCH v2 03/19] virtproxy: add debug functions for virtproxy core Michael Roth
2010-11-10 22:28 ` [Qemu-devel] [RFC][PATCH v2 04/19] virtproxy: list look-up functions conns/oforwards/iforwards Michael Roth
2010-11-10 22:28 ` [Qemu-devel] [RFC][PATCH v2 05/19] virtproxy, add vp_channel_send_all Michael Roth
2010-11-10 22:28 ` [Qemu-devel] [RFC][PATCH v2 06/19] virtproxy: add accept handler for communication channel Michael Roth
2010-11-10 22:28 ` [Qemu-devel] [RFC][PATCH v2 07/19] virtproxy: add read " Michael Roth
2010-11-10 22:28 ` [Qemu-devel] [RFC][PATCH v2 08/19] virtproxy: add vp_new() VPDriver constructor Michael Roth
2010-11-10 22:28 ` [Qemu-devel] [RFC][PATCH v2 09/19] virtproxy: interfaces to set/remove/handle VPOForwards Michael Roth
2010-11-10 22:28 ` [Qemu-devel] [RFC][PATCH v2 10/19] virtproxy: add handler for data packets Michael Roth
2010-11-10 22:28 ` [Qemu-devel] [RFC][PATCH v2 11/19] virtproxy: add handler for control packet Michael Roth
2010-11-10 22:28 ` [Qemu-devel] [RFC][PATCH v2 12/19] virtproxy: add vp_handle_packet() Michael Roth
2010-11-10 22:28 ` [Qemu-devel] [RFC][PATCH v2 13/19] virtproxy: interfaces to set/remove VPIForwards Michael Roth
2010-11-10 22:28 ` [Qemu-devel] [RFC][PATCH v2 14/19] virtproxy: add read handler for proxied connections Michael Roth
2010-11-10 22:28 ` [Qemu-devel] [RFC][PATCH v2 15/19] virtproxy: add virtproxy-builtin.c for compat defs Michael Roth
2010-11-10 22:28 ` [Qemu-devel] [RFC][PATCH v2 16/19] virtproxy: qemu integration, add virtproxy chardev Michael Roth
2010-11-10 22:28 ` [Qemu-devel] [RFC][PATCH v2 17/19] virtproxy: qemu integration, add virtproxy to Makefile.targets Michael Roth
2010-11-10 22:28 ` [Qemu-devel] [RFC][PATCH v2 18/19] virtproxy: qemu-vp, main logic Michael Roth
2010-11-10 22:28 ` [Qemu-devel] [RFC][PATCH v2 19/19] virtproxy: Makefile/configure changes to build qemu-vp Michael Roth
2010-11-10 23:47 ` [Qemu-devel] [RFC][PATCH v2 00/19] virtproxy: host/guest communication layer Michael Roth

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).