From: "Slavomir Kaslev (VMware)" <slavomir.kaslev@gmail.com>
To: rostedt@goodmis.org
Cc: linux-trace-devel@vger.kernel.org
Subject: [PATCH v12 04/13] trace-cmd: Add VM tracing protocol messages
Date: Tue, 18 Jun 2019 17:44:46 +0300 [thread overview]
Message-ID: <20190618144455.3954-5-slavomir.kaslev@gmail.com> (raw)
In-Reply-To: <20190618144455.3954-1-slavomir.kaslev@gmail.com>
From: Slavomir Kaslev <kaslevs@vmware.com>
Add TRACE_REQ and TRACE_RESP messages used for initiating guest VM tracing and
CLOSE_RESP message used for acknowledging stop recording request.
Signed-off-by: Slavomir Kaslev <kaslevs@vmware.com>
---
include/trace-cmd/trace-cmd.h | 14 ++
tracecmd/trace-msg.c | 234 +++++++++++++++++++++++++++++++++-
2 files changed, 245 insertions(+), 3 deletions(-)
diff --git a/include/trace-cmd/trace-cmd.h b/include/trace-cmd/trace-cmd.h
index 28b5b38..db5baa8 100644
--- a/include/trace-cmd/trace-cmd.h
+++ b/include/trace-cmd/trace-cmd.h
@@ -324,7 +324,9 @@ int tracecmd_msg_data_send(struct tracecmd_msg_handle *msg_handle,
const char *buf, int size);
int tracecmd_msg_finish_sending_data(struct tracecmd_msg_handle *msg_handle);
int tracecmd_msg_send_close_msg(struct tracecmd_msg_handle *msg_handle);
+int tracecmd_msg_send_close_resp_msg(struct tracecmd_msg_handle *msg_handle);
int tracecmd_msg_wait_close(struct tracecmd_msg_handle *msg_handle);
+int tracecmd_msg_wait_close_resp(struct tracecmd_msg_handle *msg_handle);
/* for server */
int tracecmd_msg_initial_setting(struct tracecmd_msg_handle *msg_handle);
@@ -335,6 +337,18 @@ int tracecmd_msg_collect_data(struct tracecmd_msg_handle *msg_handle, int ofd);
bool tracecmd_msg_done(struct tracecmd_msg_handle *msg_handle);
void tracecmd_msg_set_done(struct tracecmd_msg_handle *msg_handle);
+int tracecmd_msg_send_trace_req(struct tracecmd_msg_handle *msg_handle,
+ int argc, char **argv);
+int tracecmd_msg_recv_trace_req(struct tracecmd_msg_handle *msg_handle,
+ int *argc, char ***argv);
+
+int tracecmd_msg_send_trace_resp(struct tracecmd_msg_handle *msg_handle,
+ int nr_cpus, int page_size,
+ unsigned int *ports);
+int tracecmd_msg_recv_trace_resp(struct tracecmd_msg_handle *msg_handle,
+ int *nr_cpus, int *page_size,
+ unsigned int **ports);
+
/* --- Plugin handling --- */
extern struct tep_plugin_option trace_ftrace_options[];
diff --git a/tracecmd/trace-msg.c b/tracecmd/trace-msg.c
index 74c0bc1..69c7c5f 100644
--- a/tracecmd/trace-msg.c
+++ b/tracecmd/trace-msg.c
@@ -16,6 +16,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
+#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
@@ -59,6 +60,17 @@ struct tracecmd_msg_rinit {
be32 cpus;
} __attribute__((packed));
+struct tracecmd_msg_trace_req {
+ be32 flags;
+ be32 argc;
+} __attribute__((packed));
+
+struct tracecmd_msg_trace_resp {
+ be32 flags;
+ be32 cpus;
+ be32 page_size;
+} __attribute__((packed));
+
struct tracecmd_msg_header {
be32 size;
be32 cmd;
@@ -71,7 +83,10 @@ struct tracecmd_msg_header {
C(RINIT, 2, sizeof(struct tracecmd_msg_rinit)), \
C(SEND_DATA, 3, 0), \
C(FIN_DATA, 4, 0), \
- C(NOT_SUPP, 5, 0),
+ C(NOT_SUPP, 5, 0), \
+ C(TRACE_REQ, 6, sizeof(struct tracecmd_msg_trace_req)), \
+ C(TRACE_RESP, 7, sizeof(struct tracecmd_msg_trace_resp)),\
+ C(CLOSE_RESP, 8, 0),
#undef C
#define C(a,b,c) MSG_##a = b
@@ -103,6 +118,8 @@ struct tracecmd_msg {
union {
struct tracecmd_msg_tinit tinit;
struct tracecmd_msg_rinit rinit;
+ struct tracecmd_msg_trace_req trace_req;
+ struct tracecmd_msg_trace_resp trace_resp;
};
char *buf;
} __attribute__((packed));
@@ -625,6 +642,14 @@ int tracecmd_msg_send_close_msg(struct tracecmd_msg_handle *msg_handle)
return tracecmd_msg_send(msg_handle->fd, &msg);
}
+int tracecmd_msg_send_close_resp_msg(struct tracecmd_msg_handle *msg_handle)
+{
+ struct tracecmd_msg msg;
+
+ tracecmd_msg_init(MSG_CLOSE_RESP, &msg);
+ return tracecmd_msg_send(msg_handle->fd, &msg);
+}
+
int tracecmd_msg_data_send(struct tracecmd_msg_handle *msg_handle,
const char *buf, int size)
{
@@ -745,7 +770,7 @@ int tracecmd_msg_collect_data(struct tracecmd_msg_handle *msg_handle, int ofd)
return tracecmd_msg_wait_close(msg_handle);
}
-int tracecmd_msg_wait_close(struct tracecmd_msg_handle *msg_handle)
+static int tracecmd_msg_wait_for_cmd(struct tracecmd_msg_handle *msg_handle, enum tracecmd_msg_cmd cmd)
{
struct tracecmd_msg msg;
int ret = -1;
@@ -756,7 +781,7 @@ int tracecmd_msg_wait_close(struct tracecmd_msg_handle *msg_handle)
if (ret < 0)
goto error;
- if (ntohl(msg.hdr.cmd) == MSG_CLOSE)
+ if (ntohl(msg.hdr.cmd) == cmd)
return 0;
error_operation(&msg);
@@ -771,3 +796,206 @@ error:
msg_free(&msg);
return ret;
}
+
+int tracecmd_msg_wait_close(struct tracecmd_msg_handle *msg_handle)
+{
+ return tracecmd_msg_wait_for_cmd(msg_handle, MSG_CLOSE);
+}
+
+int tracecmd_msg_wait_close_resp(struct tracecmd_msg_handle *msg_handle)
+{
+ return tracecmd_msg_wait_for_cmd(msg_handle, MSG_CLOSE_RESP);
+}
+
+static int make_trace_req(struct tracecmd_msg *msg, int argc, char **argv)
+{
+ size_t args_size = 0;
+ char *p;
+ int i;
+
+ for (i = 0; i < argc; i++)
+ args_size += strlen(argv[i]) + 1;
+
+ msg->hdr.size = htonl(ntohl(msg->hdr.size) + args_size);
+ msg->trace_req.argc = htonl(argc);
+ msg->buf = calloc(args_size, 1);
+ if (!msg->buf)
+ return -ENOMEM;
+
+ p = msg->buf;
+ for (i = 0; i < argc; i++)
+ p = stpcpy(p, argv[i]) + 1;
+
+ return 0;
+}
+
+int tracecmd_msg_send_trace_req(struct tracecmd_msg_handle *msg_handle,
+ int argc, char **argv)
+{
+ struct tracecmd_msg msg;
+ int ret;
+
+ tracecmd_msg_init(MSG_TRACE_REQ, &msg);
+ ret = make_trace_req(&msg, argc, argv);
+ if (ret < 0)
+ return ret;
+
+ return tracecmd_msg_send(msg_handle->fd, &msg);
+}
+
+ /*
+ * NOTE: On success, the returned `argv` should be freed with:
+ * free(argv[0]);
+ * free(argv);
+ */
+int tracecmd_msg_recv_trace_req(struct tracecmd_msg_handle *msg_handle,
+ int *argc, char ***argv)
+{
+ struct tracecmd_msg msg;
+ char *p, *buf_end, **args;
+ int i, ret, nr_args;
+ ssize_t buf_len;
+
+ ret = tracecmd_msg_recv(msg_handle->fd, &msg);
+ if (ret < 0)
+ return ret;
+
+ if (ntohl(msg.hdr.cmd) != MSG_TRACE_REQ) {
+ ret = -ENOTSUP;
+ goto out;
+ }
+
+ nr_args = ntohl(msg.trace_req.argc);
+ if (nr_args <= 0) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ buf_len = ntohl(msg.hdr.size) - MSG_HDR_LEN - ntohl(msg.hdr.cmd_size);
+ buf_end = (char *)msg.buf + buf_len;
+ if (buf_len <= 0 && ((char *)msg.buf)[buf_len-1] != '\0') {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ args = calloc(nr_args, sizeof(*args));
+ if (!args) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ for (i = 0, p = msg.buf; i < nr_args; i++, p++) {
+ if (p >= buf_end) {
+ ret = -EINVAL;
+ goto out_args;
+ }
+ args[i] = p;
+ p = strchr(p, '\0');
+ }
+
+ *argc = nr_args;
+ *argv = args;
+
+ /*
+ * On success we're passing msg.buf to the caller through argv[0] so we
+ * reset it here before calling msg_free().
+ */
+ msg.buf = NULL;
+ msg_free(&msg);
+ return 0;
+
+out_args:
+ free(args);
+out:
+ error_operation(&msg);
+ if (ret == -EOPNOTSUPP)
+ handle_unexpected_msg(msg_handle, &msg);
+ msg_free(&msg);
+ return ret;
+}
+
+static int make_trace_resp(struct tracecmd_msg *msg,
+ int page_size, int nr_cpus, unsigned int *ports)
+{
+ int data_size;
+
+ data_size = write_uints(NULL, 0, ports, nr_cpus);
+ msg->buf = malloc(data_size);
+ if (!msg->buf)
+ return -ENOMEM;
+ write_uints(msg->buf, data_size, ports, nr_cpus);
+
+ msg->hdr.size = htonl(ntohl(msg->hdr.size) + data_size);
+ msg->trace_resp.cpus = htonl(nr_cpus);
+ msg->trace_resp.page_size = htonl(page_size);
+
+ return 0;
+}
+
+int tracecmd_msg_send_trace_resp(struct tracecmd_msg_handle *msg_handle,
+ int nr_cpus, int page_size,
+ unsigned int *ports)
+{
+ struct tracecmd_msg msg;
+ int ret;
+
+ tracecmd_msg_init(MSG_TRACE_RESP, &msg);
+ ret = make_trace_resp(&msg, page_size, nr_cpus, ports);
+ if (ret < 0)
+ return ret;
+
+ return tracecmd_msg_send(msg_handle->fd, &msg);
+}
+
+int tracecmd_msg_recv_trace_resp(struct tracecmd_msg_handle *msg_handle,
+ int *nr_cpus, int *page_size,
+ unsigned int **ports)
+{
+ struct tracecmd_msg msg;
+ char *p, *buf_end;
+ ssize_t buf_len;
+ int i, ret;
+
+ ret = tracecmd_msg_recv(msg_handle->fd, &msg);
+ if (ret < 0)
+ return ret;
+
+ if (ntohl(msg.hdr.cmd) != MSG_TRACE_RESP) {
+ ret = -ENOTSUP;
+ goto out;
+ }
+
+ buf_len = msg_buf_len(&msg);
+ if (buf_len <= 0) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ *nr_cpus = ntohl(msg.trace_resp.cpus);
+ *page_size = ntohl(msg.trace_resp.page_size);
+ *ports = calloc(*nr_cpus, sizeof(**ports));
+ if (!*ports) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ buf_end = msg.buf + buf_len;
+ for (i = 0, p = msg.buf; i < *nr_cpus; i++, p++) {
+ if (p >= buf_end || tatou(p, &(*ports)[i])) {
+ free(*ports);
+ ret = -EINVAL;
+ goto out;
+ }
+ p = strchr(p, '\0');
+ }
+
+ msg_free(&msg);
+ return 0;
+
+out:
+ error_operation(&msg);
+ if (ret == -EOPNOTSUPP)
+ handle_unexpected_msg(msg_handle, &msg);
+ msg_free(&msg);
+ return ret;
+}
--
2.20.1
next prev parent reply other threads:[~2019-06-18 14:45 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-06-18 14:44 [PATCH v12 00/13] Add VM kernel tracing over vsockets and FIFOs Slavomir Kaslev (VMware)
2019-06-18 14:44 ` [PATCH v12 01/13] trace-cmd: Make ports unsigned int Slavomir Kaslev (VMware)
2019-06-18 14:44 ` [PATCH v12 02/13] trace-cmd: Detect if vsockets are available Slavomir Kaslev (VMware)
2019-06-18 14:44 ` [PATCH v12 03/13] trace-cmd: Add tracecmd_create_recorder_virt() function Slavomir Kaslev (VMware)
2019-06-18 14:44 ` Slavomir Kaslev (VMware) [this message]
2019-06-18 14:44 ` [PATCH v12 05/13] trace-cmd: Add buffer instance flags for tracing in guest and agent context Slavomir Kaslev (VMware)
2019-06-18 14:44 ` [PATCH v12 06/13] trace-cmd: Add VM kernel tracing over vsockets transport Slavomir Kaslev (VMware)
2019-06-18 14:44 ` [PATCH v12 07/13] trace-cmd: Use splice(2) for vsockets if available Slavomir Kaslev (VMware)
2019-06-18 14:44 ` [PATCH v12 08/13] trace-cmd: Switch stop recording signal to SIGUSR1 Slavomir Kaslev (VMware)
2019-06-18 14:44 ` [PATCH v12 09/13] trace-cmd: Add `trace-cmd setup-guest` command Slavomir Kaslev (VMware)
2019-06-18 14:44 ` [PATCH v12 10/13] trace-cmd: Try to autodetect number of guest CPUs in setup-guest if not specified Slavomir Kaslev (VMware)
2019-06-18 14:44 ` [PATCH v12 11/13] trace-cmd: Add setup-guest flag for attaching FIFOs to the guest VM config Slavomir Kaslev (VMware)
2019-06-18 14:44 ` [PATCH v12 12/13] trace-cmd: Add splice() recording from FIFO without additional pipe buffer Slavomir Kaslev (VMware)
2019-06-18 14:44 ` [PATCH v12 13/13] trace-cmd: Add support for tracing VMware Workstation VMs by name Slavomir Kaslev (VMware)
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=20190618144455.3954-5-slavomir.kaslev@gmail.com \
--to=slavomir.kaslev@gmail.com \
--cc=linux-trace-devel@vger.kernel.org \
--cc=rostedt@goodmis.org \
/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).