Whamcloud - gitweb
LU-10825 lnet: add ip2nets syntax handling for peer 50/32250/3
authorAmir Shehata <amir.shehata@intel.com>
Fri, 23 Mar 2018 17:04:19 +0000 (10:04 -0700)
committerJohn L. Hammond <jhammond@whamcloud.com>
Wed, 1 Aug 2018 16:35:16 +0000 (16:35 +0000)
Allow peers to be added using ip2nets syntax, from
both command line and YAML block.

Command line example:
lnetctl peer add --ip2nets 10.10.10.[3-6,9]@tcp
lnetctl peer del --ip2nets 10.10.10.[3-6,9]@tcp

YAML example:
peer:
    ip2nets:
      - nid: 30.10.10.[3-8]@tcp
      - nid: 40.10.10.[9-40]@tcp

Lustre-change: https://review.whamcloud.com/31786
Lustre-commit: 70c95457f6836a9c0a9e95ae0c4bdd20f99a8747

Test-Parameters: trivial
Signed-off-by: Amir Shehata <amir.shehata@intel.com>
Change-Id: I904be8d496ad2be277c3d21dc7f72cbc7ed02b50
Reviewed-by: Sonia Sharma <sonia.sharma@intel.com>
Reviewed-by: Dmitry Eremin <dmitry.eremin@intel.com>
Reviewed-by: Oleg Drokin <oleg.drokin@intel.com>
Signed-off-by: Minh Diep <minh.diep@intel.com>
Reviewed-on: https://review.whamcloud.com/32250
Tested-by: Jenkins
Tested-by: Maloo <hpdd-maloo@intel.com>
Reviewed-by: Sonia Sharma <sharmaso@whamcloud.com>
Reviewed-by: Amir Shehata <ashehata@whamcloud.com>
Reviewed-by: John L. Hammond <jhammond@whamcloud.com>
lnet/utils/lnetconfig/liblnetconfig.c
lnet/utils/lnetconfig/liblnetconfig.h
lnet/utils/lnetctl.c

index 9b915df..e9a4c5b 100644 (file)
@@ -59,6 +59,7 @@
 #define DEL_CMD                        "del"
 #define SHOW_CMD               "show"
 #define DBG_CMD                        "dbg"
