mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-12-23 10:11:53 +00:00
Notify: Also the listener list is typed.
This commit is contained in:
parent
bb623f0ae3
commit
9d27e7c98b
61
lib/tlists.h
Normal file
61
lib/tlists.h
Normal file
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* BIRD Library -- Typed Linked Lists
|
||||
*
|
||||
* (c) 2019 Maria Matejka <mq@jmq.cz>
|
||||
*
|
||||
* Can be freely distributed and used under the terms of the GNU GPL.
|
||||
*
|
||||
* Based roughly on Martin Mares' lib/lists.h but completely implemented as macros.
|
||||
*/
|
||||
|
||||
#ifndef _BIRD_TLISTS_H_
|
||||
#define _BIRD_TLISTS_H_
|
||||
|
||||
#define TNODE(t) struct tnode__##t
|
||||
#define TNODE_DEF(t)
|
||||
#define TLIST(t) union tlist__##t
|
||||
#define TLIST_DEF(t) TNODE(t) { \
|
||||
TNODE(t) *next; \
|
||||
struct t *self; \
|
||||
TNODE(t) *prev; \
|
||||
}; \
|
||||
TLIST(t) { \
|
||||
struct { \
|
||||
TNODE(t) head_node; \
|
||||
struct t *head_null_self; \
|
||||
TNODE(t) *tail; \
|
||||
}; \
|
||||
struct { \
|
||||
TNODE(t) *head; \
|
||||
struct t *tail_padding_self; \
|
||||
TNODE(t) tail_node; \
|
||||
}; \
|
||||
}
|
||||
|
||||
#define INIT_TLIST(t, list) do { \
|
||||
memset(&(list), 0, sizeof(TLIST(t))); \
|
||||
list.head_node.next = &(list.tail_node); \
|
||||
list.tail_node.prev = &(list.head_node); \
|
||||
} while (0)
|
||||
|
||||
#define TNODE_VALID(t, n) ((n)->next)
|
||||
#define WALK_TLIST(t, n, list) for (TNODE(t) *n = list.head; TNODE_VALID(t, n); n = n->next)
|
||||
#define WALK_TLIST_DELSAFE(t, n, list) \
|
||||
for (TNODE(t) *n = list.head, *_n; _n = n->next; n = _n)
|
||||
|
||||
#define TADD_TAIL(t, list, node) do { \
|
||||
TNODE(t) *p = list.tail; \
|
||||
node.prev = p; \
|
||||
node.next = &(list.tail_node); \
|
||||
p->next = &(node); \
|
||||
list.tail = &(node); \
|
||||
} while (0)
|
||||
|
||||
#define TREM_NODE(t, node) do { \
|
||||
TNODE(t) *p = node.prev, *n = node.next; \
|
||||
node.prev = node.next = NULL; \
|
||||
p->next = n; \
|
||||
n->prev = p; \
|
||||
} while (0)
|
||||
|
||||
#endif
|
@ -1,4 +1,4 @@
|
||||
src := a-path.c a-set.c cli.c cmds.c iface.c locks.c neighbor.c notify.c password.c proto.c rt-attr.c rt-dev.c rt-fib.c rt-show.c rt-table.c
|
||||
src := a-path.c a-set.c cli.c cmds.c iface.c locks.c neighbor.c password.c proto.c rt-attr.c rt-dev.c rt-fib.c rt-show.c rt-table.c
|
||||
obj := $(src-o-files)
|
||||
$(all-daemon)
|
||||
$(cf-local)
|
||||
|
@ -1,30 +0,0 @@
|
||||
/*
|
||||
* BIRD Internet Routing Daemon -- Notificators and Listeners
|
||||
*
|
||||
* (c) 2019 Maria Matejka <mq@jmq.cz>
|
||||
*
|
||||
* Can be freely distributed and used under the terms of the GNU GPL.
|
||||
*/
|
||||
|
||||
#include "nest/bird.h"
|
||||
#include "lib/resource.h"
|
||||
#include "nest/notify.h"
|
||||
|
||||
LISTENER_DECL(void);
|
||||
|
||||
static void
|
||||
listener_unsubscribe(resource *r)
|
||||
{
|
||||
LISTENER(void) *L = (LISTENER(void) *) r;
|
||||
rem_node(&(L->n));
|
||||
CALL(L->unsubscribe, L->self);
|
||||
}
|
||||
|
||||
struct resclass listener_class = {
|
||||
.name = "Listener",
|
||||
.size = sizeof(LISTENER(void)),
|
||||
.free = listener_unsubscribe,
|
||||
.dump = NULL,
|
||||
.lookup = NULL,
|
||||
.memsize = NULL,
|
||||
};
|
@ -10,25 +10,43 @@
|
||||
#define _BIRD_NOTIFY_H_
|
||||
|
||||
#include "lib/resource.h"
|
||||
#include "lib/lists.h"
|
||||
#include "lib/tlists.h"
|
||||
|
||||
#define LISTENER(stype) struct listener__##stype
|
||||
#define LISTENER_DECL(stype) LISTENER(stype) { \
|
||||
#define LISTENER_DEF(stype) \
|
||||
TLIST_DEF(listener__##stype); \
|
||||
LISTENER(stype) { \
|
||||
resource r; \
|
||||
node n; \
|
||||
TNODE(listener__##stype) n; \
|
||||
void *self; \
|
||||
void (*unsubscribe)(void *self); \
|
||||
void (*notify)(void *self, const stype *data); \
|
||||
};
|
||||
}; \
|
||||
extern struct resclass LISTENER_CLASS(stype)
|
||||
|
||||
extern struct resclass listener_class;
|
||||
#define LISTENERS(stype) TLIST(listener__##stype)
|
||||
|
||||
#define LISTENER_CLASS(stype) listener_class__##stype
|
||||
#define LISTENER_CLASS_DEF(stype) static void listener_unsubscribe__##stype(resource *r) { \
|
||||
LISTENER(stype) *L = (LISTENER(stype) *) r; \
|
||||
TREM_NODE(listener__##stype, L->n); \
|
||||
CALL(L->unsubscribe, L->self); \
|
||||
} \
|
||||
struct resclass LISTENER_CLASS(stype) = { \
|
||||
.name = "Listener " #stype, \
|
||||
.size = sizeof(LISTENER(stype)), \
|
||||
.free = listener_unsubscribe__##stype, \
|
||||
}
|
||||
|
||||
#define INIT_LISTENERS(stype, sender) INIT_TLIST(listener__##stype, sender)
|
||||
|
||||
#define SUBSCRIBE(stype, pool, sender, _self, _notify, _unsubscribe) ({ \
|
||||
LISTENER(stype) *L = ralloc(pool, &listener_class); \
|
||||
LISTENER(stype) *L = ralloc(pool, &listener_class__##stype); \
|
||||
L->notify = _notify; \
|
||||
L->unsubscribe = _unsubscribe; \
|
||||
L->self = _self; \
|
||||
add_tail(&(sender), &(L->n)); \
|
||||
L->n.self = L; \
|
||||
TADD_TAIL(listener__##stype, sender, L->n); \
|
||||
L; \
|
||||
})
|
||||
|
||||
@ -39,18 +57,14 @@ extern struct resclass listener_class;
|
||||
} while (0)
|
||||
|
||||
#define UNNOTIFY(stype, sender) do { \
|
||||
LISTENER(stype) *L; \
|
||||
node *x, *y; \
|
||||
WALK_LIST2_DELSAFE(L, x, y, sender, n) \
|
||||
rfree(L); \
|
||||
WALK_TLIST_DELSAFE(listener__##stype, L, sender) \
|
||||
rfree(L->self); \
|
||||
} while (0)
|
||||
|
||||
#define NOTIFY(stype, sender, data) do { \
|
||||
const stype *_d = data; \
|
||||
LISTENER(stype) *L; \
|
||||
node *x, *y; \
|
||||
WALK_LIST2_DELSAFE(L, x, y, sender, n) \
|
||||
L->notify(L->self, _d); \
|
||||
WALK_TLIST_DELSAFE(listener__##stype, L, sender) \
|
||||
L->self->notify(L->self->self, _d); \
|
||||
} while (0)
|
||||
|
||||
#endif
|
||||
|
@ -146,12 +146,15 @@ struct rtable_config {
|
||||
byte sorted; /* Routes of network are sorted according to rte_better() */
|
||||
};
|
||||
|
||||
typedef struct rt_notify rt_notify_data;
|
||||
LISTENER_DEF(rt_notify_data);
|
||||
|
||||
typedef struct rtable {
|
||||
node n; /* Node in list of all tables */
|
||||
struct fib fib;
|
||||
char *name; /* Name of this table */
|
||||
list channels; /* List of attached channels (struct channel) */
|
||||
list listeners; /* List of attached listeners (struct listener) */
|
||||
LISTENERS(rt_notify_data) listeners; /* List of attached listeners */
|
||||
uint addr_type; /* Type of address data stored in table (NET_*) */
|
||||
int pipe_busy; /* Pipe loop detection */
|
||||
int use_count; /* Number of protocols using this table */
|
||||
@ -327,8 +330,6 @@ typedef struct rt_notify {
|
||||
rte *new, *old, *new_best, *old_best, *before_old;
|
||||
} rt_notify_data;
|
||||
|
||||
LISTENER_DECL(rt_notify_data);
|
||||
|
||||
/* Default limit for ECMP next hops, defined in sysdep code */
|
||||
extern const int rt_default_ecmp;
|
||||
|
||||
|
@ -864,6 +864,7 @@ rt_notify_merged(struct channel *c, net *net, rte *new_changed, rte *old_changed
|
||||
rte_free(old_changed_free);
|
||||
}
|
||||
|
||||
LISTENER_CLASS_DEF(rt_notify_data);
|
||||
|
||||
/**
|
||||
* rte_announce - announce a routing table change
|
||||
@ -1738,7 +1739,7 @@ rt_setup(pool *p, rtable *t, struct rtable_config *cf)
|
||||
t->addr_type = cf->addr_type;
|
||||
fib_init(&t->fib, p, t->addr_type, sizeof(net), OFFSETOF(net, n), 0, NULL);
|
||||
init_list(&t->channels);
|
||||
init_list(&t->listeners);
|
||||
INIT_LISTENERS(rt_notify_data, t->listeners);
|
||||
|
||||
t->rt_event = ev_new_init(p, rt_event, t);
|
||||
t->gc_time = current_time();
|
||||
|
Loading…
Reference in New Issue
Block a user