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:
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)
|
obj := $(src-o-files)
|
||||||
$(all-daemon)
|
$(all-daemon)
|
||||||
$(cf-local)
|
$(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_
|
#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
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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();
|
||||||
|
Loading…
Reference in New Issue
Block a user