* [RFC PATCH 6/6] tools: Add guest trace agent as a user tool
From: Yoshihiro YUNOMAE @ 2012-07-24 2:37 UTC (permalink / raw)
To: linux-kernel
Cc: Herbert Xu, Arnd Bergmann, Frederic Weisbecker, yrl.pp-manager.tt,
qemu-devel, Borislav Petkov, virtualization, Franch Ch. Eigler,
Ingo Molnar, Mathieu Desnoyers, Steven Rostedt, Anthony Liguori,
Greg Kroah-Hartman, Amit Shah
In-Reply-To: <20120724023657.6600.52706.stgit@ltc189.sdl.hitachi.co.jp>
This patch adds a user tool, "trace agent" for sending trace data of a guest to
a Host in low overhead. This agent has the following functions:
- splice a page of ring-buffer to read_pipe without memory copying
- splice the page from write_pipe to virtio-console without memory copying
- write trace data to stdout by using -o option
- controlled by start/stop orders from a Host
Signed-off-by: Yoshihiro YUNOMAE <yoshihiro.yunomae.ez@hitachi.com>
---
tools/virtio/virtio-trace/Makefile | 14 +
tools/virtio/virtio-trace/README | 118 ++++++++++++
tools/virtio/virtio-trace/trace-agent-ctl.c | 137 ++++++++++++++
tools/virtio/virtio-trace/trace-agent-rw.c | 192 +++++++++++++++++++
tools/virtio/virtio-trace/trace-agent.c | 270 +++++++++++++++++++++++++++
tools/virtio/virtio-trace/trace-agent.h | 75 ++++++++
6 files changed, 806 insertions(+), 0 deletions(-)
create mode 100644 tools/virtio/virtio-trace/Makefile
create mode 100644 tools/virtio/virtio-trace/README
create mode 100644 tools/virtio/virtio-trace/trace-agent-ctl.c
create mode 100644 tools/virtio/virtio-trace/trace-agent-rw.c
create mode 100644 tools/virtio/virtio-trace/trace-agent.c
create mode 100644 tools/virtio/virtio-trace/trace-agent.h
diff --git a/tools/virtio/virtio-trace/Makefile b/tools/virtio/virtio-trace/Makefile
new file mode 100644
index 0000000..ef3adfc
--- /dev/null
+++ b/tools/virtio/virtio-trace/Makefile
@@ -0,0 +1,14 @@
+CC = gcc
+CFLAGS = -O2 -Wall
+LFLAG = -lpthread
+
+all: trace-agent
+
+.c.o:
+ $(CC) $(CFLAGS) $(LFLAG) -c $^ -o $@
+
+trace-agent: trace-agent.o trace-agent-ctl.o trace-agent-rw.o
+ $(CC) $(CFLAGS) $(LFLAG) -o $@ $^
+
+clean:
+ rm -f *.o trace-agent
diff --git a/tools/virtio/virtio-trace/README b/tools/virtio/virtio-trace/README
new file mode 100644
index 0000000..b64845b
--- /dev/null
+++ b/tools/virtio/virtio-trace/README
@@ -0,0 +1,118 @@
+Trace Agent for virtio-trace
+============================
+
+Trace agent is a user tool for sending trace data of a guest to a Host in low
+overhead. Trace agent has the following functions:
+ - splice a page of ring-buffer to read_pipe without memory copying
+ - splice the page from write_pipe to virtio-console without memory copying
+ - write trace data to stdout by using -o option
+ - controlled by start/stop orders from a Host
+
+The trace agent operates as follows:
+ 1) Initialize all structures.
+ 2) Create a read/write thread per CPU. Each thread is bound to a CPU.
+ The read/write threads hold it.
+ 3) A controller thread does poll() for a start order of a host.
+ 4) After the controller of the trace agent receives a start order from a host,
+ the controller wake read/write threads.
+ 5) The read/write threads start to read trace data from ring-buffers and
+ write the data to virtio-serial.
+ 6) If the controller receives a stop order from a host, the read/write threads
+ stop to read trace data.
+
+
+Files
+=====
+
+README: this file
+Makefile: Makefile of trace agent for virtio-trace
+trace-agent.c: includes main function, sets up for operating trace agent
+trace-agent.h: includes all structures and some macros
+trace-agent-ctl.c: includes controller function for read/write threads
+trace-agent-rw.c: includes read/write threads function
+
+
+Setup
+=====
+
+To use this trace agent for virtio-trace, we need to prepare some virtio-serial
+I/Fs.
+
+1) Make FIFO in a host
+ virtio-trace uses virtio-serial pipe as trace data paths as to the number
+of CPUs and a control path, so FIFO (named pipe) should be created as follows:
+ # mkdir /tmp/virtio-trace/
+ # mkfifo /tmp/virtio-trace/trace-path-cpu{0,1,2,...,X}.{in,out}
+ # mkfifo /tmp/virtio-trace/agent-ctl-path.{in,out}
+
+For example, if a guest use three CPUs, the names are
+ trace-path-cpu{0,1,2}.{in.out}
+and
+ agent-ctl-path.{in,out}.
+
+2) Set up of virtio-serial pipe in a host
+ Add qemu option to use virtio-serial pipe.
+
+ ##virtio-serial device##
+ -device virtio-serial-pci,id=virtio-serial0\
+ ##control path##
+ -chardev pipe,id=charchannel0,path=/tmp/virtio-trace/agent-ctl-path\
+ -device virtserialport,bus=virtio-serial0.0,nr=1,chardev=charchannel0,\
+ id=channel0,name=agent-ctl-path\
+ ##data path##
+ -chardev pipe,id=charchannel1,path=/tmp/virtio-trace/trace-path-cpu0\
+ -device virtserialport,bus=virtio-serial0.0,nr=2,chardev=charchannel0,\
+ id=channel1,name=trace-path-cpu0\
+ ...
+
+If you manage guests with libvirt, add the following tags to domain XML files.
+Then, libvirt passes the same command option to qemu.
+
+ <channel type='pipe'>
+ <source path='/tmp/virtio-trace/agent-ctl-path'/>
+ <target type='virtio' name='agent-ctl-path'/>
+ <address type='virtio-serial' controller='0' bus='0' port='0'/>
+ </channel>
+ <channel type='pipe'>
+ <source path='/tmp/virtio-trace/trace-path-cpu0'/>
+ <target type='virtio' name='trace-path-cpu0'/>
+ <address type='virtio-serial' controller='0' bus='0' port='1'/>
+ </channel>
+ ...
+Here, chardev names are restricted to trace-path-cpuX and agent-ctl-path. For
+example, if a guest use three CPUs, chardev names should be trace-path-cpu0,
+trace-path-cpu1, trace-path-cpu2, and agent-ctl-path.
+
+3) Boot the guest
+ You can find some chardev in /dev/virtio-ports/ in the guest.
+
+
+Run
+===
+
+0) Build trace agent in a guest
+ $ make
+
+1) Enable ftrace in the guest
+ <Example>
+ # echo 1 > /sys/kernel/debug/tracing/events/sched/enable
+
+2) Run trace agent in the guest
+ This agent must be operated as root.
+ # ./trace-agent
+read/write threads in the agent wait for start order from host. If you add -o
+option, trace data are output via stdout in the guest.
+
+3) Open FIFO in a host
+ # cat /tmp/virtio-trace/trace-path-cpu0.out
+If a host does not open these, trace data get stuck in buffers of virtio. Then,
+the guest will stop by specification of chardev in QEMU. This blocking mode may
+be solved in the future.
+
+4) Start to read trace data by ordering from a host
+ A host injects read start order to the guest via virtio-serial.
+ # echo 1 > /tmp/virtio-trace/agent-ctl-path.in
+
+5) Stop to read trace data by ordering from a host
+ A host injects read stop order to the guest via virtio-serial.
+ # echo 0 > /tmp/virtio-trace/agent-ctl-path.in
diff --git a/tools/virtio/virtio-trace/trace-agent-ctl.c b/tools/virtio/virtio-trace/trace-agent-ctl.c
new file mode 100644
index 0000000..0739815
--- /dev/null
+++ b/tools/virtio/virtio-trace/trace-agent-ctl.c
@@ -0,0 +1,137 @@
+/*
+ * Controller of read/write threads for virtio-trace
+ *
+ * Copyright (C) 2012 Hitachi, Ltd.
+ * Created by Yoshihiro Yunomae <yoshihiro.yunomae.ez@hitachi.com>
+ * Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
+ *
+ * Licensed under GPL version 2 only.
+ *
+ */
+
+#define _GNU_SOURCE
+#include <fcntl.h>
+#include <poll.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "trace-agent.h"
+
+#define HOST_MSG_SIZE 256
+#define EVENT_WAIT_MSEC 100
+
+static volatile sig_atomic_t global_signal_val;
+bool global_sig_receive; /* default false */
+bool global_run_operation; /* default false*/
+
+/* Handle SIGTERM/SIGINT/SIGQUIT to exit */
+static void signal_handler(int sig)
+{
+ global_signal_val = sig;
+}
+
+int rw_ctl_init(const char *ctl_path)
+{
+ int ctl_fd;
+
+ ctl_fd = open(ctl_path, O_RDONLY);
+ if (ctl_fd == -1) {
+ fprintf(stderr, "Cannot open ctl_fd\n");
+ goto error;
+ }
+
+ return ctl_fd;
+
+error:
+ exit(EXIT_FAILURE);
+}
+
+static int wait_order(int ctl_fd)
+{
+ struct pollfd poll_fd;
+ int ret = 0;
+
+ while (!global_sig_receive) {
+ poll_fd.fd = ctl_fd;
+ poll_fd.events = POLLIN;
+
+ ret = poll(&poll_fd, 1, EVENT_WAIT_MSEC);
+
+ if (global_signal_val) {
+ global_sig_receive = true;
+ pr_info("Receive interrupt %d\n", global_signal_val);
+
+ /* Wakes rw-threads when they are sleeping */
+ if (!global_run_operation)
+ pthread_cond_broadcast(&cond_wakeup);
+
+ ret = -1;
+ break;
+ }
+
+ if (ret < 0) {
+ pr_err("Polling error\n");
+ goto error;
+ }
+
+ if (ret)
+ break;
+ };
+
+ return ret;
+
+error:
+ exit(EXIT_FAILURE);
+}
+
+/*
+ * contol read/write threads by handling global_run_operation
+ */
+void *rw_ctl_loop(int ctl_fd)
+{
+ ssize_t rlen;
+ char buf[HOST_MSG_SIZE];
+ int ret;
+
+ /* Setup signal handlers */
+ signal(SIGTERM, signal_handler);
+ signal(SIGINT, signal_handler);
+ signal(SIGQUIT, signal_handler);
+
+ while (!global_sig_receive) {
+
+ ret = wait_order(ctl_fd);
+ if (ret < 0)
+ break;
+
+ rlen = read(ctl_fd, buf, sizeof(buf));
+ if (rlen < 0) {
+ pr_err("read data error in ctl thread\n");
+ goto error;
+ }
+
+ if (rlen == 2 && buf[0] == '1') {
+ /*
+ * If host writes '1' to a control path,
+ * this controller wakes all read/write threads.
+ */
+ global_run_operation = true;
+ pthread_cond_broadcast(&cond_wakeup);
+ pr_debug("Wake up all read/write threads\n");
+ } else if (rlen == 2 && buf[0] == '0') {
+ /*
+ * If host writes '0' to a control path, read/write
+ * threads will wait for notification from Host.
+ */
+ global_run_operation = false;
+ pr_debug("Stop all read/write threads\n");
+ } else
+ pr_info("Invalid host notification: %s\n", buf);
+ }
+
+ return NULL;
+
+error:
+ exit(EXIT_FAILURE);
+}
diff --git a/tools/virtio/virtio-trace/trace-agent-rw.c b/tools/virtio/virtio-trace/trace-agent-rw.c
new file mode 100644
index 0000000..3aace5e
--- /dev/null
+++ b/tools/virtio/virtio-trace/trace-agent-rw.c
@@ -0,0 +1,192 @@
+/*
+ * Read/write thread of a guest agent for virtio-trace
+ *
+ * Copyright (C) 2012 Hitachi, Ltd.
+ * Created by Yoshihiro Yunomae <yoshihiro.yunomae.ez@hitachi.com>
+ * Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
+ *
+ * Licensed under GPL version 2 only.
+ *
+ */
+
+#define _GNU_SOURCE
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/syscall.h>
+#include "trace-agent.h"
+
+#define READ_WAIT_USEC 100000
+
+void *rw_thread_info_new(void)
+{
+ struct rw_thread_info *rw_ti;
+
+ rw_ti = zalloc(sizeof(struct rw_thread_info));
+ if (rw_ti == NULL) {
+ pr_err("rw_thread_info zalloc error\n");
+ exit(EXIT_FAILURE);
+ }
+
+ rw_ti->cpu_num = -1;
+ rw_ti->in_fd = -1;
+ rw_ti->out_fd = -1;
+ rw_ti->read_pipe = -1;
+ rw_ti->write_pipe = -1;
+ rw_ti->pipe_size = PIPE_INIT;
+
+ return rw_ti;
+}
+
+void *rw_thread_init(int cpu, const char *in_path, const char *out_path,
+ bool stdout_flag, unsigned long pipe_size,
+ struct rw_thread_info *rw_ti)
+{
+ int data_pipe[2];
+
+ rw_ti->cpu_num = cpu;
+
+ /* set read(input) fd */
+ rw_ti->in_fd = open(in_path, O_RDONLY);
+ if (rw_ti->in_fd == -1) {
+ pr_err("Could not open in_fd (CPU:%d)\n", cpu);
+ goto error;
+ }
+
+ /* set write(output) fd */
+ if (!stdout_flag) {
+ /* virtio-serial output mode */
+ rw_ti->out_fd = open(out_path, O_WRONLY);
+ if (rw_ti->out_fd == -1) {
+ pr_err("Could not open out_fd (CPU:%d)\n", cpu);
+ goto error;
+ }
+ } else
+ /* stdout mode */
+ rw_ti->out_fd = STDOUT_FILENO;
+
+ if (pipe2(data_pipe, O_NONBLOCK) < 0) {
+ pr_err("Could not create pipe in rw-thread(%d)\n", cpu);
+ goto error;
+ }
+
+ /*
+ * Size of pipe is 64kB in default based on fs/pipe.c.
+ * To read/write trace data speedy, pipe size is changed.
+ */
+ if (fcntl(*data_pipe, F_SETPIPE_SZ, pipe_size) < 0) {
+ pr_err("Could not change pipe size in rw-thread(%d)\n", cpu);
+ goto error;
+ }
+
+ rw_ti->read_pipe = data_pipe[1];
+ rw_ti->write_pipe = data_pipe[0];
+ rw_ti->pipe_size = pipe_size;
+
+ return NULL;
+
+error:
+ exit(EXIT_FAILURE);
+}
+
+/* Bind a thread to a cpu */
+static void bind_cpu(int cpu_num)
+{
+ cpu_set_t mask;
+
+ CPU_ZERO(&mask);
+ CPU_SET(cpu_num, &mask);
+
+ /* bind my thread to cpu_num by assigning zero to the first argument */
+ if (sched_setaffinity(0, sizeof(mask), &mask) == -1)
+ pr_err("Could not set CPU#%d affinity\n", (int)cpu_num);
+}
+
+static void *rw_thread_main(void *thread_info)
+{
+ ssize_t rlen, wlen;
+ ssize_t ret;
+ struct rw_thread_info *ts = (struct rw_thread_info *)thread_info;
+
+ bind_cpu(ts->cpu_num);
+
+ while (1) {
+ /* Wait for a read order of trace data by Host OS */
+ if (!global_run_operation) {
+ pthread_mutex_lock(&mutex_notify);
+ pthread_cond_wait(&cond_wakeup, &mutex_notify);
+ pthread_mutex_unlock(&mutex_notify);
+ }
+
+ if (global_sig_receive)
+ break;
+
+ /*
+ * Each thread read trace_pipe_raw of each cpu bounding the
+ * thread, so contention of multi-threads does not occur.
+ */
+ rlen = splice(ts->in_fd, NULL, ts->read_pipe, NULL,
+ ts->pipe_size, SPLICE_F_MOVE | SPLICE_F_MORE);
+
+ if (rlen < 0) {
+ pr_err("Splice_read in rw-thread(%d)\n", ts->cpu_num);
+ goto error;
+ } else if (rlen == 0) {
+ /*
+ * If trace data do not exist or are unreadable not
+ * for exceeding the page size, splice_read returns
+ * NULL. Then, this waits for being filled the data in a
+ * ring-buffer.
+ */
+ usleep(READ_WAIT_USEC);
+ pr_debug("Read retry(cpu:%d)\n", ts->cpu_num);
+ continue;
+ }
+
+ wlen = 0;
+
+ do {
+ ret = splice(ts->write_pipe, NULL, ts->out_fd, NULL,
+ rlen - wlen,
+ SPLICE_F_MOVE | SPLICE_F_MORE);
+
+ if (ret < 0) {
+ pr_err("Splice_write in rw-thread(%d)\n",
+ ts->cpu_num);
+ goto error;
+ } else if (ret == 0)
+ /*
+ * When host reader is not in time for reading
+ * trace data, guest will be stopped. This is
+ * because char dev in QEMU is not supported
+ * non-blocking mode. Then, writer might be
+ * sleep in that case.
+ * This sleep will be removed by supporting
+ * non-blocking mode.
+ */
+ sleep(1);
+ wlen += ret;
+ } while (wlen < rlen);
+ }
+
+ return NULL;
+
+error:
+ exit(EXIT_FAILURE);
+}
+
+
+pthread_t rw_thread_run(struct rw_thread_info *rw_ti)
+{
+ int ret;
+ pthread_t rw_thread_per_cpu;
+
+ ret = pthread_create(&rw_thread_per_cpu, NULL, rw_thread_main, rw_ti);
+ if (ret != 0) {
+ pr_err("Could not create a rw thread(%d)\n", rw_ti->cpu_num);
+ exit(EXIT_FAILURE);
+ }
+
+ return rw_thread_per_cpu;
+}
diff --git a/tools/virtio/virtio-trace/trace-agent.c b/tools/virtio/virtio-trace/trace-agent.c
new file mode 100644
index 0000000..1816259
--- /dev/null
+++ b/tools/virtio/virtio-trace/trace-agent.c
@@ -0,0 +1,270 @@
+/*
+ * Guest agent for virtio-trace
+ *
+ * Copyright (C) 2012 Hitachi, Ltd.
+ * Created by Yoshihiro Yunomae <yoshihiro.yunomae.ez@hitachi.com>
+ * Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
+ *
+ * Licensed under GPL version 2 only.
+ *
+ */
+
+#define _GNU_SOURCE
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "trace-agent.h"
+
+#define PAGE_SIZE (sysconf(_SC_PAGE_SIZE))
+#define PIPE_DEF_BUFS 16
+#define PIPE_MIN_SIZE (PAGE_SIZE*PIPE_DEF_BUFS)
+#define PIPE_MAX_SIZE (1024*1024)
+#define READ_PATH_FMT \
+ "/sys/kernel/debug/tracing/per_cpu/cpu%d/trace_pipe_raw"
+#define WRITE_PATH_FMT "/dev/virtio-ports/trace-path-cpu%d"
+#define CTL_PATH "/dev/virtio-ports/agent-ctl-path"
+
+pthread_mutex_t mutex_notify = PTHREAD_MUTEX_INITIALIZER;
+pthread_cond_t cond_wakeup = PTHREAD_COND_INITIALIZER;
+
+static int get_total_cpus(void)
+{
+ int nr_cpus = (int)sysconf(_SC_NPROCESSORS_CONF);
+
+ if (nr_cpus <= 0) {
+ pr_err("Could not read cpus\n");
+ goto error;
+ } else if (nr_cpus > MAX_CPUS) {
+ pr_err("Exceed max cpus(%d)\n", (int)MAX_CPUS);
+ goto error;
+ }
+
+ return nr_cpus;
+
+error:
+ exit(EXIT_FAILURE);
+}
+
+static void *agent_info_new(void)
+{
+ struct agent_info *s;
+ int i;
+
+ s = zalloc(sizeof(struct agent_info));
+ if (s == NULL) {
+ pr_err("agent_info zalloc error\n");
+ exit(EXIT_FAILURE);
+ }
+
+ s->pipe_size = PIPE_INIT;
+ s->use_stdout = false;
+ s->cpus = get_total_cpus();
+ s->ctl_fd = -1;
+
+ /* read/write threads init */
+ for (i = 0; i < s->cpus; i++)
+ s->rw_ti[i] = rw_thread_info_new();
+
+ return s;
+}
+
+static unsigned long parse_size(const char *arg)
+{
+ unsigned long value, round;
+ char *ptr;
+
+ value = strtoul(arg, &ptr, 10);
+ switch (*ptr) {
+ case 'K': case 'k':
+ value <<= 10;
+ break;
+ case 'M': case 'm':
+ value <<= 20;
+ break;
+ default:
+ break;
+ }
+
+ if (value > PIPE_MAX_SIZE) {
+ pr_err("Pipe size must be less than 1MB\n");
+ goto error;
+ } else if (value < PIPE_MIN_SIZE) {
+ pr_err("Pipe size must be over 64KB\n");
+ goto error;
+ }
+
+ /* Align buffer size with page unit */
+ round = value & (PAGE_SIZE - 1);
+ value = value - round;
+
+ return value;
+error:
+ return 0;
+}
+
+static void usage(char const *prg)
+{
+ fprintf(stderr, "usage: %s [-h] [-o] [-s <size of pipe>]\n", prg);
+}
+
+static const char *make_path(int cpu_num, bool this_is_write_path)
+{
+ int ret;
+ char *buf;
+
+ buf = zalloc(PATH_MAX);
+ if (buf == NULL) {
+ pr_err("Could not allocate buffer\n");
+ goto error;
+ }
+
+ if (this_is_write_path)
+ /* write(output) path */
+ ret = snprintf(buf, PATH_MAX, WRITE_PATH_FMT, cpu_num);
+ else
+ /* read(input) path */
+ ret = snprintf(buf, PATH_MAX, READ_PATH_FMT, cpu_num);
+
+ if (ret <= 0) {
+ pr_err("Failed to generate %s path(CPU#%d):%d\n",
+ this_is_write_path ? "read" : "write", cpu_num, ret);
+ goto error;
+ }
+
+ return buf;
+
+error:
+ free(buf);
+ return NULL;
+}
+
+static const char *make_input_path(int cpu_num)
+{
+ return make_path(cpu_num, false);
+}
+
+static const char *make_output_path(int cpu_num)
+{
+ return make_path(cpu_num, true);
+}
+
+static void *agent_info_init(struct agent_info *s)
+{
+ int cpu;
+ const char *in_path = NULL;
+ const char *out_path = NULL;
+
+ /* init read/write threads */
+ for (cpu = 0; cpu < s->cpus; cpu++) {
+ /* set read(input) path per read/write thread */
+ in_path = make_input_path(cpu);
+ if (in_path == NULL)
+ goto error;
+
+ /* set write(output) path per read/write thread*/
+ if (!s->use_stdout) {
+ out_path = make_output_path(cpu);
+ if (out_path == NULL)
+ goto error;
+ } else
+ /* stdout mode */
+ pr_debug("stdout mode\n");
+
+ rw_thread_init(cpu, in_path, out_path, s->use_stdout,
+ s->pipe_size, s->rw_ti[cpu]);
+ }
+
+ /* init controller of read/write threads */
+ s->ctl_fd = rw_ctl_init((const char *)CTL_PATH);
+
+ return NULL;
+
+error:
+ exit(EXIT_FAILURE);
+}
+
+static void *parse_args(int argc, char *argv[], struct agent_info *s)
+{
+ int cmd;
+ unsigned long size;
+
+ while ((cmd = getopt(argc, argv, "hos:")) != -1) {
+ switch (cmd) {
+ /* stdout mode */
+ case 'o':
+ s->use_stdout = true;
+ break;
+ /* size of pipe */
+ case 's':
+ size = parse_size(optarg);
+ if (size == 0)
+ goto error;
+ s->pipe_size = size;
+ break;
+ case 'h':
+ default:
+ usage(argv[0]);
+ goto error;
+ }
+ }
+
+ agent_info_init(s);
+
+ return NULL;
+
+error:
+ exit(EXIT_FAILURE);
+}
+
+static void agent_main_loop(struct agent_info *s)
+{
+ int cpu;
+ pthread_t rw_thread_per_cpu[MAX_CPUS];
+
+ /* Start all read/write threads */
+ for (cpu = 0; cpu < s->cpus; cpu++)
+ rw_thread_per_cpu[cpu] = rw_thread_run(s->rw_ti[cpu]);
+
+ rw_ctl_loop(s->ctl_fd);
+
+ /* Finish all read/write threads */
+ for (cpu = 0; cpu < s->cpus; cpu++) {
+ int ret;
+
+ ret = pthread_join(rw_thread_per_cpu[cpu], NULL);
+ if (ret != 0) {
+ pr_err("pthread_join() error:%d (cpu %d)\n", ret, cpu);
+ exit(EXIT_FAILURE);
+ }
+ }
+}
+
+static void agent_info_free(struct agent_info *s)
+{
+ int i;
+
+ close(s->ctl_fd);
+ for (i = 0; i < s->cpus; i++) {
+ close(s->rw_ti[i]->in_fd);
+ close(s->rw_ti[i]->out_fd);
+ close(s->rw_ti[i]->read_pipe);
+ close(s->rw_ti[i]->write_pipe);
+ free(s->rw_ti[i]);
+ }
+ free(s);
+}
+
+int main(int argc, char *argv[])
+{
+ struct agent_info *s = NULL;
+
+ s = agent_info_new();
+ parse_args(argc, argv, s);
+
+ agent_main_loop(s);
+
+ agent_info_free(s);
+
+ return 0;
+}
diff --git a/tools/virtio/virtio-trace/trace-agent.h b/tools/virtio/virtio-trace/trace-agent.h
new file mode 100644
index 0000000..4711a75
--- /dev/null
+++ b/tools/virtio/virtio-trace/trace-agent.h
@@ -0,0 +1,75 @@
+#ifndef __GUEST_AGENT_H__
+#define __GUEST_AGENT_H__
+#include <pthread.h>
+#include <stdbool.h>
+
+#define MAX_CPUS 256
+#define PIPE_INIT (1024*1024)
+
+/*
+ * agent_info - structure managing total information of guest agent
+ * @pipe_size: size of pipe (default 1MB)
+ * @use_stdout: set to true when o option is added (default false)
+ * @cpus: total number of CPUs
+ * @ctl_fd: fd of control path, /dev/virtio-ports/agent-ctl-path
+ * @rw_ti: structure managing information of read/write threads
+ */
+struct agent_info {
+ unsigned long pipe_size;
+ bool use_stdout;
+ int cpus;
+ int ctl_fd;
+ struct rw_thread_info *rw_ti[MAX_CPUS];
+};
+
+/*
+ * rw_thread_info - structure managing a read/write thread a cpu
+ * @cpu_num: cpu number operating this read/write thread
+ * @in_fd: fd of reading trace data path in cpu_num
+ * @out_fd: fd of writing trace data path in cpu_num
+ * @read_pipe: fd of read pipe
+ * @write_pipe: fd of write pipe
+ * @pipe_size: size of pipe (default 1MB)
+ */
+struct rw_thread_info {
+ int cpu_num;
+ int in_fd;
+ int out_fd;
+ int read_pipe;
+ int write_pipe;
+ unsigned long pipe_size;
+};
+
+/* use for stopping rw threads */
+extern bool global_sig_receive;
+
+/* use for notification */
+extern bool global_run_operation;
+extern pthread_mutex_t mutex_notify;
+extern pthread_cond_t cond_wakeup;
+
+/* for controller of read/write threads */
+extern int rw_ctl_init(const char *ctl_path);
+extern void *rw_ctl_loop(int ctl_fd);
+
+/* for trace read/write thread */
+extern void *rw_thread_info_new(void);
+extern void *rw_thread_init(int cpu, const char *in_path, const char *out_path,
+ bool stdout_flag, unsigned long pipe_size,
+ struct rw_thread_info *rw_ti);
+extern pthread_t rw_thread_run(struct rw_thread_info *rw_ti);
+
+static inline void *zalloc(size_t size)
+{
+ return calloc(1, size);
+}
+
+#define pr_err(format, ...) fprintf(stderr, format, ## __VA_ARGS__)
+#define pr_info(format, ...) fprintf(stdout, format, ## __VA_ARGS__)
+#ifdef DEBUG
+#define pr_debug(format, ...) fprintf(stderr, format, ## __VA_ARGS__)
+#else
+#define pr_debug(format, ...) do {} while (0)
+#endif
+
+#endif /*__GUEST_AGENT_H__*/
^ permalink raw reply related
* Re: [RFC PATCH 0/6] virtio-trace: Support virtio-trace
From: Masami Hiramatsu @ 2012-07-24 3:27 UTC (permalink / raw)
To: Yoshihiro YUNOMAE
Cc: Herbert Xu, Arnd Bergmann, qemu-devel, Frederic Weisbecker,
yrl.pp-manager.tt, linux-kernel, Borislav Petkov, virtualization,
Franch Ch. Eigler, Ingo Molnar, Mathieu Desnoyers, Steven Rostedt,
Anthony Liguori, Greg Kroah-Hartman, Amit Shah
In-Reply-To: <20120724023657.6600.52706.stgit@ltc189.sdl.hitachi.co.jp>
(2012/07/24 11:36), Yoshihiro YUNOMAE wrote:
> Therefore, we propose a new system "virtio-trace", which uses enhanced
> virtio-serial and existing ring-buffer of ftrace, for collecting guest kernel
> tracing data. In this system, there are 5 main components:
> (1) Ring-buffer of ftrace in a guest
> - When trace agent reads ring-buffer, a page is removed from ring-buffer.
> (2) Trace agent in the guest
> - Splice the page of ring-buffer to read_pipe using splice() without
> memory copying. Then, the page is spliced from write_pipe to virtio
> without memory copying.
> (3) Virtio-console driver in the guest
> - Pass the page to virtio-ring
> (4) Virtio-serial bus in QEMU
> - Copy the page to kernel pipe
> (5) Reader in the host
> - Read guest tracing data via FIFO(named pipe)
So, this is our answer for the argued points in previous thread.
This virtio-serial and ftrace enhancements doesn't introduce new
"ringbuffer" in the kernel, and just use virtio's ringbuffer.
Also, using splice gives us a great advantage in the performance
because of copy-less trace-data transfer.
Actually, one copy should occur in the host (to write it into the pipe),
because removing physical pages of the guest is hard to track and may
involve a TLB flush per page, even if it is done in background.
Thank you,
--
Masami HIRAMATSU
Software Platform Research Dept. Linux Technology Center
Hitachi, Ltd., Yokohama Research Laboratory
E-mail: masami.hiramatsu.pt@hitachi.com
^ permalink raw reply
* Re: [RFC 0/2] virtio: provide a way for host to monitor critical events in the device
From: Rusty Russell @ 2012-07-24 4:55 UTC (permalink / raw)
To: mst, penberg, asias.hejun
Cc: kvm, wency, linux-kernel, virtualization, avi, anthony,
Sasha Levin
In-Reply-To: <1343075561-29316-1-git-send-email-levinsasha928@gmail.com>
On Mon, 23 Jul 2012 22:32:39 +0200, Sasha Levin <levinsasha928@gmail.com> wrote:
> As it was discussed recently, there's currently no way for the guest to notify
> the host about panics. Further more, there's no reasonable way to notify the
> host of other critical events such as an OOM kill.
I clearly missed the discussion. Is this actually useful? In practice,
won't you want the log from the guest? What makes a virtual guest
different from a physical guest?
Guest watchdog functionality might be useful, but that's simpler to
implement via a virtio watchdog device, and more effective to implement
via a host facility that actually pings guest functionality (rather than
the kernel).
Cheers,
Rusty.
^ permalink raw reply
* Re: [RFC 0/2] virtio: provide a way for host to monitor critical events in the device
From: Gleb Natapov @ 2012-07-24 7:44 UTC (permalink / raw)
To: Sasha Levin
Cc: wency, kvm, mst, linux-kernel, virtualization, penberg, avi,
anthony
In-Reply-To: <1343075561-29316-1-git-send-email-levinsasha928@gmail.com>
On Mon, Jul 23, 2012 at 10:32:39PM +0200, Sasha Levin wrote:
> As it was discussed recently, there's currently no way for the guest to notify
> the host about panics. Further more, there's no reasonable way to notify the
> host of other critical events such as an OOM kill.
>
> This short patch series introduces a new device named virtio-notifier which
> does two simple things:
>
> 1. Provide a simple interface for the guest to notify the host of critical
To get early OOPSes virtio will have to be compiled into the kernel. If
your are so keen on using virtio for this though, why not just use
dedicated virtio serial channel?
> events. This is easily expandible to add support for any events we may find
> interesting for the host to know about.
>
> 2. Provide an "echo" interface for the host to ping the guest. This allows
> the host to ping the guest at intervals chosen by the host, and act
> accordingly if no response has been received.
>
> Sasha Levin (2):
> virtio: Introduce virtio-notifier
> kvm tools: support virtio-notifier
>
> drivers/virtio/Kconfig | 11 ++
> drivers/virtio/Makefile | 1 +
> drivers/virtio/virtio_notifier.c | 135 ++++++++++++++++++++
> include/linux/virtio_ids.h | 1 +
> include/linux/virtio_notifier.h | 15 +++
> tools/kvm/Makefile | 1 +
> tools/kvm/builtin-run.c | 6 +
> tools/kvm/include/kvm/virtio-notifier.h | 9 ++
> tools/kvm/include/kvm/virtio-pci-dev.h | 1 +
> tools/kvm/virtio/notifier.c | 203 +++++++++++++++++++++++++++++++
> 10 files changed, 383 insertions(+), 0 deletions(-)
> create mode 100644 drivers/virtio/virtio_notifier.c
> create mode 100644 include/linux/virtio_notifier.h
> create mode 100644 tools/kvm/include/kvm/virtio-notifier.h
> create mode 100644 tools/kvm/virtio/notifier.c
>
> --
> 1.7.8.6
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/
--
Gleb.
^ permalink raw reply
* Re: [RFC 0/2] virtio: provide a way for host to monitor critical events in the device
From: Dor Laor @ 2012-07-24 8:26 UTC (permalink / raw)
To: Rusty Russell
Cc: wency, kvm, mst, linux-kernel, virtualization, penberg,
Sasha Levin, anthony, avi
In-Reply-To: <87a9yprc4v.fsf@rustcorp.com.au>
On 07/24/2012 07:55 AM, Rusty Russell wrote:
> On Mon, 23 Jul 2012 22:32:39 +0200, Sasha Levin <levinsasha928@gmail.com> wrote:
>> As it was discussed recently, there's currently no way for the guest to notify
>> the host about panics. Further more, there's no reasonable way to notify the
>> host of other critical events such as an OOM kill.
>
> I clearly missed the discussion. Is this actually useful? In practice,
Admit this is not a killer feature..
> won't you want the log from the guest? What makes a virtual guest
> different from a physical guest?
Most times virt guest can do better than a physical OS. In that sense,
this is where virtualization shines (live migration, hotplug for any
virtual resource including net/block/cpu/memory/..).
There are plenty of niche but worth while small features such as the
virtio-trace series and other that allow the host/virt-mgmt to get more
insight into the guest w/o a need to configure the guest.
In theory guest OOM can trigger a host memory hot plug action. Again, I
don't see it as a key feature..
>
> Guest watchdog functionality might be useful, but that's simpler to
There is already a fully emulated watchdog device in qemu.
Cheers,
Dor
> implement via a virtio watchdog device, and more effective to implement
> via a host facility that actually pings guest functionality (rather than
> the kernel).
>
> Cheers,
> Rusty.
> --
> To unsubscribe from this list: send the line "unsubscribe kvm" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
^ permalink raw reply
* Re: [RFC PATCH 0/6] virtio-trace: Support virtio-trace
From: Stefan Hajnoczi @ 2012-07-24 10:02 UTC (permalink / raw)
To: Yoshihiro YUNOMAE
Cc: Herbert Xu, Arnd Bergmann, Greg Kroah-Hartman,
Frederic Weisbecker, Dhaval Giani, qemu-devel, Borislav Petkov,
linux-kernel, Franch Ch. Eigler, Ingo Molnar, Mathieu Desnoyers,
Steven Rostedt, Anthony Liguori, yrl.pp-manager.tt, Amit Shah,
virtualization, Srikar Dronamraju
In-Reply-To: <20120724023657.6600.52706.stgit@ltc189.sdl.hitachi.co.jp>
On Tue, Jul 24, 2012 at 3:36 AM, Yoshihiro YUNOMAE
<yoshihiro.yunomae.ez@hitachi.com> wrote:
> The performance of each method is compared as follows:
> [1] Native
> - only recording trace data to ring-buffer on a guest
> [2] Virtio-trace
> - running a trace agent on a guest
> - a reader on a host opens FIFO using cat command
> [3] IVRing
> - A SystemTap script in a guest records trace data to IVRing.
> -- probe points are same as ftrace.
> [4] Virtio-serial(normal)
> - A reader(using cat) on a guest output trace data to a host using
> standard output via virtio-serial.
The first time I read this I thought you are adding a new virtio-trace
device. But it looks like this series really add splice support to
virtio-console and that yields a big performance improvement when
sending trace_pipe_raw.
Guest ftrace is useful and I like this. Have you thought about
controlling ftrace from the host? Perhaps a command could be added to
the QEMU guest agent which basically invokes trace-cmd/perf.
Are you using text formatted ftrace?
Stefan
^ permalink raw reply
* Re: Re: [RFC PATCH 0/6] virtio-trace: Support virtio-trace
From: Masami Hiramatsu @ 2012-07-24 11:03 UTC (permalink / raw)
To: Stefan Hajnoczi
Cc: Herbert Xu, Arnd Bergmann, Greg Kroah-Hartman,
Frederic Weisbecker, Dhaval Giani, linux-kernel, Borislav Petkov,
qemu-devel, Franch Ch. Eigler, Ingo Molnar, Mathieu Desnoyers,
Steven Rostedt, Anthony Liguori, yrl.pp-manager.tt, Amit Shah,
virtualization, Srikar Dronamraju
In-Reply-To: <CAJSP0QW_2JJ0nf=NW0y30VSid2HSxaqb=mRGV8CTtAKj0ujDWw@mail.gmail.com>
(2012/07/24 19:02), Stefan Hajnoczi wrote:
> On Tue, Jul 24, 2012 at 3:36 AM, Yoshihiro YUNOMAE
> <yoshihiro.yunomae.ez@hitachi.com> wrote:
>> The performance of each method is compared as follows:
>> [1] Native
>> - only recording trace data to ring-buffer on a guest
>> [2] Virtio-trace
>> - running a trace agent on a guest
>> - a reader on a host opens FIFO using cat command
>> [3] IVRing
>> - A SystemTap script in a guest records trace data to IVRing.
>> -- probe points are same as ftrace.
>> [4] Virtio-serial(normal)
>> - A reader(using cat) on a guest output trace data to a host using
>> standard output via virtio-serial.
>
> The first time I read this I thought you are adding a new virtio-trace
> device. But it looks like this series really add splice support to
> virtio-console and that yields a big performance improvement when
> sending trace_pipe_raw.
Yes, sorry for the confusion. Actually this is an enhancement of
virtio-serial. I'm working with Yoshihiro on this feature.
> Guest ftrace is useful and I like this. Have you thought about
> controlling ftrace from the host? Perhaps a command could be added to
> the QEMU guest agent which basically invokes trace-cmd/perf.
As you can see, guest trace-agent can be controlled via a
control channel. In our scenario, host tools can control that
instead of guest one.
We are considering that exporting the tracing part of guest's
debugfs to host via another virtio-serial channel by using
9pfs, so that the host tools can refer that.
(In this scenario, guest trace-agent will also provide 9pfs server.
Since it means that the agent can handle writing a special file,
trace-agent can be controlled via the special file on exported
debugfs.)
Of course, this also requires modifying trace-cmd/perf to accept
some options like guest-debugfs mount point, guest's serial
channel pipe (or unix socket?), etc. However, it will be a small
change.
Thank you,
--
Masami HIRAMATSU
Software Platform Research Dept. Linux Technology Center
Hitachi, Ltd., Yokohama Research Laboratory
E-mail: masami.hiramatsu.pt@hitachi.com
^ permalink raw reply
* Re: Re: [RFC PATCH 0/6] virtio-trace: Support virtio-trace
From: Yoshihiro YUNOMAE @ 2012-07-24 11:19 UTC (permalink / raw)
To: Stefan Hajnoczi
Cc: Herbert Xu, Arnd Bergmann, Greg Kroah-Hartman,
Frederic Weisbecker, Dhaval Giani, linux-kernel, Borislav Petkov,
qemu-devel, Amit Shah, Franch Ch. Eigler, Ingo Molnar,
Mathieu Desnoyers, Steven Rostedt, Anthony Liguori,
yrl.pp-manager.tt, Masami Hiramatsu, virtualization,
Srikar Dronamraju
In-Reply-To: <500E810A.4030309@hitachi.com>
Hi Stefan,
Thank you for commenting on our patch set.
(2012/07/24 20:03), Masami Hiramatsu wrote:
> (2012/07/24 19:02), Stefan Hajnoczi wrote:
>> On Tue, Jul 24, 2012 at 3:36 AM, Yoshihiro YUNOMAE
>> <yoshihiro.yunomae.ez@hitachi.com> wrote:
>>> The performance of each method is compared as follows:
>>> [1] Native
>>> - only recording trace data to ring-buffer on a guest
>>> [2] Virtio-trace
>>> - running a trace agent on a guest
>>> - a reader on a host opens FIFO using cat command
>>> [3] IVRing
>>> - A SystemTap script in a guest records trace data to IVRing.
>>> -- probe points are same as ftrace.
>>> [4] Virtio-serial(normal)
>>> - A reader(using cat) on a guest output trace data to a host using
>>> standard output via virtio-serial.
>>
>> The first time I read this I thought you are adding a new virtio-trace
>> device. But it looks like this series really add splice support to
>> virtio-console and that yields a big performance improvement when
>> sending trace_pipe_raw.
>
> Yes, sorry for the confusion. Actually this is an enhancement of
> virtio-serial. I'm working with Yoshihiro on this feature.
>
>> Guest ftrace is useful and I like this. Have you thought about
>> controlling ftrace from the host? Perhaps a command could be added to
>> the QEMU guest agent which basically invokes trace-cmd/perf.
>
> As you can see, guest trace-agent can be controlled via a
> control channel. In our scenario, host tools can control that
> instead of guest one.
>
> We are considering that exporting the tracing part of guest's
> debugfs to host via another virtio-serial channel by using
> 9pfs, so that the host tools can refer that.
>
> (In this scenario, guest trace-agent will also provide 9pfs server.
> Since it means that the agent can handle writing a special file,
> trace-agent can be controlled via the special file on exported
> debugfs.)
>
> Of course, this also requires modifying trace-cmd/perf to accept
> some options like guest-debugfs mount point, guest's serial
> channel pipe (or unix socket?), etc. However, it will be a small
> change.
>
> Thank you,
>
>> Are you using text formatted ftrace?
No, currently using raw format, but we'd like to reformat it in text.
Thank you,
--
Yoshihiro YUNOMAE
Software Platform Research Dept. Linux Technology Center
Hitachi, Ltd., Yokohama Research Laboratory
E-mail: yoshihiro.yunomae.ez@hitachi.com
_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization
^ permalink raw reply
* Re: [RFC 0/2] virtio: provide a way for host to monitor critical events in the device
From: Sasha Levin @ 2012-07-24 12:23 UTC (permalink / raw)
To: Rusty Russell
Cc: wency, kvm, mst, linux-kernel, virtualization, penberg, avi,
anthony
In-Reply-To: <87a9yprc4v.fsf@rustcorp.com.au>
On 07/24/2012 06:55 AM, Rusty Russell wrote:> On Mon, 23 Jul 2012 22:32:39 +0200, Sasha Levin <levinsasha928@gmail.com> wrote:
>> As it was discussed recently, there's currently no way for the guest to notify
>> the host about panics. Further more, there's no reasonable way to notify the
>> host of other critical events such as an OOM kill.
>
> I clearly missed the discussion. Is this actually useful? In practice,
> won't you want the log from the guest? What makes a virtual guest
> different from a physical guest?
I'll try answering all of those questions:
My usecase for it is to help out with getting automatic debug output out of a problematic guest. I run a KVM tools guest which runs the trinity fuzzer within it. Once in a while, it finds something which causes the guest to misbehave (oops/panic/etc). At that point, the guest hangs there waiting for me to come and do something about it. With this device, I could automate that procedure and possibly make this entire bug hunting process fully automatic.
Now, I'm aware that this use case is probably not too common out there, but since there is a patch which tries to do the but by creating a whole new guest-host interface skipping virtio (https://lkml.org/lkml/2012/7/21/14), I guess this is useful in the real world as well.
Regarding the log, there are many ways to have that right now (good old serial/virtio-serial/etc), the issue is that I want to be notified of critical guest events and grepping the log sounds like the wrong way.
The difference between physical and virtual guest in this regard is by how much useful data I can retrieve out of a problem guest rather easily, and by things which which can occur as a result of these events (for example, add some memory if OOMs are happening frequently - which is not possible on physical hardware).
> Guest watchdog functionality might be useful, but that's simpler to
> implement via a virtio watchdog device, and more effective to implement
> via a host facility that actually pings guest functionality (rather than
> the kernel).
I agree that this echo functionality doesn't really belong in the notifier and would probably work better as a separate virtio-watchdog. Would it make sense to split this code into a virtio-notifier and virtio-watchdog?
^ permalink raw reply
* Re: [RFC 0/2] virtio: provide a way for host to monitor critical events in the device
From: Sasha Levin @ 2012-07-24 12:26 UTC (permalink / raw)
To: Gleb Natapov
Cc: wency, kvm, mst, linux-kernel, virtualization, penberg, avi,
anthony
In-Reply-To: <20120724074434.GE26120@redhat.com>
On 07/24/2012 09:44 AM, Gleb Natapov wrote:
> On Mon, Jul 23, 2012 at 10:32:39PM +0200, Sasha Levin wrote:
>> As it was discussed recently, there's currently no way for the guest to notify
>> the host about panics. Further more, there's no reasonable way to notify the
>> host of other critical events such as an OOM kill.
>>
>> This short patch series introduces a new device named virtio-notifier which
>> does two simple things:
>>
>> 1. Provide a simple interface for the guest to notify the host of critical
> To get early OOPSes virtio will have to be compiled into the kernel. If
> your are so keen on using virtio for this though, why not just use
> dedicated virtio serial channel?
Let's separate between having log for these events and receiving notifications about them.
For the log part, I can already run a simple serial console to dump everything somewhere. I'm more concerned about having notifications about something critical happening when the guest is already up and running.
^ permalink raw reply
* Re: [RFC 0/2] virtio: provide a way for host to monitor critical events in the device
From: Gleb Natapov @ 2012-07-24 12:28 UTC (permalink / raw)
To: Sasha Levin
Cc: wency, kvm, mst, linux-kernel, virtualization, penberg, avi,
anthony
In-Reply-To: <500E9479.3050405@gmail.com>
On Tue, Jul 24, 2012 at 02:26:33PM +0200, Sasha Levin wrote:
> On 07/24/2012 09:44 AM, Gleb Natapov wrote:
> > On Mon, Jul 23, 2012 at 10:32:39PM +0200, Sasha Levin wrote:
> >> As it was discussed recently, there's currently no way for the guest to notify
> >> the host about panics. Further more, there's no reasonable way to notify the
> >> host of other critical events such as an OOM kill.
> >>
> >> This short patch series introduces a new device named virtio-notifier which
> >> does two simple things:
> >>
> >> 1. Provide a simple interface for the guest to notify the host of critical
> > To get early OOPSes virtio will have to be compiled into the kernel. If
> > your are so keen on using virtio for this though, why not just use
> > dedicated virtio serial channel?
>
> Let's separate between having log for these events and receiving notifications about them.
>
> For the log part, I can already run a simple serial console to dump everything somewhere. I'm more concerned about having notifications about something critical happening when the guest is already up and running.
>
I am talking about notifications. Run your notification protocol over
dedicated virtio-serial channel. Logs goes to virtio-console as you've
said.
--
Gleb.
^ permalink raw reply
* Re: [RFC 0/2] virtio: provide a way for host to monitor critical events in the device
From: Sasha Levin @ 2012-07-24 12:30 UTC (permalink / raw)
To: dlaor; +Cc: wency, kvm, mst, linux-kernel, virtualization, penberg, avi,
anthony
In-Reply-To: <500E5C36.2070601@redhat.com>
On 07/24/2012 10:26 AM, Dor Laor wrote:
> On 07/24/2012 07:55 AM, Rusty Russell wrote:
>> On Mon, 23 Jul 2012 22:32:39 +0200, Sasha Levin <levinsasha928@gmail.com> wrote:
>>> As it was discussed recently, there's currently no way for the guest to notify
>>> the host about panics. Further more, there's no reasonable way to notify the
>>> host of other critical events such as an OOM kill.
>>
>> I clearly missed the discussion. Is this actually useful? In practice,
>
> Admit this is not a killer feature..
>
>> won't you want the log from the guest? What makes a virtual guest
>> different from a physical guest?
>
> Most times virt guest can do better than a physical OS. In that sense, this is where virtualization shines (live migration, hotplug for any virtual resource including net/block/cpu/memory/..).
>
> There are plenty of niche but worth while small features such as the virtio-trace series and other that allow the host/virt-mgmt to get more insight into the guest w/o a need to configure the guest.
>
> In theory guest OOM can trigger a host memory hot plug action. Again, I don't see it as a key feature..
>
>>
>> Guest watchdog functionality might be useful, but that's simpler to
>
> There is already a fully emulated watchdog device in qemu.
There is, but why emulate physical devices when you can take advantage of virtio?
You could say the same about the rest of the virtio family - "There is already a fully emulated NIC device in qemu".
^ permalink raw reply
* Re: [RFC 0/2] virtio: provide a way for host to monitor critical events in the device
From: Sasha Levin @ 2012-07-24 12:31 UTC (permalink / raw)
To: Gleb Natapov
Cc: wency, kvm, mst, linux-kernel, virtualization, penberg, avi,
anthony
In-Reply-To: <20120724122824.GG26120@redhat.com>
On 07/24/2012 02:28 PM, Gleb Natapov wrote:
> On Tue, Jul 24, 2012 at 02:26:33PM +0200, Sasha Levin wrote:
>> On 07/24/2012 09:44 AM, Gleb Natapov wrote:
>>> On Mon, Jul 23, 2012 at 10:32:39PM +0200, Sasha Levin wrote:
>>>> As it was discussed recently, there's currently no way for the guest to notify
>>>> the host about panics. Further more, there's no reasonable way to notify the
>>>> host of other critical events such as an OOM kill.
>>>>
>>>> This short patch series introduces a new device named virtio-notifier which
>>>> does two simple things:
>>>>
>>>> 1. Provide a simple interface for the guest to notify the host of critical
>>> To get early OOPSes virtio will have to be compiled into the kernel. If
>>> your are so keen on using virtio for this though, why not just use
>>> dedicated virtio serial channel?
>>
>> Let's separate between having log for these events and receiving notifications about them.
>>
>> For the log part, I can already run a simple serial console to dump everything somewhere. I'm more concerned about having notifications about something critical happening when the guest is already up and running.
>>
> I am talking about notifications. Run your notification protocol over
> dedicated virtio-serial channel. Logs goes to virtio-console as you've
> said.
Ah, so just add another channel into virtio-serial to pass these notifications? Good idea - I'll look into it.
^ permalink raw reply
* Re: [RFC 0/2] virtio: provide a way for host to monitor critical events in the device
From: Gleb Natapov @ 2012-07-24 12:33 UTC (permalink / raw)
To: Sasha Levin
Cc: wency, kvm, mst, linux-kernel, virtualization, penberg, avi,
anthony
In-Reply-To: <500E959D.70009@gmail.com>
On Tue, Jul 24, 2012 at 02:31:25PM +0200, Sasha Levin wrote:
> On 07/24/2012 02:28 PM, Gleb Natapov wrote:
> > On Tue, Jul 24, 2012 at 02:26:33PM +0200, Sasha Levin wrote:
> >> On 07/24/2012 09:44 AM, Gleb Natapov wrote:
> >>> On Mon, Jul 23, 2012 at 10:32:39PM +0200, Sasha Levin wrote:
> >>>> As it was discussed recently, there's currently no way for the guest to notify
> >>>> the host about panics. Further more, there's no reasonable way to notify the
> >>>> host of other critical events such as an OOM kill.
> >>>>
> >>>> This short patch series introduces a new device named virtio-notifier which
> >>>> does two simple things:
> >>>>
> >>>> 1. Provide a simple interface for the guest to notify the host of critical
> >>> To get early OOPSes virtio will have to be compiled into the kernel. If
> >>> your are so keen on using virtio for this though, why not just use
> >>> dedicated virtio serial channel?
> >>
> >> Let's separate between having log for these events and receiving notifications about them.
> >>
> >> For the log part, I can already run a simple serial console to dump everything somewhere. I'm more concerned about having notifications about something critical happening when the guest is already up and running.
> >>
> > I am talking about notifications. Run your notification protocol over
> > dedicated virtio-serial channel. Logs goes to virtio-console as you've
> > said.
>
> Ah, so just add another channel into virtio-serial to pass these notifications? Good idea - I'll look into it.
>
Yes, that's what I mean. This solution still has the disadvantage of not
been able to catch early boot oopses without compiling the whole virtio
into a kernel image.
--
Gleb.
^ permalink raw reply
* Re: [RFC 0/2] virtio: provide a way for host to monitor critical events in the device
From: Dor Laor @ 2012-07-24 12:46 UTC (permalink / raw)
To: Sasha Levin
Cc: wency, kvm, mst, linux-kernel, virtualization, penberg, avi,
anthony
In-Reply-To: <500E954F.8090102@gmail.com>
On 07/24/2012 03:30 PM, Sasha Levin wrote:
> On 07/24/2012 10:26 AM, Dor Laor wrote:
>> On 07/24/2012 07:55 AM, Rusty Russell wrote:
>>> On Mon, 23 Jul 2012 22:32:39 +0200, Sasha Levin <levinsasha928@gmail.com> wrote:
>>>> As it was discussed recently, there's currently no way for the guest to notify
>>>> the host about panics. Further more, there's no reasonable way to notify the
>>>> host of other critical events such as an OOM kill.
>>>
>>> I clearly missed the discussion. Is this actually useful? In practice,
>>
>> Admit this is not a killer feature..
>>
>>> won't you want the log from the guest? What makes a virtual guest
>>> different from a physical guest?
>>
>> Most times virt guest can do better than a physical OS. In that sense, this is where virtualization shines (live migration, hotplug for any virtual resource including net/block/cpu/memory/..).
>>
>> There are plenty of niche but worth while small features such as the virtio-trace series and other that allow the host/virt-mgmt to get more insight into the guest w/o a need to configure the guest.
>>
>> In theory guest OOM can trigger a host memory hot plug action. Again, I don't see it as a key feature..
>>
>>>
>>> Guest watchdog functionality might be useful, but that's simpler to
>>
>> There is already a fully emulated watchdog device in qemu.
>
> There is, but why emulate physical devices when you can take advantage of virtio?
>
> You could say the same about the rest of the virtio family - "There is already a fully emulated NIC device in qemu".
The single issue virtio-nic solves is performance enhancements that can
be done w/ a fully emulated NIC. The reason is that such NIC tend to
access pio/mmio space a lot while virtio is designed for virtualization.
Standard watchdog device (isn't it time you'll try qemu?) isn't about
performance and if that's all the functionality you need it should work
fine.
btw: check the virtio-trace series that was just send in a parallel thread.
Cheers,
Dor
^ permalink raw reply
* Re: [RFC 0/2] virtio: provide a way for host to monitor critical events in the device
From: Sasha Levin @ 2012-07-24 13:01 UTC (permalink / raw)
To: dlaor; +Cc: wency, kvm, mst, linux-kernel, virtualization, penberg, avi,
anthony
In-Reply-To: <500E9942.3080505@redhat.com>
On 07/24/2012 02:46 PM, Dor Laor wrote:
> On 07/24/2012 03:30 PM, Sasha Levin wrote:
>> On 07/24/2012 10:26 AM, Dor Laor wrote:
>>> On 07/24/2012 07:55 AM, Rusty Russell wrote:
>>>> On Mon, 23 Jul 2012 22:32:39 +0200, Sasha Levin <levinsasha928@gmail.com> wrote:
>>>>> As it was discussed recently, there's currently no way for the guest to notify
>>>>> the host about panics. Further more, there's no reasonable way to notify the
>>>>> host of other critical events such as an OOM kill.
>>>>
>>>> I clearly missed the discussion. Is this actually useful? In practice,
>>>
>>> Admit this is not a killer feature..
>>>
>>>> won't you want the log from the guest? What makes a virtual guest
>>>> different from a physical guest?
>>>
>>> Most times virt guest can do better than a physical OS. In that sense, this is where virtualization shines (live migration, hotplug for any virtual resource including net/block/cpu/memory/..).
>>>
>>> There are plenty of niche but worth while small features such as the virtio-trace series and other that allow the host/virt-mgmt to get more insight into the guest w/o a need to configure the guest.
>>>
>>> In theory guest OOM can trigger a host memory hot plug action. Again, I don't see it as a key feature..
>>>
>>>>
>>>> Guest watchdog functionality might be useful, but that's simpler to
>>>
>>> There is already a fully emulated watchdog device in qemu.
>>
>> There is, but why emulate physical devices when you can take advantage of virtio?
>>
>> You could say the same about the rest of the virtio family - "There is already a fully emulated NIC device in qemu".
>
> The single issue virtio-nic solves is performance enhancements that can be done w/ a fully emulated NIC. The reason is that such NIC tend to access pio/mmio space a lot while virtio is designed for virtualization.
virtio on it's own was introduced to help solve the fragmentation around virtualized devices, so I don't think that the main purpose of doing virtio drivers is due to any performance benefits virtio may provide.
Also consider virtio devices which don't exactly have strict performance considerations such as virtio-9p or virtio-rng.
I mean, why implement virtio-rng when qemu could just emulate some sort of a hardware RNG and just grab randomness from the host?
> Standard watchdog device (isn't it time you'll try qemu?) isn't about performance and if that's all the functionality you need it should work fine.
Don't understand me wrong, I'm not saying that there's something with the watchdog driver in qemu. All I want is to write a watchdog driver for lkvm which can take advantage of the fact it runs within a guest.
> btw: check the virtio-trace series that was just send in a parallel thread.
Will do!
> Cheers,
> Dor
>
>
>
^ permalink raw reply
* Re: Re: [RFC PATCH 0/6] virtio-trace: Support virtio-trace
From: Stefan Hajnoczi @ 2012-07-24 13:41 UTC (permalink / raw)
To: Yoshihiro YUNOMAE
Cc: Herbert Xu, Arnd Bergmann, Greg Kroah-Hartman,
Frederic Weisbecker, Dhaval Giani, linux-kernel, Borislav Petkov,
qemu-devel, Amit Shah, Franch Ch. Eigler, Ingo Molnar,
Mathieu Desnoyers, Steven Rostedt, Anthony Liguori,
yrl.pp-manager.tt, Masami Hiramatsu, virtualization,
Srikar Dronamraju
In-Reply-To: <500E84D7.7060103@hitachi.com>
On Tue, Jul 24, 2012 at 12:19 PM, Yoshihiro YUNOMAE
<yoshihiro.yunomae.ez@hitachi.com> wrote:
>>> Are you using text formatted ftrace?
> No, currently using raw format, but we'd like to reformat it in text.
Capturing the info necessary to translate numbers into symbols is one
of the problems of host<->guest tracing so I'm curious how you handle
this :).
Apologies for my lack of ftrace knowledge but how useful is the raw
tracing data on the host? How do you pretty-print it in
human-readable form?
Stefan
_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization
^ permalink raw reply
* Re: Re: [RFC PATCH 0/6] virtio-trace: Support virtio-trace
From: Stefan Hajnoczi @ 2012-07-24 13:43 UTC (permalink / raw)
To: Masami Hiramatsu
Cc: Herbert Xu, Arnd Bergmann, Greg Kroah-Hartman,
Frederic Weisbecker, Dhaval Giani, linux-kernel, Borislav Petkov,
qemu-devel, Franch Ch. Eigler, Ingo Molnar, Mathieu Desnoyers,
Steven Rostedt, Anthony Liguori, yrl.pp-manager.tt, Amit Shah,
virtualization, Srikar Dronamraju
In-Reply-To: <500E810A.4030309@hitachi.com>
On Tue, Jul 24, 2012 at 12:03 PM, Masami Hiramatsu
<masami.hiramatsu.pt@hitachi.com> wrote:
> (2012/07/24 19:02), Stefan Hajnoczi wrote:
>> On Tue, Jul 24, 2012 at 3:36 AM, Yoshihiro YUNOMAE
>> <yoshihiro.yunomae.ez@hitachi.com> wrote:
>>> The performance of each method is compared as follows:
>>> [1] Native
>>> - only recording trace data to ring-buffer on a guest
>>> [2] Virtio-trace
>>> - running a trace agent on a guest
>>> - a reader on a host opens FIFO using cat command
>>> [3] IVRing
>>> - A SystemTap script in a guest records trace data to IVRing.
>>> -- probe points are same as ftrace.
>>> [4] Virtio-serial(normal)
>>> - A reader(using cat) on a guest output trace data to a host using
>>> standard output via virtio-serial.
>>
>> The first time I read this I thought you are adding a new virtio-trace
>> device. But it looks like this series really add splice support to
>> virtio-console and that yields a big performance improvement when
>> sending trace_pipe_raw.
>
> Yes, sorry for the confusion. Actually this is an enhancement of
> virtio-serial. I'm working with Yoshihiro on this feature.
>
>> Guest ftrace is useful and I like this. Have you thought about
>> controlling ftrace from the host? Perhaps a command could be added to
>> the QEMU guest agent which basically invokes trace-cmd/perf.
>
> As you can see, guest trace-agent can be controlled via a
> control channel. In our scenario, host tools can control that
> instead of guest one.
>
> We are considering that exporting the tracing part of guest's
> debugfs to host via another virtio-serial channel by using
> 9pfs, so that the host tools can refer that.
>
> (In this scenario, guest trace-agent will also provide 9pfs server.
> Since it means that the agent can handle writing a special file,
> trace-agent can be controlled via the special file on exported
> debugfs.)
>
> Of course, this also requires modifying trace-cmd/perf to accept
> some options like guest-debugfs mount point, guest's serial
> channel pipe (or unix socket?), etc. However, it will be a small
> change.
Okay, thanks for explaining some of the ideas you have. I won't ask
more because it's out of scope for this patch series :).
Stefan
^ permalink raw reply
* Re: [PATCH 00/17] drivers: hv: kvp
From: Greg KH @ 2012-07-24 15:54 UTC (permalink / raw)
To: K. Y. Srinivasan
Cc: linux-kernel, devel, virtualization, olaf, apw, netdev, ben
In-Reply-To: <1343145672-3641-1-git-send-email-kys@microsoft.com>
On Tue, Jul 24, 2012 at 09:01:12AM -0700, K. Y. Srinivasan wrote:
> This patchset expands the KVP (Key Value Pair) functionality to
> implement the mechanism to GET/SET IP addresses in the guest. This
> functionality is used in Windows Server 2012 to implement VM
> replication functionality. The way IP configuration information
> is managed is distro specific. Based on the feedback I have gotten
> from Olaf, Greg, Steve, Ben and Mairus, I have chosen to seperate
> distro specific code from this patch-set. Most of the GET operation
> can be implemented in a way that is completely distro independent and
> I have implemented that as such and is included in this patch-set.
> Some of the attributes that can only be fetched in a distro
> dependent way as well the mechanism for configuring an interface
> (the SET operation) that is clearly distro specific is to be
> implemented via external scripts that will be invoked via the KVP
> code. We define here the interface to these scripts.
>
> Adding support for IP injection resulted in some changes to the
> protocol between the user level daemon and the kernel driver.
> These changes have been implemented in way that would retain
> compatibility with older daemons. I would like to thank Olaf and
> Greg for pointing out the compatibility issue.
Due to this being the middle of the merge window, I will not be able to
look at this until after 3.6-rc1 is out.
greg k-h
^ permalink raw reply
* Re: [PATCH 09/17] Tools: hv: Represent the ipv6 mask using CIDR notation
From: Borislav Petkov @ 2012-07-24 16:01 UTC (permalink / raw)
To: K. Y. Srinivasan
Cc: gregkh, linux-kernel, devel, virtualization, olaf, apw, netdev,
ben
In-Reply-To: <1343145701-3691-9-git-send-email-kys@microsoft.com>
On Tue, Jul 24, 2012 at 09:01:33AM -0700, K. Y. Srinivasan wrote:
> Transform ipv6 subnet information to CIDR notation.
>
> Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
> Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
> ---
> tools/hv/hv_kvp_daemon.c | 45 +++++++++++++++++++++++++++++++++++----------
> 1 files changed, 35 insertions(+), 10 deletions(-)
>
> diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c
> index 2c24ebf..007e698 100644
> --- a/tools/hv/hv_kvp_daemon.c
> +++ b/tools/hv/hv_kvp_daemon.c
> @@ -491,6 +491,15 @@ done:
> return;
> }
>
> +static unsigned int hweight32(unsigned int *w)
> +{
> + unsigned int res = *w - ((*w >> 1) & 0x55555555);
> + res = (res & 0x33333333) + ((res >> 2) & 0x33333333);
> + res = (res + (res >> 4)) & 0x0F0F0F0F;
> + res = res + (res >> 8);
> + return (res + (res >> 16)) & 0x000000FF;
> +}
What's wrong with the hweight32 version we have already in
<include/asm-generic/bitops/const_hweight.h> which you can include by
simply by including <asm-generic/bitops.h>?
--
Regards/Gruss,
Boris.
^ permalink raw reply
* [PATCH 00/17] drivers: hv: kvp
From: K. Y. Srinivasan @ 2012-07-24 16:01 UTC (permalink / raw)
To: gregkh, linux-kernel, devel, virtualization, olaf, apw, netdev,
ben
Cc: K. Y. Srinivasan
This patchset expands the KVP (Key Value Pair) functionality to
implement the mechanism to GET/SET IP addresses in the guest. This
functionality is used in Windows Server 2012 to implement VM
replication functionality. The way IP configuration information
is managed is distro specific. Based on the feedback I have gotten
from Olaf, Greg, Steve, Ben and Mairus, I have chosen to seperate
distro specific code from this patch-set. Most of the GET operation
can be implemented in a way that is completely distro independent and
I have implemented that as such and is included in this patch-set.
Some of the attributes that can only be fetched in a distro
dependent way as well the mechanism for configuring an interface
(the SET operation) that is clearly distro specific is to be
implemented via external scripts that will be invoked via the KVP
code. We define here the interface to these scripts.
Adding support for IP injection resulted in some changes to the
protocol between the user level daemon and the kernel driver.
These changes have been implemented in way that would retain
compatibility with older daemons. I would like to thank Olaf and
Greg for pointing out the compatibility issue.
K. Y. Srinivasan (17):
Drivers: hv: vmbus: Use the standard format string to format GUIDs
Drivers: hv: Add KVP definitions for IP address injection
Drivers: hv: kvp: Cleanup error handling in KVP
Drivers: hv: kvp: Support the new IP injection messages
Tools: hv: Prepare to expand kvp_get_ip_address() functionality
Tools: hv: Further refactor kvp_get_ip_address()
Tools: hv: Gather address family information
Tools: hv: Gather subnet information
Tools: hv: Represent the ipv6 mask using CIDR notation
Tools: hv: Gather ipv[4,6] gateway information
Tools: hv: Gather DNS information
Tools: hv: Gather DHCP information
Tools: hv: Implement the KVP verb - KVP_OP_SET_IP_INFO
Tools: hv: Rename the function kvp_get_ip_address()
Tools: hv: Implement the KVP verb - KVP_OP_GET_IP_INFO
Tools: hv: Get rid of some unused variables
Tools: hv: Correctly type string variables
drivers/hv/hv_kvp.c | 251 +++++++++++--
drivers/hv/hv_util.c | 4 +-
drivers/hv/vmbus_drv.c | 38 +--
include/linux/hyperv.h | 88 ++++-
tools/hv/hv_kvp_daemon.c | 943 +++++++++++++++++++++++++++++++++++++++++-----
5 files changed, 1160 insertions(+), 164 deletions(-)
--
1.7.4.1
^ permalink raw reply
* [PATCH 01/17] Drivers: hv: vmbus: Use the standard format string to format GUIDs
From: K. Y. Srinivasan @ 2012-07-24 16:01 UTC (permalink / raw)
To: gregkh, linux-kernel, devel, virtualization, olaf, apw, netdev,
ben
Cc: K. Y. Srinivasan
In-Reply-To: <1343145672-3641-1-git-send-email-kys@microsoft.com>
Format GUIDS as per MSFT standard. This makes interacting with MSFT
tool stack easier.
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
---
drivers/hv/vmbus_drv.c | 38 ++------------------------------------
1 files changed, 2 insertions(+), 36 deletions(-)
diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
index 4748086..b76e8b3 100644
--- a/drivers/hv/vmbus_drv.c
+++ b/drivers/hv/vmbus_drv.c
@@ -146,43 +146,9 @@ static ssize_t vmbus_show_device_attr(struct device *dev,
get_channel_info(hv_dev, device_info);
if (!strcmp(dev_attr->attr.name, "class_id")) {
- ret = sprintf(buf, "{%02x%02x%02x%02x-%02x%02x-%02x%02x-"
- "%02x%02x%02x%02x%02x%02x%02x%02x}\n",
- device_info->chn_type.b[3],
- device_info->chn_type.b[2],
- device_info->chn_type.b[1],
- device_info->chn_type.b[0],
- device_info->chn_type.b[5],
- device_info->chn_type.b[4],
- device_info->chn_type.b[7],
- device_info->chn_type.b[6],
- device_info->chn_type.b[8],
- device_info->chn_type.b[9],
- device_info->chn_type.b[10],
- device_info->chn_type.b[11],
- device_info->chn_type.b[12],
- device_info->chn_type.b[13],
- device_info->chn_type.b[14],
- device_info->chn_type.b[15]);
+ ret = sprintf(buf, "{%pUl}\n", device_info->chn_type.b);
} else if (!strcmp(dev_attr->attr.name, "device_id")) {
- ret = sprintf(buf, "{%02x%02x%02x%02x-%02x%02x-%02x%02x-"
- "%02x%02x%02x%02x%02x%02x%02x%02x}\n",
- device_info->chn_instance.b[3],
- device_info->chn_instance.b[2],
- device_info->chn_instance.b[1],
- device_info->chn_instance.b[0],
- device_info->chn_instance.b[5],
- device_info->chn_instance.b[4],
- device_info->chn_instance.b[7],
- device_info->chn_instance.b[6],
- device_info->chn_instance.b[8],
- device_info->chn_instance.b[9],
- device_info->chn_instance.b[10],
- device_info->chn_instance.b[11],
- device_info->chn_instance.b[12],
- device_info->chn_instance.b[13],
- device_info->chn_instance.b[14],
- device_info->chn_instance.b[15]);
+ ret = sprintf(buf, "{%pUl}\n", device_info->chn_instance.b);
} else if (!strcmp(dev_attr->attr.name, "modalias")) {
print_alias_name(hv_dev, alias_name);
ret = sprintf(buf, "vmbus:%s\n", alias_name);
--
1.7.4.1
^ permalink raw reply related
* [PATCH 02/17] Drivers: hv: Add KVP definitions for IP address injection
From: K. Y. Srinivasan @ 2012-07-24 16:01 UTC (permalink / raw)
To: gregkh, linux-kernel, devel, virtualization, olaf, apw, netdev,
ben
Cc: K. Y. Srinivasan
In-Reply-To: <1343145701-3691-1-git-send-email-kys@microsoft.com>
Add the necessary definitions for supporting the IP injection functionality.
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
---
drivers/hv/hv_util.c | 4 +-
include/linux/hyperv.h | 71 +++++++++++++++++++++++++++++++++++++++++++++-
tools/hv/hv_kvp_daemon.c | 2 +-
3 files changed, 73 insertions(+), 4 deletions(-)
diff --git a/drivers/hv/hv_util.c b/drivers/hv/hv_util.c
index d3ac6a4..a0667de 100644
--- a/drivers/hv/hv_util.c
+++ b/drivers/hv/hv_util.c
@@ -263,7 +263,7 @@ static int util_probe(struct hv_device *dev,
(struct hv_util_service *)dev_id->driver_data;
int ret;
- srv->recv_buffer = kmalloc(PAGE_SIZE, GFP_KERNEL);
+ srv->recv_buffer = kmalloc(PAGE_SIZE * 2, GFP_KERNEL);
if (!srv->recv_buffer)
return -ENOMEM;
if (srv->util_init) {
@@ -274,7 +274,7 @@ static int util_probe(struct hv_device *dev,
}
}
- ret = vmbus_open(dev->channel, 2 * PAGE_SIZE, 2 * PAGE_SIZE, NULL, 0,
+ ret = vmbus_open(dev->channel, 4 * PAGE_SIZE, 4 * PAGE_SIZE, NULL, 0,
srv->util_cb, dev->channel);
if (ret)
goto error;
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
index 68ed7f7..3c56ca7 100644
--- a/include/linux/hyperv.h
+++ b/include/linux/hyperv.h
@@ -122,12 +122,53 @@
#define REG_U32 4
#define REG_U64 8
+/*
+ * As we look at expanding the KVP functionality to include
+ * IP injection functionality, we need to maintain binary
+ * compatibility with older daemons.
+ *
+ * The KVP opcodes are defined by the host and it was unfortunate
+ * that I chose to treat the registration operation as part of the
+ * KVP operations defined by the host.
+ * Here is the level of compatibility
+ * (between the user level daemon and the kernel KVP driver) that we
+ * will implement:
+ *
+ * An older daemon will always be supported on a newer driver.
+ * A given user level daemon will require a minimal version of the
+ * kernel driver.
+ * If we cannot handle the version differences, we will fail gracefully
+ * (this can happen when we have a user level daemon that is more
+ * advanced than the KVP driver.
+ *
+ * We will use values used in this handshake for determining if we have
+ * workable user level daemon and the kernel driver. We begin by taking the
+ * registration opcode out of the KVP opcode namespace. We will however,
+ * maintain compatibility with the existing user-level daemon code.
+ */
+
+/*
+ * Daemon code not supporting IP injection (legacy daemon).
+ */
+
+#define KVP_OP_REGISTER 4
+
+/*
+ * Daemon code supporting IP injection.
+ * The KVP opcode field is used to communicate the
+ * registration information; so define a namespace that
+ * will be distinct from the host defined KVP opcode.
+ */
+
+#define KVP_OP_REGISTER1 100
+
enum hv_kvp_exchg_op {
KVP_OP_GET = 0,
KVP_OP_SET,
KVP_OP_DELETE,
KVP_OP_ENUMERATE,
- KVP_OP_REGISTER,
+ KVP_OP_GET_IP_INFO,
+ KVP_OP_SET_IP_INFO,
KVP_OP_COUNT /* Number of operations, must be last. */
};
@@ -140,6 +181,26 @@ enum hv_kvp_exchg_pool {
KVP_POOL_COUNT /* Number of pools, must be last. */
};
+#define ADDR_FAMILY_NONE 0x00
+#define ADDR_FAMILY_IPV4 0x01
+#define ADDR_FAMILY_IPV6 0x02
+
+#define MAX_ADAPTER_ID_SIZE 128
+#define MAX_IP_ADDR_SIZE 1024
+#define MAX_GATEWAY_SIZE 512
+
+
+struct hv_kvp_ipaddr_value {
+ __u16 adapter_id[MAX_ADAPTER_ID_SIZE];
+ __u8 addr_family;
+ __u8 dhcp_enabled;
+ __u16 ip_addr[MAX_IP_ADDR_SIZE];
+ __u16 sub_net[MAX_IP_ADDR_SIZE];
+ __u16 gate_way[MAX_GATEWAY_SIZE];
+ __u16 dns_addr[MAX_IP_ADDR_SIZE];
+} __attribute__((packed));
+
+
struct hv_kvp_hdr {
__u8 operation;
__u8 pool;
@@ -187,10 +248,17 @@ struct hv_kvp_msg {
struct hv_kvp_msg_set kvp_set;
struct hv_kvp_msg_delete kvp_delete;
struct hv_kvp_msg_enumerate kvp_enum_data;
+ struct hv_kvp_ipaddr_value kvp_ip_val;
struct hv_kvp_register kvp_register;
} body;
} __attribute__((packed));
+struct hv_kvp_ip_msg {
+ __u8 operation;
+ __u8 pool;
+ struct hv_kvp_ipaddr_value kvp_ip_val;
+} __attribute__((packed));
+
#ifdef __KERNEL__
#include <linux/scatterlist.h>
#include <linux/list.h>
@@ -982,6 +1050,7 @@ void vmbus_driver_unregister(struct hv_driver *hv_driver);
#define HV_S_CONT 0x80070103
#define HV_ERROR_NOT_SUPPORTED 0x80070032
#define HV_ERROR_MACHINE_LOCKED 0x800704F7
+#define HV_ERROR_DEVICE_NOT_CONNECTED 0x8007048F
/*
* While we want to handle util services as regular devices,
diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c
index d9834b3..8fbcf7b 100644
--- a/tools/hv/hv_kvp_daemon.c
+++ b/tools/hv/hv_kvp_daemon.c
@@ -69,7 +69,7 @@ enum key_index {
};
static char kvp_send_buffer[4096];
-static char kvp_recv_buffer[4096];
+static char kvp_recv_buffer[4096 * 2];
static struct sockaddr_nl addr;
static char *os_name = "";
--
1.7.4.1
^ permalink raw reply related
* [PATCH 03/17] Drivers: hv: kvp: Cleanup error handling in KVP
From: K. Y. Srinivasan @ 2012-07-24 16:01 UTC (permalink / raw)
To: gregkh, linux-kernel, devel, virtualization, olaf, apw, netdev,
ben
In-Reply-To: <1343145701-3691-1-git-send-email-kys@microsoft.com>
In preparation to implementing IP injection, cleanup the way we propagate
and handle errors both in the driver as well as in the user level daemon.
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
---
drivers/hv/hv_kvp.c | 112 +++++++++++++++++++++++++++++++++++++---------
include/linux/hyperv.h | 17 +++++---
tools/hv/hv_kvp_daemon.c | 70 +++++++++++++++-------------
3 files changed, 138 insertions(+), 61 deletions(-)
diff --git a/drivers/hv/hv_kvp.c b/drivers/hv/hv_kvp.c
index 0012eed..9b7fc4a 100644
--- a/drivers/hv/hv_kvp.c
+++ b/drivers/hv/hv_kvp.c
@@ -48,13 +48,24 @@ static struct {
void *kvp_context; /* for the channel callback */
} kvp_transaction;
+/*
+ * Before we can accept KVP messages from the host, we need
+ * to handshake with the user level daemon. This state tarcks
+ * if we are in the handshake phase.
+ */
+static bool in_hand_shake = true;
+
+/*
+ * This state maintains the version number registered by the daemon.
+ */
+static int dm_reg_value;
+
static void kvp_send_key(struct work_struct *dummy);
-#define TIMEOUT_FIRED 1
static void kvp_respond_to_host(char *key, char *value, int error);
static void kvp_work_func(struct work_struct *dummy);
-static void kvp_register(void);
+static void kvp_register(int);
static DECLARE_DELAYED_WORK(kvp_work, kvp_work_func);
static DECLARE_WORK(kvp_sendkey_work, kvp_send_key);
@@ -68,7 +79,7 @@ static u8 *recv_buffer;
*/
static void
-kvp_register(void)
+kvp_register(int reg_value)
{
struct cn_msg *msg;
@@ -83,7 +94,7 @@ kvp_register(void)
msg->id.idx = CN_KVP_IDX;
msg->id.val = CN_KVP_VAL;
- kvp_msg->kvp_hdr.operation = KVP_OP_REGISTER;
+ kvp_msg->kvp_hdr.operation = reg_value;
strcpy(version, HV_DRV_VERSION);
msg->len = sizeof(struct hv_kvp_msg);
cn_netlink_send(msg, 0, GFP_ATOMIC);
@@ -97,9 +108,43 @@ kvp_work_func(struct work_struct *dummy)
* If the timer fires, the user-mode component has not responded;
* process the pending transaction.
*/
- kvp_respond_to_host("Unknown key", "Guest timed out", TIMEOUT_FIRED);
+ kvp_respond_to_host("Unknown key", "Guest timed out", HV_E_FAIL);
+}
+
+static int kvp_handle_handshake(struct hv_kvp_msg *msg)
+{
+ int ret = 1;
+
+ switch (msg->kvp_hdr.operation) {
+ case KVP_OP_REGISTER:
+ dm_reg_value = KVP_OP_REGISTER;
+ pr_info("KVP: IP injection functionality not available\n");
+ pr_info("KVP: Upgrade the KVP daemon\n");
+ break;
+ case KVP_OP_REGISTER1:
+ dm_reg_value = KVP_OP_REGISTER1;
+ break;
+ default:
+ pr_info("KVP: incompatible daemon\n");
+ pr_info("KVP: KVP version: %d, Daemon version: %d\n",
+ KVP_OP_REGISTER1, msg->kvp_hdr.operation);
+ ret = 0;
+ }
+
+ if (ret) {
+ /*
+ * We have a compatible daemon; complete the handshake.
+ */
+ pr_info("KVP: user-mode registering done.\n");
+ kvp_register(dm_reg_value);
+ kvp_transaction.active = false;
+ if (kvp_transaction.kvp_context)
+ hv_kvp_onchannelcallback(kvp_transaction.kvp_context);
+ }
+ return ret;
}
+
/*
* Callback when data is received from user mode.
*/
@@ -109,27 +154,52 @@ kvp_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
{
struct hv_kvp_msg *message;
struct hv_kvp_msg_enumerate *data;
+ int error = 0;
message = (struct hv_kvp_msg *)msg->data;
- switch (message->kvp_hdr.operation) {
+
+ /*
+ * If we are negotiating the version information
+ * with the daemon; handle that first.
+ */
+
+ if (in_hand_shake) {
+ if (kvp_handle_handshake(message))
+ in_hand_shake = false;
+ return;
+ }
+
+ /*
+ * Based on the version of the daemon, we propagate errors from the
+ * daemon differently.
+ */
+
+ data = &message->body.kvp_enum_data;
+
+ switch (dm_reg_value) {
case KVP_OP_REGISTER:
- pr_info("KVP: user-mode registering done.\n");
- kvp_register();
- kvp_transaction.active = false;
- hv_kvp_onchannelcallback(kvp_transaction.kvp_context);
+ /*
+ * Null string is used to pass back error condition.
+ */
+ if (!strlen(data->data.key))
+ error = HV_S_CONT;
break;
- default:
- data = &message->body.kvp_enum_data;
+ case KVP_OP_REGISTER1:
/*
- * Complete the transaction by forwarding the key value
- * to the host. But first, cancel the timeout.
+ * We use the message header information from
+ * the user level daemon to transmit errors.
*/
- if (cancel_delayed_work_sync(&kvp_work))
- kvp_respond_to_host(data->data.key,
- data->data.value,
- !strlen(data->data.key));
+ error = *((int *)(&message->kvp_hdr.operation));
+ break;
}
+
+ /*
+ * Complete the transaction by forwarding the key value
+ * to the host. But first, cancel the timeout.
+ */
+ if (cancel_delayed_work_sync(&kvp_work))
+ kvp_respond_to_host(data->data.key, data->data.value, error);
}
static void
@@ -287,6 +357,7 @@ kvp_respond_to_host(char *key, char *value, int error)
*/
return;
+ icmsghdrp->status = error;
/*
* If the error parameter is set, terminate the host's enumeration
@@ -294,15 +365,12 @@ kvp_respond_to_host(char *key, char *value, int error)
*/
if (error) {
/*
- * Something failed or the we have timedout;
+ * Something failed or we have timedout;
* terminate the current host-side iteration.
*/
- icmsghdrp->status = HV_S_CONT;
goto response_done;
}
- icmsghdrp->status = HV_S_OK;
-
kvp_msg = (struct hv_kvp_msg *)
&recv_buffer[sizeof(struct vmbuspipe_hdr) +
sizeof(struct icmsg_hdr)];
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
index 3c56ca7..5552443 100644
--- a/include/linux/hyperv.h
+++ b/include/linux/hyperv.h
@@ -181,6 +181,17 @@ enum hv_kvp_exchg_pool {
KVP_POOL_COUNT /* Number of pools, must be last. */
};
+/*
+ * Some Hyper-V status codes.
+ */
+
+#define HV_S_OK 0x00000000
+#define HV_E_FAIL 0x80004005
+#define HV_S_CONT 0x80070103
+#define HV_ERROR_NOT_SUPPORTED 0x80070032
+#define HV_ERROR_MACHINE_LOCKED 0x800704F7
+#define HV_ERROR_DEVICE_NOT_CONNECTED 0x8007048F
+
#define ADDR_FAMILY_NONE 0x00
#define ADDR_FAMILY_IPV4 0x01
#define ADDR_FAMILY_IPV6 0x02
@@ -1045,12 +1056,6 @@ void vmbus_driver_unregister(struct hv_driver *hv_driver);
#define ICMSGHDRFLAG_REQUEST 2
#define ICMSGHDRFLAG_RESPONSE 4
-#define HV_S_OK 0x00000000
-#define HV_E_FAIL 0x80004005
-#define HV_S_CONT 0x80070103
-#define HV_ERROR_NOT_SUPPORTED 0x80070032
-#define HV_ERROR_MACHINE_LOCKED 0x800704F7
-#define HV_ERROR_DEVICE_NOT_CONNECTED 0x8007048F
/*
* While we want to handle util services as regular devices,
diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c
index 8fbcf7b..72f5fd3 100644
--- a/tools/hv/hv_kvp_daemon.c
+++ b/tools/hv/hv_kvp_daemon.c
@@ -71,13 +71,14 @@ enum key_index {
static char kvp_send_buffer[4096];
static char kvp_recv_buffer[4096 * 2];
static struct sockaddr_nl addr;
+static int in_hand_shake = 1;
static char *os_name = "";
static char *os_major = "";
static char *os_minor = "";
static char *processor_arch;
static char *os_build;
-static char *lic_version;
+static char *lic_version = "Unknown version";
static struct utsname uts_buf;
@@ -394,7 +395,7 @@ static int kvp_get_value(int pool, __u8 *key, int key_size, __u8 *value,
return 1;
}
-static void kvp_pool_enumerate(int pool, int index, __u8 *key, int key_size,
+static int kvp_pool_enumerate(int pool, int index, __u8 *key, int key_size,
__u8 *value, int value_size)
{
struct kvp_record *record;
@@ -406,16 +407,12 @@ static void kvp_pool_enumerate(int pool, int index, __u8 *key, int key_size,
record = kvp_file_info[pool].records;
if (index >= kvp_file_info[pool].num_records) {
- /*
- * This is an invalid index; terminate enumeration;
- * - a NULL value will do the trick.
- */
- strcpy(value, "");
- return;
+ return 1;
}
memcpy(key, record[index].key, key_size);
memcpy(value, record[index].value, value_size);
+ return 0;
}
@@ -646,6 +643,8 @@ int main(void)
char *p;
char *key_value;
char *key_name;
+ int op;
+ int pool;
daemon(1, 0);
openlog("KVP", 0, LOG_USER);
@@ -687,7 +686,7 @@ int main(void)
message->id.val = CN_KVP_VAL;
hv_msg = (struct hv_kvp_msg *)message->data;
- hv_msg->kvp_hdr.operation = KVP_OP_REGISTER;
+ hv_msg->kvp_hdr.operation = KVP_OP_REGISTER1;
message->ack = 0;
message->len = sizeof(struct hv_kvp_msg);
@@ -721,12 +720,21 @@ int main(void)
incoming_cn_msg = (struct cn_msg *)NLMSG_DATA(incoming_msg);
hv_msg = (struct hv_kvp_msg *)incoming_cn_msg->data;
- switch (hv_msg->kvp_hdr.operation) {
- case KVP_OP_REGISTER:
+ /*
+ * We will use the KVP header information to pass back
+ * the error from this daemon. So, first copy the state
+ * and set the error code to success.
+ */
+ op = hv_msg->kvp_hdr.operation;
+ pool = hv_msg->kvp_hdr.pool;
+ *((int *)(&hv_msg->kvp_hdr.operation)) = HV_S_OK;
+
+ if ((in_hand_shake) && (op == KVP_OP_REGISTER1)) {
/*
* Driver is registering with us; stash away the version
* information.
*/
+ in_hand_shake = 0;
p = (char *)hv_msg->body.kvp_register.version;
lic_version = malloc(strlen(p) + 1);
if (lic_version) {
@@ -737,44 +745,42 @@ int main(void)
syslog(LOG_ERR, "malloc failed");
}
continue;
+ }
- /*
- * The current protocol with the kernel component uses a
- * NULL key name to pass an error condition.
- * For the SET, GET and DELETE operations,
- * use the existing protocol to pass back error.
- */
-
+ switch (op) {
case KVP_OP_SET:
- if (kvp_key_add_or_modify(hv_msg->kvp_hdr.pool,
+ if (kvp_key_add_or_modify(pool,
hv_msg->body.kvp_set.data.key,
hv_msg->body.kvp_set.data.key_size,
hv_msg->body.kvp_set.data.value,
hv_msg->body.kvp_set.data.value_size))
- strcpy(hv_msg->body.kvp_set.data.key, "");
+ *((int *)(&hv_msg->kvp_hdr.operation)) =
+ HV_S_CONT;
break;
case KVP_OP_GET:
- if (kvp_get_value(hv_msg->kvp_hdr.pool,
+ if (kvp_get_value(pool,
hv_msg->body.kvp_set.data.key,
hv_msg->body.kvp_set.data.key_size,
hv_msg->body.kvp_set.data.value,
hv_msg->body.kvp_set.data.value_size))
- strcpy(hv_msg->body.kvp_set.data.key, "");
+ *((int *)(&hv_msg->kvp_hdr.operation)) =
+ HV_S_CONT;
break;
case KVP_OP_DELETE:
- if (kvp_key_delete(hv_msg->kvp_hdr.pool,
+ if (kvp_key_delete(pool,
hv_msg->body.kvp_delete.key,
hv_msg->body.kvp_delete.key_size))
- strcpy(hv_msg->body.kvp_delete.key, "");
+ *((int *)(&hv_msg->kvp_hdr.operation)) =
+ HV_S_CONT;
break;
default:
break;
}
- if (hv_msg->kvp_hdr.operation != KVP_OP_ENUMERATE)
+ if (op != KVP_OP_ENUMERATE)
goto kvp_done;
/*
@@ -782,13 +788,15 @@ int main(void)
* both the key and the value; if not read from the
* appropriate pool.
*/
- if (hv_msg->kvp_hdr.pool != KVP_POOL_AUTO) {
- kvp_pool_enumerate(hv_msg->kvp_hdr.pool,
+ if (pool != KVP_POOL_AUTO) {
+ if (kvp_pool_enumerate(pool,
hv_msg->body.kvp_enum_data.index,
hv_msg->body.kvp_enum_data.data.key,
HV_KVP_EXCHANGE_MAX_KEY_SIZE,
hv_msg->body.kvp_enum_data.data.value,
- HV_KVP_EXCHANGE_MAX_VALUE_SIZE);
+ HV_KVP_EXCHANGE_MAX_VALUE_SIZE))
+ *((int *)(&hv_msg->kvp_hdr.operation)) =
+ HV_S_CONT;
goto kvp_done;
}
@@ -841,11 +849,7 @@ int main(void)
strcpy(key_name, "ProcessorArchitecture");
break;
default:
- strcpy(key_value, "Unknown Key");
- /*
- * We use a null key name to terminate enumeration.
- */
- strcpy(key_name, "");
+ *((int *)(&hv_msg->kvp_hdr.operation)) = HV_S_CONT;
break;
}
/*
--
1.7.4.1
^ permalink raw reply related
* [PATCH 04/17] Drivers: hv: kvp: Support the new IP injection messages
From: K. Y. Srinivasan @ 2012-07-24 16:01 UTC (permalink / raw)
To: gregkh, linux-kernel, devel, virtualization, olaf, apw, netdev,
ben
Cc: K. Y. Srinivasan
In-Reply-To: <1343145701-3691-1-git-send-email-kys@microsoft.com>
Implement support for the new IP injection messages in the driver code.
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>
---
drivers/hv/hv_kvp.c | 143 ++++++++++++++++++++++++++++++++++++++++++++++++--
1 files changed, 137 insertions(+), 6 deletions(-)
diff --git a/drivers/hv/hv_kvp.c b/drivers/hv/hv_kvp.c
index 9b7fc4a..83e16ea 100644
--- a/drivers/hv/hv_kvp.c
+++ b/drivers/hv/hv_kvp.c
@@ -63,7 +63,7 @@ static int dm_reg_value;
static void kvp_send_key(struct work_struct *dummy);
-static void kvp_respond_to_host(char *key, char *value, int error);
+static void kvp_respond_to_host(struct hv_kvp_msg *msg, int error);
static void kvp_work_func(struct work_struct *dummy);
static void kvp_register(int);
@@ -108,7 +108,7 @@ kvp_work_func(struct work_struct *dummy)
* If the timer fires, the user-mode component has not responded;
* process the pending transaction.
*/
- kvp_respond_to_host("Unknown key", "Guest timed out", HV_E_FAIL);
+ kvp_respond_to_host(NULL, HV_E_FAIL);
}
static int kvp_handle_handshake(struct hv_kvp_msg *msg)
@@ -199,9 +199,120 @@ kvp_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
* to the host. But first, cancel the timeout.
*/
if (cancel_delayed_work_sync(&kvp_work))
- kvp_respond_to_host(data->data.key, data->data.value, error);
+ kvp_respond_to_host(message, error);
}
+
+static int process_ob_ipinfo(void *in_msg, void *out_msg, int op)
+{
+ struct hv_kvp_msg *in = in_msg;
+ struct hv_kvp_ip_msg *out = out_msg;
+ int len;
+
+ switch (op) {
+ case KVP_OP_GET_IP_INFO:
+ /*
+ * Transform all parameters into utf16 encoding.
+ */
+ len = utf8s_to_utf16s((char *)in->body.kvp_ip_val.ip_addr,
+ strlen((char *)in->body.kvp_ip_val.ip_addr),
+ UTF16_HOST_ENDIAN,
+ (wchar_t *)out->kvp_ip_val.ip_addr,
+ MAX_IP_ADDR_SIZE);
+ if (len < 0)
+ return len;
+
+ len = utf8s_to_utf16s((char *)in->body.kvp_ip_val.sub_net,
+ strlen((char *)in->body.kvp_ip_val.sub_net),
+ UTF16_HOST_ENDIAN,
+ (wchar_t *)out->kvp_ip_val.sub_net,
+ MAX_IP_ADDR_SIZE);
+ if (len < 0)
+ return len;
+
+ len = utf8s_to_utf16s((char *)in->body.kvp_ip_val.gate_way,
+ strlen((char *)in->body.kvp_ip_val.gate_way),
+ UTF16_HOST_ENDIAN,
+ (wchar_t *)out->kvp_ip_val.gate_way,
+ MAX_GATEWAY_SIZE);
+ if (len < 0)
+ return len;
+
+ len = utf8s_to_utf16s((char *)in->body.kvp_ip_val.dns_addr,
+ strlen((char *)in->body.kvp_ip_val.dns_addr),
+ UTF16_HOST_ENDIAN,
+ (wchar_t *)out->kvp_ip_val.dns_addr,
+ MAX_IP_ADDR_SIZE);
+ if (len < 0)
+ return len;
+
+ len = utf8s_to_utf16s((char *)in->body.kvp_ip_val.adapter_id,
+ strlen((char *)in->body.kvp_ip_val.adapter_id),
+ UTF16_HOST_ENDIAN,
+ (wchar_t *)out->kvp_ip_val.adapter_id,
+ MAX_IP_ADDR_SIZE);
+ if (len < 0)
+ return len;
+
+ out->kvp_ip_val.dhcp_enabled =
+ in->body.kvp_ip_val.dhcp_enabled;
+ }
+
+ return 0;
+}
+
+static void process_ib_ipinfo(void *in_msg, void *out_msg, int op)
+{
+ struct hv_kvp_ip_msg *in = in_msg;
+ struct hv_kvp_msg *out = out_msg;
+
+ switch (op) {
+ case KVP_OP_SET_IP_INFO:
+ /*
+ * Transform all parameters into utf8 encoding.
+ */
+ utf16s_to_utf8s((wchar_t *)in->kvp_ip_val.ip_addr,
+ MAX_IP_ADDR_SIZE,
+ UTF16_LITTLE_ENDIAN,
+ (__u8 *)out->body.kvp_ip_val.ip_addr,
+ MAX_IP_ADDR_SIZE);
+
+ utf16s_to_utf8s((wchar_t *)in->kvp_ip_val.sub_net,
+ MAX_IP_ADDR_SIZE,
+ UTF16_LITTLE_ENDIAN,
+ (__u8 *)out->body.kvp_ip_val.sub_net,
+ MAX_IP_ADDR_SIZE);
+
+ utf16s_to_utf8s((wchar_t *)in->kvp_ip_val.gate_way,
+ MAX_GATEWAY_SIZE,
+ UTF16_LITTLE_ENDIAN,
+ (__u8 *)out->body.kvp_ip_val.gate_way,
+ MAX_GATEWAY_SIZE);
+
+ utf16s_to_utf8s((wchar_t *)in->kvp_ip_val.dns_addr,
+ MAX_IP_ADDR_SIZE,
+ UTF16_LITTLE_ENDIAN,
+ (__u8 *)out->body.kvp_ip_val.dns_addr,
+ MAX_IP_ADDR_SIZE);
+
+ out->body.kvp_ip_val.dhcp_enabled =
+ in->kvp_ip_val.dhcp_enabled;
+
+ default:
+ utf16s_to_utf8s((wchar_t *)in->kvp_ip_val.adapter_id,
+ MAX_ADAPTER_ID_SIZE,
+ UTF16_LITTLE_ENDIAN,
+ (__u8 *)out->body.kvp_ip_val.adapter_id,
+ MAX_ADAPTER_ID_SIZE);
+
+ out->body.kvp_ip_val.addr_family =
+ in->kvp_ip_val.addr_family;
+ }
+}
+
+
+
+
static void
kvp_send_key(struct work_struct *dummy)
{
@@ -237,6 +348,12 @@ kvp_send_key(struct work_struct *dummy)
*/
switch (message->kvp_hdr.operation) {
+ case KVP_OP_SET_IP_INFO:
+ process_ib_ipinfo(in_msg, message, KVP_OP_SET_IP_INFO);
+ break;
+ case KVP_OP_GET_IP_INFO:
+ process_ib_ipinfo(in_msg, message, KVP_OP_GET_IP_INFO);
+ break;
case KVP_OP_SET:
switch (in_msg->body.kvp_set.data.value_type) {
case REG_SZ:
@@ -313,17 +430,19 @@ kvp_send_key(struct work_struct *dummy)
*/
static void
-kvp_respond_to_host(char *key, char *value, int error)
+kvp_respond_to_host(struct hv_kvp_msg *msg_to_host, int error)
{
struct hv_kvp_msg *kvp_msg;
struct hv_kvp_exchg_msg_value *kvp_data;
char *key_name;
+ char *value;
struct icmsg_hdr *icmsghdrp;
int keylen = 0;
int valuelen = 0;
u32 buf_len;
struct vmbus_channel *channel;
u64 req_id;
+ int ret;
/*
* If a transaction is not active; log and return.
@@ -376,6 +495,16 @@ kvp_respond_to_host(char *key, char *value, int error)
sizeof(struct icmsg_hdr)];
switch (kvp_transaction.kvp_msg->kvp_hdr.operation) {
+ case KVP_OP_GET_IP_INFO:
+ ret = process_ob_ipinfo(msg_to_host,
+ (struct hv_kvp_ip_msg *)kvp_msg,
+ KVP_OP_GET_IP_INFO);
+ if (ret < 0)
+ icmsghdrp->status = HV_E_FAIL;
+
+ goto response_done;
+ case KVP_OP_SET_IP_INFO:
+ goto response_done;
case KVP_OP_GET:
kvp_data = &kvp_msg->body.kvp_get.data;
goto copy_value;
@@ -389,7 +518,7 @@ kvp_respond_to_host(char *key, char *value, int error)
}
kvp_data = &kvp_msg->body.kvp_enum_data.data;
- key_name = key;
+ key_name = msg_to_host->body.kvp_enum_data.data.key;
/*
* The windows host expects the key/value pair to be encoded
@@ -403,6 +532,7 @@ kvp_respond_to_host(char *key, char *value, int error)
kvp_data->key_size = 2*(keylen + 1); /* utf16 encoding */
copy_value:
+ value = msg_to_host->body.kvp_enum_data.data.value;
valuelen = utf8s_to_utf16s(value, strlen(value), UTF16_HOST_ENDIAN,
(wchar_t *) kvp_data->value,
(HV_KVP_EXCHANGE_MAX_VALUE_SIZE / 2) - 2);
@@ -455,7 +585,8 @@ void hv_kvp_onchannelcallback(void *context)
return;
}
- vmbus_recvpacket(channel, recv_buffer, PAGE_SIZE, &recvlen, &requestid);
+ vmbus_recvpacket(channel, recv_buffer, PAGE_SIZE * 2, &recvlen,
+ &requestid);
if (recvlen > 0) {
icmsghdrp = (struct icmsg_hdr *)&recv_buffer[
--
1.7.4.1
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox