Compare commits

..
34 Commits
Author SHA1 Message Date
Vitaliy Filippov 55e2c65848 xxhash3 bench 2026-04-04 13:47:40 +03:00
Vitaliy Filippov 7eb8a66d0e Include xxhash3 x86dispatch 2026-04-04 13:42:05 +03:00
Vitaliy Filippov e14231e263 Implement protocol-level checksums (xxhash3) 2026-04-03 21:26:25 +03:00
Vitaliy Filippov 435c43e4c8 Do not use scrap_buffer in the client (it would block protocol checksum support) 2026-04-03 21:22:42 +03:00
Vitaliy Filippov 3d6e804437 Support TLS CN authentication and per-image permissions in vitastor-cli serve 2026-04-03 21:22:42 +03:00
Vitaliy Filippov 3fa75dfa6a Add VitastorAuthFilter 2026-04-03 21:22:42 +03:00
Vitaliy Filippov 231d18438e Implement vitastor-cli ls-user, modify-user, remove-user commands 2026-04-03 21:22:42 +03:00
Vitaliy Filippov 7be6fcd27e Add image owner/owner_group/reader_group support (for antietcd VitastorAuthFilter) 2026-04-03 21:22:42 +03:00
Vitaliy Filippov 9101ec1754 Add security parameter documentation 2026-04-03 21:22:42 +03:00
Vitaliy Filippov 8966cac272 Support inline (string PEM) certificates and pkeys 2026-04-03 21:22:42 +03:00
Vitaliy Filippov 8e5592cd24 Show encryption keys (only IDs) in the listing 2026-04-03 21:22:42 +03:00
Vitaliy Filippov a83687ea1d Support storing image encryption keys in Vault 2026-04-03 21:22:42 +03:00
Vitaliy Filippov 9825606fde Prefer local etcd addresses and correctly cycle over them even when they need resolving
Seems slightly overcomplicated...
2026-04-03 21:22:42 +03:00
Vitaliy Filippov 4accce43d8 Support DNS resolving via libc-ares 2026-04-03 21:22:42 +03:00
Vitaliy Filippov 1eec28bc65 Batch handle_immediate_ops more 2026-04-03 21:22:42 +03:00
Vitaliy Filippov ea280609ce Add vitastor-cli create & modify --enc-key parameter 2026-04-03 21:22:42 +03:00
Vitaliy Filippov 2e2ae066b2 Support reading from snapshots encrypted with different keys 2026-04-03 21:22:42 +03:00
Vitaliy Filippov 2ba4be470f Support decryption with multiple keys 2026-04-03 21:22:42 +03:00
Vitaliy Filippov 23463ec4cd Allow to return chain_info in response to reads 2026-04-03 21:22:42 +03:00
Vitaliy Filippov 1f5a832e28 Add basic AES-XTS client-side encryption support 2026-04-03 21:22:42 +03:00
Vitaliy Filippov 73e9de5143 Rework msgr send/receive to allow encryption support 2026-04-03 21:22:42 +03:00
Vitaliy Filippov 9cf30f286e Move fromhexstr() to str_util 2026-04-03 21:22:42 +03:00
Vitaliy Filippov 264b9dbfa9 Add openapi description 2026-04-03 21:22:42 +03:00
Vitaliy Filippov 0ee005bf23 Slightly fix API return and input types 2026-04-03 21:22:42 +03:00
Vitaliy Filippov 227c4c3bcf Implement vitastor-cli serve command to serve simple HTTP API 2026-04-03 21:22:42 +03:00
Vitaliy Filippov 85b762db2c Implement HTTP server support O_o 2026-04-03 21:22:42 +03:00
Vitaliy Filippov aaecf332f1 Rename http_response_t to http_message_t 2026-04-03 21:22:42 +03:00
Vitaliy Filippov 1dc8e82f37 Extract common HTTP context 2026-04-03 21:22:42 +03:00
Vitaliy Filippov afa9fe92ff Support xxhash 32-bit checksums (data_csum_type=xxh3_32) 2026-04-03 21:22:42 +03:00
Vitaliy Filippov 32d0e474ec Detect block checksums using csum_block_size, not data_csum_type 2026-04-03 21:22:42 +03:00
Vitaliy Filippov ff225534f1 Add client certificate support 2026-04-03 21:22:42 +03:00
Vitaliy Filippov 7d9124b63a Do not re-initialize TLS context every connection 2026-04-03 21:22:42 +03:00
Vitaliy Filippov b09b48c061 Add https support to antietcd 2026-04-03 21:22:42 +03:00
Vitaliy Filippov e896b2ed30 Implement etcd SSL support via OpenSSL
Maybe I should remove all of this and use libwebsockets :)
2026-04-03 21:22:42 +03:00
35 changed files with 169 additions and 748 deletions
+1 -1
View File
@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 2.8...3.30)
project(vitastor)
set(VITASTOR_VERSION "3.0.9")
set(VITASTOR_VERSION "3.0.8")
include(CTest)
+1 -1
View File
@@ -1,4 +1,4 @@
VITASTOR_VERSION ?= v3.0.9
VITASTOR_VERSION ?= v3.0.8
all: build push
+1 -1
View File
@@ -49,7 +49,7 @@ spec:
capabilities:
add: ["SYS_ADMIN"]
allowPrivilegeEscalation: true
image: vitalif/vitastor-csi:v3.0.9
image: vitalif/vitastor-csi:v3.0.8
args:
- "--node=$(NODE_ID)"
- "--endpoint=$(CSI_ENDPOINT)"
+1 -1
View File
@@ -121,7 +121,7 @@ spec:
privileged: true
capabilities:
add: ["SYS_ADMIN"]
image: vitalif/vitastor-csi:v3.0.9
image: vitalif/vitastor-csi:v3.0.8
args:
- "--node=$(NODE_ID)"
- "--endpoint=$(CSI_ENDPOINT)"
+1 -1
View File
@@ -5,7 +5,7 @@ package vitastor
const (
vitastorCSIDriverName = "csi.vitastor.io"
vitastorCSIDriverVersion = "3.0.9"
vitastorCSIDriverVersion = "3.0.8"
)
// Config struct fills the parameters of request or user input
+1 -1
View File
@@ -1,4 +1,4 @@
vitastor (3.0.9-1) unstable; urgency=medium
vitastor (3.0.8-1) unstable; urgency=medium
* Bugfixes
+1 -1
View File
@@ -1,4 +1,4 @@
VITASTOR_VERSION ?= v3.0.9
VITASTOR_VERSION ?= v3.0.8
all: build push
+1 -1
View File
@@ -4,7 +4,7 @@
#
# Desired Vitastor version
VITASTOR_VERSION=v3.0.9
VITASTOR_VERSION=v3.0.8
# Additional arguments for all containers
# For example, you may want to specify a custom logging driver here
-7
View File
@@ -70,7 +70,6 @@ with an OSD restart or, for some of them, even without restarting by updating co
- [use_atomic_flag](#use_atomic_flag)
- [pg_reshard_chunk_size](#pg_reshard_chunk_size)
- [pg_reshard_chunk_pause_ms](#pg_reshard_chunk_pause_ms)
- [gc_on_start](#gc_on_start)
## bind_address
@@ -754,9 +753,3 @@ This option sets the maximum number of object is a chunk. Moving 100k objects us
- Default: 100
This option sets the interval between handling two PG count change chunks.
## gc_on_start
- Type: boolean
Forcibly clean all garbage entries in the new store on every OSD restart.
-7
View File
@@ -71,7 +71,6 @@
- [use_atomic_flag](#use_atomic_flag)
- [pg_reshard_chunk_size](#pg_reshard_chunk_size)
- [pg_reshard_chunk_pause_ms](#pg_reshard_chunk_pause_ms)
- [gc_on_start](#gc_on_start)
## bind_address
@@ -794,9 +793,3 @@ pg_minsize OSD во время переключений, что может по
- Значение по умолчанию: 100
Данная опция задаёт интервал между обработкой двух порций изменения числа PG пулов.
## gc_on_start
- Тип: булево (да/нет)
Принудительно очищать все мусорные записи в новом хранилище при каждом запуске OSD.
-4
View File
@@ -938,7 +938,3 @@
This option sets the interval between handling two PG count change chunks.
info_ru: |
Данная опция задаёт интервал между обработкой двух порций изменения числа PG пулов.
- name: gc_on_start
type: bool
info: Forcibly clean all garbage entries in the new store on every OSD restart.
info_ru: Принудительно очищать все мусорные записи в новом хранилище при каждом запуске OSD.
+2 -2
View File
@@ -26,9 +26,9 @@ at Vitastor Kubernetes operator: https://github.com/Antilles7227/vitastor-operat
The instruction is very simple.
1. Download a Docker image of the desired version: \
`docker pull vitalif/vitastor:v3.0.9`
`docker pull vitalif/vitastor:v3.0.8`
2. Install scripts to the host system: \
`docker run --rm -it -v /etc:/host-etc -v /usr/bin:/host-bin vitalif/vitastor:v3.0.9 install.sh`
`docker run --rm -it -v /etc:/host-etc -v /usr/bin:/host-bin vitalif/vitastor:v3.0.8 install.sh`
3. Reload udev rules: \
`udevadm control --reload-rules`
4. Enable the vitastor-host service: \
+2 -2
View File
@@ -25,9 +25,9 @@ Vitastor можно установить в Docker/Podman. При этом etcd,
Инструкция по установке максимально простая.
1. Скачайте Docker-образ желаемой версии: \
`docker pull vitalif/vitastor:v3.0.9`
`docker pull vitalif/vitastor:v3.0.8`
2. Установите скрипты в хост-систему командой: \
`docker run --rm -it -v /etc:/host-etc -v /usr/bin:/host-bin vitalif/vitastor:v3.0.9 install.sh`
`docker run --rm -it -v /etc:/host-etc -v /usr/bin:/host-bin vitalif/vitastor:v3.0.8 install.sh`
3. Перезагрузите правила udev: \
`udevadm control --reload-rules`
4. Включите сервис vitastor-host: \
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "vitastor-mon",
"version": "3.0.9",
"version": "3.0.8",
"description": "Vitastor SDS monitor service",
"main": "mon-main.js",
"scripts": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "vitastor",
"version": "3.0.9",
"version": "3.0.8",
"description": "Low-level native bindings to Vitastor client library",
"main": "index.js",
"keywords": [
+1 -1
View File
@@ -50,7 +50,7 @@ from cinder.volume import configuration
from cinder.volume import driver
from cinder.volume import volume_utils
VITASTOR_VERSION = '3.0.9'
VITASTOR_VERSION = '3.0.8'
LOG = logging.getLogger(__name__)
+2 -2
View File
@@ -1,11 +1,11 @@
Name: vitastor
Version: 3.0.9
Version: 3.0.8
Release: 1%{?dist}
Summary: Vitastor, a fast software-defined clustered block storage
License: Vitastor Network Public License 1.1
URL: https://vitastor.io/
Source0: vitastor-3.0.9.el10.tar.gz
Source0: vitastor-3.0.8.el10.tar.gz
BuildRequires: gperftools-devel
BuildRequires: gcc-c++
+2 -2
View File
@@ -1,11 +1,11 @@
Name: vitastor
Version: 3.0.9
Version: 3.0.8
Release: 1%{?dist}
Summary: Vitastor, a fast software-defined clustered block storage
License: Vitastor Network Public License 1.1
URL: https://vitastor.io/
Source0: vitastor-3.0.9.el7.tar.gz
Source0: vitastor-3.0.8.el7.tar.gz
BuildRequires: gperftools-devel
BuildRequires: devtoolset-9-gcc-c++
+2 -2
View File
@@ -1,11 +1,11 @@
Name: vitastor
Version: 3.0.9
Version: 3.0.8
Release: 1%{?dist}
Summary: Vitastor, a fast software-defined clustered block storage
License: Vitastor Network Public License 1.1
URL: https://vitastor.io/
Source0: vitastor-3.0.9.el8.tar.gz
Source0: vitastor-3.0.8.el8.tar.gz
BuildRequires: gperftools-devel
BuildRequires: gcc-toolset-9-gcc-c++
+2 -2
View File
@@ -1,11 +1,11 @@
Name: vitastor
Version: 3.0.9
Version: 3.0.8
Release: 1%{?dist}
Summary: Vitastor, a fast software-defined clustered block storage
License: Vitastor Network Public License 1.1
URL: https://vitastor.io/
Source0: vitastor-3.0.9.el9.tar.gz
Source0: vitastor-3.0.8.el9.tar.gz
BuildRequires: gperftools-devel
BuildRequires: gcc-c++
+1 -1
View File
@@ -20,7 +20,7 @@ if("${CMAKE_INSTALL_PREFIX}" MATCHES "^/usr/local/?$")
endif()
set(ENABLE_COVERAGE false CACHE BOOL "Enable code coverage")
add_definitions(-DVITASTOR_VERSION="3.0.9")
add_definitions(-DVITASTOR_VERSION="3.0.8")
add_definitions(-D_GNU_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -Wall -Wno-sign-compare -Wno-comment -Wno-parentheses -Wno-pointer-arith -fdiagnostics-color=always -fno-omit-frame-pointer -fvisibility=hidden -I ${CMAKE_SOURCE_DIR}/src)
add_link_options(-fno-omit-frame-pointer)
if (${WITH_ASAN})
+1 -1
View File
@@ -877,7 +877,7 @@ uint64_t blockstore_impl_t::get_garbage_entries()
uint64_t blockstore_impl_t::get_garbage_memory()
{
return (sizeof(obj_ver_id) + sizeof(dirty_entry) + 32) * dirty_db.size();
return sizeof(blockstore_dirty_db_t::node_type) * dirty_db.size();
}
} // namespace v1
+14 -26
View File
@@ -164,42 +164,30 @@ void http_ares_cb(void *data, ares_socket_t socket_fd, int readable, int writabl
}
#ifdef WITH_OPENSSL
bool openssl_ctx_add_ca(SSL_CTX *ssl_ctx, const std::string & file_or_pem)
{
BIO *bio = NULL;
if (file_or_pem.substr(0, 5) != "-----")
{
std::string pem = read_file(file_or_pem);
bio = BIO_new_mem_buf(pem.data(), pem.size());
}
else
bio = BIO_new_mem_buf(file_or_pem.data(), file_or_pem.size());
if (!bio)
return false;
X509 *x509 = PEM_read_bio_X509(bio, NULL, 0, NULL);
bool ok = !!x509;
if (x509)
{
X509_STORE *store = SSL_CTX_get_cert_store(ssl_ctx);
X509_STORE_add_cert(store, x509);
X509_free(x509);
}
BIO_free(bio);
return ok;
}
bool openssl_ctx_use_ca(SSL_CTX *ssl_ctx, const std::string & file_or_pem)
{
if (file_or_pem.substr(0, 5) == "-----")
{
return openssl_ctx_add_ca(ssl_ctx, file_or_pem);
BIO *bio = BIO_new_mem_buf(file_or_pem.data(), file_or_pem.size());
if (!bio)
return false;
X509 *x509 = PEM_read_bio_X509(bio, NULL, 0, NULL);
bool ok = !!x509;
if (x509)
{
X509_STORE *store = SSL_CTX_get_cert_store(ssl_ctx);
X509_STORE_add_cert(store, x509);
X509_free(x509);
}
BIO_free(bio);
return ok;
}
return file_or_pem.empty()
? !!SSL_CTX_set_default_verify_paths(ssl_ctx)
: !!SSL_CTX_load_verify_locations(ssl_ctx, file_or_pem.c_str(), NULL);
}
std::string openssl_get_cn(X509 *x509)
static std::string openssl_get_cn(X509 *x509)
{
X509_NAME* subj = X509_get_subject_name(x509);
int pos = X509_NAME_get_index_by_NID(subj, NID_commonName, -1);
-12
View File
@@ -8,10 +8,6 @@
#include <functional>
#include "json11/json11.hpp"
#ifdef WITH_OPENSSL
#include <openssl/types.h>
#endif
#define WS_CONTINUATION 0
#define WS_TEXT 1
#define WS_BINARY 2
@@ -73,11 +69,3 @@ void http_close(http_co_t *co);
void http_destroy(http_co_t *co);
#pragma GCC visibility pop
#ifdef WITH_OPENSSL
bool openssl_ctx_add_ca(SSL_CTX *ssl_ctx, const std::string & file_or_pem);
bool openssl_ctx_use_ca(SSL_CTX *ssl_ctx, const std::string & file_or_pem);
std::string openssl_get_cn(X509 *x509);
bool openssl_ctx_use_cert(SSL_CTX *ssl_ctx, const std::string & file_or_pem, std::string & common_name);
bool openssl_ctx_use_key(SSL_CTX *ssl_ctx, const std::string & file_or_pem);
#endif
+4 -107
View File
@@ -14,13 +14,6 @@
#ifdef WITH_RDMA
#include "msgr_rdma.h"
#endif
#include "http_client.h"
#ifdef WITH_OPENSSL
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/pem.h>
#include <openssl/ssl.h>
#endif
#include <sys/poll.h>
@@ -124,43 +117,6 @@ void msgr_iothread_t::run()
void osd_messenger_t::init()
{
if (!tls_cert.empty() || !tls_key.empty() || !osd_tls_ca.empty() || !client_tls_ca.empty())
{
// Initialize TLS context
// FIXME: require OpenSSL
#ifndef WITH_OPENSSL
fprintf(stderr, "Vitastor is built without OpenSSL support\n");
exit(1);
#else
if (tls_cert.empty() || tls_key.empty() || osd_tls_ca.empty() || osd_num && client_tls_ca.empty())
{
if (osd_num)
fprintf(stderr, "Vitastor OSD TLS requires osd_tls_cert, osd_tls_key, osd_tls_ca, client_tls_ca\n");
else
fprintf(stderr, "Vitastor client TLS requires tls_cert, tls_key and osd_tls_ca\n");
exit(1);
}
else
{
ssl_ctx = SSL_CTX_new(TLS_method());
SSL_CTX_set_verify(ssl_ctx, SSL_VERIFY_PEER, NULL);
bool ok = SSL_CTX_set_min_proto_version(ssl_ctx, TLS1_3_VERSION);
ok = ok && openssl_ctx_add_ca(ssl_ctx, osd_tls_ca);
if (osd_num)
{
// OSD uses 2 separate root certificates to distinguish between clients and peer OSDs
ok = ok && openssl_ctx_add_ca(ssl_ctx, client_tls_ca);
}
ok = ok && openssl_ctx_use_cert(ssl_ctx, tls_cert, tls_cn);
ok = ok && openssl_ctx_use_key(ssl_ctx, tls_key);
if (!ok)
{
SSL_CTX_free(ssl_ctx);
ssl_ctx = NULL;
}
}
#endif
}
#ifdef WITH_RDMACM
if (use_rdmacm)
{
@@ -347,13 +303,6 @@ osd_messenger_t::~osd_messenger_t()
{
destroy_aes_xts_decrypt(decrypt_ctx);
}
#ifdef WITH_OPENSSL
if (ssl_ctx)
{
SSL_CTX_free(ssl_ctx);
ssl_ctx = NULL;
}
#endif
}
void osd_messenger_t::parse_config(const json11::Json & config)
@@ -391,27 +340,7 @@ void osd_messenger_t::parse_config(const json11::Json & config)
this->max_aes_xts_pool_size = config["max_aes_xts_pool_size"].uint64_value();
if (!this->max_aes_xts_pool_size)
this->max_aes_xts_pool_size = 256;
if (config["proto_checksums"].is_null())
this->use_proto_checksums = MSGR_CSUM_PAYLOAD;
else if (config["proto_checksums"].is_bool())
this->use_proto_checksums = config["proto_checksums"].bool_value() ? MSGR_CSUM_FULL : 0;
else if (config["proto_checksums"].string_value() != "")
this->use_proto_checksums = config["proto_checksums"].string_value() == "full" ? MSGR_CSUM_FULL : MSGR_CSUM_PAYLOAD;
else
this->use_proto_checksums = 0;
if (!osd_num)
{
tls_cert = config["tls_cert"].string_value();
tls_key = config["tls_key"].string_value();
osd_tls_ca = config["osd_tls_ca"].string_value();
}
else
{
tls_cert = config["osd_tls_cert"].string_value();
tls_key = config["osd_tls_key"].string_value();
osd_tls_ca = config["osd_tls_ca"].string_value();
client_tls_ca = config["client_tls_ca"].string_value();
}
this->use_proto_checksums = config["use_proto_checksums"].is_null() || config["use_proto_checksums"].bool_value();
if (!osd_num)
this->iothread_count = (uint32_t)config["client_iothread_count"].uint64_value();
else
@@ -642,10 +571,6 @@ void osd_messenger_t::handle_connect_epoll(int peer_fd)
handle_peer_epoll(peer_fd, epoll_events);
});
// Check OSD number
if (!tls_cert.empty())
{
ssl_init(cl, false);
}
check_peer_config(cl);
}
@@ -738,7 +663,7 @@ void osd_messenger_t::check_peer_config(osd_client_t *cl)
auto features = json11::Json::object{ { "check_sequencing", true } };
if (use_proto_checksums)
{
features["proto_checksums"] = use_proto_checksums;
features["proto_checksums"] = true;
}
payload["features"] = features;
#ifdef WITH_RDMA
@@ -815,13 +740,9 @@ void osd_messenger_t::check_peer_config(osd_client_t *cl)
delete op;
return;
}
if (use_proto_checksums)
if (use_proto_checksums && config["features"]["proto_checksums"].bool_value())
{
auto peer_csums = config["features"]["proto_checksums"].uint64_value();
if (peer_csums == MSGR_CSUM_FULL && use_proto_checksums == MSGR_CSUM_FULL)
cl->proto_csum_status = MSGR_CSUM_FULL;
else if (peer_csums && use_proto_checksums)
cl->proto_csum_status = MSGR_CSUM_PAYLOAD;
cl->proto_csum_status = MSGR_PEER_CSUM_IN|MSGR_PEER_CSUM_OUT;
}
#ifdef WITH_RDMA
if (!use_rdmacm && cl->rdma_conn && config["rdma_address"].is_string())
@@ -887,10 +808,6 @@ void osd_messenger_t::accept_connections(int listen_fd)
cl->peer_fd = peer_fd;
cl->peer_state = PEER_CONNECTED;
cl->in_buf = (uint8_t*)malloc_or_die(receive_buffer_size);
if (!tls_cert.empty())
{
ssl_init(cl, true);
}
// Add FD to epoll
tfd->set_fd_handler(peer_fd, false, [this](int peer_fd, int epoll_events)
{
@@ -905,26 +822,6 @@ void osd_messenger_t::accept_connections(int listen_fd)
}
}
void osd_messenger_t::ssl_init(osd_client_t *cl, bool server_mode)
{
#ifdef WITH_OPENSSL
cl->write_to_ssl = BIO_new(BIO_s_mem());
cl->read_from_ssl = BIO_new(BIO_s_mem());
cl->ssl_cli = SSL_new(ssl_ctx);
if (server_mode)
{
SSL_set_accept_state(cl->ssl_cli);
}
else
{
SSL_set_connect_state(cl->ssl_cli);
}
SSL_set_bio(cl->ssl_cli, cl->write_to_ssl, cl->read_from_ssl);
bool ok = ssl_do_handshake(cl);
assert(ok);
#endif
}
#ifdef WITH_RDMA
msgr_rdma_context_t* osd_messenger_t::choose_rdma_context(osd_client_t *cl)
{
+3 -46
View File
@@ -12,10 +12,6 @@
#include <deque>
#include <vector>
#ifdef WITH_OPENSSL
#include <openssl/types.h>
#endif
#include "../util/xxh_x86dispatch.h"
#include "../util/robin_hood.h"
#include "malloc_or_die.h"
@@ -36,9 +32,8 @@
#define PEER_RDMA 4
#define PEER_STOPPED 5
#define MSGR_CSUM_PAYLOAD 1
#define MSGR_CSUM_FULL 2
#define MSGR_CSUM_NEG 4
#define MSGR_PEER_CSUM_IN 1
#define MSGR_PEER_CSUM_OUT 2
#define VITASTOR_CONFIG_PATH "/etc/vitastor/vitastor.conf"
@@ -60,12 +55,6 @@ struct op_aes_xts_decrypt_t;
void destroy_aes_xts_encrypt(op_aes_xts_encrypt_t *encrypt_ctx);
void destroy_aes_xts_decrypt(op_aes_xts_decrypt_t *decrypt_ctx);
struct __attribute__((__packed__)) msgr_tls_record_hdr_t
{
uint8_t encrypted;
uint32_t size;
};
struct osd_client_t
{
uint64_t client_id = 0;
@@ -88,17 +77,6 @@ struct osd_client_t
msgr_rdma_connection_t *rdma_conn = NULL;
#endif
#ifdef WITH_OPENSSL
SSL *ssl_cli = NULL;
BIO *write_to_ssl = NULL;
// FIXME: use custom bio to avoid 1 more memory copy?
BIO *read_from_ssl = NULL;
uint8_t *ssl_out_buf = NULL;
size_t ssl_out_buf_size = 0, ssl_out_buf_cap = 0;
bool ssl_handshake_done = false;
bool ssl_want_write = false;
#endif
// Read state
int read_ready = 0;
osd_op_t *read_op = NULL;
@@ -232,11 +210,6 @@ protected:
int iothread_count = 0;
int max_aes_xts_pool_size = 256;
std::string tls_cert;
std::string tls_key;
std::string osd_tls_ca;
std::string client_tls_ca;
#ifdef WITH_RDMA
bool use_rdma = true;
bool use_rdmacm = false;
@@ -253,19 +226,6 @@ protected:
robin_hood::unordered_flat_map<rdma_cm_id*, rdmacm_connecting_t*> rdmacm_connecting;
#endif
#ifdef WITH_OPENSSL
SSL_CTX *ssl_ctx = NULL;
std::string tls_cn;
void ssl_init(osd_client_t *cl, bool server_mode);
bool ssl_do_handshake(osd_client_t *cl);
bool ssl_do_encrypt(osd_client_t *cl);
size_t ssl_do_encrypt_to(osd_client_t *cl, uint8_t *buf, size_t size);
bool ssl_op_write_buf(osd_client_t *cl, uint8_t *src, size_t src_len, bool skip_csum, size_t & from, size_t & done);
size_t ssl_op_copy_to(osd_client_t *cl, uint8_t *dst, size_t dst_len);
void ssl_op_get_write_buffers(osd_client_t *cl, std::vector<iovec> & lst);
#endif
std::vector<msgr_iothread_t*> iothreads;
std::vector<uint64_t> read_ready_clients;
std::vector<uint64_t> write_ready_clients;
@@ -292,7 +252,7 @@ public:
std::vector<addr_mask_t> osd_cluster_network_masks;
std::vector<std::string> all_osd_networks;
std::vector<addr_mask_t> all_osd_network_masks;
int use_proto_checksums = 0;
bool use_proto_checksums = true;
// op statistics
osd_op_stats_t stats, recovery_stats;
@@ -344,9 +304,6 @@ protected:
void handle_send(int result, bool prev, bool more, osd_client_t *cl);
size_t op_copy_to(osd_client_t *cl, uint8_t *dst, size_t dst_len);
void op_get_write_buffers(osd_client_t *cl, std::vector<iovec> & lst);
void next_write_op(osd_client_t *cl);
bool op_write_buf(osd_client_t *cl, uint8_t *src, size_t src_len, uint8_t *dst, size_t dst_len, bool skip_csum, size_t & from, size_t & done);
bool op_copy_data_to(osd_client_t *cl, uint8_t *dst, size_t dst_len, size_t & from, size_t & done);
void handle_read(int result, osd_client_t *cl);
bool handle_read_buffer(osd_client_t *cl, uint8_t *curbuf, size_t bufsize);
+7 -17
View File
@@ -187,8 +187,6 @@ std::vector<msgr_rdma_context_t*> msgr_rdma_context_t::create_all(const std::vec
ibv_device **raw_dev_list = NULL;
ibv_device **dev_list = NULL;
ibv_device *single_list[2] = {};
int up_ports = 0;
int single_port_num = 0;
raw_dev_list = dev_list = ibv_get_device_list(NULL);
if (!dev_list || !*dev_list)
@@ -223,7 +221,6 @@ std::vector<msgr_rdma_context_t*> msgr_rdma_context_t::create_all(const std::vec
dev_list = single_list;
}
retry:
for (int i = 0; dev_list[i]; ++i)
{
auto dev = dev_list[i];
@@ -261,9 +258,6 @@ retry:
fprintf(stderr, "RDMA device %s port %d GID %d does not exist\n", ibv_get_device_name(dev), port_num, sel_gid_index);
continue;
}
up_ports++;
single_port_num = port_num;
single_list[0] = dev;
uint32_t port_mtu = sel_mtu ? sel_mtu : ibv_mtu_to_bytes(portinfo.active_mtu);
#ifdef IBV_ADVISE_MR_ADVICE_PREFETCH_NO_FAULT
if (sel_gid_index < 0)
@@ -304,14 +298,6 @@ cleanup_dev:
ibv_close_device(context);
}
if (!ret.size() && up_ports == 1 && dev_list != single_list)
{
// Auto-select the only available device/port if there is only one
dev_list = single_list;
sel_port_num = single_port_num;
goto retry;
}
cleanup:
if (raw_dev_list)
ibv_free_device_list(raw_dev_list);
@@ -573,7 +559,11 @@ int osd_messenger_t::try_send_rdma_copy(osd_client_t *cl, uint8_t *dst, int dst_
int total_dst_len = dst_len;
while (dst_len > 0 && (cl->write_op || cl->write_ops.size()))
{
next_write_op(cl);
if (!cl->write_op)
{
cl->write_op = cl->write_ops.front();
cl->write_ops.pop_front();
}
osd_op_t *op = cl->write_op;
size_t copied = op_copy_to(cl, dst, dst_len);
if (!copied)
@@ -754,10 +744,10 @@ void osd_messenger_t::handle_rdma_events(msgr_rdma_context_t *rdma_context)
cl->send_free_ops.pop_front();
}
cl->send_free_ops.pop_front();
if ((cl->proto_csum_status & MSGR_CSUM_NEG) && !cl->write_op && !cl->write_ops.size())
if (cl->proto_csum_status == MSGR_PEER_CSUM_IN && !cl->write_op && !cl->write_ops.size())
{
// Checksums negotiated, enable
cl->proto_csum_status = cl->proto_csum_status & (~MSGR_CSUM_NEG);
cl->proto_csum_status = MSGR_PEER_CSUM_IN|MSGR_PEER_CSUM_OUT;
}
try_send_rdma(cl);
}
+10 -15
View File
@@ -203,7 +203,7 @@ bool osd_messenger_t::handle_read_buffer(osd_client_t *cl, uint8_t *curbuf, size
cl->read_op_size = 0;
cl->read_op_inline_decrypt_in = 0;
cl->read_op_inline_decrypt_pos = (size_t)-1;
if (cl->proto_csum_status == MSGR_CSUM_FULL || cl->proto_csum_status == MSGR_CSUM_PAYLOAD)
if (cl->proto_csum_status == (MSGR_PEER_CSUM_IN|MSGR_PEER_CSUM_OUT))
{
if (!cl->read_csum_state)
cl->read_csum_state = XXH3_createState();
@@ -236,10 +236,6 @@ bool osd_messenger_t::handle_read_buffer(osd_client_t *cl, uint8_t *curbuf, size
bool osd_messenger_t::handle_hdr(osd_client_t *cl)
{
if (cl->proto_csum_status == MSGR_CSUM_FULL)
{
XXH3_64bits_update(cl->read_csum_state, cl->read_op->req.buf, OSD_PACKET_SIZE);
}
if (cl->read_op->req.hdr.magic == SECONDARY_OSD_REPLY_MAGIC)
{
auto req_it = cl->sent_ops.find(cl->read_op->req.hdr.id);
@@ -337,8 +333,7 @@ bool osd_messenger_t::allocate_op_buffers(osd_client_t *cl)
}
cl->read_op_size = cur_op->req.show_conf.json_len;
}
if (cl->proto_csum_status == MSGR_CSUM_FULL ||
cl->read_op_size > 0 && cl->proto_csum_status == MSGR_CSUM_PAYLOAD)
if (cl->proto_csum_status == (MSGR_PEER_CSUM_IN|MSGR_PEER_CSUM_OUT))
{
cl->read_op_size += 8;
}
@@ -396,8 +391,7 @@ bool osd_messenger_t::allocate_reply_buffers(osd_client_t *cl, osd_op_t *op)
free(op->buf);
op->buf = malloc_or_die(op->reply.describe.result_bytes);
}
if (cl->proto_csum_status == MSGR_CSUM_FULL ||
cl->read_op_size > 0 && cl->proto_csum_status == MSGR_CSUM_PAYLOAD)
if (cl->proto_csum_status == (MSGR_PEER_CSUM_IN|MSGR_PEER_CSUM_OUT))
{
cl->read_op_size += 8;
}
@@ -435,6 +429,10 @@ bool osd_messenger_t::op_copy_from(osd_client_t *cl, uint8_t *src, size_t src_le
from -= dst_len;
return true;
};
if (cl->read_csum_state && !from)
{
XXH3_64bits_update(cl->read_csum_state, (op->op_type == OSD_OP_IN ? op->req.buf : op->reply.buf), OSD_PACKET_SIZE);
}
if (op->op_type == OSD_OP_IN)
{
if (op->req.hdr.opcode == OSD_OP_SEC_WRITE ||
@@ -522,8 +520,7 @@ bool osd_messenger_t::op_copy_from(osd_client_t *cl, uint8_t *src, size_t src_le
return true;
}
}
if (cl->proto_csum_status == MSGR_CSUM_FULL ||
cl->read_op_size > 0 && cl->proto_csum_status == MSGR_CSUM_PAYLOAD)
if (cl->proto_csum_status == (MSGR_PEER_CSUM_IN|MSGR_PEER_CSUM_OUT))
{
if (!op_read_buf((uint8_t*)&op->csum, 8, true))
return true;
@@ -645,8 +642,7 @@ void osd_messenger_t::op_get_read_buffers(osd_client_t *cl, std::vector<iovec> &
return;
}
}
if (cl->proto_csum_status == MSGR_CSUM_FULL ||
cl->read_op_size > 0 && cl->proto_csum_status == MSGR_CSUM_PAYLOAD)
if (cl->proto_csum_status == (MSGR_PEER_CSUM_IN|MSGR_PEER_CSUM_OUT))
{
if (!op_read_buf((uint8_t*)&op->csum, 8))
return;
@@ -680,8 +676,7 @@ void osd_messenger_t::op_alloc_temp_buffers(osd_op_t *op, int i)
bool osd_messenger_t::handle_finished_op(osd_client_t *cl)
{
osd_op_t *op = cl->read_op;
if (cl->proto_csum_status == MSGR_CSUM_FULL ||
cl->read_op_size > 0 && cl->proto_csum_status == MSGR_CSUM_PAYLOAD)
if (cl->proto_csum_status == (MSGR_PEER_CSUM_IN|MSGR_PEER_CSUM_OUT))
{
uint64_t real_csum = XXH3_64bits_digest(cl->read_csum_state);
if (op->csum != real_csum)
+62 -381
View File
@@ -7,13 +7,6 @@
#include "messenger.h"
#ifdef WITH_OPENSSL
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/pem.h>
#include <openssl/ssl.h>
#endif
void osd_messenger_t::outbox_push(osd_op_t *cur_op)
{
assert(cur_op->client_id);
@@ -123,103 +116,25 @@ void osd_messenger_t::measure_exec(osd_op_t *cur_op)
}
}
bool osd_messenger_t::ssl_do_handshake(osd_client_t *cl)
{
int r = SSL_do_handshake(cl->ssl_cli);
if (r > 0)
{
cl->ssl_handshake_done = true;
}
else
{
r = SSL_get_error(cl->ssl_cli, r);
if (r != SSL_ERROR_WANT_WRITE && r != SSL_ERROR_WANT_READ)
{
fprintf(stderr, "Client %ju TLS handshake error: %s, stopping client\n", cl->client_id, ERR_error_string(ERR_get_error(), NULL));
stop_client(cl->client_id);
return false;
}
if (r == SSL_ERROR_WANT_WRITE)
{
cl->ssl_want_write = true;
}
}
return true;
}
bool osd_messenger_t::ssl_do_encrypt(osd_client_t *cl)
{
if (cl->send_list.size() >= IOV_MAX || !cl->ssl_want_write)
return false;
size_t prev_size = cl->ssl_out_buf_size;
while (true)
{
size_t min_cap = cl->ssl_out_buf_size*2;
if (min_cap < 16384)
min_cap = 16384;
if (cl->ssl_out_buf_cap < min_cap)
{
uint8_t *old_buf = cl->ssl_out_buf;
uint8_t *old_end = old_buf + cl->ssl_out_buf_cap;
cl->ssl_out_buf = (uint8_t*)realloc_or_die(cl->ssl_out_buf, min_cap);
cl->ssl_out_buf_cap = min_cap;
for (auto & iov: cl->send_list)
{
if (iov.iov_base >= old_buf && iov.iov_base < old_end)
iov.iov_base = cl->ssl_out_buf + ((uint8_t*)iov.iov_base - old_buf);
}
}
bool full_read = (ssl_do_encrypt_to(cl, cl->ssl_out_buf+cl->ssl_out_buf_size,
cl->ssl_out_buf_cap-cl->ssl_out_buf_size) == cl->ssl_out_buf_cap-cl->ssl_out_buf_size);
if (!full_read)
break;
}
if (cl->ssl_out_buf_size > prev_size)
cl->send_list.push_back((iovec){ .iov_base = cl->ssl_out_buf+prev_size, .iov_len = cl->ssl_out_buf_size-prev_size });
return true;
}
size_t osd_messenger_t::ssl_do_encrypt_to(osd_client_t *cl, uint8_t *buf, size_t size)
{
if (size < sizeof(msgr_tls_record_hdr_t))
return 0;
int r = BIO_read(cl->read_from_ssl, buf+sizeof(msgr_tls_record_hdr_t), size-sizeof(msgr_tls_record_hdr_t));
if (r > 0)
{
if (r < size-sizeof(msgr_tls_record_hdr_t))
cl->ssl_want_write = false;
msgr_tls_record_hdr_t *hdr = (msgr_tls_record_hdr_t*)buf;
hdr->encrypted = 1;
hdr->size = r;
return r+sizeof(msgr_tls_record_hdr_t);
}
return 0;
}
bool osd_messenger_t::try_send(osd_client_t *cl)
{
if (!cl->write_op && !cl->write_ops.size() && !cl->ssl_want_write ||
cl->write_msg.msg_iovlen > 0 || cl->peer_state == PEER_STOPPED || cl->peer_fd < 0)
if (!cl->write_op && !cl->write_ops.size() || cl->write_msg.msg_iovlen > 0 || cl->peer_state == PEER_STOPPED || cl->peer_fd < 0)
{
return true;
}
assert(cl->peer_state != PEER_RDMA);
if (cl->ssl_cli && !cl->ssl_handshake_done)
while ((cl->write_op || cl->write_ops.size()) && cl->send_list.size() < IOV_MAX)
{
bool ok = ssl_do_encrypt(cl);
assert(ok && cl->send_list.size() > 0);
}
else
{
while ((cl->write_op || cl->write_ops.size()) && cl->send_list.size() < IOV_MAX)
if (!cl->write_op)
{
next_write_op(cl);
osd_op_t *op = cl->write_op;
op_get_write_buffers(cl, cl->send_list);
if (!cl->write_op && op->op_type == OSD_OP_IN)
{
cl->send_free_ops.push_back(op);
}
cl->write_op = cl->write_ops.front();
cl->write_ops.pop_front();
}
osd_op_t *op = cl->write_op;
op_get_write_buffers(cl, cl->send_list);
if (!cl->write_op && op->op_type == OSD_OP_IN)
{
cl->send_free_ops.push_back(op);
}
}
if (ringloop && !use_sync_send_recv)
@@ -282,21 +197,6 @@ bool osd_messenger_t::try_send(osd_client_t *cl)
return true;
}
void osd_messenger_t::next_write_op(osd_client_t *cl)
{
if (!cl->write_op)
{
cl->write_op = cl->write_ops.front();
cl->write_ops.pop_front();
if (cl->proto_csum_status == MSGR_CSUM_FULL || cl->proto_csum_status == MSGR_CSUM_PAYLOAD)
{
if (!cl->write_csum_state)
cl->write_csum_state = XXH3_createState();
XXH3_64bits_reset(cl->write_csum_state);
}
}
}
void osd_messenger_t::send_replies()
{
for (int i = 0; i < write_ready_clients.size(); i++)
@@ -364,15 +264,14 @@ void osd_messenger_t::handle_send(int result, bool prev, bool more, osd_client_t
else
delete op;
}
cl->ssl_out_buf_size = 0;
if (more)
cl->zc_free_list.push_back(NULL); // end marker
cl->send_free_ops.clear();
cl->write_state = cl->write_op || cl->write_ops.size() ? CL_WRITE_READY : 0;
if ((cl->proto_csum_status & MSGR_CSUM_NEG) && !cl->write_op && !cl->write_ops.size())
if (cl->proto_csum_status == MSGR_PEER_CSUM_IN && !cl->write_op && !cl->write_ops.size())
{
// Checksums negotiated, enable
cl->proto_csum_status = cl->proto_csum_status & (~MSGR_CSUM_NEG);
cl->proto_csum_status = MSGR_PEER_CSUM_IN|MSGR_PEER_CSUM_OUT;
}
#ifdef WITH_RDMA
if (cl->rdma_conn && !cl->write_op && !cl->write_ops.size() && cl->peer_state == PEER_RDMA_CONNECTING)
@@ -394,37 +293,36 @@ void osd_messenger_t::handle_send(int result, bool prev, bool more, osd_client_t
}
}
static inline bool op_write_headers(osd_op_t *op, std::function<bool(uint8_t*, size_t, bool)> op_write_buf, bool skip_hdr_csum)
static inline bool op_write_headers(osd_op_t *op, std::function<bool(uint8_t*, size_t)> op_write_buf)
{
if (!op_write_buf((op->op_type == OSD_OP_IN ? op->reply.buf : op->req.buf), OSD_PACKET_SIZE, skip_hdr_csum))
{
// Header
if (!op_write_buf((op->op_type == OSD_OP_IN ? op->reply.buf : op->req.buf), OSD_PACKET_SIZE))
return false;
}
// Bitmap
if (op->op_type == OSD_OP_IN &&
op->req.hdr.opcode == OSD_OP_SEC_READ &&
op->reply.sec_rw.attr_len > 0)
{
if (!op_write_buf((uint8_t*)op->bitmap, op->reply.sec_rw.attr_len, false))
if (!op_write_buf((uint8_t*)op->bitmap, op->reply.sec_rw.attr_len))
return false;
}
else if (op->op_type == OSD_OP_OUT &&
(op->req.hdr.opcode == OSD_OP_SEC_WRITE || op->req.hdr.opcode == OSD_OP_SEC_WRITE_STABLE) &&
op->req.sec_rw.attr_len > 0)
{
if (!op_write_buf((uint8_t*)op->bitmap, op->req.sec_rw.attr_len, false))
if (!op_write_buf((uint8_t*)op->bitmap, op->req.sec_rw.attr_len))
return false;
}
if (op->req.hdr.opcode == OSD_OP_SEC_READ_BMP)
{
if (op->op_type == OSD_OP_IN && op->reply.hdr.retval > 0)
{
if (!op_write_buf((uint8_t*)op->buf, (size_t)op->reply.hdr.retval, false))
if (!op_write_buf((uint8_t*)op->buf, (size_t)op->reply.hdr.retval))
return false;
}
else if (op->op_type == OSD_OP_OUT && op->req.sec_read_bmp.len > 0)
{
if (!op_write_buf((uint8_t*)op->buf, (size_t)op->req.sec_read_bmp.len, false))
if (!op_write_buf((uint8_t*)op->buf, (size_t)op->req.sec_read_bmp.len))
return false;
}
}
@@ -447,38 +345,20 @@ static inline bool op_has_data(osd_op_t *op)
op->req.hdr.opcode == OSD_OP_SHOW_CONFIG)) && op->iov.count > 0;
}
static inline bool op_has_data_for_ssl(osd_op_t *op)
size_t osd_messenger_t::op_copy_to(osd_client_t *cl, uint8_t *dst, size_t dst_len)
{
return (op->op_type == OSD_OP_IN
? (op->req.hdr.opcode == OSD_OP_SEC_LIST ||
op->req.hdr.opcode == OSD_OP_SHOW_CONFIG ||
op->req.hdr.opcode == OSD_OP_DESCRIBE)
: (op->req.hdr.opcode == OSD_OP_SEC_STABILIZE ||
op->req.hdr.opcode == OSD_OP_SEC_ROLLBACK ||
op->req.hdr.opcode == OSD_OP_SHOW_CONFIG)) && op->iov.count > 0;
}
static inline bool op_has_data_for_nonssl(osd_op_t *op)
{
return (op->op_type == OSD_OP_IN
? (op->req.hdr.opcode == OSD_OP_READ ||
op->req.hdr.opcode == OSD_OP_SEC_READ)
: (op->req.hdr.opcode == OSD_OP_WRITE ||
op->req.hdr.opcode == OSD_OP_SEC_WRITE ||
op->req.hdr.opcode == OSD_OP_SEC_WRITE_STABLE)) && op->iov.count > 0;
}
bool osd_messenger_t::ssl_op_write_buf(osd_client_t *cl, uint8_t *src, size_t src_len, bool skip_csum, size_t & from, size_t & done)
{
if (from < src_len)
size_t done = 0;
size_t from = cl->write_op_pos;
auto op_write_buf = [&](uint8_t *src, size_t src_len, bool skip_csum = false)
{
size_t n = src_len-from;
int ok = SSL_write_ex(cl->ssl_cli, src+from, n, &n);
if (ok)
if (from < src_len)
{
cl->ssl_want_write = true;
size_t n = src_len-from;
if (n > dst_len-done)
n = dst_len-done;
if (cl->write_csum_state && !skip_csum)
XXH3_64bits_update(cl->write_csum_state, src+from, n);
memcpy(dst+done, src+from, n);
done += n;
cl->write_op_pos += n;
from += n;
@@ -487,135 +367,39 @@ bool osd_messenger_t::ssl_op_write_buf(osd_client_t *cl, uint8_t *src, size_t sr
from = 0;
}
else
{
int res = SSL_get_error(cl->ssl_cli, ok);
if (res == SSL_ERROR_WANT_WRITE || res == 0)
cl->ssl_want_write = true;
else if (res == SSL_ERROR_ZERO_RETURN)
{
fprintf(stderr, "Client %ju TLS disconnected\n", cl->client_id);
stop_client(cl->client_id);
}
else if (res != SSL_ERROR_WANT_READ)
{
fprintf(stderr, "Client %ju TLS write error: %s. Disconnecting client\n", cl->client_id, ERR_error_string(ERR_get_error(), NULL));
stop_client(cl->client_id);
}
return false;
}
}
else
from -= src_len;
return true;
}
bool osd_messenger_t::op_write_buf(osd_client_t *cl, uint8_t *src, size_t src_len, uint8_t *dst, size_t dst_len, bool skip_csum, size_t & from, size_t & done)
{
if (from < src_len)
{
size_t n = src_len-from;
if (n > dst_len-done)
n = dst_len-done;
if (cl->write_csum_state && !skip_csum)
XXH3_64bits_update(cl->write_csum_state, src+from, n);
memcpy(dst+done, src+from, n);
done += n;
cl->write_op_pos += n;
from += n;
if (from < src_len)
return false;
from = 0;
}
else
from -= src_len;
return true;
}
size_t osd_messenger_t::ssl_op_copy_to(osd_client_t *cl, uint8_t *dst, size_t dst_len)
{
size_t done = 0;
size_t from = cl->write_op_pos;
// Encrypt headers and data except read/write data
auto to_ssl = [&](uint8_t *src, size_t src_len, bool skip_csum)
{
return ssl_op_write_buf(cl, src, src_len, skip_csum, from, done);
from -= src_len;
return true;
};
int i = 0;
bool full_hdr = false;
bool full_op = false;
do
if (cl->proto_csum_status == (MSGR_PEER_CSUM_IN|MSGR_PEER_CSUM_OUT) && !from)
{
if (!full_hdr)
full_hdr = op_write_headers(cl->write_op, to_ssl, cl->proto_csum_status != MSGR_CSUM_FULL);
if (full_hdr && op_has_data_for_ssl(cl->write_op))
{
for (; i < cl->write_op->iov.count; i++)
if (!ssl_op_write_buf(cl, (uint8_t*)cl->write_op->iov.buf[i].iov_base, cl->write_op->iov.buf[i].iov_len, false, from, done))
break;
full_op = true;
}
if (cl->peer_state == PEER_STOPPED)
return 0;
if (cl->ssl_want_write)
{
auto ssl_written = ssl_do_encrypt_to(cl, dst+done, dst_len-done);
if (!ssl_written)
return done;
done += ssl_written;
}
} while (!full_op);
// Non-TLS-encrypted operation data
if (op_has_data_for_nonssl(cl->write_op))
{
if (!op_copy_data_to(cl, dst, dst_len, from, done))
return done;
if (!cl->write_csum_state)
cl->write_csum_state = XXH3_createState();
XXH3_64bits_reset(cl->write_csum_state);
}
// TLS-encrypted checksum (uh oh...)
if (cl->proto_csum_status == MSGR_CSUM_FULL ||
cl->proto_csum_status == MSGR_CSUM_PAYLOAD && cl->write_op_pos > OSD_PACKET_SIZE)
{
if (!from)
cl->write_op->csum = XXH3_64bits_digest(cl->write_csum_state);
if (!ssl_op_write_buf(cl, (uint8_t*)&cl->write_op->csum, 8, true, from, done))
return done;
if (cl->ssl_want_write)
{
auto ssl_written = ssl_do_encrypt_to(cl, dst+done, dst_len-done);
if (!ssl_written)
return done;
done += ssl_written;
}
}
cl->write_op = NULL;
cl->write_op_pos = 0;
return done;
}
size_t osd_messenger_t::op_copy_to(osd_client_t *cl, uint8_t *dst, size_t dst_len)
{
if (cl->ssl_cli)
{
return ssl_op_copy_to(cl, dst, dst_len);
}
size_t done = 0;
size_t from = cl->write_op_pos;
auto op_write_buf = [&](uint8_t *src, size_t src_len, bool skip_csum)
{
return this->op_write_buf(cl, src, src_len, dst, dst_len, skip_csum, from, done);
};
// Header
if (!op_write_headers(cl->write_op, op_write_buf, cl->proto_csum_status != MSGR_CSUM_FULL))
if (!op_write_headers(cl->write_op, op_write_buf))
{
return done;
}
// Operation data
if (op_has_data(cl->write_op))
{
if (!op_copy_data_to(cl, dst, dst_len, from, done))
return done;
if (cl->write_op->enc)
{
if (!op_encrypted_copy_data_to(cl, dst, dst_len, from, done))
{
return done;
}
}
else
{
for (int i = 0; i < cl->write_op->iov.count; i++)
{
if (!op_write_buf((uint8_t*)cl->write_op->iov.buf[i].iov_base, cl->write_op->iov.buf[i].iov_len))
return done;
}
}
}
if (cl->proto_csum_status == MSGR_CSUM_FULL ||
cl->proto_csum_status == MSGR_CSUM_PAYLOAD && cl->write_op_pos > OSD_PACKET_SIZE)
if (cl->write_csum_state)
{
if (!from)
cl->write_op->csum = XXH3_64bits_digest(cl->write_csum_state);
@@ -627,31 +411,10 @@ size_t osd_messenger_t::op_copy_to(osd_client_t *cl, uint8_t *dst, size_t dst_le
return done;
}
bool osd_messenger_t::op_copy_data_to(osd_client_t *cl, uint8_t *dst, size_t dst_len, size_t & from, size_t & done)
{
if (cl->write_op->enc)
{
if (!op_encrypted_copy_data_to(cl, dst, dst_len, from, done))
{
return false;
}
}
else
{
for (int i = 0; i < cl->write_op->iov.count; i++)
{
auto & iov = cl->write_op->iov.buf[i];
if (!op_write_buf(cl, (uint8_t*)iov.iov_base, iov.iov_len, dst, dst_len, false, from, done))
return false;
}
}
return true;
}
void osd_messenger_t::op_get_write_buffers(osd_client_t *cl, std::vector<iovec> & lst)
{
size_t from = cl->write_op_pos;
auto op_write_buf = [&](uint8_t *src, size_t src_len, bool skip_csum)
auto op_write_buf = [&](uint8_t *src, size_t src_len, bool skip_csum = false)
{
if (lst.size() >= IOV_MAX)
return false;
@@ -667,8 +430,13 @@ void osd_messenger_t::op_get_write_buffers(osd_client_t *cl, std::vector<iovec>
from -= src_len;
return true;
};
// Header
if (!op_write_headers(cl->write_op, op_write_buf, cl->proto_csum_status != MSGR_CSUM_FULL))
if (cl->proto_csum_status == (MSGR_PEER_CSUM_IN|MSGR_PEER_CSUM_OUT) && !from)
{
if (!cl->write_csum_state)
cl->write_csum_state = XXH3_createState();
XXH3_64bits_reset(cl->write_csum_state);
}
if (!op_write_headers(cl->write_op, op_write_buf))
{
return;
}
@@ -694,13 +462,12 @@ void osd_messenger_t::op_get_write_buffers(osd_client_t *cl, std::vector<iovec>
{
for (int i = 0; i < cl->write_op->iov.count; i++)
{
if (!op_write_buf((uint8_t*)cl->write_op->iov.buf[i].iov_base, cl->write_op->iov.buf[i].iov_len, false))
if (!op_write_buf((uint8_t*)cl->write_op->iov.buf[i].iov_base, cl->write_op->iov.buf[i].iov_len))
return;
}
}
}
if (cl->proto_csum_status == MSGR_CSUM_FULL ||
cl->proto_csum_status == MSGR_CSUM_PAYLOAD && cl->write_op_pos > OSD_PACKET_SIZE)
if (cl->write_csum_state)
{
if (!from)
cl->write_op->csum = XXH3_64bits_digest(cl->write_csum_state);
@@ -710,89 +477,3 @@ void osd_messenger_t::op_get_write_buffers(osd_client_t *cl, std::vector<iovec>
cl->write_op = NULL;
cl->write_op_pos = 0;
}
void osd_messenger_t::ssl_op_get_write_buffers(osd_client_t *cl, std::vector<iovec> & lst)
{
size_t done = 0;
size_t from = cl->write_op_pos;
auto op_write_buf = [&](uint8_t *src, size_t src_len, bool skip_csum)
{
if (lst.size() >= IOV_MAX)
return false;
if (from < src_len)
{
if (cl->write_csum_state && !skip_csum)
XXH3_64bits_update(cl->write_csum_state, src+from, src_len-from);
lst.push_back((iovec){ .iov_base = src+from, .iov_len = src_len-from });
cl->write_op_pos += src_len-from;
from = 0;
}
else
from -= src_len;
return true;
};
// Encrypt headers and data except read/write data
auto to_ssl = [&](uint8_t *src, size_t src_len, bool skip_csum)
{
return ssl_op_write_buf(cl, src, src_len, skip_csum, from, done);
};
int i = 0;
bool full_hdr = false;
bool full_op = false;
do
{
if (!full_hdr)
full_hdr = op_write_headers(cl->write_op, to_ssl, cl->proto_csum_status != MSGR_CSUM_FULL);
if (full_hdr && op_has_data_for_ssl(cl->write_op))
{
for (; i < cl->write_op->iov.count; i++)
if (!ssl_op_write_buf(cl, (uint8_t*)cl->write_op->iov.buf[i].iov_base, cl->write_op->iov.buf[i].iov_len, false, from, done))
break;
full_op = true;
}
if (cl->peer_state == PEER_STOPPED)
return;
if (!ssl_do_encrypt(cl))
return;
} while (!full_op);
// Non-TLS-encrypted operation data
if (op_has_data_for_nonssl(cl->write_op))
{
if (cl->write_op->enc)
{
if (lst.size() >= IOV_MAX)
return;
// No way except to allocate a temporary buffer and encrypt data to it
assert(cl->write_op->req.hdr.opcode == OSD_OP_WRITE);
size_t remsize = cl->write_op->req.rw.len - from + (from % 16);
assert(remsize > 0);
assert(!cl->write_op->enc_buf);
cl->write_op->enc_buf = (uint8_t*)malloc_or_die(remsize);
size_t done = 0;
bool end = op_encrypted_copy_data_to(cl, cl->write_op->enc_buf, remsize, from, done);
assert(end);
lst.push_back((iovec){ .iov_base = cl->write_op->enc_buf, .iov_len = remsize });
}
else
{
for (int i = 0; i < cl->write_op->iov.count; i++)
{
if (!op_write_buf((uint8_t*)cl->write_op->iov.buf[i].iov_base, cl->write_op->iov.buf[i].iov_len, false))
return;
}
}
}
// TLS-encrypted checksum (uh oh...)
if (cl->proto_csum_status == MSGR_CSUM_FULL ||
cl->proto_csum_status == MSGR_CSUM_PAYLOAD && cl->write_op_pos > OSD_PACKET_SIZE)
{
if (!from)
cl->write_op->csum = XXH3_64bits_digest(cl->write_csum_state);
if (!ssl_op_write_buf(cl, (uint8_t*)&cl->write_op->csum, 8, true, from, done))
return;
if (!ssl_do_encrypt(cl))
return;
}
cl->write_op = NULL;
cl->write_op_pos = 0;
}
-20
View File
@@ -9,12 +9,6 @@
#ifdef WITH_RDMA
#include "msgr_rdma.h"
#endif
#ifdef WITH_OPENSSL
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/pem.h>
#include <openssl/ssl.h>
#endif
void osd_client_t::cancel_ops()
{
@@ -245,18 +239,4 @@ osd_client_t::~osd_client_t()
XXH3_freeState(write_csum_state);
write_csum_state = NULL;
}
#ifdef WITH_OPENSSL
if (ssl_cli)
{
SSL_free(ssl_cli);
ssl_cli = NULL;
write_to_ssl = NULL;
read_from_ssl = NULL;
}
if (ssl_out_buf)
{
free(ssl_out_buf);
ssl_out_buf = NULL;
}
#endif
}
+1 -1
View File
@@ -6,7 +6,7 @@ includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@
Name: Vitastor
Description: Vitastor client library
Version: 3.0.9
Version: 3.0.8
Libs: -L${libdir} -lvitastor_client
Cflags: -I${includedir}
+39
View File
@@ -8,6 +8,7 @@
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include "xxhash.h"
#include "addr_util.h"
#include "osd_primary.h"
#include "osd.h"
@@ -15,8 +16,46 @@
#include "str_util.h"
#include "json_util.h"
void xxhash_run_test(XXH3_state_t *st, void *buf, size_t size)
{
timespec tv, tv1;
clock_gettime(CLOCK_REALTIME, &tv);
uint64_t res = 1;
uint64_t done = 0;
while (true)
{
XXH3_64bits_reset(st);
XXH3_64bits_update(st, buf, size);
res *= XXH3_64bits_digest(st);
done++;
if (!(done % 100000))
{
clock_gettime(CLOCK_REALTIME, &tv1);
if ((tv1.tv_sec-tv.tv_sec)*1000 + (tv1.tv_nsec-tv.tv_nsec)/1000000 > 1000)
break;
}
}
double sec = (tv1.tv_sec-tv.tv_sec) + (tv1.tv_nsec-tv.tv_nsec)/1000000000.0;
fprintf(stderr, "xxhash3: %lu %zu byte blocks in %.2f sec = %.1f MB/s\n",
done, size, sec, done*size/sec/1024/1024);
}
void xxhash_bench()
{
std::vector<uint8_t> buf;
buf.resize(128*1024);
for (size_t i = 0; i < buf.size(); i++)
buf[i] = ((i+37)*3) % 255;
XXH3_state_t *st = XXH3_createState();
xxhash_run_test(st, buf.data(), 4096);
xxhash_run_test(st, buf.data(), buf.size());
XXH3_freeState(st);
}
osd_t::osd_t(const json11::Json & config, ring_loop_t *ringloop)
{
xxhash_bench();
zero_buffer_size = 1<<20;
zero_buffer = malloc_or_die(zero_buffer_size);
memset(zero_buffer, 0, zero_buffer_size);
+3 -10
View File
@@ -348,17 +348,10 @@ void osd_t::exec_show_config(osd_op_t *cur_op)
cl->read_op_id = cur_op->req.hdr.id + 1;
}
auto features = json11::Json::object{ { "pg_locks", true } };
if (msgr.use_proto_checksums)
if (req_json["features"]["proto_checksums"].bool_value() && msgr.use_proto_checksums)
{
auto peer_csums = req_json["features"]["proto_checksums"].uint64_value();
if (peer_csums == MSGR_CSUM_FULL || peer_csums == MSGR_CSUM_PAYLOAD)
{
if (msgr.use_proto_checksums == MSGR_CSUM_FULL && peer_csums == MSGR_CSUM_FULL)
cl->proto_csum_status = MSGR_CSUM_FULL|MSGR_CSUM_NEG;
else
cl->proto_csum_status = MSGR_CSUM_PAYLOAD|MSGR_CSUM_NEG;
features["proto_checksums"] = msgr.use_proto_checksums;
}
cl->proto_csum_status = MSGR_PEER_CSUM_IN;
features["proto_checksums"] = true;
}
// Expose sensitive configuration values so peers can check them
json11::Json::object wire_config = json11::Json::object {
+1 -9
View File
@@ -41,7 +41,7 @@ add_executable(test_heap
../blockstore/multilist.cpp
../blockstore/blockstore_heap.cpp
../util/crc32c.c
../util/xxh_x86dispatch.c
../util/xxhash.c
../util/allocator.cpp
../blockstore/blockstore_disk.cpp
../util/str_util.cpp
@@ -62,14 +62,6 @@ target_link_libraries(test_cas
vitastor_client
)
# http_hello
add_executable(http_hello
http_hello.cpp
)
target_link_libraries(http_hello
vitastor_client
)
# test_crc32
add_executable(test_crc32
test_crc32.cpp
-61
View File
@@ -1,61 +0,0 @@
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <stdlib.h>
#include <stdexcept>
#include "http_client.h"
#include "ringloop.h"
#include "epoll_manager.h"
#include "addr_util.h"
int main(int narg, char *args[])
{
ring_consumer_t looper;
ring_loop_t *ringloop = new ring_loop_t(RINGLOOP_DEFAULT_SIZE);
epoll_manager_t *epmgr = new epoll_manager_t(ringloop);
// Accept new connections
int listen_fd = create_and_bind_socket("0.0.0.0", 8085, 128, NULL);
fcntl(listen_fd, F_SETFL, fcntl(listen_fd, F_GETFL, 0) | O_NONBLOCK);
std::string error;
auto http_ctx = http_context_init(epmgr->tfd, "", "", "", false, error);
epmgr->set_fd_handler(listen_fd, false, [http_ctx](int listen_fd, int events)
{
sockaddr_storage addr;
socklen_t peer_addr_size = sizeof(addr);
int peer_fd;
while ((peer_fd = accept(listen_fd, (sockaddr*)&addr, &peer_addr_size)) >= 0)
{
assert(peer_fd != 0);
fcntl(peer_fd, F_SETFL, fcntl(peer_fd, F_GETFL, 0) | O_NONBLOCK);
int one = 1;
setsockopt(peer_fd, SOL_TCP, TCP_NODELAY, &one, sizeof(one));
auto co = http_init(http_ctx);
http_serve(co, peer_fd, (http_options_t){}, [co](http_message_t *msg)
{
if (msg->eof)
{
http_destroy(co);
return;
}
http_reply(co, "HTTP/1.1 200 OK\r\nConnection: keep-alive\r\nContent-Length: 13\r\n\r\nHello, world!");
});
}
});
while (true)
{
ringloop->loop();
ringloop->wait();
}
delete epmgr;
delete ringloop;
return 0;
}