From 63014195091532430a4155d3b2cd72b3a1b02dee Mon Sep 17 00:00:00 2001 From: Maximilian Dilger Date: Thu, 11 Jul 2024 15:07:17 -0400 Subject: [PATCH] LU-17367 utils: improved hostname and IPv6 NID support Improved NID parsing to accept hostnames, IPv4 and IPv6 addresses. IPv6 addresses need @network to be parsed properly. The following is a valid IPv6 address: "6699:7654::1234:1234:d84@tcp" All other non IPv6 addresses can be passed in without a network identifier. Signed-off-by: Maximilian Dilger Change-Id: I131c8b2d1f7b0fe593564af90308d2d3ea278a0c Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/55706 Tested-by: jenkins Tested-by: Maloo Reviewed-by: James Simmons Reviewed-by: Oleg Drokin Reviewed-by: Andreas Dilger Reviewed-by: Mikhail Pershin --- lustre/tests/conf-sanity.sh | 77 ++++++++++++++++++++++++++++++++++++++ lustre/utils/mount_utils.c | 91 +++++++++++++++++++++++++++++---------------- lustre/utils/mount_utils.h | 2 +- 3 files changed, 137 insertions(+), 33 deletions(-) diff --git a/lustre/tests/conf-sanity.sh b/lustre/tests/conf-sanity.sh index 76036ce..fd4bd67 100755 --- a/lustre/tests/conf-sanity.sh +++ b/lustre/tests/conf-sanity.sh @@ -11216,6 +11216,83 @@ test_153a() { } run_test 153a "bypass invalid NIDs quickly" +#LU-17367 +test_153b() { + reformat_and_config + setupall + + local IPv6_1="6699:7654::1234:1234:d84@tcp" + local IPv6_2="2001:0db8:85a3:0000:0000:8a2e:0370:7334@tcp" + local IPv6_3="5031:db8:85a3:8d3:1319:8a2e:370:7348@tcp" + local IPv4_1="127.0.0.5" + local IPv4_2="193.168.0.240@tcp" + local IPv4_3="162.32.0.100" + + local mgslist + + umount $MOUNT + + mgslist="$IPv6_1:$mgs_HOST" + mount -t lustre $mgslist:/$FSNAME $MOUNT || + error "mount failed with $mgslist:/$FSNAME $MOUNT" + umount $MOUNT + + mgslist="$mgs_HOST:$mgs_HOST:$mgs_HOST" + mount -t lustre $mgslist:/$FSNAME $MOUNT || + error "mount failed with $mgslist:/$FSNAME $MOUNT" + umount $MOUNT + + mgslist="$mgs_HOST:$IPv6_1" + mount -t lustre $mgslist:/$FSNAME $MOUNT || + error "mount failed with $mgslist:/$FSNAME $MOUNT" + umount $MOUNT + + mgslist="$mgs_HOST:$IPv4_1" + mount -t lustre $mgslist:/$FSNAME $MOUNT || + error "mount failed with $mgslist:/$FSNAME $MOUNT" + umount $MOUNT + + mgslist="$IPv4_1:$mgs_HOST" + mount -t lustre $mgslist:/$FSNAME $MOUNT || + error "mount failed with $mgslist:/$FSNAME $MOUNT" + umount $MOUNT + + mgslist="$IPv4_2:$IPv4_1:$mgs_HOST" + mount -t lustre $mgslist:/$FSNAME $MOUNT || + error "mount failed with $mgslist:/$FSNAME $MOUNT" + umount $MOUNT + + mgslist="$IPv6_1,$IPv4_2,$IPv4_1:$mgs_HOST" + mount -t lustre $mgslist:/$FSNAME $MOUNT || + error "mount failed with $mgslist:/$FSNAME $MOUNT" + umount $MOUNT + + mgslist="$IPv4_1:$IPv4_1:$IPv4_1:$IPv4_1:$IPv4_1\ +:$IPv4_1:$IPv4_1:$IPv4_1:$IPv4_1:$IPv4_1:$IPv4_1\ +:$IPv4_1:$IPv4_1:$IPv4_1:$IPv4_1:$IPv4_1:$IPv4_1\ +:$IPv4_1:$IPv4_1:$IPv4_1:$IPv4_1:$IPv4_1:$IPv4_1\ +:$IPv4_1:$IPv4_1:$IPv4_1:$IPv4_1:$IPv4_1:$IPv4_1\ +:$IPv4_1:$IPv4_1:$mgs_HOST" + mount -t lustre $mgslist:/$FSNAME $MOUNT || + error "mount failed with $mgslist:/$FSNAME $MOUNT" + umount $MOUNT + + mgslist="$IPv6_1,$IPv4_2,$IPv4_1:$IPv6_3,$IPv4_3,$IPv6_2:$mgs_HOST" + mount -t lustre $mgslist:/$FSNAME $MOUNT || + error "mount failed with $mgslist:/$FSNAME $MOUNT" + umount $MOUNT + + mgslist="$IPv4_2,$IPv6_1,$IPv4_2,$IPv4_1:$IPv6_3,$IPv4_3:$IPv6_2\ +,$IPv6_1,$IPv4_2,$IPv4_1:$IPv6_3,$IPv4_3:$IPv6_2,$IPv6_1,$IPv4_2\ +,$IPv4_1:$IPv6_3,$IPv4_3:$IPv6_2,$IPv6_1,$IPv4_2,$IPv4_1:$IPv6_3\ +,$IPv4_3:$IPv6_2,$IPv6_1,$IPv4_2,$IPv4_1:$IPv6_3,$IPv4_3:$IPv6_2\ +:$mgs_HOST" + mount -t lustre $mgslist:/$FSNAME $MOUNT || + error "mount failed with $mgslist:/$FSNAME $MOUNT" + umount $MOUNT +} +run_test 153b "added IPv6 NID support" + test_154() { [ "$mds1_FSTYPE" == "ldiskfs" ] || skip "ldiskfs only test" (( $MDS1_VERSION >= $(version_code 2.15.63.1) )) || diff --git a/lustre/utils/mount_utils.c b/lustre/utils/mount_utils.c index 89842be..cbe2c5f 100644 --- a/lustre/utils/mount_utils.c +++ b/lustre/utils/mount_utils.c @@ -948,11 +948,15 @@ int file_create(char *path, __u64 size) /* Get rid of symbolic hostnames for tcp, since kernel can't do lookups */ #define MAXNIDSTR 1024 -char *convert_hostnames(char *s1, bool mount) +char *convert_hostnames(char *buf, bool mount) { - char *converted, *s2 = 0, *c, *end, sep; + char *converted, *c, *end, sep; + char *delimiter = buf; int left = MAXNIDSTR; struct lnet_nid nid; + int hex_count = 0; + int hex_sections = 0; + bool is_ipv6 = true; converted = malloc(left); if (!converted) { @@ -963,53 +967,75 @@ char *convert_hostnames(char *s1, bool mount) /* end is different between mount and mkfs case */ if (mount) { - end = strchr(s1, '/'); + end = strchr(buf, '/'); if (!end) { fprintf(stderr, "%s: Invalid mount string: %s\n", - progname, s1); + progname, buf); goto out_bad_mnt_str; } end--; } else { - end = s1 + strlen(s1); + end = buf + strlen(buf); } c = converted; - while ((left > 0) && (s1 < end)) { + /* parse all NIDs */ + while ((left > 0) && (delimiter < end)) { int rc; + hex_count = 0; + hex_sections = 0; + is_ipv6 = true; + + /* previous delimiter */ + if (*delimiter == ',' || *delimiter == ':') + delimiter++; + + /* address parsing */ + while (*delimiter != ',' && *delimiter != ' ' && *delimiter != '\0') { + /* Need to skip : in IPv6 / GUID NIDs. Lustre also uses + * ':' as a separator, which makes this complicated. + */ + if (*delimiter == '@') { + while (*delimiter != ':' && *delimiter != ',' + && *delimiter != ' ' && *delimiter != '\0') + delimiter++; + break; + } + /* IPv6 addresses are in 0-4 hex digit groups */ + else if ((isxdigit(*delimiter) || *delimiter == ':') && + hex_count <= 4 && is_ipv6) { + if (*delimiter == ':') { + hex_sections++; + hex_count = 0; + } else { + hex_count++; + } + } else { /* NID is not IPv6 */ + is_ipv6 = false; + if (*delimiter == ':') + break; - /* Needed to skip : in IPv6 / GUID strings. Lustre uses - * ':' as a seperator as well which makes this complicated. - */ - s2 = strchr(s1, '@'); - if (!s2 || s2 > end) { - fprintf(stderr, "%s: Invalid NID string '%s'\n", - progname, s1); - goto out_free; - } - - s2 = strpbrk(s2, ",:"); - if (!s2) { - s2 = end; - } else if (s2 > end) { - fprintf(stderr, "%s: Invalid NID string '%s'\n", - progname, s1); - goto out_free; + } + delimiter++; } - sep = *s2; - *s2 = '\0'; + /* sets the position of the found delimiter to null + * temporarily so when we pass it into parse_nid + * or parse_net it only uses the found NID + */ + sep = *delimiter; + *delimiter = '\0'; - rc = libcfs_strnid(&nid, s1); + rc = libcfs_strnid(&nid, buf); if (rc < 0) { fprintf(stderr, "%s: Unsupported NID '%s': rc = %s.\n", - progname, s1, strerror(rc)); + progname, buf, strerror(rc)); goto out_free; } - *s2 = sep; /* back to original string */ + *delimiter = sep; /* back to original string */ if (LNET_NID_IS_ANY(&nid)) { fprintf(stderr, "%s: Cannot resolve hostname '%s'.\n", - progname, s1); + progname, buf); goto out_free; } @@ -1018,16 +1044,17 @@ char *convert_hostnames(char *s1, bool mount) sep); else c += scnprintf(c, left, "%s", libcfs_nidstr(&nid)); + left = converted + MAXNIDSTR - c; - s1 = s2 + 1; + buf = delimiter + 1; } if (mount) - snprintf(c, left, "%s", s1); + snprintf(c, left, "%s", buf); return converted; out_free: - fprintf(stderr, "%s: Can't parse NID '%s'\n", progname, s1); + fprintf(stderr, "%s: Can't parse NID '%s'\n", progname, buf); out_bad_mnt_str: free(converted); return NULL; diff --git a/lustre/utils/mount_utils.h b/lustre/utils/mount_utils.h index c51cf1f..a1d2173 100644 --- a/lustre/utils/mount_utils.h +++ b/lustre/utils/mount_utils.h @@ -178,7 +178,7 @@ int update_mtab_entry(char *spec, char *mtpt, char *type, char *opts, int update_utab_entry(struct mount_opts *mop); int check_mountfsoptions(char *mountopts, char *wanted_mountopts); void trim_mountfsoptions(char *s); -char *convert_hostnames(char *s1, bool mount); +char *convert_hostnames(char *buf, bool mount); #ifdef HAVE_SERVER_SUPPORT __u64 get_device_size(char* device); int lustre_rename_fsname(struct mkfs_opts *mop, const char *mntpt, -- 1.8.3.1