libceph: introduce connection modes and ms_mode option
authorIlya Dryomov <idryomov@gmail.com>
Thu, 19 Nov 2020 15:04:58 +0000 (16:04 +0100)
committerIlya Dryomov <idryomov@gmail.com>
Mon, 14 Dec 2020 22:21:50 +0000 (23:21 +0100)
msgr2 supports two connection modes: crc (plain) and secure (on-wire
encryption).  Connection mode is picked by server based on input from
client.

Introduce ms_mode option:

  ms_mode=legacy        - msgr1 (default)
  ms_mode=crc           - crc mode, if denied fail
  ms_mode=secure        - secure mode, if denied fail
  ms_mode=prefer-crc    - crc mode, if denied agree to secure mode
  ms_mode=prefer-secure - secure mode, if denied agree to crc mode

ms_mode affects all connections, we don't separate connections to mons
like it's done in userspace with ms_client_mode vs ms_mon_client_mode.

For now the default is legacy, to be flipped to prefer-crc after some
time.

Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
include/linux/ceph/auth.h
include/linux/ceph/ceph_fs.h
include/linux/ceph/libceph.h
net/ceph/auth.c
net/ceph/ceph_common.c
net/ceph/ceph_strings.c
net/ceph/mon_client.c

index 5f64f66309fa24a4e8e2d503c35404b1a1a8b716..6fc058fe9efa5543c3eb6c5043fa842962c44c36 100644 (file)
@@ -98,11 +98,15 @@ struct ceph_auth_client {
        const struct ceph_crypto_key *key;     /* our secret key */
        unsigned want_keys;     /* which services we want */
 
+       int preferred_mode;     /* CEPH_CON_MODE_* */
+       int fallback_mode;      /* ditto */
+
        struct mutex mutex;
 };
 
-extern struct ceph_auth_client *ceph_auth_init(const char *name,
-                                              const struct ceph_crypto_key *key);
+struct ceph_auth_client *ceph_auth_init(const char *name,
+                                       const struct ceph_crypto_key *key,
+                                       const int *con_modes);
 extern void ceph_auth_destroy(struct ceph_auth_client *ac);
 
 extern void ceph_auth_reset(struct ceph_auth_client *ac);
