From patchwork Thu Jan 21 07:44:42 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Tzvetomir Stoyanov (VMware)" X-Patchwork-Id: 12035063 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 59B84C4332E for ; Thu, 21 Jan 2021 07:47:57 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 0492C238EC for ; Thu, 21 Jan 2021 07:47:56 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726821AbhAUHrz (ORCPT ); Thu, 21 Jan 2021 02:47:55 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49838 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727651AbhAUHpm (ORCPT ); Thu, 21 Jan 2021 02:45:42 -0500 Received: from mail-wr1-x430.google.com (mail-wr1-x430.google.com [IPv6:2a00:1450:4864:20::430]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 72139C0613CF for ; Wed, 20 Jan 2021 23:45:01 -0800 (PST) Received: by mail-wr1-x430.google.com with SMTP id g10so747411wrx.1 for ; Wed, 20 Jan 2021 23:45:01 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=2rt1nrCP89FUKc3aOpbZvF9DEbmG3ozIZRgb/P09LY8=; b=CR3+l27Utui/VgPVAqW11nGOBJa+wYNfNad1VUJ0RV4EyxzoqXkJ3Z/ZpgbHSvWa6S 78JFHAsKRyqDYYnLXH0WIuNtJ0wDeHEy6lcmI+9HjieGNb3+Bd2lEaucDOe4GX6cHEk4 EBmWKxI5WMmEC+Vz4GoS58qxde1C6MMGdlhjalb/D48aeGBmfK5bYAMpnkDQuOBpBLQU rO2GIAnMOxUfKeJFuEFZgJ4KJtuX7TnpFHSz0eQz6ceSG5/Z2nLymXO2TXwE5oUqBpBX KpiNrGCoFshmeoBxftywQIpHbKunHrpMUP9jS3Wzic08uyedJ0n19OPslJWYxB3gHqT9 oJnQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=2rt1nrCP89FUKc3aOpbZvF9DEbmG3ozIZRgb/P09LY8=; b=UQmSBUqOdeyHRWvka4XA8Oui4y+OhihstjiJjU8SzZOnU6v8uIFIOyZ+o2DJr0nYn7 l8HkTN+S1U39dJw+6XfGR1hczSXALO3eyJoGV9rlCjc8wythVAvm0TBURaUgryuYYUwx TzJkktpK+DaKin7qj58omkMM8Yj08AIQMM3yvqKF5f5H/0wKor7APk/gPsyUaH07Cn/f bfrcuc0AiddSCuOxY/xYQ7JGCeiqQCwWwoMTjlIVGgZ/FMrCdp0HM1oM6orpfRGpxT3X 6ZTN6xBn68SXDRHtu9aisDkE8q61bNc1IZxp19wKU0v9TuAu5jvypGU6YHNoSwHT3n3t INHQ== X-Gm-Message-State: AOAM533Q4hXDq4NDhxEMoqKMcNUmTAN3kfzbdJajAmnjAHc5BHtOk1Gg 7qSvAvLechMXnZ1I2d51e34= X-Google-Smtp-Source: ABdhPJw2CMX6JhtCTXPYeSwdcZGh+F+odrMMax7wvK1YJ0nXtL1hxy3fHhjXScID0+IkJpG5w09zYQ== X-Received: by 2002:a5d:678d:: with SMTP id v13mr12804551wru.71.1611215100053; Wed, 20 Jan 2021 23:45:00 -0800 (PST) Received: from oberon.zico.biz ([83.222.187.186]) by smtp.gmail.com with ESMTPSA id q6sm6788474wmj.32.2021.01.20.23.44.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 20 Jan 2021 23:44:59 -0800 (PST) From: "Tzvetomir Stoyanov (VMware)" To: rostedt@goodmis.org Cc: linux-trace-devel@vger.kernel.org Subject: [PATCH v26 01/15] trace-cmd: Replace time sync protocol ID with string Date: Thu, 21 Jan 2021 09:44:42 +0200 Message-Id: <20210121074456.157658-2-tz.stoyanov@gmail.com> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210121074456.157658-1-tz.stoyanov@gmail.com> References: <20210121074456.157658-1-tz.stoyanov@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org Different timestamp synchronization algorithms will be implemented as trace-cmd plugins. Using IDs for identifying these algorithms is a problem, as these IDs must be defined in a single place. In order to be more flexible, protocol IDs are replaced by protocol names - strings that are part of the plugin code and are registered with plugin initialisation. The plugin names are limited up to 15 symbols, in order to simplify the structure of sync messages. Signed-off-by: Tzvetomir Stoyanov (VMware) --- .../include/private/trace-cmd-private.h | 36 ++--- lib/trace-cmd/include/trace-tsync-local.h | 12 +- lib/trace-cmd/trace-msg.c | 112 ++++++++----- lib/trace-cmd/trace-timesync.c | 152 +++++++++--------- tracecmd/include/trace-local.h | 6 +- tracecmd/trace-agent.c | 15 +- tracecmd/trace-record.c | 27 ++-- tracecmd/trace-tsync.c | 20 +-- 8 files changed, 213 insertions(+), 167 deletions(-) diff --git a/lib/trace-cmd/include/private/trace-cmd-private.h b/lib/trace-cmd/include/private/trace-cmd-private.h index 64945815..08e98a50 100644 --- a/lib/trace-cmd/include/private/trace-cmd-private.h +++ b/lib/trace-cmd/include/private/trace-cmd-private.h @@ -334,6 +334,10 @@ struct tracecmd_msg_handle { bool done; }; +struct tracecmd_tsync_protos { + char **names; +}; + struct tracecmd_msg_handle * tracecmd_msg_handle_alloc(int fd, unsigned long flags); @@ -363,50 +367,44 @@ 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, bool use_fifos, unsigned long long trace_id, - char *tsync_protos, - int tsync_protos_size); + struct tracecmd_tsync_protos *protos); int tracecmd_msg_recv_trace_req(struct tracecmd_msg_handle *msg_handle, int *argc, char ***argv, bool *use_fifos, unsigned long long *trace_id, - char **tsync_protos, - unsigned int *tsync_protos_size); + struct tracecmd_tsync_protos **protos); int tracecmd_msg_send_trace_resp(struct tracecmd_msg_handle *msg_handle, int nr_cpus, int page_size, unsigned int *ports, bool use_fifos, unsigned long long trace_id, - unsigned int tsync_proto, - unsigned int tsync_port); + const char *tsync_proto, unsigned int tsync_port); int tracecmd_msg_recv_trace_resp(struct tracecmd_msg_handle *msg_handle, int *nr_cpus, int *page_size, unsigned int **ports, bool *use_fifos, unsigned long long *trace_id, - unsigned int *tsync_proto, + char **tsync_proto, unsigned int *tsync_port); int tracecmd_msg_send_time_sync(struct tracecmd_msg_handle *msg_handle, - unsigned int sync_protocol, - unsigned int sync_msg_id, + char *sync_protocol, unsigned int sync_msg_id, unsigned int payload_size, char *payload); int tracecmd_msg_recv_time_sync(struct tracecmd_msg_handle *msg_handle, - unsigned int *sync_protocol, + char *sync_protocol, unsigned int *sync_msg_id, unsigned int *payload_size, char **payload); /* --- Timestamp synchronization --- */ -enum{ - TRACECMD_TIME_SYNC_PROTO_NONE = 0, -}; +#define TRACECMD_TSYNC_PNAME_LENGTH 16 +#define TRACECMD_TSYNC_PROTO_NONE "none" + enum{ TRACECMD_TIME_SYNC_CMD_PROBE = 1, TRACECMD_TIME_SYNC_CMD_STOP = 2, }; -#define TRACECMD_TIME_SYNC_PROTO_PTP_WEIGHT 10 - struct tracecmd_time_sync { - unsigned int sync_proto; + const char *proto_name; int loop_interval; pthread_mutex_t lock; pthread_cond_t cond; @@ -416,9 +414,9 @@ struct tracecmd_time_sync { }; void tracecmd_tsync_init(void); -int tracecmd_tsync_proto_getall(char **proto_mask, int *words); -unsigned int tracecmd_tsync_proto_select(char *proto_mask, int words); -bool tsync_proto_is_supported(unsigned int proto_id); +int tracecmd_tsync_proto_getall(struct tracecmd_tsync_protos **protos); +const char *tracecmd_tsync_proto_select(struct tracecmd_tsync_protos *protos); +bool tsync_proto_is_supported(const char *proto_name); void tracecmd_tsync_with_host(struct tracecmd_time_sync *tsync); void tracecmd_tsync_with_guest(struct tracecmd_time_sync *tsync); int tracecmd_tsync_get_offsets(struct tracecmd_time_sync *tsync, diff --git a/lib/trace-cmd/include/trace-tsync-local.h b/lib/trace-cmd/include/trace-tsync-local.h index 1de9d5e5..58841a4c 100644 --- a/lib/trace-cmd/include/trace-tsync-local.h +++ b/lib/trace-cmd/include/trace-tsync-local.h @@ -26,12 +26,12 @@ struct clock_sync_context { unsigned int remote_port; }; -int tracecmd_tsync_proto_register(unsigned int proto_id, int weight, - int (*init)(struct tracecmd_time_sync *), - int (*free)(struct tracecmd_time_sync *), - int (*calc)(struct tracecmd_time_sync *, - long long *, long long *)); -int tracecmd_tsync_proto_unregister(unsigned int proto_id); +int tracecmd_tsync_proto_register(const char *proto_name, int accuracy, + int (*init)(struct tracecmd_time_sync *), + int (*free)(struct tracecmd_time_sync *), + int (*calc)(struct tracecmd_time_sync *, + long long *, long long *)); +int tracecmd_tsync_proto_unregister(char *proto_name); int ptp_clock_sync_register(void); diff --git a/lib/trace-cmd/trace-msg.c b/lib/trace-cmd/trace-msg.c index 4a0bfa93..e0cdf677 100644 --- a/lib/trace-cmd/trace-msg.c +++ b/lib/trace-cmd/trace-msg.c @@ -26,6 +26,7 @@ #include "trace-cmd-local.h" #include "trace-local.h" #include "trace-msg.h" +#include "trace-cmd.h" typedef __u32 u32; typedef __be32 be32; @@ -85,12 +86,12 @@ struct tracecmd_msg_trace_resp { be32 cpus; be32 page_size; u64 trace_id; - be32 tsync_proto; + char tsync_proto_name[TRACECMD_TSYNC_PNAME_LENGTH]; be32 tsync_port; } __attribute__((packed)); struct tracecmd_msg_tsync { - be32 sync_protocol; + char sync_protocol_name[TRACECMD_TSYNC_PNAME_LENGTH]; be32 sync_msg_id; } __attribute__((packed)); @@ -848,12 +849,20 @@ int tracecmd_msg_wait_close_resp(struct tracecmd_msg_handle *msg_handle) } static int make_trace_req_protos(char **buf, int *size, - int protos_size, char *tsync_protos) + struct tracecmd_tsync_protos *protos) { + int protos_size = 1; size_t buf_size; + char **names; char *nbuf; char *p; + names = protos->names; + while (*names) { + protos_size += strlen(*names) + 1; + names++; + } + buf_size = TRACE_REQ_PARAM_SIZE + protos_size; nbuf = realloc(*buf, *size + buf_size); if (!nbuf) @@ -867,7 +876,13 @@ static int make_trace_req_protos(char **buf, int *size, *(unsigned int *)p = htonl(protos_size); p += sizeof(int); - memcpy(p, tsync_protos, protos_size); + names = protos->names; + while (*names) { + strcpy(p, *names); + p += strlen(*names) + 1; + names++; + } + p = NULL; *size += buf_size; *buf = nbuf; @@ -911,7 +926,7 @@ static int make_trace_req_args(char **buf, int *size, int argc, char **argv) static int make_trace_req(struct tracecmd_msg *msg, int argc, char **argv, bool use_fifos, unsigned long long trace_id, - char *tsync_protos, int tsync_protos_size) + struct tracecmd_tsync_protos *protos) { int size = 0; char *buf = NULL; @@ -924,9 +939,8 @@ static int make_trace_req(struct tracecmd_msg *msg, int argc, char **argv, if (argc && argv) make_trace_req_args(&buf, &size, argc, argv); - if (tsync_protos_size && tsync_protos) - make_trace_req_protos(&buf, &size, - tsync_protos_size, tsync_protos); + if (protos && protos->names) + make_trace_req_protos(&buf, &size, protos); msg->buf = buf; msg->hdr.size = htonl(ntohl(msg->hdr.size) + size); @@ -937,15 +951,13 @@ static int make_trace_req(struct tracecmd_msg *msg, int argc, char **argv, int tracecmd_msg_send_trace_req(struct tracecmd_msg_handle *msg_handle, int argc, char **argv, bool use_fifos, unsigned long long trace_id, - char *tsync_protos, - int tsync_protos_size) + struct tracecmd_tsync_protos *protos) { struct tracecmd_msg msg; int ret; tracecmd_msg_init(MSG_TRACE_REQ, &msg); - ret = make_trace_req(&msg, argc, argv, use_fifos, - trace_id, tsync_protos, tsync_protos_size); + ret = make_trace_req(&msg, argc, argv, use_fifos, trace_id, protos); if (ret < 0) return ret; @@ -953,16 +965,44 @@ int tracecmd_msg_send_trace_req(struct tracecmd_msg_handle *msg_handle, } static int get_trace_req_protos(char *buf, int length, - char **tsync_protos, - unsigned int *tsync_protos_size) + struct tracecmd_tsync_protos **protos) { - *tsync_protos = malloc(length); - if (!*tsync_protos) - return -1; - memcpy(*tsync_protos, buf, length); - *tsync_protos_size = length; + struct tracecmd_tsync_protos *plist = NULL; + int count = 0; + char *p; + int i, j; + + i = length; + p = buf; + while (i > 0) { + i -= strlen(p) + 1; + count++; + p += strlen(p) + 1; + } + plist = calloc(1, sizeof(struct tracecmd_tsync_protos)); + if (plist) + goto error; + plist->names = calloc(count + 1, sizeof(char *)); + if (!plist->names) + goto error; + i = length; + p = buf; + j = 0; + while (i > 0 && j < (count - 1)) { + i -= strlen(p) + 1; + plist->names[j++] = strdup(p); + p += strlen(p) + 1; + } + + *protos = plist; return 0; +error: + if (plist) { + free(plist->names); + free(plist); + } + return -1; } static int get_trace_req_args(char *buf, int length, int *argc, char ***argv) @@ -1026,8 +1066,7 @@ out: int tracecmd_msg_recv_trace_req(struct tracecmd_msg_handle *msg_handle, int *argc, char ***argv, bool *use_fifos, unsigned long long *trace_id, - char **tsync_protos, - unsigned int *tsync_protos_size) + struct tracecmd_tsync_protos **protos) { struct tracecmd_msg msg; unsigned int param_id; @@ -1069,8 +1108,7 @@ int tracecmd_msg_recv_trace_req(struct tracecmd_msg_handle *msg_handle, ret = get_trace_req_args(p, param_length, argc, argv); break; case TRACE_REQUEST_TSYNC_PROTOS: - ret = get_trace_req_protos(p, param_length, - tsync_protos, tsync_protos_size); + ret = get_trace_req_protos(p, param_length, protos); break; default: break; @@ -1095,7 +1133,8 @@ out: /** * tracecmd_msg_send_time_sync - Send a time sync packet * @msg_handle: message handle, holding the communication context - * @sync_protocol: id of the time synch protocol + * @sync_protocol: name of the time synch protocol, string up to + * TRACECMD_TSYNC_PNAME_LENGTH characters length. * @sync_msg_id: id if the time synch message, protocol dependent * @payload_size: size of the packet payload, 0 in case of no payload * @payload: pointer to the packet payload, or NULL in case of no payload @@ -1103,14 +1142,13 @@ out: * Returns 0 if packet is sent successfully, or negative error otherwise. */ int tracecmd_msg_send_time_sync(struct tracecmd_msg_handle *msg_handle, - unsigned int sync_protocol, - unsigned int sync_msg_id, + char *sync_protocol, unsigned int sync_msg_id, unsigned int payload_size, char *payload) { struct tracecmd_msg msg; tracecmd_msg_init(MSG_TIME_SYNC, &msg); - msg.tsync.sync_protocol = htonl(sync_protocol); + strncpy(msg.tsync.sync_protocol_name, sync_protocol, TRACECMD_TSYNC_PNAME_LENGTH); msg.tsync.sync_msg_id = htonl(sync_msg_id); msg.hdr.size = htonl(ntohl(msg.hdr.size) + payload_size); @@ -1121,7 +1159,9 @@ int tracecmd_msg_send_time_sync(struct tracecmd_msg_handle *msg_handle, /** * tracecmd_msg_recv_time_sync - Receive a time sync packet * @msg_handle: message handle, holding the communication context - * @sync_protocol: return the id of the packet's time synch protocol + * @sync_protocol: return the name of the packet's time synch protocol. + * It must point to a prealocated buffer with size + * TRACECMD_TSYNC_PNAME_LENGTH * @sync_msg_id: return the id of the packet's time synch message * @payload_size: size of the packet's payload, can be: * NULL - the payload is not interested and should be ignored @@ -1146,7 +1186,7 @@ int tracecmd_msg_send_time_sync(struct tracecmd_msg_handle *msg_handle, * Returns 0 if packet is received successfully, or negative error otherwise. */ int tracecmd_msg_recv_time_sync(struct tracecmd_msg_handle *msg_handle, - unsigned int *sync_protocol, + char *sync_protocol, unsigned int *sync_msg_id, unsigned int *payload_size, char **payload) { @@ -1165,7 +1205,8 @@ int tracecmd_msg_recv_time_sync(struct tracecmd_msg_handle *msg_handle, } if (sync_protocol) - *sync_protocol = ntohl(msg.tsync.sync_protocol); + strncpy(sync_protocol, msg.tsync.sync_protocol_name, + TRACECMD_TSYNC_PNAME_LENGTH); if (sync_msg_id) *sync_msg_id = ntohl(msg.tsync.sync_msg_id); @@ -1202,7 +1243,7 @@ out: static int make_trace_resp(struct tracecmd_msg *msg, int page_size, int nr_cpus, unsigned int *ports, bool use_fifos, unsigned long long trace_id, - unsigned int tsync_proto, + const char *tsync_proto, unsigned int tsync_port) { int data_size; @@ -1216,7 +1257,7 @@ static int make_trace_resp(struct tracecmd_msg *msg, int page_size, int nr_cpus, msg->hdr.size = htonl(ntohl(msg->hdr.size) + data_size); msg->trace_resp.flags = use_fifos ? MSG_TRACE_USE_FIFOS : 0; msg->trace_resp.flags = htonl(msg->trace_resp.flags); - msg->trace_resp.tsync_proto = htonl(tsync_proto); + strncpy(msg->trace_resp.tsync_proto_name, tsync_proto, TRACECMD_TSYNC_PNAME_LENGTH); msg->trace_resp.tsync_port = htonl(tsync_port); msg->trace_resp.cpus = htonl(nr_cpus); @@ -1230,8 +1271,7 @@ int tracecmd_msg_send_trace_resp(struct tracecmd_msg_handle *msg_handle, int nr_cpus, int page_size, unsigned int *ports, bool use_fifos, unsigned long long trace_id, - unsigned int tsync_proto, - unsigned int tsync_port) + const char *tsync_proto, unsigned int tsync_port) { struct tracecmd_msg msg; int ret; @@ -1249,7 +1289,7 @@ int tracecmd_msg_recv_trace_resp(struct tracecmd_msg_handle *msg_handle, int *nr_cpus, int *page_size, unsigned int **ports, bool *use_fifos, unsigned long long *trace_id, - unsigned int *tsync_proto, + char **tsync_proto, unsigned int *tsync_port) { struct tracecmd_msg msg; @@ -1276,7 +1316,7 @@ int tracecmd_msg_recv_trace_resp(struct tracecmd_msg_handle *msg_handle, *nr_cpus = ntohl(msg.trace_resp.cpus); *page_size = ntohl(msg.trace_resp.page_size); *trace_id = ntohll(msg.trace_resp.trace_id); - *tsync_proto = ntohl(msg.trace_resp.tsync_proto); + *tsync_proto = strdup(msg.trace_resp.tsync_proto_name); *tsync_port = ntohl(msg.trace_resp.tsync_port); *ports = calloc(*nr_cpus, sizeof(**ports)); if (!*ports) { diff --git a/lib/trace-cmd/trace-timesync.c b/lib/trace-cmd/trace-timesync.c index 390e9d99..c9fde0fa 100644 --- a/lib/trace-cmd/trace-timesync.c +++ b/lib/trace-cmd/trace-timesync.c @@ -24,8 +24,8 @@ struct tsync_proto { struct tsync_proto *next; - unsigned int proto_id; - int weight; + char proto_name[TRACECMD_TSYNC_PNAME_LENGTH]; + int accuracy; int (*clock_sync_init)(struct tracecmd_time_sync *clock_context); int (*clock_sync_free)(struct tracecmd_time_sync *clock_context); @@ -35,32 +35,35 @@ struct tsync_proto { static struct tsync_proto *tsync_proto_list; -static struct tsync_proto *tsync_proto_find(unsigned int proto_id) +static struct tsync_proto *tsync_proto_find(const char *proto_name) { struct tsync_proto *proto; - for (proto = tsync_proto_list; proto; proto = proto->next) - if (proto->proto_id == proto_id) + if (!proto_name) + return NULL; + for (proto = tsync_proto_list; proto; proto = proto->next) { + if (strlen(proto->proto_name) == strlen(proto_name) && + !strncmp(proto->proto_name, proto_name, TRACECMD_TSYNC_PNAME_LENGTH)) return proto; - + } return NULL; } -int tracecmd_tsync_proto_register(unsigned int proto_id, int weight, - int (*init)(struct tracecmd_time_sync *), - int (*free)(struct tracecmd_time_sync *), - int (*calc)(struct tracecmd_time_sync *, - long long *, long long *)) +int tracecmd_tsync_proto_register(const char *proto_name, int accuracy, + int (*init)(struct tracecmd_time_sync *), + int (*free)(struct tracecmd_time_sync *), + int (*calc)(struct tracecmd_time_sync *, + long long *, long long *)) { - struct tsync_proto *proto; + struct tsync_proto *proto = NULL; - if (tsync_proto_find(proto_id)) + if (tsync_proto_find(proto_name)) return -1; proto = calloc(1, sizeof(struct tsync_proto)); if (!proto) return -1; - proto->proto_id = proto_id; - proto->weight = weight; + strncpy(proto->proto_name, proto_name, TRACECMD_TSYNC_PNAME_LENGTH); + proto->accuracy = accuracy; proto->clock_sync_init = init; proto->clock_sync_free = free; proto->clock_sync_calc = calc; @@ -70,12 +73,16 @@ int tracecmd_tsync_proto_register(unsigned int proto_id, int weight, return 0; } -int tracecmd_tsync_proto_unregister(unsigned int proto_id) +int tracecmd_tsync_proto_unregister(char *proto_name) { struct tsync_proto **last = &tsync_proto_list; + if (!proto_name) + return -1; + for (; *last; last = &(*last)->next) { - if ((*last)->proto_id == proto_id) { + if (strlen((*last)->proto_name) == strlen(proto_name) && + !strncmp((*last)->proto_name, proto_name, TRACECMD_TSYNC_PNAME_LENGTH)) { struct tsync_proto *proto = *last; *last = proto->next; @@ -87,9 +94,9 @@ int tracecmd_tsync_proto_unregister(unsigned int proto_id) return -1; } -bool tsync_proto_is_supported(unsigned int proto_id) +bool tsync_proto_is_supported(const char *proto_name) { - if (tsync_proto_find(proto_id)) + if (tsync_proto_find(proto_name)) return true; return false; } @@ -129,81 +136,79 @@ int tracecmd_tsync_get_offsets(struct tracecmd_time_sync *tsync, * tracecmd_tsync_proto_select - Select time sync protocol, to be used for * timestamp synchronization with a peer * - * @proto_mask: bitmask array of time sync protocols, supported by the peer - * @length: size of the @protos array + * @protos: list of tsync protocol names * - * Retuns Id of a time sync protocol, that can be used with the peer, or 0 - * in case there is no match with supported protocols + * Retuns pointer to a protocol name, that can be used with the peer, or NULL + * in case there is no match with supported protocols. + * The returned string MUST NOT be freed by the caller */ -unsigned int tracecmd_tsync_proto_select(char *proto_mask, int length) +const char *tracecmd_tsync_proto_select(struct tracecmd_tsync_protos *protos) { struct tsync_proto *selected = NULL; struct tsync_proto *proto; - int word; - int id; + char **pname; - for (word = 0; word < length; word++) { - for (proto = tsync_proto_list; proto; proto = proto->next) { - if (proto->proto_id < word * PROTO_MASK_SIZE) - continue; + if (!protos) + return NULL; - id = proto->proto_id - word * PROTO_MASK_SIZE; - if (id >= PROTO_MASK_BITS) + pname = protos->names; + while (*pname) { + for (proto = tsync_proto_list; proto; proto = proto->next) { + if (strncmp(proto->proto_name, *pname, TRACECMD_TSYNC_PNAME_LENGTH)) continue; - - if ((1 << id) & proto_mask[word]) { - if (selected) { - if (selected->weight < proto->weight) - selected = proto; - } else + if (selected) { + if (selected->accuracy > proto->accuracy) selected = proto; - } + } else + selected = proto; } + pname++; } if (selected) - return selected->proto_id; + return selected->proto_name; - return 0; + return NULL; } /** * tracecmd_tsync_proto_getall - Returns bitmask of all supported * time sync protocols - * @proto_mask: return, allocated bitmask array of time sync protocols, + * @protos: return, allocated list of time sync protocol names, * supported by the peer. Must be freed by free() - * @words: return, allocated size of the @protobits array * - * If completed successfully 0 is returned and allocated array in @proto_mask of - * size @words. In case of an error, -1 is returned. - * @proto_mask must be freed with free() + * If completed successfully 0 is returned and allocated list of strings in @protos. + * The last list entry is NULL. In case of an error, -1 is returned. + * @protos must be freed with free() */ -int tracecmd_tsync_proto_getall(char **proto_mask, int *words) +int tracecmd_tsync_proto_getall(struct tracecmd_tsync_protos **protos) { + struct tracecmd_tsync_protos *plist = NULL; struct tsync_proto *proto; - int proto_max = 0; - int count = 0; - char *protos; + int count = 1; + int i; for (proto = tsync_proto_list; proto; proto = proto->next) - if (proto->proto_id > proto_max) - proto_max = proto->proto_id; - - count = proto_max / PROTO_MASK_SIZE + 1; - protos = calloc(count, sizeof(char)); - if (!protos) + count++; + plist = calloc(1, sizeof(struct tracecmd_tsync_protos)); + if (!plist) + goto error; + plist->names = calloc(count, sizeof(char *)); + if (!plist->names) return -1; - for (proto = tsync_proto_list; proto; proto = proto->next) { - if ((proto->proto_id / PROTO_MASK_SIZE) >= count) - continue; - protos[proto->proto_id / PROTO_MASK_SIZE] |= - (1 << (proto->proto_id % PROTO_MASK_SIZE)); - } + for (i = 0, proto = tsync_proto_list; proto && i < (count - 1); proto = proto->next) + plist->names[i++] = proto->proto_name; - *proto_mask = protos; - *words = count; + *protos = plist; return 0; + +error: + if (plist) { + free(plist->names); + free(plist); + } + return -1; } static int get_vsocket_params(int fd, unsigned int *lcid, unsigned int *lport, @@ -267,7 +272,7 @@ static int clock_context_init(struct tracecmd_time_sync *tsync, bool server) if (tsync->context) return 0; - protocol = tsync_proto_find(tsync->sync_proto); + protocol = tsync_proto_find(tsync->proto_name); if (!protocol) return -1; @@ -313,7 +318,7 @@ void tracecmd_tsync_free(struct tracecmd_time_sync *tsync) return; tsync_context = (struct clock_sync_context *)tsync->context; - proto = tsync_proto_find(tsync->sync_proto); + proto = tsync_proto_find(tsync->proto_name); if (proto && proto->clock_sync_free) proto->clock_sync_free(tsync); @@ -355,12 +360,12 @@ int tracecmd_tsync_send(struct tracecmd_time_sync *tsync, */ void tracecmd_tsync_with_host(struct tracecmd_time_sync *tsync) { + char protocol[TRACECMD_TSYNC_PNAME_LENGTH]; struct tsync_proto *proto; - unsigned int protocol; unsigned int command; int ret; - proto = tsync_proto_find(tsync->sync_proto); + proto = tsync_proto_find(tsync->proto_name); if (!proto || !proto->clock_sync_calc) return; @@ -370,11 +375,10 @@ void tracecmd_tsync_with_host(struct tracecmd_time_sync *tsync) while (true) { ret = tracecmd_msg_recv_time_sync(tsync->msg_handle, - &protocol, &command, + protocol, &command, NULL, NULL); - if (ret || - protocol != TRACECMD_TIME_SYNC_PROTO_NONE || + if (ret || strncmp(protocol, TRACECMD_TSYNC_PROTO_NONE, TRACECMD_TSYNC_PNAME_LENGTH) || command != TRACECMD_TIME_SYNC_CMD_PROBE) break; ret = tracecmd_tsync_send(tsync, proto); @@ -455,7 +459,7 @@ void tracecmd_tsync_with_guest(struct tracecmd_time_sync *tsync) bool end = false; int ret; - proto = tsync_proto_find(tsync->sync_proto); + proto = tsync_proto_find(tsync->proto_name); if (!proto || !proto->clock_sync_calc) return; @@ -470,7 +474,7 @@ void tracecmd_tsync_with_guest(struct tracecmd_time_sync *tsync) while (true) { pthread_mutex_lock(&tsync->lock); ret = tracecmd_msg_send_time_sync(tsync->msg_handle, - TRACECMD_TIME_SYNC_PROTO_NONE, + TRACECMD_TSYNC_PROTO_NONE, TRACECMD_TIME_SYNC_CMD_PROBE, 0, NULL); ret = tsync_get_sample(tsync, proto, ts_array_size); @@ -492,7 +496,7 @@ void tracecmd_tsync_with_guest(struct tracecmd_time_sync *tsync) }; tracecmd_msg_send_time_sync(tsync->msg_handle, - TRACECMD_TIME_SYNC_PROTO_NONE, + TRACECMD_TSYNC_PROTO_NONE, TRACECMD_TIME_SYNC_CMD_STOP, 0, NULL); } diff --git a/tracecmd/include/trace-local.h b/tracecmd/include/trace-local.h index 85c7e03e..4089de4e 100644 --- a/tracecmd/include/trace-local.h +++ b/tracecmd/include/trace-local.h @@ -299,9 +299,9 @@ void tracecmd_stat_cpu(struct trace_seq *s, int cpu); int tracecmd_host_tsync(struct buffer_instance *instance, unsigned int tsync_port); void tracecmd_host_tsync_complete(struct buffer_instance *instance); -unsigned int tracecmd_guest_tsync(char *tsync_protos, - unsigned int tsync_protos_size, char *clock, - unsigned int *tsync_port, pthread_t *thr_id); +const char *tracecmd_guest_tsync(struct tracecmd_tsync_protos *tsync_protos, + char *clock, unsigned int *tsync_port, + pthread_t *thr_id); int trace_make_vsock(unsigned int port); int trace_get_vsock_port(int sd, unsigned int *port); diff --git a/tracecmd/trace-agent.c b/tracecmd/trace-agent.c index b5816966..ff4a4e11 100644 --- a/tracecmd/trace-agent.c +++ b/tracecmd/trace-agent.c @@ -142,12 +142,11 @@ static char *get_clock(int argc, char **argv) static void agent_handle(int sd, int nr_cpus, int page_size) { + struct tracecmd_tsync_protos *tsync_protos = NULL; struct tracecmd_msg_handle *msg_handle; - unsigned int tsync_protos_size = 0; - unsigned int tsync_proto = 0; + const char *tsync_proto = NULL; unsigned long long trace_id; unsigned int tsync_port = 0; - char *tsync_protos = NULL; unsigned int *ports; pthread_t sync_thr; char **argv = NULL; @@ -167,7 +166,7 @@ static void agent_handle(int sd, int nr_cpus, int page_size) ret = tracecmd_msg_recv_trace_req(msg_handle, &argc, &argv, &use_fifos, &trace_id, - &tsync_protos, &tsync_protos_size); + &tsync_protos); if (ret < 0) die("Failed to receive trace request"); @@ -176,9 +175,8 @@ static void agent_handle(int sd, int nr_cpus, int page_size) if (!use_fifos) make_vsocks(nr_cpus, fds, ports); - if (tsync_protos) { + if (tsync_protos && tsync_protos->names) { tsync_proto = tracecmd_guest_tsync(tsync_protos, - tsync_protos_size, get_clock(argc, argv), &tsync_port, &sync_thr); if (!tsync_proto) @@ -197,7 +195,10 @@ static void agent_handle(int sd, int nr_cpus, int page_size) if (tsync_proto) pthread_join(sync_thr, NULL); - free(tsync_protos); + if (tsync_protos) { + free(tsync_protos->names); + free(tsync_protos); + } free(argv[0]); free(argv); free(ports); diff --git a/tracecmd/trace-record.c b/tracecmd/trace-record.c index ade52421..9316bbde 100644 --- a/tracecmd/trace-record.c +++ b/tracecmd/trace-record.c @@ -3852,12 +3852,11 @@ static int open_guest_fifos(const char *guest, int **fds) #ifdef VSOCK static void connect_to_agent(struct buffer_instance *instance) { - struct tracecmd_msg_handle *msg_handle; + struct tracecmd_tsync_protos *protos = NULL; int sd, ret, nr_fifos, nr_cpus, page_size; - unsigned int tsync_protos_reply = 0; + struct tracecmd_msg_handle *msg_handle; + char *tsync_protos_reply = NULL; unsigned int tsync_port = 0; - char *protos = NULL; - int protos_count = 0; unsigned int *ports; int i, *fds = NULL; bool use_fifos = false; @@ -3879,31 +3878,35 @@ static void connect_to_agent(struct buffer_instance *instance) die("Failed to allocate message handle"); if (instance->tsync.loop_interval >= 0) - tracecmd_tsync_proto_getall(&protos, &protos_count); + tracecmd_tsync_proto_getall(&protos); ret = tracecmd_msg_send_trace_req(msg_handle, instance->argc, instance->argv, use_fifos, - top_instance.trace_id, - protos, protos_count); + top_instance.trace_id, protos); if (ret < 0) die("Failed to send trace request"); - free(protos); - + if (protos) { + free(protos->names); + free(protos); + } ret = tracecmd_msg_recv_trace_resp(msg_handle, &nr_cpus, &page_size, &ports, &use_fifos, &instance->trace_id, &tsync_protos_reply, &tsync_port); if (ret < 0) die("Failed to receive trace response %d", ret); - - if (protos_count && tsync_protos_reply) { + if (tsync_protos_reply && tsync_protos_reply[0]) { if (tsync_proto_is_supported(tsync_protos_reply)) { - instance->tsync.sync_proto = tsync_protos_reply; + instance->tsync.proto_name = strdup(tsync_protos_reply); + printf("Negotiated %s time sync protocol with guest %s\n", + instance->tsync.proto_name, + tracefs_instance_get_name(instance->tracefs)); tracecmd_host_tsync(instance, tsync_port); } else warning("Failed to negotiate timestamps synchronization with the guest"); } + free(tsync_protos_reply); if (use_fifos) { if (nr_cpus != nr_fifos) { diff --git a/tracecmd/trace-tsync.c b/tracecmd/trace-tsync.c index 8b9083ae..5781cfd2 100644 --- a/tracecmd/trace-tsync.c +++ b/tracecmd/trace-tsync.c @@ -82,7 +82,7 @@ int tracecmd_host_tsync(struct buffer_instance *instance, int ret; int fd; - if (!instance->tsync.sync_proto) + if (!instance->tsync.proto_name) return -1; fd = trace_open_vsock(instance->cid, tsync_port); @@ -210,22 +210,22 @@ out: pthread_exit(0); } -unsigned int tracecmd_guest_tsync(char *tsync_protos, - unsigned int tsync_protos_size, char *clock, - unsigned int *tsync_port, pthread_t *thr_id) +const char *tracecmd_guest_tsync(struct tracecmd_tsync_protos *tsync_protos, + char *clock, unsigned int *tsync_port, + pthread_t *thr_id) { struct tracecmd_time_sync *tsync = NULL; cpu_set_t *pin_mask = NULL; pthread_attr_t attrib; size_t mask_size = 0; - unsigned int proto; + const char *proto; int ret; int fd; fd = -1; - proto = tracecmd_tsync_proto_select(tsync_protos, tsync_protos_size); + proto = tracecmd_tsync_proto_select(tsync_protos); if (!proto) - return 0; + return NULL; #ifdef VSOCK fd = trace_make_vsock(VMADDR_PORT_ANY); if (fd < 0) @@ -235,7 +235,7 @@ unsigned int tracecmd_guest_tsync(char *tsync_protos, if (ret < 0) goto error; #else - return 0; + return NULL; #endif tsync = calloc(1, sizeof(struct tracecmd_time_sync)); @@ -244,7 +244,7 @@ unsigned int tracecmd_guest_tsync(char *tsync_protos, tsync->clock_str = strdup(clock); pthread_attr_init(&attrib); - tsync->sync_proto = proto; + tsync->proto_name = proto; pthread_attr_setdetachstate(&attrib, PTHREAD_CREATE_JOINABLE); ret = pthread_create(thr_id, &attrib, tsync_agent_thread, tsync); @@ -272,5 +272,5 @@ error: } if (fd > 0) close(fd); - return 0; + return NULL; } From patchwork Thu Jan 21 07:44:43 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Tzvetomir Stoyanov (VMware)" X-Patchwork-Id: 12035059 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 01EC2C433DB for ; Thu, 21 Jan 2021 07:47:57 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id B7CA323356 for ; Thu, 21 Jan 2021 07:47:56 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726573AbhAUHrz (ORCPT ); Thu, 21 Jan 2021 02:47:55 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49844 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727668AbhAUHpm (ORCPT ); Thu, 21 Jan 2021 02:45:42 -0500 Received: from mail-wr1-x42e.google.com (mail-wr1-x42e.google.com [IPv6:2a00:1450:4864:20::42e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7B99FC0613D3 for ; Wed, 20 Jan 2021 23:45:02 -0800 (PST) Received: by mail-wr1-x42e.google.com with SMTP id l12so745790wry.2 for ; Wed, 20 Jan 2021 23:45:02 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=nyrs8pAZOTNh1VU/sM4KU6TnGp3INTO/Er4TnPCwv7A=; b=S0thjCuVMWQ/5Viqb4N5uk03Z3ja4QZCAcWxKYWCHQaVoj+1+eCwVYxPaxXvQ1Cr6O QWWY0ifeCeiE5ZbbqSR8yWuim0yy0zEMqiQgUVCkHGFPLq+T0QOBuyv/2vQ3Q7wUhfLf I87ySMb2/Llowm/ypNpu9mWyDfuL+4MuqWJdxFZtfs+he1uqqy2YBVOInDlDgo357MzC XVRGX1lC20FOilv7HgPEfRnXeZOynuIAZR/FSZTjjN/8l6atU+VhInfoPYaabPLU7Enk wQR/efL5qrdvBfZ1WtSQX5eznEubum0WVfr28WQomzF+8yOGdi4RTcA9nK3Pe6ovZNdI /Zgg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=nyrs8pAZOTNh1VU/sM4KU6TnGp3INTO/Er4TnPCwv7A=; b=rvJ3BHDqBrxsO5Zi57BSlX1RlH7E2ZOWTAnut825pbNSHWyQKxS3KP8zoSMRfmpoHD 9XJCZYnv/RiRsQMbRELhM94pAkAFplghTAX6KAfjnYR4+Mn3GKHvthfEpq1rqbkOflBR nn15WJwgb6nC8huoY/dDPSWD8NNkrOSKA9tgUlzQT+8/EwWCP9BdP/Ln6u659o2O+hir sQ/SG1iZCMPocR+vJi/L2BPiIgAiYg3Flw8e/30t1fF8CqB10MQQPe1MLVeAfrzBrDJt fiF7DWtrs7AwYgJbblgCXyalyfvxTbAOwq1P6+Gfl/MyvMcwXKWytsymxMnJnB2y/Ual Vpzg== X-Gm-Message-State: AOAM532KJiZlmCbj+a+/WcHxxZudsyL1d5JLrm7ePQXPAKyAoNdVEAHA 5B4nPYo8rBW3ebF+SaRLMnqB3bFkihPTaVTA X-Google-Smtp-Source: ABdhPJzmz6rDqx6b/kdMQMptp9WHly4tcfLSa2foDo7oA4hFVdle9x/QsgqwGo9w3AOud4ak+eNBFQ== X-Received: by 2002:a5d:61c4:: with SMTP id q4mr12787818wrv.304.1611215101327; Wed, 20 Jan 2021 23:45:01 -0800 (PST) Received: from oberon.zico.biz ([83.222.187.186]) by smtp.gmail.com with ESMTPSA id q6sm6788474wmj.32.2021.01.20.23.45.00 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 20 Jan 2021 23:45:00 -0800 (PST) From: "Tzvetomir Stoyanov (VMware)" To: rostedt@goodmis.org Cc: linux-trace-devel@vger.kernel.org Subject: [PATCH v26 02/15] trace-cmd: Add trace-cmd library APIs for ftrace clock name Date: Thu, 21 Jan 2021 09:44:43 +0200 Message-Id: <20210121074456.157658-3-tz.stoyanov@gmail.com> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210121074456.157658-1-tz.stoyanov@gmail.com> References: <20210121074456.157658-1-tz.stoyanov@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org Added enum with ftrace clock IDs and APIs to convert ftrace name to ID and vice versa, as part of libtracecmd. The clock items in the enum are organized as a bitmask, as it will be used by the timestamp synchronization protocol to declare supported ftrace clocks. Signed-off-by: Tzvetomir Stoyanov (VMware) --- .../include/private/trace-cmd-private.h | 16 ++++++ lib/trace-cmd/trace-util.c | 52 +++++++++++++++++++ 2 files changed, 68 insertions(+) diff --git a/lib/trace-cmd/include/private/trace-cmd-private.h b/lib/trace-cmd/include/private/trace-cmd-private.h index 08e98a50..0d323947 100644 --- a/lib/trace-cmd/include/private/trace-cmd-private.h +++ b/lib/trace-cmd/include/private/trace-cmd-private.h @@ -393,6 +393,22 @@ int tracecmd_msg_recv_time_sync(struct tracecmd_msg_handle *msg_handle, unsigned int *sync_msg_id, unsigned int *payload_size, char **payload); +enum tracecmd_clocks { + TRACECMD_CLOCK_UNKNOWN = 0, + TRACECMD_CLOCK_LOCAL = 1, + TRACECMD_CLOCK_GLOBAL = 1 << 1, + TRACECMD_CLOCK_COUNTER = 1 << 2, + TRACECMD_CLOCK_UPTIME = 1 << 3, + TRACECMD_CLOCK_PERF = 1 << 4, + TRACECMD_CLOCK_MONO = 1 << 5, + TRACECMD_CLOCK_MONO_RAW = 1 << 6, + TRACECMD_CLOCK_BOOT = 1 << 7, + TRACECMD_CLOCK_X86_TSC = 1 << 8 +}; + +enum tracecmd_clocks tracecmd_clock_str2id(const char *clock); +const char *tracecmd_clock_id2str(enum tracecmd_clocks clock); + /* --- Timestamp synchronization --- */ #define TRACECMD_TSYNC_PNAME_LENGTH 16 diff --git a/lib/trace-cmd/trace-util.c b/lib/trace-cmd/trace-util.c index 8caec7c1..9661b266 100644 --- a/lib/trace-cmd/trace-util.c +++ b/lib/trace-cmd/trace-util.c @@ -33,6 +33,58 @@ static bool debug; static FILE *logfp; +const static struct { + const char *clock_str; + enum tracecmd_clocks clock_id; +} trace_clocks[] = { + {"local", TRACECMD_CLOCK_LOCAL}, + {"global", TRACECMD_CLOCK_GLOBAL}, + {"counter", TRACECMD_CLOCK_COUNTER}, + {"uptime", TRACECMD_CLOCK_UPTIME}, + {"perf", TRACECMD_CLOCK_PERF}, + {"mono", TRACECMD_CLOCK_MONO}, + {"mono_raw", TRACECMD_CLOCK_MONO_RAW}, + {"boot", TRACECMD_CLOCK_BOOT}, + {"x86-tsc", TRACECMD_CLOCK_X86_TSC}, + {NULL, -1} +}; + +/** + * tracecmd_clock_str2id - Convert ftrace clock name to clock ID + * @clock: Ftrace clock name + * Returns ID of the ftrace clock + */ +enum tracecmd_clocks tracecmd_clock_str2id(const char *clock) +{ + int i; + + if (!clock) + return TRACECMD_CLOCK_UNKNOWN; + + for (i = 0; trace_clocks[i].clock_str; i++) { + if (!strncmp(clock, trace_clocks[i].clock_str, + strlen(trace_clocks[i].clock_str))) + return trace_clocks[i].clock_id; + } + return TRACECMD_CLOCK_UNKNOWN; +} + +/** + * tracecmd_clock_id2str - Convert clock ID to ftare clock name + * @clock: Clock ID + * Returns name of a ftrace clock + */ +const char *tracecmd_clock_id2str(enum tracecmd_clocks clock) +{ + int i; + + for (i = 0; trace_clocks[i].clock_str; i++) { + if (trace_clocks[i].clock_id == clock) + return trace_clocks[i].clock_str; + } + return NULL; +} + /** * tracecmd_set_debug - Set debug mode of the tracecmd library * @set_debug: The new "debug" mode. If true, the tracecmd library is From patchwork Thu Jan 21 07:44:44 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Tzvetomir Stoyanov (VMware)" X-Patchwork-Id: 12035035 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-12.9 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,UNWANTED_LANGUAGE_BODY, URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 30A12C433E0 for ; Thu, 21 Jan 2021 07:46:45 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id C228F221F7 for ; Thu, 21 Jan 2021 07:46:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727520AbhAUHqX (ORCPT ); Thu, 21 Jan 2021 02:46:23 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49850 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726760AbhAUHpo (ORCPT ); Thu, 21 Jan 2021 02:45:44 -0500 Received: from mail-wr1-x432.google.com (mail-wr1-x432.google.com [IPv6:2a00:1450:4864:20::432]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C64B6C0613D6 for ; Wed, 20 Jan 2021 23:45:03 -0800 (PST) Received: by mail-wr1-x432.google.com with SMTP id a9so734648wrt.5 for ; Wed, 20 Jan 2021 23:45:03 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=wgevKZfb15xf4/LJlhb5nwre71B5N+KJ1ksRt7FyyG0=; b=oCoIybg/CCXQ9NPp6rHDOoCbQJMsWnjyN1PxVgugizD+mu7qhlbNyljBSOf1Z0Viet qdK9eK9EOCtJu9QYf9lyeU1DUd+kv28B57szYYKLUqYuBgr8ZCNHSHckl9QB5rAXeHpb sBePlX/lBBEM98Y+2RTvoQOw70V1bxn32TqLzEjoAesyWt0M4jKP7d9zi56ShWmY69JQ sIfy2wiALF5Pe49xHmUhRBktLRmk6b/QbpujN+hefyoPA4C3jGxNZ2nwOEtKxH/aKrWg ccLQmYQQcjjLIYjxQ2gY9JCK7MkZohjo2JE1JO+o095lshHmIivDJqkobuBfHTsC9eGG 3G0A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=wgevKZfb15xf4/LJlhb5nwre71B5N+KJ1ksRt7FyyG0=; b=qJ9U+U7xeVkhSq693niYcoy8MNtBJgXUr9ASmdAHXUDK6ISFqM5wcORFeyFjPr/9be b0SfsYBaW4oAsPe7MVo4suxLS4bPQa4NIkWH8GQvgdc6IG0D1HrRK/SA1sXNUeLYclul M/2GX2eMLij2dY088JDFY5cEmSz6gNkT4xcJh+QrZAaGBVbWsHVqchESGz+nAjAXPqx7 G+je6Cj7c6Wsqhd0ChrdjgeAwBJNertyevS7CWlhTkYOwDSkD1Cp87fADV5c/bLaMdyb cDxTZEILbrVULIUpobVQhjyjG+PGC4k3xr88ZSalR9+kIQAFQjooKeMyurhQfCu5GfD1 wbdQ== X-Gm-Message-State: AOAM53214WfMiJSRcEWdXkmrMM9dYJS3z0A00tFD5rGDy3KXZEJCOgRe DjF3nLMr8fDrWW23s/pGmgI= X-Google-Smtp-Source: ABdhPJwiYPSPa0hur5V3CNZmshLZRL52KOWV12yT+1sg6fZ+a/UKtbDmsdbBxSC8E7+nKf6K4LEBCw== X-Received: by 2002:adf:eb05:: with SMTP id s5mr12778514wrn.333.1611215102527; Wed, 20 Jan 2021 23:45:02 -0800 (PST) Received: from oberon.zico.biz ([83.222.187.186]) by smtp.gmail.com with ESMTPSA id q6sm6788474wmj.32.2021.01.20.23.45.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 20 Jan 2021 23:45:01 -0800 (PST) From: "Tzvetomir Stoyanov (VMware)" To: rostedt@goodmis.org Cc: linux-trace-devel@vger.kernel.org Subject: [PATCH v26 03/15] trace-cmd: Move VM related logic in a separate file Date: Thu, 21 Jan 2021 09:44:44 +0200 Message-Id: <20210121074456.157658-4-tz.stoyanov@gmail.com> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210121074456.157658-1-tz.stoyanov@gmail.com> References: <20210121074456.157658-1-tz.stoyanov@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org All trace-cmd internal functions related to VM / guest resolving and mappings are moved from trace-record.c to trace-vm.c. Internal APIs are added to access the guest database, so this functionality can be used by other logic, internally in the trace-cmd context. Signed-off-by: Tzvetomir Stoyanov (VMware) --- tracecmd/Makefile | 1 + tracecmd/include/trace-local.h | 20 +++ tracecmd/trace-record.c | 232 +++------------------------------ tracecmd/trace-vm.c | 214 ++++++++++++++++++++++++++++++ 4 files changed, 250 insertions(+), 217 deletions(-) create mode 100644 tracecmd/trace-vm.c diff --git a/tracecmd/Makefile b/tracecmd/Makefile index c02851a8..2b14284b 100644 --- a/tracecmd/Makefile +++ b/tracecmd/Makefile @@ -35,6 +35,7 @@ TRACE_CMD_OBJS += trace-list.o TRACE_CMD_OBJS += trace-usage.o TRACE_CMD_OBJS += trace-dump.o TRACE_CMD_OBJS += trace-clear.o +TRACE_CMD_OBJS += trace-vm.o ifeq ($(VSOCK_DEFINED), 1) TRACE_CMD_OBJS += trace-tsync.o endif diff --git a/tracecmd/include/trace-local.h b/tracecmd/include/trace-local.h index 4089de4e..7b14c68a 100644 --- a/tracecmd/include/trace-local.h +++ b/tracecmd/include/trace-local.h @@ -8,6 +8,7 @@ #include #include /* for DIR */ +#include /* for isdigit() */ #include #include "trace-cmd-private.h" @@ -285,6 +286,17 @@ void update_first_instance(struct buffer_instance *instance, int topt); void show_instance_file(struct buffer_instance *instance, const char *name); +struct trace_guest { + char *name; + int cid; + int pid; + int cpu_max; + int *cpu_pid; +}; +struct trace_guest *get_guest_by_cid(unsigned int guest_cid); +struct trace_guest *get_guest_by_name(char *name); +void read_qemu_guests(void); +int get_guest_pid(unsigned int guest_cid); int get_guest_vcpu_pid(unsigned int guest_cid, unsigned int guest_vcpu); /* moved from trace-cmd.h */ @@ -315,4 +327,12 @@ void *malloc_or_die(unsigned int size); /* Can be overridden */ void __noreturn __die(const char *fmt, ...); void __noreturn _vdie(const char *fmt, va_list ap); +static inline bool is_digits(const char *s) +{ + for (; *s; s++) + if (!isdigit(*s)) + return false; + return true; +} + #endif /* __TRACE_LOCAL_H */ diff --git a/tracecmd/trace-record.c b/tracecmd/trace-record.c index 9316bbde..a0e128d6 100644 --- a/tracecmd/trace-record.c +++ b/tracecmd/trace-record.c @@ -3183,239 +3183,37 @@ static int do_accept(int sd) return -1; } -static bool is_digits(const char *s) +static char *parse_guest_name(char *gname, int *cid, int *port) { - for (; *s; s++) - if (!isdigit(*s)) - return false; - return true; -} - -struct guest { - char *name; - int cid; - int pid; - int cpu_max; - int *cpu_pid; -}; - -static struct guest *guests; -static size_t guests_len; - -static int set_vcpu_pid_mapping(struct guest *guest, int cpu, int pid) -{ - int *cpu_pid; - int i; - - if (cpu >= guest->cpu_max) { - cpu_pid = realloc(guest->cpu_pid, (cpu + 1) * sizeof(int)); - if (!cpu_pid) - return -1; - /* Handle sparse CPU numbers */ - for (i = guest->cpu_max; i < cpu; i++) - cpu_pid[i] = -1; - guest->cpu_max = cpu + 1; - guest->cpu_pid = cpu_pid; - } - guest->cpu_pid[cpu] = pid; - return 0; -} - -static struct guest *get_guest_info(unsigned int guest_cid) -{ - int i; - - if (!guests) - return NULL; - - for (i = 0; i < guests_len; i++) - if (guest_cid == guests[i].cid) - return guests + i; - return NULL; -} - -static char *get_qemu_guest_name(char *arg) -{ - char *tok, *end = arg; - - while ((tok = strsep(&end, ","))) { - if (strncmp(tok, "guest=", 6) == 0) - return tok + 6; - } - - return arg; -} - -static int read_qemu_guests_pids(char *guest_task, struct guest *guest) -{ - struct dirent *entry; - char path[PATH_MAX]; - char *buf = NULL; - size_t n = 0; - int ret = 0; - long vcpu; - long pid; - DIR *dir; - FILE *f; - - snprintf(path, sizeof(path), "/proc/%s/task", guest_task); - dir = opendir(path); - if (!dir) - return -1; - - while (!ret && (entry = readdir(dir))) { - if (!(entry->d_type == DT_DIR && is_digits(entry->d_name))) - continue; - - snprintf(path, sizeof(path), "/proc/%s/task/%s/comm", - guest_task, entry->d_name); - f = fopen(path, "r"); - if (!f) - continue; - - if (getline(&buf, &n, f) >= 0 && - strncmp(buf, "CPU ", 4) == 0) { - vcpu = strtol(buf + 4, NULL, 10); - pid = strtol(entry->d_name, NULL, 10); - if (vcpu < INT_MAX && pid < INT_MAX && - vcpu >= 0 && pid >= 0) { - if (set_vcpu_pid_mapping(guest, vcpu, pid)) - ret = -1; - } - } - - fclose(f); - } - free(buf); - return ret; -} - -static void read_qemu_guests(void) -{ - static bool initialized; - struct dirent *entry; - char path[PATH_MAX]; - DIR *dir; - - if (initialized) - return; - - initialized = true; - dir = opendir("/proc"); - if (!dir) - die("Can not open /proc"); - - while ((entry = readdir(dir))) { - bool is_qemu = false, last_was_name = false; - struct guest guest = {}; - char *p, *arg = NULL; - size_t arg_size = 0; - FILE *f; - - if (!(entry->d_type == DT_DIR && is_digits(entry->d_name))) - continue; - - guest.pid = atoi(entry->d_name); - snprintf(path, sizeof(path), "/proc/%s/cmdline", entry->d_name); - f = fopen(path, "r"); - if (!f) - continue; - - while (getdelim(&arg, &arg_size, 0, f) != -1) { - if (!is_qemu && strstr(arg, "qemu-system-")) { - is_qemu = true; - continue; - } - - if (!is_qemu) - continue; - - if (strcmp(arg, "-name") == 0) { - last_was_name = true; - continue; - } - - if (last_was_name) { - guest.name = strdup(get_qemu_guest_name(arg)); - if (!guest.name) - die("allocating guest name"); - last_was_name = false; - continue; - } - - p = strstr(arg, "guest-cid="); - if (p) { - guest.cid = atoi(p + 10); - continue; - } - } - - if (!is_qemu) - goto next; - - if (read_qemu_guests_pids(entry->d_name, &guest)) - warning("Failed to retrieve VPCU - PID mapping for guest %s", - guest.name ? guest.name : "Unknown"); - - guests = realloc(guests, (guests_len + 1) * sizeof(*guests)); - if (!guests) - die("Can not allocate guest buffer"); - guests[guests_len++] = guest; - -next: - free(arg); - fclose(f); - } - - closedir(dir); -} - -static char *parse_guest_name(char *guest, int *cid, int *port) -{ - size_t i; + struct trace_guest *guest; char *p; *port = -1; - p = strrchr(guest, ':'); + p = strrchr(gname, ':'); if (p) { *p = '\0'; *port = atoi(p + 1); } *cid = -1; - p = strrchr(guest, '@'); + p = strrchr(gname, '@'); if (p) { *p = '\0'; *cid = atoi(p + 1); - } else if (is_digits(guest)) - *cid = atoi(guest); + } else if (is_digits(gname)) + *cid = atoi(gname); read_qemu_guests(); - for (i = 0; i < guests_len; i++) { - if ((*cid > 0 && *cid == guests[i].cid) || - strcmp(guest, guests[i].name) == 0) { - *cid = guests[i].cid; - return guests[i].name; - } + if (*cid > 0) + guest = get_guest_by_cid(*cid); + else + guest = get_guest_by_name(gname); + if (guest) { + *cid = guest->cid; + return guest->name; } - return guest; -} - -int get_guest_vcpu_pid(unsigned int guest_cid, unsigned int guest_vcpu) -{ - int i; - - if (!guests) - return -1; - - for (i = 0; i < guests_len; i++) { - if (guests[i].cpu_pid < 0 || guest_vcpu >= guests[i].cpu_max) - continue; - if (guest_cid == guests[i].cid) - return guests[i].cpu_pid[guest_vcpu]; - } - return -1; + return gname; } static void set_prio(int prio) @@ -4091,7 +3889,7 @@ static void append_buffer(struct tracecmd_output *handle, static void add_guest_info(struct tracecmd_output *handle, struct buffer_instance *instance) { - struct guest *guest = get_guest_info(instance->cid); + struct trace_guest *guest = get_guest_by_cid(instance->cid); char *buf, *p; int size; int i; diff --git a/tracecmd/trace-vm.c b/tracecmd/trace-vm.c new file mode 100644 index 00000000..c8924ece --- /dev/null +++ b/tracecmd/trace-vm.c @@ -0,0 +1,214 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2008, 2009, 2010 Red Hat Inc, Steven Rostedt + * Copyright (C) 2020, VMware, Tzvetomir Stoyanov + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ +#include +#include +#include +#include +#include + +#include "trace-local.h" +#include "trace-msg.h" + +static struct trace_guest *guests; +static size_t guests_len; + +static int set_vcpu_pid_mapping(struct trace_guest *guest, int cpu, int pid) +{ + int *cpu_pid; + int i; + + if (cpu >= guest->cpu_max) { + cpu_pid = realloc(guest->cpu_pid, (cpu + 1) * sizeof(int)); + if (!cpu_pid) + return -1; + /* Handle sparse CPU numbers */ + for (i = guest->cpu_max; i < cpu; i++) + cpu_pid[i] = -1; + guest->cpu_max = cpu + 1; + guest->cpu_pid = cpu_pid; + } + guest->cpu_pid[cpu] = pid; + return 0; +} + +struct trace_guest *get_guest_by_cid(unsigned int guest_cid) +{ + int i; + + if (!guests) + return NULL; + + for (i = 0; i < guests_len; i++) + if (guest_cid == guests[i].cid) + return guests + i; + return NULL; +} + +struct trace_guest *get_guest_by_name(char *name) +{ + int i; + + if (!guests) + return NULL; + + for (i = 0; i < guests_len; i++) + if (strcmp(name, guests[i].name) == 0) + return guests + i; + return NULL; +} + +static char *get_qemu_guest_name(char *arg) +{ + char *tok, *end = arg; + + while ((tok = strsep(&end, ","))) { + if (strncmp(tok, "guest=", 6) == 0) + return tok + 6; + } + + return arg; +} + +static int read_qemu_guests_pids(char *guest_task, struct trace_guest *guest) +{ + struct dirent *entry; + char path[PATH_MAX]; + char *buf = NULL; + size_t n = 0; + int ret = 0; + long vcpu; + long pid; + DIR *dir; + FILE *f; + + snprintf(path, sizeof(path), "/proc/%s/task", guest_task); + dir = opendir(path); + if (!dir) + return -1; + + while (!ret && (entry = readdir(dir))) { + if (!(entry->d_type == DT_DIR && is_digits(entry->d_name))) + continue; + + snprintf(path, sizeof(path), "/proc/%s/task/%s/comm", + guest_task, entry->d_name); + f = fopen(path, "r"); + if (!f) + continue; + + if (getline(&buf, &n, f) >= 0 && + strncmp(buf, "CPU ", 4) == 0) { + vcpu = strtol(buf + 4, NULL, 10); + pid = strtol(entry->d_name, NULL, 10); + if (vcpu < INT_MAX && pid < INT_MAX && + vcpu >= 0 && pid >= 0) { + if (set_vcpu_pid_mapping(guest, vcpu, pid)) + ret = -1; + } + } + + fclose(f); + } + free(buf); + return ret; +} + +void read_qemu_guests(void) +{ + static bool initialized; + struct dirent *entry; + char path[PATH_MAX]; + DIR *dir; + + if (initialized) + return; + + initialized = true; + dir = opendir("/proc"); + if (!dir) + die("Can not open /proc"); + + while ((entry = readdir(dir))) { + bool is_qemu = false, last_was_name = false; + struct trace_guest guest = {}; + char *p, *arg = NULL; + size_t arg_size = 0; + FILE *f; + + if (!(entry->d_type == DT_DIR && is_digits(entry->d_name))) + continue; + + guest.pid = atoi(entry->d_name); + snprintf(path, sizeof(path), "/proc/%s/cmdline", entry->d_name); + f = fopen(path, "r"); + if (!f) + continue; + + while (getdelim(&arg, &arg_size, 0, f) != -1) { + if (!is_qemu && strstr(arg, "qemu-system-")) { + is_qemu = true; + continue; + } + + if (!is_qemu) + continue; + + if (strcmp(arg, "-name") == 0) { + last_was_name = true; + continue; + } + + if (last_was_name) { + guest.name = strdup(get_qemu_guest_name(arg)); + if (!guest.name) + die("allocating guest name"); + last_was_name = false; + continue; + } + + p = strstr(arg, "guest-cid="); + if (p) { + guest.cid = atoi(p + 10); + continue; + } + } + + if (!is_qemu) + goto next; + + if (read_qemu_guests_pids(entry->d_name, &guest)) + warning("Failed to retrieve VPCU - PID mapping for guest %s", + guest.name ? guest.name : "Unknown"); + + guests = realloc(guests, (guests_len + 1) * sizeof(*guests)); + if (!guests) + die("Can not allocate guest buffer"); + guests[guests_len++] = guest; + +next: + free(arg); + fclose(f); + } + + closedir(dir); +} + +int get_guest_vcpu_pid(unsigned int guest_cid, unsigned int guest_vcpu) +{ + int i; + + if (!guests) + return -1; + + for (i = 0; i < guests_len; i++) { + if (guests[i].cpu_pid < 0 || guest_vcpu >= guests[i].cpu_max) + continue; + if (guest_cid == guests[i].cid) + return guests[i].cpu_pid[guest_vcpu]; + } + return -1; +} From patchwork Thu Jan 21 07:44:45 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Tzvetomir Stoyanov (VMware)" X-Patchwork-Id: 12035053 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id DA9A3C4332D for ; Thu, 21 Jan 2021 07:47:55 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 930F323356 for ; Thu, 21 Jan 2021 07:47:55 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1725878AbhAUHry (ORCPT ); Thu, 21 Jan 2021 02:47:54 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49856 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727664AbhAUHpp (ORCPT ); Thu, 21 Jan 2021 02:45:45 -0500 Received: from mail-wr1-x42a.google.com (mail-wr1-x42a.google.com [IPv6:2a00:1450:4864:20::42a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id DD019C0613ED for ; Wed, 20 Jan 2021 23:45:04 -0800 (PST) Received: by mail-wr1-x42a.google.com with SMTP id g10so747558wrx.1 for ; Wed, 20 Jan 2021 23:45:04 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=pqhAbFPGd3uhm9st1v+lpphhcpVExohF68ZE+q552hI=; b=lwrrHw0B5eLEILi+FJLfYwM2Eetan7quk7rn9h1/G4hVlUMqAvo3wEu7nChijFL2B0 JGGfxiLNRDPGKWRLdbujqjbf+aBQC2RQuokSy0o5GTYxP1DK4zhAHe6EZfGryaSEbXqU 3BnTanoxj9Rt0d+48Zs/sm80tq32u9z75396yOBw9Qh4YlIqCK+IJC+G6ax1O7r3hgMZ Ki0P31QYMZ7wz9JKBZY2U/Js9w21/hPLmdcCMIg4xL+OW9rVUqqqu86jT5/8t9SyCxSN SvVi7rmN5LvBo4dcX7fxW1X0lfdArBVOiE+RUrlmLMOsEbLRJI/q7lJbIvSPjrt9Eyxm 48zw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=pqhAbFPGd3uhm9st1v+lpphhcpVExohF68ZE+q552hI=; b=DEvdVbllQaBKNntsltixPwfqI5xFXrLloY6dSersK6zCQoqc2UTIylrZDP0NhJeoeM hfpQdXwPoro5bV7xxlMkk8DOOuIM/diIX+zKwhVw2aWmXfz0z5n1OLHJyRZwSpLOLZde sy7bjIMCIobwubycmtdqQ09R/Qt7N+nwRTNbldOjXb/S2kNC29vky97xh9I0zlKC+tlX PLo2Iq4mHuBSKWFdt7p9BiiJOKExpbNsW2/KZvrTU9tVFX3usNXQS3+EswJLJ8fmDZKX A43pWDG3AofokGA02oPT7NKRPueXm84yLqBlIcvlp9Y9gzVkAZIV4a22buWozBkRSMFu TiyA== X-Gm-Message-State: AOAM530XOCBEdTBbAM4dxdMC10uEsfXfXKjCbxT3d03mSlfJvJWMSdwW nfzTv77XqQzFtwMvXj6fUe/rfeSnlSwEGayV X-Google-Smtp-Source: ABdhPJw0O3rVyX4ttZ3egKlEXNTcVgYojjSCCTx+Rb7bO9CvX46VE+z9I3vsm6mfJ8cblsvCjlm28Q== X-Received: by 2002:adf:fe04:: with SMTP id n4mr9424452wrr.115.1611215103632; Wed, 20 Jan 2021 23:45:03 -0800 (PST) Received: from oberon.zico.biz ([83.222.187.186]) by smtp.gmail.com with ESMTPSA id q6sm6788474wmj.32.2021.01.20.23.45.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 20 Jan 2021 23:45:02 -0800 (PST) From: "Tzvetomir Stoyanov (VMware)" To: rostedt@goodmis.org Cc: linux-trace-devel@vger.kernel.org Subject: [PATCH v26 04/15] trace-cmd: Add clock parameter to timestamp synchronization plugins Date: Thu, 21 Jan 2021 09:44:45 +0200 Message-Id: <20210121074456.157658-5-tz.stoyanov@gmail.com> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210121074456.157658-1-tz.stoyanov@gmail.com> References: <20210121074456.157658-1-tz.stoyanov@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org Some timestamp synchronization plugins may not support all ftrace clocks. Added logic to timestamp synchronization plugins to declare what ftrace clocks they support. Added logic to select plugin depending on the ftrace clock used in the current trace session and supported clocks. Signed-off-by: Tzvetomir Stoyanov (VMware) --- .../include/private/trace-cmd-private.h | 4 +-- lib/trace-cmd/include/trace-tsync-local.h | 1 + lib/trace-cmd/trace-timesync.c | 30 +++++++++++++++---- tracecmd/trace-record.c | 10 ++++++- tracecmd/trace-tsync.c | 2 +- 5 files changed, 38 insertions(+), 9 deletions(-) diff --git a/lib/trace-cmd/include/private/trace-cmd-private.h b/lib/trace-cmd/include/private/trace-cmd-private.h index 0d323947..ff700e44 100644 --- a/lib/trace-cmd/include/private/trace-cmd-private.h +++ b/lib/trace-cmd/include/private/trace-cmd-private.h @@ -430,8 +430,8 @@ struct tracecmd_time_sync { }; void tracecmd_tsync_init(void); -int tracecmd_tsync_proto_getall(struct tracecmd_tsync_protos **protos); -const char *tracecmd_tsync_proto_select(struct tracecmd_tsync_protos *protos); +int tracecmd_tsync_proto_getall(struct tracecmd_tsync_protos **protos, const char *clock); +const char *tracecmd_tsync_proto_select(struct tracecmd_tsync_protos *protos, char *clock); bool tsync_proto_is_supported(const char *proto_name); void tracecmd_tsync_with_host(struct tracecmd_time_sync *tsync); void tracecmd_tsync_with_guest(struct tracecmd_time_sync *tsync); diff --git a/lib/trace-cmd/include/trace-tsync-local.h b/lib/trace-cmd/include/trace-tsync-local.h index 58841a4c..96ec89e9 100644 --- a/lib/trace-cmd/include/trace-tsync-local.h +++ b/lib/trace-cmd/include/trace-tsync-local.h @@ -27,6 +27,7 @@ struct clock_sync_context { }; int tracecmd_tsync_proto_register(const char *proto_name, int accuracy, + int supported_clocks, int (*init)(struct tracecmd_time_sync *), int (*free)(struct tracecmd_time_sync *), int (*calc)(struct tracecmd_time_sync *, diff --git a/lib/trace-cmd/trace-timesync.c b/lib/trace-cmd/trace-timesync.c index c9fde0fa..0d46d294 100644 --- a/lib/trace-cmd/trace-timesync.c +++ b/lib/trace-cmd/trace-timesync.c @@ -26,6 +26,7 @@ struct tsync_proto { struct tsync_proto *next; char proto_name[TRACECMD_TSYNC_PNAME_LENGTH]; int accuracy; + int supported_clocks; int (*clock_sync_init)(struct tracecmd_time_sync *clock_context); int (*clock_sync_free)(struct tracecmd_time_sync *clock_context); @@ -50,6 +51,7 @@ static struct tsync_proto *tsync_proto_find(const char *proto_name) } int tracecmd_tsync_proto_register(const char *proto_name, int accuracy, + int supported_clocks, int (*init)(struct tracecmd_time_sync *), int (*free)(struct tracecmd_time_sync *), int (*calc)(struct tracecmd_time_sync *, @@ -64,6 +66,7 @@ int tracecmd_tsync_proto_register(const char *proto_name, int accuracy, return -1; strncpy(proto->proto_name, proto_name, TRACECMD_TSYNC_PNAME_LENGTH); proto->accuracy = accuracy; + proto->supported_clocks = supported_clocks; proto->clock_sync_init = init; proto->clock_sync_free = free; proto->clock_sync_calc = calc; @@ -137,23 +140,29 @@ int tracecmd_tsync_get_offsets(struct tracecmd_time_sync *tsync, * timestamp synchronization with a peer * * @protos: list of tsync protocol names + * @clock : trace clock * * Retuns pointer to a protocol name, that can be used with the peer, or NULL * in case there is no match with supported protocols. * The returned string MUST NOT be freed by the caller */ -const char *tracecmd_tsync_proto_select(struct tracecmd_tsync_protos *protos) +const char *tracecmd_tsync_proto_select(struct tracecmd_tsync_protos *protos, char *clock) { struct tsync_proto *selected = NULL; struct tsync_proto *proto; char **pname; + int clock_id = 0; if (!protos) return NULL; + clock_id = tracecmd_clock_str2id(clock); pname = protos->names; while (*pname) { for (proto = tsync_proto_list; proto; proto = proto->next) { + if (proto->supported_clocks && clock_id && + !(proto->supported_clocks & clock_id)) + continue; if (strncmp(proto->proto_name, *pname, TRACECMD_TSYNC_PNAME_LENGTH)) continue; if (selected) { @@ -176,20 +185,28 @@ const char *tracecmd_tsync_proto_select(struct tracecmd_tsync_protos *protos) * time sync protocols * @protos: return, allocated list of time sync protocol names, * supported by the peer. Must be freed by free() + * @clock: selected trace clock * * If completed successfully 0 is returned and allocated list of strings in @protos. * The last list entry is NULL. In case of an error, -1 is returned. * @protos must be freed with free() */ -int tracecmd_tsync_proto_getall(struct tracecmd_tsync_protos **protos) +int tracecmd_tsync_proto_getall(struct tracecmd_tsync_protos **protos, const char *clock) { struct tracecmd_tsync_protos *plist = NULL; struct tsync_proto *proto; + int clock_id = 0; int count = 1; int i; - for (proto = tsync_proto_list; proto; proto = proto->next) + if (clock) + clock_id = tracecmd_clock_str2id(clock); + for (proto = tsync_proto_list; proto; proto = proto->next) { + if (proto->supported_clocks && clock_id && + !(proto->supported_clocks & clock_id)) + continue; count++; + } plist = calloc(1, sizeof(struct tracecmd_tsync_protos)); if (!plist) goto error; @@ -197,9 +214,12 @@ int tracecmd_tsync_proto_getall(struct tracecmd_tsync_protos **protos) if (!plist->names) return -1; - for (i = 0, proto = tsync_proto_list; proto && i < (count - 1); proto = proto->next) + for (i = 0, proto = tsync_proto_list; proto && i < (count - 1); proto = proto->next) { + if (proto->supported_clocks && clock_id && + !(proto->supported_clocks & clock_id)) + continue; plist->names[i++] = proto->proto_name; - + } *protos = plist; return 0; diff --git a/tracecmd/trace-record.c b/tracecmd/trace-record.c index a0e128d6..51b8562b 100644 --- a/tracecmd/trace-record.c +++ b/tracecmd/trace-record.c @@ -3675,8 +3675,11 @@ static void connect_to_agent(struct buffer_instance *instance) if (!msg_handle) die("Failed to allocate message handle"); + if (!instance->clock) + instance->clock = tracefs_get_clock(NULL); + if (instance->tsync.loop_interval >= 0) - tracecmd_tsync_proto_getall(&protos); + tracecmd_tsync_proto_getall(&protos, instance->clock); ret = tracecmd_msg_send_trace_req(msg_handle, instance->argc, instance->argv, use_fifos, @@ -6098,6 +6101,11 @@ static void parse_record_options(int argc, (char *)top_instance.clock, true); add_argv(instance, "-C", true); + if (!instance->clock) { + instance->clock = strdup((char *)top_instance.clock); + if (!instance->clock) + die("Could not allocate instance clock"); + } } } instance->tsync.loop_interval = top_instance.tsync.loop_interval; diff --git a/tracecmd/trace-tsync.c b/tracecmd/trace-tsync.c index 5781cfd2..55e9857f 100644 --- a/tracecmd/trace-tsync.c +++ b/tracecmd/trace-tsync.c @@ -223,7 +223,7 @@ const char *tracecmd_guest_tsync(struct tracecmd_tsync_protos *tsync_protos, int fd; fd = -1; - proto = tracecmd_tsync_proto_select(tsync_protos); + proto = tracecmd_tsync_proto_select(tsync_protos, clock); if (!proto) return NULL; #ifdef VSOCK From patchwork Thu Jan 21 07:44:46 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Tzvetomir Stoyanov (VMware)" X-Patchwork-Id: 12035039 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.7 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5AD2AC433DB for ; Thu, 21 Jan 2021 07:47:06 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 0D04B221F7 for ; Thu, 21 Jan 2021 07:47:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727617AbhAUHrA (ORCPT ); Thu, 21 Jan 2021 02:47:00 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50086 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727486AbhAUHqu (ORCPT ); Thu, 21 Jan 2021 02:46:50 -0500 Received: from mail-wr1-x434.google.com (mail-wr1-x434.google.com [IPv6:2a00:1450:4864:20::434]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 00262C061786 for ; Wed, 20 Jan 2021 23:45:05 -0800 (PST) Received: by mail-wr1-x434.google.com with SMTP id m4so726069wrx.9 for ; Wed, 20 Jan 2021 23:45:05 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=5AAAU2KuAwiS3y+C6rroB9X9yFzrMkMjZzsI+OdnWqM=; b=P6/JD0qHl51bGO8ku603PheTdRs8jhwxmKccwGeB2lABLmTdPB8t7r27dw973oF2i2 v3Euxf8RHhgLnE8ZtfIrxYret5xEBa1VxStkBJ0MF/cu9GMT74ff4PuzVj5leYTwirYo ObPfnSBqT3aYuKzhUS9Cvbo3/tzQ3tsb2BpYBeGfy/qSSNuisF2twHXJW5gIKdwSAkWu RyEunMjP+J6g5wf/HCZuOfcD+ab8VDR4B1Vfbx7N5TyVS+84Z+XEngnUI/E6qGthN3cc 00h9HykpipEko+A1lnQGTPQRzLrUVzPGhDvfQJd5F6FrwcYkjgnbnMUKaMnqX8xYeXxc cAgA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=5AAAU2KuAwiS3y+C6rroB9X9yFzrMkMjZzsI+OdnWqM=; b=qup32bMvERFdz27fGHFR17COfGL97TJ50cotfz/8cCiRxdhlDezLKearkqtSLq/TNH pReM30HiFe8dgaGNMZxrcGKzC4bVlowii4n7wEGm4wKNrJkUluxA0SMVNoSUy4LBYK/L vGqbqNah76iDUXz2bGTrh1pqb24g9OL5nE3XvLe5oTqM32lrI4UsZcAVQREGHJLhysEa OxzHCQbW+6SLXrOSDhnZJU0VBAoewXJqn8h6AseJ4tnLor0YAlJwEHDEtQHmzG2m8k03 JH3uDpDpVvg2NmNiZZiCz8Z495pTx+Dj6qOwYYt2SLsfQ5eGHCQUAmMjcTDhS9vWip08 PifA== X-Gm-Message-State: AOAM531idVZrbgvuEMx0ylI+h/FS+LvXHw64wySFfK1hc0oZNa6hpzLL Knf+qxbNcoo8xcAetHv+S9zP0Qspb75ci/Uw X-Google-Smtp-Source: ABdhPJwEVg9tcJsybX4mrwvJYB2+/Ty4StPAR6Uex6ml8eP9FngUmUZlf17M3TqhKMhm46pYSySXUA== X-Received: by 2002:adf:b1da:: with SMTP id r26mr13479782wra.198.1611215104752; Wed, 20 Jan 2021 23:45:04 -0800 (PST) Received: from oberon.zico.biz ([83.222.187.186]) by smtp.gmail.com with ESMTPSA id q6sm6788474wmj.32.2021.01.20.23.45.03 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 20 Jan 2021 23:45:04 -0800 (PST) From: "Tzvetomir Stoyanov (VMware)" To: rostedt@goodmis.org Cc: linux-trace-devel@vger.kernel.org Subject: [PATCH v26 05/15] trace-cmd: Add role parameter to timestamp synchronization plugins Date: Thu, 21 Jan 2021 09:44:46 +0200 Message-Id: <20210121074456.157658-6-tz.stoyanov@gmail.com> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210121074456.157658-1-tz.stoyanov@gmail.com> References: <20210121074456.157658-1-tz.stoyanov@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org Defined HOST and GUEST roles in timestamp synchronization context. Some timestamp synchronization plugins may not support running in both host and guest roles. This could happen in nested virtualization use case, where the same plugin can be used as a host and as a guest. Added logic to timestamp synchronization plugins to declare what roles they support. Added logic to select plugin depending on supported roles and currently requested role. Signed-off-by: Tzvetomir Stoyanov (VMware) --- .../include/private/trace-cmd-private.h | 10 ++++++++-- lib/trace-cmd/include/trace-tsync-local.h | 2 +- lib/trace-cmd/trace-timesync.c | 18 +++++++++++++++--- tracecmd/trace-record.c | 3 ++- tracecmd/trace-tsync.c | 3 ++- 5 files changed, 28 insertions(+), 8 deletions(-) diff --git a/lib/trace-cmd/include/private/trace-cmd-private.h b/lib/trace-cmd/include/private/trace-cmd-private.h index ff700e44..685abf13 100644 --- a/lib/trace-cmd/include/private/trace-cmd-private.h +++ b/lib/trace-cmd/include/private/trace-cmd-private.h @@ -419,6 +419,11 @@ enum{ TRACECMD_TIME_SYNC_CMD_STOP = 2, }; +enum tracecmd_time_sync_role { + TRACECMD_TIME_SYNC_ROLE_HOST = (1 << 0), + TRACECMD_TIME_SYNC_ROLE_GUEST = (1 << 1), +}; + struct tracecmd_time_sync { const char *proto_name; int loop_interval; @@ -430,8 +435,9 @@ struct tracecmd_time_sync { }; void tracecmd_tsync_init(void); -int tracecmd_tsync_proto_getall(struct tracecmd_tsync_protos **protos, const char *clock); -const char *tracecmd_tsync_proto_select(struct tracecmd_tsync_protos *protos, char *clock); +int tracecmd_tsync_proto_getall(struct tracecmd_tsync_protos **protos, const char *clock, int role); +const char *tracecmd_tsync_proto_select(struct tracecmd_tsync_protos *protos, char *clock, + enum tracecmd_time_sync_role role); bool tsync_proto_is_supported(const char *proto_name); void tracecmd_tsync_with_host(struct tracecmd_time_sync *tsync); void tracecmd_tsync_with_guest(struct tracecmd_time_sync *tsync); diff --git a/lib/trace-cmd/include/trace-tsync-local.h b/lib/trace-cmd/include/trace-tsync-local.h index 96ec89e9..a99725e2 100644 --- a/lib/trace-cmd/include/trace-tsync-local.h +++ b/lib/trace-cmd/include/trace-tsync-local.h @@ -26,7 +26,7 @@ struct clock_sync_context { unsigned int remote_port; }; -int tracecmd_tsync_proto_register(const char *proto_name, int accuracy, +int tracecmd_tsync_proto_register(const char *proto_name, int accuracy, int roles, int supported_clocks, int (*init)(struct tracecmd_time_sync *), int (*free)(struct tracecmd_time_sync *), diff --git a/lib/trace-cmd/trace-timesync.c b/lib/trace-cmd/trace-timesync.c index 0d46d294..def703f6 100644 --- a/lib/trace-cmd/trace-timesync.c +++ b/lib/trace-cmd/trace-timesync.c @@ -25,6 +25,7 @@ struct tsync_proto { struct tsync_proto *next; char proto_name[TRACECMD_TSYNC_PNAME_LENGTH]; + enum tracecmd_time_sync_role roles; int accuracy; int supported_clocks; @@ -50,7 +51,7 @@ static struct tsync_proto *tsync_proto_find(const char *proto_name) return NULL; } -int tracecmd_tsync_proto_register(const char *proto_name, int accuracy, +int tracecmd_tsync_proto_register(const char *proto_name, int accuracy, int roles, int supported_clocks, int (*init)(struct tracecmd_time_sync *), int (*free)(struct tracecmd_time_sync *), @@ -66,6 +67,7 @@ int tracecmd_tsync_proto_register(const char *proto_name, int accuracy, return -1; strncpy(proto->proto_name, proto_name, TRACECMD_TSYNC_PNAME_LENGTH); proto->accuracy = accuracy; + proto->roles = roles; proto->supported_clocks = supported_clocks; proto->clock_sync_init = init; proto->clock_sync_free = free; @@ -141,12 +143,14 @@ int tracecmd_tsync_get_offsets(struct tracecmd_time_sync *tsync, * * @protos: list of tsync protocol names * @clock : trace clock + * @role : local time sync role * * Retuns pointer to a protocol name, that can be used with the peer, or NULL * in case there is no match with supported protocols. * The returned string MUST NOT be freed by the caller */ -const char *tracecmd_tsync_proto_select(struct tracecmd_tsync_protos *protos, char *clock) +const char *tracecmd_tsync_proto_select(struct tracecmd_tsync_protos *protos, char *clock, + enum tracecmd_time_sync_role role) { struct tsync_proto *selected = NULL; struct tsync_proto *proto; @@ -160,6 +164,8 @@ const char *tracecmd_tsync_proto_select(struct tracecmd_tsync_protos *protos, ch pname = protos->names; while (*pname) { for (proto = tsync_proto_list; proto; proto = proto->next) { + if (!(proto->roles & role)) + continue; if (proto->supported_clocks && clock_id && !(proto->supported_clocks & clock_id)) continue; @@ -186,12 +192,13 @@ const char *tracecmd_tsync_proto_select(struct tracecmd_tsync_protos *protos, ch * @protos: return, allocated list of time sync protocol names, * supported by the peer. Must be freed by free() * @clock: selected trace clock + * @role: supported protocol role * * If completed successfully 0 is returned and allocated list of strings in @protos. * The last list entry is NULL. In case of an error, -1 is returned. * @protos must be freed with free() */ -int tracecmd_tsync_proto_getall(struct tracecmd_tsync_protos **protos, const char *clock) +int tracecmd_tsync_proto_getall(struct tracecmd_tsync_protos **protos, const char *clock, int role) { struct tracecmd_tsync_protos *plist = NULL; struct tsync_proto *proto; @@ -202,6 +209,8 @@ int tracecmd_tsync_proto_getall(struct tracecmd_tsync_protos **protos, const cha if (clock) clock_id = tracecmd_clock_str2id(clock); for (proto = tsync_proto_list; proto; proto = proto->next) { + if (!(proto->roles & role)) + continue; if (proto->supported_clocks && clock_id && !(proto->supported_clocks & clock_id)) continue; @@ -215,11 +224,14 @@ int tracecmd_tsync_proto_getall(struct tracecmd_tsync_protos **protos, const cha return -1; for (i = 0, proto = tsync_proto_list; proto && i < (count - 1); proto = proto->next) { + if (!(proto->roles & role)) + continue; if (proto->supported_clocks && clock_id && !(proto->supported_clocks & clock_id)) continue; plist->names[i++] = proto->proto_name; } + *protos = plist; return 0; diff --git a/tracecmd/trace-record.c b/tracecmd/trace-record.c index 51b8562b..3bcb2403 100644 --- a/tracecmd/trace-record.c +++ b/tracecmd/trace-record.c @@ -3679,7 +3679,8 @@ static void connect_to_agent(struct buffer_instance *instance) instance->clock = tracefs_get_clock(NULL); if (instance->tsync.loop_interval >= 0) - tracecmd_tsync_proto_getall(&protos, instance->clock); + tracecmd_tsync_proto_getall(&protos, instance->clock, + TRACECMD_TIME_SYNC_ROLE_HOST); ret = tracecmd_msg_send_trace_req(msg_handle, instance->argc, instance->argv, use_fifos, diff --git a/tracecmd/trace-tsync.c b/tracecmd/trace-tsync.c index 55e9857f..ef20651b 100644 --- a/tracecmd/trace-tsync.c +++ b/tracecmd/trace-tsync.c @@ -223,7 +223,8 @@ const char *tracecmd_guest_tsync(struct tracecmd_tsync_protos *tsync_protos, int fd; fd = -1; - proto = tracecmd_tsync_proto_select(tsync_protos, clock); + proto = tracecmd_tsync_proto_select(tsync_protos, clock, + TRACECMD_TIME_SYNC_ROLE_GUEST); if (!proto) return NULL; #ifdef VSOCK From patchwork Thu Jan 21 07:44:47 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Tzvetomir Stoyanov (VMware)" X-Patchwork-Id: 12035037 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 76DF2C433E0 for ; Thu, 21 Jan 2021 07:47:03 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 317C8221F7 for ; Thu, 21 Jan 2021 07:47:03 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726760AbhAUHq7 (ORCPT ); Thu, 21 Jan 2021 02:46:59 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50088 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727617AbhAUHqu (ORCPT ); Thu, 21 Jan 2021 02:46:50 -0500 Received: from mail-wr1-x429.google.com (mail-wr1-x429.google.com [IPv6:2a00:1450:4864:20::429]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 06A00C061793 for ; Wed, 20 Jan 2021 23:45:07 -0800 (PST) Received: by mail-wr1-x429.google.com with SMTP id a1so734310wrq.6 for ; Wed, 20 Jan 2021 23:45:06 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=nswyThKLN9CSj5N5XKRVl6p5SammQACUOtZ/xPnYjYI=; b=jxvwmtIJvmtYk0uMW0nCrNrw5B63jY1iww41pDuS1v9JruBSgDwbxNgKAMr7+IFJpY q6tcdZIgAuN5HzcVqVoLfA4F7VEQAjcwfd567/a0ykiZ4kjzqG/Q0ASrQG1J6TAAv7b8 CL33gVeEWcRv1OwhQStu2DyOu7j+eR1voRV4uSkqj0GlALzGGZw09FtW018YC1Vvatbh 9gLM9/xUCrIu98V3NGfI0421fOLG5gDRvhvh709bNUaX1RFVPcV9m9MCaAEZgz3dl9xY 6u0NKDR89v+iyPC2tHHxokPO+4oxQwnjNPAYxTe9gDNUIAPnn19bK5p72bxgSjqeaNyO dRDA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=nswyThKLN9CSj5N5XKRVl6p5SammQACUOtZ/xPnYjYI=; b=MEB0LfENeg5Dci6jHs0HFAAGx1BJezUcvdR9417JiBdeCyqLJQNkOmULhrGjGwc+qP OEqwww6Cw4FwL2MfHJPIPkwN6zlqmWJAmmwyS78oh2hgLrGKowJ9EUQ63F6sFwKkoaVR wbW5Qeg3DGzR8WFee8qOf5utXAqxwWShcpWjxnUzK31YV+XowsEhN+dLNfHp8svEV82H J8b6iWhMbMCtP+uhP27mhvfz5l/FVhZi8r8+Cm4Y58IPjumsKSqzygdzABaUrbblptwH TYAi7Ac6TJpJiz86HLHNQfUjPO+20QmbyJqhWXKr+brYnRyu8oKyZiWNF1YgYr+witDn KIeg== X-Gm-Message-State: AOAM532dg7qRHw/CvuAbADPsgCntmUruYrZZv3wxOTtAIRB+B7Q/XNp9 fvMsfko53nEd/FCg9m6GGyY= X-Google-Smtp-Source: ABdhPJxynYLdfD7W3pkOYMucQVBgqBpW7CA9rA6VS2J9L9SPbnwDuxXPbPJ57uu1Dw/WLJ+GF1Zp6g== X-Received: by 2002:a5d:4243:: with SMTP id s3mr12785130wrr.31.1611215105846; Wed, 20 Jan 2021 23:45:05 -0800 (PST) Received: from oberon.zico.biz ([83.222.187.186]) by smtp.gmail.com with ESMTPSA id q6sm6788474wmj.32.2021.01.20.23.45.04 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 20 Jan 2021 23:45:05 -0800 (PST) From: "Tzvetomir Stoyanov (VMware)" To: rostedt@goodmis.org Cc: linux-trace-devel@vger.kernel.org Subject: [PATCH v26 06/15] trace-cmd: Add host / guest role in timestamp synchronization context Date: Thu, 21 Jan 2021 09:44:47 +0200 Message-Id: <20210121074456.157658-7-tz.stoyanov@gmail.com> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210121074456.157658-1-tz.stoyanov@gmail.com> References: <20210121074456.157658-1-tz.stoyanov@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org Added new parameter in timestamp synchronization context, holding the current role in the timestamp synchronization process - host or guest. Signed-off-by: Tzvetomir Stoyanov (VMware) --- lib/trace-cmd/include/trace-tsync-local.h | 1 + lib/trace-cmd/trace-timesync.c | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/trace-cmd/include/trace-tsync-local.h b/lib/trace-cmd/include/trace-tsync-local.h index a99725e2..1dea054c 100644 --- a/lib/trace-cmd/include/trace-tsync-local.h +++ b/lib/trace-cmd/include/trace-tsync-local.h @@ -11,6 +11,7 @@ struct clock_sync_context { void *proto_data; /* time sync protocol specific data */ bool is_server; /* server side time sync role */ + bool is_guest; /* guest or host time sync role */ struct tracefs_instance *instance; /* ftrace buffer, used for time sync events */ /* Arrays with calculated time offsets at given time */ diff --git a/lib/trace-cmd/trace-timesync.c b/lib/trace-cmd/trace-timesync.c index def703f6..f3cc2da6 100644 --- a/lib/trace-cmd/trace-timesync.c +++ b/lib/trace-cmd/trace-timesync.c @@ -296,7 +296,7 @@ clock_synch_delete_instance(struct tracefs_instance *inst) tracefs_instance_free(inst); } -static int clock_context_init(struct tracecmd_time_sync *tsync, bool server) +static int clock_context_init(struct tracecmd_time_sync *tsync, bool guest) { struct clock_sync_context *clock = NULL; struct tsync_proto *protocol; @@ -311,8 +311,9 @@ static int clock_context_init(struct tracecmd_time_sync *tsync, bool server) clock = calloc(1, sizeof(struct clock_sync_context)); if (!clock) return -1; + clock->is_guest = guest; + clock->is_server = clock->is_guest; - clock->is_server = server; if (get_vsocket_params(tsync->msg_handle->fd, &clock->local_cid, &clock->local_port, &clock->remote_cid, &clock->remote_port)) From patchwork Thu Jan 21 07:44:48 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Tzvetomir Stoyanov (VMware)" X-Patchwork-Id: 12035041 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 00402C433DB for ; Thu, 21 Jan 2021 07:47:15 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id CD0E623356 for ; Thu, 21 Jan 2021 07:47:15 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727486AbhAUHrD (ORCPT ); Thu, 21 Jan 2021 02:47:03 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50118 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726208AbhAUHq5 (ORCPT ); Thu, 21 Jan 2021 02:46:57 -0500 Received: from mail-wr1-x42b.google.com (mail-wr1-x42b.google.com [IPv6:2a00:1450:4864:20::42b]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 40046C061794 for ; Wed, 20 Jan 2021 23:45:08 -0800 (PST) Received: by mail-wr1-x42b.google.com with SMTP id a1so734370wrq.6 for ; Wed, 20 Jan 2021 23:45:08 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=hMq9nQeSzosYGpQsRepfvrukWUuTkBSj01DDphxOECY=; b=P+yPSzNPSe8vfW1hewRX6rosD7pY9Aal6tMgRLNl7Rthn4Y5rheS0hE40C6M0jeK/e 75Y41Fk5HBeHQf5QZ5klcFkXZJuMTL3Bj3yAAjrvslEtUG/SM4JhBYk3MXtJIeA4CyjR 9NnnWfjq2CwR0AWD0BnCfL85apGLz16Q02KivsvbP4LgVKKg1EXikvLr9IdUpX8JuL+T kZUWGO2SN1lBxZoq21dK8hWwewOmuJkpjYjwrlZLl08flyaB8YejSuAMG7avVy+/MO1Q uQyWZJDAZW185Mq27MyBGOKcvbqi8zj3xcPfeIDkd2MpSMoPrpSaSYDnKUd9/d5h0rJ4 IROA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=hMq9nQeSzosYGpQsRepfvrukWUuTkBSj01DDphxOECY=; b=bh4h1OH1zHgj3GxcfvlnbLIbQoSyBP88lddDqRz5P6+eL3bTRvhMbEtlYKZYuHvDzi xH6G0rux/Q7CiRMTolV4gVdM9VRAWPJnJs2Z8JXyZu12lday96sY0p1ElPqned8Us6Fg hq/r8SwdUquilTcOTM1GKiHrsw52fKa8jYHhbVu46Qb6A2+QwQtejvFeGJxuEYoqOy4H hdf5qIlXds+avbCUm3GE1TsPZhyUCfwbGOZ5UyrkCwvDTFsCrSDXiQ4+c61RUwtTL6vf U7rbTl/blrTi8i0E7SWsQiRiZnDqC5DyLTIZHod6roInyNFMBMIfNMmkPFYC7ZbxRCBO 1Zqg== X-Gm-Message-State: AOAM5338jwuX7niEelAimAkesotIDAXYcH861tCE6BM667qroy5S7iFq nqGczo829XaD0jvmTYacRL4= X-Google-Smtp-Source: ABdhPJxA6i+k5dRNKZ8+gxFUjp0ec/ZuwENecQQrzzBbrsvOTPQl3LsVa5o3Etw2s6DwDcP7BLBgoA== X-Received: by 2002:a5d:44c6:: with SMTP id z6mr12790266wrr.306.1611215107026; Wed, 20 Jan 2021 23:45:07 -0800 (PST) Received: from oberon.zico.biz ([83.222.187.186]) by smtp.gmail.com with ESMTPSA id q6sm6788474wmj.32.2021.01.20.23.45.05 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 20 Jan 2021 23:45:06 -0800 (PST) From: "Tzvetomir Stoyanov (VMware)" To: rostedt@goodmis.org Cc: linux-trace-devel@vger.kernel.org Subject: [PATCH v26 07/15] trace-cmd: Add guest CPU count PID in tracecmd_time_sync struct Date: Thu, 21 Jan 2021 09:44:48 +0200 Message-Id: <20210121074456.157658-8-tz.stoyanov@gmail.com> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210121074456.157658-1-tz.stoyanov@gmail.com> References: <20210121074456.157658-1-tz.stoyanov@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org The tracecmd_time_sync struct holds the timestamp synchronization context, used by the timestamp synchronization plugins. Guest CPU count and PID of the host task, running the guest, is important information which may be needed by the plugins. Signed-off-by: Tzvetomir Stoyanov (VMware) --- lib/trace-cmd/include/private/trace-cmd-private.h | 2 ++ tracecmd/trace-tsync.c | 7 ++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/trace-cmd/include/private/trace-cmd-private.h b/lib/trace-cmd/include/private/trace-cmd-private.h index 685abf13..ce7d87be 100644 --- a/lib/trace-cmd/include/private/trace-cmd-private.h +++ b/lib/trace-cmd/include/private/trace-cmd-private.h @@ -432,6 +432,8 @@ struct tracecmd_time_sync { char *clock_str; struct tracecmd_msg_handle *msg_handle; void *context; + int guest_pid; + int vcpu_count; }; void tracecmd_tsync_init(void); diff --git a/tracecmd/trace-tsync.c b/tracecmd/trace-tsync.c index ef20651b..3d67f5af 100644 --- a/tracecmd/trace-tsync.c +++ b/tracecmd/trace-tsync.c @@ -77,6 +77,7 @@ int tracecmd_host_tsync(struct buffer_instance *instance, { struct tracecmd_msg_handle *msg_handle = NULL; cpu_set_t *pin_mask = NULL; + struct trace_guest *guest; pthread_attr_t attrib; size_t mask_size = 0; int ret; @@ -84,7 +85,11 @@ int tracecmd_host_tsync(struct buffer_instance *instance, if (!instance->tsync.proto_name) return -1; - + guest = get_guest_by_cid(instance->cid); + if (guest == NULL) + return -1; + instance->tsync.guest_pid = guest->pid; + instance->tsync.vcpu_count = guest->cpu_max; fd = trace_open_vsock(instance->cid, tsync_port); if (fd < 0) { ret = -1; From patchwork Thu Jan 21 07:44:49 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Tzvetomir Stoyanov (VMware)" X-Patchwork-Id: 12035045 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id B80F8C433DB for ; Thu, 21 Jan 2021 07:47:20 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 6996423356 for ; Thu, 21 Jan 2021 07:47:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727306AbhAUHrK (ORCPT ); Thu, 21 Jan 2021 02:47:10 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50120 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726382AbhAUHq6 (ORCPT ); Thu, 21 Jan 2021 02:46:58 -0500 Received: from mail-wr1-x431.google.com (mail-wr1-x431.google.com [IPv6:2a00:1450:4864:20::431]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 694B4C061795 for ; Wed, 20 Jan 2021 23:45:09 -0800 (PST) Received: by mail-wr1-x431.google.com with SMTP id l12so746107wry.2 for ; Wed, 20 Jan 2021 23:45:09 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=fcQL73xJp7wk8x00EZXT2tlt0j071iAOIuVEeG0g21E=; b=EQTbgd3SMZeX4QtdMm8aXlZGgsqLvpCbIunHvKR+i48AmTfPHU2UxryAroxJ7h9vQO 6DJFN+PSKnddUiAqeaCVt2WqEdBEU0NHZe+MXUrjfzePxaVBes3MM6VJDFlEnmzUOxKz KT1DHLAGmN292rI+n4chMQaWksr83bNI8iyuX8E7tD649S0iFPgi1r4Sbu6+G0J6fbfS R/F0zBepOwofWJDUuBJxm2+JT+gR1o0XPpiKWhyRSHvVoqj+WlDSZ9+N8w+LTT3Fkx46 5x+ScMQ3FVJLQtqHg+dRL8qsoZ5XDmkpMfnq0+CEgZsIatOOgs0hVT+5p05iwiNJawk1 GIbw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=fcQL73xJp7wk8x00EZXT2tlt0j071iAOIuVEeG0g21E=; b=gaDDNe+kfX/e/lX5mzBbXA3eqAiIgBF6MbKCZQ6QhpUIUMcf/1K0sEQ7Y7dL/tHR9H LP+GLel++brEk6lJnhJwpin3FcIIafYzKjbi/3nhvytynWnBDcjf49TqbblMyH9lLJo0 wzNDGzisa/2N+lMpWlayf9Ui3EOcTTtwKxmAgP3ObHDMQYVcyV9PO+wq0YSk1x/lhzXc TJDfpMHp/NYcptW3/89sx7tQdYqLCbGge5gPgEHa4yTq1u/ufHS4xU5xQXvmWxd1kf4H LuAQ2lJxKuvy9uwF14BcOiq0m9rfSMTtnQNRc2mAVYPhmSc/x6jPi5eFB6ax6lQ/AsZf Cc5Q== X-Gm-Message-State: AOAM531etfgfwZGh9baLdXSurbNjOI9c10WLgE1NQG5HkeI847MkhXhK Wwp95wSYoZ4ITcYsnH9Bsd4XpFzaguqkcbDK X-Google-Smtp-Source: ABdhPJxf1gQHljHkgLfukv3yOL2lyyPT8UYn9EXomNXKBkdTG4GsfSwZdD3K2WTTf19WHoPITMo4vA== X-Received: by 2002:a5d:4cd1:: with SMTP id c17mr12831431wrt.49.1611215108192; Wed, 20 Jan 2021 23:45:08 -0800 (PST) Received: from oberon.zico.biz ([83.222.187.186]) by smtp.gmail.com with ESMTPSA id q6sm6788474wmj.32.2021.01.20.23.45.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 20 Jan 2021 23:45:07 -0800 (PST) From: "Tzvetomir Stoyanov (VMware)" To: rostedt@goodmis.org Cc: linux-trace-devel@vger.kernel.org Subject: [PATCH v26 08/15] trace-cmd: Add scaling ratio for timestamp correction Date: Thu, 21 Jan 2021 09:44:49 +0200 Message-Id: <20210121074456.157658-9-tz.stoyanov@gmail.com> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210121074456.157658-1-tz.stoyanov@gmail.com> References: <20210121074456.157658-1-tz.stoyanov@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org Some hypervisors support guest time scaling by given ratio, additional to the time offset. The guest time is calculated using the formula: guest time = host time * scaling ratio + time offset Scaling is useful in case of guest VM migration to a different host machine. The scaling parameter is added to timestamp synchronization algorithms. It is saved in trace.dat file metadata and is used in timestamp calculations when reading the file. Signed-off-by: Tzvetomir Stoyanov (VMware) --- .../include/private/trace-cmd-private.h | 4 +-- lib/trace-cmd/include/trace-tsync-local.h | 11 +++++-- lib/trace-cmd/trace-input.c | 8 ++++- lib/trace-cmd/trace-timesync.c | 32 ++++++++++++++----- tracecmd/trace-dump.c | 11 +++++-- tracecmd/trace-tsync.c | 16 ++++++---- 6 files changed, 60 insertions(+), 22 deletions(-) diff --git a/lib/trace-cmd/include/private/trace-cmd-private.h b/lib/trace-cmd/include/private/trace-cmd-private.h index ce7d87be..00f8d11e 100644 --- a/lib/trace-cmd/include/private/trace-cmd-private.h +++ b/lib/trace-cmd/include/private/trace-cmd-private.h @@ -444,8 +444,8 @@ bool tsync_proto_is_supported(const char *proto_name); void tracecmd_tsync_with_host(struct tracecmd_time_sync *tsync); void tracecmd_tsync_with_guest(struct tracecmd_time_sync *tsync); int tracecmd_tsync_get_offsets(struct tracecmd_time_sync *tsync, - int *count, - long long **ts, long long **offsets); + int *count, long long **ts, + long long **offsets, long long **scalings); void tracecmd_tsync_free(struct tracecmd_time_sync *tsync); /* --- Plugin handling --- */ diff --git a/lib/trace-cmd/include/trace-tsync-local.h b/lib/trace-cmd/include/trace-tsync-local.h index 1dea054c..c34d9ab7 100644 --- a/lib/trace-cmd/include/trace-tsync-local.h +++ b/lib/trace-cmd/include/trace-tsync-local.h @@ -15,10 +15,15 @@ struct clock_sync_context { struct tracefs_instance *instance; /* ftrace buffer, used for time sync events */ /* Arrays with calculated time offsets at given time */ - int sync_size; /* Allocated size of sync_ts and sync_offsets */ - int sync_count; /* Number of elements in sync_ts and sync_offsets */ + int sync_size; /* Allocated size of sync_ts, + * sync_offsets and sync_scalings + */ + int sync_count; /* Number of elements in sync_ts, + * sync_offsets and sync_scalings + */ long long *sync_ts; long long *sync_offsets; + long long *sync_scalings; /* Identifiers of local and remote time sync peers: cid and port */ unsigned int local_cid; @@ -32,7 +37,7 @@ int tracecmd_tsync_proto_register(const char *proto_name, int accuracy, int role int (*init)(struct tracecmd_time_sync *), int (*free)(struct tracecmd_time_sync *), int (*calc)(struct tracecmd_time_sync *, - long long *, long long *)); + long long *, long long *, long long *)); int tracecmd_tsync_proto_unregister(char *proto_name); int ptp_clock_sync_register(void); diff --git a/lib/trace-cmd/trace-input.c b/lib/trace-cmd/trace-input.c index 9dda0dd5..1ce26563 100644 --- a/lib/trace-cmd/trace-input.c +++ b/lib/trace-cmd/trace-input.c @@ -80,6 +80,7 @@ struct input_buffer_instance { struct ts_offset_sample { long long time; long long offset; + long long scaling; }; struct guest_trace_info { @@ -1123,12 +1124,14 @@ static inline unsigned long long timestamp_correction_calc(unsigned long long ts, struct ts_offset_sample *min, struct ts_offset_sample *max) { + long long scaling = (min->scaling + max->scaling) / 2; long long offset = ((long long)ts - min->time) * (max->offset - min->offset); long long delta = max->time - min->time; long long tscor = min->offset + (offset + delta / 2) / delta; + ts *= scaling; if (tscor < 0) return ts - llabs(tscor); @@ -2181,7 +2184,9 @@ static void tsync_offset_load(struct tracecmd_input *handle, char *buf) host->ts_samples[i].time = tep_read_number(handle->pevent, buf8 + i, 8); host->ts_samples[i].offset = tep_read_number(handle->pevent, - buf8 + host->ts_samples_count+i, 8); + buf8 + host->ts_samples_count + i, 8); + host->ts_samples[i].scaling = tep_read_number(handle->pevent, + buf8 + (2 * host->ts_samples_count) + i, 8); } qsort(host->ts_samples, host->ts_samples_count, sizeof(struct ts_offset_sample), tsync_offset_cmp); @@ -2534,6 +2539,7 @@ static int handle_options(struct tracecmd_input *handle) * long long array of size [count] of times, * when the offsets were calculated. * long long array of size [count] of timestamp offsets. + * long long array of size [count] of timestamp scaling ratios.* */ if (size < 12 || handle->flags & TRACECMD_FL_IGNORE_DATE) break; diff --git a/lib/trace-cmd/trace-timesync.c b/lib/trace-cmd/trace-timesync.c index f3cc2da6..9b12e20f 100644 --- a/lib/trace-cmd/trace-timesync.c +++ b/lib/trace-cmd/trace-timesync.c @@ -32,7 +32,8 @@ struct tsync_proto { int (*clock_sync_init)(struct tracecmd_time_sync *clock_context); int (*clock_sync_free)(struct tracecmd_time_sync *clock_context); int (*clock_sync_calc)(struct tracecmd_time_sync *clock_context, - long long *offset, long long *timestamp); + long long *offset, long long *scaling, + long long *timestamp); }; static struct tsync_proto *tsync_proto_list; @@ -56,7 +57,7 @@ int tracecmd_tsync_proto_register(const char *proto_name, int accuracy, int role int (*init)(struct tracecmd_time_sync *), int (*free)(struct tracecmd_time_sync *), int (*calc)(struct tracecmd_time_sync *, - long long *, long long *)) + long long *, long long *, long long *)) { struct tsync_proto *proto = NULL; @@ -113,12 +114,13 @@ bool tsync_proto_is_supported(const char *proto_name) * @count: Returns the number of calculated time offsets * @ts: Array of size @count containing timestamps of callculated offsets * @offsets: array of size @count, containing offsets for each timestamp + * @scalings: array of size @count, containing scaling ratios for each timestamp * * Retuns -1 in case of an error, or 0 otherwise */ int tracecmd_tsync_get_offsets(struct tracecmd_time_sync *tsync, - int *count, - long long **ts, long long **offsets) + int *count, long long **ts, + long long **offsets, long long **scalings) { struct clock_sync_context *tsync_context; @@ -131,6 +133,9 @@ int tracecmd_tsync_get_offsets(struct tracecmd_time_sync *tsync, *ts = tsync_context->sync_ts; if (offsets) *offsets = tsync_context->sync_offsets; + if (scalings) + *scalings = tsync_context->sync_scalings; + return 0; } @@ -360,8 +365,10 @@ void tracecmd_tsync_free(struct tracecmd_time_sync *tsync) free(tsync_context->sync_ts); free(tsync_context->sync_offsets); + free(tsync_context->sync_scalings); tsync_context->sync_ts = NULL; tsync_context->sync_offsets = NULL; + tsync_context->sync_scalings = NULL; tsync_context->sync_count = 0; tsync_context->sync_size = 0; pthread_mutex_destroy(&tsync->lock); @@ -373,10 +380,11 @@ int tracecmd_tsync_send(struct tracecmd_time_sync *tsync, struct tsync_proto *proto) { long long timestamp = 0; + long long scaling = 0; long long offset = 0; int ret; - ret = proto->clock_sync_calc(tsync, &offset, ×tamp); + ret = proto->clock_sync_calc(tsync, &offset, &scaling, ×tamp); return ret; } @@ -424,18 +432,20 @@ static int tsync_get_sample(struct tracecmd_time_sync *tsync, struct tsync_proto *proto, int array_step) { struct clock_sync_context *clock; + long long *sync_scalings = NULL; long long *sync_offsets = NULL; long long *sync_ts = NULL; long long timestamp = 0; + long long scaling = 0; long long offset = 0; int ret; - ret = proto->clock_sync_calc(tsync, &offset, ×tamp); + ret = proto->clock_sync_calc(tsync, &offset, &scaling, ×tamp); if (ret) { warning("Failed to synchronize timestamps with guest"); return -1; } - if (!offset || !timestamp) + if (!offset || !timestamp || !scaling) return 0; clock = tsync->context; if (clock->sync_count >= clock->sync_size) { @@ -443,18 +453,24 @@ static int tsync_get_sample(struct tracecmd_time_sync *tsync, (clock->sync_size + array_step) * sizeof(long long)); sync_offsets = realloc(clock->sync_offsets, (clock->sync_size + array_step) * sizeof(long long)); - if (!sync_ts || !sync_offsets) { + sync_scalings = realloc(clock->sync_scalings, + (clock->sync_size + array_step) * sizeof(long long)); + + if (!sync_ts || !sync_offsets || !sync_scalings) { free(sync_ts); free(sync_offsets); + free(sync_scalings); return -1; } clock->sync_size += array_step; clock->sync_ts = sync_ts; clock->sync_offsets = sync_offsets; + clock->sync_scalings = sync_scalings; } clock->sync_ts[clock->sync_count] = timestamp; clock->sync_offsets[clock->sync_count] = offset; + clock->sync_scalings[clock->sync_count] = scaling; clock->sync_count++; return 0; diff --git a/tracecmd/trace-dump.c b/tracecmd/trace-dump.c index 5642f12a..0117f979 100644 --- a/tracecmd/trace-dump.c +++ b/tracecmd/trace-dump.c @@ -369,6 +369,7 @@ static void dump_option_xlong(int fd, int size, char *desc) static void dump_option_timeshift(int fd, int size) { + long long *scalings = NULL; long long *offsets = NULL; long long *times = NULL; long long trace_id; @@ -397,19 +398,25 @@ static void dump_option_timeshift(int fd, int size) offsets = calloc(count, sizeof(long long)); if (!offsets) goto out; + scalings = calloc(count, sizeof(long long)); + if (!scalings) + goto out; for (i = 0; i < count; i++) read_file_number(fd, times + i, 8); for (i = 0; i < count; i++) read_file_number(fd, offsets + i, 8); + for (i = 0; i < count; i++) + read_file_number(fd, scalings + i, 8); for (i = 0; i < count; i++) - do_print(OPTIONS, "\t%lld %lld [offset @ time]\n", - offsets[i], times[i]); + do_print(OPTIONS, "\t%lld * %lld %lld [offset * scaling @ time]\n", + offsets[i], scalings[1], times[i]); out: free(times); free(offsets); + free(scalings); } void dump_option_guest(int fd, int size) diff --git a/tracecmd/trace-tsync.c b/tracecmd/trace-tsync.c index 3d67f5af..83954b82 100644 --- a/tracecmd/trace-tsync.c +++ b/tracecmd/trace-tsync.c @@ -135,16 +135,18 @@ out: static void write_guest_time_shift(struct buffer_instance *instance) { struct tracecmd_output *handle; - struct iovec vector[4]; - long long *offsets; - long long *ts; + struct iovec vector[5]; + long long *scalings = NULL; + long long *offsets = NULL; + long long *ts = NULL; const char *file; int count; int ret; int fd; - ret = tracecmd_tsync_get_offsets(&instance->tsync, &count, &ts, &offsets); - if (ret < 0 || !count || !ts || !offsets) + ret = tracecmd_tsync_get_offsets(&instance->tsync, &count, + &ts, &offsets, &scalings); + if (ret < 0 || !count || !ts || !offsets || !scalings) return; file = instance->output_file; @@ -160,7 +162,9 @@ static void write_guest_time_shift(struct buffer_instance *instance) vector[2].iov_base = ts; vector[3].iov_len = 8 * count; vector[3].iov_base = offsets; - tracecmd_add_option_v(handle, TRACECMD_OPTION_TIME_SHIFT, vector, 4); + vector[4].iov_len = 8 * count; + vector[4].iov_base = scalings; + tracecmd_add_option_v(handle, TRACECMD_OPTION_TIME_SHIFT, vector, 5); tracecmd_append_options(handle); tracecmd_output_close(handle); #ifdef TSYNC_DEBUG From patchwork Thu Jan 21 07:44:50 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Tzvetomir Stoyanov (VMware)" X-Patchwork-Id: 12035043 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1B3D7C433E0 for ; Thu, 21 Jan 2021 07:47:16 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id E189B23976 for ; Thu, 21 Jan 2021 07:47:15 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726208AbhAUHrG (ORCPT ); Thu, 21 Jan 2021 02:47:06 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50126 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727306AbhAUHq7 (ORCPT ); Thu, 21 Jan 2021 02:46:59 -0500 Received: from mail-wr1-x434.google.com (mail-wr1-x434.google.com [IPv6:2a00:1450:4864:20::434]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 81ABAC061796 for ; Wed, 20 Jan 2021 23:45:10 -0800 (PST) Received: by mail-wr1-x434.google.com with SMTP id l12so746151wry.2 for ; Wed, 20 Jan 2021 23:45:10 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=wCTW1LrmucZ935W8ywfgNhVLrZoebD/zycJ/NkzVjrc=; b=ICuqVCWiXgsBZmF1H3cN48hL6dOYdgzYS4hktDonyjVPPhKIWPfG8oWjzD1VPGBxA4 /2KEPSoSR4IIS5vfShc7UFl6wVZiis1KuX7/wk6HVbP7ihzdo1F3Q+sj8+K1l/V7BbVR lG3eQMAWGh075UdUTXEXXDPbwTkM0yarzXnC3+qXOVuAkj33jIr9lBisMycxKNUZHqB0 Ik4gx+hxhKkE9QIXRDFRhpSf3nVn4AQTjeONZ8E5WvSVel93UtuRdVXF1SFnlrG+9/oA PXe0wiix2ddb3r9+/r6JL8UnLuY/eJAnzh2dhM7U/JhRA7xT8J8FCgGToHFZkpno2Sla +ERw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=wCTW1LrmucZ935W8ywfgNhVLrZoebD/zycJ/NkzVjrc=; b=BYpu15OYS4fIDijYGma1mTdMtYrNYW+h8HwJhpRHGjH9jrRMu1pPTqHj9DTehFNNoz /p0M7aHy8Dnux8vAK33TpWA7Xz2O7uFWxC/zB1bA0r5HthTO4dnr9y1JjzbM59W1VYbH kepQH1SFjCXTF+nffAf2EjSVfhpp3FEWxFSd2V2D8qqB0azwKi+4j3ktEFZLJcikFSxu tib5yVwoPlCtIiW0IsNa0DnMUsM4eInweRcWa+AB1otGpFFWlI8IvvF1AF6uvHrqNQtd kGf1BLACbnJydT0fAGNv4F+aME+v6pVWQpiaZB3GgeZ07mu03WloBVryjE7y4B9r2mgl Ff0A== X-Gm-Message-State: AOAM533fOkFQciPea8fe/Wvq0DboPQLa2Yd9BuVEbCo28UQnZIYdxWWh K3hIlQy4ZbyVGHQKw7KjKDU= X-Google-Smtp-Source: ABdhPJydzLKQoPEnJglGO1EyvW3io1UfPCYV85ctHjMwVisyuN6LTcr41fZkY6IQfmT6ozuxVEO5OQ== X-Received: by 2002:a5d:4e51:: with SMTP id r17mr12965546wrt.94.1611215109234; Wed, 20 Jan 2021 23:45:09 -0800 (PST) Received: from oberon.zico.biz ([83.222.187.186]) by smtp.gmail.com with ESMTPSA id q6sm6788474wmj.32.2021.01.20.23.45.08 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 20 Jan 2021 23:45:08 -0800 (PST) From: "Tzvetomir Stoyanov (VMware)" To: rostedt@goodmis.org Cc: linux-trace-devel@vger.kernel.org Subject: [PATCH v26 09/15] trace-cmd: Add time sync protocol flags Date: Thu, 21 Jan 2021 09:44:50 +0200 Message-Id: <20210121074456.157658-10-tz.stoyanov@gmail.com> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210121074456.157658-1-tz.stoyanov@gmail.com> References: <20210121074456.157658-1-tz.stoyanov@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org Added 32bit flags for the time synchronization protocols. The first added flag is TRACECMD_TSYNC_FLAG_INTERPOLATE, used to specify how the timestamps must be corrected. - If the flag is set, an interpolation is performed: Find the (min, max) interval from the offsets array and calculate offset specific to the given timestamp using interpolation in that interval. - If the flag is not set, do not interpolate: Find the (min, max) interval from the offsets array and use the min offset for all timestamps within the interval. These flags are set by the timestamp synchronization protocols at the protocol initialization time. Signed-off-by: Tzvetomir Stoyanov (VMware) --- .../include/private/trace-cmd-private.h | 5 ++ lib/trace-cmd/include/trace-tsync-local.h | 2 +- lib/trace-cmd/trace-input.c | 48 ++++++++++++------- lib/trace-cmd/trace-timesync.c | 28 ++++++++++- tracecmd/trace-dump.c | 3 ++ tracecmd/trace-tsync.c | 20 +++++--- 6 files changed, 81 insertions(+), 25 deletions(-) diff --git a/lib/trace-cmd/include/private/trace-cmd-private.h b/lib/trace-cmd/include/private/trace-cmd-private.h index 00f8d11e..d6176337 100644 --- a/lib/trace-cmd/include/private/trace-cmd-private.h +++ b/lib/trace-cmd/include/private/trace-cmd-private.h @@ -436,6 +436,9 @@ struct tracecmd_time_sync { int vcpu_count; }; +/* Timestamp synchronization flags */ +#define TRACECMD_TSYNC_FLAG_INTERPOLATE 0x1 + void tracecmd_tsync_init(void); int tracecmd_tsync_proto_getall(struct tracecmd_tsync_protos **protos, const char *clock, int role); const char *tracecmd_tsync_proto_select(struct tracecmd_tsync_protos *protos, char *clock, @@ -446,6 +449,8 @@ void tracecmd_tsync_with_guest(struct tracecmd_time_sync *tsync); int tracecmd_tsync_get_offsets(struct tracecmd_time_sync *tsync, int *count, long long **ts, long long **offsets, long long **scalings); +int tracecmd_tsync_get_proto_flags(struct tracecmd_time_sync *tsync, + unsigned int *flags); void tracecmd_tsync_free(struct tracecmd_time_sync *tsync); /* --- Plugin handling --- */ diff --git a/lib/trace-cmd/include/trace-tsync-local.h b/lib/trace-cmd/include/trace-tsync-local.h index c34d9ab7..83d1721a 100644 --- a/lib/trace-cmd/include/trace-tsync-local.h +++ b/lib/trace-cmd/include/trace-tsync-local.h @@ -33,7 +33,7 @@ struct clock_sync_context { }; int tracecmd_tsync_proto_register(const char *proto_name, int accuracy, int roles, - int supported_clocks, + int supported_clocks, unsigned int flags, int (*init)(struct tracecmd_time_sync *), int (*free)(struct tracecmd_time_sync *), int (*calc)(struct tracecmd_time_sync *, diff --git a/lib/trace-cmd/trace-input.c b/lib/trace-cmd/trace-input.c index 1ce26563..7d28254e 100644 --- a/lib/trace-cmd/trace-input.c +++ b/lib/trace-cmd/trace-input.c @@ -93,6 +93,7 @@ struct guest_trace_info { struct host_trace_info { unsigned long long peer_trace_id; + unsigned int flags; bool sync_enable; struct tracecmd_input *peer_data; int ts_samples_count; @@ -1121,15 +1122,25 @@ static void free_next(struct tracecmd_input *handle, int cpu) } static inline unsigned long long -timestamp_correction_calc(unsigned long long ts, struct ts_offset_sample *min, +timestamp_correction_calc(unsigned long long ts, unsigned int flags, + struct ts_offset_sample *min, struct ts_offset_sample *max) { - long long scaling = (min->scaling + max->scaling) / 2; - long long offset = ((long long)ts - min->time) * - (max->offset - min->offset); - long long delta = max->time - min->time; - long long tscor = min->offset + - (offset + delta / 2) / delta; + long long scaling; + long long tscor; + + if (flags & TRACECMD_TSYNC_FLAG_INTERPOLATE) { + long long delta = max->time - min->time; + long long offset = ((long long)ts - min->time) * + (max->offset - min->offset); + + scaling = (min->scaling + max->scaling) / 2; + tscor = min->offset + (offset + delta / 2) / delta; + + } else { + scaling = min->scaling; + tscor = min->offset; + } ts *= scaling; if (tscor < 0) @@ -1156,16 +1167,17 @@ static unsigned long long timestamp_correct(unsigned long long ts, /* We have two samples, nothing to search here */ if (host->ts_samples_count == 2) - return timestamp_correction_calc(ts, &host->ts_samples[0], + return timestamp_correction_calc(ts, host->flags, + &host->ts_samples[0], &host->ts_samples[1]); /* We have more than two samples */ if (ts <= host->ts_samples[0].time) - return timestamp_correction_calc(ts, + return timestamp_correction_calc(ts, host->flags, &host->ts_samples[0], &host->ts_samples[1]); else if (ts >= host->ts_samples[host->ts_samples_count-1].time) - return timestamp_correction_calc(ts, + return timestamp_correction_calc(ts, host->flags, &host->ts_samples[host->ts_samples_count-2], &host->ts_samples[host->ts_samples_count-1]); min = 0; @@ -1181,7 +1193,8 @@ static unsigned long long timestamp_correct(unsigned long long ts, mid = (min + max)/2; } - return timestamp_correction_calc(ts, &host->ts_samples[mid], + return timestamp_correction_calc(ts, host->flags, + &host->ts_samples[mid], &host->ts_samples[mid+1]); } @@ -2535,28 +2548,31 @@ static int handle_options(struct tracecmd_input *handle) case TRACECMD_OPTION_TIME_SHIFT: /* * long long int (8 bytes) trace session ID + * int (4 bytes) protocol flags. * int (4 bytes) count of timestamp offsets. * long long array of size [count] of times, * when the offsets were calculated. * long long array of size [count] of timestamp offsets. * long long array of size [count] of timestamp scaling ratios.* */ - if (size < 12 || handle->flags & TRACECMD_FL_IGNORE_DATE) + if (size < 16 || handle->flags & TRACECMD_FL_IGNORE_DATE) break; handle->host.peer_trace_id = tep_read_number(handle->pevent, buf, 8); + handle->host.flags = tep_read_number(handle->pevent, + buf + 8, 4); handle->host.ts_samples_count = tep_read_number(handle->pevent, - buf + 8, 4); + buf + 12, 4); samples_size = (8 * handle->host.ts_samples_count); - if (size != (12 + (2 * samples_size))) { + if (size != (16 + (2 * samples_size))) { warning("Failed to extract Time Shift information from the file: found size %d, expected is %d", - size, 12 + (2 * samples_size)); + size, 16 + (2 * samples_size)); break; } handle->host.ts_samples = malloc(2 * samples_size); if (!handle->host.ts_samples) return -ENOMEM; - tsync_offset_load(handle, buf + 12); + tsync_offset_load(handle, buf + 16); break; case TRACECMD_OPTION_CPUSTAT: buf[size-1] = '\n'; diff --git a/lib/trace-cmd/trace-timesync.c b/lib/trace-cmd/trace-timesync.c index 9b12e20f..9cbed775 100644 --- a/lib/trace-cmd/trace-timesync.c +++ b/lib/trace-cmd/trace-timesync.c @@ -28,6 +28,7 @@ struct tsync_proto { enum tracecmd_time_sync_role roles; int accuracy; int supported_clocks; + unsigned int flags; int (*clock_sync_init)(struct tracecmd_time_sync *clock_context); int (*clock_sync_free)(struct tracecmd_time_sync *clock_context); @@ -53,7 +54,7 @@ static struct tsync_proto *tsync_proto_find(const char *proto_name) } int tracecmd_tsync_proto_register(const char *proto_name, int accuracy, int roles, - int supported_clocks, + int supported_clocks, unsigned int flags, int (*init)(struct tracecmd_time_sync *), int (*free)(struct tracecmd_time_sync *), int (*calc)(struct tracecmd_time_sync *, @@ -139,6 +140,31 @@ int tracecmd_tsync_get_offsets(struct tracecmd_time_sync *tsync, return 0; } +/** + * tracecmd_tsync_get_proto_flags - Get protocol flags + * + * @tsync: Pointer to time sync context + * @flags: Returns the protocol flags, a combination of TRACECMD_TSYNC_FLAG_... + * + * Retuns -1 in case of an error, or 0 otherwise + */ +int tracecmd_tsync_get_proto_flags(struct tracecmd_time_sync *tsync, + unsigned int *flags) +{ + struct tsync_proto *protocol; + + if (!tsync) + return -1; + protocol = tsync_proto_find(tsync->proto_name); + if (!protocol) + return -1; + + if (flags) + *flags = protocol->flags; + + return 0; +} + #define PROTO_MASK_SIZE (sizeof(char)) #define PROTO_MASK_BITS (PROTO_MASK_SIZE * 8) diff --git a/tracecmd/trace-dump.c b/tracecmd/trace-dump.c index 0117f979..6172231e 100644 --- a/tracecmd/trace-dump.c +++ b/tracecmd/trace-dump.c @@ -374,6 +374,7 @@ static void dump_option_timeshift(int fd, int size) long long *times = NULL; long long trace_id; unsigned int count; + unsigned int flags; int i; /* @@ -390,6 +391,8 @@ static void dump_option_timeshift(int fd, int size) do_print(OPTIONS, "\t\t[Option TimeShift, %d bytes]\n", size); read_file_number(fd, &trace_id, 8); do_print(OPTIONS, "0x%llX [peer's trace id]\n", trace_id); + read_file_number(fd, &flags, 4); + do_print(OPTIONS, "0x%llX [peer's protocol flags]\n", flags); read_file_number(fd, &count, 4); do_print(OPTIONS, "%lld [samples count]\n", count); times = calloc(count, sizeof(long long)); diff --git a/tracecmd/trace-tsync.c b/tracecmd/trace-tsync.c index 83954b82..438c60bb 100644 --- a/tracecmd/trace-tsync.c +++ b/tracecmd/trace-tsync.c @@ -135,7 +135,8 @@ out: static void write_guest_time_shift(struct buffer_instance *instance) { struct tracecmd_output *handle; - struct iovec vector[5]; + struct iovec vector[6]; + unsigned int flags; long long *scalings = NULL; long long *offsets = NULL; long long *ts = NULL; @@ -148,6 +149,9 @@ static void write_guest_time_shift(struct buffer_instance *instance) &ts, &offsets, &scalings); if (ret < 0 || !count || !ts || !offsets || !scalings) return; + ret = tracecmd_tsync_get_proto_flags(&instance->tsync, &flags); + if (ret < 0) + return; file = instance->output_file; fd = open(file, O_RDWR); @@ -157,14 +161,16 @@ static void write_guest_time_shift(struct buffer_instance *instance) vector[0].iov_len = 8; vector[0].iov_base = &top_instance.trace_id; vector[1].iov_len = 4; - vector[1].iov_base = &count; - vector[2].iov_len = 8 * count; - vector[2].iov_base = ts; + vector[1].iov_base = &flags; + vector[2].iov_len = 4; + vector[2].iov_base = &count; vector[3].iov_len = 8 * count; - vector[3].iov_base = offsets; + vector[3].iov_base = ts; vector[4].iov_len = 8 * count; - vector[4].iov_base = scalings; - tracecmd_add_option_v(handle, TRACECMD_OPTION_TIME_SHIFT, vector, 5); + vector[4].iov_base = offsets; + vector[5].iov_len = 8 * count; + vector[5].iov_base = scalings; + tracecmd_add_option_v(handle, TRACECMD_OPTION_TIME_SHIFT, vector, 6); tracecmd_append_options(handle); tracecmd_output_close(handle); #ifdef TSYNC_DEBUG From patchwork Thu Jan 21 07:44:51 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Tzvetomir Stoyanov (VMware)" X-Patchwork-Id: 12035057 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id AA23DC433E9 for ; Thu, 21 Jan 2021 07:47:54 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 6D8A123975 for ; Thu, 21 Jan 2021 07:47:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727748AbhAUHrn (ORCPT ); Thu, 21 Jan 2021 02:47:43 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50128 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727641AbhAUHq7 (ORCPT ); Thu, 21 Jan 2021 02:46:59 -0500 Received: from mail-wr1-x42c.google.com (mail-wr1-x42c.google.com [IPv6:2a00:1450:4864:20::42c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id BA33BC061798 for ; Wed, 20 Jan 2021 23:45:11 -0800 (PST) Received: by mail-wr1-x42c.google.com with SMTP id d16so54260wro.11 for ; Wed, 20 Jan 2021 23:45:11 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=MRwUcu6gFWDYUfyig2JfmN67MaFa1/4S98SEMjhZLH8=; b=mElvAn/5OLPI8zjOWctnStysJUFhLSRnh8cyd8ncU6dSIF4c2cqz+UKpk+pog57HyX tGDdxgKRjRxJ/YLF2bjJZ1cwXvbp3IW5ltMrFVbkW+R2XOTj7NSxs///QB75MNgxqgTn BqnF7mUHxLt8LynkA3Jxe8hEbc2U+8kb2TlHtFB4FfoZK6BaVPfUGcGzWaD4rP2eD3yM /K+x5l7PBu3WqKZVg/HXFqtISFN5wRAloqInOH3ga7QpL/nGIUBVYk1tE/YzLMbQgFXS vmkS6+yKMI/wBzyg+k8NUr7UL51FSu/hhtA/KmCYH40kaz33sssObqalFhXVn5v6eNae 0JmA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=MRwUcu6gFWDYUfyig2JfmN67MaFa1/4S98SEMjhZLH8=; b=a7R0VA9v0wiLwAsCw5ctTEeZUjuzaiKfMsesV95wy0stY9cEAXDBm3r5DK0Qa8oYlS +PpKq5L/7gr9si6w/nJfIHHuSK4oBqYOs2uIB6Usxia7zBKQ7HFTjnxPDrpMItHyPzqR jWmdKLOAsjQtXbC7CzGSDIjg7QSNzEqcoRF6slgCkNqXzLhC/ka/IKEzYQHF50X4F7JB l/KElZEdlunDd184u9TM5zDOg7lm4Sl4XDKFy+KfQ6xLrSeMtvDjgerYioyIHsMyHClO 4jIKXIj7QQTyaoQNiuvB4kjxG5Kg8cUr/trnpuNjax2QPNx7/DtDIbz3+0ewezxkyq4z I9gQ== X-Gm-Message-State: AOAM531jUhfTR+uHcT7bjho882y5iM3BU2/iE3ttEvpNLYUMr6/SuWhA Xku4a/lbKws5wD28RWNexbIMG+6s+6rK1eXt X-Google-Smtp-Source: ABdhPJyNraIQ9VCMh2igjKNI95dlbpMoLgD9gIUdKFMmqqWamwZqCEI8/0UlaJUU/1NC6xWl6RV7gw== X-Received: by 2002:adf:f7d2:: with SMTP id a18mr12615034wrq.47.1611215110413; Wed, 20 Jan 2021 23:45:10 -0800 (PST) Received: from oberon.zico.biz ([83.222.187.186]) by smtp.gmail.com with ESMTPSA id q6sm6788474wmj.32.2021.01.20.23.45.09 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 20 Jan 2021 23:45:09 -0800 (PST) From: "Tzvetomir Stoyanov (VMware)" To: rostedt@goodmis.org Cc: linux-trace-devel@vger.kernel.org Subject: [PATCH v26 10/15] trace-cmd: Add timestamp synchronization per vCPU Date: Thu, 21 Jan 2021 09:44:51 +0200 Message-Id: <20210121074456.157658-11-tz.stoyanov@gmail.com> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210121074456.157658-1-tz.stoyanov@gmail.com> References: <20210121074456.157658-1-tz.stoyanov@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org Timestamp synchronization logic is changed to work per virtual CPU. Some hypervisors maintain time offset and scaling per vCPU. The host-guest communication protocol is changed to request time stamp offset calculation for particular vCPU. The guest thread, responsible for running that logic is pinned to the requested CPU. The time sync medata data, saved in the trace.dat file is changed to an array of vCPUs. When an event time stamp is corrected, the CPU on that the event happened is used to get the correct offset. Signed-off-by: Tzvetomir Stoyanov (VMware) --- .../include/private/trace-cmd-private.h | 2 +- lib/trace-cmd/include/trace-tsync-local.h | 22 +- lib/trace-cmd/trace-input.c | 179 +++++++++------ lib/trace-cmd/trace-timesync.c | 215 +++++++++++++----- tracecmd/trace-dump.c | 52 +++-- tracecmd/trace-tsync.c | 67 ++++-- 6 files changed, 365 insertions(+), 172 deletions(-) diff --git a/lib/trace-cmd/include/private/trace-cmd-private.h b/lib/trace-cmd/include/private/trace-cmd-private.h index d6176337..c9d7ac55 100644 --- a/lib/trace-cmd/include/private/trace-cmd-private.h +++ b/lib/trace-cmd/include/private/trace-cmd-private.h @@ -446,7 +446,7 @@ const char *tracecmd_tsync_proto_select(struct tracecmd_tsync_protos *protos, ch bool tsync_proto_is_supported(const char *proto_name); void tracecmd_tsync_with_host(struct tracecmd_time_sync *tsync); void tracecmd_tsync_with_guest(struct tracecmd_time_sync *tsync); -int tracecmd_tsync_get_offsets(struct tracecmd_time_sync *tsync, +int tracecmd_tsync_get_offsets(struct tracecmd_time_sync *tsync, int cpu, int *count, long long **ts, long long **offsets, long long **scalings); int tracecmd_tsync_get_proto_flags(struct tracecmd_time_sync *tsync, diff --git a/lib/trace-cmd/include/trace-tsync-local.h b/lib/trace-cmd/include/trace-tsync-local.h index 83d1721a..d4281469 100644 --- a/lib/trace-cmd/include/trace-tsync-local.h +++ b/lib/trace-cmd/include/trace-tsync-local.h @@ -8,12 +8,7 @@ #include -struct clock_sync_context { - void *proto_data; /* time sync protocol specific data */ - bool is_server; /* server side time sync role */ - bool is_guest; /* guest or host time sync role */ - struct tracefs_instance *instance; /* ftrace buffer, used for time sync events */ - +struct clock_sync_offsets { /* Arrays with calculated time offsets at given time */ int sync_size; /* Allocated size of sync_ts, * sync_offsets and sync_scalings @@ -24,6 +19,18 @@ struct clock_sync_context { long long *sync_ts; long long *sync_offsets; long long *sync_scalings; +}; + +struct clock_sync_context { + void *proto_data; /* time sync protocol specific data */ + bool is_server; /* server side time sync role */ + bool is_guest; /* guest or host time sync role */ + struct tracefs_instance *instance; /* ftrace buffer, used for time sync events */ + + int cpu_count; + struct clock_sync_offsets *offsets; /* Array of size cpu_count + * calculated offsets per CPU + */ /* Identifiers of local and remote time sync peers: cid and port */ unsigned int local_cid; @@ -37,7 +44,8 @@ int tracecmd_tsync_proto_register(const char *proto_name, int accuracy, int role int (*init)(struct tracecmd_time_sync *), int (*free)(struct tracecmd_time_sync *), int (*calc)(struct tracecmd_time_sync *, - long long *, long long *, long long *)); + long long *, long long *, + long long *, unsigned int)); int tracecmd_tsync_proto_unregister(char *proto_name); int ptp_clock_sync_register(void); diff --git a/lib/trace-cmd/trace-input.c b/lib/trace-cmd/trace-input.c index 7d28254e..195f3741 100644 --- a/lib/trace-cmd/trace-input.c +++ b/lib/trace-cmd/trace-input.c @@ -91,13 +91,19 @@ struct guest_trace_info { int *cpu_pid; }; +struct timesync_offsets { + int ts_samples_count; + struct ts_offset_sample *ts_samples; + +}; + struct host_trace_info { unsigned long long peer_trace_id; unsigned int flags; bool sync_enable; struct tracecmd_input *peer_data; - int ts_samples_count; - struct ts_offset_sample *ts_samples; + int cpu_count; + struct timesync_offsets *ts_offsets; }; struct tracecmd_input { @@ -1149,53 +1155,56 @@ timestamp_correction_calc(unsigned long long ts, unsigned int flags, return ts + tscor; } -static unsigned long long timestamp_correct(unsigned long long ts, +static unsigned long long timestamp_correct(unsigned long long ts, int cpu, struct tracecmd_input *handle) { - struct host_trace_info *host = &handle->host; + struct timesync_offsets *tsync; int min, mid, max; if (handle->ts_offset) return ts + handle->ts_offset; - if (!host->sync_enable) + if (!handle->host.sync_enable) return ts; + if (cpu >= handle->host.cpu_count) + return ts; + tsync = &handle->host.ts_offsets[cpu]; /* We have one sample, nothing to calc here */ - if (host->ts_samples_count == 1) - return ts + host->ts_samples[0].offset; + if (tsync->ts_samples_count == 1) + return ts + tsync->ts_samples[0].offset; /* We have two samples, nothing to search here */ - if (host->ts_samples_count == 2) - return timestamp_correction_calc(ts, host->flags, - &host->ts_samples[0], - &host->ts_samples[1]); + if (tsync->ts_samples_count == 2) + return timestamp_correction_calc(ts, handle->host.flags, + &tsync->ts_samples[0], + &tsync->ts_samples[1]); /* We have more than two samples */ - if (ts <= host->ts_samples[0].time) - return timestamp_correction_calc(ts, host->flags, - &host->ts_samples[0], - &host->ts_samples[1]); - else if (ts >= host->ts_samples[host->ts_samples_count-1].time) - return timestamp_correction_calc(ts, host->flags, - &host->ts_samples[host->ts_samples_count-2], - &host->ts_samples[host->ts_samples_count-1]); + if (ts <= tsync->ts_samples[0].time) + return timestamp_correction_calc(ts, handle->host.flags, + &tsync->ts_samples[0], + &tsync->ts_samples[1]); + else if (ts >= tsync->ts_samples[tsync->ts_samples_count-1].time) + return timestamp_correction_calc(ts, handle->host.flags, + &tsync->ts_samples[tsync->ts_samples_count-2], + &tsync->ts_samples[tsync->ts_samples_count-1]); min = 0; - max = host->ts_samples_count-1; + max = tsync->ts_samples_count-1; mid = (min + max)/2; while (min <= max) { - if (ts < host->ts_samples[mid].time) + if (ts < tsync->ts_samples[mid].time) max = mid - 1; - else if (ts > host->ts_samples[mid].time) + else if (ts > tsync->ts_samples[mid].time) min = mid + 1; else break; mid = (min + max)/2; } - return timestamp_correction_calc(ts, host->flags, - &host->ts_samples[mid], - &host->ts_samples[mid+1]); + return timestamp_correction_calc(ts, handle->host.flags, + &tsync->ts_samples[mid], + &tsync->ts_samples[mid+1]); } /* @@ -1219,7 +1228,8 @@ static int update_page_info(struct tracecmd_input *handle, int cpu) kbuffer_subbuffer_size(kbuf)); return -1; } - handle->cpu_data[cpu].timestamp = timestamp_correct(kbuffer_timestamp(kbuf), handle); + handle->cpu_data[cpu].timestamp = timestamp_correct(kbuffer_timestamp(kbuf), + cpu, handle); if (handle->ts2secs) handle->cpu_data[cpu].timestamp *= handle->ts2secs; @@ -1852,7 +1862,7 @@ read_again: goto read_again; } - handle->cpu_data[cpu].timestamp = timestamp_correct(ts, handle); + handle->cpu_data[cpu].timestamp = timestamp_correct(ts, cpu, handle); if (handle->ts2secs) { handle->cpu_data[cpu].timestamp *= handle->ts2secs; @@ -2187,42 +2197,80 @@ static int tsync_offset_cmp(const void *a, const void *b) return 0; } -static void tsync_offset_load(struct tracecmd_input *handle, char *buf) +#define safe_read(R, C) \ + { if ((C) > size) return -EFAULT; \ + (R) = tep_read_number(tep, buf, (C)); \ + buf += (C); \ + size -= (C); } +static int tsync_offset_load(struct tep_handle *tep, + struct timesync_offsets *ts_offsets, char *buf, int size) { - struct host_trace_info *host = &handle->host; - long long *buf8 = (long long *)buf; + int start_size = size; int i, j; - for (i = 0; i < host->ts_samples_count; i++) { - host->ts_samples[i].time = tep_read_number(handle->pevent, - buf8 + i, 8); - host->ts_samples[i].offset = tep_read_number(handle->pevent, - buf8 + host->ts_samples_count + i, 8); - host->ts_samples[i].scaling = tep_read_number(handle->pevent, - buf8 + (2 * host->ts_samples_count) + i, 8); - } - qsort(host->ts_samples, host->ts_samples_count, + for (i = 0; i < ts_offsets->ts_samples_count; i++) + safe_read(ts_offsets->ts_samples[i].time, 8); + for (i = 0; i < ts_offsets->ts_samples_count; i++) + safe_read(ts_offsets->ts_samples[i].offset, 8); + for (i = 0; i < ts_offsets->ts_samples_count; i++) + safe_read(ts_offsets->ts_samples[i].scaling, 8); + qsort(ts_offsets->ts_samples, ts_offsets->ts_samples_count, sizeof(struct ts_offset_sample), tsync_offset_cmp); /* Filter possible samples with equal time */ - for (i = 0, j = 0; i < host->ts_samples_count; i++) { - if (i == 0 || host->ts_samples[i].time != host->ts_samples[i-1].time) - host->ts_samples[j++] = host->ts_samples[i]; + for (i = 0, j = 0; i < ts_offsets->ts_samples_count; i++) { + if (i == 0 || ts_offsets->ts_samples[i].time != ts_offsets->ts_samples[i-1].time) + ts_offsets->ts_samples[j++] = ts_offsets->ts_samples[i]; + } + ts_offsets->ts_samples_count = j; + + return start_size - size; +} + +static int tsync_cpu_offsets_load(struct tracecmd_input *handle, char *buf, int size) +{ + struct tep_handle *tep = handle->pevent; + int ret; + int i; + + safe_read(handle->host.cpu_count, 4); + handle->host.ts_offsets = calloc(handle->host.cpu_count, + sizeof(struct timesync_offsets)); + if (!handle->host.ts_offsets) + return -ENOMEM; + for (i = 0; i < handle->host.cpu_count; i++) { + safe_read(handle->host.ts_offsets[i].ts_samples_count, 4); + handle->host.ts_offsets[i].ts_samples = calloc(handle->host.ts_offsets[i].ts_samples_count, + sizeof(struct ts_offset_sample)); + if (!handle->host.ts_offsets[i].ts_samples) + return -ENOMEM; + ret = tsync_offset_load(tep, &handle->host.ts_offsets[i], buf, size); + if (ret <= 0) + return -EFAULT; + size -= ret; + buf += ret; } - host->ts_samples_count = j; + return 0; } static void tsync_check_enable(struct tracecmd_input *handle) { struct host_trace_info *host = &handle->host; struct guest_trace_info *guest; + int i; host->sync_enable = false; - if (!host->peer_data || !host->peer_data->guest || - !host->ts_samples_count || !host->ts_samples) + if (!host->peer_data || !host->peer_data->guest) return; if (host->peer_trace_id != host->peer_data->trace_id) return; + if (!host->cpu_count || !host->ts_offsets) + return; + for (i = 0; i < host->cpu_count; i++) { + if (!host->ts_offsets[i].ts_samples_count || + !host->ts_offsets[i].ts_samples) + return; + } guest = host->peer_data->guest; while (guest) { if (guest->trace_id == handle->trace_id) @@ -2237,8 +2285,14 @@ static void tsync_check_enable(struct tracecmd_input *handle) static void trace_tsync_offset_free(struct host_trace_info *host) { - free(host->ts_samples); - host->ts_samples = NULL; + int i; + + if (host->ts_offsets) { + for (i = 0; i < host->cpu_count; i++) + free(host->ts_offsets[i].ts_samples); + free(host->ts_offsets); + host->ts_offsets = NULL; + } if (host->peer_data) { tracecmd_close(host->peer_data); host->peer_data = NULL; @@ -2497,8 +2551,8 @@ static int handle_options(struct tracecmd_input *handle) struct input_buffer_instance *buffer; struct hook_list *hook; char *buf; - int samples_size; int cpus; + int ret; /* By default, use usecs, unless told otherwise */ handle->flags |= TRACECMD_FL_IN_USECS; @@ -2549,11 +2603,15 @@ static int handle_options(struct tracecmd_input *handle) /* * long long int (8 bytes) trace session ID * int (4 bytes) protocol flags. - * int (4 bytes) count of timestamp offsets. - * long long array of size [count] of times, + * int (4 bytes) CPU count. + * array of size [CPU count]: + * [ + * int (4 bytes) count of timestamp offsets. + * long long array of size [count] of times, * when the offsets were calculated. - * long long array of size [count] of timestamp offsets. - * long long array of size [count] of timestamp scaling ratios.* + * long long array of size [count] of timestamp offsets. + * long long array of size [count] of timestamp scaling ratios.* + * ] */ if (size < 16 || handle->flags & TRACECMD_FL_IGNORE_DATE) break; @@ -2561,18 +2619,9 @@ static int handle_options(struct tracecmd_input *handle) buf, 8); handle->host.flags = tep_read_number(handle->pevent, buf + 8, 4); - handle->host.ts_samples_count = tep_read_number(handle->pevent, - buf + 12, 4); - samples_size = (8 * handle->host.ts_samples_count); - if (size != (16 + (2 * samples_size))) { - warning("Failed to extract Time Shift information from the file: found size %d, expected is %d", - size, 16 + (2 * samples_size)); - break; - } - handle->host.ts_samples = malloc(2 * samples_size); - if (!handle->host.ts_samples) - return -ENOMEM; - tsync_offset_load(handle, buf + 16); + ret = tsync_cpu_offsets_load(handle, buf + 12, size - 12); + if (ret < 0) + return ret; break; case TRACECMD_OPTION_CPUSTAT: buf[size-1] = '\n'; @@ -3911,7 +3960,7 @@ unsigned long long tracecmd_get_tsync_peer(struct tracecmd_input *handle) int tracecmd_enable_tsync(struct tracecmd_input *handle, bool enable) { if (enable && - (!handle->host.ts_samples || !handle->host.ts_samples_count)) + (!handle->host.ts_offsets || !handle->host.cpu_count)) return -1; handle->host.sync_enable = enable; diff --git a/lib/trace-cmd/trace-timesync.c b/lib/trace-cmd/trace-timesync.c index 9cbed775..994a935a 100644 --- a/lib/trace-cmd/trace-timesync.c +++ b/lib/trace-cmd/trace-timesync.c @@ -22,6 +22,8 @@ #include "event-utils.h" #include "trace-tsync-local.h" +typedef __be16 be16; + struct tsync_proto { struct tsync_proto *next; char proto_name[TRACECMD_TSYNC_PNAME_LENGTH]; @@ -34,9 +36,13 @@ struct tsync_proto { int (*clock_sync_free)(struct tracecmd_time_sync *clock_context); int (*clock_sync_calc)(struct tracecmd_time_sync *clock_context, long long *offset, long long *scaling, - long long *timestamp); + long long *timestamp, unsigned int cpu); }; +struct tsync_probe_request_msg { + be16 cpu; +} __attribute__((packed)); + static struct tsync_proto *tsync_proto_list; static struct tsync_proto *tsync_proto_find(const char *proto_name) @@ -58,7 +64,8 @@ int tracecmd_tsync_proto_register(const char *proto_name, int accuracy, int role int (*init)(struct tracecmd_time_sync *), int (*free)(struct tracecmd_time_sync *), int (*calc)(struct tracecmd_time_sync *, - long long *, long long *, long long *)) + long long *, long long *, + long long *, unsigned int)) { struct tsync_proto *proto = NULL; @@ -70,6 +77,7 @@ int tracecmd_tsync_proto_register(const char *proto_name, int accuracy, int role strncpy(proto->proto_name, proto_name, TRACECMD_TSYNC_PNAME_LENGTH); proto->accuracy = accuracy; proto->roles = roles; + proto->flags = flags; proto->supported_clocks = supported_clocks; proto->clock_sync_init = init; proto->clock_sync_free = free; @@ -112,6 +120,7 @@ bool tsync_proto_is_supported(const char *proto_name) * tracecmd_tsync_get_offsets - Return the calculated time offsets * * @tsync: Pointer to time sync context + * @cpu: CPU for which to get the calculated offsets * @count: Returns the number of calculated time offsets * @ts: Array of size @count containing timestamps of callculated offsets * @offsets: array of size @count, containing offsets for each timestamp @@ -119,7 +128,7 @@ bool tsync_proto_is_supported(const char *proto_name) * * Retuns -1 in case of an error, or 0 otherwise */ -int tracecmd_tsync_get_offsets(struct tracecmd_time_sync *tsync, +int tracecmd_tsync_get_offsets(struct tracecmd_time_sync *tsync, int cpu, int *count, long long **ts, long long **offsets, long long **scalings) { @@ -128,14 +137,16 @@ int tracecmd_tsync_get_offsets(struct tracecmd_time_sync *tsync, if (!tsync || !tsync->context) return -1; tsync_context = (struct clock_sync_context *)tsync->context; + if (cpu >= tsync_context->cpu_count || !tsync_context->offsets) + return -1; if (count) - *count = tsync_context->sync_count; + *count = tsync_context->offsets[cpu].sync_count; if (ts) - *ts = tsync_context->sync_ts; + *ts = tsync_context->offsets[cpu].sync_ts; if (offsets) - *offsets = tsync_context->sync_offsets; + *offsets = tsync_context->offsets[cpu].sync_offsets; if (scalings) - *scalings = tsync_context->sync_scalings; + *scalings = tsync_context->offsets[cpu].sync_scalings; return 0; } @@ -355,6 +366,13 @@ static int clock_context_init(struct tracecmd_time_sync *tsync, bool guest) if (!clock->instance) goto error; + clock->cpu_count = tsync->vcpu_count; + if (clock->cpu_count) { + clock->offsets = calloc(clock->cpu_count, sizeof(struct clock_sync_offsets)); + if (!clock->offsets) + goto error; + } + tsync->context = clock; if (protocol->clock_sync_init && protocol->clock_sync_init(tsync) < 0) goto error; @@ -362,6 +380,9 @@ static int clock_context_init(struct tracecmd_time_sync *tsync, bool guest) return 0; error: tsync->context = NULL; + if (clock->instance) + clock_synch_delete_instance(clock->instance); + free(clock->offsets); free(clock); return -1; } @@ -377,6 +398,7 @@ void tracecmd_tsync_free(struct tracecmd_time_sync *tsync) { struct clock_sync_context *tsync_context; struct tsync_proto *proto; + int i; if (!tsync->context) return; @@ -389,28 +411,88 @@ void tracecmd_tsync_free(struct tracecmd_time_sync *tsync) clock_synch_delete_instance(tsync_context->instance); tsync_context->instance = NULL; - free(tsync_context->sync_ts); - free(tsync_context->sync_offsets); - free(tsync_context->sync_scalings); - tsync_context->sync_ts = NULL; - tsync_context->sync_offsets = NULL; - tsync_context->sync_scalings = NULL; - tsync_context->sync_count = 0; - tsync_context->sync_size = 0; + if (tsync_context->cpu_count && tsync_context->offsets) { + for (i = 0; i < tsync_context->cpu_count; i++) { + free(tsync_context->offsets[i].sync_ts); + free(tsync_context->offsets[i].sync_offsets); + free(tsync_context->offsets[i].sync_scalings); + tsync_context->offsets[i].sync_ts = NULL; + tsync_context->offsets[i].sync_offsets = NULL; + tsync_context->offsets[i].sync_scalings = NULL; + tsync_context->offsets[i].sync_count = 0; + tsync_context->offsets[i].sync_size = 0; + } + free(tsync_context->offsets); + tsync_context->offsets = NULL; + } pthread_mutex_destroy(&tsync->lock); pthread_cond_destroy(&tsync->cond); free(tsync->clock_str); } +static cpu_set_t *pin_to_cpu(int cpu) +{ + static size_t size; + static int cpus; + cpu_set_t *mask = NULL; + cpu_set_t *old = NULL; + + if (!cpus) { + cpus = tracecmd_count_cpus(); + size = CPU_ALLOC_SIZE(cpus); + } + if (cpu >= cpus) + goto error; + + mask = CPU_ALLOC(cpus); + if (!mask) + goto error; + old = CPU_ALLOC(cpus); + if (!old) + goto error; + + CPU_ZERO_S(size, mask); + CPU_SET_S(cpu, size, mask); + if (pthread_getaffinity_np(pthread_self(), size, old)) + goto error; + if (pthread_setaffinity_np(pthread_self(), size, mask)) + goto error; + + CPU_FREE(mask); + return old; + +error: + if (mask) + CPU_FREE(mask); + if (old) + CPU_FREE(old); + return NULL; +} + +static void restore_pin_to_cpu(cpu_set_t *mask) +{ + static size_t size; + + if (!size) + size = CPU_ALLOC_SIZE(tracecmd_count_cpus()); + + pthread_setaffinity_np(pthread_self(), size, mask); + CPU_FREE(mask); +} + int tracecmd_tsync_send(struct tracecmd_time_sync *tsync, - struct tsync_proto *proto) + struct tsync_proto *proto, unsigned int cpu) { + cpu_set_t *old_set = NULL; long long timestamp = 0; long long scaling = 0; long long offset = 0; int ret; - ret = proto->clock_sync_calc(tsync, &offset, &scaling, ×tamp); + old_set = pin_to_cpu(cpu); + ret = proto->clock_sync_calc(tsync, &offset, &scaling, ×tamp, cpu); + if (old_set) + restore_pin_to_cpu(old_set); return ret; } @@ -428,8 +510,11 @@ int tracecmd_tsync_send(struct tracecmd_time_sync *tsync, void tracecmd_tsync_with_host(struct tracecmd_time_sync *tsync) { char protocol[TRACECMD_TSYNC_PNAME_LENGTH]; + struct tsync_probe_request_msg probe; struct tsync_proto *proto; unsigned int command; + unsigned int size; + char *msg; int ret; proto = tsync_proto_find(tsync->proto_name); @@ -440,47 +525,37 @@ void tracecmd_tsync_with_host(struct tracecmd_time_sync *tsync) if (!tsync->context) return; + msg = (char *)&probe; + size = sizeof(probe); while (true) { + memset(&probe, 0, size); ret = tracecmd_msg_recv_time_sync(tsync->msg_handle, protocol, &command, - NULL, NULL); + &size, &msg); if (ret || strncmp(protocol, TRACECMD_TSYNC_PROTO_NONE, TRACECMD_TSYNC_PNAME_LENGTH) || command != TRACECMD_TIME_SYNC_CMD_PROBE) break; - ret = tracecmd_tsync_send(tsync, proto); + ret = tracecmd_tsync_send(tsync, proto, probe.cpu); if (ret) break; } } -static int tsync_get_sample(struct tracecmd_time_sync *tsync, - struct tsync_proto *proto, int array_step) +static int record_sync_sample(struct clock_sync_offsets *offsets, int array_step, + long long offset, long long scaling, long long ts) { - struct clock_sync_context *clock; long long *sync_scalings = NULL; long long *sync_offsets = NULL; long long *sync_ts = NULL; - long long timestamp = 0; - long long scaling = 0; - long long offset = 0; - int ret; - ret = proto->clock_sync_calc(tsync, &offset, &scaling, ×tamp); - if (ret) { - warning("Failed to synchronize timestamps with guest"); - return -1; - } - if (!offset || !timestamp || !scaling) - return 0; - clock = tsync->context; - if (clock->sync_count >= clock->sync_size) { - sync_ts = realloc(clock->sync_ts, - (clock->sync_size + array_step) * sizeof(long long)); - sync_offsets = realloc(clock->sync_offsets, - (clock->sync_size + array_step) * sizeof(long long)); - sync_scalings = realloc(clock->sync_scalings, - (clock->sync_size + array_step) * sizeof(long long)); + if (offsets->sync_count >= offsets->sync_size) { + sync_ts = realloc(offsets->sync_ts, + (offsets->sync_size + array_step) * sizeof(long long)); + sync_offsets = realloc(offsets->sync_offsets, + (offsets->sync_size + array_step) * sizeof(long long)); + sync_scalings = realloc(offsets->sync_scalings, + (offsets->sync_size + array_step) * sizeof(long long)); if (!sync_ts || !sync_offsets || !sync_scalings) { free(sync_ts); @@ -488,20 +563,43 @@ static int tsync_get_sample(struct tracecmd_time_sync *tsync, free(sync_scalings); return -1; } - clock->sync_size += array_step; - clock->sync_ts = sync_ts; - clock->sync_offsets = sync_offsets; - clock->sync_scalings = sync_scalings; + offsets->sync_size += array_step; + offsets->sync_ts = sync_ts; + offsets->sync_offsets = sync_offsets; + offsets->sync_scalings = sync_scalings; } - clock->sync_ts[clock->sync_count] = timestamp; - clock->sync_offsets[clock->sync_count] = offset; - clock->sync_scalings[clock->sync_count] = scaling; - clock->sync_count++; + offsets->sync_ts[offsets->sync_count] = ts; + offsets->sync_offsets[offsets->sync_count] = offset; + offsets->sync_scalings[offsets->sync_count] = scaling; + offsets->sync_count++; return 0; } +static int tsync_get_sample(struct tracecmd_time_sync *tsync, unsigned int cpu, + struct tsync_proto *proto, int array_step) +{ + struct clock_sync_context *clock; + long long timestamp = 0; + long long scaling = 0; + long long offset = 0; + int ret; + + ret = proto->clock_sync_calc(tsync, &offset, &scaling, ×tamp, cpu); + if (ret) { + warning("Failed to synchronize timestamps with guest"); + return -1; + } + if (!offset || !timestamp || !scaling) + return 0; + clock = tsync->context; + if (!clock || cpu >= clock->cpu_count || !clock->offsets) + return -1; + return record_sync_sample(&clock->offsets[cpu], array_step, + offset, scaling, timestamp); +} + #define TIMER_SEC_NANO 1000000000LL static inline void get_ts_loop_delay(struct timespec *timeout, int delay_ms) { @@ -528,11 +626,13 @@ static inline void get_ts_loop_delay(struct timespec *timeout, int delay_ms) */ void tracecmd_tsync_with_guest(struct tracecmd_time_sync *tsync) { + struct tsync_probe_request_msg probe; int ts_array_size = CLOCK_TS_ARRAY; struct tsync_proto *proto; struct timespec timeout; bool end = false; int ret; + int i; proto = tsync_proto_find(tsync->proto_name); if (!proto || !proto->clock_sync_calc) @@ -548,12 +648,17 @@ void tracecmd_tsync_with_guest(struct tracecmd_time_sync *tsync) while (true) { pthread_mutex_lock(&tsync->lock); - ret = tracecmd_msg_send_time_sync(tsync->msg_handle, - TRACECMD_TSYNC_PROTO_NONE, - TRACECMD_TIME_SYNC_CMD_PROBE, - 0, NULL); - ret = tsync_get_sample(tsync, proto, ts_array_size); - if (ret || end) + for (i = 0; i < tsync->vcpu_count; i++) { + probe.cpu = i; + ret = tracecmd_msg_send_time_sync(tsync->msg_handle, + TRACECMD_TSYNC_PROTO_NONE, + TRACECMD_TIME_SYNC_CMD_PROBE, + sizeof(probe), (char *)&probe); + ret = tsync_get_sample(tsync, i, proto, ts_array_size); + if (ret) + break; + } + if (end || i < tsync->vcpu_count) break; if (tsync->loop_interval > 0) { get_ts_loop_delay(&timeout, tsync->loop_interval); diff --git a/tracecmd/trace-dump.c b/tracecmd/trace-dump.c index 6172231e..c1143eba 100644 --- a/tracecmd/trace-dump.c +++ b/tracecmd/trace-dump.c @@ -375,7 +375,8 @@ static void dump_option_timeshift(int fd, int size) long long trace_id; unsigned int count; unsigned int flags; - int i; + unsigned int cpus; + int i, j; /* * long long int (8 bytes) trace session ID @@ -393,29 +394,34 @@ static void dump_option_timeshift(int fd, int size) do_print(OPTIONS, "0x%llX [peer's trace id]\n", trace_id); read_file_number(fd, &flags, 4); do_print(OPTIONS, "0x%llX [peer's protocol flags]\n", flags); - read_file_number(fd, &count, 4); - do_print(OPTIONS, "%lld [samples count]\n", count); - times = calloc(count, sizeof(long long)); - if (!times) - goto out; - offsets = calloc(count, sizeof(long long)); - if (!offsets) - goto out; - scalings = calloc(count, sizeof(long long)); - if (!scalings) - goto out; - - for (i = 0; i < count; i++) - read_file_number(fd, times + i, 8); - for (i = 0; i < count; i++) - read_file_number(fd, offsets + i, 8); - for (i = 0; i < count; i++) - read_file_number(fd, scalings + i, 8); - - for (i = 0; i < count; i++) - do_print(OPTIONS, "\t%lld * %lld %lld [offset * scaling @ time]\n", - offsets[i], scalings[1], times[i]); + read_file_number(fd, &cpus, 4); + do_print(OPTIONS, "0x%llX [peer's CPU count]\n", cpus); + for (j = 0; j < cpus; j++) { + read_file_number(fd, &count, 4); + do_print(OPTIONS, "%lld [samples count for CPU %d]\n", count, j); + times = calloc(count, sizeof(long long)); + offsets = calloc(count, sizeof(long long)); + scalings = calloc(count, sizeof(long long)); + if (!times || !offsets || !scalings) + goto out; + for (i = 0; i < count; i++) + read_file_number(fd, times + i, 8); + for (i = 0; i < count; i++) + read_file_number(fd, offsets + i, 8); + for (i = 0; i < count; i++) + read_file_number(fd, scalings + i, 8); + + for (i = 0; i < count; i++) + do_print(OPTIONS, "\t%lld %lld %lld [offset * scaling @ time]\n", + offsets[i], scalings[1], times[i]); + free(times); + free(offsets); + free(scalings); + times = NULL; + offsets = NULL; + scalings = NULL; + } out: free(times); free(offsets); diff --git a/tracecmd/trace-tsync.c b/tracecmd/trace-tsync.c index 438c60bb..70d4dbd1 100644 --- a/tracecmd/trace-tsync.c +++ b/tracecmd/trace-tsync.c @@ -134,51 +134,75 @@ out: static void write_guest_time_shift(struct buffer_instance *instance) { - struct tracecmd_output *handle; - struct iovec vector[6]; + struct tracecmd_output *handle = NULL; + struct iovec *vector = NULL; unsigned int flags; long long *scalings = NULL; long long *offsets = NULL; long long *ts = NULL; const char *file; + int fd = -1; + int vcount; int count; + int i, j; int ret; - int fd; - ret = tracecmd_tsync_get_offsets(&instance->tsync, &count, - &ts, &offsets, &scalings); - if (ret < 0 || !count || !ts || !offsets || !scalings) + if (!instance->tsync.vcpu_count) + return; + vcount = 3 + (4 * instance->tsync.vcpu_count); + vector = calloc(vcount, sizeof(struct iovec)); + if (!vector) return; ret = tracecmd_tsync_get_proto_flags(&instance->tsync, &flags); if (ret < 0) - return; + goto out; file = instance->output_file; fd = open(file, O_RDWR); if (fd < 0) die("error opening %s", file); handle = tracecmd_get_output_handle_fd(fd); - vector[0].iov_len = 8; - vector[0].iov_base = &top_instance.trace_id; - vector[1].iov_len = 4; - vector[1].iov_base = &flags; - vector[2].iov_len = 4; - vector[2].iov_base = &count; - vector[3].iov_len = 8 * count; - vector[3].iov_base = ts; - vector[4].iov_len = 8 * count; - vector[4].iov_base = offsets; - vector[5].iov_len = 8 * count; - vector[5].iov_base = scalings; - tracecmd_add_option_v(handle, TRACECMD_OPTION_TIME_SHIFT, vector, 6); + if (!handle) + goto out; + j = 0; + vector[j].iov_len = 8; + vector[j++].iov_base = &top_instance.trace_id; + vector[j].iov_len = 4; + vector[j++].iov_base = &flags; + vector[j].iov_len = 4; + vector[j++].iov_base = &instance->tsync.vcpu_count; + for (i = 0; i < instance->tsync.vcpu_count; i++) { + if (j >= vcount) + break; + ret = tracecmd_tsync_get_offsets(&instance->tsync, i, &count, + &ts, &offsets, &scalings); + if (ret < 0 || !count || !ts || !offsets || !scalings) + break; + vector[j].iov_len = 4; + vector[j++].iov_base = &count; + vector[j].iov_len = 8 * count; + vector[j++].iov_base = ts; + vector[j].iov_len = 8 * count; + vector[j++].iov_base = offsets; + vector[j].iov_len = 8 * count; + vector[j++].iov_base = scalings; + } + if (i < instance->tsync.vcpu_count) + goto out; + tracecmd_add_option_v(handle, TRACECMD_OPTION_TIME_SHIFT, vector, vcount); tracecmd_append_options(handle); - tracecmd_output_close(handle); #ifdef TSYNC_DEBUG if (count > 1) printf("Got %d timestamp synch samples for guest %s in %lld ns trace\n\r", count, tracefs_instance_get_name(instance->tracefs), ts[count - 1] - ts[0]); #endif +out: + if (handle) + tracecmd_output_close(handle); + else if (fd >= 0) + close(fd); + free(vector); } void tracecmd_host_tsync_complete(struct buffer_instance *instance) @@ -261,6 +285,7 @@ const char *tracecmd_guest_tsync(struct tracecmd_tsync_protos *tsync_protos, pthread_attr_init(&attrib); tsync->proto_name = proto; + tsync->vcpu_count = tracecmd_count_cpus(); pthread_attr_setdetachstate(&attrib, PTHREAD_CREATE_JOINABLE); ret = pthread_create(thr_id, &attrib, tsync_agent_thread, tsync); From patchwork Thu Jan 21 07:44:52 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Tzvetomir Stoyanov (VMware)" X-Patchwork-Id: 12035049 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6F2E2C433DB for ; Thu, 21 Jan 2021 07:47:54 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 29DA6238EC for ; Thu, 21 Jan 2021 07:47:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726382AbhAUHrg (ORCPT ); Thu, 21 Jan 2021 02:47:36 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50138 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727748AbhAUHrB (ORCPT ); Thu, 21 Jan 2021 02:47:01 -0500 Received: from mail-wr1-x429.google.com (mail-wr1-x429.google.com [IPv6:2a00:1450:4864:20::429]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 8C60EC061799 for ; Wed, 20 Jan 2021 23:45:12 -0800 (PST) Received: by mail-wr1-x429.google.com with SMTP id m4so726350wrx.9 for ; Wed, 20 Jan 2021 23:45:12 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=KAch633jbKKZzuaBgUWOLuw1zMVNfMNzOt2D49kCjgQ=; b=u0kziTCaKGeOp0ARClWADJV/uC7dgm1uFRRS56ZOBnqydWoyhj+ZztTheZN0sZUsYB WUhAJD1uusFFOMLBeMCWBnLScxbeFxNv1b10ApiWerojh4TkZMJMpGWl1CWx+H01YY/n n7gj88kH6Q7ZGMX2QcMdnTbC7kdY3GRbrm2Kc3yQGiEjTiizbzyhr+/Lh/Be0Cdv3km0 d5xgx8YM2FuTPctFaiBGbbKDEN7SeHYaLwawqhk4lrn6ypIi1OB6D0y2/GILl9cV+OQY xnNWMpTf+2TLmqxiTvD7YBwRhl7yKrN0uaNAXo+Ymau1ub7YaogmlPqnti0tmCa9dhHy 6mCA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=KAch633jbKKZzuaBgUWOLuw1zMVNfMNzOt2D49kCjgQ=; b=EtN1jx8bKu18a1bCLT+P5ZWXRfKsJu9wXV/Dd3qYbWSQX2xfKJZm0F+O0iWvm0vlZ0 KqkVmLJRYeyr4TaqOxR+r4M+VqUM+OW/FzsstFwRY0Iru7U0JGRVFPyNcHhTWvCtAbep 1bW/OlfWMSiQ5Yil92ONWU5LEtWaEiXexBfJwxq8NLnZBIY4hb5Fq6WTgTQqoH87K4r4 +W2y/HrP/QFYmoKS4HKxwJAbvB/X04wNJJoSxDzJg6vjc0LXEzeJOyrbSDCV17tqs4HK H8KQ1gkcN0dUHPZjFh84aZIx6Lc3n7Ph9/YgD+UTbkJ3m04OVcX7CABrAdQFYFs6KUOU Sepw== X-Gm-Message-State: AOAM532PclaMMLOqMnFz9JhbhKgTaitoWtV2AINm4uKErlAbVTveJcU5 27dxGfnggkCkLQoxxa1H9s0= X-Google-Smtp-Source: ABdhPJy1KeMfXc5LzVpBdxXlYqbCfA/KE3l+JSH3lvbSeJZgfPY85wUt2zYvBHNMO5wtF3PeCR4l3g== X-Received: by 2002:a5d:4d86:: with SMTP id b6mr12837953wru.152.1611215111397; Wed, 20 Jan 2021 23:45:11 -0800 (PST) Received: from oberon.zico.biz ([83.222.187.186]) by smtp.gmail.com with ESMTPSA id q6sm6788474wmj.32.2021.01.20.23.45.10 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 20 Jan 2021 23:45:10 -0800 (PST) From: "Tzvetomir Stoyanov (VMware)" To: rostedt@goodmis.org Cc: linux-trace-devel@vger.kernel.org Subject: [PATCH v26 11/15] trace-cmd: Define a macro for packed structures Date: Thu, 21 Jan 2021 09:44:52 +0200 Message-Id: <20210121074456.157658-12-tz.stoyanov@gmail.com> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210121074456.157658-1-tz.stoyanov@gmail.com> References: <20210121074456.157658-1-tz.stoyanov@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org Defined a new macro #define __packed __attribute__((packed)) used for packing the structures, to make the code look cleaner. Signed-off-by: Tzvetomir Stoyanov (VMware) --- lib/trace-cmd/include/trace-cmd-local.h | 2 ++ lib/trace-cmd/trace-msg.c | 14 +++++++------- lib/trace-cmd/trace-timesync.c | 2 +- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/lib/trace-cmd/include/trace-cmd-local.h b/lib/trace-cmd/include/trace-cmd-local.h index 0cd27441..d265e4c8 100644 --- a/lib/trace-cmd/include/trace-cmd-local.h +++ b/lib/trace-cmd/include/trace-cmd-local.h @@ -12,6 +12,8 @@ /* Can be overridden */ void warning(const char *fmt, ...); +#define __packed __attribute__((packed)) + /* trace.dat file format version */ #define FILE_VERSION 6 diff --git a/lib/trace-cmd/trace-msg.c b/lib/trace-cmd/trace-msg.c index e0cdf677..8d2ed38d 100644 --- a/lib/trace-cmd/trace-msg.c +++ b/lib/trace-cmd/trace-msg.c @@ -57,11 +57,11 @@ struct tracecmd_msg_tinit { be32 cpus; be32 page_size; be32 opt_num; -} __attribute__((packed)); +} __packed; struct tracecmd_msg_rinit { be32 cpus; -} __attribute__((packed)); +} __packed; #define TRACE_REQ_PARAM_SIZE (2 * sizeof(int)) enum trace_req_params { @@ -79,7 +79,7 @@ struct tracecmd_msg_trace_req { be32 flags; be32 argc; u64 trace_id; -} __attribute__((packed)); +} __packed; struct tracecmd_msg_trace_resp { be32 flags; @@ -88,18 +88,18 @@ struct tracecmd_msg_trace_resp { u64 trace_id; char tsync_proto_name[TRACECMD_TSYNC_PNAME_LENGTH]; be32 tsync_port; -} __attribute__((packed)); +} __packed; struct tracecmd_msg_tsync { char sync_protocol_name[TRACECMD_TSYNC_PNAME_LENGTH]; be32 sync_msg_id; -} __attribute__((packed)); +} __packed; struct tracecmd_msg_header { be32 size; be32 cmd; be32 cmd_size; -} __attribute__((packed)); +} __packed; #define MSG_MAP \ C(CLOSE, 0, 0), \ @@ -148,7 +148,7 @@ struct tracecmd_msg { struct tracecmd_msg_tsync tsync; }; char *buf; -} __attribute__((packed)); +} __packed; static inline int msg_buf_len(struct tracecmd_msg *msg) { diff --git a/lib/trace-cmd/trace-timesync.c b/lib/trace-cmd/trace-timesync.c index 994a935a..8371a141 100644 --- a/lib/trace-cmd/trace-timesync.c +++ b/lib/trace-cmd/trace-timesync.c @@ -41,7 +41,7 @@ struct tsync_proto { struct tsync_probe_request_msg { be16 cpu; -} __attribute__((packed)); +} __packed; static struct tsync_proto *tsync_proto_list; From patchwork Thu Jan 21 07:44:53 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Tzvetomir Stoyanov (VMware)" X-Patchwork-Id: 12035055 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 03EF3C4332B for ; Thu, 21 Jan 2021 07:47:55 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id C6ED623975 for ; Thu, 21 Jan 2021 07:47:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727529AbhAUHrl (ORCPT ); Thu, 21 Jan 2021 02:47:41 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50140 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727727AbhAUHrB (ORCPT ); Thu, 21 Jan 2021 02:47:01 -0500 Received: from mail-wr1-x435.google.com (mail-wr1-x435.google.com [IPv6:2a00:1450:4864:20::435]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C843DC06179A for ; Wed, 20 Jan 2021 23:45:13 -0800 (PST) Received: by mail-wr1-x435.google.com with SMTP id g10so747947wrx.1 for ; Wed, 20 Jan 2021 23:45:13 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=oyrFCLUU/Egfusyp14CEETNslUJE59i2wQS3M/QXL18=; b=tUGEqLa7Fqdv3l9IzhnQdxHHLAUNVFBv7vnWwQ2qukI5ms2U7nf2vL+WsAqtegiwu3 3oSIckQN2Dpx9C7pYRw/9iYYMD8EZrqmFjn0CCLB6RD31I2MA+BukxfMwbvH7kM8iZgt LmORwRB+4eTS+6laMPSDjLl7qCoz8m4uq8J8ALeP6PJ4nqesS1+MK5yiZfYUqdwoRHJi AfJkJ1cMcG4WwnHDUbNiemGHIHTIVS//6MyRoUcpx05JgH2aK8d2VICNbq8JtZCMwX8g 21lH9ljzjeQXiENosRykcYw/Q0DSyedJp3Pe4eiZRw+bNrB+o3gWUStlc/YPW62x5Fe2 VOzA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=oyrFCLUU/Egfusyp14CEETNslUJE59i2wQS3M/QXL18=; b=V9to/OhTj1g3hKVLN11qWCmN/J9ZlW4QPu5WTkI0vQXqgeSHWXpoYsQRhQ+m21LaN2 PvZ2ZOZQ0edD02hwFqOaj+zSiGQjEHf0uOd41dfk+QfGMs+esVajwwl4oYc0zKD9u3ea PHp1SmAZC//zp3JLXMOm+JA3uWOdSxwSSBmb2VDzdmrLB1HY450z7yC0D2OTlJBOoLXs xD/O/G4ddFfI5wXZa/ClkcDObaTR4jypCmk9J1FD5DJ4e9FAU2DA3fPIVT6ayTIRa8dv FUUhAFILV19NRYjqSRnzYQNp/PO3kemhQPaFoCWRBe5B8RTgOJuh69947R4SOCxsNffA 0eNQ== X-Gm-Message-State: AOAM531sFj6hHxytrr01xhIQ7QjEDUBX0UQOUQhua7zrq78syKU8QApQ nKbdP5XuEwlYJJ3E2TMd/nE= X-Google-Smtp-Source: ABdhPJzLIIzlz+lLonpcV9EI9TY4csV/6sL4hNfVHPS257VkK45dAEELGr2GuNw28U7m7EBwg+wgGg== X-Received: by 2002:a05:6000:1048:: with SMTP id c8mr10476988wrx.420.1611215112582; Wed, 20 Jan 2021 23:45:12 -0800 (PST) Received: from oberon.zico.biz ([83.222.187.186]) by smtp.gmail.com with ESMTPSA id q6sm6788474wmj.32.2021.01.20.23.45.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 20 Jan 2021 23:45:11 -0800 (PST) From: "Tzvetomir Stoyanov (VMware)" To: rostedt@goodmis.org Cc: linux-trace-devel@vger.kernel.org Subject: [PATCH v26 12/15] trace-cmd: Add dummy function to initialize timestamp sync logic Date: Thu, 21 Jan 2021 09:44:53 +0200 Message-Id: <20210121074456.157658-13-tz.stoyanov@gmail.com> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210121074456.157658-1-tz.stoyanov@gmail.com> References: <20210121074456.157658-1-tz.stoyanov@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org A dummy empty function is added, will be used to initialize timestamp synchronization logic: tracecmd_tsync_init() When this code is implemented as real plugins, this function will be removed. Then the initializion will be triggered at plugin load time. Signed-off-by: Tzvetomir Stoyanov (VMware) --- lib/trace-cmd/trace-timesync.c | 8 ++++++++ tracecmd/trace-agent.c | 2 ++ tracecmd/trace-record.c | 23 +++++++++++++++-------- 3 files changed, 25 insertions(+), 8 deletions(-) diff --git a/lib/trace-cmd/trace-timesync.c b/lib/trace-cmd/trace-timesync.c index 8371a141..9db9d3a5 100644 --- a/lib/trace-cmd/trace-timesync.c +++ b/lib/trace-cmd/trace-timesync.c @@ -59,6 +59,14 @@ static struct tsync_proto *tsync_proto_find(const char *proto_name) return NULL; } +/** + * tracecmd_tsync_init - Initialize the global, per task, time sync data. + */ +void tracecmd_tsync_init(void) +{ + +} + int tracecmd_tsync_proto_register(const char *proto_name, int accuracy, int roles, int supported_clocks, unsigned int flags, int (*init)(struct tracecmd_time_sync *), diff --git a/tracecmd/trace-agent.c b/tracecmd/trace-agent.c index ff4a4e11..36444d32 100644 --- a/tracecmd/trace-agent.c +++ b/tracecmd/trace-agent.c @@ -248,6 +248,8 @@ static void agent_serve(unsigned int port) if (sd < 0) die("Failed to open vsocket"); + tracecmd_tsync_init(); + if (!get_local_cid(&cid)) printf("listening on @%u:%u\n", cid, port); diff --git a/tracecmd/trace-record.c b/tracecmd/trace-record.c index 3bcb2403..e5b1eff5 100644 --- a/tracecmd/trace-record.c +++ b/tracecmd/trace-record.c @@ -6219,10 +6219,6 @@ static bool has_local_instances(void) return false; } -/* - * This function contains common code for the following commands: - * record, start, stream, profile. - */ static void record_trace(int argc, char **argv, struct common_record_context *ctx) { @@ -6380,12 +6376,23 @@ static void record_trace(int argc, char **argv, finalize_record_trace(ctx); } +/* + * This function contains common code for the following commands: + * record, start, stream, profile. + */ +static void record_trace_command(int argc, char **argv, + struct common_record_context *ctx) +{ + tracecmd_tsync_init(); + record_trace(argc, argv, ctx); +} + void trace_start(int argc, char **argv) { struct common_record_context ctx; parse_record_options(argc, argv, CMD_start, &ctx); - record_trace(argc, argv, &ctx); + record_trace_command(argc, argv, &ctx); exit(0); } @@ -6477,7 +6484,7 @@ void trace_stream(int argc, char **argv) struct common_record_context ctx; parse_record_options(argc, argv, CMD_stream, &ctx); - record_trace(argc, argv, &ctx); + record_trace_command(argc, argv, &ctx); exit(0); } @@ -6496,7 +6503,7 @@ void trace_profile(int argc, char **argv) if (!buffer_instances) top_instance.flags |= BUFFER_FL_PROFILE; - record_trace(argc, argv, &ctx); + record_trace_command(argc, argv, &ctx); do_trace_profile(); exit(0); } @@ -6506,7 +6513,7 @@ void trace_record(int argc, char **argv) struct common_record_context ctx; parse_record_options(argc, argv, CMD_record, &ctx); - record_trace(argc, argv, &ctx); + record_trace_command(argc, argv, &ctx); exit(0); } From patchwork Thu Jan 21 07:44:54 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Tzvetomir Stoyanov (VMware)" X-Patchwork-Id: 12035051 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4C546C433E0 for ; Thu, 21 Jan 2021 07:47:54 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id EDFA223356 for ; Thu, 21 Jan 2021 07:47:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727649AbhAUHre (ORCPT ); Thu, 21 Jan 2021 02:47:34 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50142 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727753AbhAUHrB (ORCPT ); Thu, 21 Jan 2021 02:47:01 -0500 Received: from mail-wm1-x331.google.com (mail-wm1-x331.google.com [IPv6:2a00:1450:4864:20::331]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9741DC06179B for ; Wed, 20 Jan 2021 23:45:15 -0800 (PST) Received: by mail-wm1-x331.google.com with SMTP id 190so590576wmz.0 for ; Wed, 20 Jan 2021 23:45:15 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=IhLA+sID5loxiaKrwAXMDLvPBYPu6RQnWLc/u3+BdIQ=; b=IZt30sOfkcgOEvJ7uT7umoOCf71Q6XwGp+rU6il+phVdsjzkpCU3QB15naAAhDG0vF 9d5E82l+pz6Gm693Kf1hAnBY1Vr0tU+M71/uh8iGJSbxxi4oDn9maLXxGMUrdyQrVwGY ZK1+BU4eH/eqlyAtfdAki+7HcG1r5GNk73sD1Du5nZsWcJHw6eCdb26B06iZjAQdP1R5 RN8ubX2UJCyybRuIa3QU3cdsq32Pvjqfsl/lJhANutG9jbZ/gE3oR32nnNs4w9BPQI9Q 3zMBR1Ds5NWnwv81Cxwib8aUiR0yoHSjVCA6AM3PZsMzAtH4RsB8XoW/N7sEZITTWOb4 sVqw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=IhLA+sID5loxiaKrwAXMDLvPBYPu6RQnWLc/u3+BdIQ=; b=aw8tIwp7t8LNDgsH92xkSZJW1pio4QQxo/37HUuKqnntyrptAHCizNrRsiBGzmJxmv Y3PqdbQun6kI9eWE+ifBXiYNnSlVpfWA5vRH3hK4dkC8JISDz64ZxrSLoXkKtBwlj8Gr ozQVq8dpcm/LipLV61YsX4I3Y6fdHiQlWosT2OEL57TN295bGmoZHR7VipNFawWmhfFA f39FDCL6rpLQhXqxdzaZpKFrySNBCIl5rrQKKK5Pr424bANOhOyEpUxK3q1I841uirMQ iwk10hh4ZkbQw7UYCLHo5FVajDDS9c/nEhb2Foo8MHEWQ1f0XrzOi5TaXj2sf86VBLte WwsA== X-Gm-Message-State: AOAM530mb2kSHEDLELz+Y3n8mVEeU66LXGOLKRJyQPTWTC3gSWRlQvwS k23qSxyE9OE5ZR30ghmdQg7XFKpGCp3Kd33a X-Google-Smtp-Source: ABdhPJyg/ev7DxZulWU+nFXM+dXjjGw2j4vYR76iXQQhJRgkHD5eRBsQyo7aCyf9ahWDC5zCMREa2Q== X-Received: by 2002:a1c:e919:: with SMTP id q25mr7600663wmc.57.1611215114241; Wed, 20 Jan 2021 23:45:14 -0800 (PST) Received: from oberon.zico.biz ([83.222.187.186]) by smtp.gmail.com with ESMTPSA id q6sm6788474wmj.32.2021.01.20.23.45.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 20 Jan 2021 23:45:13 -0800 (PST) From: "Tzvetomir Stoyanov (VMware)" To: rostedt@goodmis.org Cc: linux-trace-devel@vger.kernel.org Subject: [PATCH v26 13/15] trace-cmd: [POC] PTP-like algorithm for host - guest timestamp synchronization Date: Thu, 21 Jan 2021 09:44:54 +0200 Message-Id: <20210121074456.157658-14-tz.stoyanov@gmail.com> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210121074456.157658-1-tz.stoyanov@gmail.com> References: <20210121074456.157658-1-tz.stoyanov@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org PTP protocol is designed for synchronizing clocks of machines in a local network. The same approach can be used for host - guest timestamp synchronization. This implementation uses ftrace raw markers to track trace timestamps of PTP events. The patch is a POC, two different algorithms for PTP calculations are proposed: - Choosing the sample with the fastest response time for calculating the clocks offset. - Calculating the clocks offset using the average of all PTP samples. The implementation can be tuned using those parameters: - #define FASTEST_RESPONSE - is defined, the sample with the fastest response time is used for calculating the clocks offset. Otherwise the histogram of all samples is used. - #define PTP_SYNC_LOOP 340 - defines the number of samples, used for one calculation. - --tsync-interval - a trace-cmd argument, choose the intervals between offset calculations, performed continuously during the trace. - #define TSYNC_DEBUG - if defined, a debug information is collected and stored in files, in the guest machine: s-cid*.txt - For each offset calculation: host and guest clocks and calculated offset. res-cid*.txt - For each tracing session: all calculated clock offsets. Signed-off-by: Tzvetomir Stoyanov (VMware) --- lib/trace-cmd/Makefile | 1 + lib/trace-cmd/trace-timesync-ptp.c | 714 +++++++++++++++++++++++++++++ lib/trace-cmd/trace-timesync.c | 2 +- 3 files changed, 716 insertions(+), 1 deletion(-) create mode 100644 lib/trace-cmd/trace-timesync-ptp.c diff --git a/lib/trace-cmd/Makefile b/lib/trace-cmd/Makefile index 841c84f1..f41feef8 100644 --- a/lib/trace-cmd/Makefile +++ b/lib/trace-cmd/Makefile @@ -19,6 +19,7 @@ OBJS += trace-msg.o OBJS += trace-plugin.o ifeq ($(VSOCK_DEFINED), 1) OBJS += trace-timesync.o +OBJS += trace-timesync-ptp.o endif # Additional util objects diff --git a/lib/trace-cmd/trace-timesync-ptp.c b/lib/trace-cmd/trace-timesync-ptp.c new file mode 100644 index 00000000..1440a8d4 --- /dev/null +++ b/lib/trace-cmd/trace-timesync-ptp.c @@ -0,0 +1,714 @@ +// SPDX-License-Identifier: LGPL-2.1 +/* + * Copyright (C) 2019, VMware, Tzvetomir Stoyanov tz.stoyanov@gmail.com> + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "trace-cmd.h" +#include "tracefs.h" +#include "trace-tsync-local.h" +#include "trace-msg.h" +#include "trace-cmd-local.h" + +typedef __be32 be32; +typedef __u64 u64; +typedef __s64 s64; + +#define PTP_SYNC_LOOP 339 + +#define PTP_SYNC_PKT_START 1 +#define PTP_SYNC_PKT_PROBE 2 +#define PTP_SYNC_PKT_PROBES 3 +#define PTP_SYNC_PKT_OFFSET 4 +#define PTP_SYNC_PKT_END 5 + +/* print time sync debug messages */ +#define TSYNC_DEBUG + +struct ptp_clock_sync { + struct tep_handle *tep; + struct tep_format_field *id; + int raw_id; + int marker_fd; + int series_id; + int flags; + int debug_fd; +}; + +enum { +/* + * Consider only the probe with fastest response time, + * otherwise make a histogram from all probes. + */ + PTP_FLAG_FASTEST_RESPONSE = (1 << 0), +/* + * Use trace marker to get the clock, + * otherwise use the system clock directly. + */ + PTP_FLAG_USE_MARKER = (1 << 1), +}; +static int ptp_flags = PTP_FLAG_FASTEST_RESPONSE | PTP_FLAG_USE_MARKER; + +/* + * Calculated using formula [CPU rate]*[calculated offset deviation] + * tested on 3GHz CPU, with x86-tsc trace clock and compare the calculated + * offset with /sys/kernel/debug/kvm//vcpu0/tsc-offset + * measured 2000ns deviation + * using PTP flags PTP_FLAG_FASTEST_RESPONSE | PTP_FLAG_USE_MARKER + */ +#define PTP_ACCURACY 6000 +#define PTP_NAME "ptp" + +struct ptp_clock_start_msg { + be32 series_id; + be32 flags; +} __packed; + +struct ptp_clock_sample { + s64 ts; + be32 id; +} __packed; + +struct ptp_clock_result_msg { + be32 series_id; + be32 count; + struct ptp_clock_sample samples[2*PTP_SYNC_LOOP]; +} __packed; + +struct ptp_clock_offset_msg { + s64 ts; + s64 offset; +}; + +struct ptp_markers_context { + struct clock_sync_context *clock; + struct ptp_clock_sync *ptp; + struct ptp_clock_result_msg msg; + int size; +}; + +struct ptp_marker_buf { + int local_cid; + int remote_cid; + int count; + int packet_id; +} __packed; + +struct ptp_marker { + int series_id; + struct ptp_marker_buf data; +} __packed; + +static int ptp_clock_sync_init(struct tracecmd_time_sync *tsync) +{ + const char *systems[] = {"ftrace", NULL}; + struct clock_sync_context *clock_context; + struct ptp_clock_sync *ptp; + struct tep_event *raw; + char *path; + + if (!tsync || !tsync->context) + return -1; + clock_context = (struct clock_sync_context *)tsync->context; + if (clock_context->proto_data) + return 0; + + ptp = calloc(1, sizeof(struct ptp_clock_sync)); + if (!ptp) + return -1; + + ptp->marker_fd = -1; + ptp->debug_fd = -1; + + path = tracefs_instance_get_dir(clock_context->instance); + if (!path) + goto error; + ptp->tep = tracefs_local_events_system(path, systems); + tracefs_put_tracing_file(path); + if (!ptp->tep) + goto error; + raw = tep_find_event_by_name(ptp->tep, "ftrace", "raw_data"); + if (!raw) + goto error; + ptp->id = tep_find_field(raw, "id"); + if (!ptp->id) + goto error; + ptp->raw_id = raw->id; + + tep_set_file_bigendian(ptp->tep, tracecmd_host_bigendian()); + tep_set_local_bigendian(ptp->tep, tracecmd_host_bigendian()); + + path = tracefs_instance_get_file(clock_context->instance, "trace_marker_raw"); + if (!path) + goto error; + ptp->marker_fd = open(path, O_WRONLY); + tracefs_put_tracing_file(path); + + clock_context->proto_data = ptp; + +#ifdef TSYNC_DEBUG + if (clock_context->is_server) { + char buff[256]; + int res_fd; + + sprintf(buff, "res-cid%d.txt", clock_context->remote_cid); + + res_fd = open(buff, O_CREAT|O_WRONLY|O_TRUNC, 0644); + if (res_fd > 0) + close(res_fd); + } +#endif + + return 0; + +error: + if (ptp) { + tep_free(ptp->tep); + if (ptp->marker_fd >= 0) + close(ptp->marker_fd); + } + free(ptp); + return -1; +} + +static int ptp_clock_sync_free(struct tracecmd_time_sync *tsync) +{ + struct clock_sync_context *clock_context; + struct ptp_clock_sync *ptp; + + if (!tsync || !tsync->context) + return -1; + clock_context = (struct clock_sync_context *)tsync->context; + + if (clock_context && clock_context->proto_data) { + ptp = (struct ptp_clock_sync *)clock_context->proto_data; + tep_free(ptp->tep); + if (ptp->marker_fd >= 0) + close(ptp->marker_fd); + if (ptp->debug_fd >= 0) + close(ptp->debug_fd); + free(clock_context->proto_data); + clock_context->proto_data = NULL; + } + return 0; +} + +/* Save the timestamps of sent ('s') and returned ('r') probes in the + * ctx->msg.samples[] array. Depending of the context (server or client), there + * may be only returned probes, or both sent and returned probes. The returned + * probes are saved first in the array, after them are the sent probes. + * Depending of the context, the array can be with size: + * [0 .. max data.count] - holds only returned probes + * [0 .. 2 * max data.count] - holds both returned and sent probes + */ +static void ptp_probe_store(struct ptp_markers_context *ctx, + struct ptp_marker *marker, + unsigned long long ts) +{ + int index = -1; + + if (marker->data.packet_id == 'r' && + marker->data.count <= ctx->size) { + index = marker->data.count - 1; + } else if (marker->data.packet_id == 's' && + marker->data.count * 2 <= ctx->size){ + index = ctx->size / 2 + marker->data.count - 1; + } + + if (index >= 0) { + ctx->msg.samples[index].id = marker->data.count; + ctx->msg.samples[index].ts = ts; + ctx->msg.count++; + } +} + +static int ptp_marker_find(struct tep_event *event, struct tep_record *record, + int cpu, void *context) +{ + struct ptp_markers_context *ctx; + struct ptp_marker *marker; + + ctx = (struct ptp_markers_context *)context; + + /* Make sure this is our event */ + if (event->id != ctx->ptp->raw_id || !ctx->ptp->id) + return 0; + if (record->size >= (ctx->ptp->id->offset + sizeof(struct ptp_marker))) { + marker = (struct ptp_marker *)(record->data + ctx->ptp->id->offset); + if (marker->data.local_cid == ctx->clock->local_cid && + marker->data.remote_cid == ctx->clock->remote_cid && + marker->series_id == ctx->ptp->series_id && + marker->data.count) + ptp_probe_store(ctx, marker, record->ts); + } + + return 0; +} + +static inline bool good_probe(struct ptp_clock_sample *server_sample, + struct ptp_clock_sample *send_sample, + struct ptp_clock_sample *client_sample, + int *bad_probes) +{ + if (server_sample->ts && send_sample->ts && client_sample->ts && + server_sample->id == send_sample->id && + server_sample->id == client_sample->id) + return true; + (*bad_probes)++; + return false; +} + +static int ptp_calc_offset_fastest(struct clock_sync_context *clock, + struct ptp_clock_result_msg *server, + struct ptp_clock_result_msg *client, + long long *offset_ret, long long *ts_ret, + int *bad_probes) +{ + struct ptp_clock_sample *sample_send; + long long delta_min = LLONG_MAX; + long long offset = 0; + long long delta = 0; + long long ts = 0; + int max_i; + int i; + + *bad_probes = 0; + sample_send = server->samples + (server->count / 2); + max_i = server->count / 2 < client->count ? + server->count / 2 : client->count; + for (i = 0; i < max_i; i++) { + if (!good_probe(&server->samples[i], &sample_send[i], + &client->samples[i], bad_probes)) + continue; + ts = (sample_send[i].ts + server->samples[i].ts) / 2; + offset = client->samples[i].ts - ts; + + delta = server->samples[i].ts - sample_send[i].ts; + if (delta_min > delta) { + delta_min = delta; + *offset_ret = offset; + *ts_ret = ts; + } +#ifdef TSYNC_DEBUG + { + struct ptp_clock_sync *ptp; + + ptp = (struct ptp_clock_sync *)clock->proto_data; + if (ptp && ptp->debug_fd > 0) { + char buff[256]; + + sprintf(buff, "%lld %lld %lld\n", + ts, client->samples[i].ts, offset); + write(ptp->debug_fd, buff, strlen(buff)); + } + } +#endif + } + + return 0; +} + +static int ptp_calc_offset_hist(struct clock_sync_context *clock, + struct ptp_clock_result_msg *server, + struct ptp_clock_result_msg *client, + long long *offset_ret, long long *ts_ret, + int *bad_probes) +{ + struct ptp_clock_sample *sample_send; + long long timestamps[PTP_SYNC_LOOP]; + long long offsets[PTP_SYNC_LOOP]; + long long offset_min = LLONG_MAX; + long long offset_max = 0; + int hist[PTP_SYNC_LOOP]; + int ind, max = 0; + long long bin; + int i, k = 0; + + *bad_probes = 0; + memset(hist, 0, sizeof(int) * PTP_SYNC_LOOP); + sample_send = server->samples + (server->count / 2); + for (i = 0; i * 2 < server->count && i < client->count; i++) { + if (!good_probe(&server->samples[i], &sample_send[i], + &client->samples[i], bad_probes)) + continue; + timestamps[k] = (sample_send[i].ts + server->samples[i].ts) / 2; + offsets[k] = client->samples[i].ts - timestamps[k]; + if (offset_max < llabs(offsets[k])) + offset_max = llabs(offsets[k]); + if (offset_min > llabs(offsets[k])) + offset_min = llabs(offsets[k]); +#ifdef TSYNC_DEBUG + { + struct ptp_clock_sync *ptp; + + ptp = (struct ptp_clock_sync *)clock->proto_data; + + if (ptp && ptp->debug_fd > 0) { + char buff[256]; + + sprintf(buff, "%lld %lld %lld\n", + timestamps[k], + client->samples[i].ts, offsets[k]); + write(ptp->debug_fd, buff, strlen(buff)); + } + } +#endif + k++; + } + + bin = (offset_max - offset_min) / PTP_SYNC_LOOP; + for (i = 0; i < k; i++) { + ind = (llabs(offsets[i]) - offset_min) / bin; + if (ind < PTP_SYNC_LOOP) { + hist[ind]++; + if (max < hist[ind]) { + max = hist[ind]; + *offset_ret = offsets[i]; + *ts_ret = timestamps[i]; + } + } + } + + return 0; +} + +static void ntoh_ptp_results(struct ptp_clock_result_msg *msg) +{ + int i; + + msg->count = ntohl(msg->count); + for (i = 0; i < msg->count; i++) { + msg->samples[i].id = ntohl(msg->samples[i].id); + msg->samples[i].ts = ntohll(msg->samples[i].ts); + } + msg->series_id = ntohl(msg->series_id); +} + + +static void hton_ptp_results(struct ptp_clock_result_msg *msg) +{ + int i; + + for (i = 0; i < msg->count; i++) { + msg->samples[i].id = htonl(msg->samples[i].id); + msg->samples[i].ts = htonll(msg->samples[i].ts); + } + msg->series_id = htonl(msg->series_id); + msg->count = htonl(msg->count); +} + +static inline void ptp_track_clock(struct ptp_markers_context *ctx, + struct ptp_marker *marker) +{ + if (ctx->ptp->flags & PTP_FLAG_USE_MARKER) { + write(ctx->ptp->marker_fd, marker, sizeof(struct ptp_marker)); + } else { + struct timespec clock; + unsigned long long ts; + + clock_gettime(CLOCK_MONOTONIC_RAW, &clock); + ts = clock.tv_sec * 1000000000LL; + ts += clock.tv_nsec; + ptp_probe_store(ctx, marker, ts); + } +} + +static int ptp_clock_client(struct tracecmd_time_sync *tsync, + long long *offset, long long *timestamp) +{ + char sync_proto[TRACECMD_TSYNC_PNAME_LENGTH]; + struct clock_sync_context *clock_context; + struct ptp_clock_offset_msg res_offset; + struct ptp_clock_start_msg start; + struct ptp_markers_context ctx; + struct ptp_clock_sync *ptp; + struct ptp_marker marker; + unsigned int sync_msg; + unsigned int size; + char *msg; + int count; + int ret; + + if (!tsync || !tsync->context || !tsync->msg_handle) + return -1; + + clock_context = (struct clock_sync_context *)tsync->context; + if (clock_context->proto_data == NULL) + return -1; + + ptp = (struct ptp_clock_sync *)clock_context->proto_data; + size = sizeof(start); + msg = (char *)&start; + ret = tracecmd_msg_recv_time_sync(tsync->msg_handle, + sync_proto, &sync_msg, + &size, &msg); + if (ret || strncmp(sync_proto, PTP_NAME, TRACECMD_TSYNC_PNAME_LENGTH) || + sync_msg != PTP_SYNC_PKT_START) + return -1; + ret = tracecmd_msg_send_time_sync(tsync->msg_handle, PTP_NAME, + PTP_SYNC_PKT_START, sizeof(start), + (char *)&start); + marker.data.local_cid = clock_context->local_cid; + marker.data.remote_cid = clock_context->remote_cid; + marker.series_id = ntohl(start.series_id); + marker.data.packet_id = 'r'; + ptp->series_id = marker.series_id; + ptp->flags = ntohl(start.flags); + msg = (char *)&count; + size = sizeof(count); + ctx.msg.count = 0; + ctx.size = PTP_SYNC_LOOP; + ctx.ptp = ptp; + ctx.clock = clock_context; + ctx.msg.series_id = ptp->series_id; + while (true) { + count = 0; + ret = tracecmd_msg_recv_time_sync(tsync->msg_handle, + sync_proto, &sync_msg, + &size, &msg); + if (ret || strncmp(sync_proto, PTP_NAME, TRACECMD_TSYNC_PNAME_LENGTH) || + sync_msg != PTP_SYNC_PKT_PROBE || !ntohl(count)) + break; + marker.data.count = ntohl(count); + ptp_track_clock(&ctx, &marker); + ret = tracecmd_msg_send_time_sync(tsync->msg_handle, PTP_NAME, + PTP_SYNC_PKT_PROBE, + sizeof(count), (char *)&count); + if (ret) + break; + } + + if (strncmp(sync_proto, PTP_NAME, TRACECMD_TSYNC_PNAME_LENGTH) || + sync_msg != PTP_SYNC_PKT_END) + return -1; + + if (ptp->flags & PTP_FLAG_USE_MARKER) + tracefs_iterate_raw_events(ptp->tep, clock_context->instance, + ptp_marker_find, &ctx); + + hton_ptp_results(&ctx.msg); + ret = tracecmd_msg_send_time_sync(tsync->msg_handle, PTP_NAME, + PTP_SYNC_PKT_PROBES, + sizeof(ctx.msg), (char *)&ctx.msg); + + msg = (char *)&res_offset; + size = sizeof(res_offset); + ret = tracecmd_msg_recv_time_sync(tsync->msg_handle, + sync_proto, &sync_msg, + &size, (char **)&msg); + if (ret || strncmp(sync_proto, PTP_NAME, TRACECMD_TSYNC_PNAME_LENGTH) || + sync_msg != PTP_SYNC_PKT_OFFSET) + return -1; + + *offset = ntohll(res_offset.offset); + *timestamp = ntohll(res_offset.ts); + + return 0; +} + + +static int ptp_clock_server(struct tracecmd_time_sync *tsync, + long long *offset, long long *timestamp) +{ + char sync_proto[TRACECMD_TSYNC_PNAME_LENGTH]; + struct ptp_clock_result_msg *results = NULL; + struct clock_sync_context *clock_context; + struct ptp_clock_offset_msg res_offset; + struct ptp_clock_start_msg start; + struct ptp_markers_context ctx; + int sync_loop = PTP_SYNC_LOOP; + struct ptp_clock_sync *ptp; + struct ptp_marker marker; + unsigned int sync_msg; + unsigned int size; + int bad_probes; + int count = 1; + int msg_count; + int msg_ret; + char *msg; + int ret; + + if (!tsync || !tsync->context || !tsync->msg_handle) + return -1; + + clock_context = (struct clock_sync_context *)tsync->context; + if (clock_context->proto_data == NULL) + return -1; + + ptp = (struct ptp_clock_sync *)clock_context->proto_data; + ptp->flags = ptp_flags; + memset(&start, 0, sizeof(start)); + start.series_id = htonl(ptp->series_id + 1); + start.flags = htonl(ptp->flags); + ret = tracecmd_msg_send_time_sync(tsync->msg_handle, PTP_NAME, + PTP_SYNC_PKT_START, sizeof(start), + (char *)&start); + if (!ret) + ret = tracecmd_msg_recv_time_sync(tsync->msg_handle, + sync_proto, &sync_msg, + NULL, NULL); + if (ret || strncmp(sync_proto, PTP_NAME, TRACECMD_TSYNC_PNAME_LENGTH) || + sync_msg != PTP_SYNC_PKT_START) + return -1; + + tracefs_instance_file_write(clock_context->instance, "trace", "\0"); + + ptp->series_id++; + marker.data.local_cid = clock_context->local_cid; + marker.data.remote_cid = clock_context->remote_cid; + marker.series_id = ptp->series_id; + msg = (char *)&msg_ret; + size = sizeof(msg_ret); + ctx.size = 2*PTP_SYNC_LOOP; + ctx.ptp = ptp; + ctx.clock = clock_context; + ctx.msg.count = 0; + ctx.msg.series_id = ptp->series_id; + do { + marker.data.count = count++; + marker.data.packet_id = 's'; + msg_count = htonl(marker.data.count); + ptp_track_clock(&ctx, &marker); + ret = tracecmd_msg_send_time_sync(tsync->msg_handle, PTP_NAME, + PTP_SYNC_PKT_PROBE, + sizeof(msg_count), + (char *)&msg_count); + if (!ret) + ret = tracecmd_msg_recv_time_sync(tsync->msg_handle, + sync_proto, &sync_msg, + &size, &msg); + + marker.data.packet_id = 'r'; + ptp_track_clock(&ctx, &marker); + if (ret || strncmp(sync_proto, PTP_NAME, TRACECMD_TSYNC_PNAME_LENGTH) || + sync_msg != PTP_SYNC_PKT_PROBE || + ntohl(msg_ret) != marker.data.count) + break; + } while (--sync_loop); + + if (sync_loop) + return -1; + + ret = tracecmd_msg_send_time_sync(tsync->msg_handle, PTP_NAME, + PTP_SYNC_PKT_END, 0, NULL); + + size = 0; + ret = tracecmd_msg_recv_time_sync(tsync->msg_handle, + sync_proto, &sync_msg, + &size, (char **)&results); + if (ret || strncmp(sync_proto, PTP_NAME, TRACECMD_TSYNC_PNAME_LENGTH) || + sync_msg != PTP_SYNC_PKT_PROBES || size == 0 || results == NULL) + return -1; + + ntoh_ptp_results(results); + if (ptp->flags & PTP_FLAG_USE_MARKER) + tracefs_iterate_raw_events(ptp->tep, clock_context->instance, + ptp_marker_find, &ctx); + if (ptp->flags & PTP_FLAG_FASTEST_RESPONSE) + ptp_calc_offset_fastest(clock_context, &ctx.msg, results, offset, + timestamp, &bad_probes); + else + ptp_calc_offset_hist(clock_context, &ctx.msg, results, offset, + timestamp, &bad_probes); +#ifdef TSYNC_DEBUG + { + char buff[256]; + int res_fd; + + sprintf(buff, "res-cid%d.txt", clock_context->remote_cid); + + res_fd = open(buff, O_WRONLY|O_APPEND, 0644); + if (res_fd > 0) { + if (*offset && *timestamp) { + sprintf(buff, "%d %lld %lld\n", + ptp->series_id, *offset, *timestamp); + write(res_fd, buff, strlen(buff)); + } + close(res_fd); + } + + printf("\n calculated offset %d: %lld, %d probes, filtered out %d, PTP flags 0x%X\n\r", + ptp->series_id, *offset, results->count, bad_probes, ptp->flags); + if (ptp && ptp->debug_fd > 0) { + sprintf(buff, "%lld %lld 0\n", *offset, *timestamp); + write(ptp->debug_fd, buff, strlen(buff)); + close(ptp->debug_fd); + ptp->debug_fd = -1; + } + + } +#endif + + res_offset.offset = htonll(*offset); + res_offset.ts = htonll(*timestamp); + ret = tracecmd_msg_send_time_sync(tsync->msg_handle, PTP_NAME, + PTP_SYNC_PKT_OFFSET, + sizeof(res_offset), + (char *)&res_offset); + + free(results); + return 0; +} + +static int ptp_clock_sync_calc(struct tracecmd_time_sync *tsync, + long long *offset, long long *scaling, + long long *timestamp, unsigned int cpu) +{ + struct clock_sync_context *clock_context; + int ret; + + if (!tsync || !tsync->context) + return -1; + clock_context = (struct clock_sync_context *)tsync->context; + +#ifdef TSYNC_DEBUG + if (clock_context->is_server) { + struct ptp_clock_sync *ptp; + char buff[256]; + + ptp = (struct ptp_clock_sync *)clock_context->proto_data; + if (ptp->debug_fd > 0) + close(ptp->debug_fd); + sprintf(buff, "s-cid%d_%d.txt", + clock_context->remote_cid, ptp->series_id+1); + ptp->debug_fd = open(buff, O_CREAT|O_WRONLY|O_TRUNC, 0644); + } +#endif + + if (scaling) + *scaling = 1; + if (clock_context->is_server) + ret = ptp_clock_server(tsync, offset, timestamp); + else + ret = ptp_clock_client(tsync, offset, timestamp); + + return ret; +} + +int ptp_clock_sync_register(void) +{ + return tracecmd_tsync_proto_register(PTP_NAME, PTP_ACCURACY, + TRACECMD_TIME_SYNC_ROLE_GUEST | + TRACECMD_TIME_SYNC_ROLE_HOST, + 0, TRACECMD_TSYNC_FLAG_INTERPOLATE, + ptp_clock_sync_init, + ptp_clock_sync_free, + ptp_clock_sync_calc); + +} + +int ptp_clock_sync_unregister(void) +{ + return tracecmd_tsync_proto_unregister(PTP_NAME); +} diff --git a/lib/trace-cmd/trace-timesync.c b/lib/trace-cmd/trace-timesync.c index 9db9d3a5..b8ed82c7 100644 --- a/lib/trace-cmd/trace-timesync.c +++ b/lib/trace-cmd/trace-timesync.c @@ -64,7 +64,7 @@ static struct tsync_proto *tsync_proto_find(const char *proto_name) */ void tracecmd_tsync_init(void) { - + ptp_clock_sync_register(); } int tracecmd_tsync_proto_register(const char *proto_name, int accuracy, int roles, From patchwork Thu Jan 21 07:44:55 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Tzvetomir Stoyanov (VMware)" X-Patchwork-Id: 12035065 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.7 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 948B5C433E6 for ; Thu, 21 Jan 2021 07:47:54 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 5094E2396F for ; Thu, 21 Jan 2021 07:47:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727470AbhAUHri (ORCPT ); Thu, 21 Jan 2021 02:47:38 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50144 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727754AbhAUHrB (ORCPT ); Thu, 21 Jan 2021 02:47:01 -0500 Received: from mail-wr1-x42a.google.com (mail-wr1-x42a.google.com [IPv6:2a00:1450:4864:20::42a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 733A8C06179C for ; Wed, 20 Jan 2021 23:45:16 -0800 (PST) Received: by mail-wr1-x42a.google.com with SMTP id a9so735089wrt.5 for ; Wed, 20 Jan 2021 23:45:16 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=IenKFzFG83xtDGf9KkCaQpGW0t9/z9lSzSq7mZfH8BY=; b=WMBAEVXX7Z6PUKMw2X3pI0y8rbH7qG5JB12Y0pedjt7lrl8MGyj0IQDC4L13MR2vyb 7iJ94C15sI5LyS4eCSZV4KXQ8RjPgG2sai3Qp/lNusa6wyYIlwYre1tFlJej2WkJ2TvF LLKB+0GEceqsp80RZVf05fQ5bcExRt4mjkA8kfuZAncsi4tl4tehPygnJx9Fo0YqH6aU Iw7d8ktZLpKyP4RMlmn6+P/08Ca/U7qyxqUbv5Xg4PyxNx0NoP58OTdsoLz+S4vzqNtx Hv015O7TG42Wg1py9tMgNcR/mXJQ18sUHcLnSqBPxvcIJ20rURxG/bmFu5HwFwrRL8df RzuA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=IenKFzFG83xtDGf9KkCaQpGW0t9/z9lSzSq7mZfH8BY=; b=I0f/T5YepCc0pYgwzlgVYHtsHaBlMH8DOG4YVdNRaLC76k53z3CvcMMC0SqUxaU+JY Cit3hU63mNCIwzTGcK86lQuLAjHlN9GjKZ4a26anoOEl7dp2ywHNF1GTNiikX2o1ueoz VhLUwyHIUCAWIq+eyUGKCBINJmofmLkxPYKayohN1Mt0tCMh9UUY8dZlSqTA5N8lbDKm 10NaPzagkeuXDbqfBRb0CbB9wD1aD6e9LT/TcCC4YdrzrVuARtMg88/l9jxzGHXjg3h3 OZSLT+5PcxzSxO3qJBdBSXUvSplXnGIJRenG9/EoBggGgmP1DWv9UKEV1ZVbJKu7U5rg ST1g== X-Gm-Message-State: AOAM532DlECBx2Hq04FZpTe0qYOC/WSGIT1Lk0brqqg8LnTAibR8fufa dGWcMO0Zb4E2ljCgAeGVcTY= X-Google-Smtp-Source: ABdhPJwD0r3y9dPJIzAcTkgWQi3WSVAHdNM4pQcVbe6vkoahnjNXsOSauNs7/HTTkysc341Z3zJ1Vw== X-Received: by 2002:adf:decb:: with SMTP id i11mr12926567wrn.26.1611215115256; Wed, 20 Jan 2021 23:45:15 -0800 (PST) Received: from oberon.zico.biz ([83.222.187.186]) by smtp.gmail.com with ESMTPSA id q6sm6788474wmj.32.2021.01.20.23.45.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 20 Jan 2021 23:45:14 -0800 (PST) From: "Tzvetomir Stoyanov (VMware)" To: rostedt@goodmis.org Cc: linux-trace-devel@vger.kernel.org Subject: [PATCH v26 14/15] trace-cmd: Debug scripts for PTP-like algorithm for host - guest timestamp synchronization Date: Thu, 21 Jan 2021 09:44:55 +0200 Message-Id: <20210121074456.157658-15-tz.stoyanov@gmail.com> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210121074456.157658-1-tz.stoyanov@gmail.com> References: <20210121074456.157658-1-tz.stoyanov@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org These scripts can be used to visualise debug files, written when the PTP-like algorithm is compiled with TSYNC_DEBUG defined. The files are located in the guest machine: s-cid*.txt - For each offset calculation: host and guest clocks and calculated offset. res-cid*.txt - For each tracing session: all calculated clock offsets. tsync_hist.py plots a histogram, using data from a s-cid*.txt file: "python tsync_hist.py s-cid2_1.txt" tsync_res.py plots a line, using data from res-cid*.txt file: "python tsync_res.py res-cid2.txt" Signed-off-by: Tzvetomir Stoyanov (VMware) --- scripts/debug/tsync_hist.py | 57 +++++++++++++++++++++++++++++++++++++ scripts/debug/tsync_readme | 12 ++++++++ scripts/debug/tsync_res.py | 46 ++++++++++++++++++++++++++++++ 3 files changed, 115 insertions(+) create mode 100644 scripts/debug/tsync_hist.py create mode 100644 scripts/debug/tsync_readme create mode 100644 scripts/debug/tsync_res.py diff --git a/scripts/debug/tsync_hist.py b/scripts/debug/tsync_hist.py new file mode 100644 index 00000000..819d1e8f --- /dev/null +++ b/scripts/debug/tsync_hist.py @@ -0,0 +1,57 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# Copyright (C) 2019, VMware Inc, Tzvetomir Stoyanov +# Copyright (C) 2019, VMware Inc, Yordan Karadzhov + + +import matplotlib.pyplot as plt +import matplotlib.lines as mlines +import numpy as np +import sys + +def newline(p1, p2): + ax = plt.gca() + xmin, xmax = ax.get_xbound() + + if(p2[0] == p1[0]): + xmin = xmax = p1[0] + ymin, ymax = ax.get_ybound() + else: + ymax = p1[1]+(p2[1]-p1[1])/(p2[0]-p1[0])*(xmax-p1[0]) + ymin = p1[1]+(p2[1]-p1[1])/(p2[0]-p1[0])*(xmin-p1[0]) + + l = mlines.Line2D([xmin,xmax], [ymin,ymax], color='red') + ax.add_line(l) + return l + + +data = np.loadtxt(fname = sys.argv[1]) +selected_ts = data[-1, 1] +selected_ofs = data[-1, 0] +data = data[:-1,:] + +x = data[:, 1] - data[:, 0] + +mean = x.mean() +std = x.std() + +num_bins = 500 +min = x.min() #+ .4 * (x.max() - x.min()) +max = x.max() #- .4 * (x.max() - x.min()) +bins = np.linspace(min, max, num_bins, endpoint = False, dtype=int) + +fig, ax = plt.subplots() + +# the histogram of the data +n, bins, patches = ax.hist(x, bins, histtype=u'step'); + +ax.set_xlabel('clock offset [$\mu$s]') +ax.set_ylabel('entries') +ax.set_title("$\sigma$=%i" % std) + +x1, y1 = [selected_ofs, min], [selected_ofs, max] +newline(x1, y1) + +# Tweak spacing to prevent clipping of ylabel +fig.tight_layout() +plt.show() diff --git a/scripts/debug/tsync_readme b/scripts/debug/tsync_readme new file mode 100644 index 00000000..f3ebb25d --- /dev/null +++ b/scripts/debug/tsync_readme @@ -0,0 +1,12 @@ +PTP-like algorithm debug +======================== + +tsync_*.py scripts can be used to visualise debug files, written when the PTP-like algorithm +is compiled with TSYNC_DEBUG defined. The files are located in the guest machine: + s-cid*.txt - For each offset calculation: host and guest clocks and calculated offset. + res-cid*.txt - For each tracing session: all calculated clock offsets. + +tsync_hist.py plots a histogram, using data from a s-cid*.txt file: + "python tsync_hist.py s-cid2_1.txt" +tsync_res.py plots a line, using data from res-cid*.txt file: + "python tsync_res.py res-cid2.txt" diff --git a/scripts/debug/tsync_res.py b/scripts/debug/tsync_res.py new file mode 100644 index 00000000..7d109863 --- /dev/null +++ b/scripts/debug/tsync_res.py @@ -0,0 +1,46 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# Copyright (C) 2019, VMware Inc, Tzvetomir Stoyanov +# Copyright (C) 2019, VMware Inc, Yordan Karadzhov + + +import matplotlib.pyplot as plt +import matplotlib.lines as mlines +import numpy as np +import sys + +def newline(p1, p2): + ax = plt.gca() + xmin, xmax = ax.get_xbound() + + if(p2[0] == p1[0]): + xmin = xmax = p1[0] + ymin, ymax = ax.get_ybound() + else: + ymax = p1[1]+(p2[1]-p1[1])/(p2[0]-p1[0])*(xmax-p1[0]) + ymin = p1[1]+(p2[1]-p1[1])/(p2[0]-p1[0])*(xmin-p1[0]) + + l = mlines.Line2D([xmin,xmax], [ymin,ymax], color='red') + ax.add_line(l) + return l + +data = np.loadtxt(fname = sys.argv[1]) +x = data[:, 0] +y = data[:, 1] + +fig, ax = plt.subplots() + +ax.set_xlabel('samples (t)') +ax.set_ylabel('clock offset') +ax.set_title("$\delta$=%i ns" % (max(y) - min(y))) + +l = mlines.Line2D(x, y) +ax.add_line(l) +ax.set_xlim(min(x), max(x)) +ax.set_ylim(min(y), max(y) ) + +print(min(y), max(y), max(y) - min(y)) + +# Tweak spacing to prevent clipping of ylabel +fig.tight_layout() +plt.show() From patchwork Thu Jan 21 07:44:56 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Tzvetomir Stoyanov (VMware)" X-Patchwork-Id: 12035047 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 76C2FC433E0 for ; Thu, 21 Jan 2021 07:47:22 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 2FD7423356 for ; Thu, 21 Jan 2021 07:47:22 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727772AbhAUHrS (ORCPT ); Thu, 21 Jan 2021 02:47:18 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50088 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727718AbhAUHrM (ORCPT ); Thu, 21 Jan 2021 02:47:12 -0500 Received: from mail-wr1-x42a.google.com (mail-wr1-x42a.google.com [IPv6:2a00:1450:4864:20::42a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7FE24C06179E for ; Wed, 20 Jan 2021 23:45:17 -0800 (PST) Received: by mail-wr1-x42a.google.com with SMTP id a1so734778wrq.6 for ; Wed, 20 Jan 2021 23:45:17 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=PJSb9OOJPBlS6pFTzi4KYc8KJscqDen08f3PVzQ1c1o=; b=DB8HcmCBGFfHzVepztfX3s+2i8Q6MLfZtRm6CX/30CEHrFoaRCGliwzs+21GmqHK1z etl2byps5/cS/GgSrwJKt+uijMRP6QJPwaOVGPBQtunbtiLOKvFKVYgtPA4TVd9Oe71i nQJVRRJfuuB/h9oB5XnqiBDGZNv221yg1p4epj34VsAp4Dz2M58nWgL/ssh4pphJmSQW CW10kAKB8RBeSLjAw1dnyf4x3fL6HfJcHqlF1NW2cWkvIf0D8UlinD1sUX6di+WJW/4c 3BcovT31lbvLspsYfHXnq22qG9LtHtS0ozDBDFb7qql+sM3l0cPvRXWh3CRS071H07hQ FjVg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=PJSb9OOJPBlS6pFTzi4KYc8KJscqDen08f3PVzQ1c1o=; b=h1dVHj6JdXnm+XMFSw/cV8Qr/6DlmCkoynfOMgGRvYxjZ7pzbdx/nq+LcIJZtGZ1v3 SJyjW9cEhM880bMmkKG+vVClV0m8EmRgF18+f4NvTZkcWP1h+AUpmwK1qb1xn0kj1jlf 3P+qT6/reNKqi2LBwUTrE2UDSki6SwbK6pnp1Q6ZZiP1V1dVNERuYSBVgDLbm2nWys16 tHsD5uoNySX0m+fj1t/Nnsl6gvBbMNUK8t26zZxxqEjV8zb9BwpulfHu1UBx1y6j0SeI xgJqhLpIsTZ0QMjrbsvjUJ7T35kn2X8qqQQhh7YwyEcNUe0H5+sPvZa9HDzRW5C3mlt+ aqqg== X-Gm-Message-State: AOAM530TMsU1Cog9LJJQO2xudzZP9GZkwJVoaCABCcw5sGYa4q3YsHQN q00GGSAriwXGe+gve06XGqoqqNFGuyopP/vl X-Google-Smtp-Source: ABdhPJw93wucaHpmni7sMGMPi1DjhJk5uw6rIOgbQcesOQYJhOGSSU8iS/QVtGasgUEjgYnF7Tb2lA== X-Received: by 2002:a05:6000:368:: with SMTP id f8mr12781122wrf.150.1611215116263; Wed, 20 Jan 2021 23:45:16 -0800 (PST) Received: from oberon.zico.biz ([83.222.187.186]) by smtp.gmail.com with ESMTPSA id q6sm6788474wmj.32.2021.01.20.23.45.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 20 Jan 2021 23:45:15 -0800 (PST) From: "Tzvetomir Stoyanov (VMware)" To: rostedt@goodmis.org Cc: linux-trace-devel@vger.kernel.org Subject: [PATCH v26 15/15] trace-cmd [POC]: Add KVM timestamp synchronization plugin Date: Thu, 21 Jan 2021 09:44:56 +0200 Message-Id: <20210121074456.157658-16-tz.stoyanov@gmail.com> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210121074456.157658-1-tz.stoyanov@gmail.com> References: <20210121074456.157658-1-tz.stoyanov@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-trace-devel@vger.kernel.org Added new timestamp synchronization plugin for KVM hosts. It reads the clock offsets directly from the KVM debug filesystem, if available. The plugin works only with x86-tsc ftrace clock. Signed-off-by: Tzvetomir Stoyanov (VMware) --- lib/trace-cmd/Makefile | 1 + lib/trace-cmd/include/trace-tsync-local.h | 1 + lib/trace-cmd/trace-timesync-kvm.c | 459 ++++++++++++++++++++++ lib/trace-cmd/trace-timesync.c | 1 + 4 files changed, 462 insertions(+) create mode 100644 lib/trace-cmd/trace-timesync-kvm.c diff --git a/lib/trace-cmd/Makefile b/lib/trace-cmd/Makefile index f41feef8..e8d2dae9 100644 --- a/lib/trace-cmd/Makefile +++ b/lib/trace-cmd/Makefile @@ -20,6 +20,7 @@ OBJS += trace-plugin.o ifeq ($(VSOCK_DEFINED), 1) OBJS += trace-timesync.o OBJS += trace-timesync-ptp.o +OBJS += trace-timesync-kvm.o endif # Additional util objects diff --git a/lib/trace-cmd/include/trace-tsync-local.h b/lib/trace-cmd/include/trace-tsync-local.h index d4281469..fe91e2e3 100644 --- a/lib/trace-cmd/include/trace-tsync-local.h +++ b/lib/trace-cmd/include/trace-tsync-local.h @@ -49,5 +49,6 @@ int tracecmd_tsync_proto_register(const char *proto_name, int accuracy, int role int tracecmd_tsync_proto_unregister(char *proto_name); int ptp_clock_sync_register(void); +int kvm_clock_sync_register(void); #endif /* _TRACE_TSYNC_LOCAL_H */ diff --git a/lib/trace-cmd/trace-timesync-kvm.c b/lib/trace-cmd/trace-timesync-kvm.c new file mode 100644 index 00000000..ba3a958a --- /dev/null +++ b/lib/trace-cmd/trace-timesync-kvm.c @@ -0,0 +1,459 @@ +// SPDX-License-Identifier: LGPL-2.1 +/* + * Copyright (C) 2020, VMware, Tzvetomir Stoyanov tz.stoyanov@gmail.com> + * + */ + +#include +#include +#include +#include +#include + +#include "trace-cmd.h" +#include "tracefs.h" +#include "trace-tsync-local.h" + +#define KVM_DEBUG_FS "/sys/kernel/debug/kvm" +#define KVM_DEBUG_OFFSET_FILE "tsc-offset" +#define KVM_DEBUG_SCALING_FILE "tsc-scaling-ratio" +#define KVM_DEBUG_VCPU_DIR "vcpu" + +#define KVM_SYNC_PKT_REQUEST 1 +#define KVM_SYNC_PKT_RESPONSE 2 + +typedef __s64 s64; + +// equal to /sys/kernel/debug/kvm//vcpu0/tsc-offset +#define KVM_ACCURACY 0 +#define KVM_NAME "kvm" + +struct kvm_clock_sync { + int vcpu_count; + char **vcpu_offsets; + char **vcpu_scalings; + int marker_fd; + struct tep_handle *tep; + int raw_id; + unsigned long long ts; +}; + +struct kvm_clock_offset_msg { + s64 ts; + s64 offset; + s64 scaling; +}; + +static bool kvm_support_check(bool guest) +{ + struct stat st; + int ret; + + if (guest) + return true; + + ret = stat(KVM_DEBUG_FS, &st); + if (ret < 0) + return false; + + if (!S_ISDIR(st.st_mode)) + return false; + return true; +} + +static int kvm_open_vcpu_dir(struct kvm_clock_sync *kvm, int cpu, char *dir_str) +{ + struct dirent *entry; + char path[PATH_MAX]; + DIR *dir; + + dir = opendir(dir_str); + if (!dir) + goto error; + while ((entry = readdir(dir))) { + if (entry->d_type != DT_DIR) { + if (!strncmp(entry->d_name, KVM_DEBUG_OFFSET_FILE, + strlen(KVM_DEBUG_OFFSET_FILE))) { + snprintf(path, sizeof(path), "%s/%s", + dir_str, entry->d_name); + kvm->vcpu_offsets[cpu] = strdup(path); + } + if (!strncmp(entry->d_name, KVM_DEBUG_SCALING_FILE, + strlen(KVM_DEBUG_SCALING_FILE))) { + snprintf(path, sizeof(path), "%s/%s", + dir_str, entry->d_name); + kvm->vcpu_scalings[cpu] = strdup(path); + } + } + } + if (!kvm->vcpu_offsets[cpu]) + goto error; + closedir(dir); + return 0; + +error: + if (dir) + closedir(dir); + free(kvm->vcpu_offsets[cpu]); + kvm->vcpu_offsets[cpu] = NULL; + free(kvm->vcpu_scalings[cpu]); + kvm->vcpu_scalings[cpu] = NULL; + return -1; +} + +static int kvm_open_debug_files(struct kvm_clock_sync *kvm, int pid) +{ + char *vm_dir_str = NULL; + struct dirent *entry; + char *pid_str = NULL; + char path[PATH_MAX]; + long vcpu; + DIR *dir; + int i; + + dir = opendir(KVM_DEBUG_FS); + if (!dir) + goto error; + if (asprintf(&pid_str, "%d-", pid) <= 0) + goto error; + while ((entry = readdir(dir))) { + if (!(entry->d_type == DT_DIR && + !strncmp(entry->d_name, pid_str, strlen(pid_str)))) + continue; + asprintf(&vm_dir_str, "%s/%s", KVM_DEBUG_FS, entry->d_name); + break; + } + closedir(dir); + dir = NULL; + if (!vm_dir_str) + goto error; + dir = opendir(vm_dir_str); + if (!dir) + goto error; + while ((entry = readdir(dir))) { + if (!(entry->d_type == DT_DIR && + !strncmp(entry->d_name, KVM_DEBUG_VCPU_DIR, strlen(KVM_DEBUG_VCPU_DIR)))) + continue; + vcpu = strtol(entry->d_name + strlen(KVM_DEBUG_VCPU_DIR), NULL, 10); + if (vcpu < 0 || vcpu >= kvm->vcpu_count) + continue; + snprintf(path, sizeof(path), "%s/%s", vm_dir_str, entry->d_name); + if (kvm_open_vcpu_dir(kvm, vcpu, path) < 0) + goto error; + } + for (i = 0; i < kvm->vcpu_count; i++) { + if (!kvm->vcpu_offsets[i]) + goto error; + } + closedir(dir); + free(pid_str); + free(vm_dir_str); + return 0; +error: + free(pid_str); + free(vm_dir_str); + if (dir) + closedir(dir); + return -1; +} + +static int kvm_clock_sync_init_host(struct tracecmd_time_sync *tsync, + struct kvm_clock_sync *kvm) +{ + kvm->vcpu_count = tsync->vcpu_count; + kvm->vcpu_offsets = calloc(kvm->vcpu_count, sizeof(char *)); + kvm->vcpu_scalings = calloc(kvm->vcpu_count, sizeof(char *)); + if (!kvm->vcpu_offsets || !kvm->vcpu_scalings) + goto error; + if (kvm_open_debug_files(kvm, tsync->guest_pid) < 0) + goto error; + return 0; + +error: + free(kvm->vcpu_offsets); + free(kvm->vcpu_scalings); + return -1; +} + +static int kvm_clock_sync_init_guest(struct tracecmd_time_sync *tsync, + struct kvm_clock_sync *kvm) +{ + const char *systems[] = {"ftrace", NULL}; + struct clock_sync_context *clock_context; + struct tep_event *raw; + char *path; + + clock_context = (struct clock_sync_context *)tsync->context; + path = tracefs_instance_get_dir(clock_context->instance); + if (!path) + goto error; + kvm->tep = tracefs_local_events_system(path, systems); + tracefs_put_tracing_file(path); + if (!kvm->tep) + goto error; + raw = tep_find_event_by_name(kvm->tep, "ftrace", "raw_data"); + if (!raw) + goto error; + + kvm->raw_id = raw->id; + tep_set_file_bigendian(kvm->tep, tracecmd_host_bigendian()); + tep_set_local_bigendian(kvm->tep, tracecmd_host_bigendian()); + + path = tracefs_instance_get_file(clock_context->instance, "trace_marker_raw"); + if (!path) + goto error; + kvm->marker_fd = open(path, O_WRONLY); + tracefs_put_tracing_file(path); + + return 0; + +error: + if (kvm->tep) + tep_free(kvm->tep); + if (kvm->marker_fd >= 0) + close(kvm->marker_fd); + + return -1; +} + +static int kvm_clock_sync_init(struct tracecmd_time_sync *tsync) +{ + struct clock_sync_context *clock_context; + struct kvm_clock_sync *kvm; + int ret; + + if (!tsync || !tsync->context) + return -1; + clock_context = (struct clock_sync_context *)tsync->context; + + if (!kvm_support_check(clock_context->is_guest)) + return -1; + kvm = calloc(1, sizeof(struct kvm_clock_sync)); + if (!kvm) + return -1; + kvm->marker_fd = -1; + if (clock_context->is_guest) + ret = kvm_clock_sync_init_guest(tsync, kvm); + else + ret = kvm_clock_sync_init_host(tsync, kvm); + if (ret < 0) + goto error; + + clock_context->proto_data = kvm; + return 0; + +error: + free(kvm); + return -1; +} + +static int kvm_clock_sync_free(struct tracecmd_time_sync *tsync) +{ + struct clock_sync_context *clock_context; + struct kvm_clock_sync *kvm = NULL; + int i; + + clock_context = (struct clock_sync_context *)tsync->context; + if (clock_context) + kvm = (struct kvm_clock_sync *)clock_context->proto_data; + if (kvm) { + for (i = 0; i < kvm->vcpu_count; i++) { + free(kvm->vcpu_offsets[i]); + kvm->vcpu_offsets[i] = NULL; + free(kvm->vcpu_scalings[i]); + kvm->vcpu_scalings[i] = NULL; + } + if (kvm->tep) + tep_free(kvm->tep); + if (kvm->marker_fd >= 0) + close(kvm->marker_fd); + free(kvm); + } + return -1; +} + +static int read_ll_form_file(char *file, long long *res) +{ + char buf[32]; + int ret; + int fd; + + if (!file) + return -1; + fd = open(file, O_RDONLY | O_NONBLOCK); + if (fd < 0) + return -1; + ret = read(fd, buf, 32); + close(fd); + if (ret <= 0) + return -1; + + *res = strtoll(buf, NULL, 10); + + return 0; +} + +static int kvm_clock_host(struct tracecmd_time_sync *tsync, + long long *offset, long long *scaling, + long long *timestamp, unsigned int cpu) +{ + char sync_proto[TRACECMD_TSYNC_PNAME_LENGTH]; + struct clock_sync_context *clock_context; + struct kvm_clock_offset_msg packet; + struct kvm_clock_sync *kvm = NULL; + long long kvm_scaling = 1; + unsigned int sync_msg; + long long kvm_offset; + unsigned int size; + char *msg; + int ret; + + clock_context = (struct clock_sync_context *)tsync->context; + if (clock_context) + kvm = (struct kvm_clock_sync *)clock_context->proto_data; + if (!kvm || !kvm->vcpu_offsets || !kvm->vcpu_offsets[0]) + return -1; + if (cpu >= kvm->vcpu_count) + return -1; + ret = read_ll_form_file(kvm->vcpu_offsets[cpu], &kvm_offset); + if (ret < 0) + return -1; + if (kvm->vcpu_scalings && kvm->vcpu_scalings[cpu]) + read_ll_form_file(kvm->vcpu_scalings[cpu], &kvm_scaling); + msg = (char *)&packet; + size = sizeof(packet); + ret = tracecmd_msg_recv_time_sync(tsync->msg_handle, + sync_proto, &sync_msg, + &size, &msg); + if (ret || strncmp(sync_proto, KVM_NAME, TRACECMD_TSYNC_PNAME_LENGTH) || + sync_msg != KVM_SYNC_PKT_REQUEST) + return -1; + + packet.offset = -kvm_offset; + packet.scaling = kvm_scaling; + ret = tracecmd_msg_send_time_sync(tsync->msg_handle, KVM_NAME, + KVM_SYNC_PKT_RESPONSE, sizeof(packet), + (char *)&packet); + if (ret) + return -1; + + *scaling = packet.scaling; + *offset = packet.offset; + *timestamp = packet.ts; + + return 0; +} + +#define KVM_EVENT_MARKER "kvm sync event" +static int kvm_marker_find(struct tep_event *event, struct tep_record *record, + int cpu, void *context) +{ + struct kvm_clock_sync *kvm = (struct kvm_clock_sync *)context; + struct tep_format_field *field; + struct tep_format_field *id; + char *marker; + + /* Make sure this is our event */ + if (event->id != kvm->raw_id) + return 0; + id = tep_find_field(event, "id"); + field = tep_find_field(event, "buf"); + if (field && id && + record->size >= (id->offset + strlen(KVM_EVENT_MARKER) + 1)) { + marker = (char *)(record->data + id->offset); + if (!strcmp(marker, KVM_EVENT_MARKER)) { + kvm->ts = record->ts; + return 1; + } + } + + return 0; +} + + +static int kvm_clock_guest(struct tracecmd_time_sync *tsync, + long long *offset, + long long *scaling, + long long *timestamp) +{ + char sync_proto[TRACECMD_TSYNC_PNAME_LENGTH]; + struct clock_sync_context *clock_context; + struct kvm_clock_offset_msg packet; + struct kvm_clock_sync *kvm = NULL; + unsigned int sync_msg; + unsigned int size; + char *msg; + int ret; + + clock_context = (struct clock_sync_context *)tsync->context; + if (clock_context) + kvm = (struct kvm_clock_sync *)clock_context->proto_data; + if (!kvm) + return -1; + kvm->ts = 0; + memset(&packet, 0, sizeof(packet)); + tracefs_instance_file_write(clock_context->instance, "trace", "\0"); + write(kvm->marker_fd, KVM_EVENT_MARKER, strlen(KVM_EVENT_MARKER) + 1); + kvm->ts = 0; + tracefs_iterate_raw_events(kvm->tep, clock_context->instance, + kvm_marker_find, kvm); + packet.ts = kvm->ts; + ret = tracecmd_msg_send_time_sync(tsync->msg_handle, KVM_NAME, + KVM_SYNC_PKT_REQUEST, sizeof(packet), + (char *)&packet); + if (ret) + return -1; + msg = (char *)&packet; + size = sizeof(packet); + ret = tracecmd_msg_recv_time_sync(tsync->msg_handle, + sync_proto, &sync_msg, + &size, &msg); + if (ret || strncmp(sync_proto, KVM_NAME, TRACECMD_TSYNC_PNAME_LENGTH) || + sync_msg != KVM_SYNC_PKT_RESPONSE) + return -1; + + *scaling = packet.scaling; + *offset = packet.offset; + *timestamp = packet.ts; + return 0; +} + +static int kvm_clock_sync_calc(struct tracecmd_time_sync *tsync, + long long *offset, long long *scaling, + long long *timestamp, unsigned int cpu) +{ + struct clock_sync_context *clock_context; + int ret; + + if (!tsync || !tsync->context) + return -1; + + clock_context = (struct clock_sync_context *)tsync->context; + + if (clock_context->is_guest) + ret = kvm_clock_guest(tsync, offset, scaling, timestamp); + else + ret = kvm_clock_host(tsync, offset, scaling, timestamp, cpu); + return ret; +} + +int kvm_clock_sync_register(void) +{ + int role = TRACECMD_TIME_SYNC_ROLE_GUEST; + int clock = 0; + + if (kvm_support_check(false)) { + role |= TRACECMD_TIME_SYNC_ROLE_HOST; + clock = TRACECMD_CLOCK_X86_TSC; + } + return tracecmd_tsync_proto_register(KVM_NAME, KVM_ACCURACY, + role, clock, 0, + kvm_clock_sync_init, + kvm_clock_sync_free, + kvm_clock_sync_calc); +} + +int kvm_clock_sync_unregister(void) +{ + return tracecmd_tsync_proto_unregister(KVM_NAME); +} diff --git a/lib/trace-cmd/trace-timesync.c b/lib/trace-cmd/trace-timesync.c index b8ed82c7..0747ab42 100644 --- a/lib/trace-cmd/trace-timesync.c +++ b/lib/trace-cmd/trace-timesync.c @@ -65,6 +65,7 @@ static struct tsync_proto *tsync_proto_find(const char *proto_name) void tracecmd_tsync_init(void) { ptp_clock_sync_register(); + kvm_clock_sync_register(); } int tracecmd_tsync_proto_register(const char *proto_name, int accuracy, int roles,