diff options
| -rw-r--r-- | doc/developer/lists.rst | 27 | ||||
| -rw-r--r-- | lib/typerb.c | 10 | ||||
| -rw-r--r-- | lib/typerb.h | 7 | ||||
| -rw-r--r-- | lib/typesafe.c | 40 | ||||
| -rw-r--r-- | lib/typesafe.h | 109 | ||||
| -rw-r--r-- | nhrpd/list.h | 209 | ||||
| -rw-r--r-- | nhrpd/nhrp_cache.c | 4 | ||||
| -rw-r--r-- | nhrpd/nhrp_interface.c | 17 | ||||
| -rw-r--r-- | nhrpd/nhrp_multicast.c | 30 | ||||
| -rw-r--r-- | nhrpd/nhrp_nhs.c | 96 | ||||
| -rw-r--r-- | nhrpd/nhrp_peer.c | 2 | ||||
| -rw-r--r-- | nhrpd/nhrp_vc.c | 27 | ||||
| -rw-r--r-- | nhrpd/nhrp_vty.c | 8 | ||||
| -rw-r--r-- | nhrpd/nhrpd.h | 53 | ||||
| -rw-r--r-- | nhrpd/subdir.am | 1 | ||||
| -rw-r--r-- | nhrpd/zbuf.c | 21 | ||||
| -rw-r--r-- | nhrpd/zbuf.h | 10 | ||||
| -rw-r--r-- | tests/.gitignore | 2 | ||||
| -rw-r--r-- | tests/lib/test_typelist.h | 82 | ||||
| -rwxr-xr-x | tools/checkpatch.pl | 32 |
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(®->reglist_entry); - list_add_tail(®->reglist_entry, &nhs->reglist_head); + nhrp_reglist_add_tail(&nhs->reglist_head, reg); nhrp_peer_notify_add(reg->peer, ®->peer_notifier, nhrp_reg_peer_notify); thread_add_timer_msec(master, nhrp_reg_send_req, reg, 50, ®->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, - ®->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, + ®->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 |
