From: Michael Roth <mdroth@linux.vnet.ibm.com>
To: qemu-devel@nongnu.org
Cc: agl@linux.vnet.ibm.com, abeekhof@redhat.com,
mdroth@linux.vnet.ibm.com, aliguori@linux.vnet.ibm.com,
ryanh@us.ibm.com, amit.shah@redhat.com
Subject: [Qemu-devel] [RFC][PATCH v3 20/21] virtproxy: qemu-vp, main logic
Date: Mon, 15 Nov 2010 19:16:14 -0600 [thread overview]
Message-ID: <1289870175-14880-21-git-send-email-mdroth@linux.vnet.ibm.com> (raw)
In-Reply-To: <1289870175-14880-1-git-send-email-mdroth@linux.vnet.ibm.com>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
---
qemu-vp.c | 368 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
virtproxy.c | 24 ----
2 files changed, 367 insertions(+), 25 deletions(-)
diff --git a/qemu-vp.c b/qemu-vp.c
index 5075cdc..cfd2a69 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,319 @@ static void main_loop_wait(int nonblocking)
}
}
}
+
+#define VP_ARG_LEN 256
+
+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 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;
+}
diff --git a/virtproxy.c b/virtproxy.c
index 78cda04..336c39f 100644
--- a/virtproxy.c
+++ b/virtproxy.c
@@ -164,30 +164,6 @@ struct VPDriver {
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 */ }
- },
-};
-
static void vp_channel_read(void *opaque);
static int vp_channel_send_all(VPDriver *drv, uint8_t *buf, int count)
--
1.7.0.4
next prev parent reply other threads:[~2010-11-16 1:17 UTC|newest]
Thread overview: 51+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-11-16 1:15 [Qemu-devel] [RFC][PATCH v3 00/21] virtproxy: host/guest communication layer Michael Roth
2010-11-16 1:15 ` [Qemu-devel] [RFC][PATCH v3 01/21] virtproxy: base data structures and constants Michael Roth
2010-11-18 11:06 ` Jes Sorensen
2010-11-18 15:35 ` Michael Roth
2010-11-18 15:41 ` Anthony Liguori
2010-11-18 15:51 ` Jes Sorensen
2010-11-18 15:56 ` Anthony Liguori
2010-11-18 16:03 ` Jes Sorensen
2010-11-16 1:15 ` [Qemu-devel] [RFC][PATCH v3 02/21] virtproxy: qemu-vp, standalone daemon skeleton Michael Roth
2010-11-18 10:04 ` Stefan Hajnoczi
2010-11-18 15:46 ` Michael Roth
2010-11-18 11:04 ` Jes Sorensen
2010-11-16 1:15 ` [Qemu-devel] [RFC][PATCH v3 03/21] virtproxy: add debug functions for virtproxy core Michael Roth
2010-11-18 11:09 ` Jes Sorensen
2010-11-18 11:43 ` Stefan Hajnoczi
2010-11-18 17:17 ` Michael Roth
2010-11-19 9:21 ` Stefan Hajnoczi
2010-11-16 1:15 ` [Qemu-devel] [RFC][PATCH v3 04/21] virtproxy: list look-up functions conns/oforwards/iforwards Michael Roth
2010-11-16 1:15 ` [Qemu-devel] [RFC][PATCH v3 05/21] virtproxy, add vp_channel_send_all Michael Roth
2010-11-18 10:08 ` Stefan Hajnoczi
2010-11-16 1:16 ` [Qemu-devel] [RFC][PATCH v3 06/21] virtproxy: add accept handler for communication channel Michael Roth
2010-11-16 1:16 ` [Qemu-devel] [RFC][PATCH v3 07/21] virtproxy: add read " Michael Roth
2010-11-16 23:17 ` Anthony Liguori
2010-11-17 21:43 ` Michael Roth
2010-11-18 10:11 ` Stefan Hajnoczi
2010-11-16 1:16 ` [Qemu-devel] [RFC][PATCH v3 08/21] virtproxy: add vp_new() VPDriver constructor Michael Roth
2010-11-16 1:16 ` [Qemu-devel] [RFC][PATCH v3 09/21] virtproxy: interfaces to set/remove/handle VPOForwards Michael Roth
2010-11-16 1:16 ` [Qemu-devel] [RFC][PATCH v3 10/21] virtproxy: add handler for data packets Michael Roth
2010-11-18 11:25 ` Jes Sorensen
2010-11-16 1:16 ` [Qemu-devel] [RFC][PATCH v3 11/21] virtproxy: add handler for control packet Michael Roth
2010-11-18 11:35 ` Jes Sorensen
2010-11-18 16:18 ` Michael Roth
2010-11-18 16:22 ` Jes Sorensen
2010-11-18 16:50 ` Michael Roth
2010-11-16 1:16 ` [Qemu-devel] [RFC][PATCH v3 12/21] virtproxy: add vp_handle_packet() Michael Roth
2010-11-16 1:16 ` [Qemu-devel] [RFC][PATCH v3 13/21] virtproxy: interfaces to set/remove VPIForwards Michael Roth
2010-11-16 1:16 ` [Qemu-devel] [RFC][PATCH v3 14/21] virtproxy: use new option list in virtproxy.c Michael Roth
2010-11-16 1:16 ` [Qemu-devel] [RFC][PATCH v3 15/21] virtproxy: add read handler for proxied connections Michael Roth
2010-11-18 11:41 ` Jes Sorensen
2010-11-16 1:16 ` [Qemu-devel] [RFC][PATCH v3 16/21] virtproxy: add option parser helper vp_parse() Michael Roth
2010-11-18 11:43 ` Jes Sorensen
2010-11-16 1:16 ` [Qemu-devel] [RFC][PATCH v3 17/21] virtproxy: add virtproxy-builtin.c for compat defs Michael Roth
2010-11-18 11:45 ` Jes Sorensen
2010-11-16 1:16 ` [Qemu-devel] [RFC][PATCH v3 18/21] virtproxy: qemu integration, add virtproxy chardev Michael Roth
2010-11-18 11:47 ` Jes Sorensen
2010-11-16 1:16 ` [Qemu-devel] [RFC][PATCH v3 19/21] virtproxy: qemu integration, add virtproxy to Makefile.targets Michael Roth
2010-11-16 1:16 ` Michael Roth [this message]
2010-11-16 1:16 ` [Qemu-devel] [RFC][PATCH v3 21/21] virtproxy: Makefile/configure changes to build qemu-vp Michael Roth
2010-11-16 21:57 ` [Qemu-devel] [RFC][PATCH v3 00/21] virtproxy: host/guest communication layer Stefan Hajnoczi
2010-11-16 22:28 ` Michael Roth
2010-11-16 22:41 ` Michael Roth
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1289870175-14880-21-git-send-email-mdroth@linux.vnet.ibm.com \
--to=mdroth@linux.vnet.ibm.com \
--cc=abeekhof@redhat.com \
--cc=agl@linux.vnet.ibm.com \
--cc=aliguori@linux.vnet.ibm.com \
--cc=amit.shah@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=ryanh@us.ibm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).