]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
libcephfs_proxy: add protocol version negotiation
authorXavi Hernandez <xhernandez@gmail.com>
Sat, 26 Jul 2025 18:10:42 +0000 (20:10 +0200)
committerAnoop C S <anoopcs@cryptolab.net>
Fri, 15 Aug 2025 09:52:22 +0000 (15:22 +0530)
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 <xhernandez@gmail.com>
(cherry picked from commit 52fba7af44cb19be77bc28b9b95d52c78121c19b)

src/libcephfs_proxy/libcephfs_proxy.c
src/libcephfs_proxy/libcephfsd.c
src/libcephfs_proxy/proxy_link.c
src/libcephfs_proxy/proxy_link.h

index 620f9d483b6dfbb9b08ed595af5e8ff56a7aedfd..907161213a83742dd58f73d04644715de9f8076a 100644 (file)
@@ -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,
index a792d86cbd3995722fbac19a1df551370e4c5bde..cc5a538fa73dfef4e453d66f76015ee6abd3088a 100644 (file)
@@ -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,
index bc8885836b5238d5348fba0694451ba5d74dee27..3dbad3de67cebe2e8a3dc96be3301ac5a5d881aa 100644 (file)
@@ -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. */
 
index e4513b001309a2a0aaacea8680a3036c4c1651a3..ec7dbc2ecdab0652c49f4bbe305eeb9a61dcb964 100644 (file)
  * 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)