]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
msg/async: transmit V2 messages with new preable format.
authorRadoslaw Zarzynski <rzarzyns@redhat.com>
Tue, 12 Feb 2019 15:30:30 +0000 (16:30 +0100)
committerRadoslaw Zarzynski <rzarzyns@redhat.com>
Thu, 21 Feb 2019 20:58:34 +0000 (21:58 +0100)
Signed-off-by: Radoslaw Zarzynski <rzarzyns@redhat.com>
src/msg/async/ProtocolV2.cc
src/msg/async/ProtocolV2.h

index c5657128826caeb77185466db31cda41a6b6216f..fdcdae74b6c46b546f081f51a366997d6bd1daaf 100644 (file)
@@ -1,6 +1,8 @@
 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
 // vim: ts=8 sw=2 smarttab
 
+#include <type_traits>
+
 #include "ProtocolV2.h"
 #include "AsyncMessenger.h"
 
@@ -104,32 +106,92 @@ static void alloc_aligned_buffer(bufferlist &data, unsigned len, unsigned off) {
  * Protocol V2 Frame Structures
  **/
 
-static constexpr uint32_t FRAME_PREAMBLE_SIZE = 4 * sizeof(__le32);
+static constexpr uint8_t CRYPTO_BLOCK_SIZE { 16 };
+
+struct segment_t {
+  __le32 length;
+  __le16 alignment;
+} __attribute__((packed));
+
+struct preamble_main_t {
+  static constexpr std::size_t MAX_NUM_SEGMENTS = 2;
+
+  __le16 crc;
+  __u8 tag;
+  __u8 num_segments;
+  std::array<segment_t, MAX_NUM_SEGMENTS> segments;
+} __attribute__((packed));
+static_assert(sizeof(preamble_main_t) == CRYPTO_BLOCK_SIZE);
+static_assert(std::is_standard_layout<preamble_main_t>::value);
+
+struct preamble_extra_t {
+  static constexpr std::size_t MAX_NUM_SEGMENTS = 2;
+  std::array<segment_t, MAX_NUM_SEGMENTS> segments;
+  std::array<__u8, 4> always_padding;
+} __attribute__((packed));
+static_assert(sizeof(preamble_extra_t) == CRYPTO_BLOCK_SIZE);
+static_assert(std::is_standard_layout<preamble_extra_t>::value);
+
+
+static constexpr uint32_t FRAME_PREAMBLE_SIZE = CRYPTO_BLOCK_SIZE;
+
 template <class T>
 struct Frame {
 protected:
   ceph::bufferlist payload;
   ceph::bufferlist::contiguous_filler preamble_filler;
 
-  void fill_preamble(const uint32_t frame_size) {
-    __le32 rest_len = frame_size - FRAME_PREAMBLE_SIZE;
-    preamble_filler.copy_in(sizeof(rest_len),
-                           reinterpret_cast<const char*>(&rest_len));
-
-    __le32 tag = static_cast<uint32_t>(T::tag);
-    preamble_filler.copy_in(sizeof(tag),
-                           reinterpret_cast<const char*>(&tag));
-    uint32_t db = 0xbaadf00d;
-    preamble_filler.copy_in(sizeof(tag),
-                           reinterpret_cast<const char*>(&db));
-    ceph_assert(tag != 0);
+  void fill_preamble(
+    const std::initializer_list<segment_t> main_segments,
+    const std::initializer_list<segment_t> extra_segments)
+  {
+    ceph_assert(
+      std::size(main_segments) <= preamble_main_t::MAX_NUM_SEGMENTS);
+    ceph_assert(
+      std::size(extra_segments) <= preamble_extra_t::MAX_NUM_SEGMENTS);
+
+    // Craft the main preamble. It's always present regardless of the number
+    // of segments message is composed from. This doesn't apply to extra one
+    // as it's optional -- if there is up to 2 segments, we'll never transmit
+    // preamble_extra_t;
+    preamble_main_t main_preamble;
+    // TODO: we might fill/pad with pseudo-random data.
+    ::memset(&main_preamble, 0, sizeof(main_preamble));
+
+    main_preamble.num_segments = \
+      std::size(main_segments) + std::size(extra_segments);
+    main_preamble.tag = static_cast<__u8>(T::tag);
+    std::copy(std::cbegin(main_segments), std::cend(main_segments),
+             std::begin(main_preamble.segments));
+    main_preamble.crc = 0;
+
+    ceph_assert(main_preamble.tag != 0);
+
+    if (std::empty(extra_segments)) {
+      preamble_filler.copy_in(sizeof(main_preamble),
+                             reinterpret_cast<const char*>(&main_preamble));
+    } else {
+      preamble_extra_t extra_preamble;
+      // TODO: we might fill/pad with pseudo-random data.
+      ::memset(&extra_preamble, 0, sizeof(extra_preamble));
+
+      std::copy(std::cbegin(extra_segments), std::cend(extra_segments),
+               std::begin(extra_preamble.segments));
+      //main_preamble.crc = \
+      //  ceph::crc16(main_preamble.crc, &extra_preamble, sizeof(extra_preamble);
+
+      preamble_filler.copy_in(sizeof(main_preamble),
+                             reinterpret_cast<const char*>(&main_preamble));
+      preamble_filler.copy_in(sizeof(extra_preamble),
+                             reinterpret_cast<const char*>(&extra_preamble));
+    }
   }
 
 public:
   Frame() : preamble_filler(payload.append_hole(FRAME_PREAMBLE_SIZE)) {}
 
   ceph::bufferlist &get_buffer() {
-    fill_preamble(payload.length());
+    fill_preamble({ segment_t{ payload.length(), 1} }, {});
     return payload;
   }
 
@@ -300,7 +362,7 @@ struct SignedEncryptedFrame : public PayloadFrame<T, Args...> {
     auto exp_size = this->payload.length() + 16;
     // FIXME: plainsize -> ciphersize; for AES-GCM they are equall apart
     // from auth tag size
-    this->fill_preamble(this->payload.length() + 16);
+    //this->fill_preamble(this->payload.length() + 16);
 
     protocol.session_stream_handlers.tx->authenticated_encrypt_update(
       std::move(this->payload));
@@ -465,7 +527,8 @@ struct MessageHeaderFrame
                     const uint32_t data_len)
       : PayloadFrame<MessageHeaderFrame, ceph_msg_header2>(msghdr)
   {
-    fill_preamble(this->payload.length() + front_len + middle_len + data_len + 16);
+    // FIXME: plainsize -> ciphersize; for AES-GCM they are equall apart from auth tag size
+    //fill_preamble(this->payload.length() + front_len + middle_len + data_len + 16);
   }
 
   MessageHeaderFrame(ceph::bufferlist&& text)
index 8589015d6124842b435a48da0d2f4efd63fd3ed9..bec10174f89030ea077f3f238f9c6a640e41e3fd 100644 (file)
@@ -47,7 +47,7 @@ private:
   }
 
 public:
-  enum class Tag : uint32_t {
+  enum class Tag : __u8 {
     HELLO = 1,
     AUTH_REQUEST,
     AUTH_BAD_METHOD,