+#define DBG_CMD "dbg"
+
+/*
+ * lustre_lnet_ip_range_descr
+ * Describes an IP range.
+ * Each octect is an expression
+ */
+struct lustre_lnet_ip_range_descr {
+ struct list_head ipr_entry;
+ struct list_head ipr_expr;
+};
+
+/*
+ * lustre_lnet_ip2nets
+ * Describes an ip2nets rule. This can be on a list of rules.
+ */
+struct lustre_lnet_ip2nets {
+ struct lnet_dlc_network_descr ip2nets_net;
+ struct list_head ip2nets_ip_ranges;
+};
+
+/*
+ * free_intf_descr
+ * frees the memory allocated for an intf descriptor.
+ */
+void free_intf_descr(struct lnet_dlc_intf_descr *intf_descr)
+{
+ if (!intf_descr)
+ return;
+
+ if (intf_descr->cpt_expr != NULL)
+ cfs_expr_list_free(intf_descr->cpt_expr);
+ free(intf_descr);
+}
+
+/*
+ * lustre_lnet_add_ip_range
+ * Formatting:
+ * given a string of the format:
+ * <expr.expr.expr.expr> parse each expr into
+ * a lustre_lnet_ip_range_descr structure and insert on the list.
+ *
+ * This function is called from
+ * YAML on each ip-range.
+ * As a result of lnetctl command
+ * When building a NID or P2P selection rules
+ */
+int lustre_lnet_add_ip_range(struct list_head *list, char *str_ip_range)
+{
+ struct lustre_lnet_ip_range_descr *ip_range;
+ int rc;
+
+ ip_range = calloc(1, sizeof(*ip_range));
+ if (ip_range == NULL)
+ return LUSTRE_CFG_RC_OUT_OF_MEM;
+
+ INIT_LIST_HEAD(&ip_range->ipr_entry);
+ INIT_LIST_HEAD(&ip_range->ipr_expr);
+
+ rc = cfs_ip_addr_parse(str_ip_range, strlen(str_ip_range),
+ &ip_range->ipr_expr);
+ if (rc != 0)
+ return LUSTRE_CFG_RC_BAD_PARAM;
+
+ list_add_tail(&ip_range->ipr_entry, list);
+
+ return LUSTRE_CFG_RC_NO_ERR;
+}
+
+int lustre_lnet_add_intf_descr(struct list_head *list, char *intf, int len)
+{
+ char *open_sq_bracket = NULL, *close_sq_bracket = NULL,
+ *intf_name;
+ struct lnet_dlc_intf_descr *intf_descr = NULL;
+ int rc;
+ char intf_string[LNET_MAX_STR_LEN];
+
+ if (len >= LNET_MAX_STR_LEN)
+ return LUSTRE_CFG_RC_BAD_PARAM;
+
+ strncpy(intf_string, intf, len);
+ intf_string[len] = '\0';
+
+ intf_descr = calloc(1, sizeof(*intf_descr));
+ if (intf_descr == NULL)
+ return LUSTRE_CFG_RC_OUT_OF_MEM;
+
+ INIT_LIST_HEAD(&intf_descr->intf_on_network);
+
+ intf_name = intf_string;
+ open_sq_bracket = strchr(intf_string, '[');
+ if (open_sq_bracket != NULL) {
+ close_sq_bracket = strchr(intf_string, ']');
+ if (close_sq_bracket == NULL) {
+ free(intf_descr);
+ return LUSTRE_CFG_RC_BAD_PARAM;
+ }
+ rc = cfs_expr_list_parse(open_sq_bracket,
+ strlen(open_sq_bracket), 0, UINT_MAX,
+ &intf_descr->cpt_expr);
+ if (rc < 0) {
+ free(intf_descr);
+ return LUSTRE_CFG_RC_BAD_PARAM;
+ }
+ strncpy(intf_descr->intf_name, intf_name,
+ open_sq_bracket - intf_name);
+ intf_descr->intf_name[open_sq_bracket - intf_name] = '\0';
+ } else {
+ strcpy(intf_descr->intf_name, intf_name);
+ intf_descr->cpt_expr = NULL;
+ }
+
+ list_add_tail(&intf_descr->intf_on_network, list);
+
+ return LUSTRE_CFG_RC_NO_ERR;
+}
+
+void lustre_lnet_init_nw_descr(struct lnet_dlc_network_descr *nw_descr)
+{
+ if (nw_descr != NULL) {
+ INIT_LIST_HEAD(&nw_descr->network_on_rule);
+ INIT_LIST_HEAD(&nw_descr->nw_intflist);
+ }
+}
+
+int lustre_lnet_parse_nids(char *nids, char **array, int size,
+ char ***out_array)
+{
+ int num_nids = 0;
+ char *comma = nids, *cur, *entry;
+ char **new_array;
+ int i, len, start = 0, finish = 0;
+
+ if (nids == NULL || strlen(nids) == 0)
+ return size;
+
+ /* count the number or new nids, by counting the number of commas */
+ while (comma) {
+ comma = strchr(comma, ',');
+ if (comma) {
+ comma++;
+ num_nids++;
+ } else {
+ num_nids++;
+ }
+ }
+
+ /*
+ * if the array is not NULL allocate a large enough array to house
+ * the old and new entries
+ */
+ new_array = calloc(sizeof(char*),
+ (size > 0) ? size + num_nids : num_nids);
+
+ if (!new_array)
+ goto failed;
+
+ /* parse our the new nids and add them to the tail of the array */
+ comma = nids;
+ cur = nids;
+ start = (size > 0) ? size: 0;
+ finish = (size > 0) ? size + num_nids : num_nids;
+ for (i = start; i < finish; i++) {
+ comma = strchr(comma, ',');
+ if (!comma)
+ /*
+ * the length of the string to be parsed out is
+ * from cur to end of string. So it's good enough
+ * to strlen(cur)
+ */
+ len = strlen(cur) + 1;
+ else
+ /* length of the string is comma - cur */
+ len = (comma - cur) + 1;
+
+ entry = calloc(1, len);
+ if (!entry) {
+ finish = i > 0 ? i - 1: 0;
+ goto failed;
+ }
+ strncpy(entry, cur, len - 1);
+ entry[len] = '\0';
+ new_array[i] = entry;
+ if (comma) {
+ comma++;
+ cur = comma;
+ }
+ }
+
+ /* add the old entries in the array and delete the old array*/
+ for (i = 0; i < size; i++)
+ new_array[i] = array[i];
+
+ if (array)
+ free(array);
+
+ *out_array = new_array;
+
+ return finish;
+
+failed:
+ for (i = start; i < finish; i++)
+ free(new_array[i]);
+ if (new_array)
+ free(new_array);
+
+ return size;
+}
+
+/*
+ * format expected:
+ * <intf>[<expr>], <intf>[<expr>],..
+ */
+int lustre_lnet_parse_interfaces(char *intf_str,
+ struct lnet_dlc_network_descr *nw_descr)
+{
+ char *open_square;
+ char *close_square;
+ char *comma;
+ char *cur = intf_str, *next = NULL;
+ char *end = intf_str + strlen(intf_str);
+ int rc, len;
+ struct lnet_dlc_intf_descr *intf_descr, *tmp;
+
+ if (nw_descr == NULL)
+ return LUSTRE_CFG_RC_BAD_PARAM;
+
+ while (cur < end) {
+ open_square = strchr(cur, '[');
+ if (open_square != NULL) {
+ close_square = strchr(cur, ']');
+ if (close_square == NULL) {
+ rc = LUSTRE_CFG_RC_BAD_PARAM;
+ goto failed;
+ }
+
+ comma = strchr(cur, ',');
+ if (comma != NULL && comma > close_square) {
+ next = comma + 1;
+ len = next - close_square;
+ } else {
+ len = strlen(cur);
+ next = cur + len;
+ }
+ } else {
+ comma = strchr(cur, ',');
+ if (comma != NULL) {
+ next = comma + 1;
+ len = comma - cur;
+ } else {
+ len = strlen(cur);
+ next = cur + len;
+ }
+ }
+
+ rc = lustre_lnet_add_intf_descr(&nw_descr->nw_intflist, cur, len);
+ if (rc != LUSTRE_CFG_RC_NO_ERR)
+ goto failed;
+
+ cur = next;
+ }
+
+ return LUSTRE_CFG_RC_NO_ERR;
+
+failed:
+ list_for_each_entry_safe(intf_descr, tmp, &nw_descr->nw_intflist,
+ intf_on_network) {
+ list_del(&intf_descr->intf_on_network);
+ free_intf_descr(intf_descr);
+ }
+
+ return rc;
+}