Whamcloud - gitweb
LU-10825 libcfs: generate ip addresses 85/31785/4
authorAmir Shehata <amir.shehata@intel.com>
Mon, 19 Mar 2018 19:37:57 +0000 (12:37 -0700)
committerOleg Drokin <oleg.drokin@intel.com>
Wed, 2 May 2018 02:22:43 +0000 (02:22 +0000)
Add infrastructure API cfs_ip_addr_range_gen() to generate a
maximum of 'count' IP addresses from an expression.

Test-Parameters: trivial
Signed-off-by: Amir Shehata <amir.shehata@intel.com>
Change-Id: I479dd7128eef404106a7863124a38c501150ba9e
Reviewed-on: https://review.whamcloud.com/31785
Reviewed-by: Sonia Sharma <sonia.sharma@intel.com>
Tested-by: Jenkins
Tested-by: Maloo <hpdd-maloo@intel.com>
Reviewed-by: Dmitry Eremin <dmitry.eremin@intel.com>
Reviewed-by: Oleg Drokin <oleg.drokin@intel.com>
libcfs/include/libcfs/util/string.h
libcfs/libcfs/util/nidstrings.c

index 22e6024..065829b 100644 (file)
@@ -82,6 +82,8 @@ int cfs_expr_list_parse(char *str, int len, unsigned min, unsigned max,
 void cfs_expr_list_free(struct cfs_expr_list *expr_list);
 void cfs_expr_list_free_list(struct list_head *list);
 int cfs_ip_addr_parse(char *str, int len, struct list_head *list);
+int cfs_ip_addr_range_gen(__u32 *ip_list, int count,
+                         struct list_head *ip_addr_expr);
 int cfs_ip_addr_match(__u32 addr, struct list_head *list);
 int cfs_abs_path(const char *request_path, char **resolved_path);
 
index ba4e563..246d420 100644 (file)
@@ -204,6 +204,80 @@ libcfs_ip_addr_range_print(char *buffer, int count, struct list_head *list)
        return i;
 }
 
+static int
+cfs_ip_addr_range_gen_recurse(__u32 *ip_list, int *count, int shift,
+                             __u32 result, struct list_head *head_el,
+                             struct cfs_expr_list *octet_el)
+{
+       __u32 value = 0;
+       int i;
+       struct cfs_expr_list *next_octet_el;
+       struct cfs_range_expr *octet_expr;
+
+       /*
+        * each octet can have multiple expressions so we need to traverse
+        * all of the expressions
+        */
+       list_for_each_entry(octet_expr, &octet_el->el_exprs, re_link) {
+               for (i = octet_expr->re_lo; i <= octet_expr->re_hi; i++) {
+                       if (((i - octet_expr->re_lo) % octet_expr->re_stride) == 0) {
+                               /*
+                                * we have a hit calculate the result and
+                                * pass it forward to the next iteration
+                                * of the recursion.
+                                */
+                               next_octet_el =
+                                       list_entry(octet_el->el_link.next,
+                                                       typeof(*next_octet_el),
+                                                       el_link);
+                               value = result | (i << (shift * 8));
+                               if (next_octet_el->el_link.next != head_el) {
+                                       /*
+                                        * We still have more octets in
+                                        * the IP address so traverse
+                                        * that. We're doing a depth first
+                                        * recursion here.
+                                        */
+                                       if (cfs_ip_addr_range_gen_recurse(ip_list, count,
+                                                                         shift - 1, value,
+                                                                         head_el,
+                                                                         next_octet_el) == -1)
+                                               return -1;
+                               } else {
+                                       /*
+                                        * We have hit a leaf so store the
+                                        * calculated IP address in the
+                                        * list. If we have run out of
+                                        * space stop the recursion.
+                                        */
+                                       if (*count == -1)
+                                               return -1;
+                                       /* add ip to the list */
+                                       ip_list[*count] = value;
+                                       (*count)--;
+                               }
+                       }
+               }
+       }
+       return 0;
+}
+
+/*
+ * only generate maximum of count ip addresses from the given expression
+ */
+int
+cfs_ip_addr_range_gen(__u32 *ip_list, int count, struct list_head *ip_addr_expr)
+{
+       struct cfs_expr_list *octet_el;
+       int idx = count - 1;
+
+       octet_el = list_entry(ip_addr_expr->next, typeof(*octet_el), el_link);
+
+       (void) cfs_ip_addr_range_gen_recurse(ip_list, &idx, 3, 0, &octet_el->el_link, octet_el);
+
+       return idx;
+}
+
 /**
  * Matches address (\a addr) against address set encoded in \a list.
  *