mirror of
https://git.proxmox.com/git/mirror_frr
synced 2026-01-06 01:40:45 +00:00
Merge pull request #9766 from opensourcerouting/typesafe-member-nhrp-zap
lib: add typesafe membership-test functions
This commit is contained in:
commit
52e458d922
@ -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
|
||||
-------------------------
|
||||
|
||||
|
||||
10
lib/typerb.c
10
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;
|
||||
}
|
||||
|
||||
@ -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) \
|
||||
|
||||
@ -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)
|
||||
{
|
||||
|
||||
109
lib/typesafe.h
109
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 */
|
||||
|
||||
|
||||
|
||||
209
nhrpd/list.h
209
nhrpd/list.h
@ -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
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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 *,
|
||||
|
||||
@ -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 \
|
||||
|
||||
21
nhrpd/zbuf.c
21
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);
|
||||
}
|
||||
|
||||
|
||||
10
nhrpd/zbuf.h
10
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);
|
||||
|
||||
2
tests/.gitignore
vendored
2
tests/.gitignore
vendored
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
Loading…
Reference in New Issue
Block a user