mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-11-18 17:18:42 +00:00
Merge commit '1b9189d5' into haugesund
This commit is contained in:
commit
92b832380d
@ -519,14 +519,14 @@
|
|||||||
{
|
{
|
||||||
STATIC_ATTR;
|
STATIC_ATTR;
|
||||||
ACCESS_RTE;
|
ACCESS_RTE;
|
||||||
struct rta *rta = (*fs->rte)->attrs;
|
struct rta *rta = fs->rte->attrs;
|
||||||
|
|
||||||
switch (sa.sa_code)
|
switch (sa.sa_code)
|
||||||
{
|
{
|
||||||
case SA_FROM: RESULT(sa.f_type, ip, rta->from); break;
|
case SA_FROM: RESULT(sa.f_type, ip, rta->from); break;
|
||||||
case SA_GW: RESULT(sa.f_type, ip, rta->nh.gw); break;
|
case SA_GW: RESULT(sa.f_type, ip, rta->nh.gw); break;
|
||||||
case SA_NET: RESULT(sa.f_type, net, (*fs->rte)->net->n.addr); break;
|
case SA_NET: RESULT(sa.f_type, net, fs->rte->net); break;
|
||||||
case SA_PROTO: RESULT(sa.f_type, s, (*fs->rte)->src->proto->name); break;
|
case SA_PROTO: RESULT(sa.f_type, s, fs->rte->src->proto->name); break;
|
||||||
case SA_SOURCE: RESULT(sa.f_type, i, rta->source); break;
|
case SA_SOURCE: RESULT(sa.f_type, i, rta->source); break;
|
||||||
case SA_SCOPE: RESULT(sa.f_type, i, rta->scope); break;
|
case SA_SCOPE: RESULT(sa.f_type, i, rta->scope); break;
|
||||||
case SA_DEST: RESULT(sa.f_type, i, rta->dest); break;
|
case SA_DEST: RESULT(sa.f_type, i, rta->dest); break;
|
||||||
@ -550,7 +550,7 @@
|
|||||||
|
|
||||||
f_rta_cow(fs);
|
f_rta_cow(fs);
|
||||||
{
|
{
|
||||||
struct rta *rta = (*fs->rte)->attrs;
|
struct rta *rta = fs->rte->attrs;
|
||||||
|
|
||||||
switch (sa.sa_code)
|
switch (sa.sa_code)
|
||||||
{
|
{
|
||||||
@ -562,7 +562,7 @@
|
|||||||
{
|
{
|
||||||
ip_addr ip = v1.val.ip;
|
ip_addr ip = v1.val.ip;
|
||||||
struct iface *ifa = ipa_is_link_local(ip) ? rta->nh.iface : NULL;
|
struct iface *ifa = ipa_is_link_local(ip) ? rta->nh.iface : NULL;
|
||||||
neighbor *n = neigh_find((*fs->rte)->src->proto, ip, ifa, 0);
|
neighbor *n = neigh_find(fs->rte->src->proto, ip, ifa, 0);
|
||||||
if (!n || (n->scope == SCOPE_HOST))
|
if (!n || (n->scope == SCOPE_HOST))
|
||||||
runtime( "Invalid gw address" );
|
runtime( "Invalid gw address" );
|
||||||
|
|
||||||
@ -1314,7 +1314,7 @@
|
|||||||
struct rtable *table = rtc->table;
|
struct rtable *table = rtc->table;
|
||||||
ACCESS_RTE;
|
ACCESS_RTE;
|
||||||
ACCESS_EATTRS;
|
ACCESS_EATTRS;
|
||||||
const net_addr *net = (*fs->rte)->net->n.addr;
|
const net_addr *net = fs->rte->net;
|
||||||
|
|
||||||
/* We ignore temporary attributes, probably not a problem here */
|
/* We ignore temporary attributes, probably not a problem here */
|
||||||
/* 0x02 is a value of BA_AS_PATH, we don't want to include BGP headers */
|
/* 0x02 is a value of BA_AS_PATH, we don't want to include BGP headers */
|
||||||
|
@ -74,10 +74,7 @@ struct filter_state {
|
|||||||
} stack;
|
} stack;
|
||||||
|
|
||||||
/* The route we are processing. This may be NULL to indicate no route available. */
|
/* The route we are processing. This may be NULL to indicate no route available. */
|
||||||
struct rte **rte;
|
struct rte *rte;
|
||||||
|
|
||||||
/* The old rta to be freed after filters are done. */
|
|
||||||
struct rta *old_rta;
|
|
||||||
|
|
||||||
/* Cached pointer to ea_list */
|
/* Cached pointer to ea_list */
|
||||||
struct ea_list **eattrs;
|
struct ea_list **eattrs;
|
||||||
@ -102,15 +99,7 @@ void (*bt_assert_hook)(int result, const struct f_line_item *assert);
|
|||||||
|
|
||||||
static inline void f_cache_eattrs(struct filter_state *fs)
|
static inline void f_cache_eattrs(struct filter_state *fs)
|
||||||
{
|
{
|
||||||
fs->eattrs = &((*fs->rte)->attrs->eattrs);
|
fs->eattrs = &(fs->rte->attrs->eattrs);
|
||||||
}
|
|
||||||
|
|
||||||
static inline void f_rte_cow(struct filter_state *fs)
|
|
||||||
{
|
|
||||||
if (!((*fs->rte)->flags & REF_COW))
|
|
||||||
return;
|
|
||||||
|
|
||||||
*fs->rte = rte_cow(*fs->rte);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -119,22 +108,16 @@ static inline void f_rte_cow(struct filter_state *fs)
|
|||||||
static void
|
static void
|
||||||
f_rta_cow(struct filter_state *fs)
|
f_rta_cow(struct filter_state *fs)
|
||||||
{
|
{
|
||||||
if (!rta_is_cached((*fs->rte)->attrs))
|
if (!rta_is_cached(fs->rte->attrs))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Prepare to modify rte */
|
|
||||||
f_rte_cow(fs);
|
|
||||||
|
|
||||||
/* Store old rta to free it later, it stores reference from rte_cow() */
|
|
||||||
fs->old_rta = (*fs->rte)->attrs;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get shallow copy of rta. Fields eattrs and nexthops of rta are shared
|
* Get shallow copy of rta. Fields eattrs and nexthops of rta are shared
|
||||||
* with fs->old_rta (they will be copied when the cached rta will be obtained
|
* with fs->old_rta (they will be copied when the cached rta will be obtained
|
||||||
* at the end of f_run()), also the lock of hostentry is inherited (we
|
* at the end of f_run()), also the lock of hostentry is inherited (we
|
||||||
* suppose hostentry is not changed by filters).
|
* suppose hostentry is not changed by filters).
|
||||||
*/
|
*/
|
||||||
(*fs->rte)->attrs = rta_do_cow((*fs->rte)->attrs, fs->pool);
|
fs->rte->attrs = rta_do_cow(fs->rte->attrs, fs->pool);
|
||||||
|
|
||||||
/* Re-cache the ea_list */
|
/* Re-cache the ea_list */
|
||||||
f_cache_eattrs(fs);
|
f_cache_eattrs(fs);
|
||||||
@ -246,29 +229,15 @@ interpret(struct filter_state *fs, const struct f_line *line, struct f_val *val)
|
|||||||
/**
|
/**
|
||||||
* f_run - run a filter for a route
|
* f_run - run a filter for a route
|
||||||
* @filter: filter to run
|
* @filter: filter to run
|
||||||
* @rte: route being filtered, may be modified
|
* @rte: route being filtered, must be write-able
|
||||||
* @tmp_pool: all filter allocations go from this pool
|
* @tmp_pool: all filter allocations go from this pool
|
||||||
* @flags: flags
|
* @flags: flags
|
||||||
*
|
*
|
||||||
* If filter needs to modify the route, there are several
|
* If @rte->attrs is cached, the returned rte allocates a new rta on
|
||||||
* posibilities. @rte might be read-only (with REF_COW flag), in that
|
* tmp_pool, otherwise the filters may modify it.
|
||||||
* case rw copy is obtained by rte_cow() and @rte is replaced. If
|
|
||||||
* @rte is originally rw, it may be directly modified (and it is never
|
|
||||||
* copied).
|
|
||||||
*
|
|
||||||
* The returned rte may reuse the (possibly cached, cloned) rta, or
|
|
||||||
* (if rta was modified) contains a modified uncached rta, which
|
|
||||||
* uses parts allocated from @tmp_pool and parts shared from original
|
|
||||||
* rta. There is one exception - if @rte is rw but contains a cached
|
|
||||||
* rta and that is modified, rta in returned rte is also cached.
|
|
||||||
*
|
|
||||||
* Ownership of cached rtas is consistent with rte, i.e.
|
|
||||||
* if a new rte is returned, it has its own clone of cached rta
|
|
||||||
* (and cached rta of read-only source rte is intact), if rte is
|
|
||||||
* modified in place, old cached rta is possibly freed.
|
|
||||||
*/
|
*/
|
||||||
enum filter_return
|
enum filter_return
|
||||||
f_run(const struct filter *filter, struct rte **rte, struct linpool *tmp_pool, int flags)
|
f_run(const struct filter *filter, struct rte *rte, struct linpool *tmp_pool, int flags)
|
||||||
{
|
{
|
||||||
if (filter == FILTER_ACCEPT)
|
if (filter == FILTER_ACCEPT)
|
||||||
return F_ACCEPT;
|
return F_ACCEPT;
|
||||||
@ -276,7 +245,6 @@ f_run(const struct filter *filter, struct rte **rte, struct linpool *tmp_pool, i
|
|||||||
if (filter == FILTER_REJECT)
|
if (filter == FILTER_REJECT)
|
||||||
return F_REJECT;
|
return F_REJECT;
|
||||||
|
|
||||||
int rte_cow = ((*rte)->flags & REF_COW);
|
|
||||||
DBG( "Running filter `%s'...", filter->name );
|
DBG( "Running filter `%s'...", filter->name );
|
||||||
|
|
||||||
/* Initialize the filter state */
|
/* Initialize the filter state */
|
||||||
@ -293,32 +261,6 @@ f_run(const struct filter *filter, struct rte **rte, struct linpool *tmp_pool, i
|
|||||||
/* Run the interpreter itself */
|
/* Run the interpreter itself */
|
||||||
enum filter_return fret = interpret(&filter_state, filter->root, NULL);
|
enum filter_return fret = interpret(&filter_state, filter->root, NULL);
|
||||||
|
|
||||||
if (filter_state.old_rta) {
|
|
||||||
/*
|
|
||||||
* Cached rta was modified and filter_state->rte contains now an uncached one,
|
|
||||||
* sharing some part with the cached one. The cached rta should
|
|
||||||
* be freed (if rte was originally COW, filter_state->old_rta is a clone
|
|
||||||
* obtained during rte_cow()).
|
|
||||||
*
|
|
||||||
* This also implements the exception mentioned in f_run()
|
|
||||||
* description. The reason for this is that rta reuses parts of
|
|
||||||
* filter_state->old_rta, and these may be freed during rta_free(filter_state->old_rta).
|
|
||||||
* This is not the problem if rte was COW, because original rte
|
|
||||||
* also holds the same rta.
|
|
||||||
*/
|
|
||||||
if (!rte_cow) {
|
|
||||||
/* Cache the new attrs */
|
|
||||||
(*filter_state.rte)->attrs = rta_lookup((*filter_state.rte)->attrs);
|
|
||||||
|
|
||||||
/* Drop cached ea_list pointer */
|
|
||||||
filter_state.eattrs = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Uncache the old attrs and drop the pointer as it is invalid now. */
|
|
||||||
rta_free(filter_state.old_rta);
|
|
||||||
filter_state.old_rta = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Process the filter output, log it and return */
|
/* Process the filter output, log it and return */
|
||||||
if (fret < F_ACCEPT) {
|
if (fret < F_ACCEPT) {
|
||||||
if (!(filter_state.flags & FF_SILENT))
|
if (!(filter_state.flags & FF_SILENT))
|
||||||
@ -343,7 +285,7 @@ f_run(const struct filter *filter, struct rte **rte, struct linpool *tmp_pool, i
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
enum filter_return
|
enum filter_return
|
||||||
f_eval_rte(const struct f_line *expr, struct rte **rte, struct linpool *tmp_pool)
|
f_eval_rte(const struct f_line *expr, struct rte *rte, struct linpool *tmp_pool)
|
||||||
{
|
{
|
||||||
filter_state = (struct filter_state) {
|
filter_state = (struct filter_state) {
|
||||||
.rte = rte,
|
.rte = rte,
|
||||||
@ -354,8 +296,7 @@ f_eval_rte(const struct f_line *expr, struct rte **rte, struct linpool *tmp_pool
|
|||||||
|
|
||||||
LOG_BUFFER_INIT(filter_state.buf);
|
LOG_BUFFER_INIT(filter_state.buf);
|
||||||
|
|
||||||
ASSERT(!((*rte)->flags & REF_COW));
|
ASSERT(!rta_is_cached(rte->attrs));
|
||||||
ASSERT(!rta_is_cached((*rte)->attrs));
|
|
||||||
|
|
||||||
return interpret(&filter_state, expr, NULL);
|
return interpret(&filter_state, expr, NULL);
|
||||||
}
|
}
|
||||||
|
@ -51,8 +51,8 @@ struct filter {
|
|||||||
|
|
||||||
struct rte;
|
struct rte;
|
||||||
|
|
||||||
enum filter_return f_run(const struct filter *filter, struct rte **rte, struct linpool *tmp_pool, int flags);
|
enum filter_return f_run(const struct filter *filter, struct rte *rte, struct linpool *tmp_pool, int flags);
|
||||||
enum filter_return f_eval_rte(const struct f_line *expr, struct rte **rte, struct linpool *tmp_pool);
|
enum filter_return f_eval_rte(const struct f_line *expr, struct rte *rte, struct linpool *tmp_pool);
|
||||||
uint f_eval_int(const struct f_line *expr);
|
uint f_eval_int(const struct f_line *expr);
|
||||||
enum filter_return f_eval_buf(const struct f_line *expr, struct linpool *tmp_pool, buffer *buf);
|
enum filter_return f_eval_buf(const struct f_line *expr, struct linpool *tmp_pool, buffer *buf);
|
||||||
|
|
||||||
|
@ -211,9 +211,9 @@ struct proto {
|
|||||||
|
|
||||||
void (*if_notify)(struct proto *, unsigned flags, struct iface *i);
|
void (*if_notify)(struct proto *, unsigned flags, struct iface *i);
|
||||||
void (*ifa_notify)(struct proto *, unsigned flags, struct ifa *a);
|
void (*ifa_notify)(struct proto *, unsigned flags, struct ifa *a);
|
||||||
void (*rt_notify)(struct proto *, struct channel *, struct network *net, struct rte *new, struct rte *old);
|
void (*rt_notify)(struct proto *, struct channel *, const net_addr *net, struct rte *new, const struct rte *old);
|
||||||
void (*neigh_notify)(struct neighbor *neigh);
|
void (*neigh_notify)(struct neighbor *neigh);
|
||||||
int (*preexport)(struct proto *, struct rte *rt);
|
int (*preexport)(struct channel *, struct rte *rt);
|
||||||
void (*reload_routes)(struct channel *);
|
void (*reload_routes)(struct channel *);
|
||||||
void (*feed_begin)(struct channel *, int initial);
|
void (*feed_begin)(struct channel *, int initial);
|
||||||
void (*feed_end)(struct channel *);
|
void (*feed_end)(struct channel *);
|
||||||
@ -232,7 +232,7 @@ struct proto {
|
|||||||
int (*rte_recalculate)(struct rtable *, struct network *, struct rte *, struct rte *, struct rte *);
|
int (*rte_recalculate)(struct rtable *, 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 *);
|
||||||
struct rte * (*rte_modify)(struct rte *, struct linpool *);
|
struct rte *(*rte_modify)(struct rte *, struct linpool *);
|
||||||
void (*rte_insert)(struct network *, struct rte *);
|
void (*rte_insert)(struct network *, struct rte *);
|
||||||
void (*rte_remove)(struct network *, struct rte *);
|
void (*rte_remove)(struct network *, struct rte *);
|
||||||
u32 (*rte_igp_metric)(struct rte *);
|
u32 (*rte_igp_metric)(struct rte *);
|
||||||
@ -542,7 +542,7 @@ struct channel {
|
|||||||
struct rtable *in_table; /* Internal table for received routes */
|
struct rtable *in_table; /* Internal table for received routes */
|
||||||
struct event *reload_event; /* Event responsible for reloading from in_table */
|
struct event *reload_event; /* Event responsible for reloading from in_table */
|
||||||
struct fib_iterator reload_fit; /* FIB iterator in in_table used during reloading */
|
struct fib_iterator reload_fit; /* FIB iterator in in_table used during reloading */
|
||||||
struct rte *reload_next_rte; /* Route iterator in in_table used during reloading */
|
struct rte_storage *reload_next_rte; /* Route iterator in in_table used during reloading */
|
||||||
u8 reload_active; /* Iterator reload_fit is linked */
|
u8 reload_active; /* Iterator reload_fit is linked */
|
||||||
|
|
||||||
u8 reload_pending; /* Reloading and another reload is scheduled */
|
u8 reload_pending; /* Reloading and another reload is scheduled */
|
||||||
@ -632,18 +632,4 @@ void *channel_config_new(const struct channel_class *cc, const char *name, uint
|
|||||||
void *channel_config_get(const struct channel_class *cc, const char *name, uint net_type, struct proto_config *proto);
|
void *channel_config_get(const struct channel_class *cc, const char *name, uint net_type, struct proto_config *proto);
|
||||||
int channel_reconfigure(struct channel *c, struct channel_config *cf);
|
int channel_reconfigure(struct channel *c, struct channel_config *cf);
|
||||||
|
|
||||||
|
|
||||||
/* Moved from route.h to avoid dependency conflicts */
|
|
||||||
static inline void rte_update(struct proto *p, const net_addr *n, rte *new) { rte_update2(p->main_channel, n, new, p->main_source); }
|
|
||||||
|
|
||||||
static inline void
|
|
||||||
rte_update3(struct channel *c, const net_addr *n, rte *new, struct rte_src *src)
|
|
||||||
{
|
|
||||||
if (c->in_table && !rte_update_in(c, n, new, src))
|
|
||||||
return;
|
|
||||||
|
|
||||||
rte_update2(c, n, new, src);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
83
nest/route.h
83
nest/route.h
@ -161,6 +161,7 @@ typedef struct rtable {
|
|||||||
resource r;
|
resource r;
|
||||||
node n; /* Node in list of all tables */
|
node n; /* Node in list of all tables */
|
||||||
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 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 */
|
char *name; /* Name of this table */
|
||||||
@ -221,7 +222,7 @@ struct rt_flowspec_link {
|
|||||||
#define NHU_DIRTY 3
|
#define NHU_DIRTY 3
|
||||||
|
|
||||||
typedef struct network {
|
typedef struct network {
|
||||||
struct rte *routes; /* Available routes for this network */
|
struct rte_storage *routes; /* Available routes for this network */
|
||||||
struct fib_node n; /* FIB flags reserved for kernel syncer */
|
struct fib_node n; /* FIB flags reserved for kernel syncer */
|
||||||
} net;
|
} net;
|
||||||
|
|
||||||
@ -253,25 +254,34 @@ struct hostentry {
|
|||||||
};
|
};
|
||||||
|
|
||||||
typedef struct rte {
|
typedef struct rte {
|
||||||
struct rte *next;
|
struct rta *attrs; /* Attributes of this route */
|
||||||
net *net; /* Network this RTE belongs to */
|
const net_addr *net; /* Network this RTE belongs to */
|
||||||
struct rte_src *src; /* Route source that created the route */
|
struct rte_src *src; /* Route source that created the route */
|
||||||
struct channel *sender; /* Channel used to send the route to the routing table */
|
struct channel *sender; /* Channel used to send the route to the routing table */
|
||||||
struct rta *attrs; /* Attributes of this route */
|
btime lastmod; /* Last modified (set by table) */
|
||||||
u32 id; /* Table specific route id */
|
u32 id; /* Table specific route id */
|
||||||
byte flags; /* Flags (REF_...) */
|
byte flags; /* Table-specific flags */
|
||||||
byte pflags; /* Protocol-specific flags */
|
byte pflags; /* Protocol-specific flags */
|
||||||
btime lastmod; /* Last modified */
|
|
||||||
} rte;
|
} rte;
|
||||||
|
|
||||||
#define REF_COW 1 /* Copy this rte on write */
|
struct rte_storage {
|
||||||
|
struct rte_storage *next; /* Next in chain */
|
||||||
|
struct rte rte; /* Route data */
|
||||||
|
};
|
||||||
|
|
||||||
|
#define RTE_COPY(r, l) ((r) ? (((*(l)) = (r)->rte), (l)) : NULL)
|
||||||
|
#define RTE_OR_NULL(r) ((r) ? &((r)->rte) : NULL)
|
||||||
|
|
||||||
#define REF_FILTERED 2 /* Route is rejected by import filter */
|
#define REF_FILTERED 2 /* Route is rejected by import filter */
|
||||||
#define REF_STALE 4 /* Route is stale in a refresh cycle */
|
#define REF_STALE 4 /* Route is stale in a refresh cycle */
|
||||||
#define REF_DISCARD 8 /* Route is scheduled for discard */
|
#define REF_DISCARD 8 /* Route is scheduled for discard */
|
||||||
#define REF_MODIFY 16 /* Route is scheduled for modify */
|
#define REF_MODIFY 16 /* Route is scheduled for modify */
|
||||||
|
|
||||||
/* Route is valid for propagation (may depend on other flags in the future), accepts NULL */
|
/* Route is valid for propagation (may depend on other flags in the future), accepts NULL */
|
||||||
static inline int rte_is_valid(rte *r) { return r && !(r->flags & REF_FILTERED); }
|
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); }
|
||||||
|
|
||||||
|
#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 */
|
/* 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(rte *r) { return !!(r->flags & REF_FILTERED); }
|
||||||
@ -290,6 +300,40 @@ static inline int rte_is_filtered(rte *r) { return !!(r->flags & REF_FILTERED);
|
|||||||
#define RIC_REJECT -1 /* Rejected by protocol */
|
#define RIC_REJECT -1 /* Rejected by protocol */
|
||||||
#define RIC_DROP -2 /* Silently dropped by protocol */
|
#define RIC_DROP -2 /* Silently dropped by protocol */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* rte_update - enter a new update to a routing table
|
||||||
|
* @c: channel doing the update
|
||||||
|
* @net: network address
|
||||||
|
* @rte: a &rte representing the new route
|
||||||
|
* @src: old route source identifier
|
||||||
|
*
|
||||||
|
* This function imports a new route to the appropriate table (via the channel).
|
||||||
|
* Table keys are @net (obligatory) and @rte->attrs->src.
|
||||||
|
* Both the @net and @rte pointers can be local.
|
||||||
|
*
|
||||||
|
* The route attributes (@rte->attrs) are obligatory. They can be also allocated
|
||||||
|
* locally. Anyway, if you use an already-cached attribute object, you shall
|
||||||
|
* call rta_clone() on that object yourself. (This semantics may change in future.)
|
||||||
|
*
|
||||||
|
* If the route attributes are local, you may set @rte->attrs->src to NULL, then
|
||||||
|
* the protocol's default route source will be supplied.
|
||||||
|
*
|
||||||
|
* When rte_update() gets a route, it automatically validates it. This includes
|
||||||
|
* checking for validity of the given network and next hop addresses and also
|
||||||
|
* checking for host-scope or link-scope routes. Then the import filters are
|
||||||
|
* processed and if accepted, the route is passed to route table recalculation.
|
||||||
|
*
|
||||||
|
* The accepted routes are then inserted into the table, replacing the old route
|
||||||
|
* for the same @net identified by @src. Then the route is announced
|
||||||
|
* to all the channels connected to the table using the standard export mechanism.
|
||||||
|
* Setting @rte to NULL makes this a withdraw, otherwise @rte->src must be the same
|
||||||
|
* as @src.
|
||||||
|
*
|
||||||
|
* All memory used for temporary allocations is taken from a special linpool
|
||||||
|
* @rte_update_pool and freed when rte_update() finishes.
|
||||||
|
*/
|
||||||
|
void rte_update(struct channel *c, const net_addr *net, struct rte *rte, struct rte_src *src);
|
||||||
|
|
||||||
extern list routing_tables;
|
extern list routing_tables;
|
||||||
struct config;
|
struct config;
|
||||||
|
|
||||||
@ -309,35 +353,28 @@ 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(rtable *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(rtable *tab, const net_addr *addr)
|
||||||
{ net *n = net_find(tab, addr); return (n && rte_is_valid(n->routes)) ? 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(rtable *tab, const net_addr *addr) { return (net *) fib_get(&tab->fib, addr); }
|
||||||
net *net_get(rtable *tab, const net_addr *addr);
|
net *net_get(rtable *tab, const net_addr *addr);
|
||||||
net *net_route(rtable *tab, const net_addr *n);
|
net *net_route(rtable *tab, const net_addr *n);
|
||||||
int net_roa_check(rtable *tab, const net_addr *n, u32 asn);
|
int net_roa_check(rtable *tab, const net_addr *n, u32 asn);
|
||||||
rte *rte_find(net *net, struct rte_src *src);
|
int rt_examine(rtable *t, net_addr *a, struct channel *c, const struct filter *filter);
|
||||||
rte *rte_get_temp(struct rta *, struct rte_src *src);
|
rte *rt_export_merged(struct channel *c, net *net, linpool *pool, int silent);
|
||||||
void rte_update2(struct channel *c, const net_addr *n, rte *new, struct rte_src *src);
|
|
||||||
/* rte_update() moved to protocol.h to avoid dependency conflicts */
|
|
||||||
int rt_examine(rtable *t, net_addr *a, struct proto *p, const struct filter *filter);
|
|
||||||
rte *rt_export_merged(struct channel *c, net *net, rte **rt_free, linpool *pool, int silent);
|
|
||||||
void rt_refresh_begin(rtable *t, struct channel *c);
|
void rt_refresh_begin(rtable *t, struct channel *c);
|
||||||
void rt_refresh_end(rtable *t, struct channel *c);
|
void rt_refresh_end(rtable *t, struct channel *c);
|
||||||
void rt_modify_stale(rtable *t, struct channel *c);
|
void rt_modify_stale(rtable *t, struct channel *c);
|
||||||
void rt_schedule_prune(rtable *t);
|
void rt_schedule_prune(rtable *t);
|
||||||
void rte_dump(rte *);
|
void rte_dump(struct rte_storage *);
|
||||||
void rte_free(rte *);
|
void rte_free(struct rte_storage *, rtable *);
|
||||||
rte *rte_do_cow(rte *);
|
struct rte_storage *rte_store(const rte *, net *net, rtable *);
|
||||||
static inline rte * rte_cow(rte *r) { return (r->flags & REF_COW) ? rte_do_cow(r) : r; }
|
|
||||||
rte *rte_cow_rta(rte *r, linpool *lp);
|
|
||||||
void rt_dump(rtable *);
|
void rt_dump(rtable *);
|
||||||
void rt_dump_all(void);
|
void rt_dump_all(void);
|
||||||
int rt_feed_channel(struct channel *c);
|
int rt_feed_channel(struct channel *c);
|
||||||
void rt_feed_channel_abort(struct channel *c);
|
void rt_feed_channel_abort(struct channel *c);
|
||||||
int rte_update_in(struct channel *c, const net_addr *n, rte *new, struct rte_src *src);
|
|
||||||
int rt_reload_channel(struct channel *c);
|
int rt_reload_channel(struct channel *c);
|
||||||
void rt_reload_channel_abort(struct channel *c);
|
void rt_reload_channel_abort(struct channel *c);
|
||||||
void rt_prune_sync(rtable *t, int all);
|
void rt_prune_sync(rtable *t, int all);
|
||||||
int rte_update_out(struct channel *c, const net_addr *n, rte *new, rte *old, rte **old_exported, int refeed);
|
int rte_update_out(struct channel *c, const net_addr *n, rte *new, rte *old, struct rte_storage **old_exported, int refeed);
|
||||||
struct rtable_config *rt_new_table(struct symbol *s, uint addr_type);
|
struct rtable_config *rt_new_table(struct symbol *s, uint addr_type);
|
||||||
|
|
||||||
static inline int rt_is_ip(rtable *tab)
|
static inline int rt_is_ip(rtable *tab)
|
||||||
@ -678,7 +715,7 @@ void rta_dump(rta *);
|
|||||||
void rta_dump_all(void);
|
void rta_dump_all(void);
|
||||||
void rta_show(struct cli *, rta *);
|
void rta_show(struct cli *, rta *);
|
||||||
|
|
||||||
u32 rt_get_igp_metric(rte *rt);
|
u32 rt_get_igp_metric(rte *);
|
||||||
struct hostentry * rt_get_hostentry(rtable *tab, ip_addr a, ip_addr ll, rtable *dep);
|
struct hostentry * rt_get_hostentry(rtable *tab, ip_addr a, ip_addr ll, rtable *dep);
|
||||||
void rta_apply_hostentry(rta *a, struct hostentry *he, mpls_label_stack *mls);
|
void rta_apply_hostentry(rta *a, struct hostentry *he, mpls_label_stack *mls);
|
||||||
|
|
||||||
|
@ -67,13 +67,10 @@ dev_ifa_notify(struct proto *P, uint flags, struct ifa *ad)
|
|||||||
|
|
||||||
/* Use iface ID as local source ID */
|
/* Use iface ID as local source ID */
|
||||||
struct rte_src *src = rt_get_source(P, ad->iface->index);
|
struct rte_src *src = rt_get_source(P, ad->iface->index);
|
||||||
rte_update2(c, net, NULL, src);
|
rte_update(c, net, NULL, src);
|
||||||
}
|
}
|
||||||
else if (flags & IF_CHANGE_UP)
|
else if (flags & IF_CHANGE_UP)
|
||||||
{
|
{
|
||||||
rta *a;
|
|
||||||
rte *e;
|
|
||||||
|
|
||||||
DBG("dev_if_notify: %s:%I going up\n", ad->iface->name, ad->ip);
|
DBG("dev_if_notify: %s:%I going up\n", ad->iface->name, ad->ip);
|
||||||
|
|
||||||
if (cf->check_link && !(ad->iface->flags & IF_LINK_UP))
|
if (cf->check_link && !(ad->iface->flags & IF_LINK_UP))
|
||||||
@ -90,10 +87,12 @@ dev_ifa_notify(struct proto *P, uint flags, struct ifa *ad)
|
|||||||
.nh.iface = ad->iface,
|
.nh.iface = ad->iface,
|
||||||
};
|
};
|
||||||
|
|
||||||
a = rta_lookup(&a0);
|
rte e0 = {
|
||||||
e = rte_get_temp(a, src);
|
.attrs = rta_lookup(&a0),
|
||||||
e->pflags = 0;
|
.src = src,
|
||||||
rte_update2(c, net, e, src);
|
};
|
||||||
|
|
||||||
|
rte_update(c, net, &e0, src);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,7 +102,6 @@ rt_show_rte(struct cli *c, byte *ia, rte *e, struct rt_show_data *d, int primary
|
|||||||
static void
|
static void
|
||||||
rt_show_net(struct cli *c, net *n, struct rt_show_data *d)
|
rt_show_net(struct cli *c, net *n, struct rt_show_data *d)
|
||||||
{
|
{
|
||||||
rte *e, *ee;
|
|
||||||
byte ia[NET_MAX_TEXT_LENGTH+1];
|
byte ia[NET_MAX_TEXT_LENGTH+1];
|
||||||
struct channel *ec = d->tab->export_channel;
|
struct channel *ec = d->tab->export_channel;
|
||||||
|
|
||||||
@ -114,9 +113,9 @@ rt_show_net(struct cli *c, net *n, struct rt_show_data *d)
|
|||||||
int first_show = 1;
|
int first_show = 1;
|
||||||
int pass = 0;
|
int pass = 0;
|
||||||
|
|
||||||
for (e = n->routes; e; e = e->next)
|
for (struct rte_storage *er = n->routes; er; er = er->next)
|
||||||
{
|
{
|
||||||
if (rte_is_filtered(e) != d->filtered)
|
if (rte_is_filtered(&er->rte) != d->filtered)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
d->rt_counter++;
|
d->rt_counter++;
|
||||||
@ -126,7 +125,7 @@ rt_show_net(struct cli *c, net *n, struct rt_show_data *d)
|
|||||||
if (pass)
|
if (pass)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
ee = e;
|
struct rte e = er->rte;
|
||||||
|
|
||||||
/* Export channel is down, do not try to export routes to it */
|
/* Export channel is down, do not try to export routes to it */
|
||||||
if (ec && (ec->export_state == ES_DOWN))
|
if (ec && (ec->export_state == ES_DOWN))
|
||||||
@ -134,7 +133,7 @@ rt_show_net(struct cli *c, net *n, struct rt_show_data *d)
|
|||||||
|
|
||||||
if (d->export_mode == RSEM_EXPORTED)
|
if (d->export_mode == RSEM_EXPORTED)
|
||||||
{
|
{
|
||||||
if (!bmap_test(&ec->export_map, ee->id))
|
if (!bmap_test(&ec->export_map, e.id))
|
||||||
goto skip;
|
goto skip;
|
||||||
|
|
||||||
// if (ec->ra_mode != RA_ANY)
|
// if (ec->ra_mode != RA_ANY)
|
||||||
@ -143,17 +142,17 @@ rt_show_net(struct cli *c, net *n, struct rt_show_data *d)
|
|||||||
else if ((d->export_mode == RSEM_EXPORT) && (ec->ra_mode == RA_MERGED))
|
else if ((d->export_mode == RSEM_EXPORT) && (ec->ra_mode == RA_MERGED))
|
||||||
{
|
{
|
||||||
/* Special case for merged export */
|
/* Special case for merged export */
|
||||||
rte *rt_free;
|
|
||||||
e = rt_export_merged(ec, n, &rt_free, c->show_pool, 1);
|
|
||||||
pass = 1;
|
pass = 1;
|
||||||
|
rte *em = rt_export_merged(ec, n, c->show_pool, 1);
|
||||||
if (!e)
|
if (em)
|
||||||
{ e = ee; goto skip; }
|
e = *em;
|
||||||
|
else
|
||||||
|
goto skip;
|
||||||
}
|
}
|
||||||
else if (d->export_mode)
|
else if (d->export_mode)
|
||||||
{
|
{
|
||||||
struct proto *ep = ec->proto;
|
struct proto *ep = ec->proto;
|
||||||
int ic = ep->preexport ? ep->preexport(ep, e) : 0;
|
int ic = ep->preexport ? ep->preexport(ec, &e) : 0;
|
||||||
|
|
||||||
if (ec->ra_mode == RA_OPTIMAL || ec->ra_mode == RA_MERGED)
|
if (ec->ra_mode == RA_OPTIMAL || ec->ra_mode == RA_MERGED)
|
||||||
pass = 1;
|
pass = 1;
|
||||||
@ -179,7 +178,7 @@ rt_show_net(struct cli *c, net *n, struct rt_show_data *d)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (d->show_protocol && (d->show_protocol != e->src->proto))
|
if (d->show_protocol && (d->show_protocol != e.src->proto))
|
||||||
goto skip;
|
goto skip;
|
||||||
|
|
||||||
if (f_run(d->filter, &e, c->show_pool, 0) > F_ACCEPT)
|
if (f_run(d->filter, &e, c->show_pool, 0) > F_ACCEPT)
|
||||||
@ -192,18 +191,13 @@ rt_show_net(struct cli *c, net *n, struct rt_show_data *d)
|
|||||||
else
|
else
|
||||||
ia[0] = 0;
|
ia[0] = 0;
|
||||||
|
|
||||||
rt_show_rte(c, ia, e, d, (e->net->routes == ee));
|
rt_show_rte(c, ia, &e, d, (n->routes == er));
|
||||||
first_show = 0;
|
first_show = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
d->show_counter++;
|
d->show_counter++;
|
||||||
|
|
||||||
skip:
|
skip:
|
||||||
if (e != ee)
|
|
||||||
{
|
|
||||||
rte_free(e);
|
|
||||||
e = ee;
|
|
||||||
}
|
|
||||||
lp_flush(c->show_pool);
|
lp_flush(c->show_pool);
|
||||||
|
|
||||||
if (d->primary_only)
|
if (d->primary_only)
|
||||||
|
663
nest/rt-table.c
663
nest/rt-table.c
File diff suppressed because it is too large
Load Diff
@ -681,11 +681,13 @@ babel_announce_rte(struct babel_proto *p, struct babel_entry *e)
|
|||||||
if (!neigh_find(&p->p, r->next_hop, r->neigh->ifa->iface, 0))
|
if (!neigh_find(&p->p, r->next_hop, r->neigh->ifa->iface, 0))
|
||||||
a0.nh.flags = RNF_ONLINK;
|
a0.nh.flags = RNF_ONLINK;
|
||||||
|
|
||||||
rta *a = rta_lookup(&a0);
|
rte e0 = {
|
||||||
rte *rte = rte_get_temp(a, p->p.main_source);
|
.attrs = &a0,
|
||||||
|
.src = p->p.main_source,
|
||||||
|
};
|
||||||
|
|
||||||
e->unreachable = 0;
|
e->unreachable = 0;
|
||||||
rte_update2(c, e->n.addr, rte, p->p.main_source);
|
rte_update(c, e->n.addr, &e0, p->p.main_source);
|
||||||
}
|
}
|
||||||
else if (e->valid && (e->router_id != p->router_id))
|
else if (e->valid && (e->router_id != p->router_id))
|
||||||
{
|
{
|
||||||
@ -697,18 +699,19 @@ babel_announce_rte(struct babel_proto *p, struct babel_entry *e)
|
|||||||
.pref = 1,
|
.pref = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
rta *a = rta_lookup(&a0);
|
rte e0 = {
|
||||||
rte *rte = rte_get_temp(a, p->p.main_source);
|
.attrs = &a0,
|
||||||
rte->pflags = 0;
|
.src = p->p.main_source,
|
||||||
|
};
|
||||||
|
|
||||||
e->unreachable = 1;
|
e->unreachable = 1;
|
||||||
rte_update2(c, e->n.addr, rte, p->p.main_source);
|
rte_update(c, e->n.addr, &e0, p->p.main_source);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Retraction */
|
/* Retraction */
|
||||||
e->unreachable = 0;
|
e->unreachable = 0;
|
||||||
rte_update2(c, e->n.addr, NULL, p->p.main_source);
|
rte_update(c, e->n.addr, NULL, p->p.main_source);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -718,7 +721,7 @@ babel_announce_retraction(struct babel_proto *p, struct babel_entry *e)
|
|||||||
{
|
{
|
||||||
struct channel *c = (e->n.addr->type == NET_IP4) ? p->ip4_channel : p->ip6_channel;
|
struct channel *c = (e->n.addr->type == NET_IP4) ? p->ip4_channel : p->ip6_channel;
|
||||||
e->unreachable = 0;
|
e->unreachable = 0;
|
||||||
rte_update2(c, e->n.addr, NULL, p->p.main_source);
|
rte_update(c, e->n.addr, NULL, p->p.main_source);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2257,11 +2260,11 @@ babel_kick_timer(struct babel_proto *p)
|
|||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
babel_preexport(struct proto *P, struct rte *new)
|
babel_preexport(struct channel *c, struct rte *new)
|
||||||
{
|
{
|
||||||
struct rta *a = new->attrs;
|
struct rta *a = new->attrs;
|
||||||
/* Reject our own unreachable routes */
|
/* Reject our own unreachable routes */
|
||||||
if ((a->dest == RTD_UNREACHABLE) && (new->src->proto == P))
|
if ((a->dest == RTD_UNREACHABLE) && (new->src->proto == c->proto))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -2272,8 +2275,8 @@ babel_preexport(struct proto *P, struct rte *new)
|
|||||||
* so store it into our data structures.
|
* so store it into our data structures.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
babel_rt_notify(struct proto *P, struct channel *c UNUSED, struct network *net,
|
babel_rt_notify(struct proto *P, struct channel *c UNUSED, const net_addr *net,
|
||||||
struct rte *new, struct rte *old UNUSED)
|
struct rte *new, const struct rte *old UNUSED)
|
||||||
{
|
{
|
||||||
struct babel_proto *p = (void *) P;
|
struct babel_proto *p = (void *) P;
|
||||||
struct babel_entry *e;
|
struct babel_entry *e;
|
||||||
@ -2301,11 +2304,11 @@ babel_rt_notify(struct proto *P, struct channel *c UNUSED, struct network *net,
|
|||||||
if (rt_metric > BABEL_INFINITY)
|
if (rt_metric > BABEL_INFINITY)
|
||||||
{
|
{
|
||||||
log(L_WARN "%s: Invalid babel_metric value %u for route %N",
|
log(L_WARN "%s: Invalid babel_metric value %u for route %N",
|
||||||
p->p.name, rt_metric, net->n.addr);
|
p->p.name, rt_metric, net);
|
||||||
rt_metric = BABEL_INFINITY;
|
rt_metric = BABEL_INFINITY;
|
||||||
}
|
}
|
||||||
|
|
||||||
e = babel_get_entry(p, net->n.addr);
|
e = babel_get_entry(p, net);
|
||||||
|
|
||||||
/* Activate triggered updates */
|
/* Activate triggered updates */
|
||||||
if ((e->valid != BABEL_ENTRY_VALID) ||
|
if ((e->valid != BABEL_ENTRY_VALID) ||
|
||||||
@ -2323,7 +2326,7 @@ babel_rt_notify(struct proto *P, struct channel *c UNUSED, struct network *net,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Withdraw */
|
/* Withdraw */
|
||||||
e = babel_find_entry(p, net->n.addr);
|
e = babel_find_entry(p, net);
|
||||||
|
|
||||||
if (!e || e->valid != BABEL_ENTRY_VALID)
|
if (!e || e->valid != BABEL_ENTRY_VALID)
|
||||||
return;
|
return;
|
||||||
|
@ -336,26 +336,26 @@ bgp_aigp_set_metric(struct linpool *pool, const struct adata *ad, u64 metric)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
bgp_total_aigp_metric_(rte *e, u64 *metric, const struct adata **ad)
|
bgp_total_aigp_metric_(struct rta *a, u64 *metric, const struct adata **ad)
|
||||||
{
|
{
|
||||||
eattr *a = ea_find(e->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_AIGP));
|
eattr *ea = ea_find(a->eattrs, EA_CODE(PROTOCOL_BGP, BA_AIGP));
|
||||||
if (!a)
|
if (!ea)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
const byte *b = bgp_aigp_get_tlv(a->u.ptr, BGP_AIGP_METRIC);
|
const byte *b = bgp_aigp_get_tlv(ea->u.ptr, BGP_AIGP_METRIC);
|
||||||
if (!b)
|
if (!b)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
u64 aigp = get_u64(b + 3);
|
u64 aigp = get_u64(b + 3);
|
||||||
u64 step = e->attrs->igp_metric;
|
u64 step = a->igp_metric;
|
||||||
|
|
||||||
if (!rte_resolvable(e) || (step >= IGP_METRIC_UNKNOWN))
|
if (!rta_resolvable(a) || (step >= IGP_METRIC_UNKNOWN))
|
||||||
step = BGP_AIGP_MAX;
|
step = BGP_AIGP_MAX;
|
||||||
|
|
||||||
if (!step)
|
if (!step)
|
||||||
step = 1;
|
step = 1;
|
||||||
|
|
||||||
*ad = a->u.ptr;
|
*ad = ea->u.ptr;
|
||||||
*metric = aigp + step;
|
*metric = aigp + step;
|
||||||
if (*metric < aigp)
|
if (*metric < aigp)
|
||||||
*metric = BGP_AIGP_MAX;
|
*metric = BGP_AIGP_MAX;
|
||||||
@ -377,7 +377,7 @@ bgp_init_aigp_metric(rte *e, u64 *metric, const struct adata **ad)
|
|||||||
u32
|
u32
|
||||||
bgp_rte_igp_metric(struct rte *rt)
|
bgp_rte_igp_metric(struct rte *rt)
|
||||||
{
|
{
|
||||||
u64 metric = bgp_total_aigp_metric(rt);
|
u64 metric = bgp_total_aigp_metric(rt->attrs);
|
||||||
return (u32) MIN(metric, (u64) IGP_METRIC_UNKNOWN);
|
return (u32) MIN(metric, (u64) IGP_METRIC_UNKNOWN);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -906,7 +906,7 @@ bgp_decode_large_community(struct bgp_parse_state *s, uint code UNUSED, uint fla
|
|||||||
static void
|
static void
|
||||||
bgp_export_mpls_label_stack(struct bgp_export_state *s, eattr *a)
|
bgp_export_mpls_label_stack(struct bgp_export_state *s, eattr *a)
|
||||||
{
|
{
|
||||||
net_addr *n = s->route->net->n.addr;
|
const net_addr *n = s->route->net;
|
||||||
u32 *labels = (u32 *) a->u.ptr->data;
|
u32 *labels = (u32 *) a->u.ptr->data;
|
||||||
uint lnum = a->u.ptr->length / 4;
|
uint lnum = a->u.ptr->length / 4;
|
||||||
|
|
||||||
@ -1631,7 +1631,7 @@ bgp_free_prefix_table(struct bgp_channel *c)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static struct bgp_prefix *
|
static struct bgp_prefix *
|
||||||
bgp_get_prefix(struct bgp_channel *c, net_addr *net, u32 path_id)
|
bgp_get_prefix(struct bgp_channel *c, const net_addr *net, u32 path_id)
|
||||||
{
|
{
|
||||||
u32 hash = net_hash(net) ^ u32_hash(path_id);
|
u32 hash = net_hash(net) ^ u32_hash(path_id);
|
||||||
struct bgp_prefix *px = HASH_FIND(c->prefix_hash, PXH, net, path_id, hash);
|
struct bgp_prefix *px = HASH_FIND(c->prefix_hash, PXH, net, path_id, hash);
|
||||||
@ -1675,10 +1675,10 @@ bgp_free_prefix(struct bgp_channel *c, struct bgp_prefix *px)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
bgp_preexport(struct proto *P, rte *e)
|
bgp_preexport(struct channel *c, rte *e)
|
||||||
{
|
{
|
||||||
struct proto *SRC = e->src->proto;
|
struct proto *SRC = e->src->proto;
|
||||||
struct bgp_proto *p = (struct bgp_proto *) P;
|
struct bgp_proto *p = (struct bgp_proto *) (c->proto);
|
||||||
struct bgp_proto *src = (SRC->proto == &proto_bgp) ? (struct bgp_proto *) SRC : NULL;
|
struct bgp_proto *src = (SRC->proto == &proto_bgp) ? (struct bgp_proto *) SRC : NULL;
|
||||||
|
|
||||||
/* Reject our routes */
|
/* Reject our routes */
|
||||||
@ -1690,8 +1690,8 @@ bgp_preexport(struct proto *P, rte *e)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Reject flowspec that failed validation */
|
/* Reject flowspec that failed validation */
|
||||||
if ((e->attrs->dest == RTD_UNREACHABLE) && net_is_flow(e->net->n.addr))
|
if ((e->attrs->dest == RTD_UNREACHABLE) && net_is_flow(e->net))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* IBGP route reflection, RFC 4456 */
|
/* IBGP route reflection, RFC 4456 */
|
||||||
if (p->is_internal && src->is_internal && (p->local_as == src->local_as))
|
if (p->is_internal && src->is_internal && (p->local_as == src->local_as))
|
||||||
@ -1707,11 +1707,11 @@ bgp_preexport(struct proto *P, rte *e)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Handle well-known communities, RFC 1997 */
|
/* Handle well-known communities, RFC 1997 */
|
||||||
struct eattr *c;
|
struct eattr *com;
|
||||||
if (p->cf->interpret_communities &&
|
if (p->cf->interpret_communities &&
|
||||||
(c = ea_find(e->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_COMMUNITY))))
|
(com = ea_find(e->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_COMMUNITY))))
|
||||||
{
|
{
|
||||||
const struct adata *d = c->u.ptr;
|
const struct adata *d = com->u.ptr;
|
||||||
|
|
||||||
/* Do not export anywhere */
|
/* Do not export anywhere */
|
||||||
if (int_set_contains(d, BGP_COMM_NO_ADVERTISE))
|
if (int_set_contains(d, BGP_COMM_NO_ADVERTISE))
|
||||||
@ -1791,7 +1791,7 @@ bgp_update_attrs(struct bgp_proto *p, struct bgp_channel *c, rte *e, ea_list *at
|
|||||||
/* AIGP attribute - accumulate local metric or originate new one */
|
/* AIGP attribute - accumulate local metric or originate new one */
|
||||||
u64 metric;
|
u64 metric;
|
||||||
if (s.local_next_hop &&
|
if (s.local_next_hop &&
|
||||||
(bgp_total_aigp_metric_(e, &metric, &ad) ||
|
(bgp_total_aigp_metric_(e->attrs, &metric, &ad) ||
|
||||||
(c->cf->aigp_originate && bgp_init_aigp_metric(e, &metric, &ad))))
|
(c->cf->aigp_originate && bgp_init_aigp_metric(e, &metric, &ad))))
|
||||||
{
|
{
|
||||||
ad = bgp_aigp_set_metric(pool, ad, metric);
|
ad = bgp_aigp_set_metric(pool, ad, metric);
|
||||||
@ -1850,7 +1850,7 @@ bgp_update_attrs(struct bgp_proto *p, struct bgp_channel *c, rte *e, ea_list *at
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
bgp_rt_notify(struct proto *P, struct channel *C, net *n, rte *new, rte *old)
|
bgp_rt_notify(struct proto *P, struct channel *C, const net_addr *n, rte *new, const rte *old)
|
||||||
{
|
{
|
||||||
struct bgp_proto *p = (void *) P;
|
struct bgp_proto *p = (void *) P;
|
||||||
struct bgp_channel *c = (void *) C;
|
struct bgp_channel *c = (void *) C;
|
||||||
@ -1864,7 +1864,7 @@ bgp_rt_notify(struct proto *P, struct channel *C, net *n, rte *new, rte *old)
|
|||||||
|
|
||||||
/* Error during attribute processing */
|
/* Error during attribute processing */
|
||||||
if (!attrs)
|
if (!attrs)
|
||||||
log(L_ERR "%s: Invalid route %N withdrawn", p->p.name, n->n.addr);
|
log(L_ERR "%s: Invalid route %N withdrawn", p->p.name, n);
|
||||||
|
|
||||||
/* If attributes are invalid, we fail back to withdraw */
|
/* If attributes are invalid, we fail back to withdraw */
|
||||||
buck = attrs ? bgp_get_bucket(c, attrs) : bgp_get_withdraw_bucket(c);
|
buck = attrs ? bgp_get_bucket(c, attrs) : bgp_get_withdraw_bucket(c);
|
||||||
@ -1876,7 +1876,7 @@ bgp_rt_notify(struct proto *P, struct channel *C, net *n, rte *new, rte *old)
|
|||||||
path = old->src->global_id;
|
path = old->src->global_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
px = bgp_get_prefix(c, n->n.addr, c->add_path_tx ? path : 0);
|
px = bgp_get_prefix(c, n, c->add_path_tx ? path : 0);
|
||||||
add_tail(&buck->prefixes, &px->buck_node);
|
add_tail(&buck->prefixes, &px->buck_node);
|
||||||
|
|
||||||
bgp_schedule_packet(p->conn, c, PKT_UPDATE);
|
bgp_schedule_packet(p->conn, c, PKT_UPDATE);
|
||||||
@ -1937,8 +1937,8 @@ bgp_rte_better(rte *new, rte *old)
|
|||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
/* RFC 4271 9.1.2.1. Route resolvability test */
|
/* RFC 4271 9.1.2.1. Route resolvability test */
|
||||||
n = rte_resolvable(new);
|
n = rta_resolvable(new->attrs);
|
||||||
o = rte_resolvable(old);
|
o = rta_resolvable(old->attrs);
|
||||||
if (n > o)
|
if (n > o)
|
||||||
return 1;
|
return 1;
|
||||||
if (n < o)
|
if (n < o)
|
||||||
@ -1963,8 +1963,8 @@ bgp_rte_better(rte *new, rte *old)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* RFC 7311 4.1 - Apply AIGP metric */
|
/* RFC 7311 4.1 - Apply AIGP metric */
|
||||||
u64 n2 = bgp_total_aigp_metric(new);
|
u64 n2 = bgp_total_aigp_metric(new->attrs);
|
||||||
u64 o2 = bgp_total_aigp_metric(old);
|
u64 o2 = bgp_total_aigp_metric(old->attrs);
|
||||||
if (n2 < o2)
|
if (n2 < o2)
|
||||||
return 1;
|
return 1;
|
||||||
if (n2 > o2)
|
if (n2 > o2)
|
||||||
@ -2079,7 +2079,7 @@ bgp_rte_mergable(rte *pri, rte *sec)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* RFC 4271 9.1.2.1. Route resolvability test */
|
/* RFC 4271 9.1.2.1. Route resolvability test */
|
||||||
if (rte_resolvable(pri) != rte_resolvable(sec))
|
if (rta_resolvable(pri->attrs) != rta_resolvable(sec->attrs))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Start with local preferences */
|
/* Start with local preferences */
|
||||||
@ -2148,16 +2148,15 @@ same_group(rte *r, u32 lpref, u32 lasn)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
use_deterministic_med(rte *r)
|
use_deterministic_med(struct rte_storage *r)
|
||||||
{
|
{
|
||||||
struct proto *P = r->src->proto;
|
struct proto *P = r->rte.src->proto;
|
||||||
return (P->proto == &proto_bgp) && ((struct bgp_proto *) P)->cf->deterministic_med;
|
return (P->proto == &proto_bgp) && ((struct bgp_proto *) P)->cf->deterministic_med;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
bgp_rte_recalculate(rtable *table, net *net, rte *new, rte *old, rte *old_best)
|
bgp_rte_recalculate(rtable *table, net *net, rte *new, rte *old, rte *old_best)
|
||||||
{
|
{
|
||||||
rte *r, *s;
|
|
||||||
rte *key = new ? new : old;
|
rte *key = new ? new : old;
|
||||||
u32 lpref = key->attrs->pref;
|
u32 lpref = key->attrs->pref;
|
||||||
u32 lasn = bgp_get_neighbor(key);
|
u32 lasn = bgp_get_neighbor(key);
|
||||||
@ -2225,13 +2224,13 @@ bgp_rte_recalculate(rtable *table, net *net, rte *new, rte *old, rte *old_best)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* The default case - find a new best-in-group route */
|
/* The default case - find a new best-in-group route */
|
||||||
r = new; /* new may not be in the list */
|
rte *r = new; /* new may not be in the list */
|
||||||
for (s=net->routes; rte_is_valid(s); s=s->next)
|
for (struct rte_storage *s = net->routes; rte_is_valid(s); s = s->next)
|
||||||
if (use_deterministic_med(s) && same_group(s, lpref, lasn))
|
if (use_deterministic_med(s) && same_group(&s->rte, lpref, lasn))
|
||||||
{
|
{
|
||||||
s->pflags |= BGP_REF_SUPPRESSED;
|
s->rte.pflags |= BGP_REF_SUPPRESSED;
|
||||||
if (!r || bgp_rte_better(s, r))
|
if (!r || bgp_rte_better(&s->rte, r))
|
||||||
r = s;
|
r = &s->rte;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Simple case - the last route in group disappears */
|
/* Simple case - the last route in group disappears */
|
||||||
@ -2243,10 +2242,10 @@ bgp_rte_recalculate(rtable *table, net *net, rte *new, rte *old, rte *old_best)
|
|||||||
new->pflags &= ~BGP_REF_SUPPRESSED;
|
new->pflags &= ~BGP_REF_SUPPRESSED;
|
||||||
|
|
||||||
/* Found all existing routes mergable with best-in-group */
|
/* Found all existing routes mergable with best-in-group */
|
||||||
for (s=net->routes; rte_is_valid(s); s=s->next)
|
for (struct rte_storage *s = net->routes; rte_is_valid(s); s = s->next)
|
||||||
if (use_deterministic_med(s) && same_group(s, lpref, lasn))
|
if (use_deterministic_med(s) && same_group(&s->rte, lpref, lasn))
|
||||||
if ((s != r) && bgp_rte_mergable(r, s))
|
if ((&s->rte != r) && bgp_rte_mergable(r, &s->rte))
|
||||||
s->pflags &= ~BGP_REF_SUPPRESSED;
|
s->rte.pflags &= ~BGP_REF_SUPPRESSED;
|
||||||
|
|
||||||
/* Found best-in-group */
|
/* Found best-in-group */
|
||||||
r->pflags &= ~BGP_REF_SUPPRESSED;
|
r->pflags &= ~BGP_REF_SUPPRESSED;
|
||||||
@ -2281,12 +2280,12 @@ bgp_rte_recalculate(rtable *table, net *net, rte *new, rte *old, rte *old_best)
|
|||||||
return !old_suppressed;
|
return !old_suppressed;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct rte *
|
rte *
|
||||||
bgp_rte_modify_stale(struct rte *r, struct linpool *pool)
|
bgp_rte_modify_stale(struct rte *r, struct linpool *pool)
|
||||||
{
|
{
|
||||||
eattr *a = ea_find(r->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_COMMUNITY));
|
eattr *ea = ea_find(r->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_COMMUNITY));
|
||||||
const struct adata *ad = a ? a->u.ptr : NULL;
|
const struct adata *ad = ea ? ea->u.ptr : NULL;
|
||||||
uint flags = a ? a->flags : BAF_PARTIAL;
|
uint flags = ea ? ea->flags : BAF_PARTIAL;
|
||||||
|
|
||||||
if (ad && int_set_contains(ad, BGP_COMM_NO_LLGR))
|
if (ad && int_set_contains(ad, BGP_COMM_NO_LLGR))
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -2294,12 +2293,17 @@ bgp_rte_modify_stale(struct rte *r, struct linpool *pool)
|
|||||||
if (ad && int_set_contains(ad, BGP_COMM_LLGR_STALE))
|
if (ad && int_set_contains(ad, BGP_COMM_LLGR_STALE))
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
r = rte_cow_rta(r, pool);
|
rta *a = rta_do_cow(r->attrs, pool);
|
||||||
bgp_set_attr_ptr(&(r->attrs->eattrs), pool, BA_COMMUNITY, flags,
|
|
||||||
int_set_add(pool, ad, BGP_COMM_LLGR_STALE));
|
|
||||||
r->pflags |= BGP_REF_STALE;
|
|
||||||
|
|
||||||
return r;
|
_Thread_local static rte e0;
|
||||||
|
e0 = *r;
|
||||||
|
e0.attrs = a;
|
||||||
|
|
||||||
|
bgp_set_attr_ptr(&(a->eattrs), pool, BA_COMMUNITY, flags,
|
||||||
|
int_set_add(pool, ad, BGP_COMM_LLGR_STALE));
|
||||||
|
e0.pflags |= BGP_REF_STALE;
|
||||||
|
|
||||||
|
return &e0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2390,14 +2394,14 @@ bgp_get_route_info(rte *e, byte *buf)
|
|||||||
if (rte_stale(e))
|
if (rte_stale(e))
|
||||||
buf += bsprintf(buf, "s");
|
buf += bsprintf(buf, "s");
|
||||||
|
|
||||||
u64 metric = bgp_total_aigp_metric(e);
|
u64 metric = bgp_total_aigp_metric(e->attrs);
|
||||||
if (metric < BGP_AIGP_MAX)
|
if (metric < BGP_AIGP_MAX)
|
||||||
{
|
{
|
||||||
buf += bsprintf(buf, "/%lu", metric);
|
buf += bsprintf(buf, "/%lu", metric);
|
||||||
}
|
}
|
||||||
else if (e->attrs->igp_metric)
|
else if (e->attrs->igp_metric)
|
||||||
{
|
{
|
||||||
if (!rte_resolvable(e))
|
if (!rta_resolvable(e->attrs))
|
||||||
buf += bsprintf(buf, "/-");
|
buf += bsprintf(buf, "/-");
|
||||||
else if (e->attrs->igp_metric >= IGP_METRIC_UNKNOWN)
|
else if (e->attrs->igp_metric >= IGP_METRIC_UNKNOWN)
|
||||||
buf += bsprintf(buf, "/?");
|
buf += bsprintf(buf, "/?");
|
||||||
|
@ -518,9 +518,9 @@ struct rte_source *bgp_find_source(struct bgp_proto *p, u32 path_id);
|
|||||||
struct rte_source *bgp_get_source(struct bgp_proto *p, u32 path_id);
|
struct rte_source *bgp_get_source(struct bgp_proto *p, u32 path_id);
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
rte_resolvable(rte *rt)
|
rta_resolvable(rta *a)
|
||||||
{
|
{
|
||||||
return rt->attrs->dest != RTD_UNREACHABLE;
|
return a->dest != RTD_UNREACHABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -588,22 +588,22 @@ 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(rtable *table, net *net, rte *new, rte *old, rte *old_best);
|
||||||
struct rte *bgp_rte_modify_stale(struct rte *r, struct linpool *pool);
|
struct rte *bgp_rte_modify_stale(struct rte *r, struct linpool *pool);
|
||||||
u32 bgp_rte_igp_metric(struct rte *);
|
u32 bgp_rte_igp_metric(struct rte *);
|
||||||
void bgp_rt_notify(struct proto *P, struct channel *C, net *n, rte *new, rte *old);
|
void bgp_rt_notify(struct proto *P, struct channel *C, const net_addr *n, rte *new, const rte *old);
|
||||||
int bgp_preexport(struct proto *, struct rte *);
|
int bgp_preexport(struct channel *, struct rte *);
|
||||||
int bgp_get_attr(const struct eattr *e, byte *buf, int buflen);
|
int bgp_get_attr(const struct eattr *e, byte *buf, int buflen);
|
||||||
void bgp_get_route_info(struct rte *, byte *buf);
|
void bgp_get_route_info(struct rte *, byte *);
|
||||||
int bgp_total_aigp_metric_(rte *e, u64 *metric, const struct adata **ad);
|
int bgp_total_aigp_metric_(rta *a, u64 *metric, const struct adata **ad);
|
||||||
|
|
||||||
#define BGP_AIGP_METRIC 1
|
#define BGP_AIGP_METRIC 1
|
||||||
#define BGP_AIGP_MAX U64(0xffffffffffffffff)
|
#define BGP_AIGP_MAX U64(0xffffffffffffffff)
|
||||||
|
|
||||||
static inline u64
|
static inline u64
|
||||||
bgp_total_aigp_metric(rte *r)
|
bgp_total_aigp_metric(rta *a)
|
||||||
{
|
{
|
||||||
u64 metric = BGP_AIGP_MAX;
|
u64 metric = BGP_AIGP_MAX;
|
||||||
const struct adata *ad;
|
const struct adata *ad;
|
||||||
|
|
||||||
bgp_total_aigp_metric_(r, &metric, &ad);
|
bgp_total_aigp_metric_(a, &metric, &ad);
|
||||||
return metric;
|
return metric;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1376,7 +1376,7 @@ bgp_rte_update(struct bgp_parse_state *s, const net_addr *n, u32 path_id, rta *a
|
|||||||
REPORT("Invalid route %N withdrawn", n);
|
REPORT("Invalid route %N withdrawn", n);
|
||||||
|
|
||||||
/* Route withdraw */
|
/* Route withdraw */
|
||||||
rte_update3(&s->channel->c, n, NULL, s->last_src);
|
rte_update(&s->channel->c, n, NULL, s->last_src);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1389,11 +1389,12 @@ bgp_rte_update(struct bgp_parse_state *s, const net_addr *n, u32 path_id, rta *a
|
|||||||
a0->eattrs = ea;
|
a0->eattrs = ea;
|
||||||
}
|
}
|
||||||
|
|
||||||
rta *a = rta_clone(s->cached_rta);
|
rte e0 = {
|
||||||
rte *e = rte_get_temp(a, s->last_src);
|
.attrs = s->cached_rta,
|
||||||
|
.src = s->last_src,
|
||||||
|
};
|
||||||
|
|
||||||
e->pflags = 0;
|
rte_update(&s->channel->c, n, &e0, s->last_src);
|
||||||
rte_update3(&s->channel->c, n, e, s->last_src);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -460,7 +460,7 @@ mrt_rib_table_entry_bgp_attrs(struct mrt_table_dump_state *s, rte *r)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
mrt_log(s, "Attribute list too long for %N", r->net->n.addr);
|
mrt_log(s, "Attribute list too long for %N", r->net);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -512,24 +512,21 @@ mrt_rib_table_dump(struct mrt_table_dump_state *s, net *n, int add_path)
|
|||||||
mrt_init_message(&s->buf, MRT_TABLE_DUMP_V2, subtype);
|
mrt_init_message(&s->buf, MRT_TABLE_DUMP_V2, subtype);
|
||||||
mrt_rib_table_header(s, n->n.addr);
|
mrt_rib_table_header(s, n->n.addr);
|
||||||
|
|
||||||
rte *rt, *rt0;
|
for (struct rte_storage *rt, *rt0 = n->routes; rt = rt0; rt0 = rt0->next)
|
||||||
for (rt0 = n->routes; rt = rt0; rt0 = rt0->next)
|
|
||||||
{
|
{
|
||||||
if (rte_is_filtered(rt))
|
if (rte_is_filtered(&rt->rte))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Skip routes that should be reported in the other phase */
|
/* Skip routes that should be reported in the other phase */
|
||||||
if (!s->always_add_path && (!rt->src->private_id != !s->add_path))
|
if (!s->always_add_path && (!rt->rte.src->private_id != !s->add_path))
|
||||||
{
|
{
|
||||||
s->want_add_path = 1;
|
s->want_add_path = 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (f_run(s->filter, &rt, s->linpool, 0) <= F_ACCEPT)
|
rte e = rt->rte;
|
||||||
mrt_rib_table_entry(s, rt);
|
if (f_run(s->filter, &e, s->linpool, 0) <= F_ACCEPT)
|
||||||
|
mrt_rib_table_entry(s, &e);
|
||||||
if (rt != rt0)
|
|
||||||
rte_free(rt);
|
|
||||||
|
|
||||||
lp_flush(s->linpool);
|
lp_flush(s->linpool);
|
||||||
}
|
}
|
||||||
|
@ -107,7 +107,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "ospf.h"
|
#include "ospf.h"
|
||||||
|
|
||||||
static int ospf_preexport(struct proto *P, rte *new);
|
static int ospf_preexport(struct channel *C, rte *new);
|
||||||
static void ospf_reload_routes(struct channel *C);
|
static void ospf_reload_routes(struct channel *C);
|
||||||
static int ospf_rte_better(struct rte *new, struct rte *old);
|
static int ospf_rte_better(struct rte *new, struct rte *old);
|
||||||
static u32 ospf_rte_igp_metric(struct rte *rt);
|
static u32 ospf_rte_igp_metric(struct rte *rt);
|
||||||
@ -482,13 +482,13 @@ ospf_disp(timer * timer)
|
|||||||
* import to the filters.
|
* import to the filters.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
ospf_preexport(struct proto *P, rte *e)
|
ospf_preexport(struct channel *c, rte *e)
|
||||||
{
|
{
|
||||||
struct ospf_proto *p = (struct ospf_proto *) P;
|
struct ospf_proto *p = (struct ospf_proto *) c->proto;
|
||||||
struct ospf_area *oa = ospf_main_area(p);
|
struct ospf_area *oa = ospf_main_area(p);
|
||||||
|
|
||||||
/* Reject our own routes */
|
/* Reject our own routes */
|
||||||
if (e->src->proto == P)
|
if (e->src->proto == c->proto)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* Do not export routes to stub areas */
|
/* Do not export routes to stub areas */
|
||||||
|
@ -2096,15 +2096,18 @@ again1:
|
|||||||
.u.data = nf->n.rid,
|
.u.data = nf->n.rid,
|
||||||
};
|
};
|
||||||
|
|
||||||
rta *a = rta_lookup(&a0);
|
|
||||||
rte *e = rte_get_temp(a, p->p.main_source);
|
|
||||||
|
|
||||||
rta_free(nf->old_rta);
|
rta_free(nf->old_rta);
|
||||||
nf->old_rta = rta_clone(a);
|
nf->old_rta = rta_lookup(&a0);
|
||||||
|
|
||||||
|
rte e0 = {
|
||||||
|
.attrs = nf->old_rta,
|
||||||
|
.src = p->p.main_source,
|
||||||
|
};
|
||||||
|
|
||||||
DBG("Mod rte type %d - %N via %I on iface %s, met %d\n",
|
DBG("Mod rte type %d - %N via %I on iface %s, met %d\n",
|
||||||
a0.source, nf->fn.addr, a0.gw, a0.iface ? a0.iface->name : "(none)", nf->n.metric1);
|
a0.source, nf->fn.addr, a0.gw, a0.iface ? a0.iface->name : "(none)", nf->n.metric1);
|
||||||
rte_update(&p->p, nf->fn.addr, e);
|
|
||||||
|
rte_update(p->p.main_channel, nf->fn.addr, &e0, p->p.main_source);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (nf->old_rta)
|
else if (nf->old_rta)
|
||||||
@ -2113,7 +2116,7 @@ again1:
|
|||||||
rta_free(nf->old_rta);
|
rta_free(nf->old_rta);
|
||||||
nf->old_rta = NULL;
|
nf->old_rta = NULL;
|
||||||
|
|
||||||
rte_update(&p->p, nf->fn.addr, NULL);
|
rte_update(p->p.main_channel, nf->fn.addr, NULL, p->p.main_source);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Remove unused rt entry, some special entries are persistent */
|
/* Remove unused rt entry, some special entries are persistent */
|
||||||
@ -2129,7 +2132,6 @@ again1:
|
|||||||
}
|
}
|
||||||
FIB_ITERATE_END;
|
FIB_ITERATE_END;
|
||||||
|
|
||||||
|
|
||||||
WALK_LIST(oa, p->area_list)
|
WALK_LIST(oa, p->area_list)
|
||||||
{
|
{
|
||||||
/* Cleanup ASBR hash tables */
|
/* Cleanup ASBR hash tables */
|
||||||
|
@ -1300,7 +1300,7 @@ find_surrogate_fwaddr(struct ospf_proto *p, struct ospf_area *oa)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ospf_rt_notify(struct proto *P, struct channel *ch UNUSED, net *n, rte *new, rte *old UNUSED)
|
ospf_rt_notify(struct proto *P, struct channel *ch UNUSED, const net_addr *n, rte *new, const rte *old UNUSED)
|
||||||
{
|
{
|
||||||
struct ospf_proto *p = (struct ospf_proto *) P;
|
struct ospf_proto *p = (struct ospf_proto *) P;
|
||||||
struct ospf_area *oa = NULL; /* non-NULL for NSSA-LSA */
|
struct ospf_area *oa = NULL; /* non-NULL for NSSA-LSA */
|
||||||
@ -1319,7 +1319,7 @@ ospf_rt_notify(struct proto *P, struct channel *ch UNUSED, net *n, rte *new, rte
|
|||||||
|
|
||||||
if (!new)
|
if (!new)
|
||||||
{
|
{
|
||||||
nf = fib_find(&p->rtf, n->n.addr);
|
nf = fib_find(&p->rtf, n);
|
||||||
|
|
||||||
if (!nf || !nf->external_rte)
|
if (!nf || !nf->external_rte)
|
||||||
return;
|
return;
|
||||||
@ -1346,14 +1346,14 @@ ospf_rt_notify(struct proto *P, struct channel *ch UNUSED, net *n, rte *new, rte
|
|||||||
if (m1 > LSINFINITY)
|
if (m1 > LSINFINITY)
|
||||||
{
|
{
|
||||||
log(L_WARN "%s: Invalid ospf_metric1 value %u for route %N",
|
log(L_WARN "%s: Invalid ospf_metric1 value %u for route %N",
|
||||||
p->p.name, m1, n->n.addr);
|
p->p.name, m1, n);
|
||||||
m1 = LSINFINITY;
|
m1 = LSINFINITY;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m2 > LSINFINITY)
|
if (m2 > LSINFINITY)
|
||||||
{
|
{
|
||||||
log(L_WARN "%s: Invalid ospf_metric2 value %u for route %N",
|
log(L_WARN "%s: Invalid ospf_metric2 value %u for route %N",
|
||||||
p->p.name, m2, n->n.addr);
|
p->p.name, m2, n);
|
||||||
m2 = LSINFINITY;
|
m2 = LSINFINITY;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1377,12 +1377,12 @@ ospf_rt_notify(struct proto *P, struct channel *ch UNUSED, net *n, rte *new, rte
|
|||||||
if (ipa_zero(fwd))
|
if (ipa_zero(fwd))
|
||||||
{
|
{
|
||||||
log(L_ERR "%s: Cannot find forwarding address for NSSA-LSA %N",
|
log(L_ERR "%s: Cannot find forwarding address for NSSA-LSA %N",
|
||||||
p->p.name, n->n.addr);
|
p->p.name, n);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nf = fib_get(&p->rtf, n->n.addr);
|
nf = fib_get(&p->rtf, n);
|
||||||
ospf_originate_ext_lsa(p, oa, nf, LSA_M_EXPORT, metric, ebit, fwd, tag, 1, p->vpn_pe);
|
ospf_originate_ext_lsa(p, oa, nf, LSA_M_EXPORT, metric, ebit, fwd, tag, 1, p->vpn_pe);
|
||||||
nf->external_rte = 1;
|
nf->external_rte = 1;
|
||||||
}
|
}
|
||||||
|
@ -200,7 +200,7 @@ void ospf_originate_sum_rt_lsa(struct ospf_proto *p, struct ospf_area *oa, u32 d
|
|||||||
void ospf_originate_ext_lsa(struct ospf_proto *p, struct ospf_area *oa, ort *nf, u8 mode, u32 metric, u32 ebit, ip_addr fwaddr, u32 tag, int pbit, int dn);
|
void ospf_originate_ext_lsa(struct ospf_proto *p, struct ospf_area *oa, ort *nf, u8 mode, u32 metric, u32 ebit, ip_addr fwaddr, u32 tag, int pbit, int dn);
|
||||||
void ospf_originate_gr_lsa(struct ospf_proto *p, struct ospf_iface *ifa);
|
void ospf_originate_gr_lsa(struct ospf_proto *p, struct ospf_iface *ifa);
|
||||||
|
|
||||||
void ospf_rt_notify(struct proto *P, struct channel *ch, net *n, rte *new, rte *old);
|
void ospf_rt_notify(struct proto *P, struct channel *ch, const net_addr *n, rte *new, const rte *old);
|
||||||
void ospf_update_topology(struct ospf_proto *p);
|
void ospf_update_topology(struct ospf_proto *p);
|
||||||
|
|
||||||
struct top_hash_entry *ospf_hash_find(struct top_graph *, u32 domain, u32 lsa, u32 rtr, u32 type);
|
struct top_hash_entry *ospf_hash_find(struct top_graph *, u32 domain, u32 lsa, u32 rtr, u32 type);
|
||||||
|
@ -160,18 +160,17 @@ perf_loop(void *data)
|
|||||||
|
|
||||||
clock_gettime(CLOCK_MONOTONIC, &ts_generated);
|
clock_gettime(CLOCK_MONOTONIC, &ts_generated);
|
||||||
|
|
||||||
for (uint i=0; i<N; i++) {
|
for (uint i=0; i<N; i++)
|
||||||
rte *e = rte_get_temp(p->data[i].a, p->p.main_source);
|
{
|
||||||
e->pflags = 0;
|
rte e0 = { .attrs = p->data[i].a, .src = P->main_source, };
|
||||||
|
rte_update(P->main_channel, &(p->data[i].net), &e0, P->main_source);
|
||||||
rte_update(P, &(p->data[i].net), e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
clock_gettime(CLOCK_MONOTONIC, &ts_update);
|
clock_gettime(CLOCK_MONOTONIC, &ts_update);
|
||||||
|
|
||||||
if (!p->keep)
|
if (!p->keep)
|
||||||
for (uint i=0; i<N; i++)
|
for (uint i=0; i<N; i++)
|
||||||
rte_update(P, &(p->data[i].net), NULL);
|
rte_update(P->main_channel, &(p->data[i].net), NULL, P->main_source);
|
||||||
|
|
||||||
clock_gettime(CLOCK_MONOTONIC, &ts_withdraw);
|
clock_gettime(CLOCK_MONOTONIC, &ts_withdraw);
|
||||||
|
|
||||||
@ -204,7 +203,7 @@ perf_loop(void *data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
perf_rt_notify(struct proto *P, struct channel *c UNUSED, struct network *net UNUSED, struct rte *new UNUSED, struct rte *old UNUSED)
|
perf_rt_notify(struct proto *P, struct channel *c UNUSED, const net_addr *net UNUSED, struct rte *new UNUSED, const struct rte *old UNUSED)
|
||||||
{
|
{
|
||||||
struct perf_proto *p = (struct perf_proto *) P;
|
struct perf_proto *p = (struct perf_proto *) P;
|
||||||
p->exp++;
|
p->exp++;
|
||||||
|
@ -48,14 +48,10 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void
|
static void
|
||||||
pipe_rt_notify(struct proto *P, struct channel *src_ch, net *n, rte *new, rte *old)
|
pipe_rt_notify(struct proto *P, struct channel *src_ch, const net_addr *n, rte *new, const rte *old)
|
||||||
{
|
{
|
||||||
struct pipe_proto *p = (void *) P;
|
struct pipe_proto *p = (void *) P;
|
||||||
struct channel *dst = (src_ch == p->pri) ? p->sec : p->pri;
|
struct channel *dst = (src_ch == p->pri) ? p->sec : p->pri;
|
||||||
struct rte_src *src;
|
|
||||||
|
|
||||||
rte *e;
|
|
||||||
rta *a;
|
|
||||||
|
|
||||||
if (!new && !old)
|
if (!new && !old)
|
||||||
return;
|
return;
|
||||||
@ -63,45 +59,39 @@ pipe_rt_notify(struct proto *P, struct channel *src_ch, net *n, rte *new, rte *o
|
|||||||
if (dst->table->pipe_busy)
|
if (dst->table->pipe_busy)
|
||||||
{
|
{
|
||||||
log(L_ERR "Pipe loop detected when sending %N to table %s",
|
log(L_ERR "Pipe loop detected when sending %N to table %s",
|
||||||
n->n.addr, dst->table->name);
|
n, dst->table->name);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
src_ch->table->pipe_busy = 1;
|
||||||
|
|
||||||
if (new)
|
if (new)
|
||||||
{
|
{
|
||||||
src = new->src;
|
rta *a = alloca(rta_size(new->attrs));
|
||||||
|
|
||||||
a = alloca(rta_size(new->attrs));
|
|
||||||
memcpy(a, new->attrs, rta_size(new->attrs));
|
memcpy(a, new->attrs, rta_size(new->attrs));
|
||||||
|
|
||||||
a->cached = 0;
|
a->cached = 0;
|
||||||
a->hostentry = NULL;
|
a->hostentry = NULL;
|
||||||
e = rte_get_temp(a, src);
|
|
||||||
e->pflags = new->pflags;
|
|
||||||
|
|
||||||
#ifdef CONFIG_BGP
|
rte e0 = {
|
||||||
/* Hack to cleanup cached value */
|
.attrs = a,
|
||||||
if (e->src->proto->proto == &proto_bgp)
|
.src = new->src,
|
||||||
e->pflags &= ~(BGP_REF_STALE | BGP_REF_NOT_STALE);
|
};
|
||||||
#endif
|
|
||||||
|
rte_update(dst, n, &e0, new->src);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
rte_update(dst, n, NULL, old->src);
|
||||||
e = NULL;
|
|
||||||
src = old->src;
|
|
||||||
}
|
|
||||||
|
|
||||||
src_ch->table->pipe_busy = 1;
|
|
||||||
rte_update2(dst, n->n.addr, e, src);
|
|
||||||
src_ch->table->pipe_busy = 0;
|
src_ch->table->pipe_busy = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
pipe_preexport(struct proto *P, rte *e)
|
pipe_preexport(struct channel *c, rte *e)
|
||||||
{
|
{
|
||||||
struct proto *pp = e->sender->proto;
|
struct proto *pp = e->sender->proto;
|
||||||
|
|
||||||
if (pp == P)
|
if (pp == c->proto)
|
||||||
return -1; /* Avoid local loops automatically */
|
return -1; /* Avoid local loops automatically */
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -385,16 +385,16 @@ radv_trigger_valid(struct radv_config *cf)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
radv_net_match_trigger(struct radv_config *cf, net *n)
|
radv_net_match_trigger(struct radv_config *cf, const net_addr *n)
|
||||||
{
|
{
|
||||||
return radv_trigger_valid(cf) && net_equal(n->n.addr, &cf->trigger);
|
return radv_trigger_valid(cf) && net_equal(n, &cf->trigger);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
radv_preexport(struct proto *P, rte *new)
|
radv_preexport(struct channel *c, rte *new)
|
||||||
{
|
{
|
||||||
// struct radv_proto *p = (struct radv_proto *) P;
|
// struct radv_proto *p = (struct radv_proto *) P;
|
||||||
struct radv_config *cf = (struct radv_config *) (P->cf);
|
struct radv_config *cf = (struct radv_config *) (c->proto->cf);
|
||||||
|
|
||||||
if (radv_net_match_trigger(cf, new->net))
|
if (radv_net_match_trigger(cf, new->net))
|
||||||
return RIC_PROCESS;
|
return RIC_PROCESS;
|
||||||
@ -406,7 +406,7 @@ radv_preexport(struct proto *P, rte *new)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
radv_rt_notify(struct proto *P, struct channel *ch UNUSED, net *n, rte *new, rte *old UNUSED)
|
radv_rt_notify(struct proto *P, struct channel *ch UNUSED, const net_addr *n, rte *new, const rte *old UNUSED)
|
||||||
{
|
{
|
||||||
struct radv_proto *p = (struct radv_proto *) P;
|
struct radv_proto *p = (struct radv_proto *) P;
|
||||||
struct radv_config *cf = (struct radv_config *) (P->cf);
|
struct radv_config *cf = (struct radv_config *) (P->cf);
|
||||||
@ -457,14 +457,14 @@ radv_rt_notify(struct proto *P, struct channel *ch UNUSED, net *n, rte *new, rte
|
|||||||
(preference != RA_PREF_HIGH))
|
(preference != RA_PREF_HIGH))
|
||||||
{
|
{
|
||||||
log(L_WARN "%s: Invalid ra_preference value %u on route %N",
|
log(L_WARN "%s: Invalid ra_preference value %u on route %N",
|
||||||
p->p.name, preference, n->n.addr);
|
p->p.name, preference, n);
|
||||||
preference = RA_PREF_MEDIUM;
|
preference = RA_PREF_MEDIUM;
|
||||||
preference_set = 1;
|
preference_set = 1;
|
||||||
lifetime = 0;
|
lifetime = 0;
|
||||||
lifetime_set = 1;
|
lifetime_set = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
rt = fib_get(&p->routes, n->n.addr);
|
rt = fib_get(&p->routes, n);
|
||||||
|
|
||||||
/* Ignore update if nothing changed */
|
/* Ignore update if nothing changed */
|
||||||
if (rt->valid &&
|
if (rt->valid &&
|
||||||
@ -487,7 +487,7 @@ radv_rt_notify(struct proto *P, struct channel *ch UNUSED, net *n, rte *new, rte
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Withdraw */
|
/* Withdraw */
|
||||||
rt = fib_find(&p->routes, n->n.addr);
|
rt = fib_find(&p->routes, n);
|
||||||
|
|
||||||
if (!rt || !rt->valid)
|
if (!rt || !rt->valid)
|
||||||
return;
|
return;
|
||||||
@ -555,7 +555,7 @@ radv_check_active(struct radv_proto *p)
|
|||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
struct channel *c = p->p.main_channel;
|
struct channel *c = p->p.main_channel;
|
||||||
return rt_examine(c->table, &cf->trigger, &p->p, c->out_filter);
|
return rt_examine(c->table, &cf->trigger, c, c->out_filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -207,16 +207,15 @@ rip_announce_rte(struct rip_proto *p, struct rip_entry *en)
|
|||||||
.u.data = (uintptr_t) a0.nh.iface,
|
.u.data = (uintptr_t) a0.nh.iface,
|
||||||
};
|
};
|
||||||
|
|
||||||
rta *a = rta_lookup(&a0);
|
rte e0 = {
|
||||||
rte *e = rte_get_temp(a, p->p.main_source);
|
.attrs = &a0,
|
||||||
|
.src = p->p.main_source,
|
||||||
|
};
|
||||||
|
|
||||||
rte_update(&p->p, en->n.addr, e);
|
rte_update(p->p.main_channel, en->n.addr, &e0, p->p.main_source);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
rte_update(p->p.main_channel, en->n.addr, NULL, p->p.main_source);
|
||||||
/* Withdraw */
|
|
||||||
rte_update(&p->p, en->n.addr, NULL);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -311,8 +310,8 @@ rip_withdraw_rte(struct rip_proto *p, net_addr *n, struct rip_neighbor *from)
|
|||||||
* it into our data structures.
|
* it into our data structures.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
rip_rt_notify(struct proto *P, struct channel *ch UNUSED, struct network *net, struct rte *new,
|
rip_rt_notify(struct proto *P, struct channel *ch UNUSED, const net_addr *net, struct rte *new,
|
||||||
struct rte *old UNUSED)
|
const struct rte *old UNUSED)
|
||||||
{
|
{
|
||||||
struct rip_proto *p = (struct rip_proto *) P;
|
struct rip_proto *p = (struct rip_proto *) P;
|
||||||
struct rip_entry *en;
|
struct rip_entry *en;
|
||||||
@ -328,14 +327,14 @@ rip_rt_notify(struct proto *P, struct channel *ch UNUSED, struct network *net, s
|
|||||||
if (rt_metric > p->infinity)
|
if (rt_metric > p->infinity)
|
||||||
{
|
{
|
||||||
log(L_WARN "%s: Invalid rip_metric value %u for route %N",
|
log(L_WARN "%s: Invalid rip_metric value %u for route %N",
|
||||||
p->p.name, rt_metric, net->n.addr);
|
p->p.name, rt_metric, net);
|
||||||
rt_metric = p->infinity;
|
rt_metric = p->infinity;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rt_tag > 0xffff)
|
if (rt_tag > 0xffff)
|
||||||
{
|
{
|
||||||
log(L_WARN "%s: Invalid rip_tag value %u for route %N",
|
log(L_WARN "%s: Invalid rip_tag value %u for route %N",
|
||||||
p->p.name, rt_tag, net->n.addr);
|
p->p.name, rt_tag, net);
|
||||||
rt_metric = p->infinity;
|
rt_metric = p->infinity;
|
||||||
rt_tag = 0;
|
rt_tag = 0;
|
||||||
}
|
}
|
||||||
@ -347,7 +346,7 @@ rip_rt_notify(struct proto *P, struct channel *ch UNUSED, struct network *net, s
|
|||||||
* collection.
|
* collection.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
en = fib_get(&p->rtable, net->n.addr);
|
en = fib_get(&p->rtable, net);
|
||||||
|
|
||||||
old_metric = en->valid ? en->metric : -1;
|
old_metric = en->valid ? en->metric : -1;
|
||||||
|
|
||||||
@ -361,7 +360,7 @@ rip_rt_notify(struct proto *P, struct channel *ch UNUSED, struct network *net, s
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Withdraw */
|
/* Withdraw */
|
||||||
en = fib_find(&p->rtable, net->n.addr);
|
en = fib_find(&p->rtable, net);
|
||||||
|
|
||||||
if (!en || en->valid != RIP_ENTRY_VALID)
|
if (!en || en->valid != RIP_ENTRY_VALID)
|
||||||
return;
|
return;
|
||||||
|
@ -127,19 +127,16 @@ rpki_table_add_roa(struct rpki_cache *cache, struct channel *channel, const net_
|
|||||||
.dest = RTD_NONE,
|
.dest = RTD_NONE,
|
||||||
};
|
};
|
||||||
|
|
||||||
rta *a = rta_lookup(&a0);
|
rte e0 = { .attrs = &a0, .src = p->p.main_source, };
|
||||||
rte *e = rte_get_temp(a, p->p.main_source);
|
|
||||||
|
|
||||||
e->pflags = 0;
|
rte_update(channel, &pfxr->n, &e0, p->p.main_source);
|
||||||
|
|
||||||
rte_update2(channel, &pfxr->n, e, e->src);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
rpki_table_remove_roa(struct rpki_cache *cache, struct channel *channel, const net_addr_union *pfxr)
|
rpki_table_remove_roa(struct rpki_cache *cache, struct channel *channel, const net_addr_union *pfxr)
|
||||||
{
|
{
|
||||||
struct rpki_proto *p = cache->p;
|
struct rpki_proto *p = cache->p;
|
||||||
rte_update2(channel, &pfxr->n, NULL, p->p.main_source);
|
rte_update(channel, &pfxr->n, NULL, p->p.main_source);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -103,24 +103,13 @@ static_announce_rte(struct static_proto *p, struct static_route *r)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
/* We skip rta_lookup() here */
|
/* We skip rta_lookup() here */
|
||||||
rte *e = rte_get_temp(a, src);
|
rte e0 = { .attrs = a, .src = src, .net = r->net, }, *e = &e0;
|
||||||
e->pflags = 0;
|
|
||||||
|
|
||||||
|
/* Evaluate the filter */
|
||||||
if (r->cmds)
|
if (r->cmds)
|
||||||
{
|
f_eval_rte(r->cmds, e, static_lp);
|
||||||
/* Create a temporary table node */
|
|
||||||
e->net = alloca(sizeof(net) + r->net->length);
|
|
||||||
memset(e->net, 0, sizeof(net) + r->net->length);
|
|
||||||
net_copy(e->net->n.addr, r->net);
|
|
||||||
|
|
||||||
/* Evaluate the filter */
|
rte_update(p->p.main_channel, r->net, e, src);
|
||||||
f_eval_rte(r->cmds, &e, static_lp);
|
|
||||||
|
|
||||||
/* Remove the temporary node */
|
|
||||||
e->net = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
rte_update2(p->p.main_channel, r->net, e, src);
|
|
||||||
r->state = SRS_CLEAN;
|
r->state = SRS_CLEAN;
|
||||||
|
|
||||||
if (r->cmds)
|
if (r->cmds)
|
||||||
@ -132,7 +121,7 @@ withdraw:
|
|||||||
if (r->state == SRS_DOWN)
|
if (r->state == SRS_DOWN)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
rte_update2(p->p.main_channel, r->net, NULL, src);
|
rte_update(p->p.main_channel, r->net, NULL, src);
|
||||||
r->state = SRS_DOWN;
|
r->state = SRS_DOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -298,7 +287,7 @@ static void
|
|||||||
static_remove_rte(struct static_proto *p, struct static_route *r)
|
static_remove_rte(struct static_proto *p, struct static_route *r)
|
||||||
{
|
{
|
||||||
if (r->state)
|
if (r->state)
|
||||||
rte_update2(p->p.main_channel, r->net, NULL, static_get_source(p, r->index));
|
rte_update(p->p.main_channel, r->net, NULL, static_get_source(p, r->index));
|
||||||
|
|
||||||
static_reset_rte(p, r);
|
static_reset_rte(p, r);
|
||||||
}
|
}
|
||||||
|
@ -398,7 +398,6 @@ krt_read_route(struct ks_msg *msg, struct krt_proto *p, int scan)
|
|||||||
/* p is NULL iff KRT_SHARED_SOCKET and !scan */
|
/* p is NULL iff KRT_SHARED_SOCKET and !scan */
|
||||||
|
|
||||||
int ipv6;
|
int ipv6;
|
||||||
rte *e;
|
|
||||||
net *net;
|
net *net;
|
||||||
sockaddr dst, gate, mask;
|
sockaddr dst, gate, mask;
|
||||||
ip_addr idst, igate, imask;
|
ip_addr idst, igate, imask;
|
||||||
@ -519,7 +518,6 @@ krt_read_route(struct ks_msg *msg, struct krt_proto *p, int scan)
|
|||||||
net = net_get(p->p.main_channel->table, &ndst);
|
net = net_get(p->p.main_channel->table, &ndst);
|
||||||
|
|
||||||
rta a = {
|
rta a = {
|
||||||
.src = p->p.main_source,
|
|
||||||
.source = RTS_INHERIT,
|
.source = RTS_INHERIT,
|
||||||
.scope = SCOPE_UNIVERSE,
|
.scope = SCOPE_UNIVERSE,
|
||||||
};
|
};
|
||||||
@ -579,13 +577,12 @@ krt_read_route(struct ks_msg *msg, struct krt_proto *p, int scan)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
done:;
|
||||||
e = rte_get_temp(&a);
|
rte e0 = { .attrs = &a, .net = net, };
|
||||||
e->net = net;
|
|
||||||
|
|
||||||
ea_list *ea = alloca(sizeof(ea_list) + 1 * sizeof(eattr));
|
ea_list *ea = alloca(sizeof(ea_list) + 1 * sizeof(eattr));
|
||||||
*ea = (ea_list) { .count = 1, .next = e->attrs->eattrs };
|
*ea = (ea_list) { .count = 1, .next = e0.attrs->eattrs };
|
||||||
e->attrs->eattrs = ea;
|
e0.attrs->eattrs = ea;
|
||||||
|
|
||||||
ea->attrs[0] = (eattr) {
|
ea->attrs[0] = (eattr) {
|
||||||
.id = EA_KRT_SOURCE,
|
.id = EA_KRT_SOURCE,
|
||||||
@ -594,9 +591,9 @@ krt_read_route(struct ks_msg *msg, struct krt_proto *p, int scan)
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (scan)
|
if (scan)
|
||||||
krt_got_route(p, e, src);
|
krt_got_route(p, &e0, src);
|
||||||
else
|
else
|
||||||
krt_got_route_async(p, e, new, src);
|
krt_got_route_async(p, &e0, new, src);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -109,7 +109,7 @@ struct nl_parse_state
|
|||||||
int scan;
|
int scan;
|
||||||
int merge;
|
int merge;
|
||||||
|
|
||||||
net *net;
|
net_addr *net;
|
||||||
rta *attrs;
|
rta *attrs;
|
||||||
struct krt_proto *proto;
|
struct krt_proto *proto;
|
||||||
s8 new;
|
s8 new;
|
||||||
@ -1325,10 +1325,9 @@ nh_bufsize(struct nexthop *nh)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
nl_send_route(struct krt_proto *p, rte *e, int op, int dest, struct nexthop *nh)
|
nl_send_route(struct krt_proto *p, const rte *e, int op, int dest, struct nexthop *nh)
|
||||||
{
|
{
|
||||||
eattr *ea;
|
eattr *ea;
|
||||||
net *net = e->net;
|
|
||||||
rta *a = e->attrs;
|
rta *a = e->attrs;
|
||||||
ea_list *eattrs = a->eattrs;
|
ea_list *eattrs = a->eattrs;
|
||||||
int bufsize = 128 + KRT_METRICS_MAX*8 + nh_bufsize(&(a->nh));
|
int bufsize = 128 + KRT_METRICS_MAX*8 + nh_bufsize(&(a->nh));
|
||||||
@ -1343,7 +1342,7 @@ nl_send_route(struct krt_proto *p, rte *e, int op, int dest, struct nexthop *nh)
|
|||||||
int rsize = sizeof(*r) + bufsize;
|
int rsize = sizeof(*r) + bufsize;
|
||||||
r = alloca(rsize);
|
r = alloca(rsize);
|
||||||
|
|
||||||
DBG("nl_send_route(%N,op=%x)\n", net->n.addr, op);
|
DBG("nl_send_route(%N,op=%x)\n", e->net, op);
|
||||||
|
|
||||||
bzero(&r->h, sizeof(r->h));
|
bzero(&r->h, sizeof(r->h));
|
||||||
bzero(&r->r, sizeof(r->r));
|
bzero(&r->r, sizeof(r->r));
|
||||||
@ -1352,7 +1351,7 @@ nl_send_route(struct krt_proto *p, rte *e, int op, int dest, struct nexthop *nh)
|
|||||||
r->h.nlmsg_flags = op | NLM_F_REQUEST | NLM_F_ACK;
|
r->h.nlmsg_flags = op | NLM_F_REQUEST | NLM_F_ACK;
|
||||||
|
|
||||||
r->r.rtm_family = p->af;
|
r->r.rtm_family = p->af;
|
||||||
r->r.rtm_dst_len = net_pxlen(net->n.addr);
|
r->r.rtm_dst_len = net_pxlen(e->net);
|
||||||
r->r.rtm_protocol = RTPROT_BIRD;
|
r->r.rtm_protocol = RTPROT_BIRD;
|
||||||
r->r.rtm_scope = RT_SCOPE_NOWHERE;
|
r->r.rtm_scope = RT_SCOPE_NOWHERE;
|
||||||
#ifdef HAVE_MPLS_KERNEL
|
#ifdef HAVE_MPLS_KERNEL
|
||||||
@ -1364,7 +1363,7 @@ nl_send_route(struct krt_proto *p, rte *e, int op, int dest, struct nexthop *nh)
|
|||||||
* 2) Never use RTA_PRIORITY
|
* 2) Never use RTA_PRIORITY
|
||||||
*/
|
*/
|
||||||
|
|
||||||
u32 label = net_mpls(net->n.addr);
|
u32 label = net_mpls(e->net);
|
||||||
nl_add_attr_mpls(&r->h, rsize, RTA_DST, 1, &label);
|
nl_add_attr_mpls(&r->h, rsize, RTA_DST, 1, &label);
|
||||||
r->r.rtm_scope = RT_SCOPE_UNIVERSE;
|
r->r.rtm_scope = RT_SCOPE_UNIVERSE;
|
||||||
r->r.rtm_type = RTN_UNICAST;
|
r->r.rtm_type = RTN_UNICAST;
|
||||||
@ -1372,12 +1371,12 @@ nl_send_route(struct krt_proto *p, rte *e, int op, int dest, struct nexthop *nh)
|
|||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
nl_add_attr_ipa(&r->h, rsize, RTA_DST, net_prefix(net->n.addr));
|
nl_add_attr_ipa(&r->h, rsize, RTA_DST, net_prefix(e->net));
|
||||||
|
|
||||||
/* Add source address for IPv6 SADR routes */
|
/* Add source address for IPv6 SADR routes */
|
||||||
if (net->n.addr->type == NET_IP6_SADR)
|
if (e->net->type == NET_IP6_SADR)
|
||||||
{
|
{
|
||||||
net_addr_ip6_sadr *a = (void *) &net->n.addr;
|
net_addr_ip6_sadr *a = (void *) &e->net;
|
||||||
nl_add_attr_ip6(&r->h, rsize, RTA_SRC, a->src_prefix);
|
nl_add_attr_ip6(&r->h, rsize, RTA_SRC, a->src_prefix);
|
||||||
r->r.rtm_src_len = a->src_pxlen;
|
r->r.rtm_src_len = a->src_pxlen;
|
||||||
}
|
}
|
||||||
@ -1498,7 +1497,7 @@ nl_add_rte(struct krt_proto *p, rte *e)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
nl_delete_rte(struct krt_proto *p, rte *e)
|
nl_delete_rte(struct krt_proto *p, const rte *e)
|
||||||
{
|
{
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
@ -1519,7 +1518,7 @@ nl_replace_rte(struct krt_proto *p, rte *e)
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
krt_replace_rte(struct krt_proto *p, net *n UNUSED, rte *new, rte *old)
|
krt_replace_rte(struct krt_proto *p, const net_addr *n UNUSED, rte *new, const rte *old)
|
||||||
{
|
{
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
@ -1558,7 +1557,7 @@ krt_replace_rte(struct krt_proto *p, net *n UNUSED, rte *new, rte *old)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
nl_mergable_route(struct nl_parse_state *s, net *net, struct krt_proto *p, uint priority, uint krt_type, uint rtm_family)
|
nl_mergable_route(struct nl_parse_state *s, const net_addr *net, struct krt_proto *p, uint priority, uint krt_type, uint rtm_family)
|
||||||
{
|
{
|
||||||
/* Route merging is used for IPv6 scans */
|
/* Route merging is used for IPv6 scans */
|
||||||
if (!s->scan || (rtm_family != AF_INET6))
|
if (!s->scan || (rtm_family != AF_INET6))
|
||||||
@ -1578,12 +1577,14 @@ nl_mergable_route(struct nl_parse_state *s, net *net, struct krt_proto *p, uint
|
|||||||
static void
|
static void
|
||||||
nl_announce_route(struct nl_parse_state *s)
|
nl_announce_route(struct nl_parse_state *s)
|
||||||
{
|
{
|
||||||
rte *e = rte_get_temp(s->attrs, s->proto->p.main_source);
|
rte e0 = {
|
||||||
e->net = s->net;
|
.attrs = s->attrs,
|
||||||
|
.net = s->net,
|
||||||
|
};
|
||||||
|
|
||||||
ea_list *ea = alloca(sizeof(ea_list) + 2 * sizeof(eattr));
|
ea_list *ea = alloca(sizeof(ea_list) + 2 * sizeof(eattr));
|
||||||
*ea = (ea_list) { .count = 2, .next = e->attrs->eattrs };
|
*ea = (ea_list) { .count = 2, .next = e0.attrs->eattrs };
|
||||||
e->attrs->eattrs = ea;
|
e0.attrs->eattrs = ea;
|
||||||
|
|
||||||
ea->attrs[0] = (eattr) {
|
ea->attrs[0] = (eattr) {
|
||||||
.id = EA_KRT_SOURCE,
|
.id = EA_KRT_SOURCE,
|
||||||
@ -1597,9 +1598,9 @@ nl_announce_route(struct nl_parse_state *s)
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (s->scan)
|
if (s->scan)
|
||||||
krt_got_route(s->proto, e, s->krt_src);
|
krt_got_route(s->proto, &e0, s->krt_src);
|
||||||
else
|
else
|
||||||
krt_got_route_async(s->proto, e, s->new, s->krt_src);
|
krt_got_route_async(s->proto, &e0, s->new, s->krt_src);
|
||||||
|
|
||||||
s->net = NULL;
|
s->net = NULL;
|
||||||
s->attrs = NULL;
|
s->attrs = NULL;
|
||||||
@ -1749,16 +1750,14 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h)
|
|||||||
krt_src = KRT_SRC_ALIEN;
|
krt_src = KRT_SRC_ALIEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
net_addr *n = &dst;
|
net_addr *net = &dst;
|
||||||
if (p->p.net_type == NET_IP6_SADR)
|
if (p->p.net_type == NET_IP6_SADR)
|
||||||
{
|
{
|
||||||
n = alloca(sizeof(net_addr_ip6_sadr));
|
net = alloca(sizeof(net_addr_ip6_sadr));
|
||||||
net_fill_ip6_sadr(n, net6_prefix(&dst), net6_pxlen(&dst),
|
net_fill_ip6_sadr(net, net6_prefix(&dst), net6_pxlen(&dst),
|
||||||
net6_prefix(&src), net6_pxlen(&src));
|
net6_prefix(&src), net6_pxlen(&src));
|
||||||
}
|
}
|
||||||
|
|
||||||
net *net = net_get(p->p.main_channel->table, n);
|
|
||||||
|
|
||||||
if (s->net && !nl_mergable_route(s, net, p, priority, i->rtm_type, i->rtm_family))
|
if (s->net && !nl_mergable_route(s, net, p, priority, i->rtm_type, i->rtm_family))
|
||||||
nl_announce_route(s);
|
nl_announce_route(s);
|
||||||
|
|
||||||
@ -1778,7 +1777,7 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h)
|
|||||||
|
|
||||||
if (a[RTA_MULTIPATH])
|
if (a[RTA_MULTIPATH])
|
||||||
{
|
{
|
||||||
struct nexthop *nh = nl_parse_multipath(s, p, n, a[RTA_MULTIPATH], i->rtm_family, krt_src);
|
struct nexthop *nh = nl_parse_multipath(s, p, net, a[RTA_MULTIPATH], i->rtm_family, krt_src);
|
||||||
if (!nh)
|
if (!nh)
|
||||||
SKIP("strange RTA_MULTIPATH\n");
|
SKIP("strange RTA_MULTIPATH\n");
|
||||||
|
|
||||||
@ -1792,7 +1791,7 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h)
|
|||||||
ra->nh.iface = if_find_by_index(oif);
|
ra->nh.iface = if_find_by_index(oif);
|
||||||
if (!ra->nh.iface)
|
if (!ra->nh.iface)
|
||||||
{
|
{
|
||||||
log(L_ERR "KRT: Received route %N with unknown ifindex %u", net->n.addr, oif);
|
log(L_ERR "KRT: Received route %N with unknown ifindex %u", net, oif);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1819,8 +1818,7 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h)
|
|||||||
(ra->nh.flags & RNF_ONLINK) ? NEF_ONLINK : 0);
|
(ra->nh.flags & RNF_ONLINK) ? NEF_ONLINK : 0);
|
||||||
if (!nbr || (nbr->scope == SCOPE_HOST))
|
if (!nbr || (nbr->scope == SCOPE_HOST))
|
||||||
{
|
{
|
||||||
log(L_ERR "KRT: Received route %N with strange next-hop %I", net->n.addr,
|
log(L_ERR "KRT: Received route %N with strange next-hop %I", net, ra->nh.gw);
|
||||||
ra->nh.gw);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1919,7 +1917,7 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h)
|
|||||||
|
|
||||||
if (nl_parse_metrics(a[RTA_METRICS], metrics, ARRAY_SIZE(metrics)) < 0)
|
if (nl_parse_metrics(a[RTA_METRICS], metrics, ARRAY_SIZE(metrics)) < 0)
|
||||||
{
|
{
|
||||||
log(L_ERR "KRT: Received route %N with strange RTA_METRICS attribute", net->n.addr);
|
log(L_ERR "KRT: Received route %N with strange RTA_METRICS attribute", net);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1953,7 +1951,9 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h)
|
|||||||
if (!s->net)
|
if (!s->net)
|
||||||
{
|
{
|
||||||
/* Store the new route */
|
/* Store the new route */
|
||||||
s->net = net;
|
s->net = lp_alloc(s->pool, net->length);
|
||||||
|
net_copy(s->net, net);
|
||||||
|
|
||||||
s->attrs = ra;
|
s->attrs = ra;
|
||||||
s->proto = p;
|
s->proto = p;
|
||||||
s->new = new;
|
s->new = new;
|
||||||
|
@ -251,14 +251,14 @@ static inline void
|
|||||||
krt_trace_in(struct krt_proto *p, rte *e, char *msg)
|
krt_trace_in(struct krt_proto *p, rte *e, char *msg)
|
||||||
{
|
{
|
||||||
if (p->p.debug & D_PACKETS)
|
if (p->p.debug & D_PACKETS)
|
||||||
log(L_TRACE "%s: %N: %s", p->p.name, e->net->n.addr, msg);
|
log(L_TRACE "%s: %N: %s", p->p.name, e->net, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
krt_trace_in_rl(struct tbf *f, struct krt_proto *p, rte *e, char *msg)
|
krt_trace_in_rl(struct tbf *f, struct krt_proto *p, rte *e, char *msg)
|
||||||
{
|
{
|
||||||
if (p->p.debug & D_PACKETS)
|
if (p->p.debug & D_PACKETS)
|
||||||
log_rl(f, L_TRACE "%s: %N: %s", p->p.name, e->net->n.addr, msg);
|
log_rl(f, L_TRACE "%s: %N: %s", p->p.name, e->net, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -299,54 +299,56 @@ krt_uptodate(rte *a, rte *b)
|
|||||||
static void
|
static void
|
||||||
krt_learn_announce_update(struct krt_proto *p, rte *e)
|
krt_learn_announce_update(struct krt_proto *p, rte *e)
|
||||||
{
|
{
|
||||||
net *n = e->net;
|
rte e0 = {
|
||||||
rta *aa = rta_clone(e->attrs);
|
.attrs = rta_clone(e->attrs),
|
||||||
rte *ee = rte_get_temp(aa, p->p.main_source);
|
.src = p->p.main_source,
|
||||||
rte_update(&p->p, n->n.addr, ee);
|
};
|
||||||
|
|
||||||
|
rte_update(p->p.main_channel, e->net, &e0, p->p.main_source);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
krt_learn_announce_delete(struct krt_proto *p, net *n)
|
krt_learn_announce_delete(struct krt_proto *p, net_addr *n)
|
||||||
{
|
{
|
||||||
rte_update(&p->p, n->n.addr, NULL);
|
rte_update(p->p.main_channel, n, NULL, p->p.main_source);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Called when alien route is discovered during scan */
|
/* Called when alien route is discovered during scan */
|
||||||
static void
|
static void
|
||||||
krt_learn_scan(struct krt_proto *p, rte *e)
|
krt_learn_scan(struct krt_proto *p, rte *e)
|
||||||
{
|
{
|
||||||
net *n0 = e->net;
|
net *n = net_get(p->krt_table, e->net);
|
||||||
net *n = net_get(p->krt_table, n0->n.addr);
|
struct rte_storage *m, **mm;
|
||||||
rte *m, **mm;
|
|
||||||
|
|
||||||
e->attrs = rta_lookup(e->attrs);
|
struct rte_storage *ee = rte_store(e, n, p->krt_table);
|
||||||
|
|
||||||
for(mm=&n->routes; m = *mm; mm=&m->next)
|
for(mm = &n->routes; m = *mm; mm = &m->next)
|
||||||
if (krt_same_key(m, e))
|
if (krt_same_key(&m->rte, e))
|
||||||
break;
|
break;
|
||||||
if (m)
|
if (m)
|
||||||
{
|
{
|
||||||
if (krt_uptodate(m, e))
|
if (krt_uptodate(&m->rte, e))
|
||||||
{
|
{
|
||||||
krt_trace_in_rl(&rl_alien, p, e, "[alien] seen");
|
krt_trace_in_rl(&rl_alien, p, e, "[alien] seen");
|
||||||
rte_free(e);
|
rte_free(ee, p->krt_table);
|
||||||
m->pflags |= KRT_REF_SEEN;
|
m->rte.pflags |= KRT_REF_SEEN;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
krt_trace_in(p, e, "[alien] updated");
|
krt_trace_in(p, e, "[alien] updated");
|
||||||
*mm = m->next;
|
*mm = m->next;
|
||||||
rte_free(m);
|
rte_free(m, p->krt_table);
|
||||||
m = NULL;
|
m = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
krt_trace_in(p, e, "[alien] created");
|
krt_trace_in(p, e, "[alien] created");
|
||||||
|
|
||||||
if (!m)
|
if (!m)
|
||||||
{
|
{
|
||||||
e->next = n->routes;
|
ee->next = n->routes;
|
||||||
n->routes = e;
|
n->routes = ee;
|
||||||
e->pflags |= KRT_REF_SEEN;
|
ee->rte.pflags |= KRT_REF_SEEN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -362,7 +364,7 @@ krt_learn_prune(struct krt_proto *p)
|
|||||||
again:
|
again:
|
||||||
FIB_ITERATE_START(fib, &fit, net, n)
|
FIB_ITERATE_START(fib, &fit, net, n)
|
||||||
{
|
{
|
||||||
rte *e, **ee, *best, **pbest, *old_best;
|
struct rte_storage *e, **ee, *best, **pbest, *old_best;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Note that old_best may be NULL even if there was an old best route in
|
* Note that old_best may be NULL even if there was an old best route in
|
||||||
@ -376,48 +378,48 @@ again:
|
|||||||
ee = &n->routes;
|
ee = &n->routes;
|
||||||
while (e = *ee)
|
while (e = *ee)
|
||||||
{
|
{
|
||||||
if (e->pflags & KRT_REF_BEST)
|
if (e->rte.pflags & KRT_REF_BEST)
|
||||||
old_best = e;
|
old_best = e;
|
||||||
|
|
||||||
if (!(e->pflags & KRT_REF_SEEN))
|
if (!(e->rte.pflags & KRT_REF_SEEN))
|
||||||
{
|
{
|
||||||
*ee = e->next;
|
*ee = e->next;
|
||||||
rte_free(e);
|
rte_free(e, p->krt_table);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!best || krt_metric(best) > krt_metric(e))
|
if (!best || krt_metric(&best->rte) > krt_metric(&e->rte))
|
||||||
{
|
{
|
||||||
best = e;
|
best = e;
|
||||||
pbest = ee;
|
pbest = ee;
|
||||||
}
|
}
|
||||||
|
|
||||||
e->pflags &= ~(KRT_REF_SEEN | KRT_REF_BEST);
|
e->rte.pflags &= ~(KRT_REF_SEEN | KRT_REF_BEST);
|
||||||
ee = &e->next;
|
ee = &e->next;
|
||||||
}
|
}
|
||||||
if (!n->routes)
|
if (!n->routes)
|
||||||
{
|
{
|
||||||
DBG("%I/%d: deleting\n", n->n.prefix, n->n.pxlen);
|
DBG("%I/%d: deleting\n", n->n.prefix, n->n.pxlen);
|
||||||
if (old_best)
|
if (old_best)
|
||||||
krt_learn_announce_delete(p, n);
|
krt_learn_announce_delete(p, n->n.addr);
|
||||||
|
|
||||||
FIB_ITERATE_PUT(&fit);
|
FIB_ITERATE_PUT(&fit);
|
||||||
fib_delete(fib, n);
|
fib_delete(fib, n);
|
||||||
goto again;
|
goto again;
|
||||||
}
|
}
|
||||||
|
|
||||||
best->pflags |= KRT_REF_BEST;
|
best->rte.pflags |= KRT_REF_BEST;
|
||||||
*pbest = best->next;
|
*pbest = best->next;
|
||||||
best->next = n->routes;
|
best->next = n->routes;
|
||||||
n->routes = best;
|
n->routes = best;
|
||||||
|
|
||||||
if ((best != old_best) || p->reload)
|
if ((best != old_best) || p->reload)
|
||||||
{
|
{
|
||||||
DBG("%I/%d: announcing (metric=%d)\n", n->n.prefix, n->n.pxlen, krt_metric(best));
|
DBG("%I/%d: announcing (metric=%d)\n", n->n.prefix, n->n.pxlen, krt_metric(&best->rte));
|
||||||
krt_learn_announce_update(p, best);
|
krt_learn_announce_update(p, &best->rte);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
DBG("%I/%d: uptodate (metric=%d)\n", n->n.prefix, n->n.pxlen, krt_metric(best));
|
DBG("%I/%d: uptodate (metric=%d)\n", n->n.prefix, n->n.pxlen, krt_metric(&best->rte));
|
||||||
}
|
}
|
||||||
FIB_ITERATE_END;
|
FIB_ITERATE_END;
|
||||||
|
|
||||||
@ -427,68 +429,67 @@ again:
|
|||||||
static void
|
static void
|
||||||
krt_learn_async(struct krt_proto *p, rte *e, int new)
|
krt_learn_async(struct krt_proto *p, rte *e, int new)
|
||||||
{
|
{
|
||||||
net *n0 = e->net;
|
net *n = net_get(p->krt_table, e->net);
|
||||||
net *n = net_get(p->krt_table, n0->n.addr);
|
struct rte_storage *g, **gg, *best, **bestp, *old_best;
|
||||||
rte *g, **gg, *best, **bestp, *old_best;
|
|
||||||
|
|
||||||
ASSERT(!e->attrs->cached);
|
ASSERT(!e->attrs->cached);
|
||||||
e->attrs->pref = p->p.main_channel->preference;
|
e->attrs->pref = p->p.main_channel->preference;
|
||||||
|
|
||||||
e->attrs = rta_lookup(e->attrs);
|
struct rte_storage *ee = rte_store(e, n, p->krt_table);
|
||||||
|
|
||||||
old_best = n->routes;
|
old_best = n->routes;
|
||||||
for(gg=&n->routes; g = *gg; gg = &g->next)
|
for(gg=&n->routes; g = *gg; gg = &g->next)
|
||||||
if (krt_same_key(g, e))
|
if (krt_same_key(&g->rte, e))
|
||||||
break;
|
break;
|
||||||
if (new)
|
if (new)
|
||||||
{
|
{
|
||||||
if (g)
|
if (g)
|
||||||
{
|
{
|
||||||
if (krt_uptodate(g, e))
|
if (krt_uptodate(&g->rte, e))
|
||||||
{
|
{
|
||||||
krt_trace_in(p, e, "[alien async] same");
|
krt_trace_in(p, e, "[alien async] same");
|
||||||
rte_free(e);
|
rte_free(ee, p->krt_table);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
krt_trace_in(p, e, "[alien async] updated");
|
krt_trace_in(p, e, "[alien async] updated");
|
||||||
*gg = g->next;
|
*gg = g->next;
|
||||||
rte_free(g);
|
rte_free(g, p->krt_table);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
krt_trace_in(p, e, "[alien async] created");
|
krt_trace_in(p, e, "[alien async] created");
|
||||||
|
|
||||||
e->next = n->routes;
|
ee->next = n->routes;
|
||||||
n->routes = e;
|
n->routes = ee;
|
||||||
}
|
}
|
||||||
else if (!g)
|
else if (!g)
|
||||||
{
|
{
|
||||||
krt_trace_in(p, e, "[alien async] delete failed");
|
krt_trace_in(p, e, "[alien async] delete failed");
|
||||||
rte_free(e);
|
rte_free(ee, p->krt_table);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
krt_trace_in(p, e, "[alien async] removed");
|
krt_trace_in(p, e, "[alien async] removed");
|
||||||
*gg = g->next;
|
*gg = g->next;
|
||||||
rte_free(e);
|
rte_free(ee, p->krt_table);
|
||||||
rte_free(g);
|
rte_free(g, p->krt_table);
|
||||||
}
|
}
|
||||||
best = n->routes;
|
best = n->routes;
|
||||||
bestp = &n->routes;
|
bestp = &n->routes;
|
||||||
for(gg=&n->routes; g=*gg; gg=&g->next)
|
for(gg=&n->routes; g=*gg; gg=&g->next)
|
||||||
{
|
{
|
||||||
if (krt_metric(best) > krt_metric(g))
|
if (krt_metric(&best->rte) > krt_metric(&g->rte))
|
||||||
{
|
{
|
||||||
best = g;
|
best = g;
|
||||||
bestp = gg;
|
bestp = gg;
|
||||||
}
|
}
|
||||||
|
|
||||||
g->pflags &= ~KRT_REF_BEST;
|
g->rte.pflags &= ~KRT_REF_BEST;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (best)
|
if (best)
|
||||||
{
|
{
|
||||||
best->pflags |= KRT_REF_BEST;
|
best->rte.pflags |= KRT_REF_BEST;
|
||||||
*bestp = best->next;
|
*bestp = best->next;
|
||||||
best->next = n->routes;
|
best->next = n->routes;
|
||||||
n->routes = best;
|
n->routes = best;
|
||||||
@ -498,9 +499,9 @@ krt_learn_async(struct krt_proto *p, rte *e, int new)
|
|||||||
{
|
{
|
||||||
DBG("krt_learn_async: distributing change\n");
|
DBG("krt_learn_async: distributing change\n");
|
||||||
if (best)
|
if (best)
|
||||||
krt_learn_announce_update(p, best);
|
krt_learn_announce_update(p, &best->rte);
|
||||||
else
|
else
|
||||||
krt_learn_announce_delete(p, n);
|
krt_learn_announce_delete(p, n->n.addr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -538,7 +539,7 @@ krt_dump(struct proto *P)
|
|||||||
static inline int
|
static inline int
|
||||||
krt_is_installed(struct krt_proto *p, net *n)
|
krt_is_installed(struct krt_proto *p, net *n)
|
||||||
{
|
{
|
||||||
return n->routes && bmap_test(&p->p.main_channel->export_map, n->routes->id);
|
return n->routes && bmap_test(&p->p.main_channel->export_map, n->routes->rte.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -552,26 +553,25 @@ krt_flush_routes(struct krt_proto *p)
|
|||||||
if (krt_is_installed(p, n))
|
if (krt_is_installed(p, n))
|
||||||
{
|
{
|
||||||
/* FIXME: this does not work if gw is changed in export filter */
|
/* FIXME: this does not work if gw is changed in export filter */
|
||||||
krt_replace_rte(p, n, NULL, n->routes);
|
krt_replace_rte(p, n->n.addr, NULL, &n->routes->rte);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FIB_WALK_END;
|
FIB_WALK_END;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct rte *
|
static struct rte *
|
||||||
krt_export_net(struct krt_proto *p, net *net, rte **rt_free)
|
krt_export_net(struct krt_proto *p, net *net)
|
||||||
{
|
{
|
||||||
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;
|
||||||
rte *rt;
|
|
||||||
|
|
||||||
if (c->ra_mode == RA_MERGED)
|
if (c->ra_mode == RA_MERGED)
|
||||||
return rt_export_merged(c, net, rt_free, krt_filter_lp, 1);
|
return rt_export_merged(c, net, krt_filter_lp, 1);
|
||||||
|
|
||||||
rt = net->routes;
|
static _Thread_local rte rt;
|
||||||
*rt_free = NULL;
|
rt = net->routes->rte;
|
||||||
|
|
||||||
if (!rte_is_valid(rt))
|
if (!rte_is_valid(&rt))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (filter == FILTER_REJECT)
|
if (filter == FILTER_REJECT)
|
||||||
@ -587,13 +587,9 @@ krt_export_net(struct krt_proto *p, net *net, rte **rt_free)
|
|||||||
|
|
||||||
|
|
||||||
accept:
|
accept:
|
||||||
if (rt != net->routes)
|
return &rt;
|
||||||
*rt_free = rt;
|
|
||||||
return rt;
|
|
||||||
|
|
||||||
reject:
|
reject:
|
||||||
if (rt != net->routes)
|
|
||||||
rte_free(rt);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -619,8 +615,7 @@ krt_same_dest(rte *k, rte *e)
|
|||||||
void
|
void
|
||||||
krt_got_route(struct krt_proto *p, rte *e, s8 src)
|
krt_got_route(struct krt_proto *p, rte *e, s8 src)
|
||||||
{
|
{
|
||||||
rte *new = NULL, *rt_free = NULL;
|
rte *new = NULL;
|
||||||
net *n = e->net;
|
|
||||||
e->pflags = 0;
|
e->pflags = 0;
|
||||||
|
|
||||||
#ifdef KRT_ALLOW_LEARN
|
#ifdef KRT_ALLOW_LEARN
|
||||||
@ -636,10 +631,7 @@ krt_got_route(struct krt_proto *p, rte *e, s8 src)
|
|||||||
if (KRT_CF->learn)
|
if (KRT_CF->learn)
|
||||||
krt_learn_scan(p, e);
|
krt_learn_scan(p, e);
|
||||||
else
|
else
|
||||||
{
|
krt_trace_in_rl(&rl_alien, p, e, "[alien] ignored");
|
||||||
krt_trace_in_rl(&rl_alien, p, e, "[alien] ignored");
|
|
||||||
rte_free(e);
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -650,10 +642,11 @@ krt_got_route(struct krt_proto *p, rte *e, s8 src)
|
|||||||
if (!p->ready)
|
if (!p->ready)
|
||||||
goto ignore;
|
goto ignore;
|
||||||
|
|
||||||
if (!krt_is_installed(p, n))
|
net *net = net_find(p->p.main_channel->table, e->net);
|
||||||
|
if (!net || !krt_is_installed(p, net))
|
||||||
goto delete;
|
goto delete;
|
||||||
|
|
||||||
new = krt_export_net(p, n, &rt_free);
|
new = krt_export_net(p, net);
|
||||||
|
|
||||||
/* Rejected by filters */
|
/* Rejected by filters */
|
||||||
if (!new)
|
if (!new)
|
||||||
@ -686,20 +679,15 @@ ignore:
|
|||||||
|
|
||||||
update:
|
update:
|
||||||
krt_trace_in(p, new, "updating");
|
krt_trace_in(p, new, "updating");
|
||||||
krt_replace_rte(p, n, new, e);
|
krt_replace_rte(p, e->net, new, e);
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
delete:
|
delete:
|
||||||
krt_trace_in(p, e, "deleting");
|
krt_trace_in(p, e, "deleting");
|
||||||
krt_replace_rte(p, n, NULL, e);
|
krt_replace_rte(p, e->net, NULL, e);
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
done:
|
done:
|
||||||
rte_free(e);
|
|
||||||
|
|
||||||
if (rt_free)
|
|
||||||
rte_free(rt_free);
|
|
||||||
|
|
||||||
lp_flush(krt_filter_lp);
|
lp_flush(krt_filter_lp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -717,20 +705,16 @@ krt_prune(struct krt_proto *p)
|
|||||||
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)
|
||||||
{
|
{
|
||||||
if (p->ready && krt_is_installed(p, n) && !bmap_test(&p->seen_map, n->routes->id))
|
if (p->ready && krt_is_installed(p, n) && !bmap_test(&p->seen_map, n->routes->rte.id))
|
||||||
{
|
{
|
||||||
rte *rt_free = NULL;
|
rte *new = krt_export_net(p, n);
|
||||||
rte *new = krt_export_net(p, n, &rt_free);
|
|
||||||
|
|
||||||
if (new)
|
if (new)
|
||||||
{
|
{
|
||||||
krt_trace_in(p, new, "installing");
|
krt_trace_in(p, new, "installing");
|
||||||
krt_replace_rte(p, n, new, NULL);
|
krt_replace_rte(p, n->n.addr, new, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rt_free)
|
|
||||||
rte_free(rt_free);
|
|
||||||
|
|
||||||
lp_flush(krt_filter_lp);
|
lp_flush(krt_filter_lp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -748,7 +732,6 @@ krt_prune(struct krt_proto *p)
|
|||||||
void
|
void
|
||||||
krt_got_route_async(struct krt_proto *p, rte *e, int new, s8 src)
|
krt_got_route_async(struct krt_proto *p, rte *e, int new, s8 src)
|
||||||
{
|
{
|
||||||
net *net = e->net;
|
|
||||||
e->pflags = 0;
|
e->pflags = 0;
|
||||||
|
|
||||||
switch (src)
|
switch (src)
|
||||||
@ -761,7 +744,7 @@ krt_got_route_async(struct krt_proto *p, rte *e, int new, s8 src)
|
|||||||
if (new)
|
if (new)
|
||||||
{
|
{
|
||||||
krt_trace_in(p, e, "[redirect] deleting");
|
krt_trace_in(p, e, "[redirect] deleting");
|
||||||
krt_replace_rte(p, net, NULL, e);
|
krt_replace_rte(p, e->net, NULL, e);
|
||||||
}
|
}
|
||||||
/* If !new, it is probably echo of our deletion */
|
/* If !new, it is probably echo of our deletion */
|
||||||
break;
|
break;
|
||||||
@ -775,7 +758,6 @@ krt_got_route_async(struct krt_proto *p, rte *e, int new, s8 src)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
rte_free(e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -882,10 +864,9 @@ krt_scan_timer_kick(struct krt_proto *p)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
static int
|
static int
|
||||||
krt_preexport(struct proto *P, rte *e)
|
krt_preexport(struct channel *c, rte *e)
|
||||||
{
|
{
|
||||||
// struct krt_proto *p = (struct krt_proto *) P;
|
if (e->src->proto == c->proto)
|
||||||
if (e->src->proto == P)
|
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (!krt_capable(e))
|
if (!krt_capable(e))
|
||||||
@ -895,8 +876,8 @@ krt_preexport(struct proto *P, rte *e)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
krt_rt_notify(struct proto *P, struct channel *ch UNUSED, net *net,
|
krt_rt_notify(struct proto *P, struct channel *ch UNUSED, const net_addr *net,
|
||||||
rte *new, rte *old)
|
rte *new, const rte *old)
|
||||||
{
|
{
|
||||||
struct krt_proto *p = (struct krt_proto *) P;
|
struct krt_proto *p = (struct krt_proto *) P;
|
||||||
|
|
||||||
|
@ -143,7 +143,7 @@ void krt_sys_copy_config(struct krt_config *, struct krt_config *);
|
|||||||
|
|
||||||
int krt_capable(rte *e);
|
int krt_capable(rte *e);
|
||||||
void krt_do_scan(struct krt_proto *);
|
void krt_do_scan(struct krt_proto *);
|
||||||
void krt_replace_rte(struct krt_proto *p, net *n, rte *new, rte *old);
|
void krt_replace_rte(struct krt_proto *p, const net_addr *n, rte *new, const rte *old);
|
||||||
int krt_sys_get_attr(const eattr *a, byte *buf, int buflen);
|
int krt_sys_get_attr(const eattr *a, byte *buf, int buflen);
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user