]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
rgw_cksum: prototype support for CRC64NVME
authorMatt Benjamin <mbenjamin@redhat.com>
Tue, 18 Feb 2025 01:26:33 +0000 (20:26 -0500)
committerMatt Benjamin <mbenjamin@redhat.com>
Wed, 26 Mar 2025 19:30:11 +0000 (15:30 -0400)
Support uses conditionally compiled implementations from spdk
and ISA-L.

Validated against SPDK test vectors and one example generated and
passed via awscliv2 (AWS SDK) version 2.24.5.

Restored the ability of unittest_rgw_cksum to create a binary input
file for external checksum testing, but only when requested via
cmdline option.

Fixes: https://tracker.ceph.com/issues/70040
Signed-off-by: Matt Benjamin <mbenjamin@redhat.com>
src/crypto/isa-l/CMakeLists.txt
src/rgw/CMakeLists.txt
src/rgw/rgw_cksum.h
src/rgw/rgw_cksum_digest.h
src/rgw/rgw_cksum_pipe.cc
src/rgw/rgw_crc_digest.h
src/rgw/spdk/crc64.c
src/rgw/spdk/crc64.h
src/rgw/spdk/crc_internal.h
src/test/rgw/test_rgw_cksum.cc

index af8f7e185c86ca135c6e4cc0b85ac0d49f03441e..b7b2e3006c787961fdb45d822d46466d749c1273 100644 (file)
@@ -1,4 +1,6 @@
 # build isa-l_crypto from its makefile and expose as target ISAL::Crypto
+set(CEPH_HAVE_ISAL, TRUE)
+
 include(BuildISALCrypto)
 build_isal_crypto()
 
index 41e473e23f038f4d98075cb5da55075071304807..a4f154b619046c90ef708f774178b8d284f779b8 100644 (file)
@@ -19,6 +19,11 @@ if(WITH_RADOSGW_ARROW_FLIGHT)
   message("-- arrow flight is installed")
 endif(WITH_RADOSGW_ARROW_FLIGHT)
 
