summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/developer/lists.rst27
-rw-r--r--lib/typerb.c10
-rw-r--r--lib/typerb.h7
-rw-r--r--lib/typesafe.c40
-rw-r--r--lib/typesafe.h109
-rw-r--r--nhrpd/list.h209
-rw-r--r--nhrpd/nhrp_cache.c4
-rw-r--r--nhrpd/nhrp_interface.c17
-rw-r--r--nhrpd/nhrp_multicast.c30
-rw-r--r--nhrpd/nhrp_nhs.c96
-rw-r--r--nhrpd/nhrp_peer.c2
-rw-r--r--nhrpd/nhrp_vc.c27
-rw-r--r--nhrpd/nhrp_vty.c8
-rw-r--r--nhrpd/nhrpd.h53
-rw-r--r--nhrpd/subdir.am1
-rw-r--r--nhrpd/zbuf.c21
-rw-r--r--nhrpd/zbuf.h10
-rw-r--r--tests/.gitignore2
-rw-r--r--tests/lib/test_typelist.h82
-rwxr-xr-xtools/checkpatch.pl32
20 files changed, 423 insertions, 364 deletions
diff --git a/doc/developer/lists.rst b/doc/developer/lists.rst
index 718e404764..dc8f236927 100644
--- a/doc/developer/lists.rst
+++ b/doc/developer/lists.rst
@@ -106,19 +106,25 @@ Functions provided:
| _init, _fini | yes | yes | yes | yes | yes |
+------------------------------------+------+------+------+---------+------------+
| _first, _next, _next_safe, | yes | yes | yes | yes | yes |
+| | | | | | |
| _const_first, _const_next | | | | | |
+------------------------------------+------+------+------+---------+------------+
| _swap_all | yes | yes | yes | yes | yes |
+------------------------------------+------+------+------+---------+------------+
+| _anywhere | yes | -- | -- | -- | -- |
++------------------------------------+------+------+------+---------+------------+
| _add_head, _add_tail, _add_after | yes | -- | -- | -- | -- |
+------------------------------------+------+------+------+---------+------------+
| _add | -- | yes | yes | yes | yes |
+------------------------------------+------+------+------+---------+------------+
+| _member | yes | yes | yes | yes | yes |
++------------------------------------+------+------+------+---------+------------+
| _del, _pop | yes | yes | yes | yes | yes |
+------------------------------------+------+------+------+---------+------------+
| _find, _const_find | -- | -- | yes | yes | -- |
+------------------------------------+------+------+------+---------+------------+
| _find_lt, _find_gteq, | -- | -- | -- | yes | yes |
+| | | | | | |
| _const_find_lt, _const_find_gteq | | | | | |
+------------------------------------+------+------+------+---------+------------+
| use with frr_each() macros | yes | yes | yes | yes | yes |
@@ -268,6 +274,16 @@ The following documentation assumes that a list has been defined using
outdated by the time this function returns and can therefore only be
used as an estimate.
+.. c:function:: bool Z_member(const struct Z_head *, const itemtype *)
+
+ Determines whether some item is a member of the given container. The
+ item must either be valid on some container, or set to all zeroes.
+
+ On some containers, if no faster way to determine membership is possible,
+ this is simply ``item == Z_find(head, item)``.
+
+ Not currently available for atomic containers.
+
.. c:function:: const itemtype *Z_const_first(const struct Z_head *)
.. c:function:: itemtype *Z_first(struct Z_head *)
@@ -396,6 +412,17 @@ are several functions exposed to insert data:
maybe flip the order of ``item`` & ``after``?
``Z_add_after(head, item, after)``
+.. c:function:: bool Z_anywhere(const itemtype *)
+
+ Returns whether an item is a member of *any* container of this type.
+ The item must either be valid on some container, or set to all zeroes.
+
+ Guaranteed to be fast (pointer compare or similar.)
+
+ Not currently available for sorted and atomic containers. Might be added
+ for sorted containers at some point (when needed.)
+
+
API for sorted structures
-------------------------
diff --git a/lib/typerb.c b/lib/typerb.c
index 092faa4cc9..e1346df191 100644
--- a/lib/typerb.c
+++ b/lib/typerb.c
@@ -45,6 +45,7 @@
#include "config.h"
#endif
+#include <string.h>
#include "typerb.h"
#define RB_BLACK 0
@@ -330,6 +331,7 @@ color:
rbe_remove_color(rbt, parent, child);
rbt->count--;
+ memset(old, 0, sizeof(*old));
return (old);
}
@@ -478,3 +480,11 @@ struct rb_entry *typed_rb_min(const struct rbt_tree *rbt)
return parent;
}
+
+bool typed_rb_member(const struct typed_rb_root *rbt,
+ const struct typed_rb_entry *rbe)
+{
+ while (rbe->rbt_parent)
+ rbe = rbe->rbt_parent;
+ return rbe == rbt->rbt_root;
+}
diff --git a/lib/typerb.h b/lib/typerb.h
index cbed8d4893..d22d864aae 100644
--- a/lib/typerb.h
+++ b/lib/typerb.h
@@ -62,6 +62,8 @@ const struct typed_rb_entry *typed_rb_find_lt(const struct typed_rb_root *rbt,
const struct typed_rb_entry *b));
struct typed_rb_entry *typed_rb_min(const struct typed_rb_root *rbt);
struct typed_rb_entry *typed_rb_next(const struct typed_rb_entry *rbe);
+bool typed_rb_member(const struct typed_rb_root *rbt,
+ const struct typed_rb_entry *rbe);
#define _PREDECL_RBTREE(prefix) \
struct prefix ## _head { struct typed_rb_root rr; }; \
@@ -142,6 +144,11 @@ macro_pure size_t prefix ## _count(const struct prefix##_head *h) \
{ \
return h->rr.count; \
} \
+macro_pure bool prefix ## _member(const struct prefix##_head *h, \
+ const type *item) \
+{ \
+ return typed_rb_member(&h->rr, &item->field.re); \
+} \
MACRO_REQUIRE_SEMICOLON() /* end */
#define PREDECL_RBTREE_UNIQ(prefix) \
diff --git a/lib/typesafe.c b/lib/typesafe.c
index 76705fad0d..f90b59daf0 100644
--- a/lib/typesafe.c
+++ b/lib/typesafe.c
@@ -29,6 +29,46 @@ DEFINE_MTYPE_STATIC(LIB, TYPEDHASH_BUCKET, "Typed-hash bucket");
DEFINE_MTYPE_STATIC(LIB, SKIPLIST_OFLOW, "Skiplist overflow");
DEFINE_MTYPE_STATIC(LIB, HEAP_ARRAY, "Typed-heap array");
+struct slist_item typesafe_slist_sentinel = { NULL };
+
+bool typesafe_list_member(const struct slist_head *head,
+ const struct slist_item *item)
+{
+ struct slist_item *fromhead = head->first;
+ struct slist_item **fromnext = (struct slist_item **)&item->next;
+
+ while (fromhead != _SLIST_LAST) {
+ if (fromhead == item || fromnext == head->last_next)
+ return true;
+
+ fromhead = fromhead->next;
+ if (!*fromnext || *fromnext == _SLIST_LAST)
+ break;
+ fromnext = &(*fromnext)->next;
+ }
+
+ return false;
+}
+
+bool typesafe_dlist_member(const struct dlist_head *head,
+ const struct dlist_item *item)
+{
+ const struct dlist_item *fromhead = head->hitem.next;
+ const struct dlist_item *fromitem = item->next;
+
+ if (!item->prev || !item->next)
+ return false;
+
+ while (fromhead != &head->hitem && fromitem != item) {
+ if (fromitem == &head->hitem || fromhead == item)
+ return true;
+ fromhead = fromhead->next;
+ fromitem = fromitem->next;
+ }
+
+ return false;
+}
+
#if 0
static void hash_consistency_check(struct thash_head *head)
{
diff --git a/lib/typesafe.h b/lib/typesafe.h
index ecac1a4381..44c42ffbca 100644
--- a/lib/typesafe.h
+++ b/lib/typesafe.h
@@ -78,8 +78,34 @@ macro_inline type *prefix ## _find_gteq(struct prefix##_head *h, \
} \
/* ... */
+/* *_member via find - when there is no better membership check than find() */
+#define TYPESAFE_MEMBER_VIA_FIND(prefix, type) \
+macro_inline bool prefix ## _member(struct prefix##_head *h, \
+ const type *item) \
+{ \
+ return item == prefix ## _const_find(h, item); \
+} \
+/* ... */
+
+/* *_member via find_gteq - same for non-unique containers */
+#define TYPESAFE_MEMBER_VIA_FIND_GTEQ(prefix, type, cmpfn) \
+macro_inline bool prefix ## _member(struct prefix##_head *h, \
+ const type *item) \
+{ \
+ const type *iter; \
+ for (iter = prefix ## _const_find_gteq(h, item); iter; \
+ iter = prefix ## _const_next(h, iter)) { \
+ if (iter == item) \
+ return true; \
+ if (cmpfn(iter, item) > 0) \
+ break; \
+ } \
+ return false; \
+} \
+/* ... */
+
/* SWAP_ALL_SIMPLE = for containers where the items don't point back to the
- * head *AND* the head doesn'T points to itself (= everything except LIST,
+ * head *AND* the head doesn't point to itself (= everything except LIST,
* DLIST and SKIPLIST), just switch out the entire head
*/
#define TYPESAFE_SWAP_ALL_SIMPLE(prefix) \
@@ -106,6 +132,10 @@ struct slist_head {
size_t count;
};
+/* this replaces NULL as the value for ->next on the last item. */
+extern struct slist_item typesafe_slist_sentinel;
+#define _SLIST_LAST &typesafe_slist_sentinel
+
static inline void typesafe_list_add(struct slist_head *head,
struct slist_item **pos, struct slist_item *item)
{
@@ -116,6 +146,9 @@ static inline void typesafe_list_add(struct slist_head *head,
head->count++;
}
+extern bool typesafe_list_member(const struct slist_head *head,
+ const struct slist_item *item);
+
/* use as:
*
* PREDECL_LIST(namelist);
@@ -136,6 +169,7 @@ MACRO_REQUIRE_SEMICOLON() /* end */
macro_inline void prefix ## _init(struct prefix##_head *h) \
{ \
memset(h, 0, sizeof(*h)); \
+ h->sh.first = _SLIST_LAST; \
h->sh.last_next = &h->sh.first; \
} \
macro_inline void prefix ## _fini(struct prefix##_head *h) \
@@ -161,25 +195,27 @@ macro_inline void prefix ## _add_after(struct prefix##_head *h, \
macro_inline type *prefix ## _del(struct prefix##_head *h, type *item) \
{ \
struct slist_item **iter = &h->sh.first; \
- while (*iter && *iter != &item->field.si) \
+ while (*iter != _SLIST_LAST && *iter != &item->field.si) \
iter = &(*iter)->next; \
- if (!*iter) \
+ if (*iter == _SLIST_LAST) \
return NULL; \
h->sh.count--; \
*iter = item->field.si.next; \
- if (!item->field.si.next) \
+ if (item->field.si.next == _SLIST_LAST) \
h->sh.last_next = iter; \
+ item->field.si.next = NULL; \
return item; \
} \
macro_inline type *prefix ## _pop(struct prefix##_head *h) \
{ \
struct slist_item *sitem = h->sh.first; \
- if (!sitem) \
+ if (sitem == _SLIST_LAST) \
return NULL; \
h->sh.count--; \
h->sh.first = sitem->next; \
- if (h->sh.first == NULL) \
+ if (h->sh.first == _SLIST_LAST) \
h->sh.last_next = &h->sh.first; \
+ sitem->next = NULL; \
return container_of(sitem, type, field.si); \
} \
macro_inline void prefix ## _swap_all(struct prefix##_head *a, \
@@ -195,13 +231,17 @@ macro_inline void prefix ## _swap_all(struct prefix##_head *a, \
} \
macro_pure const type *prefix ## _const_first(const struct prefix##_head *h) \
{ \
- return container_of_null(h->sh.first, type, field.si); \
+ if (h->sh.first != _SLIST_LAST) \
+ return container_of(h->sh.first, type, field.si); \
+ return NULL; \
} \
macro_pure const type *prefix ## _const_next(const struct prefix##_head *h, \
const type *item) \
{ \
const struct slist_item *sitem = &item->field.si; \
- return container_of_null(sitem->next, type, field.si); \
+ if (sitem->next != _SLIST_LAST) \
+ return container_of(sitem->next, type, field.si); \
+ return NULL; \
} \
TYPESAFE_FIRST_NEXT(prefix, type) \
macro_pure type *prefix ## _next_safe(struct prefix##_head *h, type *item) \
@@ -210,12 +250,23 @@ macro_pure type *prefix ## _next_safe(struct prefix##_head *h, type *item) \
if (!item) \
return NULL; \
sitem = &item->field.si; \
- return container_of_null(sitem->next, type, field.si); \
+ if (sitem->next != _SLIST_LAST) \
+ return container_of(sitem->next, type, field.si); \
+ return NULL; \
} \
macro_pure size_t prefix ## _count(const struct prefix##_head *h) \
{ \
return h->sh.count; \
} \
+macro_pure bool prefix ## _anywhere(const type *item) \
+{ \
+ return item->field.si.next != NULL; \
+} \
+macro_pure bool prefix ## _member(const struct prefix##_head *h, \
+ const type *item) \
+{ \
+ return typesafe_list_member(&h->sh, &item->field.si); \
+} \
MACRO_REQUIRE_SEMICOLON() /* end */
/* don't use these structs directly */
@@ -267,6 +318,9 @@ static inline void typesafe_dlist_swap_all(struct dlist_head *a,
}
}
+extern bool typesafe_dlist_member(const struct dlist_head *head,
+ const struct dlist_item *item);
+
/* double-linked list, for fast item deletion
*/
#define PREDECL_DLIST(prefix) \
@@ -321,6 +375,7 @@ macro_inline type *prefix ## _pop(struct prefix##_head *h) \
ditem->prev->next = ditem->next; \
ditem->next->prev = ditem->prev; \
h->dh.count--; \
+ ditem->prev = ditem->next = NULL; \
return container_of(ditem, type, field.di); \
} \
macro_inline void prefix ## _swap_all(struct prefix##_head *a, \
@@ -354,6 +409,16 @@ macro_pure size_t prefix ## _count(const struct prefix##_head *h) \
{ \
return h->dh.count; \
} \
+macro_pure bool prefix ## _anywhere(const type *item) \
+{ \
+ const struct dlist_item *ditem = &item->field.di; \
+ return ditem->next && ditem->prev; \
+} \
+macro_pure bool prefix ## _member(const struct prefix##_head *h, \
+ const type *item) \
+{ \
+ return typesafe_dlist_member(&h->dh, &item->field.di); \
+} \
MACRO_REQUIRE_SEMICOLON() /* end */
/* note: heap currently caps out at 4G items */
@@ -463,6 +528,14 @@ macro_pure size_t prefix ## _count(const struct prefix##_head *h) \
{ \
return h->hh.count; \
} \
+macro_pure bool prefix ## _member(const struct prefix##_head *h, \
+ const type *item) \
+{ \
+ uint32_t idx = item->field.hi.index; \
+ if (idx >= h->hh.count) \
+ return false; \
+ return h->hh.array[idx] == &item->field.hi; \
+} \
MACRO_REQUIRE_SEMICOLON() /* end */
extern void typesafe_heap_resize(struct heap_head *head, bool grow);
@@ -565,6 +638,7 @@ macro_inline type *prefix ## _del(struct prefix##_head *h, type *item) \
return NULL; \
h->sh.count--; \
*iter = item->field.si.next; \
+ item->field.si.next = NULL; \
return item; \
} \
macro_inline type *prefix ## _pop(struct prefix##_head *h) \
@@ -618,6 +692,7 @@ macro_inline const type *prefix ## _const_find(const struct prefix##_head *h, \
return container_of(sitem, type, field.si); \
} \
TYPESAFE_FIND(prefix, type) \
+TYPESAFE_MEMBER_VIA_FIND(prefix, type) \
MACRO_REQUIRE_SEMICOLON() /* end */
#define DECLARE_SORTLIST_NONUNIQ(prefix, type, field, cmpfn) \
@@ -633,6 +708,7 @@ macro_inline int _ ## prefix ## _cmp(const type *a, const type *b) \
return 0; \
} \
_DECLARE_SORTLIST(prefix, type, field, cmpfn, _ ## prefix ## _cmp); \
+TYPESAFE_MEMBER_VIA_FIND_GTEQ(prefix, type, cmpfn) \
MACRO_REQUIRE_SEMICOLON() /* end */
@@ -799,6 +875,19 @@ macro_pure size_t prefix ## _count(const struct prefix##_head *h) \
{ \
return h->hh.count; \
} \
+macro_pure bool prefix ## _member(const struct prefix##_head *h, \
+ const type *item) \
+{ \
+ uint32_t hval = item->field.hi.hashval, hbits = HASH_KEY(h->hh, hval); \
+ const struct thash_item *hitem = h->hh.entries[hbits]; \
+ while (hitem && hitem->hashval < hval) \
+ hitem = hitem->next; \
+ for (hitem = h->hh.entries[hbits]; hitem && hitem->hashval <= hval; \
+ hitem = hitem->next) \
+ if (hitem == &item->field.hi) \
+ return true; \
+ return false; \
+} \
MACRO_REQUIRE_SEMICOLON() /* end */
/* skiplist, sorted.
@@ -937,6 +1026,7 @@ macro_inline const type *prefix ## _const_find(const struct prefix##_head *h, \
return container_of_null(sitem, type, field.si); \
} \
TYPESAFE_FIND(prefix, type) \
+TYPESAFE_MEMBER_VIA_FIND(prefix, type) \
\
_DECLARE_SKIPLIST(prefix, type, field, \
prefix ## __cmp, prefix ## __cmp); \
@@ -968,6 +1058,7 @@ macro_inline int prefix ## __cmp_uq(const struct sskip_item *a, \
\
_DECLARE_SKIPLIST(prefix, type, field, \
prefix ## __cmp, prefix ## __cmp_uq); \
+TYPESAFE_MEMBER_VIA_FIND_GTEQ(prefix, type, cmpfn) \
MACRO_REQUIRE_SEMICOLON() /* end */
diff --git a/nhrpd/list.h b/nhrpd/list.h
deleted file mode 100644
index a43687ac08..0000000000
--- a/nhrpd/list.h
+++ /dev/null
@@ -1,209 +0,0 @@
-/* Linux kernel style list handling function
- *
- * Written from scratch by Timo Teräs <timo.teras@iki.fi>, but modeled
- * after the linux kernel code.
- *
- * This file is free software: you may copy, redistribute and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef LIST_H
-#define LIST_H
-
-#ifndef NULL
-#define NULL 0L
-#endif
-
-#ifndef offsetof
-#ifdef __compiler_offsetof
-#define offsetof(TYPE,MEMBER) __compiler_offsetof(TYPE,MEMBER)
-#else
-#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
-#endif
-#endif
-
-#ifndef container_of
-#define container_of(ptr, type, member) \
- ({ \
- const typeof(((type *)0)->member) *__mptr = (ptr); \
- (type *)((char *)__mptr - offsetof(type, member)); \
- })
-#endif
-
-struct hlist_head {
- struct hlist_node *first;
-};
-
-struct hlist_node {
- struct hlist_node *next;
- struct hlist_node **pprev;
-};
-
-static inline int hlist_empty(const struct hlist_head *h)
-{
- return !h->first;
-}
-
-static inline int hlist_hashed(const struct hlist_node *n)
-{
- return n->pprev != NULL;
-}
-
-static inline void hlist_del(struct hlist_node *n)
-{
- struct hlist_node *next = n->next;
- struct hlist_node **pprev = n->pprev;
-
- *pprev = next;
- if (next)
- next->pprev = pprev;
-
- n->next = NULL;
- n->pprev = NULL;
-}
-
-static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
-{
- struct hlist_node *first = h->first;
-
- n->next = first;
- if (first)
- first->pprev = &n->next;
- n->pprev = &h->first;
- h->first = n;
-}
-
-static inline void hlist_add_after(struct hlist_node *n,
- struct hlist_node *prev)
-{
- n->next = prev->next;
- n->pprev = &prev->next;
- prev->next = n;
-}
-
-static inline struct hlist_node **hlist_tail_ptr(struct hlist_head *h)
-{
- struct hlist_node *n = h->first;
- if (n == NULL)
- return &h->first;
- while (n->next != NULL)
- n = n->next;
- return &n->next;
-}
-
-#define hlist_entry(ptr, type, member) container_of(ptr,type,member)
-
-#define hlist_for_each(pos, head) \
- for (pos = (head)->first; pos; pos = pos->next)
-
-#define hlist_for_each_safe(pos, n, head) \
- for (pos = (head)->first; pos && ({ \
- n = pos->next; \
- 1; \
- }); \
- pos = n)
-
-#define hlist_for_each_entry(tpos, pos, head, member) \
- for (pos = (head)->first; \
- pos && ({ \
- tpos = hlist_entry(pos, typeof(*tpos), member); \
- 1; \
- }); \
- pos = pos->next)
-
-#define hlist_for_each_entry_safe(tpos, pos, n, head, member) \
- for (pos = (head)->first; \
- pos && ({ \
- n = pos->next; \
- 1; \
- }) \
- && ({ \
- tpos = hlist_entry(pos, typeof(*tpos), member); \
- 1; \
- }); \
- pos = n)
-
-
-struct list_head {
- struct list_head *next, *prev;
-};
-
-#define LIST_INITIALIZER(l) { .next = &l, .prev = &l }
-
-static inline void list_init(struct list_head *list)
-{
- list->next = list;
- list->prev = list;
-}
-
-static inline void __list_add(struct list_head *new, struct list_head *prev,
- struct list_head *next)
-{
- next->prev = new;
- new->next = next;
- new->prev = prev;
- prev->next = new;
-}
-
-static inline void list_add(struct list_head *new, struct list_head *head)
-{
- __list_add(new, head, head->next);
-}
-
-static inline void list_add_tail(struct list_head *new, struct list_head *head)
-{
- __list_add(new, head->prev, head);
-}
-
-static inline void __list_del(struct list_head *prev, struct list_head *next)
-{
- next->prev = prev;
- prev->next = next;
-}
-
-static inline void list_del(struct list_head *entry)
-{
- __list_del(entry->prev, entry->next);
- entry->next = NULL;
- entry->prev = NULL;
-}
-
-static inline int list_hashed(const struct list_head *n)
-{
- return n->next != n && n->next != NULL;
-}
-
-static inline int list_empty(const struct list_head *n)
-{
- return !list_hashed(n);
-}
-
-#define list_next(ptr, type, member) \
- (list_hashed(ptr) ? container_of((ptr)->next, type, member) : NULL)
-
-#define list_entry(ptr, type, member) container_of(ptr,type,member)
-
-#define list_for_each(pos, head) \
- for (pos = (head)->next; pos != (head); pos = pos->next)
-
-#define list_for_each_safe(pos, n, head) \
- for (pos = (head)->next, n = pos->next; pos != (head); \
- pos = n, n = pos->next)
-
-#define list_for_each_entry(pos, head, member) \
- for (pos = list_entry((head)->next, typeof(*pos), member); \
- &pos->member != (head); \
- pos = list_entry(pos->member.next, typeof(*pos), member))
-
-#define list_for_each_entry_safe(pos, n, head, member) \
- for (pos = ((head)->next != head ? \
- list_entry((head)->next, typeof(*pos), member) : \
- NULL), \
- n = (pos ? \
- list_entry(pos->member.next, typeof(*pos), member) : NULL); \
- pos && (&pos->member != (head)); \
- pos = n, n = list_entry(n->member.next, typeof(*n), member))
-
-#endif
diff --git a/nhrpd/nhrp_cache.c b/nhrpd/nhrp_cache.c
index c358baecb2..3823464a73 100644
--- a/nhrpd/nhrp_cache.c
+++ b/nhrpd/nhrp_cache.c
@@ -315,7 +315,7 @@ static void nhrp_cache_peer_notifier(struct notifier_block *n,
static void nhrp_cache_reset_new(struct nhrp_cache *c)
{
THREAD_OFF(c->t_auth);
- if (list_hashed(&c->newpeer_notifier.notifier_entry))
+ if (notifier_list_anywhere(&c->newpeer_notifier))
nhrp_peer_notify_del(c->new.peer, &c->newpeer_notifier);
nhrp_peer_unref(c->new.peer);
memset(&c->new, 0, sizeof(c->new));
@@ -574,5 +574,5 @@ void nhrp_cache_notify_add(struct nhrp_cache *c, struct notifier_block *n,
void nhrp_cache_notify_del(struct nhrp_cache *c, struct notifier_block *n)
{
- notifier_del(n);
+ notifier_del(n, &c->notifier_list);
}
diff --git a/nhrpd/nhrp_interface.c b/nhrpd/nhrp_interface.c
index 2db8997bad..94cec0281f 100644
--- a/nhrpd/nhrp_interface.c
+++ b/nhrpd/nhrp_interface.c
@@ -79,8 +79,8 @@ static int nhrp_if_new_hook(struct interface *ifp)
for (afi = 0; afi < AFI_MAX; afi++) {
struct nhrp_afi_data *ad = &nifp->afi[afi];
ad->holdtime = NHRPD_DEFAULT_HOLDTIME;
- list_init(&ad->nhslist_head);
- list_init(&ad->mcastlist_head);
+ nhrp_nhslist_init(&ad->nhslist_head);
+ nhrp_mcastlist_init(&ad->mcastlist_head);
}
return 0;
@@ -224,8 +224,12 @@ void nhrp_interface_update_nbma(struct interface *ifp,
nbmanifp = nbmaifp->info;
if (nbmaifp != nifp->nbmaifp) {
- if (nifp->nbmaifp)
- notifier_del(&nifp->nbmanifp_notifier);
+ if (nifp->nbmaifp) {
+ struct nhrp_interface *prev_nifp = nifp->nbmaifp->info;
+
+ notifier_del(&nifp->nbmanifp_notifier,
+ &prev_nifp->notifier_list);
+ }
nifp->nbmaifp = nbmaifp;
if (nbmaifp) {
notifier_add(&nifp->nbmanifp_notifier,
@@ -509,12 +513,15 @@ void nhrp_interface_notify_add(struct interface *ifp, struct notifier_block *n,
notifier_fn_t fn)
{
struct nhrp_interface *nifp = ifp->info;
+
notifier_add(n, &nifp->notifier_list, fn);
}
void nhrp_interface_notify_del(struct interface *ifp, struct notifier_block *n)
{
- notifier_del(n);
+ struct nhrp_interface *nifp = ifp->info;
+
+ notifier_del(n, &nifp->notifier_list);
}
void nhrp_interface_set_protection(struct interface *ifp, const char *profile,
diff --git a/nhrpd/nhrp_multicast.c b/nhrpd/nhrp_multicast.c
index 339b6dfabe..d8372ae8a8 100644
--- a/nhrpd/nhrp_multicast.c
+++ b/nhrpd/nhrp_multicast.c
@@ -219,7 +219,9 @@ void netlink_mcast_set_nflog_group(int nlgroup)
static int nhrp_multicast_free(struct interface *ifp,
struct nhrp_multicast *mcast)
{
- list_del(&mcast->list_entry);
+ struct nhrp_interface *nifp = ifp->info;
+
+ nhrp_mcastlist_del(&nifp->afi[mcast->afi].mcastlist_head, mcast);
XFREE(MTYPE_NHRP_MULTICAST, mcast);
return 0;
}
@@ -230,8 +232,7 @@ int nhrp_multicast_add(struct interface *ifp, afi_t afi,
struct nhrp_interface *nifp = ifp->info;
struct nhrp_multicast *mcast;
- list_for_each_entry(mcast, &nifp->afi[afi].mcastlist_head, list_entry)
- {
+ frr_each (nhrp_mcastlist, &nifp->afi[afi].mcastlist_head, mcast) {
if (sockunion_same(&mcast->nbma_addr, nbma_addr))
return NHRP_ERR_ENTRY_EXISTS;
}
@@ -241,7 +242,7 @@ int nhrp_multicast_add(struct interface *ifp, afi_t afi,
*mcast = (struct nhrp_multicast){
.afi = afi, .ifp = ifp, .nbma_addr = *nbma_addr,
};
- list_add_tail(&mcast->list_entry, &nifp->afi[afi].mcastlist_head);
+ nhrp_mcastlist_add_tail(&nifp->afi[afi].mcastlist_head, mcast);
debugf(NHRP_DEBUG_COMMON, "Adding multicast entry (%pSU)", nbma_addr);
@@ -252,11 +253,9 @@ int nhrp_multicast_del(struct interface *ifp, afi_t afi,
union sockunion *nbma_addr)
{
struct nhrp_interface *nifp = ifp->info;
- struct nhrp_multicast *mcast, *tmp;
+ struct nhrp_multicast *mcast;
- list_for_each_entry_safe(mcast, tmp, &nifp->afi[afi].mcastlist_head,
- list_entry)
- {
+ frr_each_safe (nhrp_mcastlist, &nifp->afi[afi].mcastlist_head, mcast) {
if (!sockunion_same(&mcast->nbma_addr, nbma_addr))
continue;
@@ -274,17 +273,15 @@ int nhrp_multicast_del(struct interface *ifp, afi_t afi,
void nhrp_multicast_interface_del(struct interface *ifp)
{
struct nhrp_interface *nifp = ifp->info;
- struct nhrp_multicast *mcast, *tmp;
+ struct nhrp_multicast *mcast;
afi_t afi;
for (afi = 0; afi < AFI_MAX; afi++) {
- debugf(NHRP_DEBUG_COMMON,
- "Cleaning up multicast entries (%d)",
- !list_empty(&nifp->afi[afi].mcastlist_head));
+ debugf(NHRP_DEBUG_COMMON, "Cleaning up multicast entries (%zu)",
+ nhrp_mcastlist_count(&nifp->afi[afi].mcastlist_head));
- list_for_each_entry_safe(
- mcast, tmp, &nifp->afi[afi].mcastlist_head, list_entry)
- {
+ frr_each_safe (nhrp_mcastlist, &nifp->afi[afi].mcastlist_head,
+ mcast) {
nhrp_multicast_free(ifp, mcast);
}
}
@@ -297,8 +294,7 @@ void nhrp_multicast_foreach(struct interface *ifp, afi_t afi,
struct nhrp_interface *nifp = ifp->info;
struct nhrp_multicast *mcast;
- list_for_each_entry(mcast, &nifp->afi[afi].mcastlist_head, list_entry)
- {
+ frr_each (nhrp_mcastlist, &nifp->afi[afi].mcastlist_head, mcast) {
cb(mcast, ctx);
}
}
diff --git a/nhrpd/nhrp_nhs.c b/nhrpd/nhrp_nhs.c
index 5179f15ebf..597c125e17 100644
--- a/nhrpd/nhrp_nhs.c
+++ b/nhrpd/nhrp_nhs.c
@@ -254,7 +254,7 @@ static void nhrp_reg_delete(struct nhrp_registration *r)
{
nhrp_peer_notify_del(r->peer, &r->peer_notifier);
nhrp_peer_unref(r->peer);
- list_del(&r->reglist_entry);
+ nhrp_reglist_del(&r->nhs->reglist_head, r);
THREAD_OFF(r->t_register);
XFREE(MTYPE_NHRP_REGISTRATION, r);
}
@@ -264,10 +264,9 @@ nhrp_reg_by_nbma(struct nhrp_nhs *nhs, const union sockunion *nbma_addr)
{
struct nhrp_registration *r;
- list_for_each_entry(
- r, &nhs->reglist_head,
- reglist_entry) if (sockunion_same(&r->peer->vc->remote.nbma,
- nbma_addr)) return r;
+ frr_each (nhrp_reglist, &nhs->reglist_head, r)
+ if (sockunion_same(&r->peer->vc->remote.nbma, nbma_addr))
+ return r;
return NULL;
}
@@ -276,7 +275,7 @@ static void nhrp_nhs_resolve_cb(struct resolver_query *q, const char *errstr,
{
struct nhrp_nhs *nhs = container_of(q, struct nhrp_nhs, dns_resolve);
struct nhrp_interface *nifp = nhs->ifp->info;
- struct nhrp_registration *reg, *regn;
+ struct nhrp_registration *reg;
int i;
if (n < 0) {
@@ -289,8 +288,8 @@ static void nhrp_nhs_resolve_cb(struct resolver_query *q, const char *errstr,
thread_add_timer(master, nhrp_nhs_resolve, nhs, 2 * 60 * 60,
&nhs->t_resolve);
- list_for_each_entry(reg, &nhs->reglist_head, reglist_entry) reg->mark =
- 1;
+ frr_each (nhrp_reglist, &nhs->reglist_head, reg)
+ reg->mark = 1;
nhs->hub = 0;
for (i = 0; i < n; i++) {
@@ -309,19 +308,16 @@ static void nhrp_nhs_resolve_cb(struct resolver_query *q, const char *errstr,
reg->peer = nhrp_peer_get(nhs->ifp, &addrs[i]);
reg->nhs = nhs;
reg->timeout = 1;
- list_init(&reg->reglist_entry);
- list_add_tail(&reg->reglist_entry, &nhs->reglist_head);
+ nhrp_reglist_add_tail(&nhs->reglist_head, reg);
nhrp_peer_notify_add(reg->peer, &reg->peer_notifier,
nhrp_reg_peer_notify);
thread_add_timer_msec(master, nhrp_reg_send_req, reg, 50,
&reg->t_register);
}
- list_for_each_entry_safe(reg, regn, &nhs->reglist_head, reglist_entry)
- {
+ frr_each_safe (nhrp_reglist, &nhs->reglist_head, reg)
if (reg->mark)
nhrp_reg_delete(reg);
- }
}
static int nhrp_nhs_resolve(struct thread *t)
@@ -344,8 +340,7 @@ int nhrp_nhs_add(struct interface *ifp, afi_t afi, union sockunion *proto_addr,
&& sockunion_family(proto_addr) != afi2family(afi))
return NHRP_ERR_PROTOCOL_ADDRESS_MISMATCH;
- list_for_each_entry(nhs, &nifp->afi[afi].nhslist_head, nhslist_entry)
- {
+ frr_each (nhrp_nhslist, &nifp->afi[afi].nhslist_head, nhs) {
if (sockunion_family(&nhs->proto_addr) != AF_UNSPEC
&& sockunion_family(proto_addr) != AF_UNSPEC
&& sockunion_same(&nhs->proto_addr, proto_addr))
@@ -362,9 +357,9 @@ int nhrp_nhs_add(struct interface *ifp, afi_t afi, union sockunion *proto_addr,
.ifp = ifp,
.proto_addr = *proto_addr,
.nbma_fqdn = strdup(nbma_fqdn),
- .reglist_head = LIST_INITIALIZER(nhs->reglist_head),
+ .reglist_head = INIT_DLIST(nhs->reglist_head),
};
- list_add_tail(&nhs->nhslist_entry, &nifp->afi[afi].nhslist_head);
+ nhrp_nhslist_add_tail(&nifp->afi[afi].nhslist_head, nhs);
thread_add_timer_msec(master, nhrp_nhs_resolve, nhs, 1000,
&nhs->t_resolve);
@@ -375,36 +370,34 @@ int nhrp_nhs_del(struct interface *ifp, afi_t afi, union sockunion *proto_addr,
const char *nbma_fqdn)
{
struct nhrp_interface *nifp = ifp->info;
- struct nhrp_nhs *nhs, *nnhs;
+ struct nhrp_nhs *nhs;
int ret = NHRP_ERR_ENTRY_NOT_FOUND;
if (sockunion_family(proto_addr) != AF_UNSPEC
&& sockunion_family(proto_addr) != afi2family(afi))
return NHRP_ERR_PROTOCOL_ADDRESS_MISMATCH;
- list_for_each_entry_safe(nhs, nnhs, &nifp->afi[afi].nhslist_head,
- nhslist_entry)
- {
+ frr_each_safe (nhrp_nhslist, &nifp->afi[afi].nhslist_head, nhs) {
if (!sockunion_same(&nhs->proto_addr, proto_addr))
continue;
if (strcmp(nhs->nbma_fqdn, nbma_fqdn) != 0)
continue;
- nhrp_nhs_free(nhs);
+ nhrp_nhs_free(nifp, afi, nhs);
ret = NHRP_OK;
}
return ret;
}
-int nhrp_nhs_free(struct nhrp_nhs *nhs)
+int nhrp_nhs_free(struct nhrp_interface *nifp, afi_t afi, struct nhrp_nhs *nhs)
{
- struct nhrp_registration *r, *rn;
+ struct nhrp_registration *r;
- list_for_each_entry_safe(r, rn, &nhs->reglist_head, reglist_entry)
+ frr_each_safe (nhrp_reglist, &nhs->reglist_head, r)
nhrp_reg_delete(r);
THREAD_OFF(nhs->t_resolve);
- list_del(&nhs->nhslist_entry);
+ nhrp_nhslist_del(&nifp->afi[afi].nhslist_head, nhs);
free((void *)nhs->nbma_fqdn);
XFREE(MTYPE_NHRP_NHS, nhs);
return 0;
@@ -413,18 +406,15 @@ int nhrp_nhs_free(struct nhrp_nhs *nhs)
void nhrp_nhs_interface_del(struct interface *ifp)
{
struct nhrp_interface *nifp = ifp->info;
- struct nhrp_nhs *nhs, *tmp;
+ struct nhrp_nhs *nhs;
afi_t afi;
for (afi = 0; afi < AFI_MAX; afi++) {
- debugf(NHRP_DEBUG_COMMON, "Cleaning up nhs entries (%d)",
- !list_empty(&nifp->afi[afi].nhslist_head));
+ debugf(NHRP_DEBUG_COMMON, "Cleaning up nhs entries (%zu)",
+ nhrp_nhslist_count(&nifp->afi[afi].nhslist_head));
- list_for_each_entry_safe(nhs, tmp, &nifp->afi[afi].nhslist_head,
- nhslist_entry)
- {
- nhrp_nhs_free(nhs);
- }
+ frr_each_safe (nhrp_nhslist, &nifp->afi[afi].nhslist_head, nhs)
+ nhrp_nhs_free(nifp, afi, nhs);
}
}
@@ -433,15 +423,15 @@ void nhrp_nhs_terminate(void)
struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
struct interface *ifp;
struct nhrp_interface *nifp;
- struct nhrp_nhs *nhs, *tmp;
+ struct nhrp_nhs *nhs;
afi_t afi;
FOR_ALL_INTERFACES (vrf, ifp) {
nifp = ifp->info;
for (afi = 0; afi < AFI_MAX; afi++) {
- list_for_each_entry_safe(
- nhs, tmp, &nifp->afi[afi].nhslist_head,
- nhslist_entry) nhrp_nhs_free(nhs);
+ frr_each_safe (nhrp_nhslist,
+ &nifp->afi[afi].nhslist_head, nhs)
+ nhrp_nhs_free(nifp, afi, nhs);
}
}
}
@@ -455,11 +445,10 @@ void nhrp_nhs_foreach(struct interface *ifp, afi_t afi,
struct nhrp_nhs *nhs;
struct nhrp_registration *reg;
- list_for_each_entry(nhs, &nifp->afi[afi].nhslist_head, nhslist_entry)
- {
- if (!list_empty(&nhs->reglist_head)) {
- list_for_each_entry(reg, &nhs->reglist_head,
- reglist_entry) cb(nhs, reg, ctx);
+ frr_each (nhrp_nhslist, &nifp->afi[afi].nhslist_head, nhs) {
+ if (nhrp_reglist_count(&nhs->reglist_head)) {
+ frr_each (nhrp_reglist, &nhs->reglist_head, reg)
+ cb(nhs, reg, ctx);
} else
cb(nhs, 0, ctx);
}
@@ -472,19 +461,14 @@ int nhrp_nhs_match_ip(union sockunion *in_ip, struct nhrp_interface *nifp)
struct nhrp_registration *reg;
for (i = 0; i < AFI_MAX; i++) {
- list_for_each_entry(nhs, &nifp->afi[i].nhslist_head,
- nhslist_entry)
- {
- if (!list_empty(&nhs->reglist_head)) {
- list_for_each_entry(reg, &nhs->reglist_head,
- reglist_entry)
- {
- if (!sockunion_cmp(
- in_ip,
- &reg->peer->vc->remote
- .nbma))
- return 1;
- }
+ frr_each (nhrp_nhslist, &nifp->afi[i].nhslist_head, nhs) {
+ if (!nhrp_reglist_count(&nhs->reglist_head))
+ continue;
+
+ frr_each (nhrp_reglist, &nhs->reglist_head, reg) {
+ if (!sockunion_cmp(in_ip,
+ &reg->peer->vc->remote.nbma))
+ return 1;
}
}
}
diff --git a/nhrpd/nhrp_peer.c b/nhrpd/nhrp_peer.c
index 030f4c0ff3..51cae44bd1 100644
--- a/nhrpd/nhrp_peer.c
+++ b/nhrpd/nhrp_peer.c
@@ -359,7 +359,7 @@ void nhrp_peer_notify_add(struct nhrp_peer *p, struct notifier_block *n,
void nhrp_peer_notify_del(struct nhrp_peer *p, struct notifier_block *n)
{
- notifier_del(n);
+ notifier_del(n, &p->notifier_list);
nhrp_peer_check_delete(p);
}
diff --git a/nhrpd/nhrp_vc.c b/nhrpd/nhrp_vc.c
index b3b657f3fa..4b45389dad 100644
--- a/nhrpd/nhrp_vc.c
+++ b/nhrpd/nhrp_vc.c
@@ -19,14 +19,18 @@
DEFINE_MTYPE_STATIC(NHRPD, NHRP_VC, "NHRP virtual connection");
+PREDECL_DLIST(childlist);
+
struct child_sa {
uint32_t id;
struct nhrp_vc *vc;
- struct list_head childlist_entry;
+ struct childlist_item childlist_entry;
};
+DECLARE_DLIST(childlist, struct child_sa, childlist_entry);
+
static struct hash *nhrp_vc_hash;
-static struct list_head childlist_head[512];
+static struct childlist_head childlist_head[512];
static unsigned int nhrp_vc_key(const void *peer_data)
{
@@ -104,8 +108,7 @@ int nhrp_vc_ipsec_updown(uint32_t child_id, struct nhrp_vc *vc)
uint32_t child_hash = child_id % array_size(childlist_head);
int abort_migration = 0;
- list_for_each_entry(lsa, &childlist_head[child_hash], childlist_entry)
- {
+ frr_each (childlist, &childlist_head[child_hash], lsa) {
if (lsa->id == child_id) {
sa = lsa;
break;
@@ -120,12 +123,9 @@ int nhrp_vc_ipsec_updown(uint32_t child_id, struct nhrp_vc *vc)
*sa = (struct child_sa){
.id = child_id,
- .childlist_entry =
- LIST_INITIALIZER(sa->childlist_entry),
.vc = NULL,
};
- list_add_tail(&sa->childlist_entry,
- &childlist_head[child_hash]);
+ childlist_add_tail(&childlist_head[child_hash], sa);
}
if (sa->vc == vc)
@@ -155,7 +155,7 @@ int nhrp_vc_ipsec_updown(uint32_t child_id, struct nhrp_vc *vc)
/* Update */
sa->vc = vc;
if (!vc) {
- list_del(&sa->childlist_entry);
+ childlist_del(&childlist_head[child_hash], sa);
XFREE(MTYPE_NHRP_VC, sa);
}
@@ -170,7 +170,7 @@ void nhrp_vc_notify_add(struct nhrp_vc *vc, struct notifier_block *n,
void nhrp_vc_notify_del(struct nhrp_vc *vc, struct notifier_block *n)
{
- notifier_del(n);
+ notifier_del(n, &vc->notifier_list);
nhrp_vc_check_delete(vc);
}
@@ -200,17 +200,16 @@ void nhrp_vc_init(void)
nhrp_vc_hash = hash_create(nhrp_vc_key, nhrp_vc_cmp, "NHRP VC hash");
for (i = 0; i < array_size(childlist_head); i++)
- list_init(&childlist_head[i]);
+ childlist_init(&childlist_head[i]);
}
void nhrp_vc_reset(void)
{
- struct child_sa *sa, *n;
+ struct child_sa *sa;
size_t i;
for (i = 0; i < array_size(childlist_head); i++) {
- list_for_each_entry_safe(sa, n, &childlist_head[i],
- childlist_entry)
+ frr_each_safe (childlist, &childlist_head[i], sa)
nhrp_vc_ipsec_updown(sa->id, 0);
}
}
diff --git a/nhrpd/nhrp_vty.c b/nhrpd/nhrp_vty.c
index 50161dae2f..0dfabcf6ae 100644
--- a/nhrpd/nhrp_vty.c
+++ b/nhrpd/nhrp_vty.c
@@ -1200,9 +1200,7 @@ static int interface_config_write(struct vty *vty)
nhrp_cache_config_foreach(
ifp, interface_config_write_nhrp_map, &mapctx);
- list_for_each_entry(nhs, &ad->nhslist_head,
- nhslist_entry)
- {
+ frr_each (nhrp_nhslist, &ad->nhslist_head, nhs) {
vty_out(vty, " %s nhrp nhs ", aficmd);
if (sockunion_family(&nhs->proto_addr)
== AF_UNSPEC)
@@ -1212,9 +1210,7 @@ static int interface_config_write(struct vty *vty)
vty_out(vty, " nbma %s\n", nhs->nbma_fqdn);
}
- list_for_each_entry(mcast, &ad->mcastlist_head,
- list_entry)
- {
+ frr_each (nhrp_mcastlist, &ad->mcastlist_head, mcast) {
vty_out(vty, " %s nhrp map multicast ", aficmd);
if (sockunion_family(&mcast->nbma_addr)
== AF_UNSPEC)
diff --git a/nhrpd/nhrpd.h b/nhrpd/nhrpd.h
index 17abb04762..63f1cb97ef 100644
--- a/nhrpd/nhrpd.h
+++ b/nhrpd/nhrpd.h
@@ -10,8 +10,6 @@
#ifndef NHRPD_H
#define NHRPD_H
-#include "list.h"
-
#include "zbuf.h"
#include "zclient.h"
#include "debug.h"
@@ -42,48 +40,53 @@ struct notifier_block;
typedef void (*notifier_fn_t)(struct notifier_block *, unsigned long);
+PREDECL_DLIST(notifier_list);
+
struct notifier_block {
- struct list_head notifier_entry;
+ struct notifier_list_item notifier_entry;
notifier_fn_t action;
};
+DECLARE_DLIST(notifier_list, struct notifier_block, notifier_entry);
+
struct notifier_list {
- struct list_head notifier_head;
+ struct notifier_list_head head;
};
#define NOTIFIER_LIST_INITIALIZER(l) \
{ \
- .notifier_head = LIST_INITIALIZER((l)->notifier_head) \
+ .head = INIT_DLIST((l)->head) \
}
static inline void notifier_init(struct notifier_list *l)
{
- list_init(&l->notifier_head);
+ notifier_list_init(&l->head);
}
static inline void notifier_add(struct notifier_block *n,
struct notifier_list *l, notifier_fn_t action)
{
n->action = action;
- list_add_tail(&n->notifier_entry, &l->notifier_head);
+ notifier_list_add_tail(&l->head, n);
}
-static inline void notifier_del(struct notifier_block *n)
+static inline void notifier_del(struct notifier_block *n,
+ struct notifier_list *l)
{
- list_del(&n->notifier_entry);
+ notifier_list_del(&l->head, n);
}
static inline void notifier_call(struct notifier_list *l, int cmd)
{
- struct notifier_block *n, *nn;
- list_for_each_entry_safe(n, nn, &l->notifier_head, notifier_entry) {
+ struct notifier_block *n;
+
+ frr_each_safe (notifier_list, &l->head, n)
n->action(n, cmd);
- }
}
static inline int notifier_active(struct notifier_list *l)
{
- return !list_empty(&l->notifier_head);
+ return notifier_list_count(&l->head) > 0;
}
extern struct hash *nhrp_gre_list;
@@ -263,9 +266,13 @@ struct nhrp_shortcut {
struct notifier_block cache_notifier;
};
+PREDECL_DLIST(nhrp_nhslist);
+PREDECL_DLIST(nhrp_mcastlist);
+PREDECL_DLIST(nhrp_reglist);
+
struct nhrp_nhs {
struct interface *ifp;
- struct list_head nhslist_entry;
+ struct nhrp_nhslist_item nhslist_entry;
unsigned hub : 1;
afi_t afi;
@@ -274,18 +281,22 @@ struct nhrp_nhs {
struct thread *t_resolve;
struct resolver_query dns_resolve;
- struct list_head reglist_head;
+ struct nhrp_reglist_head reglist_head;
};
+DECLARE_DLIST(nhrp_nhslist, struct nhrp_nhs, nhslist_entry);
+
struct nhrp_multicast {
struct interface *ifp;
- struct list_head list_entry;
+ struct nhrp_mcastlist_item mcastlist_entry;
afi_t afi;
union sockunion nbma_addr; /* IP-address */
};
+DECLARE_DLIST(nhrp_mcastlist, struct nhrp_multicast, mcastlist_entry);
+
struct nhrp_registration {
- struct list_head reglist_entry;
+ struct nhrp_reglist_item reglist_entry;
struct thread *t_register;
struct nhrp_nhs *nhs;
struct nhrp_reqid reqid;
@@ -296,6 +307,8 @@ struct nhrp_registration {
struct notifier_block peer_notifier;
};
+DECLARE_DLIST(nhrp_reglist, struct nhrp_registration, reglist_entry);
+
#define NHRP_IFF_SHORTCUT 0x0001
#define NHRP_IFF_REDIRECT 0x0002
#define NHRP_IFF_REG_NO_UNIQUE 0x0100
@@ -330,8 +343,8 @@ struct nhrp_interface {
short configured_mtu;
unsigned short mtu;
unsigned int holdtime;
- struct list_head nhslist_head;
- struct list_head mcastlist_head;
+ struct nhrp_nhslist_head nhslist_head;
+ struct nhrp_mcastlist_head mcastlist_head;
} afi[AFI_MAX];
};
@@ -381,7 +394,7 @@ int nhrp_nhs_add(struct interface *ifp, afi_t afi, union sockunion *proto_addr,
const char *nbma_fqdn);
int nhrp_nhs_del(struct interface *ifp, afi_t afi, union sockunion *proto_addr,
const char *nbma_fqdn);
-int nhrp_nhs_free(struct nhrp_nhs *nhs);
+int nhrp_nhs_free(struct nhrp_interface *nifp, afi_t afi, struct nhrp_nhs *nhs);
void nhrp_nhs_terminate(void);
void nhrp_nhs_foreach(struct interface *ifp, afi_t afi,
void (*cb)(struct nhrp_nhs *, struct nhrp_registration *,
diff --git a/nhrpd/subdir.am b/nhrpd/subdir.am
index 9a186d6ed8..dc0c162c83 100644
--- a/nhrpd/subdir.am
+++ b/nhrpd/subdir.am
@@ -34,7 +34,6 @@ nhrpd_nhrpd_SOURCES = \
noinst_HEADERS += \
nhrpd/debug.h \
- nhrpd/list.h \
nhrpd/netlink.h \
nhrpd/nhrp_errors.h \
nhrpd/nhrp_protocol.h \
diff --git a/nhrpd/zbuf.c b/nhrpd/zbuf.c
index e191a90f2d..9cc2b56245 100644
--- a/nhrpd/zbuf.c
+++ b/nhrpd/zbuf.c
@@ -164,35 +164,33 @@ void *zbuf_may_pull_until(struct zbuf *zb, const char *sep, struct zbuf *msg)
void zbufq_init(struct zbuf_queue *zbq)
{
*zbq = (struct zbuf_queue){
- .queue_head = LIST_INITIALIZER(zbq->queue_head),
+ .queue_head = INIT_DLIST(zbq->queue_head),
};
}
void zbufq_reset(struct zbuf_queue *zbq)
{
- struct zbuf *buf, *bufn;
+ struct zbuf *buf;
- list_for_each_entry_safe(buf, bufn, &zbq->queue_head, queue_list)
- {
- list_del(&buf->queue_list);
+ frr_each_safe (zbuf_queue, &zbq->queue_head, buf) {
+ zbuf_queue_del(&zbq->queue_head, buf);
zbuf_free(buf);
}
}
void zbufq_queue(struct zbuf_queue *zbq, struct zbuf *zb)
{
- list_add_tail(&zb->queue_list, &zbq->queue_head);
+ zbuf_queue_add_tail(&zbq->queue_head, zb);
}
int zbufq_write(struct zbuf_queue *zbq, int fd)
{
struct iovec iov[16];
- struct zbuf *zb, *zbn;
+ struct zbuf *zb;
ssize_t r;
size_t iovcnt = 0;
- list_for_each_entry_safe(zb, zbn, &zbq->queue_head, queue_list)
- {
+ frr_each_safe (zbuf_queue, &zbq->queue_head, zb) {
iov[iovcnt++] = (struct iovec){
.iov_base = zb->head, .iov_len = zbuf_used(zb),
};
@@ -204,15 +202,14 @@ int zbufq_write(struct zbuf_queue *zbq, int fd)
if (r < 0)
return r;
- list_for_each_entry_safe(zb, zbn, &zbq->queue_head, queue_list)
- {
+ frr_each_safe (zbuf_queue, &zbq->queue_head, zb) {
if (r < (ssize_t)zbuf_used(zb)) {
zb->head += r;
return 1;
}
r -= zbuf_used(zb);
- list_del(&zb->queue_list);
+ zbuf_queue_del(&zbq->queue_head, zb);
zbuf_free(zb);
}
diff --git a/nhrpd/zbuf.h b/nhrpd/zbuf.h
index 2741860bfd..d036b10460 100644
--- a/nhrpd/zbuf.h
+++ b/nhrpd/zbuf.h
@@ -15,18 +15,22 @@
#include <endian.h>
#include <sys/types.h>
-#include "list.h"
+#include "typesafe.h"
+
+PREDECL_DLIST(zbuf_queue);
struct zbuf {
- struct list_head queue_list;
+ struct zbuf_queue_item queue_entry;
unsigned allocated : 1;
unsigned error : 1;
uint8_t *buf, *end;
uint8_t *head, *tail;
};
+DECLARE_DLIST(zbuf_queue, struct zbuf, queue_entry);
+
struct zbuf_queue {
- struct list_head queue_head;
+ struct zbuf_queue_head queue_head;
};
struct zbuf *zbuf_alloc(size_t size);
diff --git a/tests/.gitignore b/tests/.gitignore
index 498d7dd0b7..8cc2aa98f9 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -28,6 +28,7 @@
/lib/test_frrscript
/lib/test_frrlua
/lib/test_graph
+/lib/test_grpc
/lib/test_heavy
/lib/test_heavy_thread
/lib/test_heavy_wq
@@ -44,6 +45,7 @@
/lib/test_segv
/lib/test_seqlock
/lib/test_sig
+/lib/test_skiplist
/lib/test_srcdest_table
/lib/test_stream
/lib/test_table
diff --git a/tests/lib/test_typelist.h b/tests/lib/test_typelist.h
index 379a2396b4..8261616ed2 100644
--- a/tests/lib/test_typelist.h
+++ b/tests/lib/test_typelist.h
@@ -39,6 +39,8 @@
#define list_find concat(TYPE, _find)
#define list_find_lt concat(TYPE, _find_lt)
#define list_find_gteq concat(TYPE, _find_gteq)
+#define list_member concat(TYPE, _member)
+#define list_anywhere concat(TYPE, _anywhere)
#define list_del concat(TYPE, _del)
#define list_pop concat(TYPE, _pop)
#define list_swap_all concat(TYPE, _swap_all)
@@ -239,6 +241,13 @@ static void concat(test_, TYPE)(void)
ts_hash_headx(
&head, "swap2b",
"a538546a6e6ab0484e925940aa8dd02fd934408bbaed8cb66a0721841584d838");
+
+ while (list_pop(&other))
+ ;
+ list_fini(&other);
+ prng_free(prng_swap);
+
+ ts_ref("swap-cleanup");
#endif /* !IS_ATOMIC */
k = 0;
@@ -294,7 +303,7 @@ static void concat(test_, TYPE)(void)
#elif IS_HEAP(REALTYPE)
/* heap - partially sorted. */
prev = NULL;
- l = k / 2;
+ l = k / 4;
for (i = 0; i < l; i++) {
item = list_pop(&head);
if (prev)
@@ -303,7 +312,24 @@ static void concat(test_, TYPE)(void)
k--;
prev = item;
}
- ts_hash("pop", NULL);
+ ts_hash("pop#1", NULL);
+
+ for (i = 0; i < NITEM; i++)
+ assertf(list_member(&head, &itm[i]) == itm[i].scratchpad,
+ "%zu should:%d is:%d", i, itm[i].scratchpad,
+ list_member(&head, &itm[i]));
+ ts_hash("member", NULL);
+
+ l = k / 2;
+ for (; i < l; i++) {
+ item = list_pop(&head);
+ if (prev)
+ assert(prev->val < item->val);
+ item->scratchpad = 0;
+ k--;
+ prev = item;
+ }
+ ts_hash("pop#2", NULL);
#else /* !IS_UNIQ(REALTYPE) && !IS_HEAP(REALTYPE) */
for (i = 0; i < NITEM; i++) {
@@ -380,6 +406,14 @@ static void concat(test_, TYPE)(void)
assert(l + list_count(&head) == k);
ts_hashx("del", "cb2e5d80f08a803ef7b56c15e981b681adcea214bebc2f55e12e0bfb242b07ca");
+#if !IS_ATOMIC(REALTYPE)
+ for (i = 0; i < NITEM; i++)
+ assertf(list_member(&head, &itm[i]) == itm[i].scratchpad,
+ "%zu should:%d is:%d", i, itm[i].scratchpad,
+ list_member(&head, &itm[i]));
+ ts_hashx("member", "cb2e5d80f08a803ef7b56c15e981b681adcea214bebc2f55e12e0bfb242b07ca");
+#endif
+
frr_each_safe(list, &head, item) {
assert(item->scratchpad != 0);
@@ -449,6 +483,13 @@ static void concat(test_, TYPE)(void)
ts_hash_head(
&head, "swap2b",
"eabfcf1413936daaf20965abced95762f45110a6619b84aac7d38481bce4ea19");
+
+ while (list_pop(&other))
+ ;
+ list_fini(&other);
+ prng_free(prng_swap);
+
+ ts_ref("swap-cleanup");
#endif
for (i = 0; i < NITEM / 2; i++) {
@@ -461,7 +502,39 @@ static void concat(test_, TYPE)(void)
}
ts_hash("del-prng", "86d568a95eb429dab3162976c5a5f3f75aabc835932cd682aa280b6923549564");
+#if !IS_ATOMIC(REALTYPE)
+ for (i = 0; i < NITEM; i++) {
+ assertf(list_member(&head, &itm[i]) == itm[i].scratchpad,
+ "%zu should:%d is:%d", i, itm[i].scratchpad,
+ list_member(&head, &itm[i]));
+ assertf(list_anywhere(&itm[i]) == itm[i].scratchpad,
+ "%zu should:%d is:%d", i, itm[i].scratchpad,
+ list_anywhere(&itm[i]));
+ }
+ ts_hash("member", "86d568a95eb429dab3162976c5a5f3f75aabc835932cd682aa280b6923549564");
+#endif
+
l = 0;
+ while (l < (k / 4) && (prev = list_pop(&head))) {
+ assert(prev->scratchpad != 0);
+
+ prev->scratchpad = 0;
+ l++;
+ }
+ ts_hash("pop#1", "42b8950c880535b2d2e0c980f9845f7841ecf675c0fb9801aec4170d2036349d");
+
+#if !IS_ATOMIC(REALTYPE)
+ for (i = 0; i < NITEM; i++) {
+ assertf(list_member(&head, &itm[i]) == itm[i].scratchpad,
+ "%zu should:%d is:%d", i, itm[i].scratchpad,
+ list_member(&head, &itm[i]));
+ assertf(list_anywhere(&itm[i]) == itm[i].scratchpad,
+ "%zu should:%d is:%d", i, itm[i].scratchpad,
+ list_anywhere(&itm[i]));
+ }
+ ts_hash("member", "42b8950c880535b2d2e0c980f9845f7841ecf675c0fb9801aec4170d2036349d");
+#endif
+
while ((item = list_pop(&head))) {
assert(item->scratchpad != 0);
@@ -471,7 +544,7 @@ static void concat(test_, TYPE)(void)
assert(l == k);
assert(list_count(&head) == 0);
assert(list_first(&head) == NULL);
- ts_hash("pop", "df3f619804a92fdb4057192dc43dd748ea778adc52bc498ce80524c014b81119");
+ ts_hash("pop#2", "df3f619804a92fdb4057192dc43dd748ea778adc52bc498ce80524c014b81119");
prng_free(prng);
prng = prng_new(0x1e5a2d69);
@@ -650,6 +723,7 @@ static void concat(test_, TYPE)(void)
list_fini(&head);
ts_ref("fini");
ts_end();
+ prng_free(prng);
printfrr("%s end\n", str(TYPE));
}
@@ -680,6 +754,8 @@ static void concat(test_, TYPE)(void)
#undef list_find
#undef list_find_lt
#undef list_find_gteq
+#undef list_member
+#undef list_anywhere
#undef list_del
#undef list_pop
#undef list_swap_all
diff --git a/tools/checkpatch.pl b/tools/checkpatch.pl
index cf15d00796..d2eb20ce5b 100755
--- a/tools/checkpatch.pl
+++ b/tools/checkpatch.pl
@@ -409,6 +409,25 @@ our $Operators = qr{
}x;
our $c90_Keywords = qr{do|for|while|if|else|return|goto|continue|switch|default|case|break}x;
+our $Iterators = qr{
+ frr_each|frr_each_safe|frr_each_from|
+ frr_with_mutex|frr_with_privs|
+ LIST_FOREACH|LIST_FOREACH_SAFE|
+ SLIST_FOREACH|SLIST_FOREACH_SAFE|SLIST_FOREACH_PREVPTR|
+ STAILQ_FOREACH|STAILQ_FOREACH_SAFE|
+ TAILQ_FOREACH|TAILQ_FOREACH_SAFE|TAILQ_FOREACH_REVERSE|TAILQ_FOREACH_REVERSE_SAFE|
+ RB_FOREACH|RB_FOREACH_SAFE|RB_FOREACH_REVERSE|RB_FOREACH_REVERSE_SAFE|
+ SPLAY_FOREACH|
+ FOR_ALL_INTERFACES|FOR_ALL_INTERFACES_ADDRESSES|JSON_FOREACH|
+ LY_FOR_KEYS|LY_LIST_FOR|LY_TREE_FOR|LY_TREE_DFS_BEGIN|LYD_TREE_DFS_BEGIN|
+ RE_DEST_FOREACH_ROUTE|RE_DEST_FOREACH_ROUTE_SAFE|
+ RNODE_FOREACH_RE|RNODE_FOREACH_RE_SAFE|
+ UPDGRP_FOREACH_SUBGRP|UPDGRP_FOREACH_SUBGRP_SAFE|
+ SUBGRP_FOREACH_PEER|SUBGRP_FOREACH_PEER_SAFE|
+ SUBGRP_FOREACH_ADJ|SUBGRP_FOREACH_ADJ_SAFE|
+ AF_FOREACH|FOREACH_AFI_SAFI|FOREACH_SAFI|
+ LSDB_LOOP
+ }x;
our $BasicType;
our $NonptrType;
@@ -1009,9 +1028,9 @@ sub top_of_kernel_tree {
my ($root) = @_;
my @tree_check = (
- "COPYING", "CREDITS", "Kbuild", "MAINTAINERS", "Makefile",
- "README", "Documentation", "arch", "include", "drivers",
- "fs", "init", "ipc", "kernel", "lib", "scripts",
+ "COPYING", "configure.ac", "Makefile.am",
+ "README.md", "doc", "lib", "vtysh", "watchfrr", "tests",
+ "zebra", "bgpd", "ospfd", "ospf6d", "isisd", "staticd",
);
foreach my $check (@tree_check) {
@@ -2655,8 +2674,8 @@ sub process {
(defined($1) || defined($2))))) {
$is_patch = 1;
$reported_maintainer_file = 1;
- WARN("FILE_PATH_CHANGES",
- "added, moved or deleted file(s), does MAINTAINERS need updating?\n" . $herecurr);
+ #WARN("FILE_PATH_CHANGES",
+ # "added, moved or deleted file(s), does MAINTAINERS need updating?\n" . $herecurr);
}
# Check for wrappage within a valid hunk of the file
@@ -4028,7 +4047,8 @@ sub process {
if|for|while|switch|return|case|
volatile|__volatile__|
__attribute__|format|__extension__|
- asm|__asm__)$/x)
+ asm|__asm__|
+ $Iterators)$/x)
{
# cpp #define statements have non-optional spaces, ie
# if there is a space between the name and the open