index 6d986e52000b1776517f06e4d31811eaf3c4cbd0..ce22d546967011fadad19b8e49af9e189792e3f9 100644 (file)
@@ -93,9 +93,15 @@ struct ceph_dir_layout {
 #define CEPH_AUTH_NONE         0x1
 #define CEPH_AUTH_CEPHX                0x2
 
+/* msgr2 protocol modes */
+#define CEPH_CON_MODE_UNKNOWN  0x0
+#define CEPH_CON_MODE_CRC      0x1
+#define CEPH_CON_MODE_SECURE   0x2
+
 #define CEPH_AUTH_UID_DEFAULT ((__u64) -1)
 
 const char *ceph_auth_proto_name(int proto);
+const char *ceph_con_mode_name(int mode);
 
 /*********************************************
  * message layer
index eb5a7ca13f9c5e93521211c4f324256ffff991b9..8765a5ad267a96e1c4d206d95edc978055b16122 100644 (file)
@@ -53,6 +53,7 @@ struct ceph_options {
        unsigned long osd_keepalive_timeout;    /* jiffies */
        unsigned long osd_request_timeout;      /* jiffies */
        u32 read_from_replica;  /* CEPH_OSD_FLAG_BALANCE/LOCALIZE_READS */
+       int con_modes[2];  /* CEPH_CON_MODE_* */
 
        /*
         * any type that can't be simply compared or doesn't need
index deaf267f894275fc08d79a191c2e7d200b24096c..4a0f32b32cc6af8c3166546e9f76a362664bd5e1 100644 (file)
@@ -39,13 +39,13 @@ static int init_protocol(struct ceph_auth_client *ac, int proto)
 /*
  * setup, teardown.
  */
-struct ceph_auth_client *ceph_auth_init(const char *name, const struct ceph_crypto_key *key)
+struct ceph_auth_client *ceph_auth_init(const char *name,
+                                       const struct ceph_crypto_key *key,
+                                       const int *con_modes)
 {
        struct ceph_auth_client *ac;
        int ret;
 
-       dout("auth_init name '%s'\n", name);
-
        ret = -ENOMEM;
        ac = kzalloc(sizeof(*ac), GFP_NOFS);
        if (!ac)
@@ -57,8 +57,12 @@ struct ceph_auth_client *ceph_auth_init(const char *name, const struct ceph_cryp
                ac->name = name;
        else
                ac->name = CEPH_AUTH_NAME_DEFAULT;
-       dout("auth_init name %s\n", ac->name);
        ac->key = key;
+       ac->preferred_mode = con_modes[0];
+       ac->fallback_mode = con_modes[1];
+
+       dout("%s name '%s' preferred_mode %d fallback_mode %d\n", __func__,
+            ac->name, ac->preferred_mode, ac->fallback_mode);
        return ac;
 
 out:
index 4e7edd707a14b9e6b21579c1a445971ecb992b0e..271287c5ec12d5fb7130e1e9da179bc34ae0bac9 100644 (file)
@@ -265,6 +265,7 @@ enum {
        Opt_ip,
        Opt_crush_location,
        Opt_read_from_replica,
+       Opt_ms_mode,
        /* string args above */
        Opt_share,
        Opt_crc,
@@ -287,6 +288,23 @@ static const struct constant_table ceph_param_read_from_replica[] = {
        {}
 };
 
+enum ceph_ms_mode {
+       Opt_ms_mode_legacy,
+       Opt_ms_mode_crc,
+       Opt_ms_mode_secure,
+       Opt_ms_mode_prefer_crc,
+       Opt_ms_mode_prefer_secure
+};
+
+static const struct constant_table ceph_param_ms_mode[] = {
+       {"legacy",              Opt_ms_mode_legacy},
+       {"crc",                 Opt_ms_mode_crc},
+       {"secure",              Opt_ms_mode_secure},
+       {"prefer-crc",          Opt_ms_mode_prefer_crc},
+       {"prefer-secure",       Opt_ms_mode_prefer_secure},
+       {}
+};
+
 static const struct fs_parameter_spec ceph_parameters[] = {
        fsparam_flag    ("abort_on_full",               Opt_abort_on_full),
        fsparam_flag_no ("cephx_require_signatures",    Opt_cephx_require_signatures),
@@ -305,6 +323,8 @@ static const struct fs_parameter_spec ceph_parameters[] = {
                         fs_param_deprecated, NULL),
        fsparam_enum    ("read_from_replica",           Opt_read_from_replica,
                         ceph_param_read_from_replica),
+       fsparam_enum    ("ms_mode",                     Opt_ms_mode,
+                        ceph_param_ms_mode),
        fsparam_string  ("secret",                      Opt_secret),
        fsparam_flag_no ("share",                       Opt_share),
        fsparam_flag_no ("tcp_nodelay",                 Opt_tcp_nodelay),
@@ -333,6 +353,8 @@ struct ceph_options *ceph_alloc_options(void)
        opt->osd_idle_ttl = CEPH_OSD_IDLE_TTL_DEFAULT;
        opt->osd_request_timeout = CEPH_OSD_REQUEST_TIMEOUT_DEFAULT;
        opt->read_from_replica = CEPH_READ_FROM_REPLICA_DEFAULT;
+       opt->con_modes[0] = CEPH_CON_MODE_UNKNOWN;
+       opt->con_modes[1] = CEPH_CON_MODE_UNKNOWN;
        return opt;
 }
 EXPORT_SYMBOL(ceph_alloc_options);
@@ -503,6 +525,32 @@ int ceph_parse_param(struct fs_parameter *param, struct ceph_options *opt,
                        BUG();
                }
                break;
+       case Opt_ms_mode:
+               switch (result.uint_32) {
+               case Opt_ms_mode_legacy:
+                       opt->con_modes[0] = CEPH_CON_MODE_UNKNOWN;
+                       opt->con_modes[1] = CEPH_CON_MODE_UNKNOWN;
+                       break;
+               case Opt_ms_mode_crc:
+                       opt->con_modes[0] = CEPH_CON_MODE_CRC;
+                       opt->con_modes[1] = CEPH_CON_MODE_UNKNOWN;
+                       break;
+               case Opt_ms_mode_secure:
+                       opt->con_modes[0] = CEPH_CON_MODE_SECURE;
+                       opt->con_modes[1] = CEPH_CON_MODE_UNKNOWN;
+                       break;
+               case Opt_ms_mode_prefer_crc:
+                       opt->con_modes[0] = CEPH_CON_MODE_CRC;
+                       opt->con_modes[1] = CEPH_CON_MODE_SECURE;
+                       break;
+               case Opt_ms_mode_prefer_secure:
+                       opt->con_modes[0] = CEPH_CON_MODE_SECURE;
+                       opt->con_modes[1] = CEPH_CON_MODE_CRC;
+                       break;
+               default:
+                       BUG();
+               }
+               break;
 
        case Opt_osdtimeout:
                warn_plog(&log, "Ignoring osdtimeout");
@@ -616,6 +664,21 @@ int ceph_print_client_options(struct seq_file *m, struct ceph_client *client,
        } else if (opt->read_from_replica == CEPH_OSD_FLAG_LOCALIZE_READS) {
                seq_puts(m, "read_from_replica=localize,");
        }
+       if (opt->con_modes[0] != CEPH_CON_MODE_UNKNOWN) {
+               if (opt->con_modes[0] == CEPH_CON_MODE_CRC &&
+                   opt->con_modes[1] == CEPH_CON_MODE_UNKNOWN) {
+                       seq_puts(m, "ms_mode=crc,");
+               } else if (opt->con_modes[0] == CEPH_CON_MODE_SECURE &&
+                          opt->con_modes[1] == CEPH_CON_MODE_UNKNOWN) {
+                       seq_puts(m, "ms_mode=secure,");
+               } else if (opt->con_modes[0] == CEPH_CON_MODE_CRC &&
+                          opt->con_modes[1] == CEPH_CON_MODE_SECURE) {
+                       seq_puts(m, "ms_mode=prefer-crc,");
+               } else if (opt->con_modes[0] == CEPH_CON_MODE_SECURE &&
+                          opt->con_modes[1] == CEPH_CON_MODE_CRC) {
+                       seq_puts(m, "ms_mode=prefer-secure,");
+               }
+       }
 
        if (opt->flags & CEPH_OPT_FSID)
                seq_printf(m, "fsid=%pU,", &opt->fsid);
index 69cd391e02a6e8dec286385b7996da230b84bd90..355fea2721205c6b8818c77d945e375596397f44 100644 (file)
@@ -32,6 +32,20 @@ const char *ceph_auth_proto_name(int proto)
        }
 }
 
+const char *ceph_con_mode_name(int mode)
+{
+       switch (mode) {
+       case CEPH_CON_MODE_UNKNOWN:
+               return "unknown";
+       case CEPH_CON_MODE_CRC:
+               return "crc";
+       case CEPH_CON_MODE_SECURE:
+               return "secure";
+       default:
+               return "???";
+       }
+}
+
 const char *ceph_osd_op_name(int op)
 {
        switch (op) {
index f5f090b4e4090bdc4eb30015cac64b6da686541a..792a8c4164d73e44543b8a62e5d0a20ff86e5d61 100644 (file)
@@ -1156,8 +1156,8 @@ int ceph_monc_init(struct ceph_mon_client *monc, struct ceph_client *cl)
 
        /* connection */
        /* authentication */
-       monc->auth = ceph_auth_init(cl->options->name,
-                                   cl->options->key);
+       monc->auth = ceph_auth_init(cl->options->name, cl->options->key,
+                                   cl->options->con_modes);
        if (IS_ERR(monc->auth)) {
                err = PTR_ERR(monc->auth);
                goto out_monmap;