0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2024-11-09 20:58:44 +00:00

Merge commit 'f81702b7' into haugesund

This commit is contained in:
Maria Matejka 2022-03-09 15:03:48 +01:00
commit 41572e0c1b
15 changed files with 1371 additions and 825 deletions

View File

@ -425,6 +425,23 @@ filter_commit(struct config *new, struct config *old)
}
}
void channel_filter_dump(const struct filter *f)
{
if (f == FILTER_ACCEPT)
debug(" ALL");
else if (f == FILTER_REJECT)
debug(" NONE");
else if (f == FILTER_UNDEF)
debug(" UNDEF");
else if (f->sym) {
ASSERT(f->sym->filter == f);
debug(" named filter %s", f->sym->name);
} else {
debug("\n");
f_dump_line(f->root, 2);
}
}
void filters_dump_all(void)
{
struct symbol *sym;
@ -444,19 +461,10 @@ void filters_dump_all(void)
struct channel *c;
WALK_LIST(c, sym->proto->proto->channels) {
debug(" Channel %s (%s) IMPORT", c->name, net_label[c->net_type]);
if (c->in_filter == FILTER_ACCEPT)
debug(" ALL\n");
else if (c->in_filter == FILTER_REJECT)
debug(" NONE\n");
else if (c->in_filter == FILTER_UNDEF)
debug(" UNDEF\n");
else if (c->in_filter->sym) {
ASSERT(c->in_filter->sym->filter == c->in_filter);
debug(" named filter %s\n", c->in_filter->sym->name);
} else {
debug("\n");
f_dump_line(c->in_filter->root, 2);
}
channel_filter_dump(c->in_filter);
debug(" EXPORT", c->name, net_label[c->net_type]);
channel_filter_dump(c->out_filter);
debug("\n");
}
}
}

View File

@ -851,8 +851,10 @@ CF_CLI(DUMP NEIGHBORS,,, [[Dump neighbor cache]])
{ neigh_dump_all(); cli_msg(0, ""); } ;
CF_CLI(DUMP ATTRIBUTES,,, [[Dump attribute cache]])
{ rta_dump_all(); cli_msg(0, ""); } ;
CF_CLI(DUMP ROUTES,,, [[Dump routing table]])
CF_CLI(DUMP ROUTES,,, [[Dump routes]])
{ rt_dump_all(); cli_msg(0, ""); } ;
CF_CLI(DUMP TABLES,,, [[Dump table connections]])
{ rt_dump_hooks_all(); cli_msg(0, ""); } ;
CF_CLI(DUMP PROTOCOLS,,, [[Dump protocol information]])
{ protos_dump_all(); cli_msg(0, ""); } ;
CF_CLI(DUMP FILTER ALL,,, [[Dump all filters in linearized form]])

49
nest/limit.h Normal file
View File

