summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/frrstr.c16
-rw-r--r--lib/frrstr.h19
-rw-r--r--lib/linklist.c57
-rw-r--r--lib/linklist.h33
-rw-r--r--lib/nexthop.c206
-rw-r--r--lib/nexthop.h9
-rw-r--r--lib/sockunion.c15
-rw-r--r--lib/sockunion.h1
-rw-r--r--lib/thread.c5
9 files changed, 263 insertions, 98 deletions
diff --git a/lib/frrstr.c b/lib/frrstr.c
index fbbc890ec6..c575c0b568 100644
--- a/lib/frrstr.c
+++ b/lib/frrstr.c
@@ -178,7 +178,7 @@ char *frrstr_replace(const char *str, const char *find, const char *replace)
return nustr;
}
-bool begins_with(const char *str, const char *prefix)
+bool frrstr_startswith(const char *str, const char *prefix)
{
if (!str || !prefix)
return false;
@@ -192,6 +192,20 @@ bool begins_with(const char *str, const char *prefix)
return strncmp(str, prefix, lenprefix) == 0;
}
+bool frrstr_endswith(const char *str, const char *suffix)
+{
+ if (!str || !suffix)
+ return false;
+
+ size_t lenstr = strlen(str);
+ size_t lensuffix = strlen(suffix);
+
+ if (lensuffix > lenstr)
+ return false;
+
+ return strncmp(&str[lenstr - lensuffix], suffix, lensuffix) == 0;
+}
+
int all_digit(const char *str)
{
for (; *str != '\0'; str++)
diff --git a/lib/frrstr.h b/lib/frrstr.h
index d40ca14ba5..3a935c90cb 100644
--- a/lib/frrstr.h
+++ b/lib/frrstr.h
@@ -109,6 +109,7 @@ void frrstr_strvec_free(vector v);
* the replacement on 'str'. This must be freed by the caller.
*/
char *frrstr_replace(const char *str, const char *find, const char *replace);
+
/*
* Prefix match for string.
*
@@ -119,9 +120,23 @@ char *frrstr_replace(const char *str, const char *find, const char *replace);
* prefix to look for
*
* Returns:
- * true str starts with prefix, false otherwise
+ * true if str starts with prefix, false otherwise
+ */
+bool frrstr_startswith(const char *str, const char *prefix);
+
+/*
+ * Suffix match for string.
+ *
+ * str
+ * string to check for suffix match
+ *
+ * suffix
+ * suffix to look for
+ *
+ * Returns:
+ * true if str ends with suffix, false otherwise
*/
-bool begins_with(const char *str, const char *prefix);
+bool frrstr_endswith(const char *str, const char *suffix);
/*
* Check the string only contains digit characters.
diff --git a/lib/linklist.c b/lib/linklist.c
index 43bc709325..e8ba9edc12 100644
--- a/lib/linklist.c
+++ b/lib/linklist.c
@@ -92,6 +92,46 @@ void listnode_add_head(struct list *list, void *val)
list->count++;
}
+bool listnode_add_sort_nodup(struct list *list, void *val)
+{
+ struct listnode *n;
+ struct listnode *new;
+ int ret;
+
+ assert(val != NULL);
+
+ if (list->cmp) {
+ for (n = list->head; n; n = n->next) {
+ ret = (*list->cmp)(val, n->data);
+ if (ret < 0) {
+ new = listnode_new();
+ new->data = val;
+
+ new->next = n;
+ new->prev = n->prev;
+
+ if (n->prev)
+ n->prev->next = new;
+ else
+ list->head = new;
+ n->prev = new;
+ list->count++;
+ return true;
+ }
+ /* found duplicate return false */
+ if (ret == 0)
+ return false;
+ }
+ }
+
+ new = listnode_new();
+ new->data = val;
+
+ LISTNODE_ATTACH(list, new);
+
+ return true;
+}
+
void listnode_add_sort(struct list *list, void *val)
{
struct listnode *n;
@@ -242,6 +282,23 @@ void list_delete_all_node(struct list *list)
list->count = 0;
}
+void list_filter_out_nodes(struct list *list, bool (*cond)(void *data))
+{
+ struct listnode *node;
+ struct listnode *next;
+ void *data;
+
+ assert(list);
+
+ for (ALL_LIST_ELEMENTS(list, node, next, data)) {
+ if ((cond && cond(data)) || (!cond)) {
+ if (*list->del)
+ (*list->del)(data);
+ list_delete_node(list, node);
+ }
+ }
+}
+
void list_delete(struct list **list)
{
assert(*list);
diff --git a/lib/linklist.h b/lib/linklist.h
index c2b289596d..da42aa2688 100644
--- a/lib/linklist.h
+++ b/lib/linklist.h
@@ -308,6 +308,39 @@ extern void list_delete_node(struct list *list, struct listnode *node);
*/
extern void list_add_list(struct list *list, struct list *add);
+/*
+ * Delete all nodes which satisfy a condition from a list.
+ * Deletes the node if cond function returns true for the node.
+ * If function ptr passed is NULL, it deletes all nodes
+ *
+ * list
+ * list to operate on
+ * cond
+ * function pointer which takes node data as input and return TRUE or FALSE
+ */
+
+extern void list_filter_out_nodes(struct list *list, bool (*cond)(void *data));
+
+/*
+ * Insert a new element into a list with insertion sort if there is no
+ * duplicate element present in the list. This assumes the input list is
+ * sorted. If unsorted, it will check for duplicate until it finds out
+ * the position to do insertion sort with the unsorted list.
+ *
+ * If list->cmp is set, this function is used to determine the position to
+ * insert the new element. If it is not set, this function is equivalent to
+ * listnode_add. duplicate element is determined by cmp function returning 0.
+ *
+ * Runtime is O(N).
+ *
+ * list
+ * list to operate on
+ *
+ * val
+ * element to add
+ */
+
+extern bool listnode_add_sort_nodup(struct list *list, void *val);
/* List iteration macro.
* Usage: for (ALL_LIST_ELEMENTS (...) { ... }
* It is safe to delete the listnode using this macro.
diff --git a/lib/nexthop.c b/lib/nexthop.c
index 8e16e70590..57a2f1daaa 100644
--- a/lib/nexthop.c
+++ b/lib/nexthop.c
@@ -36,40 +36,132 @@
DEFINE_MTYPE_STATIC(LIB, NEXTHOP, "Nexthop")
DEFINE_MTYPE_STATIC(LIB, NH_LABEL, "Nexthop label")
-/* check if nexthops are same, non-recursive */
-int nexthop_same_no_recurse(const struct nexthop *next1,
- const struct nexthop *next2)
+static int _nexthop_labels_cmp(const struct nexthop *nh1,
+ const struct nexthop *nh2)
{
- if (next1->type != next2->type)
+ const struct mpls_label_stack *nhl1 = NULL;
+ const struct mpls_label_stack *nhl2 = NULL;
+
+ nhl1 = nh1->nh_label;
+ nhl2 = nh2->nh_label;
+
+ /* No labels is a match */
+ if (!nhl1 && !nhl2)
return 0;
- switch (next1->type) {
+ if (nhl1 && !nhl2)
+ return 1;
+
+ if (nhl2 && !nhl1)
+ return -1;
+
+ if (nhl1->num_labels > nhl2->num_labels)
+ return 1;
+
+ if (nhl1->num_labels < nhl2->num_labels)
+ return -1;
+
+ return memcmp(nhl1->label, nhl2->label, nhl1->num_labels);
+}
+
+static int _nexthop_g_addr_cmp(enum nexthop_types_t type,
+ const union g_addr *addr1,
+ const union g_addr *addr2)
+{
+ int ret = 0;
+
+ switch (type) {
case NEXTHOP_TYPE_IPV4:
case NEXTHOP_TYPE_IPV4_IFINDEX:
- if (!IPV4_ADDR_SAME(&next1->gate.ipv4, &next2->gate.ipv4))
- return 0;
- if (next1->ifindex && (next1->ifindex != next2->ifindex))
- return 0;
+ ret = IPV4_ADDR_CMP(&addr1->ipv4, &addr2->ipv4);
+ break;
+ case NEXTHOP_TYPE_IPV6:
+ case NEXTHOP_TYPE_IPV6_IFINDEX:
+ ret = IPV6_ADDR_CMP(&addr1->ipv6, &addr2->ipv6);
break;
case NEXTHOP_TYPE_IFINDEX:
- if (next1->ifindex != next2->ifindex)
- return 0;
+ case NEXTHOP_TYPE_BLACKHOLE:
+ /* No addr here */
break;
+ }
+
+ return ret;
+}
+
+static int _nexthop_gateway_cmp(const struct nexthop *nh1,
+ const struct nexthop *nh2)
+{
+ return _nexthop_g_addr_cmp(nh1->type, &nh1->gate, &nh2->gate);
+}
+
+static int _nexthop_source_cmp(const struct nexthop *nh1,
+ const struct nexthop *nh2)
+{
+ return _nexthop_g_addr_cmp(nh1->type, &nh1->src, &nh2->src);
+}
+
+static int _nexthop_cmp_no_labels(const struct nexthop *next1,
+ const struct nexthop *next2)
+{
+ int ret = 0;
+
+ if (next1->vrf_id < next2->vrf_id)
+ return -1;
+
+ if (next1->vrf_id > next2->vrf_id)
+ return 1;
+
+ if (next1->type < next2->type)
+ return -1;
+
+ if (next1->type > next2->type)
+ return 1;
+
+ switch (next1->type) {
+ case NEXTHOP_TYPE_IPV4:
case NEXTHOP_TYPE_IPV6:
- if (!IPV6_ADDR_SAME(&next1->gate.ipv6, &next2->gate.ipv6))
- return 0;
+ ret = _nexthop_gateway_cmp(next1, next2);
+ if (ret != 0)
+ return ret;
break;
+ case NEXTHOP_TYPE_IPV4_IFINDEX:
case NEXTHOP_TYPE_IPV6_IFINDEX:
- if (!IPV6_ADDR_SAME(&next1->gate.ipv6, &next2->gate.ipv6))
- return 0;
- if (next1->ifindex != next2->ifindex)
- return 0;
+ ret = _nexthop_gateway_cmp(next1, next2);
+ if (ret != 0)
+ return ret;
+ /* Intentional Fall-Through */
+ case NEXTHOP_TYPE_IFINDEX:
+ if (next1->ifindex < next2->ifindex)
+ return -1;
+
+ if (next1->ifindex > next2->ifindex)
+ return 1;
break;
- default:
- /* do nothing */
+ case NEXTHOP_TYPE_BLACKHOLE:
+ if (next1->bh_type < next2->bh_type)
+ return -1;
+
+ if (next1->bh_type > next2->bh_type)
+ return 1;
break;
}
- return 1;
+
+ ret = _nexthop_source_cmp(next1, next2);
+
+ return ret;
+}
+
+int nexthop_cmp(const struct nexthop *next1, const struct nexthop *next2)
+{
+ int ret = 0;
+
+ ret = _nexthop_cmp_no_labels(next1, next2);
+ if (ret != 0)
+ return ret;
+
+ ret = _nexthop_labels_cmp(next1, next2);
+
+ return ret;
}
int nexthop_same_firsthop(struct nexthop *next1, struct nexthop *next2)
@@ -121,27 +213,12 @@ const char *nexthop_type_to_str(enum nexthop_types_t nh_type)
/*
* Check if the labels match for the 2 nexthops specified.
*/
-int nexthop_labels_match(const struct nexthop *nh1, const struct nexthop *nh2)
+bool nexthop_labels_match(const struct nexthop *nh1, const struct nexthop *nh2)
{
- const struct mpls_label_stack *nhl1, *nhl2;
-
- nhl1 = nh1->nh_label;
- nhl2 = nh2->nh_label;
-
- /* No labels is a match */
- if (!nhl1 && !nhl2)
- return 1;
-
- if (!nhl1 || !nhl2)
- return 0;
-
- if (nhl1->num_labels != nhl2->num_labels)
- return 0;
-
- if (memcmp(nhl1->label, nhl2->label, nhl1->num_labels))
- return 0;
+ if (_nexthop_labels_cmp(nh1, nh2) != 0)
+ return false;
- return 1;
+ return true;
}
struct nexthop *nexthop_new(void)
@@ -180,45 +257,28 @@ bool nexthop_same(const struct nexthop *nh1, const struct nexthop *nh2)
if (nh1 == nh2)
return true;
- if (nh1->vrf_id != nh2->vrf_id)
+ if (nexthop_cmp(nh1, nh2) != 0)
return false;
- if (nh1->type != nh2->type)
+ return true;
+}
+
+bool nexthop_same_no_labels(const struct nexthop *nh1,
+ const struct nexthop *nh2)
+{
+ if (nh1 && !nh2)
return false;
- switch (nh1->type) {
- case NEXTHOP_TYPE_IFINDEX:
- if (nh1->ifindex != nh2->ifindex)
- return false;
- break;
- case NEXTHOP_TYPE_IPV4:
- if (nh1->gate.ipv4.s_addr != nh2->gate.ipv4.s_addr)
- return false;
- break;
- case NEXTHOP_TYPE_IPV4_IFINDEX:
- if (nh1->gate.ipv4.s_addr != nh2->gate.ipv4.s_addr)
- return false;
- if (nh1->ifindex != nh2->ifindex)
- return false;
- break;
- case NEXTHOP_TYPE_IPV6:
- if (memcmp(&nh1->gate.ipv6, &nh2->gate.ipv6, 16))
- return false;
- break;
- case NEXTHOP_TYPE_IPV6_IFINDEX:
- if (memcmp(&nh1->gate.ipv6, &nh2->gate.ipv6, 16))
- return false;
- if (nh1->ifindex != nh2->ifindex)
- return false;
- break;
- case NEXTHOP_TYPE_BLACKHOLE:
- if (nh1->bh_type != nh2->bh_type)
- return false;
- break;
- }
+ if (!nh1 && nh2)
+ return false;
+
+ if (nh1 == nh2)
+ return true;
+
+ if (_nexthop_cmp_no_labels(nh1, nh2) != 0)
+ return false;
- /* Compare labels too (if present) */
- return (!!nexthop_labels_match(nh1, nh2));
+ return true;
}
/* Update nexthop with label information. */
diff --git a/lib/nexthop.h b/lib/nexthop.h
index 663acaeb69..5b6c12d4ef 100644
--- a/lib/nexthop.h
+++ b/lib/nexthop.h
@@ -139,12 +139,13 @@ void nexthop_del_labels(struct nexthop *);
uint32_t nexthop_hash(const struct nexthop *nexthop);
extern bool nexthop_same(const struct nexthop *nh1, const struct nexthop *nh2);
+extern bool nexthop_same_no_labels(const struct nexthop *nh1,
+ const struct nexthop *nh2);
+extern int nexthop_cmp(const struct nexthop *nh1, const struct nexthop *nh2);
extern const char *nexthop_type_to_str(enum nexthop_types_t nh_type);
-extern int nexthop_same_no_recurse(const struct nexthop *next1,
- const struct nexthop *next2);
-extern int nexthop_labels_match(const struct nexthop *nh1,
- const struct nexthop *nh2);
+extern bool nexthop_labels_match(const struct nexthop *nh1,
+ const struct nexthop *nh2);
extern int nexthop_same_firsthop(struct nexthop *next1, struct nexthop *next2);
extern const char *nexthop2str(const struct nexthop *nexthop,
diff --git a/lib/sockunion.c b/lib/sockunion.c
index 5afd10eb48..8fa9a3fad9 100644
--- a/lib/sockunion.c
+++ b/lib/sockunion.c
@@ -366,21 +366,6 @@ int sockopt_cork(int sock, int onoff)
return 0;
}
-int sockopt_mark_default(int sock, int mark, struct zebra_privs_t *cap)
-{
-#ifdef SO_MARK
- int ret;
-
- frr_elevate_privs(cap) {
- ret = setsockopt(sock, SOL_SOCKET, SO_MARK, &mark,
- sizeof(mark));
- }
- return ret;
-#else
- return 0;
-#endif
-}
-
int sockopt_minttl(int family, int sock, int minttl)
{
#ifdef IP_MINTTL
diff --git a/lib/sockunion.h b/lib/sockunion.h
index b996735550..7091c1b5e7 100644
--- a/lib/sockunion.h
+++ b/lib/sockunion.h
@@ -93,7 +93,6 @@ extern int sockunion_bind(int sock, union sockunion *, unsigned short,
extern int sockopt_ttl(int family, int sock, int ttl);
extern int sockopt_minttl(int family, int sock, int minttl);
extern int sockopt_cork(int sock, int onoff);
-extern int sockopt_mark_default(int sock, int mark, struct zebra_privs_t *);
extern int sockunion_socket(const union sockunion *su);
extern const char *inet_sutop(const union sockunion *su, char *str);
extern enum connect_result sockunion_connect(int fd, const union sockunion *su,
diff --git a/lib/thread.c b/lib/thread.c
index 7a9a0ab608..d3fb2cdf36 100644
--- a/lib/thread.c
+++ b/lib/thread.c
@@ -281,7 +281,7 @@ DEFUN (show_thread_cpu,
SHOW_STR
"Thread information\n"
"Thread CPU usage\n"
- "Display filter (rwtexb)\n")
+ "Display filter (rwtex)\n")
{
uint8_t filter = (uint8_t)-1U;
int idx = 0;
@@ -312,7 +312,8 @@ static void show_thread_poll_helper(struct vty *vty, struct thread_master *m)
vty_out(vty, "\nShowing poll FD's for %s\n", name);
vty_out(vty, "----------------------%s\n", underline);
- vty_out(vty, "Count: %u\n", (uint32_t)m->handler.pfdcount);
+ vty_out(vty, "Count: %u/%d\n", (uint32_t)m->handler.pfdcount,
+ m->fd_limit);
for (i = 0; i < m->handler.pfdcount; i++)
vty_out(vty, "\t%6d fd:%6d events:%2d revents:%2d\n", i,
m->handler.pfds[i].fd,