Patchwork [RFC,v2,10/17] qmp proxy: add qmp_proxy chardev

login
register
mail settings
Submitter Michael Roth
Date April 18, 2011, 3:02 p.m.
Message ID <1303138953-1334-11-git-send-email-mdroth@linux.vnet.ibm.com>
Download mbox | patch
Permalink /patch/91778/
State New
Headers show

Comments

Michael Roth - April 18, 2011, 3:02 p.m.
This allows qemu to be started with guest agent support via:

qemu -chardev qmp_proxy,id=qmp_proxy -device ...,chardev=qmp_proxy

Writes to the guest agent are buffered, with deferred work handled by a
timer. Writes from the guest agent to host/proxy are passed directly
into a JSON streamer object/buffer.

The chardev is intended for use with virtio-serial or isa-serial
channels. Other uses may be possible with appropriate changes to guest
agent.

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

Patch

diff --git a/qemu-char.c b/qemu-char.c
index d301925..27b1252 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -2276,6 +2276,60 @@  static CharDriverState *qemu_chr_open_socket(QemuOpts *opts)
 }
 
 /***********************************************************/
+/* QMP host->guest proxy chardev */
+#include "qmp-proxy-core.h"
+#include "json-streamer.h"
+
+extern QmpProxy *qmp_proxy_default;
+
+static int qmp_proxy_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
+{
+    QmpProxy *p = chr->opaque;
+
+    qmp_proxy_read(p, buf, len);
+
+    return len;
+}
+
+static void qmp_proxy_chr_close(CharDriverState *chr)
+{
+    QmpProxy *p = chr->opaque;
+
+    qmp_proxy_default = NULL;
+    qmp_proxy_close(p);
+    qemu_chr_event(chr, CHR_EVENT_CLOSED);
+}
+
+static CharDriverState *qemu_chr_open_qmp_proxy(QemuOpts *opts)
+{
+    CharDriverState *chr = qemu_mallocz(sizeof(CharDriverState));
+    QmpProxy *p;
+
+    /* initialize the qmp guest proxy */
+    if (qmp_proxy_default) {
+        fprintf(stderr, "error, multiple qmp guest proxies are not allowed\n");
+        goto err;
+    }
+    p = qmp_proxy_default = qmp_proxy_new(chr);
+    if (p == NULL) {
+        fprintf(stderr, "error initializing qmp guest proxy\n");
+        goto err;
+    }
+
+    chr->opaque = p;
+    chr->chr_write = qmp_proxy_chr_write;
+    chr->chr_close = qmp_proxy_chr_close;
+    qemu_chr_generic_open(chr);
+
+    return chr;
+err:
+    if (chr) {
+        qemu_free(chr);
+    }
+    return NULL;
+}
+
+/***********************************************************/
 /* Memory chardev */
 typedef struct {
     size_t outbuf_size;
@@ -2495,6 +2549,7 @@  static const struct {
     || defined(__FreeBSD_kernel__)
     { .name = "parport",   .open = qemu_chr_open_pp },
 #endif
+    { .name = "qmp_proxy", .open = qemu_chr_open_qmp_proxy },
 };
 
 CharDriverState *qemu_chr_open_opts(QemuOpts *opts,