relayd: Implement get_configuration relayd protocol command
authorMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Wed, 11 Dec 2019 18:24:49 +0000 (13:24 -0500)
committerJérémie Galarneau <jeremie.galarneau@efficios.com>
Thu, 19 Dec 2019 22:36:45 +0000 (17:36 -0500)
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 <mathieu.desnoyers@efficios.com>
Change-Id: I33a03d09871f1c0c248d5514451c533ffd773979
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
src/bin/lttng-relayd/main.c
src/common/relayd/relayd.c
src/common/relayd/relayd.h
src/common/sessiond-comm/relayd.h
src/common/sessiond-comm/sessiond-comm.h

index 6beb21692c4b2fe7077b751456e7f272c9c5c366..d874a9c50bdcabfbbc5bf0bc49c584e1eb635665 100644 (file)
@@ -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);
index 228b35cb26b4414854a6218bded70003905df28b..54fe6734516589bd6c3fe432ae8aaba4eea7846b 100644 (file)
@@ -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;
+}
index 2f0c937f68d148c5adc27bcec6c18bbefc59f85b..c2ee95aed6d57fe24d943f2e75ec75402128848c 100644 (file)
@@ -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 */
index de0c7f254303bc3a4c65e3bf19ef5913916f3731..492f3efae5ee722cc17bb3fb649028c1af06e136 100644 (file)
@@ -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 */
index cf50f0e44515573c81ce2d13b58ffd3711b6f579..8b1757438de448096337b7ae820513e59ae23891 100644 (file)
@@ -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. */
 };
This page took 0.043167 seconds and 5 git commands to generate.