From: Matt Benjamin Date: Tue, 18 Feb 2025 01:26:33 +0000 (-0500) Subject: rgw_cksum: prototype support for CRC64NVME X-Git-Tag: v20.3.0~225^2~2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=ff4a4153cb70c584a50faea34d9f49f35e2aa7e1;p=ceph.git rgw_cksum: prototype support for CRC64NVME 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 --- diff --git a/src/crypto/isa-l/CMakeLists.txt b/src/crypto/isa-l/CMakeLists.txt index af8f7e185c86..b7b2e3006c78 100644 --- a/src/crypto/isa-l/CMakeLists.txt +++ b/src/crypto/isa-l/CMakeLists.txt @@ -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() diff --git a/src/rgw/CMakeLists.txt b/src/rgw/CMakeLists.txt index 41e473e23f03..a4f154b61904 100644 --- a/src/rgw/CMakeLists.txt +++ b/src/rgw/CMakeLists.txt @@ -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 diff --git a/src/rgw/rgw_cksum.h b/src/rgw/rgw_cksum.h index 955b553f27de..900a1046d19a 100644 --- a/src/rgw/rgw_cksum.h +++ b/src/rgw/rgw_cksum.h @@ -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 checksums = + static constexpr std::array 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; diff --git a/src/rgw/rgw_cksum_digest.h b/src/rgw/rgw_cksum_digest.h index ba7e3bd58c6f..33f9a629519a 100644 --- a/src/rgw/rgw_cksum_digest.h +++ b/src/rgw/rgw_cksum_digest.h @@ -63,6 +63,7 @@ namespace rgw { namespace cksum { typedef TDigest SHA1; typedef TDigest SHA256; typedef TDigest SHA512; + typedef TDigest Crc64Nvme; typedef boost::variant DigestVariant; + SHA512, + Crc64Nvme> DigestVariant; struct get_digest_ptr : public boost::static_visitor { @@ -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; diff --git a/src/rgw/rgw_cksum_pipe.cc b/src/rgw/rgw_cksum_pipe.cc index 32b93755f5d8..da60c2071f99 100644 --- a/src/rgw/rgw_cksum_pipe.cc +++ b/src/rgw/rgw_cksum_pipe.cc @@ -49,7 +49,8 @@ namespace rgw::putobj { std::make_unique( next, cksum_type, std::move(algo_header)); } else { - return std::unique_ptr(); + /* 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( next, override_type, std::move(algo_header)); } + /* no checksum requested */ return std::unique_ptr(); } diff --git a/src/rgw/rgw_crc_digest.h b/src/rgw/rgw_crc_digest.h index 8e97df56b485..15e488152cd0 100644 --- a/src/rgw/rgw_crc_digest.h +++ b/src/rgw/rgw_crc_digest.h @@ -22,6 +22,7 @@ #include #include "include/crc32c.h" #include +#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 */ diff --git a/src/rgw/spdk/crc64.c b/src/rgw/spdk/crc64.c index b1a37af35be4..305d8392508b 100644 --- a/src/rgw/spdk/crc64.c +++ b/src/rgw/spdk/crc64.c @@ -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" diff --git a/src/rgw/spdk/crc64.h b/src/rgw/spdk/crc64.h index 5a3d31915b37..a108acf1639d 100644 --- a/src/rgw/spdk/crc64.h +++ b/src/rgw/spdk/crc64.h @@ -11,8 +11,13 @@ #ifndef SPDK_CRC64_H #define SPDK_CRC64_H +#if 0 #include "spdk/stdinc.h" #include "spdk/config.h" +#else +#include +#include +#endif #ifdef __cplusplus extern "C" { diff --git a/src/rgw/spdk/crc_internal.h b/src/rgw/spdk/crc_internal.h index b432d0d7bb47..81836dce0b9f 100644 --- a/src/rgw/spdk/crc_internal.h +++ b/src/rgw/spdk/crc_internal.h @@ -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 diff --git a/src/test/rgw/test_rgw_cksum.cc b/src/test/rgw/test_rgw_cksum.cc index 3572f5994fa8..4167d8779e97 100644 --- a/src/test/rgw/test_rgw_cksum.cc +++ b/src/test/rgw/test_rgw_cksum.cc @@ -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; }