Whamcloud - gitweb
LU-10391 lnet: update Netlink commands functionality 03/53003/15
authorJames Simmons <jsimmons@infradead.org>
Sat, 23 Mar 2024 14:40:46 +0000 (08:40 -0600)
committerOleg Drokin <green@whamcloud.com>
Mon, 8 Apr 2024 15:35:31 +0000 (15:35 +0000)
Update jt_import() for the lnetctl import command to support
all the new Netlink API.

Fix a sending message bug that was due to  multiple calls
to genl_ctrl_resolve_grp() and genl_ctrl_resolve(). We
were using the special netlink socket for these calls.
That special socket has its own callbacks which don't
work with the libnl functions we are calling. Fix this
by creating an internal generic netlink socket for use
with the libnl functions.

Test-Parameters: trivial testlist=sanity-lnet
Change-Id: I1d360cc0375bc56a05ca47d58d8319a0ded0ccf9
Signed-off-by: James Simmons <jsimmons@infradead.org>
Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/53003
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Chris Horn <chris.horn@hpe.com>
Reviewed-by: Serguei Smirnov <ssmirnov@whamcloud.com>
Reviewed-by: Frank Sehr <fsehr@whamcloud.com>
Reviewed-by: Cyril Bordage <cbordage@whamcloud.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
lnet/utils/lnetconfig/liblnetconfig.c
lnet/utils/lnetconfig/liblnetconfig.h
lnet/utils/lnetconfig/liblnetconfig_netlink.c
lnet/utils/lnetctl.c
lustre/tests/sanity-lnet.sh

index 0dbb8d2..e768d51 100644 (file)
@@ -357,6 +357,62 @@ failed:
        return rc;
 }
 
