mirror of
https://github.com/versity/versitygw.git
synced 2026-09-22 07:54:14 +00:00
Port the hipObject v2 reliable-connection session core into cuwrapper/rc: the session table and state machine, the wire codec for the hipobj-rc-v2 headers, request parsing, the injectable clock and randomness sources, the transport layer (QP/CQ lifecycle, RTR/RTS transitions, staging registration), the data phase (RDMA write with immediate for GET, receive with immediate for PUT), the RDMA token codec, and the dynamically loaded ibverbs shim (ibv-core.h plus the dlopen host binding). The sources are a port of the upstream hipObject v2 core, kept close to the original so the two trees can be diffed during review. Nothing links against them yet; a Makefile rule builds the objects into rdma/librcserver.a for the ABI layer that follows. Signed-off-by: Jihyeon Gim <potatogim@potatogim.net>
120 lines
4.8 KiB
C++
120 lines
4.8 KiB
C++
/* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
|
|
* Copyright (c) Gluesys Inc. and Jihyeon Gim. All rights reserved.
|
|
*
|
|
* SPDX-License-Identifier: MIT
|
|
*/
|
|
|
|
/* hipobj-rc-v2 wire protocol parsing and formatting.
|
|
*
|
|
* The v2 protocol runs on a dedicated control endpoint and exchanges
|
|
* three request types (prepare/ready/cancel), each answered by a single
|
|
* HTTP response. The READY response doubles as the FINAL outcome: the
|
|
* server performs the RDMA transfer while answering READY, so the
|
|
* exchange completes in exactly two round trips.
|
|
*
|
|
* All parsing functions are pure (no library state) so they can be unit
|
|
* tested without RDMA hardware.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <cstddef>
|
|
#include <cstdint>
|
|
#include <string>
|
|
|
|
namespace hipObj {
|
|
namespace v2 {
|
|
|
|
/* Header and path names used by the control protocol. */
|
|
constexpr const char* kProtocolHeader = "X-Amz-Rdma-Protocol";
|
|
constexpr const char* kProtocolValue = "hipobj-rc-v2";
|
|
constexpr const char* kTokenHeader = "X-Amz-Rdma-Token";
|
|
constexpr const char* kSessionHeader = "X-Amz-Rdma-Session";
|
|
constexpr const char* kCookieHeader = "X-Amz-Rdma-Cookie";
|
|
constexpr const char* kPsnHeader = "X-Amz-Rdma-Psn";
|
|
constexpr const char* kOpHeader = "X-Amz-Rdma-Op";
|
|
constexpr const char* kSizeHeader = "X-Amz-Rdma-Size";
|
|
constexpr const char* kOffsetHeader = "X-Amz-Rdma-Offset";
|
|
constexpr const char* kTargetHeader = "X-Amz-Rdma-Target";
|
|
constexpr const char* kUnsupportedHeader = "X-Amz-Rdma-Protocol-Status";
|
|
constexpr const char* kUnsupportedValue = "unsupported";
|
|
constexpr const char* kReplyHeader = "X-Amz-Rdma-Reply";
|
|
constexpr const char* kBytesHeader = "X-Amz-Rdma-Bytes-Transferred";
|
|
constexpr const char* kEtagHeader = "X-Amz-Rdma-Etag";
|
|
constexpr const char* kVersionHeader = "X-Amz-Rdma-Version-Id";
|
|
constexpr const char* kChecksumHeader = "X-Amz-Rdma-Checksum";
|
|
constexpr const char* kControlPathPrefix = "/.hipobj-rc/";
|
|
|
|
/* Wire limits. */
|
|
constexpr size_t kSessionHexLen = 32; /* 128-bit session id */
|
|
constexpr size_t kCookieHexLen = 8; /* 32-bit cookie */
|
|
constexpr size_t kPsnHexLen = 6; /* 24-bit PSN, 000001..ffffff */
|
|
constexpr size_t kTokenHexLen = 88; /* 44-byte token payload */
|
|
constexpr size_t kChecksumB64Len = 12; /* 8-byte CRC64NVME base64 */
|
|
constexpr uint32_t kMaxTransferSize = 0x7fffffff; /* 2^31-1 */
|
|
|
|
struct PrepareReply {
|
|
int httpStatus = 0;
|
|
bool protocolEcho = false;
|
|
bool unsupportedMarker = false;
|
|
std::string serverToken; /* 88 hex chars */
|
|
std::string session; /* 32 hex chars */
|
|
uint32_t serverPsn = 0;
|
|
};
|
|
|
|
struct FinalReply {
|
|
int httpStatus = 0;
|
|
bool protocolEcho = false;
|
|
uint64_t bytes = 0;
|
|
uint32_t cookieEcho = 0;
|
|
bool cookiePresent = false; /* cookie echo header seen */
|
|
std::string etag;
|
|
std::string versionId;
|
|
std::string checksumB64; /* 12-char canonical base64 text */
|
|
};
|
|
|
|
/* Parses a single "Name: value" header line (without CRLF) into name and
|
|
* value with surrounding OWS trimmed. Returns false for lines without a
|
|
* colon. */
|
|
bool splitHeaderLine(const std::string& line, std::string& name,
|
|
std::string& value);
|
|
|
|
/* Parses the response to PREPARE. headers is the raw header block with
|
|
* lines separated by \r\n (final empty line optional); httpStatus is the
|
|
* status code from the status line. Returns false when the block is
|
|
* malformed in a way that makes the fields unusable. */
|
|
bool parsePrepareReply(int httpStatus, const std::string& headers,
|
|
PrepareReply& out);
|
|
|
|
/* Parses the READY/FINAL response. Same conventions as parsePrepareReply.
|
|
* The checksum field, when present, must be "CRC64NVME " followed by
|
|
* exactly 12 canonical base64 characters (11 data + one trailing '=');
|
|
* otherwise parsing fails. */
|
|
bool parseFinalReply(int httpStatus, const std::string& headers,
|
|
FinalReply& out);
|
|
|
|
/* Validates a canonical CRC64NVME checksum value: "CRC64NVME " prefix
|
|
* plus 12 base64 chars where the last is '=' and the text round-trips
|
|
* through strict decode/re-encode. Returns the 12-char text via out when
|
|
* valid. */
|
|
bool validateChecksumText(const std::string& headerValue, std::string& out);
|
|
|
|
/* Validates a session id (32 lowercase/uppercase hex chars). */
|
|
bool isValidSessionHex(const std::string& s);
|
|
|
|
/* Validates a PSN value string: 6 hex chars, value in 1..0xffffff. */
|
|
bool parsePsn(const std::string& s, uint32_t& psn);
|
|
|
|
/* Formats a cookie or PSN as 8/6 uppercase-zero-padded hex. */
|
|
std::string formatCookie(uint32_t cookie);
|
|
std::string formatPsn(uint32_t psn);
|
|
|
|
/* Builds the canonical rdma-target header value from bucket, key and an
|
|
* optional canonical query string (already encoded and sorted, may be
|
|
* empty). Percent-encodes the path per RFC 3986 unreserved rules. */
|
|
std::string buildTarget(const std::string& bucket, const std::string& key,
|
|
const std::string& canonicalQuery);
|
|
|
|
} // namespace v2
|
|
} // namespace hipObj
|