@ -0,0 +1,49 @@
/*
* BIRD Internet Routing Daemon -- Limits
*
* (c) 1998--2000 Martin Mares <mj@ucw.cz>
* (c) 2021 Maria Matejka <mq@jmq.cz>
*
* Can be freely distributed and used under the terms of the GNU GPL.
*/
#ifndef _BIRD_LIMIT_H_
#define _BIRD_LIMIT_H_
struct limit {
u32 max;
u32 count;
int (*action)(struct limit *, void *data);
};
static inline int limit_do_action(struct limit *l, void *data)
{
return l->action ? l->action(l, data) : 1;
}
static inline int limit_push(struct limit *l, void *data)
{
if ((l->count >= l->max) && limit_do_action(l, data))
return 1;
l->count++;
return 0;
}
static inline void limit_pop(struct limit *l)
{
--l->count;
}
static inline void limit_reset(struct limit *l)
{
l->count = 0;
}
static inline void limit_update(struct limit *l, void *data, u32 max)
{
if (l->count > (l->max = max))
limit_do_action(l, data);
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -13,6 +13,7 @@
#include "lib/resource.h"
#include "lib/event.h"
#include "nest/route.h"
#include "nest/limit.h"
#include "conf/conf.h"
struct iface;
@ -76,7 +77,6 @@ struct protocol {
void (*dump)(struct proto *); /* Debugging dump */
int (*start)(struct proto *); /* Start the instance */
int (*shutdown)(struct proto *); /* Stop the instance */
void (*cleanup)(struct proto *); /* Called after shutdown when protocol became hungry/down */
void (*get_status)(struct proto *, byte *buf); /* Get instance status (for `show protocols' command) */
void (*get_route_info)(struct rte *, byte *buf); /* Get route information (for `show route' command) */
int (*get_attr)(const struct eattr *, byte *buf, int buflen); /* ASCIIfy dynamic attribute (returns GA_*) */
@ -132,33 +132,6 @@ struct proto_config {
};
/* Protocol statistics */
struct import_stats {
/* Import - from protocol to core */
u32 routes; /* Number of routes successfully imported to the (adjacent) routing table */
u32 filtered; /* Number of routes rejected in import filter but kept in the routing table */
u32 pref; /* Number of routes selected as best in the (adjacent) routing table */
u32 updates_received; /* Number of route updates received */
u32 updates_invalid; /* Number of route updates rejected as invalid */
u32 updates_filtered; /* Number of route updates rejected by filters */
u32 updates_ignored; /* Number of route updates rejected as already in route table */
u32 updates_accepted; /* Number of route updates accepted and imported */
u32 withdraws_received; /* Number of route withdraws received */
u32 withdraws_invalid; /* Number of route withdraws rejected as invalid */
u32 withdraws_ignored; /* Number of route withdraws rejected as already not in route table */
u32 withdraws_accepted; /* Number of route withdraws accepted and processed */
};
struct export_stats {
/* Export - from core to protocol */
u32 routes; /* Number of routes successfully exported to the protocol */
u32 updates_received; /* Number of route updates received */
u32 updates_rejected; /* Number of route updates rejected by protocol */
u32 updates_filtered; /* Number of route updates rejected by filters */
u32 updates_accepted; /* Number of route updates accepted and exported */
u32 withdraws_received; /* Number of route withdraws received */
u32 withdraws_accepted; /* Number of route withdraws accepted and processed */
};
struct proto {
node n; /* Node in global proto_list */
struct protocol *proto; /* Protocol */
@ -277,7 +250,7 @@ void channel_graceful_restart_unlock(struct channel *c);
#define DEFAULT_GR_WAIT 240
void channel_show_limit(struct channel_limit *l, const char *dsc);
void channel_show_limit(struct limit *l, const char *dsc, int active, int action);
void channel_show_info(struct channel *c);
void channel_cmd_debug(struct channel *c, uint mask);
@ -432,18 +405,29 @@ extern struct proto_config *cf_dev_proto;
#define PLA_RESTART 4 /* Force protocol restart */
#define PLA_DISABLE 5 /* Shutdown and disable protocol */
#define PLS_INITIAL 0 /* Initial limit state after protocol start */
#define PLS_ACTIVE 1 /* Limit was hit */
#define PLS_BLOCKED 2 /* Limit is active and blocking new routes */
struct channel_limit {
u32 limit; /* Maximum number of prefixes */
u8 action; /* Action to take (PLA_*) */
u8 state; /* State of limit (PLS_*) */
};
void channel_notify_limit(struct channel *c, struct channel_limit *l, int dir, u32 rt_count);
struct channel_limit_data {
struct channel *c;
int dir;
};
#define CLP__RX(_c) (&(_c)->rx_limit)
#define CLP__IN(_c) (&(_c)->in_limit)
#define CLP__OUT(_c) (&(_c)->out_limit)
#if 0
#define CHANNEL_LIMIT_LOG(_c, _dir, _op) log(L_TRACE "%s.%s: %s limit %s %u", (_c)->proto->name, (_c)->name, #_dir, _op, (CLP__##_dir(_c))->count)
#else
#define CHANNEL_LIMIT_LOG(_c, _dir, _op)
#endif
#define CHANNEL_LIMIT_PUSH(_c, _dir) ({ CHANNEL_LIMIT_LOG(_c, _dir, "push from"); struct channel_limit_data cld = { .c = (_c), .dir = PLD_##_dir }; limit_push(CLP__##_dir(_c), &cld); })
#define CHANNEL_LIMIT_POP(_c, _dir) ({ limit_pop(CLP__##_dir(_c)); CHANNEL_LIMIT_LOG(_c, _dir, "pop to"); })
/*
* Channels
@ -486,6 +470,7 @@ struct channel_config {
struct proto_config *parent; /* Where channel is defined (proto or template) */
struct rtable_config *table; /* Table we're attached to */
const struct filter *in_filter, *out_filter; /* Attached filters */
struct channel_limit rx_limit; /* Limit for receiving routes from protocol
(relevant when in_keep_filtered is active) */
struct channel_limit in_limit; /* Limit for importing routes from protocol */
@ -502,7 +487,6 @@ struct channel_config {
struct channel {
node n; /* Node in proto->channels */
node table_node; /* Node in table->channels */
const char *name; /* Channel name (may be NULL) */
const struct channel_class *channel;
@ -513,14 +497,36 @@ struct channel {
const struct filter *out_filter; /* Output filter */
struct bmap export_map; /* Keeps track which routes were really exported */
struct bmap export_reject_map; /* Keeps track which routes were rejected by export filter */
struct channel_limit rx_limit; /* Receive limit (for in_keep_filtered) */
struct channel_limit in_limit; /* Input limit */
struct channel_limit out_limit; /* Output limit */
struct event *feed_event; /* Event responsible for feeding */
struct fib_iterator feed_fit; /* Routing table iterator used during feeding */
struct import_stats import_stats; /* Import statistics */
struct export_stats export_stats; /* Export statistics */
struct limit rx_limit; /* Receive limit (for in_keep_filtered) */
struct limit in_limit; /* Input limit */
struct limit out_limit; /* Output limit */
u8 limit_actions[PLD_MAX]; /* Limit actions enum */
u8 limit_active; /* Flags for active limits */
struct channel_import_stats {
/* Import - from protocol to core */
u32 updates_received; /* Number of route updates received */
u32 updates_invalid; /* Number of route updates rejected as invalid */
u32 updates_filtered; /* Number of route updates rejected by filters */
u32 updates_limited_rx; /* Number of route updates exceeding the rx_limit */
u32 updates_limited_in; /* Number of route updates exceeding the in_limit */
u32 withdraws_received; /* Number of route withdraws received */
u32 withdraws_invalid; /* Number of route withdraws rejected as invalid */
} import_stats;
struct channel_export_stats {
/* Export - from core to protocol */
u32 updates_rejected; /* Number of route updates rejected by protocol */
u32 updates_filtered; /* Number of route updates rejected by filters */
u32 updates_accepted; /* Number of route updates accepted and exported */
u32 updates_limited; /* Number of route updates exceeding the out_limit */
u32 withdraws_accepted; /* Number of route withdraws accepted and processed */
} export_stats;
struct rt_import_request in_req; /* Table import connection */
struct rt_export_request out_req; /* Table export connection */
u32 refeed_count; /* Number of routes exported during refeed regardless of out_limit */
@ -534,10 +540,7 @@ struct channel {
u8 stale; /* Used in reconfiguration */
u8 channel_state;
u8 export_state; /* Route export state (ES_*, see below) */
u8 feed_active;
u8 flush_active;
u8 refeeding; /* We are refeeding (valid only if export_state == ES_FEEDING) */
u8 refeeding; /* Refeeding the channel. */
u8 reloadable; /* Hook reload_routes() is allowed on the channel */
u8 gr_lock; /* Graceful restart mechanism should wait for this channel */
u8 gr_wait; /* Route export to channel is postponed until graceful restart */
@ -585,34 +588,34 @@ struct channel {
* restricted by that and is on volition of the protocol. Generally, channels
* are opened in protocols' start() hooks when going to PS_UP.
*
* CS_FLUSHING - The transitional state between initialized channel and closed
* CS_STOP - The transitional state between initialized channel and closed
* channel. The channel is still initialized, but no route exchange is allowed.
* Instead, the associated table is running flush loop to remove routes imported
* through the channel. After that, the channel changes state to CS_DOWN and
* is detached from the table (the table is unlocked and the channel is unlinked
* from it). Unlike other states, the CS_FLUSHING state is not explicitly
* from it). Unlike other states, the CS_STOP state is not explicitly
* entered or left by the protocol. A protocol may request to close a channel
* (by calling channel_close()), which causes the channel to change state to
* CS_FLUSHING and later to CS_DOWN. Also note that channels are closed
* CS_STOP and later to CS_DOWN. Also note that channels are closed
* automatically by the core when the protocol is going down.
*
* CS_PAUSE - Almost the same as CS_STOP, just the table import is kept and
* the table export is stopped before transitioning to CS_START.
*
* Allowed transitions:
*
* CS_DOWN -> CS_START / CS_UP
* CS_START -> CS_UP / CS_FLUSHING
* CS_UP -> CS_START / CS_FLUSHING
* CS_FLUSHING -> CS_DOWN (automatic)
* CS_START -> CS_UP / CS_STOP
* CS_UP -> CS_PAUSE / CS_STOP
* CS_PAUSE -> CS_START (automatic)
* CS_STOP -> CS_DOWN (automatic)
*/
#define CS_DOWN 0
#define CS_START 1
#define CS_UP 2
#define CS_FLUSHING 3
#define ES_DOWN 0
#define ES_FEEDING 1
#define ES_READY 2
#define CS_STOP 3
#define CS_PAUSE 4
struct channel_config *proto_cf_find_channel(struct proto_config *p, uint net_type);
static inline struct channel_config *proto_cf_main_channel(struct proto_config *pc)
@ -630,7 +633,7 @@ void channel_schedule_reload(struct channel *c);
static inline void channel_init(struct channel *c) { channel_set_state(c, CS_START); }
static inline void channel_open(struct channel *c) { channel_set_state(c, CS_UP); }
static inline void channel_close(struct channel *c) { channel_set_state(c, CS_FLUSHING); }
static inline void channel_close(struct channel *c) { channel_set_state(c, CS_STOP); }
void channel_request_feeding(struct channel *c);
void *channel_config_new(const struct channel_class *cc, const char *name, uint net_type, struct proto_config *proto);

View File

@ -2,6 +2,7 @@
* BIRD Internet Routing Daemon -- Routing Table
*
* (c) 1998--2000 Martin Mares <mj@ucw.cz>
* (c) 2019--2021 Maria Matejka <mq@jmq.cz>
*
* Can be freely distributed and used under the terms of the GNU GPL.
*/
@ -17,6 +18,7 @@
struct ea_list;
struct protocol;
struct proto;
struct channel;
struct rte_src;
struct symbol;
struct timer;
@ -165,12 +167,12 @@ typedef struct rtable {
struct fib fib;
struct f_trie *trie; /* Trie of prefixes defined in fib */
char *name; /* Name of this table */
list channels; /* List of attached channels (struct channel) */
uint addr_type; /* Type of address data stored in table (NET_*) */
int use_count; /* Number of protocols using this table */
u32 rt_count; /* Number of routes in the table */
byte internal; /* Internal table of a protocol */
list imports; /* Registered route importers */
list exports; /* Registered route exporters */
struct hmap id_map;
struct hostcache *hostcache;
@ -188,6 +190,7 @@ typedef struct rtable {
byte prune_trie; /* Prune prefix trie during next table prune */
byte hcu_scheduled; /* Hostcache update is scheduled */
byte nhu_state; /* Next Hop Update state */
byte internal; /* This table is internal for some other object */
struct fib_iterator prune_fit; /* Rtable prune FIB iterator */
struct fib_iterator nhu_fit; /* Next Hop Update FIB iterator */
struct f_trie *trie_new; /* New prefix trie defined during pruning */
@ -257,7 +260,7 @@ typedef struct rte {
struct rta *attrs; /* Attributes of this route */
const net_addr *net; /* Network this RTE belongs to */
struct rte_src *src; /* Route source that created the route */
struct channel *sender; /* Channel used to send the route to the routing table */
struct rt_import_hook *sender; /* Import hook used to send the route to the routing table */
btime lastmod; /* Last modified (set by table) */
u32 id; /* Table specific route id */
byte flags; /* Table-specific flags */
@ -281,15 +284,130 @@ struct rte_storage {
#define REF_MODIFY 16 /* Route is scheduled for modify */
/* Route is valid for propagation (may depend on other flags in the future), accepts NULL */
static inline int rte_is_valid_rte(rte *r) { return r && !(r->flags & REF_FILTERED); }
static inline int rte_is_valid_storage(struct rte_storage *r) { return r && rte_is_valid_rte(&r->rte); }
static inline int rte_is_valid_rte(const rte *r) { return r && !(r->flags & REF_FILTERED); }
static inline int rte_is_valid_storage(const struct rte_storage *r) { return r && rte_is_valid_rte(&r->rte); }
#define rte_is_valid(r) _Generic((*r), rte: rte_is_valid_rte, struct rte_storage: rte_is_valid_storage)(r)
/* Route just has REF_FILTERED flag */
static inline int rte_is_filtered(rte *r) { return !!(r->flags & REF_FILTERED); }
static inline int rte_is_filtered(const rte *r) { return !!(r->flags & REF_FILTERED); }
/* Table-channel connections */
struct rt_import_request {
struct rt_import_hook *hook; /* The table part of importer */
char *name;
u8 trace_routes;
void (*dump_req)(struct rt_import_request *req);
void (*log_state_change)(struct rt_import_request *req, u8 state);
/* Preimport is called when the @new route is just-to-be inserted, replacing @old.
* Return a route (may be different or modified in-place) to continue or NULL to withdraw. */
struct rte *(*preimport)(struct rt_import_request *req, struct rte *new, struct rte *old);
struct rte *(*rte_modify)(struct rte *, struct linpool *);
};
struct rt_import_hook {
node n;
rtable *table; /* The connected table */
struct rt_import_request *req; /* The requestor */
struct rt_import_stats {
/* Import - from protocol to core */
u32 pref; /* Number of routes selected as best in the (adjacent) routing table */
u32 updates_ignored; /* Number of route updates rejected as already in route table */
u32 updates_accepted; /* Number of route updates accepted and imported */
u32 withdraws_ignored; /* Number of route withdraws rejected as already not in route table */
u32 withdraws_accepted; /* Number of route withdraws accepted and processed */
} stats;
btime last_state_change; /* Time of last state transition */
u8 import_state; /* IS_* */
void (*stopped)(struct rt_import_request *); /* Stored callback when import is stopped */
};
struct rt_pending_export {
struct rte_storage *new, *new_best, *old, *old_best;
};
struct rt_export_request {
struct rt_export_hook *hook; /* Table part of the export */
char *name;
u8 trace_routes;
/* There are two methods of export. You can either request feeding every single change
* or feeding the whole route feed. In case of regular export, &export_one is preferred.
* Anyway, when feeding, &export_bulk is preferred, falling back to &export_one.
* Thus, for RA_OPTIMAL, &export_one is only set,
* for RA_MERGED and RA_ACCEPTED, &export_bulk is only set
* and for RA_ANY, both are set to accomodate for feeding all routes but receiving single changes
*/
void (*export_one)(struct rt_export_request *req, const net_addr *net, struct rt_pending_export *rpe);
void (*export_bulk)(struct rt_export_request *req, const net_addr *net, struct rt_pending_export *rpe, rte **feed, uint count);
void (*dump_req)(struct rt_export_request *req);
void (*log_state_change)(struct rt_export_request *req, u8);
};
struct rt_export_hook {
node n;
rtable *table; /* The connected table */
pool *pool;
linpool *lp;
struct rt_export_request *req; /* The requestor */
struct rt_export_stats {
/* Export - from core to protocol */
u32 updates_received; /* Number of route updates received */
u32 withdraws_received; /* Number of route withdraws received */
} stats;
struct fib_iterator feed_fit; /* Routing table iterator used during feeding */
btime last_state_change; /* Time of last state transition */
u8 refeed_pending; /* Refeeding and another refeed is scheduled */
u8 export_state; /* Route export state (TES_*, see below) */
struct event *event; /* Event running all the export operations */
void (*stopped)(struct rt_export_request *); /* Stored callback when export is stopped */
};
#define TIS_DOWN 0
#define TIS_UP 1
#define TIS_STOP 2
#define TIS_FLUSHING 3
#define TIS_WAITING 4
#define TIS_CLEARED 5
#define TIS_MAX 6
#define TES_DOWN 0
#define TES_HUNGRY 1
#define TES_FEEDING 2
#define TES_READY 3
#define TES_STOP 4
#define TES_MAX 5
void rt_request_import(rtable *tab, struct rt_import_request *req);
void rt_request_export(rtable *tab, struct rt_export_request *req);
void rt_stop_import(struct rt_import_request *, void (*stopped)(struct rt_import_request *));
void rt_stop_export(struct rt_export_request *, void (*stopped)(struct rt_export_request *));
const char *rt_import_state_name(u8 state);
const char *rt_export_state_name(u8 state);
static inline u8 rt_import_get_state(struct rt_import_hook *ih) { return ih ? ih->import_state : TIS_DOWN; }
static inline u8 rt_export_get_state(struct rt_export_hook *eh) { return eh ? eh->export_state : TES_DOWN; }
void rte_import(struct rt_import_request *req, const net_addr *net, rte *new, struct rte_src *src);
/* Types of route announcement, also used as flags */
#define RA_UNDEF 0 /* Undefined RA type */
#define RA_OPTIMAL 1 /* Announcement of optimal route change */
@ -303,6 +421,7 @@ static inline int rte_is_filtered(rte *r) { return !!(r->flags & REF_FILTERED);
#define RIC_REJECT -1 /* Rejected by protocol */
#define RIC_DROP -2 /* Silently dropped by protocol */
#define rte_update channel_rte_import
/**
* rte_update - enter a new update to a routing table
* @c: channel doing the update
@ -362,23 +481,24 @@ net *net_get(rtable *tab, const net_addr *addr);
net *net_route(rtable *tab, const net_addr *n);
int net_roa_check(rtable *tab, const net_addr *n, u32 asn);
int rt_examine(rtable *t, net_addr *a, struct channel *c, const struct filter *filter);
rte *rt_export_merged_show(struct channel *c, net *n, linpool *pool);
void rt_refresh_begin(rtable *t, struct channel *c);
void rt_refresh_end(rtable *t, struct channel *c);
void rt_modify_stale(rtable *t, struct channel *c);
rte *rt_export_merged(struct channel *c, rte ** feed, uint count, linpool *pool, int silent);
void rt_refresh_begin(rtable *t, struct rt_import_request *);
void rt_refresh_end(rtable *t, struct rt_import_request *);
void rt_modify_stale(rtable *t, struct rt_import_request *);
void rt_schedule_prune(rtable *t);
void rte_dump(struct rte_storage *);
void rte_free(struct rte_storage *, rtable *);
struct rte_storage *rte_store(const rte *, net *net, rtable *);
void rt_dump(rtable *);
void rt_dump_all(void);
int rt_feed_channel(struct channel *c);
void rt_feed_channel_abort(struct channel *c);
void rt_dump_hooks(rtable *);
void rt_dump_hooks_all(void);
int rt_reload_channel(struct channel *c);
void rt_reload_channel_abort(struct channel *c);
void rt_refeed_channel(struct channel *c);
void rt_prune_sync(rtable *t, int all);
int rte_update_out(struct channel *c, const net_addr *n, rte *new, rte *old, struct rte_storage **old_exported);
int rte_update_in(struct channel *c, const net_addr *n, rte *new, struct rte_src *src);
int rte_update_out(struct channel *c, const net_addr *n, rte *new, const rte *old, struct rte_storage **old_exported);
struct rtable_config *rt_new_table(struct symbol *s, uint addr_type);
static inline int rt_is_ip(rtable *tab)
@ -418,6 +538,7 @@ struct rt_show_data {
struct channel *export_channel;
struct config *running_on_config;
struct krt_proto *kernel;
struct rt_export_hook *kernel_export_hook;
int export_mode, addr_mode, primary_only, filtered, stats;
int table_open; /* Iteration (fit) is open */

View File

@ -99,6 +99,29 @@ rt_show_rte(struct cli *c, byte *ia, rte *e, struct rt_show_data *d, int primary
rta_show(c, a);
}
static uint
rte_feed_count(net *n)
{
uint count = 0;
for (struct rte_storage *e = n->routes; e; e = e->next)
if (rte_is_valid(RTE_OR_NULL(e)))
count++;
return count;
}
static void
rte_feed_obtain(net *n, rte **feed, uint count)
{
uint i = 0;
for (struct rte_storage *e = n->routes; e; e = e->next)
if (rte_is_valid(RTE_OR_NULL(e)))
{
ASSERT_DIE(i < count);
feed[i++] = &e->rte;
}
ASSERT_DIE(i == count);
}
static void
rt_show_net(struct cli *c, net *n, struct rt_show_data *d)
{
@ -128,7 +151,7 @@ rt_show_net(struct cli *c, net *n, struct rt_show_data *d)
struct rte e = er->rte;
/* Export channel is down, do not try to export routes to it */
if (ec && (ec->export_state == ES_DOWN))
if (ec && !ec->out_req.hook)
goto skip;
if (d->export_mode == RSEM_EXPORTED)
@ -143,7 +166,14 @@ rt_show_net(struct cli *c, net *n, struct rt_show_data *d)
{
/* Special case for merged export */
pass = 1;
rte *em = rt_export_merged_show(ec, n, c->show_pool);
uint count = rte_feed_count(n);
if (!count)
goto skip;
rte **feed = alloca(count * sizeof(rte *));
rte_feed_obtain(n, feed, count);
rte *em = rt_export_merged(ec, feed, count, c->show_pool, 1);
if (em)
e = *em;
else
@ -369,7 +399,7 @@ rt_show_get_default_tables(struct rt_show_data *d)
{
WALK_LIST(c, d->export_protocol->channels)
{
if (c->export_state == ES_DOWN)
if (!c->out_req.hook)
continue;
tab = rt_show_add_table(d, c->table);

File diff suppressed because it is too large Load Diff

View File

@ -760,25 +760,25 @@ bgp_handle_graceful_restart(struct bgp_proto *p)
{
case BGP_GRS_NONE:
c->gr_active = BGP_GRS_ACTIVE;
rt_refresh_begin(c->c.table, &c->c);
rt_refresh_begin(c->c.table, &c->c.in_req);
break;
case BGP_GRS_ACTIVE:
rt_refresh_end(c->c.table, &c->c);
rt_refresh_begin(c->c.table, &c->c);
rt_refresh_end(c->c.table, &c->c.in_req);
rt_refresh_begin(c->c.table, &c->c.in_req);
break;
case BGP_GRS_LLGR:
rt_refresh_begin(c->c.table, &c->c);
rt_modify_stale(c->c.table, &c->c);
rt_refresh_begin(c->c.table, &c->c.in_req);
rt_modify_stale(c->c.table, &c->c.in_req);
break;
}
}
else
{
/* Just flush the routes */
rt_refresh_begin(c->c.table, &c->c);
rt_refresh_end(c->c.table, &c->c);
rt_refresh_begin(c->c.table, &c->c.in_req);
rt_refresh_end(c->c.table, &c->c.in_req);
}
/* Reset bucket and prefix tables */
@ -819,7 +819,7 @@ bgp_graceful_restart_done(struct bgp_channel *c)
BGP_TRACE(D_EVENTS, "Neighbor graceful restart done");
tm_stop(c->stale_timer);
rt_refresh_end(c->c.table, &c->c);
rt_refresh_end(c->c.table, &c->c.in_req);
}
/**
@ -861,7 +861,7 @@ bgp_graceful_restart_timeout(timer *t)
/* Channel is in GR, and supports LLGR -> start LLGR */
c->gr_active = BGP_GRS_LLGR;
tm_start(c->stale_timer, c->stale_time S);
rt_modify_stale(c->c.table, &c->c);
rt_modify_stale(c->c.table, &c->c.in_req);
}
}
else
@ -899,10 +899,10 @@ bgp_refresh_begin(struct bgp_channel *c)
{ log(L_WARN "%s: BEGIN-OF-RR received before END-OF-RIB, ignoring", p->p.name); return; }
c->load_state = BFS_REFRESHING;
rt_refresh_begin(c->c.table, &c->c);
rt_refresh_begin(c->c.table, &c->c.in_req);
if (c->c.in_table)
rt_refresh_begin(c->c.in_table, &c->c);
rt_refresh_begin(c->c.in_table, &c->c.in_req);
}
/**
@ -923,7 +923,7 @@ bgp_refresh_end(struct bgp_channel *c)
{ log(L_WARN "%s: END-OF-RR received without prior BEGIN-OF-RR, ignoring", p->p.name); return; }
c->load_state = BFS_NONE;
rt_refresh_end(c->c.table, &c->c);
rt_refresh_end(c->c.table, &c->c.in_req);
if (c->c.in_table)
rt_prune_sync(c->c.in_table, 0);

View File

@ -82,7 +82,7 @@ pipe_preexport(struct channel *c, rte *e)
struct pipe_proto *p = (void *) c->proto;
/* Avoid direct loopbacks */
if (e->sender == c)
if (e->sender == c->in_req.hook)
return -1;
/* Indirection check */
@ -212,10 +212,18 @@ pipe_get_status(struct proto *P, byte *buf)
static void
pipe_show_stats(struct pipe_proto *p)
{
struct import_stats *s1i = &p->pri->import_stats;
struct export_stats *s1e = &p->pri->export_stats;
struct import_stats *s2i = &p->sec->import_stats;
struct export_stats *s2e = &p->sec->export_stats;
struct channel_import_stats *s1i = &p->pri->import_stats;
struct channel_export_stats *s1e = &p->pri->export_stats;
struct channel_import_stats *s2i = &p->sec->import_stats;
struct channel_export_stats *s2e = &p->sec->export_stats;
struct rt_import_stats *rs1i = p->pri->in_req.hook ? &p->pri->in_req.hook->stats : NULL;
struct rt_export_stats *rs1e = p->pri->out_req.hook ? &p->pri->out_req.hook->stats : NULL;
struct rt_import_stats *rs2i = p->sec->in_req.hook ? &p->sec->in_req.hook->stats : NULL;
struct rt_export_stats *rs2e = p->sec->out_req.hook ? &p->sec->out_req.hook->stats : NULL;
u32 pri_routes = p->pri->in_limit.count;
u32 sec_routes = p->sec->in_limit.count;
/*
* Pipe stats (as anything related to pipes) are a bit tricky. There
@ -239,24 +247,22 @@ pipe_show_stats(struct pipe_proto *p)
*/
cli_msg(-1006, " Routes: %u imported, %u exported",
s1i->routes, s2i->routes);
pri_routes, sec_routes);
cli_msg(-1006, " Route change stats: received rejected filtered ignored accepted");
cli_msg(-1006, " Import updates: %10u %10u %10u %10u %10u",
s2e->updates_received, s2e->updates_rejected + s1i->updates_invalid,
s2e->updates_filtered, s1i->updates_ignored, s1i->updates_accepted);
rs2e->updates_received, s2e->updates_rejected + s1i->updates_invalid,
s2e->updates_filtered, rs1i->updates_ignored, rs1i->updates_accepted);
cli_msg(-1006, " Import withdraws: %10u %10u --- %10u %10u",
s2e->withdraws_received, s1i->withdraws_invalid,
s1i->withdraws_ignored, s1i->withdraws_accepted);
rs2e->withdraws_received, s1i->withdraws_invalid,
rs1i->withdraws_ignored, rs1i->withdraws_accepted);
cli_msg(-1006, " Export updates: %10u %10u %10u %10u %10u",
s1e->updates_received, s1e->updates_rejected + s2i->updates_invalid,
s1e->updates_filtered, s2i->updates_ignored, s2i->updates_accepted);
rs1e->updates_received, s1e->updates_rejected + s2i->updates_invalid,
s1e->updates_filtered, rs2i->updates_ignored, rs2i->updates_accepted);
cli_msg(-1006, " Export withdraws: %10u %10u --- %10u %10u",
s1e->withdraws_received, s2i->withdraws_invalid,
s2i->withdraws_ignored, s2i->withdraws_accepted);
rs1e->withdraws_received, s2i->withdraws_invalid,
rs2i->withdraws_ignored, rs2i->withdraws_accepted);
}
static const char *pipe_feed_state[] = { [ES_DOWN] = "down", [ES_FEEDING] = "feed", [ES_READY] = "up" };
static void
pipe_show_proto_info(struct proto *P)
{
@ -265,13 +271,17 @@ pipe_show_proto_info(struct proto *P)
cli_msg(-1006, " Channel %s", "main");
cli_msg(-1006, " Table: %s", p->pri->table->name);
cli_msg(-1006, " Peer table: %s", p->sec->table->name);
cli_msg(-1006, " Import state: %s", pipe_feed_state[p->sec->export_state]);
cli_msg(-1006, " Export state: %s", pipe_feed_state[p->pri->export_state]);
cli_msg(-1006, " Import state: %s", rt_export_state_name(rt_export_get_state(p->sec->out_req.hook)));
cli_msg(-1006, " Export state: %s", rt_export_state_name(rt_export_get_state(p->pri->out_req.hook)));
cli_msg(-1006, " Import filter: %s", filter_name(p->sec->out_filter));
cli_msg(-1006, " Export filter: %s", filter_name(p->pri->out_filter));
channel_show_limit(&p->pri->in_limit, "Import limit:");
channel_show_limit(&p->sec->in_limit, "Export limit:");
channel_show_limit(&p->pri->in_limit, "Import limit:",
(p->pri->limit_active & (1 << PLD_IN)), p->pri->limit_actions[PLD_IN]);
channel_show_limit(&p->sec->in_limit, "Export limit:",
(p->sec->limit_active & (1 << PLD_IN)), p->sec->limit_actions[PLD_IN]);
if (P->proto_state != PS_DOWN)
pipe_show_stats(p);

View File

@ -661,9 +661,9 @@ rpki_handle_cache_response_pdu(struct rpki_cache *cache, const struct pdu_cache_
* a refresh cycle.
*/
if (cache->p->roa4_channel)
rt_refresh_begin(cache->p->roa4_channel->table, cache->p->roa4_channel);
rt_refresh_begin(cache->p->roa4_channel->table, &cache->p->roa4_channel->in_req);
if (cache->p->roa6_channel)
rt_refresh_begin(cache->p->roa6_channel->table, cache->p->roa6_channel);
rt_refresh_begin(cache->p->roa6_channel->table, &cache->p->roa6_channel->in_req);
cache->p->refresh_channels = 1;
}
@ -846,9 +846,9 @@ rpki_handle_end_of_data_pdu(struct rpki_cache *cache, const struct pdu_end_of_da
{
cache->p->refresh_channels = 0;
if (cache->p->roa4_channel)
rt_refresh_end(cache->p->roa4_channel->table, cache->p->roa4_channel);
rt_refresh_end(cache->p->roa4_channel->table, &cache->p->roa4_channel->in_req);
if (cache->p->roa6_channel)
rt_refresh_end(cache->p->roa6_channel->table, cache->p->roa6_channel);
rt_refresh_end(cache->p->roa6_channel->table, &cache->p->roa6_channel->in_req);
}
cache->last_update = current_time();
@ -924,6 +924,9 @@ rpki_rx_hook(struct birdsock *sk, uint size)
struct rpki_cache *cache = sk->data;
struct rpki_proto *p = cache->p;
if ((p->p.proto_state == PS_DOWN) || (p->cache != cache))
return 0;
byte *pkt_start = sk->rbuf;
byte *end = pkt_start + size;
@ -980,6 +983,8 @@ rpki_err_hook(struct birdsock *sk, int error_num)
CACHE_TRACE(D_EVENTS, cache, "The other side closed a connection");
}
if (cache->p->cache != cache)
return;
rpki_cache_change_state(cache, RPKI_CS_ERROR_TRANSPORT);
}
@ -999,6 +1004,9 @@ rpki_tx_hook(sock *sk)
{
struct rpki_cache *cache = sk->data;
if (cache->p->cache != cache)
return;
while (rpki_fire_tx(cache) > 0)
;
}
@ -1008,6 +1016,9 @@ rpki_connected_hook(sock *sk)
{
struct rpki_cache *cache = sk->data;
if (cache->p->cache != cache)
return;
CACHE_TRACE(D_EVENTS, cache, "Connected");
proto_notify_state(&cache->p->p, PS_UP);

View File

@ -384,6 +384,9 @@ rpki_refresh_hook(timer *tm)
{
struct rpki_cache *cache = tm->data;
if (cache->p->cache != cache)
return;
CACHE_DBG(cache, "%s", rpki_cache_state_to_str(cache->state));
switch (cache->state)
@ -430,6 +433,9 @@ rpki_retry_hook(timer *tm)
{
struct rpki_cache *cache = tm->data;
if (cache->p->cache != cache)
return;
CACHE_DBG(cache, "%s", rpki_cache_state_to_str(cache->state));
switch (cache->state)
@ -475,6 +481,9 @@ rpki_expire_hook(timer *tm)
{
struct rpki_cache *cache = tm->data;
if (cache->p->cache != cache)
return;
if (!cache->last_update)
return;

View File

@ -507,19 +507,13 @@ static_shutdown(struct proto *P)
WALK_LIST(r, cf->routes)
static_reset_rte(p, r);
return PS_DOWN;
}
static void
static_cleanup(struct proto *P)
{
struct static_proto *p = (void *) P;
if (p->igp_table_ip4)
rt_unlock_table(p->igp_table_ip4);
if (p->igp_table_ip6)
rt_unlock_table(p->igp_table_ip6);
return PS_DOWN;
}
static void
@ -777,7 +771,6 @@ struct protocol proto_static = {
.dump = static_dump,
.start = static_start,
.shutdown = static_shutdown,
.cleanup = static_cleanup,
.reconfigure = static_reconfigure,
.copy_config = static_copy_config,
.get_route_info = static_get_route_info,

View File

@ -542,21 +542,27 @@ krt_is_installed(struct krt_proto *p, net *n)
return n->routes && bmap_test(&p->p.main_channel->export_map, n->routes->rte.id);
}
static void
krt_flush_routes(struct krt_proto *p)
static uint
rte_feed_count(net *n)
{
struct rtable *t = p->p.main_channel->table;
uint count = 0;
for (struct rte_storage *e = n->routes; e; e = e->next)
if (rte_is_valid(RTE_OR_NULL(e)))
count++;
return count;
}
KRT_TRACE(p, D_EVENTS, "Flushing kernel routes");
FIB_WALK(&t->fib, net, n)
static void
rte_feed_obtain(net *n, rte **feed, uint count)
{
uint i = 0;
for (struct rte_storage *e = n->routes; e; e = e->next)
if (rte_is_valid(RTE_OR_NULL(e)))
{
if (krt_is_installed(p, n))
{
/* FIXME: this does not work if gw is changed in export filter */
krt_replace_rte(p, n->n.addr, NULL, &n->routes->rte);
}
ASSERT_DIE(i < count);
feed[i++] = &e->rte;
}
FIB_WALK_END;
ASSERT_DIE(i == count);
}
static struct rte *
@ -566,7 +572,15 @@ krt_export_net(struct krt_proto *p, net *net)
const struct filter *filter = c->out_filter;
if (c->ra_mode == RA_MERGED)
return rt_export_merged_show(c, net, krt_filter_lp);
{
uint count = rte_feed_count(net);
if (!count)
return NULL;
rte **feed = alloca(count * sizeof(rte *));
rte_feed_obtain(net, feed, count);
return rt_export_merged(c, feed, count, krt_filter_lp, 1);
}
static _Thread_local rte rt;
rt = net->routes->rte;
@ -637,6 +651,9 @@ krt_got_route(struct krt_proto *p, rte *e, s8 src)
#endif
/* The rest is for KRT_SRC_BIRD (or KRT_SRC_UNKNOWN) */
/* Deleting all routes if flush is requested */
if (p->flush_routes)
goto delete;
/* We wait for the initial feed to have correct installed state */
if (!p->ready)
@ -729,6 +746,17 @@ krt_prune(struct krt_proto *p)
p->initialized = 1;
}
static void
krt_flush_routes(struct krt_proto *p)
{
KRT_TRACE(p, D_EVENTS, "Flushing kernel routes");
p->flush_routes = 1;
krt_init_scan(p);
krt_do_scan(p);
/* No prune! */
p->flush_routes = 0;
}
void
krt_got_route_async(struct krt_proto *p, rte *e, int new, s8 src)
{

View File

@ -66,6 +66,7 @@ struct krt_proto {
byte ready; /* Initial feed has been finished */
byte initialized; /* First scan has been finished */
byte reload; /* Next scan is doing reload */
byte flush_routes; /* Scanning to flush */
};
extern pool *krt_pool;