+#define MAX_NUM_IPS            128
 
 /*
  * lustre_lnet_ip_range_descr
@@ -183,6 +184,20 @@ void lustre_lnet_init_nw_descr(struct lnet_dlc_network_descr *nw_descr)
        }
 }
 
+static char *get_next_delimiter_in_nid(char *str, char sep)
+{
+       char *at, *comma;
+
+       /* first find the '@' */
+       at = strchr(str, '@');
+       if (!at)
+               return str;
+
+       /* now that you found the at find the sep after */
+       comma = strchr(at, sep);
+       return comma;
+}
+
 int lustre_lnet_parse_nids(char *nids, char **array, int size,
                           char ***out_array)
 {
@@ -194,9 +209,9 @@ int lustre_lnet_parse_nids(char *nids, char **array, int size,
        if (nids == NULL || strlen(nids) == 0)
                return size;
 
-       /* count the number or new nids, by counting the number of comma*/
+       /* count the number or new nids, by counting the number of comma*/
        while (comma) {
-               comma = strchr(comma, ',');
+               comma = get_next_delimiter_in_nid(comma, ',');
                if (comma) {
                        comma++;
                        num_nids++;
@@ -221,7 +236,7 @@ int lustre_lnet_parse_nids(char *nids, char **array, int size,
        start = (size > 0) ? size: 0;
        finish = (size > 0) ? size + num_nids : num_nids;
        for (i = start; i < finish; i++) {
-               comma = strchr(comma, ',');
+               comma = get_next_delimiter_in_nid(comma, ',');
                if (!comma)
                        /*
                         * the length of the string to be parsed out is
@@ -375,37 +390,6 @@ int lustre_lnet_config_ni_system(bool up, bool load_ni_from_mod,
        return rc;
 }
 
-static lnet_nid_t *allocate_create_nid_array(char **nids, __u32 num_nids,
-                                            char *err_str)
-{
-       lnet_nid_t *array = NULL;
-       __u32 i;
-
-       if (!nids || num_nids == 0) {
-               snprintf(err_str, LNET_MAX_STR_LEN, "no NIDs to add");
-               return NULL;
-       }
-
-       array = calloc(sizeof(*array) * num_nids, 1);
-       if (array == NULL) {
-               snprintf(err_str, LNET_MAX_STR_LEN, "out of memory");
-               return NULL;
-       }
-
-       for (i = 0; i < num_nids; i++) {
-               array[i] = libcfs_str2nid(nids[i]);
-               if (array[i] == LNET_NID_ANY) {
-                       free(array);
-                       snprintf(err_str, LNET_MAX_STR_LEN,
-                                "bad NID: '%s'",
-                                nids[i]);
-                       return NULL;
-               }
-       }
-
-       return array;
-}
-
 static int dispatch_peer_ni_cmd(lnet_nid_t pnid, lnet_nid_t nid, __u32 cmd,
                                struct lnet_ioctl_peer_cfg *data,
                                char *err_str, char *cmd_str)
@@ -422,104 +406,289 @@ static int dispatch_peer_ni_cmd(lnet_nid_t pnid, lnet_nid_t nid, __u32 cmd,
                        LNET_MAX_STR_LEN,
                        "\"cannot %s peer ni: %s\"",
                        (cmd_str) ? cmd_str : "add", strerror(errno));
+               err_str[LNET_MAX_STR_LEN - 1] = '\0';
        }
 
        return rc;
 }
 
-int lustre_lnet_config_peer_nid(char *pnid, char **nid, int num_nids,
-                               bool mr, int seq_no, struct cYAML **err_rc)
+static void lustre_lnet_clean_ip2nets(struct lustre_lnet_ip2nets *ip2nets)
 {
-       struct lnet_ioctl_peer_cfg data;
-       lnet_nid_t prim_nid = LNET_NID_ANY;
-       int rc = LUSTRE_CFG_RC_NO_ERR;
-       int idx = 0;
-       bool nid0_used = false;
-       char err_str[LNET_MAX_STR_LEN] = {0};
-       lnet_nid_t *nids = allocate_create_nid_array(nid, num_nids, err_str);
+       struct lustre_lnet_ip_range_descr *ipr, *tmp;
+       struct cfs_expr_list *el, *el_tmp;
 
-       if (pnid) {
-               prim_nid = libcfs_str2nid(pnid);
-               if (prim_nid == LNET_NID_ANY) {
-                       snprintf(err_str, sizeof(err_str),
-                                "bad key NID: '%s'",
-                                pnid);
-                       rc = LUSTRE_CFG_RC_MISSING_PARAM;
-                       goto out;
+       list_for_each_entry_safe(ipr, tmp,
+                                &ip2nets->ip2nets_ip_ranges,
+                                ipr_entry) {
+               list_del(&ipr->ipr_entry);
+               list_for_each_entry_safe(el, el_tmp, &ipr->ipr_expr,
+                                        el_link) {
+                       list_del(&el->el_link);
+                       cfs_expr_list_free(el);
                }
-       } else if (!nids || nids[0] == LNET_NID_ANY) {
-               snprintf(err_str, sizeof(err_str),
-                        "no NIDs provided for configuration");
-               rc = LUSTRE_CFG_RC_MISSING_PARAM;
+               free(ipr);
+       }
+}
+
+/*
+ * returns an rc < 0 if there is an error
+ * otherwise it returns the number IPs generated
+ *  it also has out params: net - network name
+ */
+static int lnet_expr2ips(char *nidstr, __u32 *ip_list,
+                        struct lustre_lnet_ip2nets *ip2nets,
+                        __u32 *net, char *err_str)
+{
+       struct lustre_lnet_ip_range_descr *ipr;
+       char *comp1, *comp2;
+       int ip_idx = MAX_NUM_IPS - 1;
+       int ip_range_len, rc = LUSTRE_CFG_RC_NO_ERR;
+       __u32 net_type;
+       char ip_range[LNET_MAX_STR_LEN];
+
+       /* separate the two components of the NID */
+       comp1 = nidstr;
+       comp2 = strchr(nidstr, '@');
+       if (comp2 == NULL) {
+               snprintf(err_str,
+                       LNET_MAX_STR_LEN,
+                       "\"cannot parse NID %s\"", nidstr);
+               err_str[LNET_MAX_STR_LEN - 1] = '\0';
+               rc = LUSTRE_CFG_RC_BAD_PARAM;
                goto out;
-       } else {
-               prim_nid = LNET_NID_ANY;
        }
 
-       snprintf(err_str, sizeof(err_str), "\"Success\"");
+       /* length of the expected ip-range */
+       ip_range_len = comp2 - comp1;
+       if (ip_range_len >= LNET_MAX_STR_LEN) {
+               snprintf(err_str,
+                       LNET_MAX_STR_LEN,
+                       "\"cannot parse ip_range '%s'\"", ip_range);
+               err_str[LNET_MAX_STR_LEN - 1] = '\0';
+               rc = LUSTRE_CFG_RC_BAD_PARAM;
+               goto out;
+       }
 
-       LIBCFS_IOC_INIT_V2(data, prcfg_hdr);
-       data.prcfg_mr = mr;
+       /* move beyond '@' */
+       comp2++;
 
        /*
-        * if prim_nid is not specified use the first nid in the list of
-        * nids provided as the prim_nid. NOTE: on entering 'if' we must
-        * have at least 1 NID
+        * if the net component is either o2ib or tcp then we expect
+        * an IP range which could only be a single IP address.
+        * Parse that.
         */
-       if (prim_nid == LNET_NID_ANY) {
-               nid0_used = true;
-               prim_nid = nids[0];
+       *net = libcfs_str2net(comp2);
+       net_type = LNET_NETTYP(*net);
+       /* expression support is for o2iblnd and socklnd only */
+       if (net_type != O2IBLND && net_type != SOCKLND)
+               return LUSTRE_CFG_RC_SKIP;
+
+       strncpy(ip_range, comp1, ip_range_len);
+       ip_range[ip_range_len] = '\0';
+       ip2nets->ip2nets_net.nw_id = *net;
+
+       rc = lustre_lnet_add_ip_range(&ip2nets->ip2nets_ip_ranges, ip_range);
+       if (rc != LUSTRE_CFG_RC_NO_ERR) {
+               snprintf(err_str,
+                       LNET_MAX_STR_LEN,
+                       "\"cannot parse ip_range '%s'\"", ip_range);
+               err_str[LNET_MAX_STR_LEN - 1] = '\0';
+               rc = LUSTRE_CFG_RC_BAD_PARAM;
+               goto out;
        }
 
-       /* Create the prim_nid first */
-       rc = dispatch_peer_ni_cmd(prim_nid, LNET_NID_ANY,
-                                 IOC_LIBCFS_ADD_PEER_NI,
-                                 &data, err_str, "add");
+       /*
+       * Generate all the IP Addresses from the parsed range. For sanity
+       * we allow only a max of MAX_NUM_IPS nids to be configured for
+       * a single peer.
+       */
+       list_for_each_entry(ipr, &ip2nets->ip2nets_ip_ranges, ipr_entry)
+               ip_idx = cfs_ip_addr_range_gen(ip_list, MAX_NUM_IPS,
+                                               &ipr->ipr_expr);
+
+       if (ip_idx == MAX_NUM_IPS - 1) {
+               snprintf(err_str, LNET_MAX_STR_LEN,
+                               "no NIDs provided for configuration");
+               err_str[LNET_MAX_STR_LEN - 1] = '\0';
+               rc = LUSTRE_CFG_RC_NO_MATCH;
+               goto out;
+       } else if (ip_idx == -1) {
+               rc = LUSTRE_CFG_RC_LAST_ELEM;
+       } else {
+               rc = ip_idx;
+       }
 
-       if (rc != 0)
+out:
+       return rc;
+}
+
+static int lustre_lnet_handle_peer_ip2nets(char **nid, int num_nids, bool mr,
+                                          bool range, __u32 cmd,
+                                          char *cmd_type, char *err_str)
+{
+       __u32 net = LNET_NIDNET(LNET_NID_ANY);
+       int ip_idx;
+       int i, j, rc = LUSTRE_CFG_RC_NO_ERR;
+       __u32 ip_list[MAX_NUM_IPS];
+       struct lustre_lnet_ip2nets ip2nets;
+       struct lnet_ioctl_peer_cfg data;
+       lnet_nid_t peer_nid;
+       lnet_nid_t prim_nid = LNET_NID_ANY;
+
+       /* initialize all lists */
+       INIT_LIST_HEAD(&ip2nets.ip2nets_ip_ranges);
+       INIT_LIST_HEAD(&ip2nets.ip2nets_net.network_on_rule);
+       INIT_LIST_HEAD(&ip2nets.ip2nets_net.nw_intflist);
+
+       /* each nid entry is an expression */
+       for (i = 0; i < num_nids; i++) {
+               if (!range && i == 0)
+                       prim_nid = libcfs_str2nid(nid[0]);
+               else if (range)
+                       prim_nid = LNET_NID_ANY;
+
+               rc = lnet_expr2ips(nid[i], ip_list, &ip2nets, &net, err_str);
+               if (rc == LUSTRE_CFG_RC_SKIP)
+                       continue;
+               else if (rc == LUSTRE_CFG_RC_LAST_ELEM)
+                       rc = -1;
+               else if (rc < LUSTRE_CFG_RC_NO_ERR)
+                       goto out;
+
+               ip_idx = rc;
+
+               for (j = MAX_NUM_IPS - 1; j > ip_idx; j--) {
+                       peer_nid = LNET_MKNID(net, ip_list[j]);
+                       if (peer_nid == LNET_NID_ANY) {
+                               snprintf(err_str,
+                                       LNET_MAX_STR_LEN,
+                                       "\"cannot parse NID\"");
+                               err_str[LNET_MAX_STR_LEN - 1] = '\0';
+                               rc = LUSTRE_CFG_RC_BAD_PARAM;
+                               goto out;
+                       }
+
+                       LIBCFS_IOC_INIT_V2(data, prcfg_hdr);
+                       data.prcfg_mr = mr;
+
+                       if (prim_nid == LNET_NID_ANY && j == MAX_NUM_IPS - 1) {
+                               prim_nid = peer_nid;
+                               peer_nid = LNET_NID_ANY;
+                       }
+
+                       if (!range && num_nids > 1 && i == 0 &&
+                           cmd == IOC_LIBCFS_DEL_PEER_NI)
+                               continue;
+                       else if (!range && i == 0)
+                               peer_nid = LNET_NID_ANY;
+
+                       /*
+                       * If prim_nid is not provided then the first nid in the
+                       * list becomes the prim_nid. First time round the loop
+                       * use LNET_NID_ANY for the first parameter, then use
+                       * nid[0] as the key nid after wards
+                       */
+                       rc = dispatch_peer_ni_cmd(prim_nid, peer_nid, cmd,
+                                                 &data, err_str, cmd_type);
+                       if (rc != 0)
+                               goto out;
+
+                       /*
+                        * we just deleted the entire peer using the
+                        * primary_nid. So don't bother iterating through
+                        * the rest of the nids
+                        */
+                       if (prim_nid != LNET_NID_ANY &&
+                           peer_nid == LNET_NID_ANY &&
+                           cmd == IOC_LIBCFS_DEL_PEER_NI)
+                               goto next_nid;
+               }
+next_nid:
+               lustre_lnet_clean_ip2nets(&ip2nets);
+       }
+
+out:
+       lustre_lnet_clean_ip2nets(&ip2nets);
+       return rc;
+}
+
+int lustre_lnet_config_peer_nid(char *pnid, char **nid, int num_nids,
+                               bool mr, bool ip2nets, int seq_no,
+                               struct cYAML **err_rc)
+{
+       int rc = LUSTRE_CFG_RC_NO_ERR;
+       char err_str[LNET_MAX_STR_LEN] = {0};
+       char **nid_array = NULL;
+
+       snprintf(err_str, sizeof(err_str), "\"Success\"");
+
+       if (ip2nets) {
+               rc = lustre_lnet_handle_peer_ip2nets(nid, num_nids, mr,
+                                               ip2nets, IOC_LIBCFS_ADD_PEER_NI,
+                                               ADD_CMD, err_str);
                goto out;
+       }
 
-       /* add the rest of the nids to the key nid if any are available */
-       for (idx = nid0_used ? 1 : 0 ; nids && idx < num_nids; idx++) {
-               /*
-                * If prim_nid is not provided then the first nid in the
-                * list becomes the prim_nid. First time round the loop use
-                * LNET_NID_ANY for the first parameter, then use nid[0]
-                * as the key nid after wards
-                */
-               rc = dispatch_peer_ni_cmd(prim_nid, nids[idx],
-                                         IOC_LIBCFS_ADD_PEER_NI, &data,
-                                         err_str, "add");
+       if (pnid) {
+               if (libcfs_str2nid(pnid) == LNET_NID_ANY) {
+                       snprintf(err_str, sizeof(err_str),
+                                "bad primary NID: '%s'",
+                                pnid);
+                       rc = LUSTRE_CFG_RC_MISSING_PARAM;
+                       goto out;
+               }
 
-               if (rc != 0)
+               num_nids++;
+
+               nid_array = calloc(sizeof(*nid_array), num_nids);
+               if (!nid_array) {
+                       snprintf(err_str, sizeof(err_str),
+                                       "out of memory");
+                       rc = LUSTRE_CFG_RC_OUT_OF_MEM;
                        goto out;
+               }
+               nid_array[0] = pnid;
+               memcpy(&nid_array[1], nid, sizeof(*nid) * (num_nids - 1));
        }
 
+       rc = lustre_lnet_handle_peer_ip2nets((pnid) ? nid_array : nid,
+                                            num_nids, mr, ip2nets,
+                                            IOC_LIBCFS_ADD_PEER_NI, ADD_CMD,
+                                            err_str);
+       if (rc)
+               goto out;
+
 out:
-       if (nids != NULL)
-               free(nids);
+       if (nid_array)
+               free(nid_array);
+
        cYAML_build_error(rc, seq_no, ADD_CMD, "peer_ni", err_str, err_rc);
        return rc;
 }
 
 int lustre_lnet_del_peer_nid(char *pnid, char **nid, int num_nids,
-                            int seq_no, struct cYAML **err_rc)
+                            bool ip2nets, int seq_no, struct cYAML **err_rc)
 {
-       struct lnet_ioctl_peer_cfg data;
-       lnet_nid_t prim_nid;
        int rc = LUSTRE_CFG_RC_NO_ERR;
-       int idx = 0;
        char err_str[LNET_MAX_STR_LEN] = {0};
-       lnet_nid_t *nids = allocate_create_nid_array(nid, num_nids, err_str);
+       char **nid_array = NULL;
+
+       snprintf(err_str, sizeof(err_str), "\"Success\"");
+
+       if (ip2nets) {
+               rc = lustre_lnet_handle_peer_ip2nets(nid, num_nids, false,
+                                               ip2nets, IOC_LIBCFS_DEL_PEER_NI,
+                                               DEL_CMD, err_str);
+               goto out;
+       }
 
        if (pnid == NULL) {
                snprintf(err_str, sizeof(err_str),
                         "\"Primary nid is not provided\"");
                rc = LUSTRE_CFG_RC_MISSING_PARAM;
                goto out;
-       } else {
-               prim_nid = libcfs_str2nid(pnid);
-               if (prim_nid == LNET_NID_ANY) {
+       } else if (!ip2nets) {
+               if (libcfs_str2nid(pnid) == LNET_NID_ANY) {
                        rc = LUSTRE_CFG_RC_BAD_PARAM;
                        snprintf(err_str, sizeof(err_str),
                                 "bad key NID: '%s'",
@@ -528,28 +697,27 @@ int lustre_lnet_del_peer_nid(char *pnid, char **nid, int num_nids,
                }
        }
 
-       snprintf(err_str, sizeof(err_str), "\"Success\"");
-
-       LIBCFS_IOC_INIT_V2(data, prcfg_hdr);
-       if (!nids || nids[0] == LNET_NID_ANY) {
-               rc = dispatch_peer_ni_cmd(prim_nid, LNET_NID_ANY,
-                                         IOC_LIBCFS_DEL_PEER_NI,
-                                         &data, err_str, "del");
+       num_nids++;
+       nid_array = calloc(sizeof(*nid_array), num_nids);
+       if (!nid_array) {
+               snprintf(err_str, sizeof(err_str),
+                               "out of memory");
+               rc = LUSTRE_CFG_RC_OUT_OF_MEM;
                goto out;
        }
+       nid_array[0] = pnid;
+       memcpy(&nid_array[1], nid, sizeof(*nid) * (num_nids - 1));
 
-       for (idx = 0; nids && idx < num_nids; idx++) {
-               rc = dispatch_peer_ni_cmd(prim_nid, nids[idx],
-                                         IOC_LIBCFS_DEL_PEER_NI, &data,
-                                         err_str, "del");
-
-               if (rc != 0)
-                       goto out;
-       }
+       rc = lustre_lnet_handle_peer_ip2nets(nid_array, num_nids, false,
+                                            ip2nets, IOC_LIBCFS_DEL_PEER_NI,
+                                            DEL_CMD, err_str);
+       if (rc)
+               goto out;
 
 out:
-       if (nids != NULL)
-               free(nids);
+       if (nid_array)
+               free(nid_array);
+
        cYAML_build_error(rc, seq_no, DEL_CMD, "peer_ni", err_str, err_rc);
        return rc;
 }
@@ -2762,18 +2930,13 @@ static int handle_yaml_del_ni(struct cYAML *tree, struct cYAML **show_rc,
        return rc;
 }
 
-static int yaml_copy_peer_nids(struct cYAML *tree, char ***nidsppp, bool del)
+static int yaml_copy_peer_nids(struct cYAML *nids_entry, char ***nidsppp,
+                              char *prim_nid, bool del)
 {
-       struct cYAML *nids_entry = NULL, *child = NULL, *entry = NULL,
-                    *prim_nid = NULL;
+       struct cYAML *child = NULL, *entry = NULL;
        char **nids = NULL;
        int num = 0, rc = LUSTRE_CFG_RC_NO_ERR;
 
-       prim_nid = cYAML_get_object_item(tree, "primary nid");
-       if (!prim_nid || !prim_nid->cy_valuestring)
-               return LUSTRE_CFG_RC_MISSING_PARAM;
-
-       nids_entry = cYAML_get_object_item(tree, "peer ni");
        if (cYAML_is_sequence(nids_entry)) {
                while (cYAML_get_next_seq_item(nids_entry, &child)) {
                        entry = cYAML_get_object_item(child, "nid");
@@ -2781,7 +2944,8 @@ static int yaml_copy_peer_nids(struct cYAML *tree, char ***nidsppp, bool del)
                        if (!entry || !entry->cy_valuestring)
                                continue;
 
-                       if ((strcmp(entry->cy_valuestring, prim_nid->cy_valuestring)
+                       if (prim_nid &&
+                           (strcmp(entry->cy_valuestring, prim_nid)
                                        == 0) && del) {
                                /*
                                 * primary nid is present in the list of
@@ -2799,8 +2963,8 @@ static int yaml_copy_peer_nids(struct cYAML *tree, char ***nidsppp, bool del)
        if (num == 0)
                return LUSTRE_CFG_RC_MISSING_PARAM;
 
-       nids = calloc(sizeof(*nids) * num, 1);
-       if (nids == NULL)
+       nids = calloc(sizeof(*nids), num);
+       if (!nids)
                return LUSTRE_CFG_RC_OUT_OF_MEM;
 
        /* now grab all the nids */
@@ -2837,19 +3001,41 @@ static int handle_yaml_config_peer(struct cYAML *tree, struct cYAML **show_rc,
 {
        char **nids = NULL;
        int num, rc;
-       struct cYAML *seq_no, *prim_nid, *non_mr;
-
-       num = yaml_copy_peer_nids(tree, &nids, false);
-       if (num < 0)
-               return num;
+       struct cYAML *seq_no, *prim_nid, *non_mr, *ip2nets, *peer_nis;
+       char err_str[LNET_MAX_STR_LEN];
 
        seq_no = cYAML_get_object_item(tree, "seq_no");
        prim_nid = cYAML_get_object_item(tree, "primary nid");
        non_mr = cYAML_get_object_item(tree, "non_mr");
+       ip2nets = cYAML_get_object_item(tree, "ip2nets");
+       peer_nis = cYAML_get_object_item(tree, "peer ni");
+
+       if (ip2nets && (prim_nid || peer_nis)) {
+               rc = LUSTRE_CFG_RC_BAD_PARAM;
+               snprintf(err_str, sizeof(err_str),
+                        "ip2nets can not be specified along side prim_nid"
+                        " or peer ni fields");
+               cYAML_build_error(rc, (seq_no) ? seq_no->cy_valueint : -1,
+                                 ADD_CMD, "peer", err_str, err_rc);
+               return rc;
+       }
+
+       num = yaml_copy_peer_nids((ip2nets) ? ip2nets : peer_nis, &nids,
+                                 (prim_nid) ? prim_nid->cy_valuestring : NULL,
+                                  false);
+
+       if (num < 0) {
+               snprintf(err_str, sizeof(err_str),
+                        "error copying nids from YAML block");
+               cYAML_build_error(num, (seq_no) ? seq_no->cy_valueint : -1,
+                                 ADD_CMD, "peer", err_str, err_rc);
+               return num;
+       }
 
        rc = lustre_lnet_config_peer_nid((prim_nid) ? prim_nid->cy_valuestring : NULL,
                                         nids, num,
                                         (non_mr) ? false : true,
+                                        (ip2nets) ? true : false,
                                         (seq_no) ? seq_no->cy_valueint : -1,
                                         err_rc);
 
@@ -2862,17 +3048,37 @@ static int handle_yaml_del_peer(struct cYAML *tree, struct cYAML **show_rc,
 {
        char **nids = NULL;
        int num, rc;
-       struct cYAML *seq_no, *prim_nid;
-
-       num = yaml_copy_peer_nids(tree, &nids, true);
-       if (num < 0)
-               return num;
+       struct cYAML *seq_no, *prim_nid, *ip2nets, *peer_nis;
+       char err_str[LNET_MAX_STR_LEN];
 
        seq_no = cYAML_get_object_item(tree, "seq_no");
        prim_nid = cYAML_get_object_item(tree, "primary nid");
+       ip2nets = cYAML_get_object_item(tree, "ip2nets");
+       peer_nis = cYAML_get_object_item(tree, "peer ni");
+
+       if (ip2nets && (prim_nid || peer_nis)) {
+               rc = LUSTRE_CFG_RC_BAD_PARAM;
+               snprintf(err_str, sizeof(err_str),
+                        "ip2nets can not be specified along side prim_nid"
+                        " or peer ni fields");
+               cYAML_build_error(rc, (seq_no) ? seq_no->cy_valueint : -1,
+                                 DEL_CMD, "peer", err_str, err_rc);
+               return rc;
+       }
+
+       num = yaml_copy_peer_nids((ip2nets) ? ip2nets : peer_nis , &nids,
+                                 (prim_nid) ? prim_nid->cy_valuestring : NULL,
+                                 true);
+       if (num < 0) {
+               snprintf(err_str, sizeof(err_str),
+                        "error copying nids from YAML block");
+               cYAML_build_error(num, (seq_no) ? seq_no->cy_valueint : -1,
+                                 ADD_CMD, "peer", err_str, err_rc);
+               return num;
+       }
 
        rc = lustre_lnet_del_peer_nid((prim_nid) ? prim_nid->cy_valuestring : NULL,
-                                     nids, num,
+                                     nids, num, (ip2nets) ? true : false,
                                      (seq_no) ? seq_no->cy_valueint : -1,
                                      err_rc);
 
index 5b9e36b..69d66e7 100644 (file)
@@ -37,6 +37,8 @@
 #define LUSTRE_CFG_RC_GENERIC_ERR              -5
 #define LUSTRE_CFG_RC_NO_MATCH                 -6
 #define LUSTRE_CFG_RC_MATCH                    -7
+#define LUSTRE_CFG_RC_SKIP                     -8
+#define LUSTRE_CFG_RC_LAST_ELEM                        -9
 
 #include <lnet/lnet.h>
 #include <libcfs/util/string.h>
@@ -273,11 +275,14 @@ int lustre_lnet_show_stats(int seq_no, struct cYAML **show_rc,
  *     nid - list of nids to add
  *     num_nids - number of nids in the nid array
  *     mr - true if this peer is MR capable.
+ *     ip2nets - true if a list of nid expressions are given to configure
+ *     multiple peers
  *     seq_no - sequence number of the command
  *     err_rc - YAML strucutre of the resultant return code.
  */
 int lustre_lnet_config_peer_nid(char *pnid, char **nid, int num_nids,
-                               bool mr, int seq_no, struct cYAML **err_rc);
+                               bool mr, bool ip2nets, int seq_no,
+                               struct cYAML **err_rc);
 
 /*
  * lustre_lnet_del_peer_nid
@@ -289,11 +294,12 @@ int lustre_lnet_config_peer_nid(char *pnid, char **nid, int num_nids,
  *     pnid - Primary NID of the peer
  *     nid - list of nids to add
  *     num_nids - number of nids in the nid array
+ *     ip2nets - used to specify a range of nids
  *     seq_no - sequence number of the command
  *     err_rc - YAML strucutre of the resultant return code.
  */
 int lustre_lnet_del_peer_nid(char *pnid, char **nid, int num_nids,
-                            int seq_no, struct cYAML **err_rc);
+                            bool ip2nets, int seq_no, struct cYAML **err_rc);
 
 /*
  * lustre_lnet_show_peer
index 70c986a..96bc649 100644 (file)
@@ -140,11 +140,13 @@ command_t peer_cmds[] = {
         "\t            NID in the list becomes the Primary NID of a newly created\n"
         "\t            peer. \n"
         "\t--nid: one or more peer NIDs\n"
-        "\t--non_mr: create this peer as not Multi-Rail capable\n"},
+        "\t--non_mr: create this peer as not Multi-Rail capable\n"
+        "\t--ip2nets: specify a range of nids per peer"},
        {"del", jt_del_peer_nid, 0, "delete a peer NID\n"
         "\t--prim_nid: Primary NID of the peer.\n"
         "\t--nid: list of NIDs to remove. If none provided,\n"
-        "\t       peer is deleted\n"},
+        "\t       peer is deleted\n"
+        "\t--ip2nets: specify a range of nids per peer"},
        {"show", jt_show_peer, 0, "show peer information\n"
         "\t--nid: NID of peer to filter on.\n"
         "\t--verbose: Include  extended  statistics\n"},
@@ -1023,6 +1025,7 @@ static int jt_export(int argc, char **argv)
                case 'h':
                        printf("export FILE\n"
                               "export > FILE : export configuration\n"
+                              "\t--backup: export only what's necessary for reconfig\n"
                               "\t--help: display this help\n");
                        return 0;
                default:
@@ -1087,13 +1090,15 @@ static int jt_add_peer_nid(int argc, char **argv)
        struct cYAML *err_rc = NULL;
        int rc = LUSTRE_CFG_RC_NO_ERR, opt, i;
        bool non_mr = false;
+       bool ip2nets = false, nid_list = false, prim_nid_present = false;
 
-       const char *const short_options = "k:n:mh";
+       const char *const short_options = "k:n:i:mh";
        const struct option long_options[] = {
                { "prim_nid", 1, NULL, 'k' },
                { "nid", 1, NULL, 'n' },
                { "non_mr", 0, NULL, 'm'},
                { "help", 0, NULL, 'h' },
+               { "ip2nets", 1, NULL, 'i' },
                { NULL, 0, NULL, 0 },
        };
 
@@ -1101,9 +1106,32 @@ static int jt_add_peer_nid(int argc, char **argv)
                                  long_options, NULL)) != -1) {
                switch (opt) {
                case 'k':
+                       prim_nid_present = true;
+                       if (ip2nets) {
+                               cYAML_build_error(-1, -1, "peer", "add",
+                                               "ip2nets can not be specified"
+                                               " along side prim_nid parameter.",
+                                               &err_rc);
+                               goto failed;
+                       }
                        prim_nid = optarg;
                        break;
+               case 'i':
                case 'n':
+                       if (opt == 'i')
+                               ip2nets = true;
+
+                       if (opt == 'n')
+                               nid_list = true;
+
+                       if (ip2nets && (nid_list || prim_nid_present)) {
+                               cYAML_build_error(-1, -1, "peer", "add",
+                                               "ip2nets can not be specified"
+                                               " along side nid or prim_nid"
+                                               " parameters", &err_rc);
+                               goto failed;
+                       }
+
                        size = lustre_lnet_parse_nids(optarg, nids, size,
                                                      &nids2);
                        if (nids2 == NULL)
@@ -1122,8 +1150,16 @@ static int jt_add_peer_nid(int argc, char **argv)
                }
        }
 
+       for (; optind < argc; optind++) {
+               size = lustre_lnet_parse_nids(argv[optind], nids, size,
+                                               &nids2);
+               if (nids2 == NULL)
+                       goto failed;
+               nids = nids2;
+       }
+
        rc = lustre_lnet_config_peer_nid(prim_nid, nids, size,
-                                        !non_mr, -1, &err_rc);
+                                        !non_mr, ip2nets, -1, &err_rc);
 
 failed:
        if (nids) {
@@ -1147,12 +1183,14 @@ static int jt_del_peer_nid(int argc, char **argv)
        char **nids = NULL, **nids2 = NULL;
        struct cYAML *err_rc = NULL;
        int rc = LUSTRE_CFG_RC_NO_ERR, opt, i, size = 0;
+       bool ip2nets = false, nid_list = false, prim_nid_present = false;
 
-       const char *const short_options = "k:n:h";
+       const char *const short_options = "k:n:i:h";
        const struct option long_options[] = {
                { "prim_nid", 1, NULL, 'k' },
                { "nid", 1, NULL, 'n' },
                { "help", 0, NULL, 'h' },
+               { "ip2nets", 1, NULL, 'i' },
                { NULL, 0, NULL, 0 },
        };
 
@@ -1160,9 +1198,31 @@ static int jt_del_peer_nid(int argc, char **argv)
                                  long_options, NULL)) != -1) {
                switch (opt) {
                case 'k':
+                       prim_nid_present = true;
+                       if (ip2nets) {
+                               cYAML_build_error(-1, -1, "peer", "add",
+                                               "ip2nets can not be specified"
+                                               " along side prim_nid parameter.",
+                                               &err_rc);
+                               goto failed;
+                       }
                        prim_nid = optarg;
                        break;
+               case 'i':
                case 'n':
+                       if (opt == 'i')
+                               ip2nets = true;
+
+                       if (opt == 'n')
+                               nid_list = true;
+
+                       if (ip2nets && (nid_list || prim_nid_present)) {
+                               cYAML_build_error(-1, -1, "peer", "add",
+                                               "ip2nets can not be specified"
+                                               " along side nid or prim_nid"
+                                               " parameters", &err_rc);
+                               goto failed;
+                       }
                        size = lustre_lnet_parse_nids(optarg, nids, size,
                                                      &nids2);
                        if (nids2 == NULL)
@@ -1178,7 +1238,15 @@ static int jt_del_peer_nid(int argc, char **argv)
                }
        }
 
-       rc = lustre_lnet_del_peer_nid(prim_nid, nids, size, -1, &err_rc);
+       for (; optind < argc; optind++) {
+               size = lustre_lnet_parse_nids(argv[optind], nids, size,
+                                               &nids2);
+               if (nids2 == NULL)
+                       goto failed;
+               nids = nids2;
+       }
+
+       rc = lustre_lnet_del_peer_nid(prim_nid, nids, size, ip2nets, -1, &err_rc);
 
 failed:
        if (nids) {