Whamcloud - gitweb
LU-56 libcfs: move range expression parser to libcfs
authorLiang Zhen <liang@whamcloud.com>
Wed, 14 Mar 2012 03:10:20 +0000 (11:10 +0800)
committerOleg Drokin <green@whamcloud.com>
Tue, 22 May 2012 05:50:44 +0000 (01:50 -0400)
There are mulptile implementations of range expression parser,
we removed those redundant code and move the only implementation
into libcfs so everyone can use it.

Signed-off-by: Liang Zhen <liang@whamcloud.com>
Change-Id: I0717fbff2f32a616ff94f6bd53b363fda7d77168
Reviewed-on: http://review.whamcloud.com/2346
Tested-by: Hudson
Reviewed-by: James Simmons <uja.ornl@gmail.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-by: Doug Oucharek <doug@whamcloud.com>
Tested-by: Maloo <whamcloud.maloo@gmail.com>
libcfs/include/libcfs/libcfs_private.h
libcfs/include/libcfs/libcfs_string.h
libcfs/include/libcfs/posix/libcfs.h
libcfs/libcfs/autoMakefile.am
libcfs/libcfs/libcfs_string.c
libcfs/libcfs/nidstrings.c
lnet/lnet/config.c
lustre/include/liblustre.h

index 0b0bf7d..abcc7b8 100644 (file)
@@ -400,7 +400,6 @@ __u32       libcfs_str2net(const char *str);
 lnet_nid_t  libcfs_str2nid(const char *str);
 int         libcfs_str2anynid(lnet_nid_t *nid, const char *str);
 char       *libcfs_id2str(lnet_process_id_t id);
 lnet_nid_t  libcfs_str2nid(const char *str);
 int         libcfs_str2anynid(lnet_nid_t *nid, const char *str);
 char       *libcfs_id2str(lnet_process_id_t id);
-int         cfs_iswhite(char c);
 void        cfs_free_nidlist(cfs_list_t *list);
 int         cfs_parse_nidlist(char *str, int len, cfs_list_t *list);
 int         cfs_match_nid(lnet_nid_t nid, cfs_list_t *list);
 void        cfs_free_nidlist(cfs_list_t *list);
 int         cfs_parse_nidlist(char *str, int len, cfs_list_t *list);
 int         cfs_match_nid(lnet_nid_t nid, cfs_list_t *list);
index 0b520c6..1f8771d 100644 (file)
@@ -61,4 +61,68 @@ int cfs_snprintf(char *buf, size_t size, const char *fmt, ...);
 
 /* trim leading and trailing space characters */
 char *cfs_firststr(char *str, size_t size);
 
 /* trim leading and trailing space characters */
 char *cfs_firststr(char *str, size_t size);
+
+/**
+ * Structure to represent NULL-less strings.
+ */
+struct cfs_lstr {
+       char            *ls_str;
+       int             ls_len;
+};
+
+/*
+ * Structure to represent \<range_expr\> token of the syntax.
+ */
+struct cfs_range_expr {
+       /*
+        * Link to cfs_expr_list::el_exprs.
+        */
+       cfs_list_t      re_link;
+       __u32           re_lo;
+       __u32           re_hi;
+       __u32           re_stride;
+};
+
+struct cfs_expr_list {
+       cfs_list_t      el_link;
+       cfs_list_t      el_exprs;
+};
+
+static inline int
+cfs_iswhite(char c)
+{
+       switch (c) {
+       case ' ':
+       case '\t':
+       case '\n':
+       case '\r':
+               return 1;
+       default:
+               break;
+       }
+       return 0;
+}
+
+char *cfs_trimwhite(char *str);
+int cfs_gettok(struct cfs_lstr *next, char delim, struct cfs_lstr *res);
+int cfs_str2num_check(char *str, int nob, unsigned *num,
+                     unsigned min, unsigned max);
+int cfs_range_expr_parse(struct cfs_lstr *src, unsigned min, unsigned max,
+                        int single_tok, struct cfs_range_expr **expr);
+int cfs_expr_list_match(__u32 value, struct cfs_expr_list *expr_list);
+int cfs_expr_list_values(struct cfs_expr_list *expr_list,
+                        int max, __u32 **values);
+void cfs_expr_list_free(struct cfs_expr_list *expr_list);
+void cfs_expr_list_print(struct cfs_expr_list *expr_list);
+int cfs_expr_list_parse(char *str, int len, unsigned min, unsigned max,
+                       struct cfs_expr_list **elpp);
+void cfs_expr_list_free_list(cfs_list_t *list);
+int cfs_ip_addr_parse(char *str, int len, cfs_list_t *list);
+int cfs_ip_addr_match(__u32 addr, cfs_list_t *list);
+void cfs_ip_addr_free(cfs_list_t *list);
+
+#ifdef __KERNEL__
+#define        strtoul(str, endp, base)        simple_strtoul(str, endp, base)
+#endif
+
 #endif
 #endif
index 02fb2a0..57a6239 100644 (file)
@@ -243,6 +243,8 @@ static inline void MODULE_AUTHOR(char *name)
 #define __init
 #define __exit
 
 #define __init
 #define __exit
 
+#define EXPORT_SYMBOL(symbol)
+
 static inline int cfs_request_module(const char *name, ...)
 {
         return (-EINVAL);
 static inline int cfs_request_module(const char *name, ...)
 {
         return (-EINVAL);
index fc5f4f1..dbbc1fb 100644 (file)
@@ -50,7 +50,7 @@ libcfs_a_CFLAGS = $(LLCFLAGS)
 endif
 
 lib_LIBRARIES = libcfsutil.a
 endif
 
 lib_LIBRARIES = libcfsutil.a
-libcfsutil_a_SOURCES = nidstrings.c util/parser.c \
+libcfsutil_a_SOURCES = nidstrings.c libcfs_string.c util/parser.c \
                        util/l_ioctl.c util/util.c
 libcfsutil_a_CPPFLAGS = $(LLCPPFLAGS) 
 libcfsutil_a_CFLAGS = $(LLCFLAGS) -DLUSTRE_UTILS=1
                        util/l_ioctl.c util/util.c
 libcfsutil_a_CPPFLAGS = $(LLCPPFLAGS) 
 libcfsutil_a_CFLAGS = $(LLCFLAGS) -DLUSTRE_UTILS=1
index e8a05c2..00a732a 100644 (file)
@@ -210,3 +210,441 @@ out:
         return str;
 }
 EXPORT_SYMBOL(cfs_firststr);
         return str;
 }
 EXPORT_SYMBOL(cfs_firststr);