+int yaml_netlink_setup_emitter(yaml_emitter_t *output, struct nl_sock *sk,
+                              char *family, int version, int flags, int op,
+                              bool stream)
+{
+       yaml_event_t hdr;
+       int rc;
+
+       rc = yaml_emitter_initialize(output);
+       if (rc == 0)
+               goto emitter_error;
+
+       rc = yaml_emitter_set_streaming_output_netlink(output, sk, family,
+                                                      version, op, flags,
+                                                      stream);
+       if (rc == 0)
+               goto emitter_error;
+
+       yaml_emitter_open(output);
+       yaml_emitter_set_indent(output, 6);
+       yaml_document_start_event_initialize(&hdr, NULL, NULL, NULL, 0);
+       rc = yaml_emitter_emit(output, &hdr);
+       if (rc == 0)
+               goto emitter_error;
+
+       yaml_mapping_start_event_initialize(&hdr, NULL,
+                                           (yaml_char_t *)YAML_MAP_TAG,
+                                           1, YAML_BLOCK_MAPPING_STYLE);
+       rc = yaml_emitter_emit(output, &hdr);
+emitter_error:
+       return rc;
+}
+
+int yaml_netlink_complete_emitter(yaml_emitter_t *output)
+{
+       yaml_event_t hdr;
+       int rc;
+
+       yaml_mapping_end_event_initialize(&hdr);
+       rc = yaml_emitter_emit(output, &hdr);
+       if (rc == 0)
+               goto emitter_error;
+
+       yaml_document_end_event_initialize(&hdr, 0);
+       rc = yaml_emitter_emit(output, &hdr);
+       if (rc == 0)
+               goto emitter_error;
+
+       rc = yaml_emitter_close(output);
+       if (rc == 0)
+               goto emitter_error;
+
+       yaml_emitter_delete(output);
+emitter_error:
+       return rc;
+}
+
 int lustre_lnet_config_lib_init(void)
 {
        return register_ioc_dev(LNET_DEV_ID, LNET_DEV_PATH);
index 65f5076..8a852a2 100644 (file)
@@ -809,6 +809,15 @@ int yaml_lnet_configure(int flags, const char **msg);
 int yaml_emitter_set_output_netlink(yaml_emitter_t *emitter, struct nl_sock *nl,
                                    char *family, int version, int cmd,
                                    int flags);
+/**
+ * yaml_emitter_set_streaming_output_netlink
+ *
+ * Special handling to handle the fact RHEL7 is super old.
+ */
+int yaml_emitter_set_streaming_output_netlink(yaml_emitter_t *sender,
+                                             struct nl_sock *nl, char *family,
+                                             int version, int cmd, int flags,
+                                             bool stream);
 
 /**
  * yaml_parser_set_input_netlink
@@ -868,6 +877,33 @@ void yaml_parser_log_error(yaml_parser_t *parser, FILE *log,
  */
 void yaml_emitter_log_error(yaml_emitter_t *emitter, FILE *log);
 
+/**
+ * yaml_netlink_setup_emitter
+ *
+ *   Helper function to setup emitter with Netlink. Needed for
+ *   cases where we reuse the @sk.
+ *
+ *   emitter   - YAML emitter to setup.
+ *   sk                - Netlink socket.
+ *   family    - Netlink family
+ *   version   - Netlink API version
+ *   flags     - Netlink flags (NLM_F_*)
+ *   op                - Netlink command (*_CMD_*)
+ *   stream    - Is the netlink socket reusable
+ */
+int yaml_netlink_setup_emitter(yaml_emitter_t *output, struct nl_sock *sk,
+                              char *family, int version, int flags, int op,
+                              bool stream);
+
+/**
+ * yaml_netlink_complete_emitter
+ *
+ *   Helper function to cleanup emitter when done. The netlink socket
+ *   is not altered in anyway.
+ *
+ *   emitter   - YAML emitter to cleanup.
+ */
+int yaml_netlink_complete_emitter(yaml_emitter_t *output);
 
 /*
  * lustre_lnet_init_nw_descr
index a79b55c..74a4b78 100644 (file)
@@ -284,30 +284,6 @@ static int lustre_netlink_register(struct nl_sock *sk, bool async_events)
        return rc;
 }
 
-/**
- * Filter Netlink socket by groups
- *
- * @nl         Netlink socket
- * @family     The family name of the Netlink socket.
- * @group      Netlink messages will only been sent if they belong to this
- *             group
- *
- * Return      0 on success or a negative error code.
- */
-static int lustre_netlink_add_group(struct nl_sock *nl, const char *family,
-                                   const char *group)
-{
-       int group_id;
-
-       /* Get group ID */
-       group_id = genl_ctrl_resolve_grp(nl, family, group);
-       if (group_id < 0)
-               return group_id;
-
-       /* subscribe to generic netlink multicast group */
-       return nl_socket_add_membership(nl, group_id);
-}
-
 /* A YAML file is used to describe data. In a YAML document the content is
  * all about a collection of scalars used to create new data types such as
  * key-value pairs. This allows complex documents to represent anything from
@@ -1282,6 +1258,7 @@ failed:
 struct yaml_netlink_output {
        yaml_emitter_t          *emitter;
        struct nl_sock          *nl;
+       struct nl_sock          *ctrl;
        char                    *family;
        int                     family_id;
        int                     version;
@@ -1664,6 +1641,30 @@ static void yaml_quotation_handling(char *buf)
        }
 }
 
+/**
+ * Filter Netlink socket by groups
+ *
+ * @out                Data structure for YAML write handler.
+ * @family     The family name of the Netlink socket.
+ * @group      Netlink messages will only been sent if they belong to this
+ *             group
+ *
+ * Return      0 on success or a negative error code.
+ */
+static int lustre_netlink_add_group(struct yaml_netlink_output *out,
+                                   const char *group)
+{
+       int group_id;
+
+       /* Get group ID */
+       group_id = genl_ctrl_resolve_grp(out->ctrl, out->family, group);
+       if (group_id < 0)
+               return group_id;
+
+       /* subscribe to generic netlink multicast group */
+       return nl_socket_add_membership(out->nl, group_id);
+}
+
 /* libyaml takes the YAML documents and places the data into an
  * internal buffer to the library. We take each line and turn it
  * into a Netlink message using the same format as the key table.
@@ -1703,8 +1704,7 @@ already_have_line:
                                continue;
                        *tmp = '\0';
 
-                       rc = lustre_netlink_add_group(out->nl, out->family,
-                                                     line);
+                       rc = lustre_netlink_add_group(out, line);
                        if (rc < 0) {
                                yaml_emitter_set_writer_error(out->emitter,
                                                              "Netlink group does not exist");
@@ -1791,6 +1791,8 @@ already_have_line:
                yaml_emitter_set_writer_error(out->emitter,
                                              nl_geterror(rc));
 nla_put_failure:
+       if (out->ctrl != out->nl)
+               nl_socket_free(out->ctrl);
        free(buf);
        return out->emitter->error == YAML_NO_ERROR ? 1 : 0;
 }
@@ -1801,8 +1803,10 @@ nla_put_failure:
  * which is used to write out a YAML document to a file.
  */
 YAML_DECLARE(int)
-yaml_emitter_set_output_netlink(yaml_emitter_t *sender, struct nl_sock *nl,
-                               char *family, int version, int cmd, int flags)
+yaml_emitter_set_streaming_output_netlink(yaml_emitter_t *sender,
+                                         struct nl_sock *nl, char *family,
+                                         int version, int cmd, int flags,
+                                         bool stream)
 {
        struct yaml_netlink_output *out;
 
@@ -1812,11 +1816,36 @@ yaml_emitter_set_output_netlink(yaml_emitter_t *sender, struct nl_sock *nl,
                return false;
        }
 
+       /* All because RHEL7 is really too old. Once we drop RHEL7
+        * this hack can go away.
+        */
+       if (stream) {
+               out->ctrl = nl_socket_alloc();
+               if (!out->ctrl) {
+                       sender->problem = "socket allocation failed";
+                       sender->error = YAML_MEMORY_ERROR;
+                       free(out);
+                       return false;
+               }
+
+               if (genl_connect(out->ctrl) < 0) {
+                       yaml_emitter_set_writer_error(sender,
+                                                     "socket failed to connect");
+                       nl_socket_free(out->ctrl);
+                       free(out);
+                       return false;
+               }
+       } else {
+               out->ctrl = nl;
+       }
+
        /* Get family ID */
-       out->family_id = genl_ctrl_resolve(nl, family);
+       out->family_id = genl_ctrl_resolve(out->ctrl, family);
        if (out->family_id < 0) {
                yaml_emitter_set_writer_error(sender,
                                              "failed to resolve Netlink family id");
+               if (stream)
+                       nl_socket_free(out->ctrl);
                free(out);
                return false;
        }
@@ -1832,6 +1861,15 @@ yaml_emitter_set_output_netlink(yaml_emitter_t *sender, struct nl_sock *nl,
        return true;
 }
 
+YAML_DECLARE(int)
+yaml_emitter_set_output_netlink(yaml_emitter_t *sender, struct nl_sock *nl,
+                               char *family, int version, int cmd, int flags)
+{
+       return yaml_emitter_set_streaming_output_netlink(sender, nl, family,
+                                                        version, cmd, flags,
+                                                        false);
+}
+
 /* Error handling helpers */
 void yaml_emitter_log_error(yaml_emitter_t *emitter, FILE *log)
 {
index d20e2d9..afab4f3 100644 (file)
@@ -3829,6 +3829,127 @@ static int jt_udsp(int argc, char **argv)
        return cfs_parser(argc, argv, udsp_cmds);
 }
 
+static int yaml_import_global_settings(char *key, unsigned long value,
+                                      char cmd, struct cYAML *show_rc,
+                                      struct cYAML *err_rc)
+{
+       int rc;
+
+       if (strcmp("numa_range", key) == 0) {
+               if (cmd == 'a' || cmd == 'd') {
+                       if (cmd == 'd')
+                               value = 0;
+                       rc = lustre_lnet_config_numa_range(value, -1,
+                                                          &err_rc);
+               } else if (cmd == 's') {
+                       rc = lustre_lnet_show_numa_range(-1, &show_rc,
+                                                        &err_rc);
+               }
+       } else if (strcmp("max_interfaces", key) == 0 ||
+                  strcmp("max_intf", key) == 0) {
+               if (cmd == 'a' || cmd == 'd') {
+                       if (cmd == 'd')
+                               value = LNET_INTERFACES_MAX_DEFAULT;
+                       rc = lustre_lnet_config_max_intf(value, -1,
+                                                        &err_rc);
+               } else if (cmd == 's') {
+                       rc = lustre_lnet_show_max_intf(-1, &show_rc,
+                                                      &err_rc);
+               }
+       } else if (strcmp("discovery", key) == 0) {
+               if (cmd == 'a' || cmd == 'd') {
+                       if (cmd == 'd')
+                               value = 1;
+                       rc = lustre_lnet_config_discovery(value, -1,
+                                                         &err_rc);
+               } else if (cmd == 's') {
+                       rc = lustre_lnet_show_discovery(-1, &show_rc,
+                                                       &err_rc);
+               }
+       } else if (strcmp("drop_asym_route", key) == 0) {
+               if (cmd == 'a') {
+                       rc = lustre_lnet_config_drop_asym_route(value,
+                                                               -1,
+                                                               &err_rc);
+               } else if (cmd == 's') {
+                       rc = lustre_lnet_show_drop_asym_route(-1, &show_rc,
+                                                             &err_rc);
+               }
+       } else if (strcmp("retry_count", key) == 0) {
+               if (cmd == 'a') {
+                       rc = lustre_lnet_config_retry_count(value, -1,
+                                                           &err_rc);
+               } else if (cmd == 's') {
+                       rc = lustre_lnet_show_retry_count(-1, &show_rc,
+                                                         &err_rc);
+               }
+       } else if (strcmp("transaction_timeout", key) == 0) {
+               if (cmd == 'a') {
+                       rc = lustre_lnet_config_transaction_to(value, -1,
+                                                              &err_rc);
+               } else if (cmd == 's') {
+                       rc = lustre_lnet_show_transaction_to(-1, &show_rc,
+                                                            &err_rc);
+               }
+       } else if (strcmp("health_sensitivity", key) == 0) {
+               if (cmd == 'a') {
+                       rc = lustre_lnet_config_hsensitivity(value, -1,
+                                                            &err_rc);
+               } else if (cmd == 's') {
+                       rc = lustre_lnet_show_hsensitivity(-1, &show_rc,
+                                                          &err_rc);
+               }
+       } else if (strcmp("recovery_interval", key) == 0) {
+               if (cmd == 'a') {
+                       rc = lustre_lnet_config_recov_intrv(value, -1,
+                                                           &err_rc);
+               } else if (cmd == 's') {
+                       rc = lustre_lnet_show_recov_intrv(-1, &show_rc,
+                                                         &err_rc);
+               }
+       } else if (strcmp("router_sensitivity", key) == 0) {
+               if (cmd == 'a') {
+                       rc = lustre_lnet_config_rtr_sensitivity(value, -1,
+                                                               &err_rc);
+               } else if (cmd == 's') {
+                       rc = lustre_lnet_show_rtr_sensitivity(-1, &show_rc,
+                                                             &err_rc);
+               }
+       } else if (strcmp("lnd_timeout", key) == 0) {
+               if (cmd == 'a') {
+               } else if (cmd == 's') {
+                       rc = lustre_lnet_show_lnd_timeout(-1, &show_rc,
+                                                         &err_rc);
+               }
+       } else if (strcmp("response_tracking", key) == 0) {
+               if (cmd == 'a') {
+                       rc = lustre_lnet_config_response_tracking(value, -1,
+                                                                 &err_rc);
+               } else if (cmd == 's') {
+                       rc = lustre_lnet_show_response_tracking(-1, &show_rc,
+                                                               &err_rc);
+               }
+       } else if (strcmp("recovery_limit", key) == 0) {
+               if (cmd == 'a') {
+                       rc = lustre_lnet_config_recovery_limit(value, -1,
+                                                              &err_rc);
+               } else if (cmd == 's') {
+                       rc = lustre_lnet_show_recovery_limit(-1, &show_rc,
+                                                            &err_rc);
+               }
+       } else if (strcmp("max_recovery_ping_interval", key) == 0) {
+               if (cmd == 'a') {
+                       rc = lustre_lnet_config_max_recovery_ping_interval(value, -1,
+                                                                          &err_rc);
+               } else if (cmd == 's') {
+                       rc = lustre_lnet_show_max_recovery_ping_interval(-1, &show_rc,
+                                                                        &err_rc);
+               }
+       }
+
+       return rc;
+}
+
 static int jt_import(int argc, char **argv)
 {
        char *file = NULL;
@@ -3836,6 +3957,7 @@ static int jt_import(int argc, char **argv)
        struct cYAML *show_rc = NULL;
        int rc = 0, return_rc = 0, opt, opt_found = 0;
        char *yaml_blk = NULL, *buf, cmd = 'a';
+       int flags = NLM_F_CREATE;
        bool release = true;
        char err_str[256];
        struct stat st;
@@ -3850,19 +3972,32 @@ static int jt_import(int argc, char **argv)
                { .name = "help", .has_arg = no_argument, .val = 'h' },
                { .name = NULL }
        };
+       bool done = false, unspec = true;
+       yaml_parser_t setup, reply;
+       struct nl_sock *sk = NULL;
+       int op = LNET_CMD_UNSPEC;
+       const char *msg = NULL;
+       yaml_emitter_t output;
+       yaml_event_t event;
 
        while ((opt = getopt_long(argc, argv, short_options,
                                   long_options, NULL)) != -1) {
                opt_found = 1;
                switch (opt) {
                case 'a':
+                       /* default is NLM_F_CREATE */
                        cmd = opt;
                        break;
                case 'd':
+                       flags = 0; /* Netlink delete cmd */
+                       cmd = opt;
+                       break;
                case 's':
+                       flags = NLM_F_DUMP;
                        cmd = opt;
                        break;
                case 'e':
+                       /* use NLM_F_CREATE for discover */
                        cmd = opt;
                        break;
                case 'h':
@@ -3905,6 +4040,193 @@ static int jt_import(int argc, char **argv)
                input = stdin;
        }
 
+       /* Create Netlink emitter to send request to kernel */
+       sk = nl_socket_alloc();
+       if (!sk)
+               goto old_api;
+
+       /* Setup parser to receive Netlink packets */
+       rc = yaml_parser_initialize(&reply);
+       if (rc == 0) {
+               nl_socket_free(sk);
+               goto old_api;
+       }
+
+       rc = yaml_parser_set_input_netlink(&reply, sk, false);
+       if (rc == 0) {
+               msg = yaml_parser_get_reader_error(&reply);
+               goto free_reply;
+       }
+
+       /* Initialize configuration parser */
+       rc = yaml_parser_initialize(&setup);
+       if (rc == 0) {
+               yaml_parser_log_error(&setup, stderr, "import: ");
+               yaml_parser_delete(&setup);
+               return -EINVAL;
+       }
+
+       yaml_parser_set_input_file(&setup, input);
+
+       while (!done) {
+               if (!yaml_parser_parse(&setup, &event)) {
+                       yaml_parser_log_error(&setup, stderr, "import: ");
+                       break;
+               }
+
+               if (event.type != YAML_SCALAR_EVENT)
+                       goto skip_test;
+
+               if (!strcmp((char *)event.data.scalar.value, "net") &&
+                   op != LNET_CMD_ROUTES && cmd != 'e') {
+                       if (op != LNET_CMD_UNSPEC) {
+                               rc = yaml_netlink_complete_emitter(&output);
+                               if (rc == 0)
+                                       goto emitter_error;
+                       }
+                       op = LNET_CMD_NETS;
+
+                       rc = yaml_netlink_setup_emitter(&output, sk,
+                                                       LNET_GENL_NAME,
+                                                       LNET_GENL_VERSION,
+                                                       flags, op, true);
+                       if (rc == 0)
+                               goto emitter_error;
+
+                       unspec = false;
+               } else if (!strcmp((char *)event.data.scalar.value, "peer") &&
+                          cmd != 'e') {
+                       if (op != LNET_CMD_UNSPEC) {
+                               rc = yaml_netlink_complete_emitter(&output);
+                               if (rc == 0)
+                                       goto emitter_error;
+                       }
+                       op = LNET_CMD_PEERS;
+
+                       rc = yaml_netlink_setup_emitter(&output, sk,
+                                                       LNET_GENL_NAME,
+                                                       LNET_GENL_VERSION,
+                                                       flags, op, true);
+                       if (rc == 0)
+                               goto emitter_error;
+
+                       unspec = false;
+               } else if (!strcmp((char *)event.data.scalar.value, "route") &&
+                          cmd != 'e') {
+                       if (op != LNET_CMD_UNSPEC) {
+                               rc = yaml_netlink_complete_emitter(&output);
+                               if (rc == 0)
+                                       goto emitter_error;
+                       }
+                       op = LNET_CMD_ROUTES;
+
+                       rc = yaml_netlink_setup_emitter(&output, sk,
+                                                       LNET_GENL_NAME,
+                                                       LNET_GENL_VERSION,
+                                                       flags, op, true);
+                       if (rc == 0)
+                               goto emitter_error;
+
+                       unspec = false;
+               } else if ((!strcmp((char *)event.data.scalar.value, "discover") ||
+                           !strcmp((char *)event.data.scalar.value, "ping")) &&
+                          cmd == 'e') {
+                       if (op != LNET_CMD_UNSPEC) {
+                               rc = yaml_netlink_complete_emitter(&output);
+                               if (rc == 0)
+                                       goto emitter_error;
+                       }
+                       op = LNET_CMD_PING;
+
+                       if (!strcmp((char *)event.data.scalar.value, "ping"))
+                               flags = NLM_F_DUMP;
+
+                       rc = yaml_netlink_setup_emitter(&output, sk,
+                                                       LNET_GENL_NAME,
+                                                       LNET_GENL_VERSION,
+                                                       flags, op, true);
+                       if (rc == 0)
+                               goto emitter_error;
+
+                       unspec = false;
+               } else if (!strcmp((char *)event.data.scalar.value, "global")) {
+                       if (op != LNET_CMD_UNSPEC) {
+                               rc = yaml_netlink_complete_emitter(&output);
+                               if (rc == 0)
+                                       goto emitter_error;
+                       }
+                       op = LNET_CMD_UNSPEC;
+               } else if (op == LNET_CMD_UNSPEC) {
+                       struct cYAML *err_rc = NULL;
+                       long int value;
+                       char *key;
+
+                       key = strdup((char *)event.data.scalar.value);
+                       rc = yaml_parser_parse(&setup, &event);
+                       if (rc == 0)
+                               goto free_reply;
+
+                       rc = parse_long((char *)event.data.scalar.value,
+                                       &value);
+                       if (rc != 0)
+                               goto free_reply;
+
+                       rc = yaml_import_global_settings(key, value, cmd,
+                                                        show_rc, err_rc);
+                       if (rc != LUSTRE_CFG_RC_NO_ERR)
+                               cYAML_print_tree2file(stderr, err_rc);
+                       else
+                               rc = 1;
+               }
+skip_test:
+               if (op != LNET_CMD_UNSPEC) {
+                       rc = yaml_emitter_emit(&output, &event);
+                       if (rc == 0)
+                               break;
+               }
+
+               done = (event.type == YAML_STREAM_END_EVENT);
+       }
+emitter_error:
+       if (rc == 0) {
+               yaml_emitter_log_error(&output, stderr);
+               yaml_emitter_delete(&output);
+               rc = -EINVAL;
+       } else if (!unspec) {
+               yaml_document_t errmsg;
+
+               rc = yaml_parser_load(&reply, &errmsg);
+               if (rc == 1 && (flags & NLM_F_DUMP)) {
+                       yaml_emitter_t debug;
+
+                       rc = yaml_emitter_initialize(&debug);
+                       if (rc == 1) {
+                               yaml_emitter_set_indent(&debug,
+                                                       LNET_DEFAULT_INDENT);
+                               yaml_emitter_set_output_file(&debug,
+                                                            stdout);
+                               rc = yaml_emitter_dump(&debug, &errmsg);
+                       }
+                       yaml_emitter_delete(&debug);
+               } else {
+                       msg = yaml_parser_get_reader_error(&reply);
+               }
+               yaml_emitter_delete(&output);
+               yaml_document_delete(&errmsg);
+       }
+free_reply:
+       if (rc == 0) {
+               yaml_lnet_print_error(flags, "import", msg);
+               rc = -EINVAL;
+       }
+       yaml_parser_delete(&reply);
+       yaml_parser_delete(&setup);
+       nl_socket_free(sk);
+       if (input)
+               fclose(input);
+
+       return rc == 1 ? 0 : rc;
+old_api:
        /* assume that we're getting our input from stdin */
        rc = fstat(fileno(input), &st);
        if (rc < 0) {
index 366099b..9369723 100755 (executable)
@@ -3524,6 +3524,11 @@ EOF
                error "export failed $?"
 
        validate_gateway_nids
+
+       # Since we have an complex YAML config file we can test import
+       do_lnetctl lnet unconfigure ||
+               error "Failed to stop LNet rc=$?"
+       do_lnetctl import <  ${GLOBAL_YAML_FILE} || error "Import failed $?"
 }
 run_test 255 "Use lnet routes param with pdsh syntax"