0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2024-12-23 18:21:54 +00:00

Notify: Also the listener list is typed.

This commit is contained in:
Maria Matejka 2019-03-11 23:23:21 +01:00
parent bb623f0ae3
commit 9d27e7c98b
6 changed files with 97 additions and 50 deletions

61
lib/tlists.h Normal file
View 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

View File

@ -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) obj := $(src-o-files)
$(all-daemon) $(all-daemon)
$(cf-local) $(cf-local)

View File

@ -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,
};

View File

@ -10,25 +10,43 @@
#define _BIRD_NOTIFY_H_ #define _BIRD_NOTIFY_H_
#include "lib/resource.h" #include "lib/resource.h"
#include "lib/lists.h" #include "lib/tlists.h"
#define LISTENER(stype) struct listener__##stype #define LISTENER(stype) struct listener__##stype
#define LISTENER_DECL(stype) LISTENER(stype) { \ #define LISTENER_DEF(stype) \
TLIST_DEF(listener__##stype); \
LISTENER(stype) { \
resource r; \ resource r; \
node n; \ TNODE(listener__##stype) n; \
void *self; \ void *self; \
void (*unsubscribe)(void *self); \ void (*unsubscribe)(void *self); \
void (*notify)(void *self, const stype *data); \ 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) ({ \ #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->notify = _notify; \
L->unsubscribe = _unsubscribe; \ L->unsubscribe = _unsubscribe; \
L->self = _self; \ L->self = _self; \
add_tail(&(sender), &(L->n)); \ L->n.self = L; \
TADD_TAIL(listener__##stype, sender, L->n); \
L; \ L; \
}) })
@ -39,18 +57,14 @@ extern struct resclass listener_class;
} while (0) } while (0)
#define UNNOTIFY(stype, sender) do { \ #define UNNOTIFY(stype, sender) do { \
LISTENER(stype) *L; \ WALK_TLIST_DELSAFE(listener__##stype, L, sender) \
node *x, *y; \ rfree(L->self); \
WALK_LIST2_DELSAFE(L, x, y, sender, n) \
rfree(L); \
} while (0) } while (0)
#define NOTIFY(stype, sender, data) do { \ #define NOTIFY(stype, sender, data) do { \
const stype *_d = data; \ const stype *_d = data; \
LISTENER(stype) *L; \ WALK_TLIST_DELSAFE(listener__##stype, L, sender) \
node *x, *y; \ L->self->notify(L->self->self, _d); \
WALK_LIST2_DELSAFE(L, x, y, sender, n) \
L->notify(L->self, _d); \
} while (0) } while (0)
#endif #endif

View File

@ -146,12 +146,15 @@ struct rtable_config {
byte sorted; /* Routes of network are sorted according to rte_better() */ 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 { typedef struct rtable {
node n; /* Node in list of all tables */ node n; /* Node in list of all tables */
struct fib fib; struct fib fib;
char *name; /* Name of this table */ char *name; /* Name of this table */
list channels; /* List of attached channels (struct channel) */ 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_*) */ uint addr_type; /* Type of address data stored in table (NET_*) */
int pipe_busy; /* Pipe loop detection */ int pipe_busy; /* Pipe loop detection */
int use_count; /* Number of protocols using this table */ 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; rte *new, *old, *new_best, *old_best, *before_old;
} rt_notify_data; } rt_notify_data;
LISTENER_DECL(rt_notify_data);
/* Default limit for ECMP next hops, defined in sysdep code */ /* Default limit for ECMP next hops, defined in sysdep code */
extern const int rt_default_ecmp; extern const int rt_default_ecmp;

View File

@ -864,6 +864,7 @@ rt_notify_merged(struct channel *c, net *net, rte *new_changed, rte *old_changed
rte_free(old_changed_free); rte_free(old_changed_free);
} }
LISTENER_CLASS_DEF(rt_notify_data);
/** /**
* rte_announce - announce a routing table change * 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; t->addr_type = cf->addr_type;
fib_init(&t->fib, p, t->addr_type, sizeof(net), OFFSETOF(net, n), 0, NULL); fib_init(&t->fib, p, t->addr_type, sizeof(net), OFFSETOF(net, n), 0, NULL);
init_list(&t->channels); 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->rt_event = ev_new_init(p, rt_event, t);
t->gc_time = current_time(); t->gc_time = current_time();