From: Jonathan Rajotte Date: Fri, 6 May 2022 19:01:30 +0000 (-0400) Subject: relayd: Extend relayd get configuration command to check for trace format support X-Git-Url: http://git.efficios.com/?a=commitdiff_plain;h=f4c5b12712588c5b79719a21001d57d73840bf75;p=deliverable%2Flttng-tools.git relayd: Extend relayd get configuration command to check for trace format support Signed-off-by: Jonathan Rajotte Change-Id: Id06c8a5de4eb0a5b2919390b3b019d17d0365544 --- diff --git a/include/lttng/lttng-error.h b/include/lttng/lttng-error.h index 1438e0dc2..6a0f350ae 100644 --- a/include/lttng/lttng-error.h +++ b/include/lttng/lttng-error.h @@ -184,6 +184,7 @@ enum lttng_error_code { LTTNG_ERR_INVALID_ERROR_QUERY_TARGET = 169, /* Invalid error query target. */ LTTNG_ERR_BUFFER_FLUSH_FAILED = 170, /* Buffer flush failed */ LTTNG_ERR_TRACE_FORMAT_UNSUPPORTED_KERNEL_TRACER = 171, /* Kernel tracer does not support the specified trace format */ + LTTNG_ERR_TRACE_FORMAT_UNSUPPORTED_RELAY_DAEMON = 172, /* The trace format is not supported by the targeted lttng-relayd */ /* MUST be last element of the manually-assigned section of the enum */ LTTNG_ERR_NR, diff --git a/include/lttng/trace-format-descriptor-internal.hpp b/include/lttng/trace-format-descriptor-internal.hpp index 527965670..eb27c3e65 100644 --- a/include/lttng/trace-format-descriptor-internal.hpp +++ b/include/lttng/trace-format-descriptor-internal.hpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include diff --git a/src/bin/lttng-relayd/main.cpp b/src/bin/lttng-relayd/main.cpp index 318af66f7..e2d947cc6 100644 --- a/src/bin/lttng-relayd/main.cpp +++ b/src/bin/lttng-relayd/main.cpp @@ -3286,9 +3286,14 @@ static int relay_get_configuration( struct lttcomm_relayd_get_configuration *msg; struct lttcomm_relayd_get_configuration_reply reply = {}; struct lttng_buffer_view header_view; + struct lttng_dynamic_buffer buffer; + struct lttng_dynamic_buffer extra_payload; uint64_t query_flags = 0; uint64_t result_flags = 0; + lttng_dynamic_buffer_init(&buffer); + lttng_dynamic_buffer_init(&extra_payload); + header_view = lttng_buffer_view_from_view(payload, 0, sizeof(*msg)); if (!lttng_buffer_view_is_valid(&header_view)) { ERR("Failed to receive payload of chunk close command"); @@ -3300,26 +3305,47 @@ static int relay_get_configuration( msg = (typeof(msg)) header_view.data; query_flags = be64toh(msg->query_flags); - if (query_flags) { + if (query_flags & ~LTTCOMM_RELAYD_CONFIGURATION_QUERY_FLAG_MASK) { ret = LTTNG_ERR_INVALID_PROTOCOL; goto reply; } + if (opt_allow_clear) { result_flags |= LTTCOMM_RELAYD_CONFIGURATION_FLAG_CLEAR_ALLOWED; } - ret = 0; + + if (query_flags & LTTCOMM_RELAYD_CONFIGURATION_QUERY_FLAG_SUPPORTED_TRACE_FORMAT) { + uint64_t supported_trace_format = 0; + + supported_trace_format |= LTTCOMM_RELAYD_CONFIGURATION_TRACE_FORMAT_SUPPORTED_CTF1; + + supported_trace_format = htobe64(supported_trace_format); + + lttcomm_relayd_get_configuration_specialized_query_reply s_reply = {}; + s_reply.query_flag = htobe64( + LTTCOMM_RELAYD_CONFIGURATION_QUERY_FLAG_SUPPORTED_TRACE_FORMAT); + s_reply.payload_len = htobe64((uint64_t) sizeof(supported_trace_format)); + lttng_dynamic_buffer_append(&extra_payload, &s_reply, sizeof(s_reply)); + lttng_dynamic_buffer_append(&extra_payload, &supported_trace_format, + sizeof(supported_trace_format)); + } + reply: - reply.generic.ret_code = htobe32((uint32_t) (ret == 0 ? LTTNG_OK : LTTNG_ERR_INVALID_PROTOCOL)); + reply.generic.ret_code = + htobe32((uint32_t) (ret == 0 ? LTTNG_OK : LTTNG_ERR_INVALID_PROTOCOL)); reply.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); + lttng_dynamic_buffer_append(&buffer, &reply, sizeof(reply)); + lttng_dynamic_buffer_append_buffer(&buffer, &extra_payload); + + send_ret = conn->sock->ops->sendmsg(conn->sock, buffer.data, buffer.size, 0); + if (send_ret < (ssize_t) buffer.size) { + ERR("Failed to send \"get configuration\" command reply (ret = %zd)", send_ret); ret = -1; } end_no_reply: + lttng_dynamic_buffer_reset(&extra_payload); + lttng_dynamic_buffer_reset(&buffer); return ret; } diff --git a/src/bin/lttng-sessiond/cmd.cpp b/src/bin/lttng-sessiond/cmd.cpp index be1ab52ab..f975f31e2 100644 --- a/src/bin/lttng-sessiond/cmd.cpp +++ b/src/bin/lttng-sessiond/cmd.cpp @@ -890,6 +890,28 @@ error: return status; } +static bool is_trace_format_configuration_supported( + uint64_t supported_trace_format, lttng::trace_format_descriptor& trace_format) +{ + static const std::unordered_map + mapping = { + {LTTNG_TRACE_FORMAT_DESCRIPTOR_TYPE_CTF_1, + LTTCOMM_RELAYD_CONFIGURATION_TRACE_FORMAT_SUPPORTED_CTF1}, + }; + + auto it = mapping.find(trace_format.type()); + if (it == mapping.end()) { + return false; + } + + if (!(supported_trace_format & it->second)) { + return false; + } + + return true; +} + /* * Send both relayd sockets to a specific consumer and domain. This is a * helper function to facilitate sending the information to the consumer for a @@ -916,6 +938,7 @@ static lttng_error_code send_consumer_relayd_sockets(const ltt_session& session, if (!sock->control_sock_sent) { int ret; uint64_t result_flags = 0; + uint64_t supported_trace_format = 0; /* Connect to relayd and make version check if uri is the control. */ status = create_connect_relayd(&consumer->dst.net.control, &control_sock); if (status != LTTNG_OK) { @@ -926,7 +949,7 @@ static lttng_error_code send_consumer_relayd_sockets(const ltt_session& session, consumer->relay_major_version = control_sock->major; consumer->relay_minor_version = control_sock->minor; - ret = relayd_get_configuration(control_sock, 0, &result_flags); + ret = relayd_get_configuration(control_sock, 0, result_flags, nullptr); if (ret < 0) { ERR("Unable to get relayd configuration"); status = LTTNG_ERR_RELAYD_CONNECT_FAIL; @@ -937,6 +960,13 @@ static lttng_error_code send_consumer_relayd_sockets(const ltt_session& session, consumer->relay_allows_clear = true; } + if (!is_trace_format_configuration_supported( + supported_trace_format, *session.trace_format)) { + ERR("Relayd does not support the requested trace format"); + status = LTTNG_ERR_TRACE_FORMAT_UNSUPPORTED_RELAY_DAEMON; + goto error; + } + status = send_consumer_relayd_socket(session.id, &consumer->dst.net.control, consumer, sock, session.name, session.hostname, base_path, session.live_timer, current_chunk_id, session.creation_time, @@ -999,7 +1029,7 @@ int cmd_setup_relayd(struct ltt_session *session) usess = session->ust_session; ksess = session->kernel_session; - ERR("Setting relayd for session %s", session->name); + DBG("Setting relayd for session %s", session->name); rcu_read_lock(); if (session->current_trace_chunk) { diff --git a/src/common/error.cpp b/src/common/error.cpp index 40c1faf0b..2760b4ff2 100644 --- a/src/common/error.cpp +++ b/src/common/error.cpp @@ -406,6 +406,9 @@ const char *lttng_error_code_str(lttng_error_code code) return "Failed to flush stream buffer"; case LTTNG_ERR_TRACE_FORMAT_UNSUPPORTED_KERNEL_TRACER: return "Kernel tracer does not support the specified trace format"; + case LTTNG_ERR_TRACE_FORMAT_UNSUPPORTED_RELAY_DAEMON: /* The trace format is not supported + by the targeted lttng-relayd */ + return "The relay does not support the specified trace format"; case LTTNG_ERR_NR: abort(); } diff --git a/src/common/relayd/relayd.cpp b/src/common/relayd/relayd.cpp index a422d8b5a..9f444d6e9 100644 --- a/src/common/relayd/relayd.cpp +++ b/src/common/relayd/relayd.cpp @@ -12,14 +12,15 @@ #include #include +#include #include -#include #include #include -#include +#include #include -#include +#include #include +#include #include "relayd.hpp" @@ -45,6 +46,16 @@ bool relayd_supports_get_configuration(const struct lttcomm_relayd_sock *sock) return false; } +static bool relayd_supports_get_configuration_trace_format(const struct lttcomm_relayd_sock *sock) +{ + if (sock->major > 2) { + return true; + } else if (sock->major == 2 && sock->minor >= 15) { + return true; + } + return false; +} + /* * Send command. Fill up the header and append the data. */ @@ -68,7 +79,7 @@ static int send_command(struct lttcomm_relayd_sock *rsock, buf = calloc(buf_size); if (buf == NULL) { PERROR("zmalloc relayd send command buf"); - ret = -1; + ret = -ENOMEM; goto alloc_error; } @@ -1537,49 +1548,112 @@ end: return ret; } -int relayd_get_configuration(struct lttcomm_relayd_sock *sock, +enum lttng_error_code relayd_get_configuration(struct lttcomm_relayd_sock *sock, uint64_t query_flags, - uint64_t *result_flags) + uint64_t& result_flags, + uint64_t *trace_format_query_results) { - int ret = 0; - struct lttcomm_relayd_get_configuration msg = (typeof(msg)) { - .query_flags = htobe64(query_flags), - }; + int ret; + enum lttng_error_code ret_code = LTTNG_OK; + struct lttcomm_relayd_get_configuration msg = {}; struct lttcomm_relayd_get_configuration_reply reply = {}; + lttng_dynamic_buffer buffer; + bool requesting_trace_format = query_flags & + LTTCOMM_RELAYD_CONFIGURATION_QUERY_FLAG_SUPPORTED_TRACE_FORMAT; + + lttng_dynamic_buffer_init(&buffer); + + assert(!(query_flags & ~LTTCOMM_RELAYD_CONFIGURATION_QUERY_FLAG_MASK)); + assert(!(requesting_trace_format && !trace_format_query_results)); if (!relayd_supports_get_configuration(sock)) { DBG("Refusing to get relayd configuration (unsupported by relayd)"); - *result_flags = 0; + result_flags = 0; + if (trace_format_query_results) { + *trace_format_query_results = + LTTCOMM_RELAYD_CONFIGURATION_TRACE_FORMAT_SUPPORTED_CTF1; + } goto end; } - ret = send_command(sock, RELAYD_GET_CONFIGURATION, &msg, sizeof(msg), - 0); + if (requesting_trace_format && !relayd_supports_get_configuration_trace_format(sock)) { + /* + * Provide default value for that query since lttng-relayd does + * not know this query type. + */ + if (trace_format_query_results) { + *trace_format_query_results = + LTTCOMM_RELAYD_CONFIGURATION_TRACE_FORMAT_SUPPORTED_CTF1; + } + /* Remove from the query set. */ + query_flags &= ~LTTCOMM_RELAYD_CONFIGURATION_QUERY_FLAG_SUPPORTED_TRACE_FORMAT; + requesting_trace_format = false; + } + + msg.query_flags = htobe64(query_flags); + + ret = send_command(sock, RELAYD_GET_CONFIGURATION, &msg, sizeof(msg), 0); if (ret < 0) { ERR("Failed to send get configuration command to relay daemon"); + ret_code = LTTNG_ERR_RELAYD_CONNECT_FAIL; goto end; } ret = recv_reply(sock, &reply, sizeof(reply)); if (ret < 0) { ERR("Failed to receive relay daemon get configuration command reply"); + ret_code = LTTNG_ERR_RELAYD_CONNECT_FAIL; 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; + ret_code = static_cast(be32toh(reply.generic.ret_code)); + if (ret_code != LTTNG_OK) { + ERR("Relayd get configuration replied error %d", ret_code); + goto end; } + + result_flags = be64toh(reply.relayd_configuration_flags); + DBG("Relayd successfully got configuration: query_flags = %" PRIu64 + ", results_flags = %" PRIu64, + query_flags, result_flags); + + if (!requesting_trace_format) { + ret_code = LTTNG_OK; + goto end; + } + + /* Receive trace formats */ + { + lttcomm_relayd_get_configuration_specialized_query_reply query_flag_reply = {}; + ret = recv_reply(sock, &query_flag_reply, sizeof(query_flag_reply)); + if (ret < 0) { + ERR("Failed to receive relay daemon get configuration query flag data"); + ret_code = LTTNG_ERR_RELAYD_CONNECT_FAIL; + goto end; + } + + query_flag_reply.query_flag = be64toh(query_flag_reply.query_flag); + LTTNG_ASSERT(query_flag_reply.query_flag & + LTTCOMM_RELAYD_CONFIGURATION_QUERY_FLAG_SUPPORTED_TRACE_FORMAT); + + query_flag_reply.payload_len = be64toh(query_flag_reply.payload_len); + LTTNG_ASSERT(query_flag_reply.payload_len == sizeof(uint64_t)); + + lttng_dynamic_buffer_set_size(&buffer, query_flag_reply.payload_len); + + ret = recv_reply(sock, buffer.data, query_flag_reply.payload_len); + if (ret < 0) { + ret_code = LTTNG_ERR_RELAYD_CONNECT_FAIL; + ERR("Failed to receive configuration dynamic payload for flag TODO"); + goto end; + } + + *trace_format_query_results = be64toh(*(uint64_t *) buffer.data); + } + + ret_code = LTTNG_OK; + end: - return ret; + lttng_dynamic_buffer_reset(&buffer); + return ret_code; } diff --git a/src/common/relayd/relayd.hpp b/src/common/relayd/relayd.hpp index 05d1ec684..c0dcf5aca 100644 --- a/src/common/relayd/relayd.hpp +++ b/src/common/relayd/relayd.hpp @@ -68,13 +68,13 @@ int relayd_rotate_streams(struct lttcomm_relayd_sock *sock, const struct relayd_stream_rotation_position *positions); int relayd_create_trace_chunk(struct lttcomm_relayd_sock *sock, struct lttng_trace_chunk *chunk); -int relayd_close_trace_chunk(struct lttcomm_relayd_sock *sock, - struct lttng_trace_chunk *chunk, - 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, +int relayd_close_trace_chunk( + struct lttcomm_relayd_sock *sock, struct lttng_trace_chunk *chunk, char *path); +int relayd_trace_chunk_exists( + struct lttcomm_relayd_sock *sock, uint64_t chunk_id, bool *chunk_exists); +enum lttng_error_code relayd_get_configuration(struct lttcomm_relayd_sock *sock, uint64_t query_flags, - uint64_t *result_flags); + uint64_t& result_flags, + uint64_t *supported_trace_format); #endif /* _RELAYD_H */ diff --git a/src/common/sessiond-comm/relayd.hpp b/src/common/sessiond-comm/relayd.hpp index 0f5adaa94..5f7bd3dc4 100644 --- a/src/common/sessiond-comm/relayd.hpp +++ b/src/common/sessiond-comm/relayd.hpp @@ -341,10 +341,29 @@ enum lttcomm_relayd_configuration_flag { LTTCOMM_RELAYD_CONFIGURATION_FLAG_CLEAR_ALLOWED = (1 << 0), }; +enum lttcomm_relayd_configuration_query_flag { + LTTCOMM_RELAYD_CONFIGURATION_QUERY_FLAG_SUPPORTED_TRACE_FORMAT = (1 << 0), + LTTCOMM_RELAYD_CONFIGURATION_QUERY_FLAG_MASK = 0x01 +}; + +enum lttcomm_relayd_configuration_trace_format_flag { + LTTCOMM_RELAYD_CONFIGURATION_TRACE_FORMAT_SUPPORTED_CTF1 = (1 << 0), +}; + struct lttcomm_relayd_get_configuration { uint64_t query_flags; } LTTNG_PACKED; +struct lttcomm_relayd_get_configuration_specialized_query_reply { + uint64_t query_flag; // Single flag, enum lttcomm_relayd_configuration_trace_format_flag + uint64_t payload_len; + /* + * Payload dependant on type + * LTTCOMM_RELAYD_CONFIGURATION_QUERY_FLAG_SUPPORTED_TRACE_FORMAT: + * uint64_t, bitfield of lttcomm_relayd_configuration_trace_format_flag. + */ + char payload[]; +} LTTNG_PACKED; /* * Used to return a relay daemon's configuration in reply to the * RELAYD_GET_CONFIGURATION command. @@ -353,7 +372,11 @@ 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. */ + /* + * Optional variable-length payload. + * When N query flags are used, it is expected that N dynamic sized + * lttcomm_relayd_get_configuration_specialized_query_reply be present. + */ char payload[]; } LTTNG_PACKED;