+
+char *
+cfs_trimwhite(char *str)
+{
+       char *end;
+
+       while (cfs_iswhite(*str))
+               str++;
+
+       end = str + strlen(str);
+       while (end > str) {
+               if (!cfs_iswhite(end[-1]))
+                       break;
+               end--;
+       }
+
+       *end = 0;
+       return str;
+}
+EXPORT_SYMBOL(cfs_trimwhite);
+
+/**
+ * Extracts tokens from strings.
+ *
+ * Looks for \a delim in string \a next, sets \a res to point to
+ * substring before the delimiter, sets \a next right after the found
+ * delimiter.
+ *
+ * \retval 1 if \a res points to a string of non-whitespace characters
+ * \retval 0 otherwise
+ */
+int
+cfs_gettok(struct cfs_lstr *next, char delim, struct cfs_lstr *res)
+{
+       char *end;
+
+       if (next->ls_str == NULL)
+               return 0;
+
+       /* skip leading white spaces */
+       while (next->ls_len) {
+               if (!cfs_iswhite(*next->ls_str))
+                       break;
+               next->ls_str++;
+               next->ls_len--;
+       }
+
+       if (next->ls_len == 0) /* whitespaces only */
+               return 0;
+
+       if (*next->ls_str == delim) {
+               /* first non-writespace is the delimiter */
+               return 0;
+       }
+
+       res->ls_str = next->ls_str;
+       end = memchr(next->ls_str, delim, next->ls_len);
+       if (end == NULL) {
+               /* there is no the delimeter in the string */
+               end = next->ls_str + next->ls_len;
+               next->ls_str = NULL;
+       } else {
+               next->ls_str = end + 1;
+               next->ls_len -= (end - res->ls_str + 1);
+       }
+
+       /* skip ending whitespaces */
+       while (--end != res->ls_str) {
+               if (!cfs_iswhite(*end))
+                       break;
+       }
+
+       res->ls_len = end - res->ls_str + 1;
+       return 1;
+}
+EXPORT_SYMBOL(cfs_gettok);
+
+/**
+ * Converts string to integer.
+ *
+ * Accepts decimal and hexadecimal number recordings.
+ *
+ * \retval 1 if first \a nob chars of \a str convert to decimal or
+ * hexadecimal integer in the range [\a min, \a max]
+ * \retval 0 otherwise
+ */
+int
+cfs_str2num_check(char *str, int nob, unsigned *num,
+                 unsigned min, unsigned max)
+{
+       char    *endp;
+
+       str = cfs_trimwhite(str);
+       *num = strtoul(str, &endp, 0);
+       if (endp == str)
+               return 0;
+
+       for (; endp < str + nob; endp++) {
+               if (!cfs_iswhite(*endp))
+                       return 0;
+       }
+
+       return (*num >= min && *num <= max);
+}
+EXPORT_SYMBOL(cfs_str2num_check);
+
+/**
+ * Parses \<range_expr\> token of the syntax. If \a bracketed is false,
+ * \a src should only have a single token which can be \<number\> or  \*
+ *
+ * \retval pointer to allocated range_expr and initialized
+ * range_expr::re_lo, range_expr::re_hi and range_expr:re_stride if \a
+ `* src parses to
+ * \<number\> |
+ * \<number\> '-' \<number\> |
+ * \<number\> '-' \<number\> '/' \<number\>
+ * \retval 0 will be returned if it can be parsed, otherwise -EINVAL or
+ * -ENOMEM will be returned.
+ */
+int
+cfs_range_expr_parse(struct cfs_lstr *src, unsigned min, unsigned max,
+                    int bracketed, struct cfs_range_expr **expr)
+{
+       struct cfs_range_expr   *re;
+       struct cfs_lstr         tok;
+
+       LIBCFS_ALLOC(re, sizeof(*re));
+       if (re == NULL)
+               return -ENOMEM;
+
+       if (src->ls_len == 1 && src->ls_str[0] == '*') {
+               re->re_lo = min;
+               re->re_hi = max;
+               re->re_stride = 1;
+               goto out;
+       }
+
+       if (cfs_str2num_check(src->ls_str, src->ls_len,
+                             &re->re_lo, min, max)) {
+               /* <number> is parsed */
+               re->re_hi = re->re_lo;
+               re->re_stride = 1;
+               goto out;
+       }
+
+       if (!bracketed || !cfs_gettok(src, '-', &tok))
+               goto failed;
+
+       if (!cfs_str2num_check(tok.ls_str, tok.ls_len,
+                              &re->re_lo, min, max))
+               goto failed;
+
+       /* <number> - */
+       if (cfs_str2num_check(src->ls_str, src->ls_len,
+                             &re->re_hi, min, max)) {
+               /* <number> - <number> is parsed */
+               re->re_stride = 1;
+               goto out;
+       }
+
+       /* go to check <number> '-' <number> '/' <number> */
+       if (cfs_gettok(src, '/', &tok)) {
+               if (!cfs_str2num_check(tok.ls_str, tok.ls_len,
+                                      &re->re_hi, min, max))
+                       goto failed;
+
+               /* <number> - <number> / ... */
+               if (cfs_str2num_check(src->ls_str, src->ls_len,
+                                     &re->re_stride, min, max)) {
+                       /* <number> - <number> / <number> is parsed */
+                       goto out;
+               }
+       }
+
+ out:
+       *expr = re;
+       return 0;
+
+ failed:
+       LIBCFS_FREE(re, sizeof(*re));
+       return -EINVAL;
+}
+EXPORT_SYMBOL(cfs_range_expr_parse);
+
+/**
+ * Matches value (\a value) against ranges expression list \a expr_list.
+ *
+ * \retval 1 if \a value matches
+ * \retval 0 otherwise
+ */
+int
+cfs_expr_list_match(__u32 value, struct cfs_expr_list *expr_list)
+{
+       struct cfs_range_expr   *expr;
+
+       cfs_list_for_each_entry(expr, &expr_list->el_exprs, re_link) {
+               if (value >= expr->re_lo && value <= expr->re_hi &&
+                   ((value - expr->re_lo) % expr->re_stride) == 0)
+                       return 1;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL(cfs_expr_list_match);
+
+/**
+ * Convert express list (\a expr_list) to an array of all matched values
+ *
+ * \retval N N is total number of all matched values
+ * \retval 0 if expression list is empty
+ * \retval < 0 for failure
+ */
+int
+cfs_expr_list_values(struct cfs_expr_list *expr_list, int max, __u32 **valpp)
+{
+       struct cfs_range_expr   *expr;
+       __u32                   *val;
+       int                     count = 0;
+       int                     i;
+
+       cfs_list_for_each_entry(expr, &expr_list->el_exprs, re_link) {
+               for (i = expr->re_lo; i <= expr->re_hi; i++) {
+                       if (((i - expr->re_lo) % expr->re_stride) == 0)
+                               count++;
+               }
+       }
+
+       if (count == 0) /* empty expression list */
+               return 0;
+
+       if (count > max) {
+               CERROR("Number of values %d exceeds max allowed %d\n",
+                      max, count);
+               return -EINVAL;
+       }
+
+       LIBCFS_ALLOC(val, sizeof(val[0]) * count);
+       if (val == NULL)
+               return -ENOMEM;
+
+       count = 0;
+       cfs_list_for_each_entry(expr, &expr_list->el_exprs, re_link) {
+               for (i = expr->re_lo; i <= expr->re_hi; i++) {
+                       if (((i - expr->re_lo) % expr->re_stride) == 0)
+                               val[count++] = i;
+               }
+       }
+
+       *valpp = val;
+       return count;
+}
+EXPORT_SYMBOL(cfs_expr_list_values);
+
+/**
+ * Frees cfs_range_expr structures of \a expr_list.
+ *
+ * \retval none
+ */
+void
+cfs_expr_list_free(struct cfs_expr_list *expr_list)
+{
+       while (!cfs_list_empty(&expr_list->el_exprs)) {
+               struct cfs_range_expr *expr;
+
+               expr = cfs_list_entry(expr_list->el_exprs.next,
+                                     struct cfs_range_expr, re_link),
+               cfs_list_del(&expr->re_link);
+               LIBCFS_FREE(expr, sizeof(*expr));
+       }
+
+       LIBCFS_FREE(expr_list, sizeof(*expr_list));
+}
+EXPORT_SYMBOL(cfs_expr_list_free);
+
+void
+cfs_expr_list_print(struct cfs_expr_list *expr_list)
+{
+       struct cfs_range_expr *expr;
+
+       cfs_list_for_each_entry(expr, &expr_list->el_exprs, re_link) {
+               CDEBUG(D_WARNING, "%d-%d/%d\n",
+                      expr->re_lo, expr->re_hi, expr->re_stride);
+       }
+}
+EXPORT_SYMBOL(cfs_expr_list_print);
+
+/**
+ * Parses \<cfs_expr_list\> token of the syntax.
+ *
+ * \retval 1 if \a str parses to \<number\> | \<expr_list\>
+ * \retval 0 otherwise
+ */
+int
+cfs_expr_list_parse(char *str, int len, unsigned min, unsigned max,
+                   struct cfs_expr_list **elpp)
+{
+       struct cfs_expr_list    *expr_list;
+       struct cfs_range_expr   *expr;
+       struct cfs_lstr         src;
+       int                     rc;
+
+       LIBCFS_ALLOC(expr_list, sizeof(*expr_list));
+       if (expr_list == NULL)
+               return -ENOMEM;
+
+       src.ls_str = str;
+       src.ls_len = len;
+
+       CFS_INIT_LIST_HEAD(&expr_list->el_exprs);
+
+       if (src.ls_str[0] == '[' &&
+           src.ls_str[src.ls_len - 1] == ']') {
+               src.ls_str++;
+               src.ls_len -= 2;
+
+               rc = -EINVAL;
+               while (src.ls_str != NULL) {
+                       struct cfs_lstr tok;
+
+                       if (!cfs_gettok(&src, ',', &tok)) {
+                               rc = -EINVAL;
+                               break;
+                       }
+
+                       rc = cfs_range_expr_parse(&tok, min, max, 1, &expr);
+                       if (rc != 0)
+                               break;
+
+                       cfs_list_add_tail(&expr->re_link,
+                                         &expr_list->el_exprs);
+               }
+       } else {
+               rc = cfs_range_expr_parse(&src, min, max, 0, &expr);
+               if (rc == 0) {
+                       cfs_list_add_tail(&expr->re_link,
+                                         &expr_list->el_exprs);
+               }
+       }
+
+       if (rc != 0)
+               cfs_expr_list_free(expr_list);
+       else
+               *elpp = expr_list;
+
+       return rc;
+}
+EXPORT_SYMBOL(cfs_expr_list_parse);
+
+/**
+ * Frees cfs_expr_list structures of \a list.
+ *
+ * For each struct cfs_expr_list structure found on \a list it frees
+ * range_expr list attached to it and frees the cfs_expr_list itself.
+ *
+ * \retval none
+ */
+void
+cfs_expr_list_free_list(cfs_list_t *list)
+{
+       struct cfs_expr_list *el;
+
+       while (!cfs_list_empty(list)) {
+               el = cfs_list_entry(list->next,
+                                   struct cfs_expr_list, el_link);
+               cfs_list_del(&el->el_link);
+               cfs_expr_list_free(el);
+       }
+}
+EXPORT_SYMBOL(cfs_expr_list_free_list);
+
+int
+cfs_ip_addr_parse(char *str, int len, cfs_list_t *list)
+{
+       struct cfs_expr_list    *el;
+       struct cfs_lstr         src;
+       int                     rc;
+       int                     i;
+
+       src.ls_str = str;
+       src.ls_len = len;
+       i = 0;
+
+       while (src.ls_str != NULL) {
+               struct cfs_lstr res;
+
+               if (!cfs_gettok(&src, '.', &res)) {
+                       rc = -EINVAL;
+                       goto out;
+               }
+
+               rc = cfs_expr_list_parse(res.ls_str, res.ls_len, 0, 255, &el);
+               if (rc != 0)
+                       goto out;
+
+               cfs_list_add_tail(&el->el_link, list);
+               i++;
+       }
+
+       if (i == 4)
+               return 0;
+
+       rc = -EINVAL;
+ out:
+       cfs_expr_list_free_list(list);
+
+       return rc;
+}
+EXPORT_SYMBOL(cfs_ip_addr_parse);
+
+/**
+ * Matches address (\a addr) against address set encoded in \a list.
+ *
+ * \retval 1 if \a addr matches
+ * \retval 0 otherwise
+ */
+int
+cfs_ip_addr_match(__u32 addr, cfs_list_t *list)
+{
+       struct cfs_expr_list *el;
+       int i = 0;
+
+       cfs_list_for_each_entry_reverse(el, list, el_link) {
+               if (!cfs_expr_list_match(addr & 0xff, el))
+                       return 0;
+               addr >>= 8;
+               i++;
+       }
+
+       return i == 4;
+}
+EXPORT_SYMBOL(cfs_ip_addr_match);
+
+void
+cfs_ip_addr_free(cfs_list_t *list)
+{
+       cfs_expr_list_free_list(list);
+}
+EXPORT_SYMBOL(cfs_ip_addr_free);
index f045eaf..f448f9e 100644 (file)
@@ -105,9 +105,7 @@ static int  libcfs_ip_str2addr(const char *str, int nob, __u32 *addr);
 static void libcfs_decnum_addr2str(__u32 addr, char *str);
 static void libcfs_hexnum_addr2str(__u32 addr, char *str);
 static int  libcfs_num_str2addr(const char *str, int nob, __u32 *addr);
 static void libcfs_decnum_addr2str(__u32 addr, char *str);
 static void libcfs_hexnum_addr2str(__u32 addr, char *str);
 static int  libcfs_num_str2addr(const char *str, int nob, __u32 *addr);
-static int  libcfs_ip_parse(char *str, int len, cfs_list_t *list);
 static int  libcfs_num_parse(char *str, int len, cfs_list_t *list);
 static int  libcfs_num_parse(char *str, int len, cfs_list_t *list);
-static int  libcfs_ip_match(__u32 addr, cfs_list_t *list);
 static int  libcfs_num_match(__u32 addr, cfs_list_t *list);
 
 struct netstrfns {
 static int  libcfs_num_match(__u32 addr, cfs_list_t *list);
 
 struct netstrfns {
@@ -122,62 +120,62 @@ struct netstrfns {
 };
 
 static struct netstrfns  libcfs_netstrfns[] = {
 };
 
 static struct netstrfns  libcfs_netstrfns[] = {
-        {/* .nf_type      */  LOLND,
-         /* .nf_name      */  "lo",
-         /* .nf_modname   */  "klolnd",
-         /* .nf_addr2str  */  libcfs_decnum_addr2str,
-         /* .nf_str2addr  */  libcfs_lo_str2addr,
-         /* .nf_parse_addr*/  libcfs_num_parse,
-         /* .nf_match_addr*/  libcfs_num_match},
-        {/* .nf_type      */  SOCKLND,
-         /* .nf_name      */  "tcp",
-         /* .nf_modname   */  "ksocklnd",
-         /* .nf_addr2str  */  libcfs_ip_addr2str,
-         /* .nf_str2addr  */  libcfs_ip_str2addr,
-         /* .nf_parse_addrlist*/  libcfs_ip_parse,
-         /* .nf_match_addr*/  libcfs_ip_match},
-        {/* .nf_type      */  O2IBLND,
-         /* .nf_name      */  "o2ib",
-         /* .nf_modname   */  "ko2iblnd",
-         /* .nf_addr2str  */  libcfs_ip_addr2str,
-         /* .nf_str2addr  */  libcfs_ip_str2addr,
-         /* .nf_parse_addrlist*/  libcfs_ip_parse,
-         /* .nf_match_addr*/  libcfs_ip_match},
-        {/* .nf_type      */  CIBLND,
-         /* .nf_name      */  "cib",
-         /* .nf_modname   */  "kciblnd",
-         /* .nf_addr2str  */  libcfs_ip_addr2str,
-         /* .nf_str2addr  */  libcfs_ip_str2addr,
-         /* .nf_parse_addrlist*/  libcfs_ip_parse,
-         /* .nf_match_addr*/  libcfs_ip_match},
-        {/* .nf_type      */  OPENIBLND,
-         /* .nf_name      */  "openib",
-         /* .nf_modname   */  "kopeniblnd",
-         /* .nf_addr2str  */  libcfs_ip_addr2str,
-         /* .nf_str2addr  */  libcfs_ip_str2addr,
-         /* .nf_parse_addrlist*/  libcfs_ip_parse,
-         /* .nf_match_addr*/  libcfs_ip_match},
-        {/* .nf_type      */  IIBLND,
-         /* .nf_name      */  "iib",
-         /* .nf_modname   */  "kiiblnd",
-         /* .nf_addr2str  */  libcfs_ip_addr2str,
-         /* .nf_str2addr  */  libcfs_ip_str2addr,
-         /* .nf_parse_addrlist*/  libcfs_ip_parse,
-         /* .nf_match_addr*/  libcfs_ip_match},
-        {/* .nf_type      */  VIBLND,
-         /* .nf_name      */  "vib",
-         /* .nf_modname   */  "kviblnd",
-         /* .nf_addr2str  */  libcfs_ip_addr2str,
-         /* .nf_str2addr  */  libcfs_ip_str2addr,
-         /* .nf_parse_addrlist*/  libcfs_ip_parse,
-         /* .nf_match_addr*/  libcfs_ip_match},
-        {/* .nf_type      */  RALND,
-         /* .nf_name      */  "ra",
-         /* .nf_modname   */  "kralnd",
-         /* .nf_addr2str  */  libcfs_ip_addr2str,
-         /* .nf_str2addr  */  libcfs_ip_str2addr,
-         /* .nf_parse_addrlist*/  libcfs_ip_parse,
-         /* .nf_match_addr*/  libcfs_ip_match},
+       {/* .nf_type      */  LOLND,
+        /* .nf_name      */  "lo",
+        /* .nf_modname   */  "klolnd",
+        /* .nf_addr2str  */  libcfs_decnum_addr2str,
+        /* .nf_str2addr  */  libcfs_lo_str2addr,
+        /* .nf_parse_addr*/  libcfs_num_parse,
+        /* .nf_match_addr*/  libcfs_num_match},
+       {/* .nf_type      */  SOCKLND,
+        /* .nf_name      */  "tcp",
+        /* .nf_modname   */  "ksocklnd",
+        /* .nf_addr2str  */  libcfs_ip_addr2str,
+        /* .nf_str2addr  */  libcfs_ip_str2addr,
+        /* .nf_parse_addrlist*/  cfs_ip_addr_parse,
+        /* .nf_match_addr*/  cfs_ip_addr_match},
+       {/* .nf_type      */  O2IBLND,
+        /* .nf_name      */  "o2ib",
+        /* .nf_modname   */  "ko2iblnd",
+        /* .nf_addr2str  */  libcfs_ip_addr2str,
+        /* .nf_str2addr  */  libcfs_ip_str2addr,
+        /* .nf_parse_addrlist*/  cfs_ip_addr_parse,
+        /* .nf_match_addr*/  cfs_ip_addr_match},
+       {/* .nf_type      */  CIBLND,
+        /* .nf_name      */  "cib",
+        /* .nf_modname   */  "kciblnd",
+        /* .nf_addr2str  */  libcfs_ip_addr2str,
+        /* .nf_str2addr  */  libcfs_ip_str2addr,
+        /* .nf_parse_addrlist*/  cfs_ip_addr_parse,
+        /* .nf_match_addr*/  cfs_ip_addr_match},
+       {/* .nf_type      */  OPENIBLND,
+        /* .nf_name      */  "openib",
+        /* .nf_modname   */  "kopeniblnd",
+        /* .nf_addr2str  */  libcfs_ip_addr2str,
+        /* .nf_str2addr  */  libcfs_ip_str2addr,
+        /* .nf_parse_addrlist*/  cfs_ip_addr_parse,
+        /* .nf_match_addr*/  cfs_ip_addr_match},
+       {/* .nf_type      */  IIBLND,
+        /* .nf_name      */  "iib",
+        /* .nf_modname   */  "kiiblnd",
+        /* .nf_addr2str  */  libcfs_ip_addr2str,
+        /* .nf_str2addr  */  libcfs_ip_str2addr,
+        /* .nf_parse_addrlist*/  cfs_ip_addr_parse,
+        /* .nf_match_addr*/  cfs_ip_addr_match},
+       {/* .nf_type      */  VIBLND,
+        /* .nf_name      */  "vib",
+        /* .nf_modname   */  "kviblnd",
+        /* .nf_addr2str  */  libcfs_ip_addr2str,
+        /* .nf_str2addr  */  libcfs_ip_str2addr,
+        /* .nf_parse_addrlist*/  cfs_ip_addr_parse,
+        /* .nf_match_addr*/  cfs_ip_addr_match},
+       {/* .nf_type      */  RALND,
+        /* .nf_name      */  "ra",
+        /* .nf_modname   */  "kralnd",
+        /* .nf_addr2str  */  libcfs_ip_addr2str,
+        /* .nf_str2addr  */  libcfs_ip_str2addr,
+        /* .nf_parse_addrlist*/  cfs_ip_addr_parse,
+        /* .nf_match_addr*/  cfs_ip_addr_match},
         {/* .nf_type      */  QSWLND,
          /* .nf_name      */  "elan",
          /* .nf_modname   */  "kqswlnd",
         {/* .nf_type      */  QSWLND,
          /* .nf_name      */  "elan",
          /* .nf_modname   */  "kqswlnd",
@@ -192,13 +190,13 @@ static struct netstrfns  libcfs_netstrfns[] = {
          /* .nf_str2addr  */  libcfs_num_str2addr,
          /* .nf_parse_addrlist*/  libcfs_num_parse,
          /* .nf_match_addr*/  libcfs_num_match},
          /* .nf_str2addr  */  libcfs_num_str2addr,
          /* .nf_parse_addrlist*/  libcfs_num_parse,
          /* .nf_match_addr*/  libcfs_num_match},
-        {/* .nf_type      */  MXLND,
-         /* .nf_name      */  "mx",
-         /* .nf_modname   */  "kmxlnd",
-         /* .nf_addr2str  */  libcfs_ip_addr2str,
-         /* .nf_str2addr  */  libcfs_ip_str2addr,
-         /* .nf_parse_addrlist*/  libcfs_ip_parse,
-         /* .nf_match_addr*/  libcfs_ip_match},
+       {/* .nf_type      */  MXLND,
+        /* .nf_name      */  "mx",
+        /* .nf_modname   */  "kmxlnd",
+        /* .nf_addr2str  */  libcfs_ip_addr2str,
+        /* .nf_str2addr  */  libcfs_ip_str2addr,
+        /* .nf_parse_addrlist*/  cfs_ip_addr_parse,
+        /* .nf_match_addr*/  cfs_ip_addr_match},
         {/* .nf_type      */  PTLLND,
          /* .nf_name      */  "ptl",
          /* .nf_modname   */  "kptllnd",
         {/* .nf_type      */  PTLLND,
          /* .nf_name      */  "ptl",
          /* .nf_modname   */  "kptllnd",
@@ -572,10 +570,10 @@ libcfs_str2anynid(lnet_nid_t *nidp, const char *str)
  * <nidrange>        :== <addrrange> '@' <net>
  * <addrrange>       :== '*' |
  *                       <ipaddr_range> |
  * <nidrange>        :== <addrrange> '@' <net>
  * <addrrange>       :== '*' |
  *                       <ipaddr_range> |
- *                       <numaddr_range>
- * <ipaddr_range>    :== <numaddr_range>.<numaddr_range>.<numaddr_range>.
- *                       <numaddr_range>
- * <numaddr_range>   :== <number> |
+ *                      <cfs_expr_list>
+ * <ipaddr_range>    :== <cfs_expr_list>.<cfs_expr_list>.<cfs_expr_list>.
+ *                      <cfs_expr_list>
+ * <cfs_expr_list>   :== <number> |
  *                       <expr_list>
  * <expr_list>       :== '[' <range_expr> [ ',' <range_expr>] ']'
  * <range_expr>      :== <number> |
  *                       <expr_list>
  * <expr_list>       :== '[' <range_expr> [ ',' <range_expr>] ']'
  * <range_expr>      :== <number> |
@@ -588,14 +586,6 @@ libcfs_str2anynid(lnet_nid_t *nidp, const char *str)
  */
 
 /**
  */
 
 /**
- * Structure to represent NULL-less strings.
- */
-struct lstr {
-        char *ls_str;
-        int ls_len;
-};
-
-/**
  * Structure to represent \<nidrange\> token of the syntax.
  *
  * One of this is created for each \<net\> parsed.
  * Structure to represent \<nidrange\> token of the syntax.
  *
  * One of this is created for each \<net\> parsed.
@@ -633,310 +623,30 @@ struct addrrange {
          */
         cfs_list_t ar_link;
         /**
          */
         cfs_list_t ar_link;
         /**
-         * List head for numaddr_range::nar_link.
+        * List head for cfs_expr_list::el_list.
          */
         cfs_list_t ar_numaddr_ranges;
 };
 
 /**
          */
         cfs_list_t ar_numaddr_ranges;
 };
 
 /**
- * Structure to represent \<numaddr_range\> token of the syntax.
- */
-struct numaddr_range {
-        /**
-         * Link to addrrange::ar_numaddr_ranges.
-         */
-        cfs_list_t nar_link;
-        /**
-         * List head for range_expr::re_link.
-         */
-        cfs_list_t nar_range_exprs;
-};
-
-/**
- * Structure to represent \<range_expr\> token of the syntax.
- */
-struct range_expr {
-        /**
-         * Link to numaddr_range::nar_range_exprs.
-         */
-        cfs_list_t re_link;
-        __u32 re_lo;
-        __u32 re_hi;
-        __u32 re_stride;
-};
-
-int
-cfs_iswhite(char c)
-{
-        switch (c) {
-        case ' ':
-        case '\t':
-        case '\n':
-        case '\r':
-                return 1;
-        default:
-                break;
-        }
-        return 0;
-}
-
-/*
- * Extracts tokens from strings.
- *
- * Looks for \a delim in string \a next, sets \a res to point to
- * substring before the delimiter, sets \a next right after the found
- * delimiter.
- *
- * \retval 1 if \a res points to a string of non-whitespace characters
- * \retval 0 otherwise
- */
-static int
-gettok(struct lstr *next, char delim, struct lstr *res)
-{
-        char *end;
-
-        if (next->ls_str == NULL)
-                return 0;
-
-        /* skip leading white spaces */
-        while (next->ls_len) {
-                if (!cfs_iswhite(*next->ls_str))
-                        break;
-                next->ls_str ++;
-                next->ls_len --;
-        }
-        if (next->ls_len == 0)
-                /* whitespaces only */
-                return 0;
-
-        if (*next->ls_str == delim)
-                /* first non-writespace is the delimiter */
-                return 0;
-
-        res->ls_str = next->ls_str;
-        end = memchr(next->ls_str, delim, next->ls_len);
-        if (end == NULL) {
-                /* there is no the delimeter in the string */
-                end = next->ls_str + next->ls_len;
-                next->ls_str = NULL;
-        } else {
-                next->ls_str = end + 1;
-                next->ls_len -= (end - res->ls_str + 1);
-        }
-
-        /* skip ending whitespaces */
-        while (--end != res->ls_str)
-                if (!cfs_iswhite(*end))
-                        break;
-
-        res->ls_len = end - res->ls_str + 1;
-        return 1;
-}
-
-/**
- * Converts string to integer.
- *
- * Accepts decimal and hexadecimal number recordings.
- *
- * \retval 1 if first \a nob chars of \a str convert to decimal or
- * hexadecimal integer in the range [\a min, \a max]
- * \retval 0 otherwise
- */
-static int
-libcfs_str2num_check(const char *str, int nob, unsigned *num,
-                     unsigned min, unsigned max)
-{
-        int n;
-        char nstr[12];
-
-        n = nob;
-        if (sscanf(str, "%u%n", num, &n) != 1 || n != nob)
-                if (sscanf(str, "0x%x%n", num, &n) != 1 || n != nob)
-                        if (sscanf(str, "0X%x%n", num, &n) != 1 || n != nob)
-                                return 0;
-        sprintf(nstr, "%u", *num);
-        if (n != strlen(nstr) || memcmp(nstr, str, n)) {
-                sprintf(nstr, "0x%x", *num);
-                if (n != strlen(nstr) || memcmp(nstr, str, n)) {
-                        sprintf(nstr, "0X%x", *num);
-                        if (n != strlen(nstr) || memcmp(nstr, str, n))
-                                return 0;
-                }
-        }
-        if (*num < min || *num > max)
-                return 0;
-        return 1;
-}
-
-/**
- * Parses \<range_expr\> token of the syntax.
- *
- * \retval pointer to allocated range_expr and initialized
- * range_expr::re_lo, range_expr::re_hi and range_expr:re_stride if \a
- `* src parses to
- * \<number\> |
- * \<number\> '-' \<number\> |
- * \<number\> '-' \<number\> '/' \<number\>
- * \retval NULL othersize
- */
-static struct range_expr *
-parse_range_expr(struct lstr *src, unsigned min, unsigned max)
-{
-        struct lstr tok;
-        struct range_expr *expr;
-
-        LIBCFS_ALLOC(expr, sizeof(struct range_expr));
-        if (expr == NULL)
-                return NULL;
-
-        if (libcfs_str2num_check(src->ls_str, src->ls_len, &expr->re_lo,
-                                 min, max)) {
-                /* <number> is parsed */
-                expr->re_hi = expr->re_lo;
-                expr->re_stride = 1;
-                return expr;
-        }
-
-        if (!gettok(src, '-', &tok))
-                goto failed;
-        if (!libcfs_str2num_check(tok.ls_str, tok.ls_len, &expr->re_lo,
-                                  min, max))
-                goto failed;
-        /* <number> - */
-        if (libcfs_str2num_check(src->ls_str, src->ls_len, &expr->re_hi,
-                                 min, max)) {
-                /* <number> - <number> is parsed */
-                expr->re_stride = 1;
-                return expr;
-        }
-
-        /* go to check <number> '-' <number> '/' <number> */
-        if (gettok(src, '/', &tok)) {
-                if (!libcfs_str2num_check(tok.ls_str, tok.ls_len,
-                                          &expr->re_hi, min, max))
-                        goto failed;
-                /* <number> - <number> / ... */
-                if (libcfs_str2num_check(src->ls_str, src->ls_len,
-                                         &expr->re_stride, min, max))
-                        /* <number> - <number> / <number> is parsed */
-                        return expr;
-        }
-
-failed:
-        LIBCFS_FREE(expr, sizeof(struct range_expr));
-        return NULL;
-}
-
-/**
- * Parses \<expr_list\> token of the syntax.
- *
- * \retval 1 if \a str parses to '[' \<range_expr\> [ ',' \<range_expr\>] ']'
- * \retval 0 otherwise
- */
-static int
-parse_expr_list(struct lstr *str, cfs_list_t *list,
-                unsigned min, unsigned max)
-{
-        struct lstr res;
-        struct range_expr *range;
-
-        if (str->ls_str[0] != '[' || str->ls_str[str->ls_len - 1] != ']')
-                return 0;
-        str->ls_str ++;
-        str->ls_len -= 2;
-
-        while (str->ls_str) {
-                if (gettok(str, ',', &res) == 0)
-                        return 0;
-                range = parse_range_expr(&res, min, max);
-                if (range == NULL)
-                        return 0;
-                cfs_list_add_tail(&range->re_link, list);
-        }
-        return 1;
-}
-
-/**
- * Parses \<numaddr_range\> token of the syntax.
- *
- * \retval 1 if \a str parses to \<number\> | \<expr_list\>
- * \retval 0 otherwise
- */
-static int
-num_parse(char *str, int len,
-          cfs_list_t *list, unsigned min, unsigned max)
-{
-        __u32 num;
-        struct lstr src;
-        struct numaddr_range *numaddr;
-
-        src.ls_str = str;
-        src.ls_len = len;
-
-        LIBCFS_ALLOC(numaddr, sizeof(struct numaddr_range));
-        if (numaddr == NULL)
-                return 0;
-        cfs_list_add_tail(&numaddr->nar_link, list);
-        CFS_INIT_LIST_HEAD(&numaddr->nar_range_exprs);
-
-        if (libcfs_str2num_check(src.ls_str, src.ls_len, &num, min, max)) {
-                /* <number> */
-                struct range_expr *expr;
-
-                LIBCFS_ALLOC(expr, sizeof(struct range_expr));
-                if (expr == NULL)
-                        return 0;
-
-                expr->re_lo = expr->re_hi = num;
-                expr->re_stride = 1;
-                cfs_list_add_tail(&expr->re_link, &numaddr->nar_range_exprs);
-                return 1;
-        }
-
-        return parse_expr_list(&src, &numaddr->nar_range_exprs, min, max);
-}
-
-/**
  * Nf_parse_addrlist method for networks using numeric addresses.
  *
  * Examples of such networks are gm and elan.
  *
  * Nf_parse_addrlist method for networks using numeric addresses.
  *
  * Examples of such networks are gm and elan.
  *
- * \retval 1 if \a str parsed to numeric address
- * \retval 0 otherwise
+ * \retval 0 if \a str parsed to numeric address
+ * \retval errno otherwise
  */
 static int
 libcfs_num_parse(char *str, int len, cfs_list_t *list)
 {
  */
 static int
 libcfs_num_parse(char *str, int len, cfs_list_t *list)
 {
-        return num_parse(str, len, list, 0, MAX_NUMERIC_VALUE);
-}
+       struct cfs_expr_list *el;
+       int     rc;
 
 
-/**
- * Nf_parse_addrlist method for networks using ip addresses.
- *
- * Examples of such networks are tcp and o2ib.
- *
- * \retval 1 if \a str parsed to ip address
- * \retval 0 otherwise
- */
-static int
-libcfs_ip_parse(char *str, int len,
-                cfs_list_t *list)
-{
-        struct lstr src, res;
-        int i;
+       rc = cfs_expr_list_parse(str, len, 0, MAX_NUMERIC_VALUE, &el);
+       if (rc == 0)
+               cfs_list_add_tail(&el->el_link, list);
 
 
-        src.ls_str = str;
-        src.ls_len = len;
-        i = 0;
-        while (src.ls_str) {
-                if (gettok(&src, '.', &res) == 0)
-                        return 0;
-                if (!num_parse(res.ls_str, res.ls_len, list, 0, 255))
-                        return 0;
-                i ++;
-        }
-
-        return (i == 4) ? 1 : 0;
+       return rc;
 }
 
 /**
 }
 
 /**
@@ -945,11 +655,11 @@ libcfs_ip_parse(char *str, int len,
  * Allocates struct addrrange and links to \a nidrange via
  * (nidrange::nr_addrranges)
  *
  * Allocates struct addrrange and links to \a nidrange via
  * (nidrange::nr_addrranges)
  *
- * \retval 1 if \a src parses to '*' | \<ipaddr_range\> | \<numaddr_range\>
+ * \retval 1 if \a src parses to '*' | \<ipaddr_range\> | \<cfs_expr_list\>
  * \retval 0 otherwise
  */
 static int
  * \retval 0 otherwise
  */
 static int
-parse_addrange(const struct lstr *src, struct nidrange *nidrange)
+parse_addrange(const struct cfs_lstr *src, struct nidrange *nidrange)
 {
         struct addrrange *addrrange;
 
 {
         struct addrrange *addrrange;
 
@@ -980,7 +690,7 @@ parse_addrange(const struct lstr *src, struct nidrange *nidrange)
  * \retval NULL if \a src does not match any network
  */
 static struct nidrange *
  * \retval NULL if \a src does not match any network
  */
 static struct nidrange *
-add_nidrange(const struct lstr *src,
+add_nidrange(const struct cfs_lstr *src,
              cfs_list_t *nidlist)
 {
         struct netstrfns *nf;
              cfs_list_t *nidlist)
 {
         struct netstrfns *nf;
@@ -1002,9 +712,8 @@ add_nidrange(const struct lstr *src,
                 /* e.g. "elan25" or "tcp23", refuse to parse if
                  * network name is not appended with decimal or
                  * hexadecimal number */
                 /* e.g. "elan25" or "tcp23", refuse to parse if
                  * network name is not appended with decimal or
                  * hexadecimal number */
-                if (!libcfs_str2num_check(src->ls_str + strlen(nf->nf_name),
-                                          endlen, &netnum,
-                                          0, MAX_NUMERIC_VALUE))
+               if (!cfs_str2num_check(src->ls_str + strlen(nf->nf_name),
+                                      endlen, &netnum, 0, MAX_NUMERIC_VALUE))
                         return NULL;
         }
 
                         return NULL;
         }
 
@@ -1035,23 +744,25 @@ add_nidrange(const struct lstr *src,
  * \retval 0 otherwise
  */
 static int
  * \retval 0 otherwise
  */
 static int
-parse_nidrange(struct lstr *src, cfs_list_t *nidlist)
+parse_nidrange(struct cfs_lstr *src, cfs_list_t *nidlist)
 {
 {
-        struct lstr addrrange, net, tmp;
+       struct cfs_lstr addrrange;
+       struct cfs_lstr net;
+       struct cfs_lstr tmp;
         struct nidrange *nr;
 
         tmp = *src;
         struct nidrange *nr;
 
         tmp = *src;
-        if (gettok(src, '@', &addrrange) == 0)
+       if (cfs_gettok(src, '@', &addrrange) == 0)
                 goto failed;
 
                 goto failed;
 
-        if (gettok(src, '@', &net) == 0 || src->ls_str != NULL)
+       if (cfs_gettok(src, '@', &net) == 0 || src->ls_str != NULL)
                 goto failed;
 
         nr = add_nidrange(&net, nidlist);
         if (nr == NULL)
                 goto failed;
 
                 goto failed;
 
         nr = add_nidrange(&net, nidlist);
         if (nr == NULL)
                 goto failed;
 
-        if (!parse_addrange(&addrrange, nr))
+       if (parse_addrange(&addrrange, nr) != 0)
                 goto failed;
 
         return 1;
                 goto failed;
 
         return 1;
@@ -1061,64 +772,25 @@ parse_nidrange(struct lstr *src, cfs_list_t *nidlist)
 }
 
 /**
 }
 
 /**
- * Frees range_expr structures of \a list.
- *
- * \retval none
- */
-static void
-free_range_exprs(cfs_list_t *list)
-{
-        cfs_list_t *pos, *next;
-
-        cfs_list_for_each_safe(pos, next, list) {
-                cfs_list_del(pos);
-                LIBCFS_FREE(cfs_list_entry(pos, struct range_expr, re_link),
-                            sizeof(struct range_expr));
-        }
-}
-
-/**
- * Frees numaddr_range structures of \a list.
- *
- * For each struct numaddr_range structure found on \a list it frees
- * range_expr list attached to it and frees the numddr_range itself.
- *
- * \retval none
- */
-static void
-free_numaddr_ranges(cfs_list_t *list)
-{
-        cfs_list_t *pos, *next;
-        struct numaddr_range *numaddr;
-
-        cfs_list_for_each_safe(pos, next, list) {
-                numaddr = cfs_list_entry(pos, struct numaddr_range, nar_link);
-                free_range_exprs(&numaddr->nar_range_exprs);
-                cfs_list_del(pos);
-                LIBCFS_FREE(numaddr, sizeof(struct numaddr_range));
-        }
-}
-
-/**
  * Frees addrrange structures of \a list.
  *
  * For each struct addrrange structure found on \a list it frees
  * Frees addrrange structures of \a list.
  *
  * For each struct addrrange structure found on \a list it frees
- * numaddr_range list attached to it and frees the addrrange itself.
+ * cfs_expr_list list attached to it and frees the addrrange itself.
  *
  * \retval none
  */
 static void
 free_addrranges(cfs_list_t *list)
 {
  *
  * \retval none
  */
 static void
 free_addrranges(cfs_list_t *list)
 {
-        cfs_list_t *pos, *next;
-        struct addrrange *ar;
+       while (!cfs_list_empty(list)) {
+               struct addrrange *ar;
 
 
-        cfs_list_for_each_safe(pos, next, list) {
-                ar = cfs_list_entry(pos, struct addrrange, ar_link);
-                free_numaddr_ranges(&ar->ar_numaddr_ranges);
-                cfs_list_del(pos);
-                LIBCFS_FREE(ar, sizeof(struct addrrange));
-        }
+               ar = cfs_list_entry(list->next, struct addrrange, ar_link);
+
+               cfs_expr_list_free_list(&ar->ar_numaddr_ranges);
+               cfs_list_del(&ar->ar_link);
+               LIBCFS_FREE(ar, sizeof(struct addrrange));
+       }
 }
 
 /**
 }
 
 /**
@@ -1159,7 +831,8 @@ cfs_free_nidlist(cfs_list_t *list)
 int
 cfs_parse_nidlist(char *str, int len, cfs_list_t *nidlist)
 {
 int
 cfs_parse_nidlist(char *str, int len, cfs_list_t *nidlist)
 {
-        struct lstr src, res;
+       struct cfs_lstr src;
+       struct cfs_lstr res;
         int rc;
         ENTRY;
 
         int rc;
         ENTRY;
 
@@ -1167,7 +840,7 @@ cfs_parse_nidlist(char *str, int len, cfs_list_t *nidlist)
         src.ls_len = len;
         CFS_INIT_LIST_HEAD(nidlist);
         while (src.ls_str) {
         src.ls_len = len;
         CFS_INIT_LIST_HEAD(nidlist);
         while (src.ls_str) {
-                rc = gettok(&src, ' ', &res);
+               rc = cfs_gettok(&src, ' ', &res);
                 if (rc == 0) {
                         cfs_free_nidlist(nidlist);
                         RETURN(0);
                 if (rc == 0) {
                         cfs_free_nidlist(nidlist);
                         RETURN(0);
@@ -1181,41 +854,6 @@ cfs_parse_nidlist(char *str, int len, cfs_list_t *nidlist)
         RETURN(1);
 }
 
         RETURN(1);
 }
 
-/**
- * Matches address (\a addr) against address set encoded in \a list.
- *
- * \see libcfs_num_match(), libcfs_ip_match()
- *
- * \retval 1 if \a addr matches
- * \retval 0 otherwise
- */
-static int
-match_numaddr(__u32 addr, cfs_list_t *list, int shift, __u32 mask)
-{
-        struct numaddr_range *numaddr;
-        struct range_expr *expr;
-        int ip, ok;
-        ENTRY;
-
-        cfs_list_for_each_entry(numaddr, list, nar_link) {
-                ip = (addr >> shift) & mask;
-                shift -= 8;
-                ok = 0;
-                cfs_list_for_each_entry(expr, &numaddr->nar_range_exprs,
-                                        re_link) {
-                        if (ip >= expr->re_lo &&
-                            ip <= expr->re_hi &&
-                            ((ip - expr->re_lo) % expr->re_stride) == 0) {
-                                ok = 1;
-                                break;
-                        }
-                }
-                if (!ok)
-                        RETURN(0);
-        }
-        RETURN(1);
-}
-
 /*
  * Nf_match_addr method for networks using numeric addresses
  *
 /*
  * Nf_match_addr method for networks using numeric addresses
  *
@@ -1225,19 +863,12 @@ match_numaddr(__u32 addr, cfs_list_t *list, int shift, __u32 mask)
 static int
 libcfs_num_match(__u32 addr, cfs_list_t *numaddr)
 {
 static int
 libcfs_num_match(__u32 addr, cfs_list_t *numaddr)
 {
-        return match_numaddr(addr, numaddr, 0, 0xffffffff);
-}
+       struct cfs_expr_list *el;
 
 
-/*
- * Nf_match_addr method for networks using ip addresses
- *
- * \retval 1 on match
- * \retval 0 otherwise
- */
-static int
-libcfs_ip_match(__u32 addr, cfs_list_t *numaddr)
-{
-        return match_numaddr(addr, numaddr, 24, 0xff);
+       LASSERT(!cfs_list_empty(numaddr));
+       el = cfs_list_entry(numaddr->next, struct cfs_expr_list, el_link);
+
+       return cfs_expr_list_match(addr, el);
 }
 
 /**
 }
 
 /**
@@ -1281,7 +912,6 @@ EXPORT_SYMBOL(libcfs_str2net);
 EXPORT_SYMBOL(libcfs_str2nid);
 EXPORT_SYMBOL(libcfs_id2str);
 EXPORT_SYMBOL(libcfs_str2anynid);
 EXPORT_SYMBOL(libcfs_str2nid);
 EXPORT_SYMBOL(libcfs_id2str);
 EXPORT_SYMBOL(libcfs_str2anynid);
-EXPORT_SYMBOL(cfs_iswhite);
 EXPORT_SYMBOL(cfs_free_nidlist);
 EXPORT_SYMBOL(cfs_parse_nidlist);
 EXPORT_SYMBOL(cfs_match_nid);
 EXPORT_SYMBOL(cfs_free_nidlist);
 EXPORT_SYMBOL(cfs_parse_nidlist);
 EXPORT_SYMBOL(cfs_match_nid);
index 5ddff9c..9c4660e 100644 (file)
@@ -45,15 +45,6 @@ static int lnet_tbnob = 0;                   /* track text buf allocation */
 #define LNET_MAX_TEXTBUF_NOB     (64<<10)      /* bound allocation */
 #define LNET_SINGLE_TEXTBUF_NOB  (4<<10)
 
 #define LNET_MAX_TEXTBUF_NOB     (64<<10)      /* bound allocation */
 #define LNET_SINGLE_TEXTBUF_NOB  (4<<10)
 
-typedef struct {
-        cfs_list_t         lre_list;            /* stash in a list */
-        int                lre_min;             /* min value */
-        int                lre_max;             /* max value */
-        int                lre_stride;          /* stride */
-} lnet_range_expr_t;
-
-static int lnet_re_alloc = 0;                   /* track expr allocation */
-
 void
 lnet_syntax(char *name, char *str, int offset, int width)
 {
 void
 lnet_syntax(char *name, char *str, int offset, int width)
 {
@@ -84,25 +75,6 @@ lnet_issep (char c)
        }
 }
 
        }
 }
 
-char *
-lnet_trimwhite(char *str)
-{
-       char *end;
-
-        while (cfs_iswhite(*str))
-               str++;
-
-       end = str + strlen(str);
-       while (end > str) {
-                if (!cfs_iswhite(end[-1]))
-                       break;
-               end--;
-       }
-
-       *end = 0;
-       return str;
-}
-
 int
 lnet_net_unique(__u32 net, cfs_list_t *nilist)
 {
 int
 lnet_net_unique(__u32 net, cfs_list_t *nilist)
 {
@@ -198,10 +170,10 @@ lnet_parse_networks(cfs_list_t *nilist, char *networks)
 
                        if (comma != NULL)
                                *comma++ = 0;
 
                        if (comma != NULL)
                                *comma++ = 0;
-                       net = libcfs_str2net(lnet_trimwhite(str));
-                       
+                       net = libcfs_str2net(cfs_trimwhite(str));
+
                        if (net == LNET_NIDNET(LNET_NID_ANY)) {
                        if (net == LNET_NIDNET(LNET_NID_ANY)) {
-                                lnet_syntax("networks", networks, 
+                               lnet_syntax("networks", networks,
                                             (int)(str - tokens), strlen(str));
                                 LCONSOLE_ERROR_MSG(0x113, "Unrecognised network"
                                                    " type\n");
                                             (int)(str - tokens), strlen(str));
                                 LCONSOLE_ERROR_MSG(0x113, "Unrecognised network"
                                                    " type\n");
@@ -217,12 +189,12 @@ lnet_parse_networks(cfs_list_t *nilist, char *networks)
                }
 
                *bracket = 0;
                }
 
                *bracket = 0;
-               net = libcfs_str2net(lnet_trimwhite(str));
+               net = libcfs_str2net(cfs_trimwhite(str));
                if (net == LNET_NIDNET(LNET_NID_ANY)) {
                if (net == LNET_NIDNET(LNET_NID_ANY)) {
-                        lnet_syntax("networks", networks,
-                                    (int)(str - tokens), strlen(str));
-                        goto failed;
-                } 
+                       lnet_syntax("networks", networks,
+                                   (int)(str - tokens), strlen(str));
+                       goto failed;
+               }
 
                 nnets++;
                 ni = lnet_new_ni(net, nilist);
 
                 nnets++;
                 ni = lnet_new_ni(net, nilist);
@@ -244,11 +216,12 @@ lnet_parse_networks(cfs_list_t *nilist, char *networks)
                        comma = strchr(iface, ',');
                        if (comma != NULL)
                                *comma++ = 0;
                        comma = strchr(iface, ',');
                        if (comma != NULL)
                                *comma++ = 0;
-                       
-                       iface = lnet_trimwhite(iface);
+
+                       iface = cfs_trimwhite(iface);
                        if (*iface == 0) {
                        if (*iface == 0) {
-                                lnet_syntax("networks", networks, 
-                                            (int)(iface - tokens), strlen(iface));
+                               lnet_syntax("networks", networks,
+                                           (int)(iface - tokens),
+                                           strlen(iface));
                                 goto failed;
                         }
 
                                 goto failed;
                         }
 
@@ -267,7 +240,7 @@ lnet_parse_networks(cfs_list_t *nilist, char *networks)
                comma = strchr(bracket + 1, ',');
                if (comma != NULL) {
                        *comma = 0;
                comma = strchr(bracket + 1, ',');
                if (comma != NULL) {
                        *comma = 0;
-                       str = lnet_trimwhite(str);
+                       str = cfs_trimwhite(str);
                        if (*str != 0) {
                                 lnet_syntax("networks", networks,
                                             (int)(str - tokens), strlen(str));
                        if (*str != 0) {
                                 lnet_syntax("networks", networks,
                                             (int)(str - tokens), strlen(str));
@@ -276,8 +249,8 @@ lnet_parse_networks(cfs_list_t *nilist, char *networks)
                        str = comma + 1;
                        continue;
                }
                        str = comma + 1;
                        continue;
                }
-               
-               str = lnet_trimwhite(str);
+
+               str = cfs_trimwhite(str);
                if (*str != 0) {
                         lnet_syntax("networks", networks,
                                     (int)(str - tokens), strlen(str));
                if (*str != 0) {
                         lnet_syntax("networks", networks,
                                     (int)(str - tokens), strlen(str));
@@ -719,196 +692,22 @@ lnet_parse_routes (char *routes, int *im_a_router)
        return rc;
 }
 
        return rc;
 }
 
-void
-lnet_print_range_exprs(cfs_list_t *exprs)
-{
-        cfs_list_t        *e;
-        lnet_range_expr_t *lre;
-
-        cfs_list_for_each(e, exprs) {
-                lre = cfs_list_entry(exprs->next, lnet_range_expr_t, lre_list);
-                
-                CDEBUG(D_WARNING, "%d-%d/%d\n", 
-                       lre->lre_min, lre->lre_max, lre->lre_stride);
-        }
-        
-        CDEBUG(D_WARNING, "%d allocated\n", lnet_re_alloc);
-}
-
-int
-lnet_new_range_expr(cfs_list_t *exprs, int min, int max, int stride)
-{
-        lnet_range_expr_t *lre;
-
-        CDEBUG(D_NET, "%d-%d/%d\n", min, max, stride);
-
-        if (min < 0 || min > 255 || min > max || stride < 0)
-                return -EINVAL;
-
-        LIBCFS_ALLOC(lre, sizeof(*lre));
-        if (lre == NULL)
-                return -ENOMEM;
-
-        lnet_re_alloc++;
-
-        lre->lre_min = min;
-        lre->lre_max = max;
-        lre->lre_stride = stride;
-        
-        cfs_list_add(&lre->lre_list, exprs);
-        return 0;
-}
-
-void
-lnet_destroy_range_exprs(cfs_list_t *exprs)
-{
-        lnet_range_expr_t *lre;
-        
-        while (!cfs_list_empty(exprs)) {
-                lre = cfs_list_entry(exprs->next, lnet_range_expr_t, lre_list);
-                
-                cfs_list_del(&lre->lre_list);
-                LIBCFS_FREE(lre, sizeof(*lre));
-                lnet_re_alloc--;
-        }
-}
-
-int
-lnet_parse_range_expr(cfs_list_t *exprs, char *str)
-{
-        int                nob = strlen(str);
-        char              *sep;
-        int                n;
-        int                x;
-        int                y;
-        int                z;
-        int                rc;
-
-        if (nob == 0)
-                return -EINVAL;
-
-        if (!strcmp(str, "*"))                  /* match all */
-                return lnet_new_range_expr(exprs, 0, 255, 1);
-                
-        n = nob;
-        if (sscanf(str, "%u%n", &x, &n) >= 1 && n == nob) {
-                /* simple number */
-                return lnet_new_range_expr(exprs, x, x, 1);
-        }
-
-        /* Has to be an expansion */
-        if (!(str[0] == '[' && nob > 2 && str[nob-1] == ']'))
-                return -EINVAL;
-
-        nob -= 2;
-        str++;
-        str[nob] = 0;
-
-        do {
-                /* Comma separated list of expressions... */
-                sep = strchr(str, ',');
-                if (sep != NULL)
-                        *sep++ = 0;
-                
-                nob = strlen(str);
-                n = nob;
-                if (sscanf(str, "%u%n", &x, &n) >= 1 && n == nob) {
-                        /* simple number */
-                        rc = lnet_new_range_expr(exprs, x, x, 1);
-                        if (rc != 0)
-                                return rc;
-
-                        continue;
-                }
-
-                n = nob;
-                if (sscanf(str, "%u-%u%n", &x, &y, &n) >= 2 && n == nob) {
-                        /* simple range */
-                        rc = lnet_new_range_expr(exprs, x, y, 1);
-                        if (rc != 0)
-                                return rc;
-                        continue;
-                }
-                        
-                n = nob;
-                if (sscanf(str, "%u-%u/%u%n", &x, &y, &z, &n) >= 3 && n == nob) {
-                        /* strided range */
-                        rc = lnet_new_range_expr(exprs, x, y, z);
-                        if (rc != 0)
-                                return rc;
-                        continue;
-                }
-                
-                return -EINVAL;
-
-        } while ((str = sep) != NULL);
-
-        return 0;
-}
-
 int
 int
-lnet_match_network_token(char *token, __u32 *ipaddrs, int nip)
+lnet_match_network_token(char *token, int len, __u32 *ipaddrs, int nip)
 {
 {
-        cfs_list_t         exprs[4];
-        cfs_list_t        *e;
-        lnet_range_expr_t *re;
-        char              *str;
-        int                i;
-        int                j;
-        __u32              ip;
-        int                n;
-        int                match;
-        int                rc;
-
-        for (i = 0; i < 4; i++)
-                CFS_INIT_LIST_HEAD(&exprs[i]);
-
-        for (i = 0; i < 4; i++) {
-                str = token;
-                if (i != 3) {
-                        token = strchr(token, '.');
-                        if (token == NULL) {
-                                rc = -EINVAL;
-                                goto out;
-                        }
-                        *token++ = 0;
-                }
-
-                rc = lnet_parse_range_expr(&exprs[i], str);
-                if (rc != 0) {
-                        LASSERT (rc < 0);
-                        goto out;
-                }
-        }
-
-        for (match = i = 0; !match && i < nip; i++) {
-                ip = ipaddrs[i];
+       CFS_LIST_HEAD   (list);
+       int             rc;
+       int             i;
 
 
-                for (match = 1, j = 0; match && j < 4; j++) {
-                        n = (ip >> (8 * (3 - j))) & 0xff;
-                        match = 0;
+       rc = cfs_ip_addr_parse(token, len, &list);
+       if (rc != 0)
+               return rc;
 
 
-                        cfs_list_for_each(e, &exprs[j]) {
-                                re = cfs_list_entry(e, lnet_range_expr_t,
-                                                    lre_list);
+       for (rc = i = 0; !rc && i < nip; i++)
+               rc = cfs_ip_addr_match(ipaddrs[i], &list);
 
 
-                                if (re->lre_min <= n &&
-                                    re->lre_max >= n &&
-                                    (n - re->lre_min) % re->lre_stride == 0) {
-                                        match = 1;
-                                        break;
-                                }
-                        }
-                }
-        }
-        
-        rc = match ? 1 : 0;
+       cfs_ip_addr_free(&list);
 
 
- out:
-        for (i = 0; i < 4; i++)
-                lnet_destroy_range_exprs(&exprs[i]);
-        LASSERT (lnet_re_alloc == 0);
-        
         return rc;
 }
 
         return rc;
 }
 
@@ -951,8 +750,8 @@ lnet_match_network_tokens(char *net_entry, __u32 *ipaddrs, int nip)
                 }
 
                 len = strlen(token);
                 }
 
                 len = strlen(token);
-                
-                rc = lnet_match_network_token(token, ipaddrs, nip);
+
+               rc = lnet_match_network_token(token, len, ipaddrs, nip);
                 if (rc < 0) {
                         lnet_syntax("ip2nets", net_entry,
                                     (int)(token - tokens), len);
                 if (rc < 0) {
                         lnet_syntax("ip2nets", net_entry,
                                     (int)(token - tokens), len);
index 463067c..6485b70 100644 (file)
@@ -135,8 +135,6 @@ extern int echo_client_init(void);
 
 /* general stuff */
 
 
 /* general stuff */
 
-#define EXPORT_SYMBOL(S)
-
 typedef __u64 kdev_t;
 
 #ifndef min
 typedef __u64 kdev_t;
 
 #ifndef min