From f89b6bf3f5221fcb2aa7feb36a84d0a29f520733 Mon Sep 17 00:00:00 2001 From: Xavi Hernandez Date: Sat, 26 Jul 2025 20:10:42 +0200 Subject: [PATCH] libcephfs_proxy: add protocol version negotiation A new negotiation option has been introduced which will be used to decide which protocol version to use between client and server. Signed-off-by: Xavi Hernandez (cherry picked from commit 52fba7af44cb19be77bc28b9b95d52c78121c19b) --- src/libcephfs_proxy/libcephfs_proxy.c | 8 +++-- src/libcephfs_proxy/libcephfsd.c | 6 ++-- src/libcephfs_proxy/proxy_link.c | 43 ++++++++++++++++++++++++++- src/libcephfs_proxy/proxy_link.h | 19 ++++++++++-- 4 files changed, 68 insertions(+), 8 deletions(-) diff --git a/src/libcephfs_proxy/libcephfs_proxy.c b/src/libcephfs_proxy/libcephfs_proxy.c index 620f9d483b6..907161213a8 100644 --- a/src/libcephfs_proxy/libcephfs_proxy.c +++ b/src/libcephfs_proxy/libcephfs_proxy.c @@ -33,7 +33,8 @@ static bool client_stop(proxy_link_t *link) static int32_t proxy_negotiation_check(proxy_link_negotiate_t *neg) { - proxy_log(LOG_INFO, 0, "Features enabled: %08x", neg->v1.enabled); + proxy_log(LOG_INFO, 0, "Features enabled: %08x, protocol: %u", + neg->v1.enabled, neg->v2.protocol); return 0; } @@ -75,7 +76,7 @@ static int32_t proxy_global_connect(void) } proxy_link_negotiate_init(&global_cmount.neg, 0, PROXY_FEAT_ALL, - 0, 0); + 0, 0, PROXY_LINK_PROTOCOL_VERSION); err = proxy_link_handshake_client(&global_cmount.link, err, &global_cmount.neg, @@ -181,7 +182,8 @@ __public int ceph_create(struct ceph_mount_info **cmount, const char *const id) sd = err; proxy_link_negotiate_init(&ceph_mount->neg, 0, PROXY_FEAT_ALL, 0, - PROXY_FEAT_ASYNC_IO); + PROXY_FEAT_ASYNC_IO, + PROXY_LINK_PROTOCOL_VERSION); err = proxy_link_handshake_client(&ceph_mount->link, sd, &ceph_mount->neg, diff --git a/src/libcephfs_proxy/libcephfsd.c b/src/libcephfs_proxy/libcephfsd.c index a792d86cbd3..cc5a538fa73 100644 --- a/src/libcephfs_proxy/libcephfsd.c +++ b/src/libcephfs_proxy/libcephfsd.c @@ -1736,7 +1736,8 @@ static void serve_binary(proxy_client_t *client) static int32_t server_negotiation_check(proxy_link_negotiate_t *neg) { - proxy_log(LOG_INFO, 0, "Features enabled: %08x", neg->v1.enabled); + proxy_log(LOG_INFO, 0, "Features enabled: %08x, protocol: %u", + neg->v1.enabled, neg->v2.protocol); return 0; } @@ -1748,7 +1749,8 @@ static void serve_connection(proxy_worker_t *worker) client = container_of(worker, proxy_client_t, worker); - proxy_link_negotiate_init(&client->neg, 0, PROXY_FEAT_ALL, 0, 0); + proxy_link_negotiate_init(&client->neg, 0, PROXY_FEAT_ALL, 0, 0, + PROXY_LINK_PROTOCOL_VERSION); err = proxy_link_handshake_server(client->link, client->sd, &client->neg, diff --git a/src/libcephfs_proxy/proxy_link.c b/src/libcephfs_proxy/proxy_link.c index bc8885836b5..3dbad3de67c 100644 --- a/src/libcephfs_proxy/proxy_link.c +++ b/src/libcephfs_proxy/proxy_link.c @@ -16,7 +16,8 @@ typedef struct _proxy_version { #define DEFINE_VERSION(_num) [_num] = NEG_VERSION_SIZE(_num) static uint32_t negotiation_sizes[PROXY_LINK_NEGOTIATE_VERSION + 1] = { - DEFINE_VERSION(1) + DEFINE_VERSION(1), + DEFINE_VERSION(2) /* NEG_VERSION: Add newly defined versions above this comment. */ }; @@ -323,11 +324,18 @@ static int32_t proxy_link_negotiate_check(proxy_link_negotiate_t *local, "features"); } + /* NEG_VERSION: Check if there's any incompatibility with new + * extensions that are not supported by an old + * peer. */ + /* The peer is running the old version, but it is compatible * with us, so everything is fine and the connection can be * completed successfully with all features disabled. */ local->v1.enabled = 0; + local->v2.protocol = 0; + + /* NEG_VERSION: Initialize default values for new extensions. */ proxy_log(LOG_INFO, 0, "Connected to legacy peer. No features enabled"); @@ -356,6 +364,10 @@ static int32_t proxy_link_negotiate_check(proxy_link_negotiate_t *local, enabled = (local->v1.enabled | remote->v1.enabled) & supported; local->v1.enabled = enabled; + if (local->v2.protocol > remote->v2.protocol) { + local->v2.protocol = remote->v2.protocol; + } + /* NEG_VERSION: Implement handling of negotiate extensions. */ validate: @@ -402,6 +414,20 @@ static int32_t proxy_link_negotiate_client(proxy_link_t *link, int32_t sd, return err; } + if (remote.v0.version == 1) { + return 0; + } + + /* For version 2 and higher, send the agreed protocol. */ + err = proxy_link_write(link, sd, &neg->v2.protocol, + sizeof(neg->v2.protocol)); + if (err < 0) { + return err; + } + + /* NEG_VERSION: Send any extension related information to the server. + * Make the changes above this line. */ + return 0; } @@ -448,6 +474,21 @@ static int32_t proxy_link_negotiate_server(proxy_link_t *link, int32_t sd, } } + if (remote.v0.version > 1) { + /* Read the agreed protocol version. */ + err = proxy_link_read(link, sd, &neg->v2.protocol, + sizeof(neg->v2.protocol)); + if (err < 0) { + return err; + } + + if (neg->v2.protocol > PROXY_LINK_PROTOCOL_VERSION) { + return proxy_log(LOG_ERR, EINVAL, + "The client tried to use an " + "unsupported protocol"); + } + } + /* NEG_VERSION: Implement any required handling for new negotiate * extensions. */ diff --git a/src/libcephfs_proxy/proxy_link.h b/src/libcephfs_proxy/proxy_link.h index e4513b00130..ec7dbc2ecda 100644 --- a/src/libcephfs_proxy/proxy_link.h +++ b/src/libcephfs_proxy/proxy_link.h @@ -13,7 +13,13 @@ * starting with "NEG_VERSION" and do the appropriate changes in each place. */ /* NEG_VERSION: Update this value to the latest implemented version. */ -#define PROXY_LINK_NEGOTIATE_VERSION 1 +#define PROXY_LINK_NEGOTIATE_VERSION 2 + +/* Known versions for communication protocol. */ +#define PROXY_PROTOCOL_V0 0 + +/* The maximum supported protocol version. */ +#define PROXY_LINK_PROTOCOL_VERSION PROXY_PROTOCOL_V0 /* Version 0 structure will be used to handle legacy clients that don't support * negotiation. */ @@ -38,11 +44,16 @@ typedef struct _proxy_link_negotiate_v1 { uint32_t enabled; } proxy_link_negotiate_v1_t; +typedef struct _proxy_link_negotiate_v2 { + uint32_t protocol; +} proxy_link_negotiate_v2_t; + /* NEG_VERSION: Add typedefs for new negotiate extensions above this comment. */ struct _proxy_link_negotiate { proxy_link_negotiate_v0_t v0; proxy_link_negotiate_v1_t v1; + proxy_link_negotiate_v2_t v2; /* NEG_VERSION: Add newly defined typedefs above this comment. */ }; @@ -85,13 +96,17 @@ static inline void proxy_link_negotiate_init(proxy_link_negotiate_t *neg, uint32_t min_version, uint32_t supported, uint32_t required, - uint32_t enabled) + uint32_t enabled, + uint32_t protocol) { proxy_link_negotiate_init_v0(neg, PROXY_LINK_NEGOTIATE_VERSION, min_version); + neg->v1.supported = supported; neg->v1.required = required; neg->v1.enabled = enabled; + + neg->v2.protocol = protocol; } static inline bool proxy_link_is_connected(proxy_link_t *link) -- 2.39.5