Skip to content

Commit ff4a415

Browse files
committed
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 <[email protected]>
1 parent 07afdc1 commit ff4a415

File tree

10 files changed

+139
-6
lines changed

10 files changed

+139
-6
lines changed

src/crypto/isa-l/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
# build isa-l_crypto from its makefile and expose as target ISAL::Crypto
2+
set(CEPH_HAVE_ISAL, TRUE)
3+
24
include(BuildISALCrypto)
35
build_isal_crypto()
46

src/rgw/CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@ if(WITH_RADOSGW_ARROW_FLIGHT)
1919
message("-- arrow flight is installed")
2020
endif(WITH_RADOSGW_ARROW_FLIGHT)
2121

22+
if(CEPH_HAVE_ISAL)
23+
message("-- building RGW with ISA-L support")
24+
add_definitions(-DSPDK_CONFIG_ISAL)
25+
endif()
26+
2227
function(gperf_generate input output)
2328
add_custom_command(
2429
OUTPUT ${output}
@@ -51,6 +56,7 @@ set(librgw_common_srcs
5156
services/svc_user_rados.cc
5257
services/svc_zone.cc
5358
services/svc_zone_utils.cc
59+
spdk/crc64.c
5460
rgw_account.cc
5561
rgw_acl.cc
5662
rgw_acl_s3.cc

src/rgw/rgw_cksum.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ namespace rgw { namespace cksum {
4545
sha256,
4646
sha512,
4747
blake3,
48+
crc64nvme,
4849
};
4950

5051
static constexpr uint16_t FLAG_NONE = 0x0000;
@@ -80,7 +81,7 @@ namespace rgw { namespace cksum {
8081

8182
class Cksum {
8283
public:
83-
static constexpr std::array<Desc, 8> checksums =
84+
static constexpr std::array<Desc, 9> checksums =
8485
{
8586
Desc(Type::none, "none", 0, FLAG_NONE),
8687
Desc(Type::crc32, "crc32", 4, FLAG_AWS_CKSUM),
@@ -90,6 +91,7 @@ namespace rgw { namespace cksum {
9091
Desc(Type::sha256, "sha256", 32, FLAG_AWS_CKSUM),
9192
Desc(Type::sha512, "sha512", 64, FLAG_NONE),
9293
Desc(Type::blake3, "blake3", 32, FLAG_NONE),
94+
Desc(Type::crc64nvme, "crc64nvme", 8, FLAG_AWS_CKSUM),
9395
};
9496

9597
static constexpr uint16_t max_digest_size = 64;

src/rgw/rgw_cksum_digest.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ namespace rgw { namespace cksum {
6363
typedef TDigest<ceph::crypto::SHA1> SHA1;
6464
typedef TDigest<ceph::crypto::SHA256> SHA256;
6565
typedef TDigest<ceph::crypto::SHA512> SHA512;
66+
typedef TDigest<rgw::digest::Crc64Nvme> Crc64Nvme;
6667

6768
typedef boost::variant<boost::blank,
6869
Blake3,
@@ -71,7 +72,8 @@ namespace rgw { namespace cksum {
7172
XXH3,
7273
SHA1,
7374
SHA256,
74-
SHA512> DigestVariant;
75+
SHA512,
76+
Crc64Nvme> DigestVariant;
7577

7678
struct get_digest_ptr : public boost::static_visitor<Digest*>
7779
{
@@ -84,6 +86,7 @@ namespace rgw { namespace cksum {
8486
Digest* operator()(SHA1& digest) const { return &digest; }
8587
Digest* operator()(SHA256& digest) const { return &digest; }
8688
Digest* operator()(SHA512& digest) const { return &digest; }
89+
Digest* operator()(Crc64Nvme& digest) const { return &digest; }
8790
};
8891

8992
static inline Digest* get_digest(DigestVariant& ev)
@@ -106,6 +109,9 @@ namespace rgw { namespace cksum {
106109
case Type::crc32c:
107110
return Crc32c();
108111
break;
112+
case Type::crc64nvme:
113+
return Crc64Nvme();
114+
break;
109115
case Type::xxh3:
110116
return XXH3();
111117
break;

src/rgw/rgw_cksum_pipe.cc

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ namespace rgw::putobj {
4949
std::make_unique<RGWPutObj_Cksum>(
5050
next, cksum_type, std::move(algo_header));
5151
} else {
52-
return std::unique_ptr<RGWPutObj_Cksum>();
52+
/* unknown checksum type requested */
53+
throw rgw::io::Exception(EINVAL, std::system_category());
5354
}
5455
}
5556
/* malformed checksum algorithm header(s) */
@@ -63,6 +64,7 @@ namespace rgw::putobj {
6364
std::make_unique<RGWPutObj_Cksum>(
6465
next, override_type, std::move(algo_header));
6566
}
67+
/* no checksum requested */
6668
return std::unique_ptr<RGWPutObj_Cksum>();
6769
}
6870

src/rgw/rgw_crc_digest.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <stdio.h>
2323
#include "include/crc32c.h"
2424
#include <boost/crc.hpp>
25+
#include "spdk/crc64.h"
2526

2627
namespace rgw { namespace digest {
2728

@@ -90,4 +91,29 @@ namespace rgw { namespace digest {
9091
memcpy((char*) digest, &crc, sizeof(crc));
9192
}
9293
}; /* Crc32c */
94+
95+
class Crc64Nvme {
96+
private:
97+
uint64_t crc;
98+
99+
public:
100+
static constexpr uint16_t digest_size = 8;
101+
static constexpr uint64_t initial_value = 0x0;
102+
103+
Crc64Nvme() { Restart(); }
104+
105+
void Restart() { crc = initial_value; }
106+
107+
void Update(const unsigned char *data, uint64_t len) {
108+
crc = spdk_crc64_nvme(data, len, crc);
109+
}
110+
111+
void Final(unsigned char* digest) {
112+
if constexpr (std::endian::native != std::endian::big) {
113+
crc = rgw::digest::byteswap(crc);
114+
}
115+
memcpy((char*) digest, &crc, sizeof(crc));
116+
}
117+
}; /* Crc64Nvme */
118+
93119
}} /* namespace */

src/rgw/spdk/crc64.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
*/
55

66
#include "crc_internal.h"
7-
#include "spdk/crc64.h"
7+
#include "crc64.h"
88

99
#ifdef SPDK_CONFIG_ISAL
1010
#include "isa-l/include/crc64.h"

src/rgw/spdk/crc64.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,13 @@
1111
#ifndef SPDK_CRC64_H
1212
#define SPDK_CRC64_H
1313

14+
#if 0
1415
#include "spdk/stdinc.h"
1516
#include "spdk/config.h"
17+
#else
18+
#include <stdint.h>
19+
#include <sys/types.h>
20+
#endif
1621

1722
#ifdef __cplusplus
1823
extern "C" {

src/rgw/spdk/crc_internal.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66
#ifndef SPDK_CRC_INTERNAL_H
77
#define SPDK_CRC_INTERNAL_H
88

9+
#if 0
910
#include "spdk/config.h"
11+
#endif
1012

1113
#ifdef SPDK_CONFIG_ISAL
1214
#define SPDK_HAVE_ISAL

src/test/rgw/test_rgw_cksum.cc

Lines changed: 84 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ namespace {
3636
using namespace rgw::cksum;
3737

3838
bool verbose = false;
39+
bool gen_test_data = false;
3940

4041
cksum::Type t1 = cksum::Type::blake3;
4142
cksum::Type t2 = cksum::Type::sha1;
@@ -51,6 +52,24 @@ namespace {
5152
std::string dolor =
5253
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.)";
5354

55+
TEST(RGWCksum, Output)
56+
{
57+
if (gen_test_data) {
58+
auto o_mode = std::ios::out|std::ios::trunc;
59+
std::ofstream of;
60+
61+
std::cout << "writing lorem text to /tmp/lorem " << std::endl;
62+
of.open("/tmp/lorem", o_mode);
63+
of << lorem;
64+
of.close();
65+
66+
std::cout << "writing dolor text to /tmp/dolor " << std::endl;
67+
of.open("/tmp/dolor", o_mode);
68+
of << dolor;
69+
of.close();
70+
}
71+
}
72+
5473
TEST(RGWCksum, Ctor)
5574
{
5675
cksum::Cksum ck1;
@@ -328,10 +347,71 @@ TEST(RGWCksum, DigestBL)
328347
} /* for t1, ... */
329348
}
330349

350+
TEST(RGWCksum, CRC64NVME1)
351+
{
352+
/* from SPDK crc64_ut.c */
353+
unsigned int buf_size = 4096;
354+
char buf[buf_size];
355+
uint64_t crc;
356+
unsigned int i, j;
357+
358+
/* All the expected CRC values are compliant with
359+
* the NVM Command Set Specification 1.0c */
360+
361+
/* Input buffer = 0s */
362+
memset(buf, 0, buf_size);
363+
crc = spdk_crc64_nvme(buf, buf_size, 0);
364+
ASSERT_TRUE(crc == 0x6482D367EB22B64E);
365+
366+
/* Input buffer = 1s */
367+
memset(buf, 0xFF, buf_size);
368+
crc = spdk_crc64_nvme(buf, buf_size, 0);
369+
ASSERT_TRUE(crc == 0xC0DDBA7302ECA3AC);
370+
371+
/* Input buffer = 0x00, 0x01, 0x02, ... */
372+
memset(buf, 0, buf_size);
373+
j = 0;
374+
for (i = 0; i < buf_size; i++) {
375+
buf[i] = (char)j;
376+
if (j == 0xFF) {
377+
j = 0;
378+
} else {
379+
j++;
380+
}
381+
}
382+
crc = spdk_crc64_nvme(buf, buf_size, 0);
383+
ASSERT_TRUE(crc == 0x3E729F5F6750449C);
384+
385+
/* Input buffer = 0xFF, 0xFE, 0xFD, ... */
386+
memset(buf, 0, buf_size);
387+
j = 0xFF;
388+
for (i = 0; i < buf_size ; i++) {
389+
buf[i] = (char)j;
390+
if (j == 0) {
391+
j = 0xFF;
392+
} else {
393+
j--;
394+
}
395+
}
396+
crc = spdk_crc64_nvme(buf, buf_size, 0);
397+
ASSERT_TRUE(crc == 0x9A2DF64B8E9E517E);
398+
}
331399

400+
TEST(RGWCksum, CRC64NVME2)
401+
{
402+
auto t = cksum::Type::crc64nvme;
403+
DigestVariant dv = rgw::cksum::digest_factory(t);
404+
Digest *digest = get_digest(dv);
405+
ASSERT_NE(digest, nullptr);
406+
407+
digest->Update((const unsigned char *)dolor.c_str(), dolor.length());
408+
409+
auto cksum = rgw::cksum::finalize_digest(digest, t);
332410

411+
/* the armored value produced by awscliv2 2.24.5 */
412+
ASSERT_EQ(cksum.to_armor(), "wiBA+PSv41M=");
413+
}
333414

334-
//foop
335415
TEST(RGWCksum, CtorUnarmor)
336416
{
337417
auto t = cksum::Type::sha256;
@@ -357,11 +437,13 @@ int main(int argc, char *argv[])
357437
auto args = argv_to_vec(argc, argv);
358438
env_to_vec(args);
359439

360-
std::string val;
361440
for (auto arg_iter = args.begin(); arg_iter != args.end();) {
362441
if (ceph_argparse_flag(args, arg_iter, "--verbose",
363442
(char*) nullptr)) {
364443
verbose = true;
444+
} else if (ceph_argparse_flag(args, arg_iter, "--gen_test_data",
445+
(char*) nullptr)) {
446+
gen_test_data = true;
365447
} else {
366448
++arg_iter;
367449
}

0 commit comments

Comments
 (0)