From 8614e600d7a8dc653c473254fc302870d73f32ae Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Wed, 11 Dec 2019 13:24:49 -0500 Subject: [PATCH] relayd: Implement get_configuration relayd protocol command MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Introduce a "GET_CONFIGURATION" command to the relayd protocol. This allows checking whether the relay daemon allows the clear command or not. A 64-bit set of flags are returned, and it can be extended in the future with a variable length payload. Signed-off-by: Mathieu Desnoyers Change-Id: I33a03d09871f1c0c248d5514451c533ffd773979 Signed-off-by: Jérémie Galarneau --- src/bin/lttng-relayd/main.c | 55 +++++++++++++++++++++ src/common/relayd/relayd.c | 62 ++++++++++++++++++++++++ src/common/relayd/relayd.h | 3 ++ src/common/sessiond-comm/relayd.h | 21 ++++++++ src/common/sessiond-comm/sessiond-comm.h | 2 + 5 files changed, 143 insertions(+) diff --git a/src/bin/lttng-relayd/main.c b/src/bin/lttng-relayd/main.c index 6beb21692..d874a9c50 100644 --- a/src/bin/lttng-relayd/main.c +++ b/src/bin/lttng-relayd/main.c @@ -2866,6 +2866,57 @@ end_no_reply: return ret; } +/* + * relay_get_configuration: query whether feature is available + */ +static int relay_get_configuration(const struct lttcomm_relayd_hdr *recv_hdr, + struct relay_connection *conn, + const struct lttng_buffer_view *payload) +{ + int ret = 0; + ssize_t send_ret; + struct lttcomm_relayd_get_configuration *msg; + struct lttcomm_relayd_get_configuration_reply reply = {}; + struct lttng_buffer_view header_view; + uint64_t query_flags = 0; + uint64_t result_flags = 0; + + header_view = lttng_buffer_view_from_view(payload, 0, sizeof(*msg)); + if (!header_view.data) { + ERR("Failed to receive payload of chunk close command"); + ret = -1; + goto end_no_reply; + } + + /* Convert to host endianness. */ + msg = (typeof(msg)) header_view.data; + query_flags = be64toh(msg->query_flags); + + if (query_flags) { + ret = LTTNG_ERR_INVALID_PROTOCOL; + goto reply; + } + if (opt_allow_clear) { + result_flags |= LTTCOMM_RELAYD_CONFIGURATION_FLAG_CLEAR_ALLOWED; + } + ret = 0; +reply: + reply = (typeof(reply)){ + .generic.ret_code = htobe32((uint32_t) + (ret == 0 ? LTTNG_OK : LTTNG_ERR_INVALID_PROTOCOL)), + .relayd_configuration_flags = htobe64(result_flags), + }; + send_ret = conn->sock->ops->sendmsg( + conn->sock, &reply, sizeof(reply), 0); + if (send_ret < (ssize_t) sizeof(reply)) { + ERR("Failed to send \"get configuration\" command reply (ret = %zd)", + send_ret); + ret = -1; + } +end_no_reply: + return ret; +} + #define DBG_CMD(cmd_name, conn) \ DBG3("Processing \"%s\" command for socket %i", cmd_name, conn->sock->fd); @@ -2944,6 +2995,10 @@ static int relay_process_control_command(struct relay_connection *conn, DBG_CMD("RELAYD_TRACE_CHUNK_EXISTS", conn); ret = relay_trace_chunk_exists(header, conn, payload); break; + case RELAYD_GET_CONFIGURATION: + DBG_CMD("RELAYD_GET_CONFIGURATION", conn); + ret = relay_get_configuration(header, conn, payload); + break; case RELAYD_UPDATE_SYNC_INFO: default: ERR("Received unknown command (%u)", header->cmd); diff --git a/src/common/relayd/relayd.c b/src/common/relayd/relayd.c index 228b35cb2..54fe67345 100644 --- a/src/common/relayd/relayd.c +++ b/src/common/relayd/relayd.c @@ -45,6 +45,17 @@ bool relayd_supports_chunks(const struct lttcomm_relayd_sock *sock) return false; } +static +bool relayd_supports_get_configuration(const struct lttcomm_relayd_sock *sock) +{ + if (sock->major > 2) { + return true; + } else if (sock->major == 2 && sock->minor >= 12) { + return true; + } + return false; +} + /* * Send command. Fill up the header and append the data. */ @@ -1533,3 +1544,54 @@ int relayd_trace_chunk_exists(struct lttcomm_relayd_sock *sock, end: return ret; } + +int relayd_get_configuration(struct lttcomm_relayd_sock *sock, + uint64_t query_flags, + uint64_t *result_flags) +{ + int ret = 0; + struct lttcomm_relayd_get_configuration msg = (typeof(msg)) { + .query_flags = htobe64(query_flags), + }; + struct lttcomm_relayd_get_configuration_reply reply = {}; + + if (!relayd_supports_get_configuration(sock)) { + DBG("Refusing to get relayd configuration (unsupported by relayd)"); + if (query_flags) { + ret = -1; + goto end; + } + *result_flags = 0; + goto end; + } + + ret = send_command(sock, RELAYD_GET_CONFIGURATION, &msg, sizeof(msg), + 0); + if (ret < 0) { + ERR("Failed to send get configuration command to relay daemon"); + goto end; + } + + ret = recv_reply(sock, &reply, sizeof(reply)); + if (ret < 0) { + ERR("Failed to receive relay daemon get configuration command reply"); + goto end; + } + + reply.generic.ret_code = be32toh(reply.generic.ret_code); + if (reply.generic.ret_code != LTTNG_OK) { + ret = -1; + ERR("Relayd get configuration replied error %d", + reply.generic.ret_code); + } else { + reply.relayd_configuration_flags = + be64toh(reply.relayd_configuration_flags); + ret = 0; + DBG("Relayd successfully got configuration: query_flags = %" PRIu64 + ", results_flags = %" PRIu64, query_flags, + reply.relayd_configuration_flags); + *result_flags = reply.relayd_configuration_flags; + } +end: + return ret; +} diff --git a/src/common/relayd/relayd.h b/src/common/relayd/relayd.h index 2f0c937f6..c2ee95aed 100644 --- a/src/common/relayd/relayd.h +++ b/src/common/relayd/relayd.h @@ -83,5 +83,8 @@ int relayd_close_trace_chunk(struct lttcomm_relayd_sock *sock, char *path); int relayd_trace_chunk_exists(struct lttcomm_relayd_sock *sock, uint64_t chunk_id, bool *chunk_exists); +int relayd_get_configuration(struct lttcomm_relayd_sock *sock, + uint64_t query_flags, + uint64_t *result_flags); #endif /* _RELAYD_H */ diff --git a/src/common/sessiond-comm/relayd.h b/src/common/sessiond-comm/relayd.h index de0c7f254..492f3efae 100644 --- a/src/common/sessiond-comm/relayd.h +++ b/src/common/sessiond-comm/relayd.h @@ -293,4 +293,25 @@ struct lttcomm_relayd_trace_chunk_exists_reply { uint8_t trace_chunk_exists; } LTTNG_PACKED; +enum lttcomm_relayd_configuration_flag { + /* The relay daemon (2.12) is configured to allow clear operations. */ + LTTCOMM_RELAYD_CONFIGURATION_FLAG_CLEAR_ALLOWED = (1 << 0), +}; + +struct lttcomm_relayd_get_configuration { + uint64_t query_flags; +} LTTNG_PACKED; + +/* + * Used to return a relay daemon's configuration in reply to the + * RELAYD_GET_CONFIGURATION command. + */ +struct lttcomm_relayd_get_configuration_reply { + struct lttcomm_relayd_generic_reply generic; + /* Set of lttcomm_relayd_configuration_flag. */ + uint64_t relayd_configuration_flags; + /* Optional variable-length payload. */ + char payload[]; +} LTTNG_PACKED; + #endif /* _RELAYD_COMM */ diff --git a/src/common/sessiond-comm/sessiond-comm.h b/src/common/sessiond-comm/sessiond-comm.h index cf50f0e44..8b1757438 100644 --- a/src/common/sessiond-comm/sessiond-comm.h +++ b/src/common/sessiond-comm/sessiond-comm.h @@ -140,6 +140,8 @@ enum lttcomm_relayd_command { RELAYD_CLOSE_TRACE_CHUNK = 20, /* Ask the relay whether a trace chunk exists (2.11+) */ RELAYD_TRACE_CHUNK_EXISTS = 21, + /* Get the current configuration of a relayd peer (2.12+) */ + RELAYD_GET_CONFIGURATION = 22, /* Feature branch specific commands start at 10000. */ }; -- 2.34.1