mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-11-18 17:18:42 +00:00
Table access is now locked.
This commit is contained in:
parent
a42877b9bf
commit
fb7fb67445
@ -1467,7 +1467,7 @@
|
|||||||
ARG(1, T_NET);
|
ARG(1, T_NET);
|
||||||
ARG(2, T_INT);
|
ARG(2, T_INT);
|
||||||
RTC(3);
|
RTC(3);
|
||||||
struct rtable *table = rtc->table;
|
rtable *table = rtc->table;
|
||||||
|
|
||||||
u32 as = v2.val.i;
|
u32 as = v2.val.i;
|
||||||
|
|
||||||
|
@ -14,8 +14,9 @@
|
|||||||
|
|
||||||
/* Ugly structure offset handling macros */
|
/* Ugly structure offset handling macros */
|
||||||
|
|
||||||
|
#define SAME_TYPE(a, b) ({ int _ = ((a) != (b)); !_; })
|
||||||
#define OFFSETOF(s, i) ((size_t) &((s *)0)->i)
|
#define OFFSETOF(s, i) ((size_t) &((s *)0)->i)
|
||||||
#define SKIP_BACK(s, i, p) ({ s *_ptr = ((s *)((char *)p - OFFSETOF(s, i))); ASSERT_DIE(&_ptr->i == p); _ptr; })
|
#define SKIP_BACK(s, i, p) ({ s *_ptr = ((s *)((char *)p - OFFSETOF(s, i))); SAME_TYPE(&_ptr->i, p); _ptr; })
|
||||||
#define BIRD_ALIGN(s, a) (((s)+a-1)&~(a-1))
|
#define BIRD_ALIGN(s, a) (((s)+a-1)&~(a-1))
|
||||||
#define CPU_STRUCT_ALIGN (MAX_(_Alignof(void*), _Alignof(u64)))
|
#define CPU_STRUCT_ALIGN (MAX_(_Alignof(void*), _Alignof(u64)))
|
||||||
#define BIRD_CPU_ALIGN(s) BIRD_ALIGN((s), CPU_STRUCT_ALIGN)
|
#define BIRD_CPU_ALIGN(s) BIRD_ALIGN((s), CPU_STRUCT_ALIGN)
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
struct network;
|
struct network;
|
||||||
struct proto;
|
struct proto;
|
||||||
struct cli;
|
struct cli;
|
||||||
struct rtable;
|
struct rtable_private;
|
||||||
|
|
||||||
typedef struct rte {
|
typedef struct rte {
|
||||||
struct ea_list *attrs; /* Attributes of this route */
|
struct ea_list *attrs; /* Attributes of this route */
|
||||||
@ -63,7 +63,7 @@ struct rte_owner_class {
|
|||||||
|
|
||||||
struct rte_owner {
|
struct rte_owner {
|
||||||
struct rte_owner_class *class;
|
struct rte_owner_class *class;
|
||||||
int (*rte_recalculate)(struct rtable *, struct network *, struct rte *, struct rte *, struct rte *);
|
int (*rte_recalculate)(struct rtable_private *, struct network *, struct rte *, struct rte *, struct rte *);
|
||||||
HASH(struct rte_src) hash;
|
HASH(struct rte_src) hash;
|
||||||
const char *name;
|
const char *name;
|
||||||
u32 hash_key;
|
u32 hash_key;
|
||||||
|
@ -702,7 +702,8 @@ r_args:
|
|||||||
}
|
}
|
||||||
| r_args IMPORT TABLE channel_arg {
|
| r_args IMPORT TABLE channel_arg {
|
||||||
if (!($4->in_keep & RIK_PREFILTER)) cf_error("No import table in channel %s.%s", $4->proto->name, $4->name);
|
if (!($4->in_keep & RIK_PREFILTER)) cf_error("No import table in channel %s.%s", $4->proto->name, $4->name);
|
||||||
rt_show_add_exporter($$, &$4->table->exporter.e, "import")->prefilter = $4;
|
RT_LOCKED($4->table, tab)
|
||||||
|
rt_show_add_exporter($$, &tab->exporter.e, "import")->prefilter = $4;
|
||||||
$$->tables_defined_by = RSD_TDB_DIRECT;
|
$$->tables_defined_by = RSD_TDB_DIRECT;
|
||||||
}
|
}
|
||||||
| r_args EXPORT TABLE channel_arg {
|
| r_args EXPORT TABLE channel_arg {
|
||||||
|
11
nest/proto.c
11
nest/proto.c
@ -169,7 +169,7 @@ proto_cf_find_channel(struct proto_config *pc, uint net_type)
|
|||||||
* Returns pointer to channel or NULL
|
* Returns pointer to channel or NULL
|
||||||
*/
|
*/
|
||||||
struct channel *
|
struct channel *
|
||||||
proto_find_channel_by_table(struct proto *p, struct rtable *t)
|
proto_find_channel_by_table(struct proto *p, rtable *t)
|
||||||
{
|
{
|
||||||
struct channel *c;
|
struct channel *c;
|
||||||
|
|
||||||
@ -376,7 +376,7 @@ channel_dump_roa_req(struct rt_export_request *req)
|
|||||||
{
|
{
|
||||||
struct roa_subscription *s = SKIP_BACK(struct roa_subscription, req, req);
|
struct roa_subscription *s = SKIP_BACK(struct roa_subscription, req, req);
|
||||||
struct channel *c = s->c;
|
struct channel *c = s->c;
|
||||||
rtable *tab = SKIP_BACK(rtable, exporter.e, req->hook->table);
|
struct rtable_private *tab = SKIP_BACK(struct rtable_private, exporter.e, req->hook->table);
|
||||||
|
|
||||||
debug(" Channel %s.%s ROA %s change notifier from table %s request %p\n",
|
debug(" Channel %s.%s ROA %s change notifier from table %s request %p\n",
|
||||||
c->proto->name, c->name,
|
c->proto->name, c->name,
|
||||||
@ -394,7 +394,8 @@ channel_roa_is_subscribed(struct channel *c, rtable *tab, int dir)
|
|||||||
node *n;
|
node *n;
|
||||||
|
|
||||||
WALK_LIST2(s, n, c->roa_subscriptions, roa_node)
|
WALK_LIST2(s, n, c->roa_subscriptions, roa_node)
|
||||||
if ((s->req.hook->table == &tab->exporter.e) && (s->t.hook == hook))
|
if ((tab == SKIP_BACK(rtable, priv.exporter.e, s->req.hook->table))
|
||||||
|
&& (s->t.hook == hook))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -447,7 +448,7 @@ static void
|
|||||||
channel_roa_subscribe_filter(struct channel *c, int dir)
|
channel_roa_subscribe_filter(struct channel *c, int dir)
|
||||||
{
|
{
|
||||||
const struct filter *f = dir ? c->in_filter : c->out_filter;
|
const struct filter *f = dir ? c->in_filter : c->out_filter;
|
||||||
struct rtable *tab;
|
rtable *tab;
|
||||||
int valid = 1, found = 0;
|
int valid = 1, found = 0;
|
||||||
|
|
||||||
if ((f == FILTER_ACCEPT) || (f == FILTER_REJECT))
|
if ((f == FILTER_ACCEPT) || (f == FILTER_REJECT))
|
||||||
@ -609,8 +610,6 @@ channel_import_stopped(struct rt_import_request *req)
|
|||||||
{
|
{
|
||||||
struct channel *c = SKIP_BACK(struct channel, in_req, req);
|
struct channel *c = SKIP_BACK(struct channel, in_req, req);
|
||||||
|
|
||||||
req->hook = NULL;
|
|
||||||
|
|
||||||
mb_free(c->in_req.name);
|
mb_free(c->in_req.name);
|
||||||
c->in_req.name = NULL;
|
c->in_req.name = NULL;
|
||||||
|
|
||||||
|
@ -18,7 +18,6 @@
|
|||||||
|
|
||||||
struct iface;
|
struct iface;
|
||||||
struct ifa;
|
struct ifa;
|
||||||
struct rtable;
|
|
||||||
struct rte;
|
struct rte;
|
||||||
struct neighbor;
|
struct neighbor;
|
||||||
struct rta;
|
struct rta;
|
||||||
@ -189,7 +188,7 @@ struct proto {
|
|||||||
* rte_remove Called whenever a rte is removed from the routing table.
|
* rte_remove Called whenever a rte is removed from the routing table.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int (*rte_recalculate)(struct rtable *, struct network *, struct rte *, struct rte *, struct rte *);
|
int (*rte_recalculate)(struct rtable_private *, struct network *, struct rte *, struct rte *, struct rte *);
|
||||||
int (*rte_better)(struct rte *, struct rte *);
|
int (*rte_better)(struct rte *, struct rte *);
|
||||||
int (*rte_mergable)(struct rte *, struct rte *);
|
int (*rte_mergable)(struct rte *, struct rte *);
|
||||||
void (*rte_insert)(struct network *, struct rte *);
|
void (*rte_insert)(struct network *, struct rte *);
|
||||||
@ -482,7 +481,7 @@ struct channel {
|
|||||||
const struct channel_class *channel;
|
const struct channel_class *channel;
|
||||||
struct proto *proto;
|
struct proto *proto;
|
||||||
|
|
||||||
struct rtable *table;
|
rtable *table;
|
||||||
const struct filter *in_filter; /* Input filter */
|
const struct filter *in_filter; /* Input filter */
|
||||||
const struct filter *out_filter; /* Output filter */
|
const struct filter *out_filter; /* Output filter */
|
||||||
const net_addr *out_subprefix; /* Export only subprefixes of this net */
|
const net_addr *out_subprefix; /* Export only subprefixes of this net */
|
||||||
@ -613,7 +612,7 @@ struct channel_config *proto_cf_find_channel(struct proto_config *p, uint net_ty
|
|||||||
static inline struct channel_config *proto_cf_main_channel(struct proto_config *pc)
|
static inline struct channel_config *proto_cf_main_channel(struct proto_config *pc)
|
||||||
{ return proto_cf_find_channel(pc, pc->net_type); }
|
{ return proto_cf_find_channel(pc, pc->net_type); }
|
||||||
|
|
||||||
struct channel *proto_find_channel_by_table(struct proto *p, struct rtable *t);
|
struct channel *proto_find_channel_by_table(struct proto *p, rtable *t);
|
||||||
struct channel *proto_find_channel_by_name(struct proto *p, const char *n);
|
struct channel *proto_find_channel_by_name(struct proto *p, const char *n);
|
||||||
struct channel *proto_add_channel(struct proto *p, struct channel_config *cf);
|
struct channel *proto_add_channel(struct proto *p, struct channel_config *cf);
|
||||||
int proto_configure_channel(struct proto *p, struct channel **c, struct channel_config *cf);
|
int proto_configure_channel(struct proto *p, struct channel **c, struct channel_config *cf);
|
||||||
|
@ -354,9 +354,11 @@ rt_show_add_exporter(struct rt_show_data *d, struct rt_exporter *t, const char *
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct rt_show_data_rtable *
|
struct rt_show_data_rtable *
|
||||||
rt_show_add_table(struct rt_show_data *d, struct rtable *t)
|
rt_show_add_table(struct rt_show_data *d, rtable *t)
|
||||||
{
|
{
|
||||||
struct rt_show_data_rtable *rsdr = rt_show_add_exporter(d, &t->exporter.e, t->name);
|
struct rt_show_data_rtable *rsdr;
|
||||||
|
RT_LOCKED(t, tp)
|
||||||
|
rsdr = rt_show_add_exporter(d, &tp->exporter.e, t->name);
|
||||||
|
|
||||||
struct proto_config *krt = t->config->krt_attached;
|
struct proto_config *krt = t->config->krt_attached;
|
||||||
if (krt)
|
if (krt)
|
||||||
@ -418,12 +420,13 @@ rt_show_prepare_tables(struct rt_show_data *d)
|
|||||||
/* Ensure there is defined export_channel for each table */
|
/* Ensure there is defined export_channel for each table */
|
||||||
if (d->export_mode)
|
if (d->export_mode)
|
||||||
{
|
{
|
||||||
|
rtable *rt = SKIP_BACK(rtable, priv.exporter.e, tab->table);
|
||||||
if (!tab->export_channel && d->export_channel &&
|
if (!tab->export_channel && d->export_channel &&
|
||||||
(tab->table == &d->export_channel->table->exporter.e))
|
(rt == d->export_channel->table))
|
||||||
tab->export_channel = d->export_channel;
|
tab->export_channel = d->export_channel;
|
||||||
|
|
||||||
if (!tab->export_channel && d->export_protocol)
|
if (!tab->export_channel && d->export_protocol)
|
||||||
tab->export_channel = proto_find_channel_by_table(d->export_protocol, SKIP_BACK(rtable, exporter.e, tab->table));
|
tab->export_channel = proto_find_channel_by_table(d->export_protocol, rt);
|
||||||
|
|
||||||
if (!tab->export_channel)
|
if (!tab->export_channel)
|
||||||
{
|
{
|
||||||
|
746
nest/rt-table.c
746
nest/rt-table.c
File diff suppressed because it is too large
Load Diff
87
nest/rt.h
87
nest/rt.h
@ -53,7 +53,7 @@ struct rt_cork_threshold {
|
|||||||
struct rtable_config {
|
struct rtable_config {
|
||||||
node n;
|
node n;
|
||||||
char *name;
|
char *name;
|
||||||
struct rtable *table;
|
union rtable *table;
|
||||||
struct proto_config *krt_attached; /* Kernel syncer attached to this table */
|
struct proto_config *krt_attached; /* Kernel syncer attached to this table */
|
||||||
uint addr_type; /* Type of address data stored in table (NET_*) */
|
uint addr_type; /* Type of address data stored in table (NET_*) */
|
||||||
uint gc_threshold; /* Maximum number of operations before GC is run */
|
uint gc_threshold; /* Maximum number of operations before GC is run */
|
||||||
@ -93,16 +93,28 @@ struct rt_table_exporter {
|
|||||||
|
|
||||||
extern uint rtable_max_id;
|
extern uint rtable_max_id;
|
||||||
|
|
||||||
typedef struct rtable {
|
DEFINE_DOMAIN(rtable);
|
||||||
resource r;
|
|
||||||
node n; /* Node in list of all tables */
|
/* The public part of rtable structure */
|
||||||
|
#define RTABLE_PUBLIC \
|
||||||
|
resource r; \
|
||||||
|
node n; /* Node in list of all tables */ \
|
||||||
|
char *name; /* Name of this table */ \
|
||||||
|
uint addr_type; /* Type of address data stored in table (NET_*) */ \
|
||||||
|
uint id; /* Integer table ID for fast lookup */ \
|
||||||
|
DOMAIN(rtable) lock; /* Lock to take to access the private parts */ \
|
||||||
|
struct rtable_config *config; /* Configuration of this table */ \
|
||||||
|
|
||||||
|
/* The complete rtable structure */
|
||||||
|
struct rtable_private {
|
||||||
|
/* Once more the public part */
|
||||||
|
RTABLE_PUBLIC;
|
||||||
|
|
||||||
|
/* Here the private items not to be accessed without locking */
|
||||||
pool *rp; /* Resource pool to allocate everything from, including itself */
|
pool *rp; /* Resource pool to allocate everything from, including itself */
|
||||||
struct slab *rte_slab; /* Slab to allocate route objects */
|
struct slab *rte_slab; /* Slab to allocate route objects */
|
||||||
struct fib fib;
|
struct fib fib;
|
||||||
struct f_trie *trie; /* Trie of prefixes defined in fib */
|
struct f_trie *trie; /* Trie of prefixes defined in fib */
|
||||||
char *name; /* Name of this table */
|
|
||||||
uint addr_type; /* Type of address data stored in table (NET_*) */
|
|
||||||
uint id; /* Integer table ID for fast lookup */
|
|
||||||
int use_count; /* Number of protocols using this table */
|
int use_count; /* Number of protocols using this table */
|
||||||
u32 rt_count; /* Number of routes in the table */
|
u32 rt_count; /* Number of routes in the table */
|
||||||
|
|
||||||
@ -111,7 +123,6 @@ typedef struct rtable {
|
|||||||
|
|
||||||
struct hmap id_map;
|
struct hmap id_map;
|
||||||
struct hostcache *hostcache;
|
struct hostcache *hostcache;
|
||||||
struct rtable_config *config; /* Configuration of this table */
|
|
||||||
struct config *deleted; /* Table doesn't exist in current configuration,
|
struct config *deleted; /* Table doesn't exist in current configuration,
|
||||||
* delete as soon as use_count becomes 0 and remove
|
* delete as soon as use_count becomes 0 and remove
|
||||||
* obstacle from this routing table.
|
* obstacle from this routing table.
|
||||||
@ -138,8 +149,28 @@ typedef struct rtable {
|
|||||||
struct tbf rl_pipe; /* Rate limiting token buffer for pipe collisions */
|
struct tbf rl_pipe; /* Rate limiting token buffer for pipe collisions */
|
||||||
|
|
||||||
struct f_trie *flowspec_trie; /* Trie for evaluation of flowspec notifications */
|
struct f_trie *flowspec_trie; /* Trie for evaluation of flowspec notifications */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* The final union private-public rtable structure */
|
||||||
|
typedef union rtable {
|
||||||
|
struct {
|
||||||
|
RTABLE_PUBLIC;
|
||||||
|
};
|
||||||
|
struct rtable_private priv;
|
||||||
} rtable;
|
} rtable;
|
||||||
|
|
||||||
|
#define RT_IS_LOCKED(tab) DOMAIN_IS_LOCKED(rtable, (tab)->lock)
|
||||||
|
|
||||||
|
#define RT_LOCK(tab) ({ LOCK_DOMAIN(rtable, (tab)->lock); &(tab)->priv; })
|
||||||
|
#define RT_UNLOCK(tab) UNLOCK_DOMAIN(rtable, (tab)->lock)
|
||||||
|
#define RT_PRIV(tab) ({ ASSERT_DIE(RT_IS_LOCKED((tab))); &(tab)->priv; })
|
||||||
|
#define RT_PUB(tab) SKIP_BACK(rtable, priv, tab)
|
||||||
|
|
||||||
|
#define RT_LOCKED(tpub, tpriv) for (struct rtable_private *tpriv = RT_LOCK(tpub); tpriv; RT_UNLOCK(tpriv), (tpriv = NULL))
|
||||||
|
#define RT_RETURN(tpriv, ...) do { RT_UNLOCK(tpriv); return __VA_ARGS__; } while (0)
|
||||||
|
|
||||||
|
#define RT_PRIV_SAME(tpriv, tpub) (&(tpub)->priv == (tpriv))
|
||||||
|
|
||||||
extern struct rt_cork {
|
extern struct rt_cork {
|
||||||
_Atomic uint active;
|
_Atomic uint active;
|
||||||
event_list queue;
|
event_list queue;
|
||||||
@ -386,7 +417,7 @@ int rpe_get_seen(struct rt_export_hook *hook, struct rt_pending_export *rpe);
|
|||||||
|
|
||||||
void rt_init_export(struct rt_exporter *re, struct rt_export_hook *hook);
|
void rt_init_export(struct rt_exporter *re, struct rt_export_hook *hook);
|
||||||
struct rt_export_hook *rt_alloc_export(struct rt_exporter *re, uint size);
|
struct rt_export_hook *rt_alloc_export(struct rt_exporter *re, uint size);
|
||||||
void rt_export_stopped(void *data);
|
void rt_export_stopped(struct rt_export_hook *hook);
|
||||||
void rt_exporter_init(struct rt_exporter *re);
|
void rt_exporter_init(struct rt_exporter *re);
|
||||||
|
|
||||||
/* Types of route announcement, also used as flags */
|
/* Types of route announcement, also used as flags */
|
||||||
@ -416,7 +447,7 @@ struct hostentry {
|
|||||||
ip_addr addr; /* IP address of host, part of key */
|
ip_addr addr; /* IP address of host, part of key */
|
||||||
ip_addr link; /* (link-local) IP address of host, used as gw
|
ip_addr link; /* (link-local) IP address of host, used as gw
|
||||||
if host is directly attached */
|
if host is directly attached */
|
||||||
struct rtable *tab; /* Dependent table, part of key */
|
rtable *tab; /* Dependent table, part of key */
|
||||||
struct hostentry *next; /* Next in hash chain */
|
struct hostentry *next; /* Next in hash chain */
|
||||||
unsigned hash_key; /* Hash key */
|
unsigned hash_key; /* Hash key */
|
||||||
unsigned uc; /* Use count */
|
unsigned uc; /* Use count */
|
||||||
@ -487,34 +518,36 @@ void rt_init(void);
|
|||||||
void rt_preconfig(struct config *);
|
void rt_preconfig(struct config *);
|
||||||
void rt_postconfig(struct config *);
|
void rt_postconfig(struct config *);
|
||||||
void rt_commit(struct config *new, struct config *old);
|
void rt_commit(struct config *new, struct config *old);
|
||||||
|
void rt_lock_table_priv(struct rtable_private *, const char *file, uint line);
|
||||||
|
void rt_unlock_table_priv(struct rtable_private *, const char *file, uint line);
|
||||||
|
static inline void rt_lock_table_pub(rtable *t, const char *file, uint line)
|
||||||
|
{ RT_LOCKED(t, tt) rt_lock_table_priv(tt, file, line); }
|
||||||
|
static inline void rt_unlock_table_pub(rtable *t, const char *file, uint line)
|
||||||
|
{ RT_LOCKED(t, tt) rt_unlock_table_priv(tt, file, line); }
|
||||||
|
|
||||||
void rt_lock_table_debug(rtable *, const char *file, uint line);
|
#define rt_lock_table(t) _Generic((t), rtable *: rt_lock_table_pub, \
|
||||||
void rt_unlock_table_debug(rtable *, const char *file, uint line);
|
struct rtable_private *: rt_lock_table_priv)((t), __FILE__, __LINE__)
|
||||||
#define rt_lock_table(tab) rt_lock_table_debug(tab, __FILE__, __LINE__)
|
#define rt_unlock_table(t) _Generic((t), rtable *: rt_unlock_table_pub, \
|
||||||
#define rt_unlock_table(tab) rt_unlock_table_debug(tab, __FILE__, __LINE__)
|
struct rtable_private *: rt_unlock_table_priv)((t), __FILE__, __LINE__)
|
||||||
|
|
||||||
struct f_trie * rt_lock_trie(rtable *tab);
|
struct f_trie * rt_lock_trie(struct rtable_private *tab);
|
||||||
void rt_unlock_trie(rtable *tab, struct f_trie *trie);
|
void rt_unlock_trie(struct rtable_private *tab, struct f_trie *trie);
|
||||||
void rt_flowspec_link(rtable *src, rtable *dst);
|
void rt_flowspec_link(rtable *src, rtable *dst);
|
||||||
void rt_flowspec_unlink(rtable *src, rtable *dst);
|
void rt_flowspec_unlink(rtable *src, rtable *dst);
|
||||||
rtable *rt_setup(pool *, struct rtable_config *);
|
rtable *rt_setup(pool *, struct rtable_config *);
|
||||||
static inline void rt_shutdown(rtable *r) { rfree(r->rp); }
|
|
||||||
|
|
||||||
static inline net *net_find(rtable *tab, const net_addr *addr) { return (net *) fib_find(&tab->fib, addr); }
|
static inline net *net_find(struct rtable_private *tab, const net_addr *addr) { return (net *) fib_find(&tab->fib, addr); }
|
||||||
static inline net *net_find_valid(rtable *tab, const net_addr *addr)
|
static inline net *net_find_valid(struct rtable_private *tab, const net_addr *addr)
|
||||||
{ net *n = net_find(tab, addr); return (n && n->routes && rte_is_valid(&n->routes->rte)) ? n : NULL; }
|
{ net *n = net_find(tab, addr); return (n && n->routes && rte_is_valid(&n->routes->rte)) ? n : NULL; }
|
||||||
static inline net *net_get(rtable *tab, const net_addr *addr) { return (net *) fib_get(&tab->fib, addr); }
|
static inline net *net_get(struct rtable_private *tab, const net_addr *addr) { return (net *) fib_get(&tab->fib, addr); }
|
||||||
net *net_get(rtable *tab, const net_addr *addr);
|
net *net_route(struct rtable_private *tab, const net_addr *n);
|
||||||
net *net_route(rtable *tab, const net_addr *n);
|
|
||||||
int rt_examine(rtable *t, net_addr *a, struct channel *c, const struct filter *filter);
|
int rt_examine(rtable *t, net_addr *a, struct channel *c, const struct filter *filter);
|
||||||
rte *rt_export_merged(struct channel *c, rte ** feed, uint count, linpool *pool, int silent);
|
rte *rt_export_merged(struct channel *c, rte ** feed, uint count, linpool *pool, int silent);
|
||||||
void rt_refresh_begin(struct rt_import_request *);
|
void rt_refresh_begin(struct rt_import_request *);
|
||||||
void rt_refresh_end(struct rt_import_request *);
|
void rt_refresh_end(struct rt_import_request *);
|
||||||
void rt_modify_stale(rtable *t, struct rt_import_request *);
|
void rt_modify_stale(rtable *t, struct rt_import_request *);
|
||||||
void rt_schedule_prune(rtable *t);
|
void rt_schedule_prune(struct rtable_private *t);
|
||||||
void rte_dump(struct rte_storage *);
|
void rte_dump(struct rte_storage *);
|
||||||
void rte_free(struct rte_storage *);
|
|
||||||
struct rte_storage *rte_store(const rte *, net *net, rtable *);
|
|
||||||
void rt_dump(rtable *);
|
void rt_dump(rtable *);
|
||||||
void rt_dump_all(void);
|
void rt_dump_all(void);
|
||||||
void rt_dump_hooks(rtable *);
|
void rt_dump_hooks(rtable *);
|
||||||
@ -575,7 +608,7 @@ struct rt_show_data {
|
|||||||
|
|
||||||
void rt_show(struct rt_show_data *);
|
void rt_show(struct rt_show_data *);
|
||||||
struct rt_show_data_rtable * rt_show_add_exporter(struct rt_show_data *d, struct rt_exporter *t, const char *name);
|
struct rt_show_data_rtable * rt_show_add_exporter(struct rt_show_data *d, struct rt_exporter *t, const char *name);
|
||||||
struct rt_show_data_rtable * rt_show_add_table(struct rt_show_data *d, struct rtable *t);
|
struct rt_show_data_rtable * rt_show_add_table(struct rt_show_data *d, rtable *t);
|
||||||
|
|
||||||
/* Value of table definition mode in struct rt_show_data */
|
/* Value of table definition mode in struct rt_show_data */
|
||||||
#define RSD_TDB_DEFAULT 0 /* no table specified */
|
#define RSD_TDB_DEFAULT 0 /* no table specified */
|
||||||
@ -602,7 +635,7 @@ struct hostentry_adata {
|
|||||||
};
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
ea_set_hostentry(ea_list **to, struct rtable *dep, struct rtable *tab, ip_addr gw, ip_addr ll, u32 lnum, u32 labels[lnum]);
|
ea_set_hostentry(ea_list **to, rtable *dep, rtable *tab, ip_addr gw, ip_addr ll, u32 lnum, u32 labels[lnum]);
|
||||||
|
|
||||||
void ea_show_hostentry(const struct adata *ad, byte *buf, uint size);
|
void ea_show_hostentry(const struct adata *ad, byte *buf, uint size);
|
||||||
void ea_show_nexthop_list(struct cli *c, struct nexthop_adata *nhad);
|
void ea_show_nexthop_list(struct cli *c, struct nexthop_adata *nhad);
|
||||||
|
@ -113,7 +113,6 @@
|
|||||||
#define HASH_IP_EQ(a1,n1,a2,n2) ipa_equal(a1, a2) && n1 == n2
|
#define HASH_IP_EQ(a1,n1,a2,n2) ipa_equal(a1, a2) && n1 == n2
|
||||||
#define HASH_IP_FN(a,n) ipa_hash(a) ^ u32_hash(n)
|
#define HASH_IP_FN(a,n) ipa_hash(a) ^ u32_hash(n)
|
||||||
|
|
||||||
DEFINE_DOMAIN(rtable);
|
|
||||||
#define BFD_LOCK LOCK_DOMAIN(rtable, bfd_global.lock)
|
#define BFD_LOCK LOCK_DOMAIN(rtable, bfd_global.lock)
|
||||||
#define BFD_UNLOCK UNLOCK_DOMAIN(rtable, bfd_global.lock)
|
#define BFD_UNLOCK UNLOCK_DOMAIN(rtable, bfd_global.lock)
|
||||||
|
|
||||||
|
@ -1981,9 +1981,20 @@ bgp_out_table_export_start(struct rt_exporter *re, struct rt_export_request *req
|
|||||||
rt_init_export(re, req->hook);
|
rt_init_export(re, req->hook);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
bgp_out_table_export_done(void *data)
|
||||||
|
{
|
||||||
|
struct bgp_out_export_hook *hook = data;
|
||||||
|
struct rt_export_request *req = hook->h.req;
|
||||||
|
void (*stopped)(struct rt_export_request *) = hook->h.stopped;
|
||||||
|
|
||||||
|
rt_export_stopped(&hook->h);
|
||||||
|
CALL(stopped, req);
|
||||||
|
}
|
||||||
|
|
||||||
static const struct rt_exporter_class bgp_out_table_export_class = {
|
static const struct rt_exporter_class bgp_out_table_export_class = {
|
||||||
.start = bgp_out_table_export_start,
|
.start = bgp_out_table_export_start,
|
||||||
.done = rt_export_stopped,
|
.done = bgp_out_table_export_done,
|
||||||
};
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -2519,7 +2530,7 @@ use_deterministic_med(struct rte_storage *r)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
bgp_rte_recalculate(rtable *table, net *net, rte *new, rte *old, rte *old_best)
|
bgp_rte_recalculate(struct rtable_private *table, net *net, rte *new, rte *old, rte *old_best)
|
||||||
{
|
{
|
||||||
rte *key = new ? new : old;
|
rte *key = new ? new : old;
|
||||||
u32 lpref = rt_get_preference(key);
|
u32 lpref = rt_get_preference(key);
|
||||||
|
@ -599,7 +599,7 @@ void bgp_done_prefix(struct bgp_channel *c, struct bgp_prefix *px, struct bgp_bu
|
|||||||
|
|
||||||
int bgp_rte_better(struct rte *, struct rte *);
|
int bgp_rte_better(struct rte *, struct rte *);
|
||||||
int bgp_rte_mergable(rte *pri, rte *sec);
|
int bgp_rte_mergable(rte *pri, rte *sec);
|
||||||
int bgp_rte_recalculate(rtable *table, net *net, rte *new, rte *old, rte *old_best);
|
int bgp_rte_recalculate(struct rtable_private *table, net *net, rte *new, rte *old, rte *old_best);
|
||||||
void bgp_rte_modify_stale(struct rt_export_request *req, const net_addr *n, struct rt_pending_export *rpe UNUSED, rte **feed, uint count);
|
void bgp_rte_modify_stale(struct rt_export_request *req, const net_addr *n, struct rt_pending_export *rpe UNUSED, rte **feed, uint count);
|
||||||
u32 bgp_rte_igp_metric(const rte *);
|
u32 bgp_rte_igp_metric(const rte *);
|
||||||
void bgp_rt_notify(struct proto *P, struct channel *C, const net_addr *n, rte *new, const rte *old);
|
void bgp_rt_notify(struct proto *P, struct channel *C, const net_addr *n, rte *new, const rte *old);
|
||||||
|
@ -228,7 +228,7 @@ mrt_next_table_(rtable *tab, rtable *tab_ptr, const char *pattern)
|
|||||||
NODE_VALID(tn);
|
NODE_VALID(tn);
|
||||||
tn = tn->next)
|
tn = tn->next)
|
||||||
{
|
{
|
||||||
tab = SKIP_BACK(struct rtable, n, tn);
|
tab = SKIP_BACK(rtable, n, tn);
|
||||||
if (patmatch(pattern, tab->name) &&
|
if (patmatch(pattern, tab->name) &&
|
||||||
((tab->addr_type == NET_IP4) || (tab->addr_type == NET_IP6)))
|
((tab->addr_type == NET_IP4) || (tab->addr_type == NET_IP6)))
|
||||||
return tab;
|
return tab;
|
||||||
@ -243,13 +243,15 @@ mrt_next_table(struct mrt_table_dump_state *s)
|
|||||||
rtable *tab = mrt_next_table_(s->table, s->table_ptr, s->table_expr);
|
rtable *tab = mrt_next_table_(s->table, s->table_ptr, s->table_expr);
|
||||||
|
|
||||||
if (s->table)
|
if (s->table)
|
||||||
rt_unlock_table(s->table);
|
RT_LOCKED(s->table, tab)
|
||||||
|
rt_unlock_table(tab);
|
||||||
|
|
||||||
s->table = tab;
|
s->table = tab;
|
||||||
s->ipv4 = tab ? (tab->addr_type == NET_IP4) : 0;
|
s->ipv4 = tab ? (tab->addr_type == NET_IP4) : 0;
|
||||||
|
|
||||||
if (s->table)
|
if (s->table)
|
||||||
rt_lock_table(s->table);
|
RT_LOCKED(s->table, tab)
|
||||||
|
rt_lock_table(tab);
|
||||||
|
|
||||||
return s->table;
|
return s->table;
|
||||||
}
|
}
|
||||||
@ -573,14 +575,18 @@ mrt_table_dump_init(pool *pp)
|
|||||||
static void
|
static void
|
||||||
mrt_table_dump_free(struct mrt_table_dump_state *s)
|
mrt_table_dump_free(struct mrt_table_dump_state *s)
|
||||||
{
|
{
|
||||||
if (s->table_open)
|
|
||||||
FIB_ITERATE_UNLINK(&s->fit, &s->table->fib);
|
|
||||||
|
|
||||||
if (s->table)
|
if (s->table)
|
||||||
rt_unlock_table(s->table);
|
RT_LOCKED(s->table, tab)
|
||||||
|
{
|
||||||
|
if (s->table_open)
|
||||||
|
FIB_ITERATE_UNLINK(&s->fit, &tab->fib);
|
||||||
|
|
||||||
|
rt_unlock_table(tab);
|
||||||
|
}
|
||||||
|
|
||||||
if (s->table_ptr)
|
if (s->table_ptr)
|
||||||
rt_unlock_table(s->table_ptr);
|
RT_LOCKED(s->table_ptr, tab)
|
||||||
|
rt_unlock_table(tab);
|
||||||
|
|
||||||
config_del_obstacle(s->config);
|
config_del_obstacle(s->config);
|
||||||
|
|
||||||
@ -606,16 +612,19 @@ mrt_table_dump_step(struct mrt_table_dump_state *s)
|
|||||||
|
|
||||||
mrt_peer_table_dump(s);
|
mrt_peer_table_dump(s);
|
||||||
|
|
||||||
FIB_ITERATE_INIT(&s->fit, &s->table->fib);
|
RT_LOCKED(s->table, tab)
|
||||||
|
{
|
||||||
|
|
||||||
|
FIB_ITERATE_INIT(&s->fit, &tab->fib);
|
||||||
s->table_open = 1;
|
s->table_open = 1;
|
||||||
|
|
||||||
step:
|
step:
|
||||||
FIB_ITERATE_START(&s->table->fib, &s->fit, net, n)
|
FIB_ITERATE_START(&tab->fib, &s->fit, net, n)
|
||||||
{
|
{
|
||||||
if (s->max < 0)
|
if (s->max < 0)
|
||||||
{
|
{
|
||||||
FIB_ITERATE_PUT(&s->fit);
|
FIB_ITERATE_PUT(&s->fit);
|
||||||
return 0;
|
RT_RETURN(tab, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* With Always ADD_PATH option, we jump directly to second phase */
|
/* With Always ADD_PATH option, we jump directly to second phase */
|
||||||
@ -630,6 +639,8 @@ mrt_table_dump_step(struct mrt_table_dump_state *s)
|
|||||||
FIB_ITERATE_END;
|
FIB_ITERATE_END;
|
||||||
s->table_open = 0;
|
s->table_open = 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
mrt_close_file(s);
|
mrt_close_file(s);
|
||||||
mrt_peer_table_flush(s);
|
mrt_peer_table_flush(s);
|
||||||
}
|
}
|
||||||
@ -661,7 +672,8 @@ mrt_timer(timer *t)
|
|||||||
s->always_add_path = cf->always_add_path;
|
s->always_add_path = cf->always_add_path;
|
||||||
|
|
||||||
if (s->table_ptr)
|
if (s->table_ptr)
|
||||||
rt_lock_table(s->table_ptr);
|
RT_LOCKED(s->table_ptr, tab)
|
||||||
|
rt_lock_table(tab);
|
||||||
|
|
||||||
p->table_dump = s;
|
p->table_dump = s;
|
||||||
ev_schedule(p->event);
|
ev_schedule(p->event);
|
||||||
@ -737,7 +749,8 @@ mrt_dump_cmd(struct mrt_dump_data *d)
|
|||||||
s->filename = d->filename;
|
s->filename = d->filename;
|
||||||
|
|
||||||
if (s->table_ptr)
|
if (s->table_ptr)
|
||||||
rt_lock_table(s->table_ptr);
|
RT_LOCKED(s->table_ptr, tab)
|
||||||
|
rt_lock_table(tab);
|
||||||
|
|
||||||
this_cli->cont = mrt_dump_cont;
|
this_cli->cont = mrt_dump_cont;
|
||||||
this_cli->cleanup = mrt_dump_cleanup;
|
this_cli->cleanup = mrt_dump_cleanup;
|
||||||
|
@ -40,7 +40,7 @@ struct mrt_proto {
|
|||||||
|
|
||||||
struct mrt_dump_data {
|
struct mrt_dump_data {
|
||||||
const char *table_expr;
|
const char *table_expr;
|
||||||
struct rtable *table_ptr;
|
rtable *table_ptr;
|
||||||
const struct filter *filter;
|
const struct filter *filter;
|
||||||
const char *filename;
|
const char *filename;
|
||||||
};
|
};
|
||||||
@ -60,7 +60,7 @@ struct mrt_table_dump_state {
|
|||||||
|
|
||||||
/* Configuration information */
|
/* Configuration information */
|
||||||
const char *table_expr; /* Wildcard for table name (or NULL) */
|
const char *table_expr; /* Wildcard for table name (or NULL) */
|
||||||
struct rtable *table_ptr; /* Explicit table (or NULL) */
|
rtable *table_ptr; /* Explicit table (or NULL) */
|
||||||
const struct filter *filter; /* Optional filter */
|
const struct filter *filter; /* Optional filter */
|
||||||
const char *filename; /* Filename pattern */
|
const char *filename; /* Filename pattern */
|
||||||
int always_add_path; /* Always use *_ADDPATH message subtypes */
|
int always_add_path; /* Always use *_ADDPATH message subtypes */
|
||||||
@ -73,7 +73,7 @@ struct mrt_table_dump_state {
|
|||||||
|
|
||||||
HASH(struct mrt_peer_entry) peer_hash; /* Hash for peers to find the index */
|
HASH(struct mrt_peer_entry) peer_hash; /* Hash for peers to find the index */
|
||||||
|
|
||||||
struct rtable *table; /* Processed table, NULL initially */
|
rtable *table; /* Processed table, NULL initially */
|
||||||
struct fib_iterator fit; /* Iterator in processed table */
|
struct fib_iterator fit; /* Iterator in processed table */
|
||||||
int table_open; /* Whether iterator is linked */
|
int table_open; /* Whether iterator is linked */
|
||||||
|
|
||||||
|
@ -202,7 +202,9 @@ perf_loop(void *data)
|
|||||||
p->exp++;
|
p->exp++;
|
||||||
}
|
}
|
||||||
|
|
||||||
rt_schedule_prune(P->main_channel->table);
|
RT_LOCKED(P->main_channel->table, tab)
|
||||||
|
rt_schedule_prune(tab);
|
||||||
|
|
||||||
ev_schedule(p->loop);
|
ev_schedule(p->loop);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -366,6 +366,13 @@ rte_feed_obtain(net *n, rte **feed, uint count)
|
|||||||
static struct rte *
|
static struct rte *
|
||||||
krt_export_net(struct krt_proto *p, net *net)
|
krt_export_net(struct krt_proto *p, net *net)
|
||||||
{
|
{
|
||||||
|
/* FIXME: Here we are calling filters in table-locked context when exporting
|
||||||
|
* to kernel. Here BIRD can crash if the user requested ROA check in kernel
|
||||||
|
* export filter. It doesn't make much sense to write the filters like this,
|
||||||
|
* therefore we may keep this unfinished piece of work here for later as it
|
||||||
|
* won't really affect anybody. */
|
||||||
|
ASSERT_DIE(RT_IS_LOCKED(p->p.main_channel->table));
|
||||||
|
|
||||||
struct channel *c = p->p.main_channel;
|
struct channel *c = p->p.main_channel;
|
||||||
const struct filter *filter = c->out_filter;
|
const struct filter *filter = c->out_filter;
|
||||||
|
|
||||||
@ -446,6 +453,9 @@ krt_got_route(struct krt_proto *p, rte *e, s8 src)
|
|||||||
#endif
|
#endif
|
||||||
/* The rest is for KRT_SRC_BIRD (or KRT_SRC_UNKNOWN) */
|
/* The rest is for KRT_SRC_BIRD (or KRT_SRC_UNKNOWN) */
|
||||||
|
|
||||||
|
RT_LOCKED(p->p.main_channel->table, tab)
|
||||||
|
{
|
||||||
|
|
||||||
/* Deleting all routes if flush is requested */
|
/* Deleting all routes if flush is requested */
|
||||||
if (p->flush_routes)
|
if (p->flush_routes)
|
||||||
goto delete;
|
goto delete;
|
||||||
@ -454,7 +464,7 @@ krt_got_route(struct krt_proto *p, rte *e, s8 src)
|
|||||||
if (!p->ready)
|
if (!p->ready)
|
||||||
goto ignore;
|
goto ignore;
|
||||||
|
|
||||||
net *net = net_find(p->p.main_channel->table, e->net);
|
net *net = net_find(tab, e->net);
|
||||||
if (!net || !krt_is_installed(p, net))
|
if (!net || !krt_is_installed(p, net))
|
||||||
goto delete;
|
goto delete;
|
||||||
|
|
||||||
@ -499,7 +509,9 @@ delete:
|
|||||||
krt_replace_rte(p, e->net, NULL, e);
|
krt_replace_rte(p, e->net, NULL, e);
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
done:
|
done:;
|
||||||
|
}
|
||||||
|
|
||||||
lp_flush(krt_filter_lp);
|
lp_flush(krt_filter_lp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -512,7 +524,8 @@ krt_init_scan(struct krt_proto *p)
|
|||||||
static void
|
static void
|
||||||
krt_prune(struct krt_proto *p)
|
krt_prune(struct krt_proto *p)
|
||||||
{
|
{
|
||||||
struct rtable *t = p->p.main_channel->table;
|
RT_LOCKED(p->p.main_channel->table, t)
|
||||||
|
{
|
||||||
|
|
||||||
KRT_TRACE(p, D_EVENTS, "Pruning table %s", t->name);
|
KRT_TRACE(p, D_EVENTS, "Pruning table %s", t->name);
|
||||||
FIB_WALK(&t->fib, net, n)
|
FIB_WALK(&t->fib, net, n)
|
||||||
@ -534,6 +547,8 @@ krt_prune(struct krt_proto *p)
|
|||||||
|
|
||||||
if (p->ready)
|
if (p->ready)
|
||||||
p->initialized = 1;
|
p->initialized = 1;
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
Loading…
Reference in New Issue
Block a user