From 4c5f788397213aa41356df1f96f7ade58653973a Mon Sep 17 00:00:00 2001 From: Amir Shehata Date: Mon, 19 Mar 2018 12:37:57 -0700 Subject: [PATCH] LU-10825 libcfs: generate ip addresses 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 Change-Id: I479dd7128eef404106a7863124a38c501150ba9e Reviewed-on: https://review.whamcloud.com/31785 Reviewed-by: Sonia Sharma Tested-by: Jenkins Tested-by: Maloo Reviewed-by: Dmitry Eremin Reviewed-by: Oleg Drokin --- libcfs/include/libcfs/util/string.h | 2 + libcfs/libcfs/util/nidstrings.c | 74 +++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+) diff --git a/libcfs/include/libcfs/util/string.h b/libcfs/include/libcfs/util/string.h index 22e6024..065829b 100644 --- a/libcfs/include/libcfs/util/string.h +++ b/libcfs/include/libcfs/util/string.h @@ -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); diff --git a/libcfs/libcfs/util/nidstrings.c b/libcfs/libcfs/util/nidstrings.c index ba4e563..246d420 100644 --- a/libcfs/libcfs/util/nidstrings.c +++ b/libcfs/libcfs/util/nidstrings.c @@ -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. * -- 1.8.3.1