+if(CEPH_HAVE_ISAL)
+  message("-- building RGW with ISA-L support")
+  add_definitions(-DSPDK_CONFIG_ISAL)
+endif()
+
 function(gperf_generate input output)
   add_custom_command(
     OUTPUT ${output}
@@ -51,6 +56,7 @@ set(librgw_common_srcs
   services/svc_user_rados.cc
   services/svc_zone.cc
   services/svc_zone_utils.cc
+  spdk/crc64.c
   rgw_account.cc
   rgw_acl.cc
   rgw_acl_s3.cc
index 955b553f27de95dbc151943bfbfb46d3185a5b92..900a1046d19af0063f0dd4bc73ddf8dfe73e7b25 100644 (file)
@@ -45,6 +45,7 @@ namespace rgw { namespace cksum {
       sha256,
       sha512,
       blake3,
+      crc64nvme,
   };
 
   static constexpr uint16_t FLAG_NONE =      0x0000;
@@ -80,7 +81,7 @@ namespace rgw { namespace cksum {
 
   class Cksum {
   public:
-    static constexpr std::array<Desc, 8> checksums =
+    static constexpr std::array<Desc, 9> checksums =
     {
       Desc(Type::none, "none", 0, FLAG_NONE),
       Desc(Type::crc32, "crc32", 4, FLAG_AWS_CKSUM),
@@ -90,6 +91,7 @@ namespace rgw { namespace cksum {
       Desc(Type::sha256, "sha256", 32, FLAG_AWS_CKSUM),
       Desc(Type::sha512, "sha512", 64, FLAG_NONE),
       Desc(Type::blake3, "blake3", 32, FLAG_NONE),
+      Desc(Type::crc64nvme, "crc64nvme", 8, FLAG_AWS_CKSUM),
     };
 
     static constexpr uint16_t max_digest_size = 64;
index ba7e3bd58c6f82a6a17eab9b81a77e4b07c64f0a..33f9a629519ad491593c9861d6cd91c4c890a452 100644 (file)
@@ -63,6 +63,7 @@ namespace rgw { namespace cksum {
   typedef TDigest<ceph::crypto::SHA1> SHA1;
   typedef TDigest<ceph::crypto::SHA256> SHA256;
   typedef TDigest<ceph::crypto::SHA512> SHA512;
+  typedef TDigest<rgw::digest::Crc64Nvme> Crc64Nvme;
 
   typedef boost::variant<boost::blank,
                         Blake3,
@@ -71,7 +72,8 @@ namespace rgw { namespace cksum {
                         XXH3,
                         SHA1,
                         SHA256,
-                        SHA512> DigestVariant;
+                        SHA512,
+                        Crc64Nvme> DigestVariant;
 
   struct get_digest_ptr : public boost::static_visitor<Digest*>
   {
@@ -84,6 +86,7 @@ namespace rgw { namespace cksum {
     Digest* operator()(SHA1& digest) const { return &digest; }
     Digest* operator()(SHA256& digest) const { return &digest; }
     Digest* operator()(SHA512& digest) const { return &digest; }
+    Digest* operator()(Crc64Nvme& digest) const { return &digest; }
   };
 
   static inline Digest* get_digest(DigestVariant& ev)
@@ -106,6 +109,9 @@ namespace rgw { namespace cksum {
     case Type::crc32c:
       return Crc32c();
       break;
+    case Type::crc64nvme:
+      return Crc64Nvme();
+      break;
     case Type::xxh3:
       return XXH3();
       break;
index 32b93755f5d8fdb8ec86ca6322b7ad0bb04440d1..da60c2071f992afd8dbe2dbbb02354bb8ee20b09 100644 (file)
@@ -49,7 +49,8 @@ namespace rgw::putobj {
            std::make_unique<RGWPutObj_Cksum>(
                               next, cksum_type, std::move(algo_header));
        } else {
-         return std::unique_ptr<RGWPutObj_Cksum>();
+        /* unknown checksum type requested */
+        throw rgw::io::Exception(EINVAL, std::system_category());
        }
       }
       /* malformed checksum algorithm header(s) */
@@ -63,6 +64,7 @@ namespace rgw::putobj {
        std::make_unique<RGWPutObj_Cksum>(
                           next, override_type, std::move(algo_header));
     }
+    /* no checksum requested */
     return std::unique_ptr<RGWPutObj_Cksum>();
   }
 
index 8e97df56b485a804087af08d48da3580cd71097a..15e488152cd0278b4833ead29de3a9e5fcb1c40b 100644 (file)
@@ -22,6 +22,7 @@
 #include <stdio.h>
 #include "include/crc32c.h"
 #include <boost/crc.hpp>
+#include "spdk/crc64.h"
 
 namespace rgw { namespace digest {
 
@@ -90,4 +91,29 @@ namespace rgw { namespace digest {
       memcpy((char*) digest, &crc, sizeof(crc));
     }
   }; /* Crc32c */
+
+  class Crc64Nvme {
+  private:
+    uint64_t crc;
+
+  public:
+    static constexpr uint16_t digest_size = 8;
+    static constexpr uint64_t initial_value = 0x0;
+
+    Crc64Nvme() { Restart(); }
+
+    void Restart() { crc = initial_value; }
+
+    void Update(const unsigned char *data, uint64_t len) {
+      crc = spdk_crc64_nvme(data, len, crc);
+    }
+
+    void Final(unsigned char* digest) {
+      if constexpr (std::endian::native != std::endian::big) {
+       crc = rgw::digest::byteswap(crc);
+      }
+      memcpy((char*) digest, &crc, sizeof(crc));
+    }
+  }; /* Crc64Nvme */
+
 }} /* namespace */
index b1a37af35be4e9ffe5a4f1ac8bb04be55df42808..305d8392508bbb3a2e1612162772239af3295879 100644 (file)
@@ -4,7 +4,7 @@
  */
 
 #include "crc_internal.h"
-#include "spdk/crc64.h"
+#include "crc64.h"
 
 #ifdef SPDK_CONFIG_ISAL
 #include "isa-l/include/crc64.h"
index 5a3d31915b37787630eebdb2c7a28f6c1a95ddd3..a108acf1639d30f05a8673d8f2717b4cc3b451ff 100644 (file)
 #ifndef SPDK_CRC64_H
 #define SPDK_CRC64_H
 
+#if 0
 #include "spdk/stdinc.h"
 #include "spdk/config.h"
+#else
+#include <stdint.h>
+#include <sys/types.h>
+#endif
 
 #ifdef __cplusplus
 extern "C" {
index b432d0d7bb4719dea3a92ff42d95d794ccd8fa05..81836dce0b9f4eb6b9fe63e787eaf4f5f7dbd8b9 100644 (file)
@@ -6,7 +6,9 @@
 #ifndef SPDK_CRC_INTERNAL_H
 #define SPDK_CRC_INTERNAL_H
 
+#if 0
 #include "spdk/config.h"
+#endif
 
 #ifdef SPDK_CONFIG_ISAL
 #define SPDK_HAVE_ISAL
index 3572f5994fa899139e04101003719241d8afa146..4167d8779e9737ccd1bc261e5353673e59636916 100644 (file)
@@ -36,6 +36,7 @@ namespace {
   using namespace rgw::cksum;
 
   bool verbose = false;
+  bool gen_test_data = false;
 
   cksum::Type t1 = cksum::Type::blake3;
   cksum::Type t2 = cksum::Type::sha1;
@@ -51,6 +52,24 @@ namespace {
   std::string dolor =
     R"(Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.)";
 
+TEST(RGWCksum, Output)
+{
+  if (gen_test_data) {
+    auto o_mode = std::ios::out|std::ios::trunc;
+    std::ofstream of;
+
+    std::cout << "writing lorem text to /tmp/lorem " << std::endl;
+    of.open("/tmp/lorem", o_mode);
+    of << lorem;
+    of.close();
+
+    std::cout << "writing dolor text to /tmp/dolor " << std::endl;
+    of.open("/tmp/dolor", o_mode);
+    of << dolor;
+    of.close();
+  }
+}
 TEST(RGWCksum, Ctor)
 {
   cksum::Cksum ck1;
@@ -328,10 +347,71 @@ TEST(RGWCksum, DigestBL)
   } /* for t1, ... */
 }
 
+TEST(RGWCksum, CRC64NVME1)
+{
+  /* from SPDK crc64_ut.c */
+  unsigned int buf_size = 4096;
+  char buf[buf_size];
+  uint64_t crc;
+  unsigned int i, j;
+
+  /* All the expected CRC values are compliant with
+   * the NVM Command Set Specification 1.0c */
+
+  /* Input buffer = 0s */
+  memset(buf, 0, buf_size);
+  crc = spdk_crc64_nvme(buf, buf_size, 0);
+  ASSERT_TRUE(crc == 0x6482D367EB22B64E);
+
+  /* Input buffer = 1s */
+  memset(buf, 0xFF, buf_size);
+  crc = spdk_crc64_nvme(buf, buf_size, 0);
+  ASSERT_TRUE(crc == 0xC0DDBA7302ECA3AC);
+
+  /* Input buffer = 0x00, 0x01, 0x02, ... */
+  memset(buf, 0, buf_size);
+  j = 0;
+  for (i = 0; i < buf_size; i++) {
+    buf[i] = (char)j;
+    if (j == 0xFF) {
+      j = 0;
+    } else {
+      j++;
+    }
+  }
+  crc = spdk_crc64_nvme(buf, buf_size, 0);
+  ASSERT_TRUE(crc == 0x3E729F5F6750449C);
+
+  /* Input buffer = 0xFF, 0xFE, 0xFD, ... */
+  memset(buf, 0, buf_size);
+  j = 0xFF;
+  for (i = 0; i < buf_size ; i++) {
+               buf[i] = (char)j;
+               if (j == 0) {
+                 j = 0xFF;
+               } else {
+                 j--;
+               }
+  }
+  crc = spdk_crc64_nvme(buf, buf_size, 0);
+  ASSERT_TRUE(crc == 0x9A2DF64B8E9E517E);
+}
 
+TEST(RGWCksum, CRC64NVME2)
+{
+  auto t = cksum::Type::crc64nvme;
+  DigestVariant dv = rgw::cksum::digest_factory(t);
+  Digest *digest = get_digest(dv);
+  ASSERT_NE(digest, nullptr);
+
+  digest->Update((const unsigned char *)dolor.c_str(), dolor.length());
+
+  auto cksum = rgw::cksum::finalize_digest(digest, t);
 
+  /* the armored value produced by awscliv2 2.24.5 */
+  ASSERT_EQ(cksum.to_armor(), "wiBA+PSv41M=");
+}
 
-  //foop
 TEST(RGWCksum, CtorUnarmor)
 {
   auto t = cksum::Type::sha256;
@@ -357,11 +437,13 @@ int main(int argc, char *argv[])
   auto args = argv_to_vec(argc, argv);
   env_to_vec(args);
 
-  std::string val;
   for (auto arg_iter = args.begin(); arg_iter != args.end();) {
      if (ceph_argparse_flag(args, arg_iter, "--verbose",
                            (char*) nullptr)) {
        verbose = true;
+     } else if (ceph_argparse_flag(args, arg_iter, "--gen_test_data",
+                                  (char*) nullptr)) {
+       gen_test_data = true;
      } else {
        ++arg_iter;
      }