0
0
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:
Maria Matejka 2022-09-07 13:54:20 +02:00
parent a42877b9bf
commit fb7fb67445
16 changed files with 607 additions and 355 deletions

View File

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

View File

@ -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)

View File

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

View File

@ -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 {

View File

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

View File

@ -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);

View File

@ -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)
{ {

File diff suppressed because it is too large Load Diff

View File

@ -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);

View File

@ -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)

View File

@ -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);

View File

@ -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);

View File

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

View File

@ -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 */

View File

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

View File

@ -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