relayd: Extend relayd get configuration command to check for trace format support
authorJonathan Rajotte <jonathan.rajotte-julien@efficios.com>
Fri, 6 May 2022 19:01:30 +0000 (15:01 -0400)
committerJonathan Rajotte <jonathan.rajotte-julien@efficios.com>
Fri, 19 Aug 2022 16:02:37 +0000 (12:02 -0400)
Signed-off-by: Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
Change-Id: Id06c8a5de4eb0a5b2919390b3b019d17d0365544

include/lttng/lttng-error.h
include/lttng/trace-format-descriptor-internal.hpp
src/bin/lttng-relayd/main.cpp
src/bin/lttng-sessiond/cmd.cpp
src/common/error.cpp
src/common/relayd/relayd.cpp
src/common/relayd/relayd.hpp
src/common/sessiond-comm/relayd.hpp

index 1438e0dc25178a7ad5270a9ef5106d8a596af12b..6a0f350ae775d8e03e7a6ae3e0496b6ac7c88dc9 100644 (file)
@@ -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,
index 527965670110cc20f291d5223ec6f1800bc340d4..eb27c3e652de6a28055ab17328bef10af3dbd8ce 100644 (file)
@@ -13,6 +13,7 @@
 #include <common/dynamic-array.hpp>
 #include <common/macros.hpp>
 #include <common/optional.hpp>
+#include <common/sessiond-comm/relayd.hpp>
 #include <cstdint>
 #include <functional>
 #include <lttng/lttng.h>
index 318af66f787526f049faef36f9c4cf1a78425c71..e2d947cc693aa96920c2f0f0cbb6d39ffbdea6ce 100644 (file)
@@ -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;
 }
 
index be1ab52ab2b315df51cd7ff3dff297acca773096..f975f31e227981589c32d13dd725bdf115d6e3df 100644 (file)
@@ -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<enum lttng_trace_format_descriptor_type,
+                       enum lttcomm_relayd_configuration_trace_format_flag>
+                       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) {
index 40c1faf0b9a6379866d30eceaf2e14ab534706ab..2760b4ff20238dc5c1dfcbda5ef7bf879d030c77 100644 (file)
@@ -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();
        }
index a422d8b5a57e681769f1933048be984e96a25644..9f444d6e982cbfe0c95d3fd5274e7d276cb5e63c 100644 (file)
 #include <sys/stat.h>
 #include <inttypes.h>
 
+#include <bitset>
 #include <common/common.hpp>
-#include <common/defaults.hpp>
 #include <common/compat/endian.hpp>
 #include <common/compat/string.hpp>
-#include <common/sessiond-comm/relayd.hpp>
+#include <common/defaults.hpp>
 #include <common/index/ctf-index.hpp>
-#include <common/trace-chunk.hpp>
+#include <common/sessiond-comm/relayd.hpp>
 #include <common/string-utils/format.hpp>
+#include <common/trace-chunk.hpp>
 
 #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<char>(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<enum lttng_error_code>(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;
 }
index 05d1ec684630a3bb95b6286424aeba78ac646687..c0dcf5aca71d5d84c73b3effaeff3060feda6f33 100644 (file)
@@ -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 */
index 0f5adaa94bba32443286bcefe1d99c9f445e96a8..5f7bd3dc42aca6705427cb1b209ca1ccdc034298 100644 (file)
@@ -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;
 
This page took 0.040202 seconds and 5 git commands to generate.