Nest: Removing separate tmpa from route propagation
This is a fundamental change of an original (1999) concept of route processing inside BIRD. During import/export, there was a temporary ea_list created which was to be used instead of the another one inside the route itself. This led to some confusion, quirks, and strange filter code that handled extended route attributes. Dropping it now. The protocol interface has changed in an uniform way -- the `struct ea_list *attrs` argument has been removed from store_tmp_attrs(), import_control(), rt_notify() and get_route_info().
This commit is contained in:
parent
ee7e2ffd26
commit
13c0be19d3
24 changed files with 220 additions and 242 deletions
|
@ -538,14 +538,23 @@ val_format(struct f_val v, buffer *buf)
|
||||||
|
|
||||||
static struct rte **f_rte;
|
static struct rte **f_rte;
|
||||||
static struct rta *f_old_rta;
|
static struct rta *f_old_rta;
|
||||||
static struct ea_list **f_tmp_attrs;
|
static struct ea_list **f_eattrs;
|
||||||
static struct linpool *f_pool;
|
static struct linpool *f_pool;
|
||||||
static struct buffer f_buf;
|
static struct buffer f_buf;
|
||||||
static int f_flags;
|
static int f_flags;
|
||||||
|
|
||||||
|
static inline void f_cache_eattrs(void)
|
||||||
|
{
|
||||||
|
f_eattrs = &((*f_rte)->attrs->eattrs);
|
||||||
|
}
|
||||||
|
|
||||||
static inline void f_rte_cow(void)
|
static inline void f_rte_cow(void)
|
||||||
{
|
{
|
||||||
*f_rte = rte_cow(*f_rte);
|
if (!((*f_rte)->flags & REF_COW))
|
||||||
|
return;
|
||||||
|
|
||||||
|
*f_rte = rte_do_cow(*f_rte);
|
||||||
|
f_eattrs = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -570,6 +579,9 @@ f_rta_cow(void)
|
||||||
* suppose hostentry is not changed by filters).
|
* suppose hostentry is not changed by filters).
|
||||||
*/
|
*/
|
||||||
(*f_rte)->attrs = rta_do_cow((*f_rte)->attrs, f_pool);
|
(*f_rte)->attrs = rta_do_cow((*f_rte)->attrs, f_pool);
|
||||||
|
|
||||||
|
/* Re-cache the ea_list */
|
||||||
|
f_cache_eattrs();
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
|
@ -603,7 +615,10 @@ static struct tbf rl_runtime_err = TBF_DEFAULT_LOG_LIMITS;
|
||||||
return val;
|
return val;
|
||||||
|
|
||||||
#define ACCESS_RTE \
|
#define ACCESS_RTE \
|
||||||
do { if (!f_rte) runtime("No route to access"); } while (0)
|
do { if (!f_rte) runtime("No route to access"); else f_cache_eattrs(); } while (0)
|
||||||
|
|
||||||
|
#define ACCESS_EATTRS \
|
||||||
|
do { if (!f_eattrs) f_cache_eattrs(); } while (0)
|
||||||
|
|
||||||
#define BITFIELD_MASK(what) \
|
#define BITFIELD_MASK(what) \
|
||||||
(1u << (what->a2.i >> 24))
|
(1u << (what->a2.i >> 24))
|
||||||
|
@ -995,17 +1010,11 @@ interpret(struct f_inst *what)
|
||||||
break;
|
break;
|
||||||
case FI_EA_GET: /* Access to extended attributes */
|
case FI_EA_GET: /* Access to extended attributes */
|
||||||
ACCESS_RTE;
|
ACCESS_RTE;
|
||||||
|
ACCESS_EATTRS;
|
||||||
{
|
{
|
||||||
eattr *e = NULL;
|
|
||||||
u16 code = what->a2.i;
|
u16 code = what->a2.i;
|
||||||
int f_type = what->aux >> 8;
|
int f_type = what->aux >> 8;
|
||||||
|
eattr *e = ea_find(*f_eattrs, code);
|
||||||
if (!(f_flags & FF_FORCE_TMPATTR))
|
|
||||||
e = ea_find((*f_rte)->attrs->eattrs, code);
|
|
||||||
if (!e)
|
|
||||||
e = ea_find((*f_tmp_attrs), code);
|
|
||||||
if ((!e) && (f_flags & FF_FORCE_TMPATTR))
|
|
||||||
e = ea_find((*f_rte)->attrs->eattrs, code);
|
|
||||||
|
|
||||||
if (!e) {
|
if (!e) {
|
||||||
/* A special case: undefined as_path looks like empty as_path */
|
/* A special case: undefined as_path looks like empty as_path */
|
||||||
|
@ -1089,6 +1098,7 @@ interpret(struct f_inst *what)
|
||||||
break;
|
break;
|
||||||
case FI_EA_SET:
|
case FI_EA_SET:
|
||||||
ACCESS_RTE;
|
ACCESS_RTE;
|
||||||
|
ACCESS_EATTRS;
|
||||||
ARG_ANY(1);
|
ARG_ANY(1);
|
||||||
{
|
{
|
||||||
struct ea_list *l = lp_alloc(f_pool, sizeof(struct ea_list) + sizeof(eattr));
|
struct ea_list *l = lp_alloc(f_pool, sizeof(struct ea_list) + sizeof(eattr));
|
||||||
|
@ -1143,13 +1153,7 @@ interpret(struct f_inst *what)
|
||||||
runtime( "Setting bit in bitfield attribute to non-bool value" );
|
runtime( "Setting bit in bitfield attribute to non-bool value" );
|
||||||
{
|
{
|
||||||
/* First, we have to find the old value */
|
/* First, we have to find the old value */
|
||||||
eattr *e = NULL;
|
eattr *e = ea_find(*f_eattrs, code);
|
||||||
if (!(f_flags & FF_FORCE_TMPATTR))
|
|
||||||
e = ea_find((*f_rte)->attrs->eattrs, code);
|
|
||||||
if (!e)
|
|
||||||
e = ea_find((*f_tmp_attrs), code);
|
|
||||||
if ((!e) && (f_flags & FF_FORCE_TMPATTR))
|
|
||||||
e = ea_find((*f_rte)->attrs->eattrs, code);
|
|
||||||
u32 data = e ? e->u.data : 0;
|
u32 data = e ? e->u.data : 0;
|
||||||
|
|
||||||
if (v1.val.i)
|
if (v1.val.i)
|
||||||
|
@ -1181,14 +1185,9 @@ interpret(struct f_inst *what)
|
||||||
default: bug("Unknown type in e,S");
|
default: bug("Unknown type in e,S");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(what->aux & EAF_TEMP) && (!(f_flags & FF_FORCE_TMPATTR))) {
|
|
||||||
f_rta_cow();
|
f_rta_cow();
|
||||||
l->next = (*f_rte)->attrs->eattrs;
|
l->next = *f_eattrs;
|
||||||
(*f_rte)->attrs->eattrs = l;
|
*f_eattrs = l;
|
||||||
} else {
|
|
||||||
l->next = (*f_tmp_attrs);
|
|
||||||
(*f_tmp_attrs) = l;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case FI_PREF_GET:
|
case FI_PREF_GET:
|
||||||
|
@ -1518,11 +1517,12 @@ interpret(struct f_inst *what)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ACCESS_RTE;
|
ACCESS_RTE;
|
||||||
|
ACCESS_EATTRS;
|
||||||
v1.val.net = (*f_rte)->net->n.addr;
|
v1.val.net = (*f_rte)->net->n.addr;
|
||||||
|
|
||||||
/* 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 */
|
||||||
eattr *e = ea_find((*f_rte)->attrs->eattrs, EA_CODE(PROTOCOL_BGP, 0x02));
|
eattr *e = ea_find(*f_eattrs, EA_CODE(PROTOCOL_BGP, 0x02));
|
||||||
|
|
||||||
if (!e || e->type != EAF_TYPE_AS_PATH)
|
if (!e || e->type != EAF_TYPE_AS_PATH)
|
||||||
runtime("Missing AS_PATH attribute");
|
runtime("Missing AS_PATH attribute");
|
||||||
|
@ -1720,7 +1720,6 @@ i_same(struct f_inst *f1, struct f_inst *f2)
|
||||||
* 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, may be modified
|
||||||
* @tmp_attrs: temporary attributes, prepared by caller or generated by f_run()
|
|
||||||
* @tmp_pool: all filter allocations go from this pool
|
* @tmp_pool: all filter allocations go from this pool
|
||||||
* @flags: flags
|
* @flags: flags
|
||||||
*
|
*
|
||||||
|
@ -1742,7 +1741,7 @@ i_same(struct f_inst *f1, struct f_inst *f2)
|
||||||
* modified in place, old cached rta is possibly freed.
|
* modified in place, old cached rta is possibly freed.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
f_run(struct filter *filter, struct rte **rte, struct ea_list **tmp_attrs, struct linpool *tmp_pool, int flags)
|
f_run(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;
|
||||||
|
@ -1755,7 +1754,6 @@ f_run(struct filter *filter, struct rte **rte, struct ea_list **tmp_attrs, struc
|
||||||
|
|
||||||
f_rte = rte;
|
f_rte = rte;
|
||||||
f_old_rta = NULL;
|
f_old_rta = NULL;
|
||||||
f_tmp_attrs = tmp_attrs;
|
|
||||||
f_pool = tmp_pool;
|
f_pool = tmp_pool;
|
||||||
f_flags = flags;
|
f_flags = flags;
|
||||||
|
|
||||||
|
@ -1797,11 +1795,9 @@ f_run(struct filter *filter, struct rte **rte, struct ea_list **tmp_attrs, struc
|
||||||
struct f_val
|
struct f_val
|
||||||
f_eval_rte(struct f_inst *expr, struct rte **rte, struct linpool *tmp_pool)
|
f_eval_rte(struct f_inst *expr, struct rte **rte, struct linpool *tmp_pool)
|
||||||
{
|
{
|
||||||
struct ea_list *tmp_attrs = NULL;
|
|
||||||
|
|
||||||
f_rte = rte;
|
f_rte = rte;
|
||||||
f_old_rta = NULL;
|
f_old_rta = NULL;
|
||||||
f_tmp_attrs = &tmp_attrs;
|
|
||||||
f_pool = tmp_pool;
|
f_pool = tmp_pool;
|
||||||
f_flags = 0;
|
f_flags = 0;
|
||||||
|
|
||||||
|
@ -1810,9 +1806,6 @@ f_eval_rte(struct f_inst *expr, struct rte **rte, struct linpool *tmp_pool)
|
||||||
/* Note that in this function we assume that rte->attrs is private / uncached */
|
/* Note that in this function we assume that rte->attrs is private / uncached */
|
||||||
struct f_val res = interpret(expr);
|
struct f_val res = interpret(expr);
|
||||||
|
|
||||||
/* Hack to include EAF_TEMP attributes to the main list */
|
|
||||||
(*rte)->attrs->eattrs = ea_append(tmp_attrs, (*rte)->attrs->eattrs);
|
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1820,7 +1813,6 @@ struct f_val
|
||||||
f_eval(struct f_inst *expr, struct linpool *tmp_pool)
|
f_eval(struct f_inst *expr, struct linpool *tmp_pool)
|
||||||
{
|
{
|
||||||
f_flags = 0;
|
f_flags = 0;
|
||||||
f_tmp_attrs = NULL;
|
|
||||||
f_rte = NULL;
|
f_rte = NULL;
|
||||||
f_pool = tmp_pool;
|
f_pool = tmp_pool;
|
||||||
|
|
||||||
|
|
|
@ -175,7 +175,7 @@ void trie_format(struct f_trie *t, buffer *buf);
|
||||||
struct ea_list;
|
struct ea_list;
|
||||||
struct rte;
|
struct rte;
|
||||||
|
|
||||||
int f_run(struct filter *filter, struct rte **rte, struct ea_list **tmp_attrs, struct linpool *tmp_pool, int flags);
|
int f_run(struct filter *filter, struct rte **rte, struct linpool *tmp_pool, int flags);
|
||||||
struct f_val f_eval_rte(struct f_inst *expr, struct rte **rte, struct linpool *tmp_pool);
|
struct f_val f_eval_rte(struct f_inst *expr, struct rte **rte, struct linpool *tmp_pool);
|
||||||
struct f_val f_eval(struct f_inst *expr, struct linpool *tmp_pool);
|
struct f_val f_eval(struct f_inst *expr, struct linpool *tmp_pool);
|
||||||
uint f_eval_int(struct f_inst *expr);
|
uint f_eval_int(struct f_inst *expr);
|
||||||
|
@ -285,7 +285,6 @@ struct f_trie
|
||||||
|
|
||||||
#define NEW_F_VAL struct f_val * val; val = cfg_alloc(sizeof(struct f_val));
|
#define NEW_F_VAL struct f_val * val; val = cfg_alloc(sizeof(struct f_val));
|
||||||
|
|
||||||
#define FF_FORCE_TMPATTR 1 /* Force all attributes to be temporary */
|
|
||||||
#define FF_SILENT 2 /* Silent filter execution */
|
#define FF_SILENT 2 /* Silent filter execution */
|
||||||
|
|
||||||
/* Bird Tests */
|
/* Bird Tests */
|
||||||
|
|
|
@ -77,7 +77,7 @@ struct protocol {
|
||||||
int (*shutdown)(struct proto *); /* Stop the instance */
|
int (*shutdown)(struct proto *); /* Stop the instance */
|
||||||
void (*cleanup)(struct proto *); /* Called after shutdown when protocol became hungry/down */
|
void (*cleanup)(struct proto *); /* Called after shutdown when protocol became hungry/down */
|
||||||
void (*get_status)(struct proto *, byte *buf); /* Get instance status (for `show protocols' command) */
|
void (*get_status)(struct proto *, byte *buf); /* Get instance status (for `show protocols' command) */
|
||||||
void (*get_route_info)(struct rte *, byte *buf, struct ea_list *attrs); /* Get route information (for `show route' command) */
|
void (*get_route_info)(struct rte *, byte *buf); /* Get route information (for `show route' command) */
|
||||||
int (*get_attr)(struct eattr *, byte *buf, int buflen); /* ASCIIfy dynamic attribute (returns GA_*) */
|
int (*get_attr)(struct eattr *, byte *buf, int buflen); /* ASCIIfy dynamic attribute (returns GA_*) */
|
||||||
void (*show_proto_info)(struct proto *); /* Show protocol info (for `show protocols all' command) */
|
void (*show_proto_info)(struct proto *); /* Show protocol info (for `show protocols all' command) */
|
||||||
void (*copy_config)(struct proto_config *, struct proto_config *); /* Copy config from given protocol instance */
|
void (*copy_config)(struct proto_config *, struct proto_config *); /* Copy config from given protocol instance */
|
||||||
|
@ -191,7 +191,7 @@ struct proto {
|
||||||
* rt_notify Notify protocol about routing table updates.
|
* rt_notify Notify protocol about routing table updates.
|
||||||
* neigh_notify Notify protocol about neighbor cache events.
|
* neigh_notify Notify protocol about neighbor cache events.
|
||||||
* make_tmp_attrs Construct ea_list from private attrs stored in rte.
|
* make_tmp_attrs Construct ea_list from private attrs stored in rte.
|
||||||
* store_tmp_attrs Store private attrs back to the rte.
|
* store_tmp_attrs Store private attrs back to rta. The route MUST NOT be cached.
|
||||||
* import_control Called as the first step of the route importing process.
|
* import_control Called as the first step of the route importing process.
|
||||||
* It can construct a new rte, add private attributes and
|
* It can construct a new rte, add private attributes and
|
||||||
* decide whether the route shall be imported: 1=yes, -1=no,
|
* decide whether the route shall be imported: 1=yes, -1=no,
|
||||||
|
@ -205,11 +205,11 @@ 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, struct ea_list *attrs);
|
void (*rt_notify)(struct proto *, struct channel *, struct network *net, struct rte *new, struct rte *old);
|
||||||
void (*neigh_notify)(struct neighbor *neigh);
|
void (*neigh_notify)(struct neighbor *neigh);
|
||||||
struct ea_list *(*make_tmp_attrs)(struct rte *rt, struct linpool *pool);
|
struct ea_list *(*make_tmp_attrs)(struct rte *rt, struct linpool *pool);
|
||||||
void (*store_tmp_attrs)(struct rte *rt, struct ea_list *attrs);
|
void (*store_tmp_attrs)(struct rte *rt);
|
||||||
int (*import_control)(struct proto *, struct rte **rt, struct ea_list **attrs, struct linpool *pool);
|
int (*import_control)(struct proto *, struct rte **rt, struct linpool *pool);
|
||||||
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 *);
|
||||||
|
@ -292,12 +292,16 @@ proto_get_router_id(struct proto_config *pc)
|
||||||
return pc->router_id ? pc->router_id : pc->global->router_id;
|
return pc->router_id ? pc->router_id : pc->global->router_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline struct ea_list *
|
static inline void
|
||||||
rte_make_tmp_attrs(struct rte *rt, struct linpool *pool)
|
rte_make_tmp_attrs(struct rte **rt, struct linpool *pool)
|
||||||
{
|
{
|
||||||
struct ea_list *(*mta)(struct rte *rt, struct linpool *pool);
|
struct ea_list *(*mta)(struct rte *rt, struct linpool *pool);
|
||||||
mta = rt->attrs->src->proto->make_tmp_attrs;
|
mta = (*rt)->attrs->src->proto->make_tmp_attrs;
|
||||||
return mta ? mta(rt, pool) : NULL;
|
if (!mta) return;
|
||||||
|
*rt = rte_cow_rta(*rt, pool);
|
||||||
|
struct ea_list *ea = mta(*rt, pool);
|
||||||
|
ea->next = (*rt)->attrs->eattrs;
|
||||||
|
(*rt)->attrs->eattrs = ea;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Moved from route.h to avoid dependency conflicts */
|
/* Moved from route.h to avoid dependency conflicts */
|
||||||
|
@ -466,7 +470,7 @@ struct channel_class {
|
||||||
void (*dump_attrs)(struct rte *); /* Dump protocol-dependent attributes */
|
void (*dump_attrs)(struct rte *); /* Dump protocol-dependent attributes */
|
||||||
|
|
||||||
void (*get_status)(struct proto *, byte *buf); /* Get instance status (for `show protocols' command) */
|
void (*get_status)(struct proto *, byte *buf); /* Get instance status (for `show protocols' command) */
|
||||||
void (*get_route_info)(struct rte *, byte *buf, struct ea_list *attrs); /* Get route information (for `show route' command) */
|
void (*get_route_info)(struct rte *, byte *buf); /* Get route information (for `show route' command) */
|
||||||
int (*get_attr)(struct eattr *, byte *buf, int buflen); /* ASCIIfy dynamic attribute (returns GA_*) */
|
int (*get_attr)(struct eattr *, byte *buf, int buflen); /* ASCIIfy dynamic attribute (returns GA_*) */
|
||||||
void (*show_proto_info)(struct proto *); /* Show protocol info (for `show protocols all' command) */
|
void (*show_proto_info)(struct proto *); /* Show protocol info (for `show protocols all' command) */
|
||||||
|
|
||||||
|
|
13
nest/route.h
13
nest/route.h
|
@ -294,7 +294,7 @@ rte *rte_get_temp(struct rta *);
|
||||||
void rte_update2(struct channel *c, const net_addr *n, rte *new, struct rte_src *src);
|
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 */
|
/* rte_update() moved to protocol.h to avoid dependency conflicts */
|
||||||
int rt_examine(rtable *t, net_addr *a, struct proto *p, struct filter *filter);
|
int rt_examine(rtable *t, net_addr *a, struct proto *p, struct filter *filter);
|
||||||
rte *rt_export_merged(struct channel *c, net *net, rte **rt_free, struct ea_list **tmpa, linpool *pool, int silent);
|
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_schedule_prune(rtable *t);
|
void rt_schedule_prune(rtable *t);
|
||||||
|
@ -546,6 +546,15 @@ uint ea_hash(ea_list *e); /* Calculate 16-bit hash value */
|
||||||
ea_list *ea_append(ea_list *to, ea_list *what);
|
ea_list *ea_append(ea_list *to, ea_list *what);
|
||||||
void ea_format_bitfield(struct eattr *a, byte *buf, int bufsize, const char **names, int min, int max);
|
void ea_format_bitfield(struct eattr *a, byte *buf, int bufsize, const char **names, int min, int max);
|
||||||
|
|
||||||
|
#define ea_normalize(ea) do { \
|
||||||
|
if (ea->next) { \
|
||||||
|
ea_list *t = alloca(ea_scan(ea)); \
|
||||||
|
ea_merge(ea, t); \
|
||||||
|
ea = t; \
|
||||||
|
} \
|
||||||
|
ea_sort(ea); \
|
||||||
|
} while(0) \
|
||||||
|
|
||||||
static inline eattr *
|
static inline eattr *
|
||||||
ea_set_attr(ea_list **to, struct linpool *pool, uint id, uint flags, uint type, uintptr_t val)
|
ea_set_attr(ea_list **to, struct linpool *pool, uint id, uint flags, uint type, uintptr_t val)
|
||||||
{
|
{
|
||||||
|
@ -611,7 +620,7 @@ rta *rta_do_cow(rta *o, linpool *lp);
|
||||||
static inline rta * rta_cow(rta *r, linpool *lp) { return rta_is_cached(r) ? rta_do_cow(r, lp) : r; }
|
static inline rta * rta_cow(rta *r, linpool *lp) { return rta_is_cached(r) ? rta_do_cow(r, lp) : r; }
|
||||||
void rta_dump(rta *);
|
void rta_dump(rta *);
|
||||||
void rta_dump_all(void);
|
void rta_dump_all(void);
|
||||||
void rta_show(struct cli *, rta *, ea_list *);
|
void rta_show(struct cli *, rta *);
|
||||||
|
|
||||||
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);
|
||||||
|
|
|
@ -550,29 +550,47 @@ ea_do_sort(ea_list *e)
|
||||||
while (ss);
|
while (ss);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* In place discard duplicates, undefs and temporary attributes in sorted
|
||||||
|
* ea_list. We use stable sort for this reason.
|
||||||
|
**/
|
||||||
static inline void
|
static inline void
|
||||||
ea_do_prune(ea_list *e)
|
ea_do_prune(ea_list *e)
|
||||||
{
|
{
|
||||||
eattr *s, *d, *l, *s0;
|
eattr *s, *d, *l, *s0;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
/* Discard duplicates and undefs. Do you remember sorting was stable? */
|
s = d = e->attrs; /* Beginning of the list. @s is source, @d is destination. */
|
||||||
s = d = e->attrs;
|
l = e->attrs + e->count; /* End of the list */
|
||||||
l = e->attrs + e->count;
|
|
||||||
|
/* Walk from begin to end. */
|
||||||
while (s < l)
|
while (s < l)
|
||||||
{
|
{
|
||||||
s0 = s++;
|
s0 = s++;
|
||||||
|
/* Find a consecutive block of the same attribute */
|
||||||
while (s < l && s->id == s[-1].id)
|
while (s < l && s->id == s[-1].id)
|
||||||
s++;
|
s++;
|
||||||
/* s0 is the most recent version, s[-1] the oldest one */
|
|
||||||
if ((s0->type & EAF_TYPE_MASK) != EAF_TYPE_UNDEF)
|
/* Now s0 is the most recent version, s[-1] the oldest one */
|
||||||
{
|
/* Drop undefs */
|
||||||
|
if ((s0->type & EAF_TYPE_MASK) == EAF_TYPE_UNDEF)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Drop temporary attributes */
|
||||||
|
if (s0->type & EAF_TEMP)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* Copy the newest version to destination */
|
||||||
*d = *s0;
|
*d = *s0;
|
||||||
|
|
||||||
|
/* Preserve info whether it originated locally */
|
||||||
d->type = (d->type & ~(EAF_ORIGINATED|EAF_FRESH)) | (s[-1].type & EAF_ORIGINATED);
|
d->type = (d->type & ~(EAF_ORIGINATED|EAF_FRESH)) | (s[-1].type & EAF_ORIGINATED);
|
||||||
|
|
||||||
|
/* Next destination */
|
||||||
d++;
|
d++;
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
e->count = i;
|
e->count = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1128,15 +1146,7 @@ rta_lookup(rta *o)
|
||||||
|
|
||||||
ASSERT(!(o->aflags & RTAF_CACHED));
|
ASSERT(!(o->aflags & RTAF_CACHED));
|
||||||
if (o->eattrs)
|
if (o->eattrs)
|
||||||
{
|
ea_normalize(o->eattrs);
|
||||||
if (o->eattrs->next) /* Multiple ea_list's, need to merge them */
|
|
||||||
{
|
|
||||||
ea_list *ml = alloca(ea_scan(o->eattrs));
|
|
||||||
ea_merge(o->eattrs, ml);
|
|
||||||
o->eattrs = ml;
|
|
||||||
}
|
|
||||||
ea_sort(o->eattrs);
|
|
||||||
}
|
|
||||||
|
|
||||||
h = rta_hash(o);
|
h = rta_hash(o);
|
||||||
for(r=rta_hash_table[h & rta_cache_mask]; r; r=r->next)
|
for(r=rta_hash_table[h & rta_cache_mask]; r; r=r->next)
|
||||||
|
@ -1250,17 +1260,15 @@ rta_dump_all(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
rta_show(struct cli *c, rta *a, ea_list *eal)
|
rta_show(struct cli *c, rta *a)
|
||||||
{
|
{
|
||||||
static char *src_names[] = { "dummy", "static", "inherit", "device", "static-device", "redirect",
|
static char *src_names[] = { "dummy", "static", "inherit", "device", "static-device", "redirect",
|
||||||
"RIP", "OSPF", "OSPF-IA", "OSPF-E1", "OSPF-E2", "BGP", "pipe" };
|
"RIP", "OSPF", "OSPF-IA", "OSPF-E1", "OSPF-E2", "BGP", "pipe" };
|
||||||
int i;
|
|
||||||
|
|
||||||
cli_printf(c, -1008, "\tType: %s %s", src_names[a->source], ip_scope_text(a->scope));
|
cli_printf(c, -1008, "\tType: %s %s", src_names[a->source], ip_scope_text(a->scope));
|
||||||
if (!eal)
|
|
||||||
eal = a->eattrs;
|
for(ea_list *eal = a->eattrs; eal; eal=eal->next)
|
||||||
for(; eal; eal=eal->next)
|
for(int i=0; i<eal->count; i++)
|
||||||
for(i=0; i<eal->count; i++)
|
|
||||||
ea_show(c, &eal->attrs[i]);
|
ea_show(c, &eal->attrs[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,14 +29,14 @@ rt_show_table(struct cli *c, struct rt_show_data *d)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
rt_show_rte(struct cli *c, byte *ia, rte *e, struct rt_show_data *d, ea_list *tmpa)
|
rt_show_rte(struct cli *c, byte *ia, rte *e, struct rt_show_data *d)
|
||||||
{
|
{
|
||||||
byte from[IPA_MAX_TEXT_LENGTH+8];
|
byte from[IPA_MAX_TEXT_LENGTH+8];
|
||||||
byte tm[TM_DATETIME_BUFFER_SIZE], info[256];
|
byte tm[TM_DATETIME_BUFFER_SIZE], info[256];
|
||||||
rta *a = e->attrs;
|
rta *a = e->attrs;
|
||||||
int primary = (e->net->routes == e);
|
int primary = (e->net->routes == e);
|
||||||
int sync_error = (e->net->n.flags & KRF_SYNC_ERROR);
|
int sync_error = (e->net->n.flags & KRF_SYNC_ERROR);
|
||||||
void (*get_route_info)(struct rte *, byte *buf, struct ea_list *attrs);
|
void (*get_route_info)(struct rte *, byte *buf);
|
||||||
struct nexthop *nh;
|
struct nexthop *nh;
|
||||||
|
|
||||||
tm_format_time(tm, &config->tf_route, e->lastmod);
|
tm_format_time(tm, &config->tf_route, e->lastmod);
|
||||||
|
@ -46,17 +46,11 @@ rt_show_rte(struct cli *c, byte *ia, rte *e, struct rt_show_data *d, ea_list *tm
|
||||||
from[0] = 0;
|
from[0] = 0;
|
||||||
|
|
||||||
get_route_info = a->src->proto->proto->get_route_info;
|
get_route_info = a->src->proto->proto->get_route_info;
|
||||||
if (get_route_info || d->verbose)
|
|
||||||
{
|
|
||||||
/* Need to normalize the extended attributes */
|
/* Need to normalize the extended attributes */
|
||||||
ea_list *t = tmpa;
|
if ((get_route_info || d->verbose) && !rta_is_cached(a))
|
||||||
t = ea_append(t, a->eattrs);
|
ea_normalize(a->eattrs);
|
||||||
tmpa = alloca(ea_scan(t));
|
|
||||||
ea_merge(t, tmpa);
|
|
||||||
ea_sort(tmpa);
|
|
||||||
}
|
|
||||||
if (get_route_info)
|
if (get_route_info)
|
||||||
get_route_info(e, info, tmpa);
|
get_route_info(e, info);
|
||||||
else
|
else
|
||||||
bsprintf(info, " (%d)", e->pref);
|
bsprintf(info, " (%d)", e->pref);
|
||||||
|
|
||||||
|
@ -93,7 +87,7 @@ rt_show_rte(struct cli *c, byte *ia, rte *e, struct rt_show_data *d, ea_list *tm
|
||||||
}
|
}
|
||||||
|
|
||||||
if (d->verbose)
|
if (d->verbose)
|
||||||
rta_show(c, a, tmpa);
|
rta_show(c, a);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -101,7 +95,6 @@ rt_show_net(struct cli *c, net *n, struct rt_show_data *d)
|
||||||
{
|
{
|
||||||
rte *e, *ee;
|
rte *e, *ee;
|
||||||
byte ia[NET_MAX_TEXT_LENGTH+1];
|
byte ia[NET_MAX_TEXT_LENGTH+1];
|
||||||
struct ea_list *tmpa;
|
|
||||||
struct channel *ec = d->tab->export_channel;
|
struct channel *ec = d->tab->export_channel;
|
||||||
int first = 1;
|
int first = 1;
|
||||||
int pass = 0;
|
int pass = 0;
|
||||||
|
@ -121,7 +114,7 @@ rt_show_net(struct cli *c, net *n, struct rt_show_data *d)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
ee = e;
|
ee = e;
|
||||||
tmpa = rte_make_tmp_attrs(e, c->show_pool);
|
rte_make_tmp_attrs(&e, c->show_pool);
|
||||||
|
|
||||||
/* 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))
|
||||||
|
@ -131,7 +124,7 @@ rt_show_net(struct cli *c, net *n, struct rt_show_data *d)
|
||||||
if ((d->export_mode == RSEM_EXPORT) && (ec->ra_mode == RA_MERGED))
|
if ((d->export_mode == RSEM_EXPORT) && (ec->ra_mode == RA_MERGED))
|
||||||
{
|
{
|
||||||
rte *rt_free;
|
rte *rt_free;
|
||||||
e = rt_export_merged(ec, n, &rt_free, &tmpa, c->show_pool, 1);
|
e = rt_export_merged(ec, n, &rt_free, c->show_pool, 1);
|
||||||
pass = 1;
|
pass = 1;
|
||||||
|
|
||||||
if (!e)
|
if (!e)
|
||||||
|
@ -140,7 +133,7 @@ rt_show_net(struct cli *c, net *n, struct rt_show_data *d)
|
||||||
else if (d->export_mode)
|
else if (d->export_mode)
|
||||||
{
|
{
|
||||||
struct proto *ep = ec->proto;
|
struct proto *ep = ec->proto;
|
||||||
int ic = ep->import_control ? ep->import_control(ep, &e, &tmpa, c->show_pool) : 0;
|
int ic = ep->import_control ? ep->import_control(ep, &e, c->show_pool) : 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;
|
||||||
|
@ -156,8 +149,7 @@ rt_show_net(struct cli *c, net *n, struct rt_show_data *d)
|
||||||
* command may change the export filter and do not update routes.
|
* command may change the export filter and do not update routes.
|
||||||
*/
|
*/
|
||||||
int do_export = (ic > 0) ||
|
int do_export = (ic > 0) ||
|
||||||
(f_run(ec->out_filter, &e, &tmpa, c->show_pool,
|
(f_run(ec->out_filter, &e, c->show_pool, FF_SILENT) <= F_ACCEPT);
|
||||||
FF_FORCE_TMPATTR | FF_SILENT) <= F_ACCEPT);
|
|
||||||
|
|
||||||
if (do_export != (d->export_mode == RSEM_EXPORT))
|
if (do_export != (d->export_mode == RSEM_EXPORT))
|
||||||
goto skip;
|
goto skip;
|
||||||
|
@ -170,11 +162,11 @@ rt_show_net(struct cli *c, net *n, struct rt_show_data *d)
|
||||||
if (d->show_protocol && (d->show_protocol != e->attrs->src->proto))
|
if (d->show_protocol && (d->show_protocol != e->attrs->src->proto))
|
||||||
goto skip;
|
goto skip;
|
||||||
|
|
||||||
if (f_run(d->filter, &e, &tmpa, c->show_pool, FF_FORCE_TMPATTR) > F_ACCEPT)
|
if (f_run(d->filter, &e, c->show_pool, 0) > F_ACCEPT)
|
||||||
goto skip;
|
goto skip;
|
||||||
|
|
||||||
if (d->stats < 2)
|
if (d->stats < 2)
|
||||||
rt_show_rte(c, ia, e, d, tmpa);
|
rt_show_rte(c, ia, e, d);
|
||||||
|
|
||||||
d->show_counter++;
|
d->show_counter++;
|
||||||
ia[0] = 0;
|
ia[0] = 0;
|
||||||
|
|
|
@ -317,11 +317,11 @@ rte_cow_rta(rte *r, linpool *lp)
|
||||||
if (!rta_is_cached(r->attrs))
|
if (!rta_is_cached(r->attrs))
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
rte *e = rte_cow(r);
|
r = rte_cow(r);
|
||||||
rta *a = rta_do_cow(r->attrs, lp);
|
rta *a = rta_do_cow(r->attrs, lp);
|
||||||
rta_free(e->attrs);
|
rta_free(r->attrs);
|
||||||
e->attrs = a;
|
r->attrs = a;
|
||||||
return e;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int /* Actually better or at least as good as */
|
static int /* Actually better or at least as good as */
|
||||||
|
@ -393,24 +393,20 @@ rte_trace_out(uint flag, struct proto *p, rte *e, char *msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
static rte *
|
static rte *
|
||||||
export_filter_(struct channel *c, rte *rt0, rte **rt_free, ea_list **tmpa, linpool *pool, int silent)
|
export_filter_(struct channel *c, rte *rt0, rte **rt_free, linpool *pool, int silent)
|
||||||
{
|
{
|
||||||
struct proto *p = c->proto;
|
struct proto *p = c->proto;
|
||||||
struct filter *filter = c->out_filter;
|
struct filter *filter = c->out_filter;
|
||||||
struct proto_stats *stats = &c->stats;
|
struct proto_stats *stats = &c->stats;
|
||||||
ea_list *tmpb = NULL;
|
|
||||||
rte *rt;
|
rte *rt;
|
||||||
int v;
|
int v;
|
||||||
|
|
||||||
rt = rt0;
|
rt = rt0;
|
||||||
*rt_free = NULL;
|
*rt_free = NULL;
|
||||||
|
|
||||||
if (!tmpa)
|
rte_make_tmp_attrs(&rt, pool);
|
||||||
tmpa = &tmpb;
|
|
||||||
|
|
||||||
*tmpa = rte_make_tmp_attrs(rt, pool);
|
v = p->import_control ? p->import_control(p, &rt, pool) : 0;
|
||||||
|
|
||||||
v = p->import_control ? p->import_control(p, &rt, tmpa, pool) : 0;
|
|
||||||
if (v < 0)
|
if (v < 0)
|
||||||
{
|
{
|
||||||
if (silent)
|
if (silent)
|
||||||
|
@ -429,8 +425,8 @@ export_filter_(struct channel *c, rte *rt0, rte **rt_free, ea_list **tmpa, linpo
|
||||||
}
|
}
|
||||||
|
|
||||||
v = filter && ((filter == FILTER_REJECT) ||
|
v = filter && ((filter == FILTER_REJECT) ||
|
||||||
(f_run(filter, &rt, tmpa, pool,
|
(f_run(filter, &rt, pool,
|
||||||
FF_FORCE_TMPATTR | (silent ? FF_SILENT : 0)) > F_ACCEPT));
|
(silent ? FF_SILENT : 0)) > F_ACCEPT));
|
||||||
if (v)
|
if (v)
|
||||||
{
|
{
|
||||||
if (silent)
|
if (silent)
|
||||||
|
@ -454,13 +450,13 @@ export_filter_(struct channel *c, rte *rt0, rte **rt_free, ea_list **tmpa, linpo
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline rte *
|
static inline rte *
|
||||||
export_filter(struct channel *c, rte *rt0, rte **rt_free, ea_list **tmpa, int silent)
|
export_filter(struct channel *c, rte *rt0, rte **rt_free, int silent)
|
||||||
{
|
{
|
||||||
return export_filter_(c, rt0, rt_free, tmpa, rte_update_pool, silent);
|
return export_filter_(c, rt0, rt_free, rte_update_pool, silent);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
do_rt_notify(struct channel *c, net *net, rte *new, rte *old, ea_list *tmpa, int refeed)
|
do_rt_notify(struct channel *c, net *net, rte *new, rte *old, int refeed)
|
||||||
{
|
{
|
||||||
struct proto *p = c->proto;
|
struct proto *p = c->proto;
|
||||||
struct proto_stats *stats = &c->stats;
|
struct proto_stats *stats = &c->stats;
|
||||||
|
@ -533,19 +529,7 @@ do_rt_notify(struct channel *c, net *net, rte *new, rte *old, ea_list *tmpa, int
|
||||||
else if (old)
|
else if (old)
|
||||||
rte_trace_out(D_ROUTES, p, old, "removed");
|
rte_trace_out(D_ROUTES, p, old, "removed");
|
||||||
}
|
}
|
||||||
if (!new)
|
p->rt_notify(p, c, net, new, old);
|
||||||
p->rt_notify(p, c, net, NULL, old, NULL);
|
|
||||||
else if (tmpa)
|
|
||||||
{
|
|
||||||
ea_list *t = tmpa;
|
|
||||||
while (t->next)
|
|
||||||
t = t->next;
|
|
||||||
t->next = new->attrs->eattrs;
|
|
||||||
p->rt_notify(p, c, net, new, old, tmpa);
|
|
||||||
t->next = NULL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
p->rt_notify(p, c, net, new, old, new->attrs->eattrs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -557,7 +541,6 @@ rt_notify_basic(struct channel *c, net *net, rte *new0, rte *old0, int refeed)
|
||||||
rte *old = old0;
|
rte *old = old0;
|
||||||
rte *new_free = NULL;
|
rte *new_free = NULL;
|
||||||
rte *old_free = NULL;
|
rte *old_free = NULL;
|
||||||
ea_list *tmpa = NULL;
|
|
||||||
|
|
||||||
if (new)
|
if (new)
|
||||||
c->stats.exp_updates_received++;
|
c->stats.exp_updates_received++;
|
||||||
|
@ -585,10 +568,10 @@ rt_notify_basic(struct channel *c, net *net, rte *new0, rte *old0, int refeed)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (new)
|
if (new)
|
||||||
new = export_filter(c, new, &new_free, &tmpa, 0);
|
new = export_filter(c, new, &new_free, 0);
|
||||||
|
|
||||||
if (old && !refeed)
|
if (old && !refeed)
|
||||||
old = export_filter(c, old, &old_free, NULL, 1);
|
old = export_filter(c, old, &old_free, 1);
|
||||||
|
|
||||||
if (!new && !old)
|
if (!new && !old)
|
||||||
{
|
{
|
||||||
|
@ -605,13 +588,13 @@ rt_notify_basic(struct channel *c, net *net, rte *new0, rte *old0, int refeed)
|
||||||
|
|
||||||
#ifdef CONFIG_PIPE
|
#ifdef CONFIG_PIPE
|
||||||
if ((p->proto == &proto_pipe) && !new0 && (p != old0->sender->proto))
|
if ((p->proto == &proto_pipe) && !new0 && (p != old0->sender->proto))
|
||||||
p->rt_notify(p, c, net, NULL, old0, NULL);
|
p->rt_notify(p, c, net, NULL, old0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
do_rt_notify(c, net, new, old, tmpa, refeed);
|
do_rt_notify(c, net, new, old, refeed);
|
||||||
|
|
||||||
/* Discard temporary rte's */
|
/* Discard temporary rte's */
|
||||||
if (new_free)
|
if (new_free)
|
||||||
|
@ -630,7 +613,6 @@ rt_notify_accepted(struct channel *c, net *net, rte *new_changed, rte *old_chang
|
||||||
rte *old_best = NULL;
|
rte *old_best = NULL;
|
||||||
rte *new_free = NULL;
|
rte *new_free = NULL;
|
||||||
rte *old_free = NULL;
|
rte *old_free = NULL;
|
||||||
ea_list *tmpa = NULL;
|
|
||||||
|
|
||||||
/* Used to track whether we met old_changed position. If before_old is NULL
|
/* Used to track whether we met old_changed position. If before_old is NULL
|
||||||
old_changed was the first and we met it implicitly before current best route. */
|
old_changed was the first and we met it implicitly before current best route. */
|
||||||
|
@ -648,7 +630,7 @@ rt_notify_accepted(struct channel *c, net *net, rte *new_changed, rte *old_chang
|
||||||
/* First, find the new_best route - first accepted by filters */
|
/* First, find the new_best route - first accepted by filters */
|
||||||
for (r=net->routes; rte_is_valid(r); r=r->next)
|
for (r=net->routes; rte_is_valid(r); r=r->next)
|
||||||
{
|
{
|
||||||
if (new_best = export_filter(c, r, &new_free, &tmpa, 0))
|
if (new_best = export_filter(c, r, &new_free, 0))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Note if we walked around the position of old_changed route */
|
/* Note if we walked around the position of old_changed route */
|
||||||
|
@ -699,7 +681,7 @@ rt_notify_accepted(struct channel *c, net *net, rte *new_changed, rte *old_chang
|
||||||
|
|
||||||
/* First case */
|
/* First case */
|
||||||
if (old_meet)
|
if (old_meet)
|
||||||
if (old_best = export_filter(c, old_changed, &old_free, NULL, 1))
|
if (old_best = export_filter(c, old_changed, &old_free, 1))
|
||||||
goto found;
|
goto found;
|
||||||
|
|
||||||
/* Second case */
|
/* Second case */
|
||||||
|
@ -717,18 +699,18 @@ rt_notify_accepted(struct channel *c, net *net, rte *new_changed, rte *old_chang
|
||||||
/* Fourth case */
|
/* Fourth case */
|
||||||
for (r=r->next; rte_is_valid(r); r=r->next)
|
for (r=r->next; rte_is_valid(r); r=r->next)
|
||||||
{
|
{
|
||||||
if (old_best = export_filter(c, r, &old_free, NULL, 1))
|
if (old_best = export_filter(c, r, &old_free, 1))
|
||||||
goto found;
|
goto found;
|
||||||
|
|
||||||
if (r == before_old)
|
if (r == before_old)
|
||||||
if (old_best = export_filter(c, old_changed, &old_free, NULL, 1))
|
if (old_best = export_filter(c, old_changed, &old_free, 1))
|
||||||
goto found;
|
goto found;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Implicitly, old_best is NULL and new_best is non-NULL */
|
/* Implicitly, old_best is NULL and new_best is non-NULL */
|
||||||
|
|
||||||
found:
|
found:
|
||||||
do_rt_notify(c, net, new_best, old_best, tmpa, (feed == 2));
|
do_rt_notify(c, net, new_best, old_best, (feed == 2));
|
||||||
|
|
||||||
/* Discard temporary rte's */
|
/* Discard temporary rte's */
|
||||||
if (new_free)
|
if (new_free)
|
||||||
|
@ -745,7 +727,7 @@ nexthop_merge_rta(struct nexthop *nhs, rta *a, linpool *pool, int max)
|
||||||
}
|
}
|
||||||
|
|
||||||
rte *
|
rte *
|
||||||
rt_export_merged(struct channel *c, net *net, rte **rt_free, ea_list **tmpa, linpool *pool, int silent)
|
rt_export_merged(struct channel *c, net *net, rte **rt_free, linpool *pool, int silent)
|
||||||
{
|
{
|
||||||
// struct proto *p = c->proto;
|
// struct proto *p = c->proto;
|
||||||
struct nexthop *nhs = NULL;
|
struct nexthop *nhs = NULL;
|
||||||
|
@ -757,7 +739,7 @@ rt_export_merged(struct channel *c, net *net, rte **rt_free, ea_list **tmpa, lin
|
||||||
if (!rte_is_valid(best0))
|
if (!rte_is_valid(best0))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
best = export_filter_(c, best0, rt_free, tmpa, pool, silent);
|
best = export_filter_(c, best0, rt_free, pool, silent);
|
||||||
|
|
||||||
if (!best || !rte_is_reachable(best))
|
if (!best || !rte_is_reachable(best))
|
||||||
return best;
|
return best;
|
||||||
|
@ -767,7 +749,7 @@ rt_export_merged(struct channel *c, net *net, rte **rt_free, ea_list **tmpa, lin
|
||||||
if (!rte_mergable(best0, rt0))
|
if (!rte_mergable(best0, rt0))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
rt = export_filter_(c, rt0, &tmp, NULL, pool, 1);
|
rt = export_filter_(c, rt0, &tmp, pool, 1);
|
||||||
|
|
||||||
if (!rt)
|
if (!rt)
|
||||||
continue;
|
continue;
|
||||||
|
@ -807,7 +789,6 @@ rt_notify_merged(struct channel *c, net *net, rte *new_changed, rte *old_changed
|
||||||
rte *old_best_free = NULL;
|
rte *old_best_free = NULL;
|
||||||
rte *new_changed_free = NULL;
|
rte *new_changed_free = NULL;
|
||||||
rte *old_changed_free = NULL;
|
rte *old_changed_free = NULL;
|
||||||
ea_list *tmpa = NULL;
|
|
||||||
|
|
||||||
/* We assume that all rte arguments are either NULL or rte_is_valid() */
|
/* We assume that all rte arguments are either NULL or rte_is_valid() */
|
||||||
|
|
||||||
|
@ -819,10 +800,10 @@ rt_notify_merged(struct channel *c, net *net, rte *new_changed, rte *old_changed
|
||||||
if ((new_best == old_best) && !refeed)
|
if ((new_best == old_best) && !refeed)
|
||||||
{
|
{
|
||||||
new_changed = rte_mergable(new_best, new_changed) ?
|
new_changed = rte_mergable(new_best, new_changed) ?
|
||||||
export_filter(c, new_changed, &new_changed_free, NULL, 1) : NULL;
|
export_filter(c, new_changed, &new_changed_free, 1) : NULL;
|
||||||
|
|
||||||
old_changed = rte_mergable(old_best, old_changed) ?
|
old_changed = rte_mergable(old_best, old_changed) ?
|
||||||
export_filter(c, old_changed, &old_changed_free, NULL, 1) : NULL;
|
export_filter(c, old_changed, &old_changed_free, 1) : NULL;
|
||||||
|
|
||||||
if (!new_changed && !old_changed)
|
if (!new_changed && !old_changed)
|
||||||
return;
|
return;
|
||||||
|
@ -835,15 +816,15 @@ rt_notify_merged(struct channel *c, net *net, rte *new_changed, rte *old_changed
|
||||||
|
|
||||||
/* Prepare new merged route */
|
/* Prepare new merged route */
|
||||||
if (new_best)
|
if (new_best)
|
||||||
new_best = rt_export_merged(c, net, &new_best_free, &tmpa, rte_update_pool, 0);
|
new_best = rt_export_merged(c, net, &new_best_free, rte_update_pool, 0);
|
||||||
|
|
||||||
/* Prepare old merged route (without proper merged next hops) */
|
/* Prepare old merged route (without proper merged next hops) */
|
||||||
/* There are some issues with running filter on old route - see rt_notify_basic() */
|
/* There are some issues with running filter on old route - see rt_notify_basic() */
|
||||||
if (old_best && !refeed)
|
if (old_best && !refeed)
|
||||||
old_best = export_filter(c, old_best, &old_best_free, NULL, 1);
|
old_best = export_filter(c, old_best, &old_best_free, 1);
|
||||||
|
|
||||||
if (new_best || old_best)
|
if (new_best || old_best)
|
||||||
do_rt_notify(c, net, new_best, old_best, tmpa, refeed);
|
do_rt_notify(c, net, new_best, old_best, refeed);
|
||||||
|
|
||||||
/* Discard temporary rte's */
|
/* Discard temporary rte's */
|
||||||
if (new_best_free)
|
if (new_best_free)
|
||||||
|
@ -1341,7 +1322,6 @@ rte_update2(struct channel *c, const net_addr *n, rte *new, struct rte_src *src)
|
||||||
struct proto *p = c->proto;
|
struct proto *p = c->proto;
|
||||||
struct proto_stats *stats = &c->stats;
|
struct proto_stats *stats = &c->stats;
|
||||||
struct filter *filter = c->in_filter;
|
struct filter *filter = c->in_filter;
|
||||||
ea_list *tmpa = NULL;
|
|
||||||
rte *dummy = NULL;
|
rte *dummy = NULL;
|
||||||
net *nn;
|
net *nn;
|
||||||
|
|
||||||
|
@ -1379,11 +1359,11 @@ rte_update2(struct channel *c, const net_addr *n, rte *new, struct rte_src *src)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
tmpa = rte_make_tmp_attrs(new, rte_update_pool);
|
rte_make_tmp_attrs(&new, rte_update_pool);
|
||||||
if (filter && (filter != FILTER_REJECT))
|
if (filter && (filter != FILTER_REJECT))
|
||||||
{
|
{
|
||||||
ea_list *old_tmpa = tmpa;
|
ea_list *oldea = new->attrs->eattrs;
|
||||||
int fr = f_run(filter, &new, &tmpa, rte_update_pool, 0);
|
int fr = f_run(filter, &new, rte_update_pool, 0);
|
||||||
if (fr > F_ACCEPT)
|
if (fr > F_ACCEPT)
|
||||||
{
|
{
|
||||||
stats->imp_updates_filtered++;
|
stats->imp_updates_filtered++;
|
||||||
|
@ -1394,8 +1374,8 @@ rte_update2(struct channel *c, const net_addr *n, rte *new, struct rte_src *src)
|
||||||
|
|
||||||
new->flags |= REF_FILTERED;
|
new->flags |= REF_FILTERED;
|
||||||
}
|
}
|
||||||
if (tmpa != old_tmpa && src->proto->store_tmp_attrs)
|
if (new->attrs->eattrs != oldea && src->proto->store_tmp_attrs)
|
||||||
src->proto->store_tmp_attrs(new, tmpa);
|
src->proto->store_tmp_attrs(new);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!rta_is_cached(new->attrs)) /* Need to copy attributes */
|
if (!rta_is_cached(new->attrs)) /* Need to copy attributes */
|
||||||
|
@ -1459,11 +1439,10 @@ rt_examine(rtable *t, net_addr *a, struct proto *p, struct filter *filter)
|
||||||
rte_update_lock();
|
rte_update_lock();
|
||||||
|
|
||||||
/* Rest is stripped down export_filter() */
|
/* Rest is stripped down export_filter() */
|
||||||
ea_list *tmpa = rte_make_tmp_attrs(rt, rte_update_pool);
|
rte_make_tmp_attrs(&rt, rte_update_pool);
|
||||||
int v = p->import_control ? p->import_control(p, &rt, &tmpa, rte_update_pool) : 0;
|
int v = p->import_control ? p->import_control(p, &rt, rte_update_pool) : 0;
|
||||||
if (v == RIC_PROCESS)
|
if (v == RIC_PROCESS)
|
||||||
v = (f_run(filter, &rt, &tmpa, rte_update_pool,
|
v = (f_run(filter, &rt, rte_update_pool, FF_SILENT) <= F_ACCEPT);
|
||||||
FF_FORCE_TMPATTR | FF_SILENT) <= F_ACCEPT);
|
|
||||||
|
|
||||||
/* Discard temporary rte */
|
/* Discard temporary rte */
|
||||||
if (rt != n->routes)
|
if (rt != n->routes)
|
||||||
|
|
|
@ -1829,7 +1829,7 @@ babel_dump(struct proto *P)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
babel_get_route_info(rte *rte, byte *buf, ea_list *attrs UNUSED)
|
babel_get_route_info(rte *rte, byte *buf)
|
||||||
{
|
{
|
||||||
buf += bsprintf(buf, " (%d/%d) [%lR]", rte->pref, rte->u.babel.metric, rte->u.babel.router_id);
|
buf += bsprintf(buf, " (%d/%d) [%lR]", rte->pref, rte->u.babel.metric, rte->u.babel.router_id);
|
||||||
}
|
}
|
||||||
|
@ -2087,12 +2087,13 @@ babel_prepare_attrs(struct linpool *pool, ea_list *next, uint metric, u64 router
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
babel_import_control(struct proto *P, struct rte **new, struct ea_list **attrs UNUSED, struct linpool *pool UNUSED)
|
babel_import_control(struct proto *P, struct rte **new, struct linpool *pool)
|
||||||
{
|
{
|
||||||
rte *e = *new;
|
struct babel_proto *p = (void *) P;
|
||||||
|
struct rta *a = (*new)->attrs;
|
||||||
|
|
||||||
/* Reject our own unreachable routes */
|
/* Reject our own unreachable routes */
|
||||||
if ((e->attrs->dest == RTD_UNREACHABLE) && (e->attrs->src->proto == P))
|
if ((a->dest == RTD_UNREACHABLE) && (a->src->proto == P))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -2105,9 +2106,9 @@ babel_make_tmp_attrs(struct rte *rt, struct linpool *pool)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
babel_store_tmp_attrs(struct rte *rt, struct ea_list *attrs)
|
babel_store_tmp_attrs(struct rte *rt)
|
||||||
{
|
{
|
||||||
rt->u.babel.metric = ea_get_int(attrs, EA_BABEL_METRIC, 0);
|
rt->u.babel.metric = ea_get_int(rt->attrs->eattrs, EA_BABEL_METRIC, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -2116,7 +2117,7 @@ babel_store_tmp_attrs(struct rte *rt, struct ea_list *attrs)
|
||||||
*/
|
*/
|
||||||
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, struct network *net,
|
||||||
struct rte *new, struct rte *old UNUSED, struct ea_list *attrs UNUSED)
|
struct rte *new, struct rte *old UNUSED)
|
||||||
{
|
{
|
||||||
struct babel_proto *p = (void *) P;
|
struct babel_proto *p = (void *) P;
|
||||||
struct babel_entry *e;
|
struct babel_entry *e;
|
||||||
|
@ -2126,7 +2127,7 @@ babel_rt_notify(struct proto *P, struct channel *c UNUSED, struct network *net,
|
||||||
/* Update */
|
/* Update */
|
||||||
uint internal = (new->attrs->src->proto == P);
|
uint internal = (new->attrs->src->proto == P);
|
||||||
uint rt_seqno = internal ? new->u.babel.seqno : p->update_seqno;
|
uint rt_seqno = internal ? new->u.babel.seqno : p->update_seqno;
|
||||||
uint rt_metric = ea_get_int(attrs, EA_BABEL_METRIC, 0);
|
uint rt_metric = ea_get_int(new->attrs->eattrs, EA_BABEL_METRIC, 0);
|
||||||
u64 rt_router_id = internal ? new->u.babel.router_id : p->router_id;
|
u64 rt_router_id = internal ? new->u.babel.router_id : p->router_id;
|
||||||
|
|
||||||
if (rt_metric > BABEL_INFINITY)
|
if (rt_metric > BABEL_INFINITY)
|
||||||
|
|
|
@ -125,7 +125,7 @@ babel_iface_opt_list:
|
||||||
babel_iface:
|
babel_iface:
|
||||||
babel_iface_start iface_patt_list_nopx babel_iface_opt_list babel_iface_finish;
|
babel_iface_start iface_patt_list_nopx babel_iface_opt_list babel_iface_finish;
|
||||||
|
|
||||||
CF_ADDTO(dynamic_attr, BABEL_METRIC { $$ = f_new_dynamic_attr(EAF_TYPE_INT | EAF_TEMP, T_INT, EA_BABEL_METRIC); })
|
CF_ADDTO(dynamic_attr, BABEL_METRIC { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_BABEL_METRIC); })
|
||||||
|
|
||||||
CF_CLI_HELP(SHOW BABEL, ..., [[Show information about Babel protocol]]);
|
CF_CLI_HELP(SHOW BABEL, ..., [[Show information about Babel protocol]]);
|
||||||
|
|
||||||
|
|
|
@ -1372,7 +1372,7 @@ bgp_free_prefix(struct bgp_channel *c, struct bgp_prefix *px)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
int
|
||||||
bgp_import_control(struct proto *P, rte **new, ea_list **attrs UNUSED, struct linpool *pool UNUSED)
|
bgp_import_control(struct proto *P, rte **new, struct linpool *pool UNUSED)
|
||||||
{
|
{
|
||||||
rte *e = *new;
|
rte *e = *new;
|
||||||
struct proto *SRC = e->attrs->src->proto;
|
struct proto *SRC = e->attrs->src->proto;
|
||||||
|
@ -1536,7 +1536,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, ea_list *attrs)
|
bgp_rt_notify(struct proto *P, struct channel *C, net *n, rte *new, 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;
|
||||||
|
@ -1546,7 +1546,7 @@ bgp_rt_notify(struct proto *P, struct channel *C, net *n, rte *new, rte *old, ea
|
||||||
|
|
||||||
if (new)
|
if (new)
|
||||||
{
|
{
|
||||||
attrs = bgp_update_attrs(p, c, new, attrs, bgp_linpool2);
|
struct ea_list *attrs = bgp_update_attrs(p, c, new, new->attrs->eattrs, bgp_linpool2);
|
||||||
|
|
||||||
/* 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);
|
||||||
|
@ -2007,10 +2007,10 @@ bgp_get_attr(eattr *a, byte *buf, int buflen)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
bgp_get_route_info(rte *e, byte *buf, ea_list *attrs)
|
bgp_get_route_info(rte *e, byte *buf)
|
||||||
{
|
{
|
||||||
eattr *p = ea_find(attrs, EA_CODE(PROTOCOL_BGP, BA_AS_PATH));
|
eattr *p = ea_find(e->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_AS_PATH));
|
||||||
eattr *o = ea_find(attrs, EA_CODE(PROTOCOL_BGP, BA_ORIGIN));
|
eattr *o = ea_find(e->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_ORIGIN));
|
||||||
u32 origas;
|
u32 origas;
|
||||||
|
|
||||||
buf += bsprintf(buf, " (%d", e->pref);
|
buf += bsprintf(buf, " (%d", e->pref);
|
||||||
|
|
|
@ -505,10 +505,10 @@ void bgp_free_prefix(struct bgp_channel *c, struct bgp_prefix *bp);
|
||||||
int bgp_rte_better(struct rte *, struct rte *);
|
int bgp_rte_better(struct rte *, struct rte *);
|
||||||
int bgp_rte_mergable(rte *pri, rte *sec);
|
int bgp_rte_mergable(rte *pri, rte *sec);
|
||||||
int bgp_rte_recalculate(rtable *table, net *net, rte *new, rte *old, rte *old_best);
|
int bgp_rte_recalculate(rtable *table, net *net, rte *new, rte *old, rte *old_best);
|
||||||
void bgp_rt_notify(struct proto *P, struct channel *C, net *n, rte *new, rte *old, ea_list *attrs);
|
void bgp_rt_notify(struct proto *P, struct channel *C, net *n, rte *new, rte *old);
|
||||||
int bgp_import_control(struct proto *, struct rte **, struct ea_list **, struct linpool *);
|
int bgp_import_control(struct proto *, struct rte **, struct linpool *);
|
||||||
int bgp_get_attr(struct eattr *e, byte *buf, int buflen);
|
int bgp_get_attr(struct eattr *e, byte *buf, int buflen);
|
||||||
void bgp_get_route_info(struct rte *, byte *buf, struct ea_list *attrs);
|
void bgp_get_route_info(struct rte *, byte *buf);
|
||||||
|
|
||||||
|
|
||||||
/* packets.c */
|
/* packets.c */
|
||||||
|
|
|
@ -497,10 +497,10 @@ ospf_iface:
|
||||||
ospf_iface_start ospf_iface_patt_list ospf_iface_opt_list { ospf_iface_finish(); }
|
ospf_iface_start ospf_iface_patt_list ospf_iface_opt_list { ospf_iface_finish(); }
|
||||||
;
|
;
|
||||||
|
|
||||||
CF_ADDTO(dynamic_attr, OSPF_METRIC1 { $$ = f_new_dynamic_attr(EAF_TYPE_INT | EAF_TEMP, T_INT, EA_OSPF_METRIC1); })
|
CF_ADDTO(dynamic_attr, OSPF_METRIC1 { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_OSPF_METRIC1); })
|
||||||
CF_ADDTO(dynamic_attr, OSPF_METRIC2 { $$ = f_new_dynamic_attr(EAF_TYPE_INT | EAF_TEMP, T_INT, EA_OSPF_METRIC2); })
|
CF_ADDTO(dynamic_attr, OSPF_METRIC2 { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_OSPF_METRIC2); })
|
||||||
CF_ADDTO(dynamic_attr, OSPF_TAG { $$ = f_new_dynamic_attr(EAF_TYPE_INT | EAF_TEMP, T_INT, EA_OSPF_TAG); })
|
CF_ADDTO(dynamic_attr, OSPF_TAG { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_OSPF_TAG); })
|
||||||
CF_ADDTO(dynamic_attr, OSPF_ROUTER_ID { $$ = f_new_dynamic_attr(EAF_TYPE_ROUTER_ID | EAF_TEMP, T_QUAD, EA_OSPF_ROUTER_ID); })
|
CF_ADDTO(dynamic_attr, OSPF_ROUTER_ID { $$ = f_new_dynamic_attr(EAF_TYPE_ROUTER_ID, T_QUAD, EA_OSPF_ROUTER_ID); })
|
||||||
|
|
||||||
CF_CLI_HELP(SHOW OSPF, ..., [[Show information about OSPF protocol]]);
|
CF_CLI_HELP(SHOW OSPF, ..., [[Show information about OSPF protocol]]);
|
||||||
CF_CLI(SHOW OSPF, optsym, [<name>], [[Show information about OSPF protocol]])
|
CF_CLI(SHOW OSPF, optsym, [<name>], [[Show information about OSPF protocol]])
|
||||||
|
|
|
@ -101,9 +101,9 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "ospf.h"
|
#include "ospf.h"
|
||||||
|
|
||||||
static int ospf_import_control(struct proto *P, rte **new, ea_list **attrs, struct linpool *pool);
|
static int ospf_import_control(struct proto *P, rte **new, struct linpool *pool);
|
||||||
static struct ea_list *ospf_make_tmp_attrs(struct rte *rt, struct linpool *pool);
|
static struct ea_list *ospf_make_tmp_attrs(struct rte *rt, struct linpool *pool);
|
||||||
static void ospf_store_tmp_attrs(struct rte *rt, struct ea_list *attrs);
|
static void ospf_store_tmp_attrs(struct rte *rt);
|
||||||
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 int ospf_rte_same(struct rte *new, struct rte *old);
|
static int ospf_rte_same(struct rte *new, struct rte *old);
|
||||||
|
@ -446,7 +446,7 @@ ospf_disp(timer * timer)
|
||||||
* import to the filters.
|
* import to the filters.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
ospf_import_control(struct proto *P, rte **new, ea_list **attrs UNUSED, struct linpool *pool UNUSED)
|
ospf_import_control(struct proto *P, rte **new, struct linpool *pool)
|
||||||
{
|
{
|
||||||
struct ospf_proto *p = (struct ospf_proto *) P;
|
struct ospf_proto *p = (struct ospf_proto *) P;
|
||||||
struct ospf_area *oa = ospf_main_area(p);
|
struct ospf_area *oa = ospf_main_area(p);
|
||||||
|
@ -471,12 +471,12 @@ ospf_make_tmp_attrs(struct rte *rt, struct linpool *pool)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ospf_store_tmp_attrs(struct rte *rt, struct ea_list *attrs)
|
ospf_store_tmp_attrs(struct rte *rt)
|
||||||
{
|
{
|
||||||
rt->u.ospf.metric1 = ea_get_int(attrs, EA_OSPF_METRIC1, LSINFINITY);
|
rt->u.ospf.metric1 = ea_get_int(rt->attrs->eattrs, EA_OSPF_METRIC1, LSINFINITY);
|
||||||
rt->u.ospf.metric2 = ea_get_int(attrs, EA_OSPF_METRIC2, 10000);
|
rt->u.ospf.metric2 = ea_get_int(rt->attrs->eattrs, EA_OSPF_METRIC2, 10000);
|
||||||
rt->u.ospf.tag = ea_get_int(attrs, EA_OSPF_TAG, 0);
|
rt->u.ospf.tag = ea_get_int(rt->attrs->eattrs, EA_OSPF_TAG, 0);
|
||||||
rt->u.ospf.router_id = ea_get_int(attrs, EA_OSPF_ROUTER_ID, 0);
|
rt->u.ospf.router_id = ea_get_int(rt->attrs->eattrs, EA_OSPF_ROUTER_ID, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -535,7 +535,7 @@ ospf_get_status(struct proto *P, byte * buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ospf_get_route_info(rte * rte, byte * buf, ea_list * attrs UNUSED)
|
ospf_get_route_info(rte * rte, byte * buf)
|
||||||
{
|
{
|
||||||
char *type = "<bug>";
|
char *type = "<bug>";
|
||||||
|
|
||||||
|
|
|
@ -1243,11 +1243,12 @@ 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, ea_list *ea)
|
ospf_rt_notify(struct proto *P, struct channel *ch UNUSED, net *n, rte *new, 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 */
|
||||||
ort *nf;
|
ort *nf;
|
||||||
|
struct ea_list *ea = new->attrs->eattrs;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* There are several posibilities:
|
* There are several posibilities:
|
||||||
|
|
|
@ -188,7 +188,7 @@ void ospf_originate_sum_net_lsa(struct ospf_proto *p, struct ospf_area *oa, ort
|
||||||
void ospf_originate_sum_rt_lsa(struct ospf_proto *p, struct ospf_area *oa, u32 drid, int metric, u32 options);
|
void ospf_originate_sum_rt_lsa(struct ospf_proto *p, struct ospf_area *oa, u32 drid, int metric, u32 options);
|
||||||
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);
|
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);
|
||||||
|
|
||||||
void ospf_rt_notify(struct proto *P, struct channel *ch, net *n, rte *new, rte *old, ea_list *attrs);
|
void ospf_rt_notify(struct proto *P, struct channel *ch, net *n, rte *new, 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);
|
||||||
|
|
|
@ -44,7 +44,7 @@
|
||||||
#include "pipe.h"
|
#include "pipe.h"
|
||||||
|
|
||||||
static void
|
static void
|
||||||
pipe_rt_notify(struct proto *P, struct channel *src_ch, net *n, rte *new, rte *old, ea_list *attrs)
|
pipe_rt_notify(struct proto *P, struct channel *src_ch, net *n, rte *new, 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;
|
||||||
|
@ -69,7 +69,6 @@ pipe_rt_notify(struct proto *P, struct channel *src_ch, net *n, rte *new, rte *o
|
||||||
memcpy(a, new->attrs, rta_size(new->attrs));
|
memcpy(a, new->attrs, rta_size(new->attrs));
|
||||||
|
|
||||||
a->aflags = 0;
|
a->aflags = 0;
|
||||||
a->eattrs = attrs;
|
|
||||||
a->hostentry = NULL;
|
a->hostentry = NULL;
|
||||||
e = rte_get_temp(a);
|
e = rte_get_temp(a);
|
||||||
e->pflags = 0;
|
e->pflags = 0;
|
||||||
|
@ -93,7 +92,7 @@ pipe_rt_notify(struct proto *P, struct channel *src_ch, net *n, rte *new, rte *o
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
pipe_import_control(struct proto *P, rte **ee, ea_list **ea UNUSED, struct linpool *p UNUSED)
|
pipe_import_control(struct proto *P, rte **ee, struct linpool *p UNUSED)
|
||||||
{
|
{
|
||||||
struct proto *pp = (*ee)->sender->proto;
|
struct proto *pp = (*ee)->sender->proto;
|
||||||
|
|
||||||
|
|
|
@ -395,7 +395,7 @@ radv_net_match_trigger(struct radv_config *cf, net *n)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
radv_import_control(struct proto *P, rte **new, ea_list **attrs UNUSED, struct linpool *pool UNUSED)
|
radv_import_control(struct proto *P, rte **new, struct linpool *pool 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);
|
||||||
|
@ -410,7 +410,7 @@ radv_import_control(struct proto *P, rte **new, ea_list **attrs UNUSED, struct l
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
radv_rt_notify(struct proto *P, struct channel *ch UNUSED, net *n, rte *new, rte *old UNUSED, ea_list *attrs)
|
radv_rt_notify(struct proto *P, struct channel *ch UNUSED, net *n, rte *new, 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);
|
||||||
|
@ -448,11 +448,11 @@ radv_rt_notify(struct proto *P, struct channel *ch UNUSED, net *n, rte *new, rte
|
||||||
{
|
{
|
||||||
/* Update */
|
/* Update */
|
||||||
|
|
||||||
ea = ea_find(attrs, EA_RA_PREFERENCE);
|
ea = ea_find(new->attrs->eattrs, EA_RA_PREFERENCE);
|
||||||
uint preference = ea ? ea->u.data : RA_PREF_MEDIUM;
|
uint preference = ea ? ea->u.data : RA_PREF_MEDIUM;
|
||||||
uint preference_set = !!ea;
|
uint preference_set = !!ea;
|
||||||
|
|
||||||
ea = ea_find(attrs, EA_RA_LIFETIME);
|
ea = ea_find(new->attrs->eattrs, EA_RA_LIFETIME);
|
||||||
uint lifetime = ea ? ea->u.data : 0;
|
uint lifetime = ea ? ea->u.data : 0;
|
||||||
uint lifetime_set = !!ea;
|
uint lifetime_set = !!ea;
|
||||||
|
|
||||||
|
|
|
@ -186,8 +186,8 @@ rip_iface:
|
||||||
rip_iface_start iface_patt_list_nopx rip_iface_opt_list rip_iface_finish;
|
rip_iface_start iface_patt_list_nopx rip_iface_opt_list rip_iface_finish;
|
||||||
|
|
||||||
|
|
||||||
CF_ADDTO(dynamic_attr, RIP_METRIC { $$ = f_new_dynamic_attr(EAF_TYPE_INT | EAF_TEMP, T_INT, EA_RIP_METRIC); })
|
CF_ADDTO(dynamic_attr, RIP_METRIC { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_RIP_METRIC); })
|
||||||
CF_ADDTO(dynamic_attr, RIP_TAG { $$ = f_new_dynamic_attr(EAF_TYPE_INT | EAF_TEMP, T_INT, EA_RIP_TAG); })
|
CF_ADDTO(dynamic_attr, RIP_TAG { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_RIP_TAG); })
|
||||||
|
|
||||||
CF_CLI_HELP(SHOW RIP, ..., [[Show information about RIP protocol]]);
|
CF_CLI_HELP(SHOW RIP, ..., [[Show information about RIP protocol]]);
|
||||||
|
|
||||||
|
|
|
@ -298,7 +298,7 @@ rip_withdraw_rte(struct rip_proto *p, net_addr *n, struct rip_neighbor *from)
|
||||||
*/
|
*/
|
||||||
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, struct network *net, struct rte *new,
|
||||||
struct rte *old UNUSED, struct ea_list *attrs)
|
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;
|
||||||
|
@ -307,8 +307,8 @@ rip_rt_notify(struct proto *P, struct channel *ch UNUSED, struct network *net, s
|
||||||
if (new)
|
if (new)
|
||||||
{
|
{
|
||||||
/* Update */
|
/* Update */
|
||||||
u32 rt_metric = ea_get_int(attrs, EA_RIP_METRIC, 1);
|
u32 rt_metric = ea_get_int(new->attrs->eattrs, EA_RIP_METRIC, 1);
|
||||||
u32 rt_tag = ea_get_int(attrs, EA_RIP_TAG, 0);
|
u32 rt_tag = ea_get_int(new->attrs->eattrs, EA_RIP_TAG, 0);
|
||||||
|
|
||||||
if (rt_metric > p->infinity)
|
if (rt_metric > p->infinity)
|
||||||
{
|
{
|
||||||
|
@ -1040,10 +1040,10 @@ rip_make_tmp_attrs(struct rte *rt, struct linpool *pool)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
rip_store_tmp_attrs(struct rte *rt, struct ea_list *attrs)
|
rip_store_tmp_attrs(struct rte *rt)
|
||||||
{
|
{
|
||||||
rt->u.rip.metric = ea_get_int(attrs, EA_RIP_METRIC, 1);
|
rt->u.rip.metric = ea_get_int(rt->attrs->eattrs, EA_RIP_METRIC, 1);
|
||||||
rt->u.rip.tag = ea_get_int(attrs, EA_RIP_TAG, 0);
|
rt->u.rip.tag = ea_get_int(rt->attrs->eattrs, EA_RIP_TAG, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -1081,7 +1081,6 @@ rip_init(struct proto_config *CF)
|
||||||
P->if_notify = rip_if_notify;
|
P->if_notify = rip_if_notify;
|
||||||
P->rt_notify = rip_rt_notify;
|
P->rt_notify = rip_rt_notify;
|
||||||
P->neigh_notify = rip_neigh_notify;
|
P->neigh_notify = rip_neigh_notify;
|
||||||
// P->import_control = rip_import_control;
|
|
||||||
P->reload_routes = rip_reload_routes;
|
P->reload_routes = rip_reload_routes;
|
||||||
P->make_tmp_attrs = rip_make_tmp_attrs;
|
P->make_tmp_attrs = rip_make_tmp_attrs;
|
||||||
P->store_tmp_attrs = rip_store_tmp_attrs;
|
P->store_tmp_attrs = rip_store_tmp_attrs;
|
||||||
|
@ -1145,7 +1144,7 @@ rip_reconfigure(struct proto *P, struct proto_config *CF)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
rip_get_route_info(rte *rte, byte *buf, ea_list *attrs UNUSED)
|
rip_get_route_info(rte *rte, byte *buf)
|
||||||
{
|
{
|
||||||
buf += bsprintf(buf, " (%d/%d)", rte->pref, rte->u.rip.metric);
|
buf += bsprintf(buf, " (%d/%d)", rte->pref, rte->u.rip.metric);
|
||||||
|
|
||||||
|
|
|
@ -347,8 +347,7 @@ krt_send_route(struct krt_proto *p, int cmd, rte *e)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
krt_replace_rte(struct krt_proto *p, net *n, rte *new, rte *old,
|
krt_replace_rte(struct krt_proto *p, net *n, rte *new, rte *old)
|
||||||
struct ea_list *eattrs UNUSED)
|
|
||||||
{
|
{
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
|
|
|
@ -1177,11 +1177,12 @@ nh_bufsize(struct nexthop *nh)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
nl_send_route(struct krt_proto *p, rte *e, struct ea_list *eattrs, int op, int dest, struct nexthop *nh)
|
nl_send_route(struct krt_proto *p, rte *e, int op, int dest, struct nexthop *nh)
|
||||||
{
|
{
|
||||||
eattr *ea;
|
eattr *ea;
|
||||||
net *net = e->net;
|
net *net = e->net;
|
||||||
rta *a = e->attrs;
|
rta *a = e->attrs;
|
||||||
|
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));
|
||||||
u32 priority = 0;
|
u32 priority = 0;
|
||||||
|
|
||||||
|
@ -1328,7 +1329,7 @@ dest:
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
nl_add_rte(struct krt_proto *p, rte *e, struct ea_list *eattrs)
|
nl_add_rte(struct krt_proto *p, rte *e)
|
||||||
{
|
{
|
||||||
rta *a = e->attrs;
|
rta *a = e->attrs;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
@ -1337,34 +1338,34 @@ nl_add_rte(struct krt_proto *p, rte *e, struct ea_list *eattrs)
|
||||||
{
|
{
|
||||||
struct nexthop *nh = &(a->nh);
|
struct nexthop *nh = &(a->nh);
|
||||||
|
|
||||||
err = nl_send_route(p, e, eattrs, NL_OP_ADD, RTD_UNICAST, nh);
|
err = nl_send_route(p, e, NL_OP_ADD, RTD_UNICAST, nh);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
for (nh = nh->next; nh; nh = nh->next)
|
for (nh = nh->next; nh; nh = nh->next)
|
||||||
err += nl_send_route(p, e, eattrs, NL_OP_APPEND, RTD_UNICAST, nh);
|
err += nl_send_route(p, e, NL_OP_APPEND, RTD_UNICAST, nh);
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
return nl_send_route(p, e, eattrs, NL_OP_ADD, a->dest, &(a->nh));
|
return nl_send_route(p, e, NL_OP_ADD, a->dest, &(a->nh));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
nl_delete_rte(struct krt_proto *p, rte *e, struct ea_list *eattrs)
|
nl_delete_rte(struct krt_proto *p, rte *e)
|
||||||
{
|
{
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
/* For IPv6, we just repeatedly request DELETE until we get error */
|
/* For IPv6, we just repeatedly request DELETE until we get error */
|
||||||
do
|
do
|
||||||
err = nl_send_route(p, e, eattrs, NL_OP_DELETE, RTD_NONE, NULL);
|
err = nl_send_route(p, e, NL_OP_DELETE, RTD_NONE, NULL);
|
||||||
while (krt_ecmp6(p) && !err);
|
while (krt_ecmp6(p) && !err);
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
krt_replace_rte(struct krt_proto *p, net *n, rte *new, rte *old, struct ea_list *eattrs)
|
krt_replace_rte(struct krt_proto *p, net *n, rte *new, rte *old)
|
||||||
{
|
{
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
|
@ -1380,10 +1381,10 @@ krt_replace_rte(struct krt_proto *p, net *n, rte *new, rte *old, struct ea_list
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (old)
|
if (old)
|
||||||
nl_delete_rte(p, old, eattrs);
|
nl_delete_rte(p, old);
|
||||||
|
|
||||||
if (new)
|
if (new)
|
||||||
err = nl_add_rte(p, new, eattrs);
|
err = nl_add_rte(p, new);
|
||||||
|
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
n->n.flags |= KRF_SYNC_ERROR;
|
n->n.flags |= KRF_SYNC_ERROR;
|
||||||
|
|
|
@ -122,8 +122,8 @@ kif_iface:
|
||||||
kif_iface_start iface_patt_list_nopx kif_iface_opt_list;
|
kif_iface_start iface_patt_list_nopx kif_iface_opt_list;
|
||||||
|
|
||||||
|
|
||||||
CF_ADDTO(dynamic_attr, KRT_SOURCE { $$ = f_new_dynamic_attr(EAF_TYPE_INT | EAF_TEMP, T_INT, EA_KRT_SOURCE); })
|
CF_ADDTO(dynamic_attr, KRT_SOURCE { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_KRT_SOURCE); })
|
||||||
CF_ADDTO(dynamic_attr, KRT_METRIC { $$ = f_new_dynamic_attr(EAF_TYPE_INT | EAF_TEMP, T_INT, EA_KRT_METRIC); })
|
CF_ADDTO(dynamic_attr, KRT_METRIC { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_KRT_METRIC); })
|
||||||
|
|
||||||
CF_CODE
|
CF_CODE
|
||||||
|
|
||||||
|
|
|
@ -551,7 +551,7 @@ krt_flush_routes(struct krt_proto *p)
|
||||||
if (rte_is_valid(e) && (n->n.flags & KRF_INSTALLED))
|
if (rte_is_valid(e) && (n->n.flags & KRF_INSTALLED))
|
||||||
{
|
{
|
||||||
/* 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, e->net, NULL, e, NULL);
|
krt_replace_rte(p, e->net, NULL, e);
|
||||||
n->n.flags &= ~KRF_INSTALLED;
|
n->n.flags &= ~KRF_INSTALLED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -559,14 +559,14 @@ krt_flush_routes(struct krt_proto *p)
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct rte *
|
static struct rte *
|
||||||
krt_export_net(struct krt_proto *p, net *net, rte **rt_free, ea_list **tmpa)
|
krt_export_net(struct krt_proto *p, net *net, rte **rt_free)
|
||||||
{
|
{
|
||||||
struct channel *c = p->p.main_channel;
|
struct channel *c = p->p.main_channel;
|
||||||
struct filter *filter = c->out_filter;
|
struct filter *filter = c->out_filter;
|
||||||
rte *rt;
|
rte *rt;
|
||||||
|
|
||||||
if (c->ra_mode == RA_MERGED)
|
if (c->ra_mode == RA_MERGED)
|
||||||
return rt_export_merged(c, net, rt_free, tmpa, krt_filter_lp, 1);
|
return rt_export_merged(c, net, rt_free, krt_filter_lp, 1);
|
||||||
|
|
||||||
rt = net->routes;
|
rt = net->routes;
|
||||||
*rt_free = NULL;
|
*rt_free = NULL;
|
||||||
|
@ -577,15 +577,14 @@ krt_export_net(struct krt_proto *p, net *net, rte **rt_free, ea_list **tmpa)
|
||||||
if (filter == FILTER_REJECT)
|
if (filter == FILTER_REJECT)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
struct proto *src = rt->attrs->src->proto;
|
rte_make_tmp_attrs(&rt, krt_filter_lp);
|
||||||
*tmpa = src->make_tmp_attrs ? src->make_tmp_attrs(rt, krt_filter_lp) : NULL;
|
|
||||||
|
|
||||||
/* We could run krt_import_control() here, but it is already handled by KRF_INSTALLED */
|
/* We could run krt_import_control() here, but it is already handled by KRF_INSTALLED */
|
||||||
|
|
||||||
if (filter == FILTER_ACCEPT)
|
if (filter == FILTER_ACCEPT)
|
||||||
goto accept;
|
goto accept;
|
||||||
|
|
||||||
if (f_run(filter, &rt, tmpa, krt_filter_lp, FF_FORCE_TMPATTR | FF_SILENT) > F_ACCEPT)
|
if (f_run(filter, &rt, krt_filter_lp, FF_SILENT) > F_ACCEPT)
|
||||||
goto reject;
|
goto reject;
|
||||||
|
|
||||||
|
|
||||||
|
@ -667,9 +666,8 @@ krt_got_route(struct krt_proto *p, rte *e)
|
||||||
if (net->n.flags & KRF_INSTALLED)
|
if (net->n.flags & KRF_INSTALLED)
|
||||||
{
|
{
|
||||||
rte *new, *rt_free;
|
rte *new, *rt_free;
|
||||||
ea_list *tmpa;
|
|
||||||
|
|
||||||
new = krt_export_net(p, net, &rt_free, &tmpa);
|
new = krt_export_net(p, net, &rt_free);
|
||||||
|
|
||||||
/* TODO: There also may be changes in route eattrs, we ignore that for now. */
|
/* TODO: There also may be changes in route eattrs, we ignore that for now. */
|
||||||
|
|
||||||
|
@ -714,7 +712,6 @@ krt_prune(struct krt_proto *p)
|
||||||
{
|
{
|
||||||
int verdict = n->n.flags & KRF_VERDICT_MASK;
|
int verdict = n->n.flags & KRF_VERDICT_MASK;
|
||||||
rte *new, *old, *rt_free = NULL;
|
rte *new, *old, *rt_free = NULL;
|
||||||
ea_list *tmpa = NULL;
|
|
||||||
|
|
||||||
if (verdict == KRF_UPDATE || verdict == KRF_DELETE)
|
if (verdict == KRF_UPDATE || verdict == KRF_DELETE)
|
||||||
{
|
{
|
||||||
|
@ -728,12 +725,10 @@ krt_prune(struct krt_proto *p)
|
||||||
if (verdict == KRF_CREATE || verdict == KRF_UPDATE)
|
if (verdict == KRF_CREATE || verdict == KRF_UPDATE)
|
||||||
{
|
{
|
||||||
/* We have to run export filter to get proper 'new' route */
|
/* We have to run export filter to get proper 'new' route */
|
||||||
new = krt_export_net(p, n, &rt_free, &tmpa);
|
new = krt_export_net(p, n, &rt_free);
|
||||||
|
|
||||||
if (!new)
|
if (!new)
|
||||||
verdict = (verdict == KRF_CREATE) ? KRF_IGNORE : KRF_DELETE;
|
verdict = (verdict == KRF_CREATE) ? KRF_IGNORE : KRF_DELETE;
|
||||||
else
|
|
||||||
tmpa = ea_append(tmpa, new->attrs->eattrs);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
new = NULL;
|
new = NULL;
|
||||||
|
@ -744,7 +739,7 @@ krt_prune(struct krt_proto *p)
|
||||||
if (new && (n->n.flags & KRF_INSTALLED))
|
if (new && (n->n.flags & KRF_INSTALLED))
|
||||||
{
|
{
|
||||||
krt_trace_in(p, new, "reinstalling");
|
krt_trace_in(p, new, "reinstalling");
|
||||||
krt_replace_rte(p, n, new, NULL, tmpa);
|
krt_replace_rte(p, n, new, NULL);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case KRF_SEEN:
|
case KRF_SEEN:
|
||||||
|
@ -753,11 +748,11 @@ krt_prune(struct krt_proto *p)
|
||||||
break;
|
break;
|
||||||
case KRF_UPDATE:
|
case KRF_UPDATE:
|
||||||
krt_trace_in(p, new, "updating");
|
krt_trace_in(p, new, "updating");
|
||||||
krt_replace_rte(p, n, new, old, tmpa);
|
krt_replace_rte(p, n, new, old);
|
||||||
break;
|
break;
|
||||||
case KRF_DELETE:
|
case KRF_DELETE:
|
||||||
krt_trace_in(p, old, "deleting");
|
krt_trace_in(p, old, "deleting");
|
||||||
krt_replace_rte(p, n, NULL, old, NULL);
|
krt_replace_rte(p, n, NULL, old);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
bug("krt_prune: invalid route status");
|
bug("krt_prune: invalid route status");
|
||||||
|
@ -795,7 +790,7 @@ krt_got_route_async(struct krt_proto *p, rte *e, int new)
|
||||||
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, NULL);
|
krt_replace_rte(p, net, NULL, e);
|
||||||
}
|
}
|
||||||
/* If !new, it is probably echo of our deletion */
|
/* If !new, it is probably echo of our deletion */
|
||||||
break;
|
break;
|
||||||
|
@ -937,14 +932,14 @@ krt_make_tmp_attrs(rte *rt, struct linpool *pool)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
krt_store_tmp_attrs(rte *rt, struct ea_list *attrs)
|
krt_store_tmp_attrs(rte *rt)
|
||||||
{
|
{
|
||||||
/* EA_KRT_SOURCE is read-only */
|
/* EA_KRT_SOURCE is read-only */
|
||||||
rt->u.krt.metric = ea_get_int(attrs, EA_KRT_METRIC, 0);
|
rt->u.krt.metric = ea_get_int(rt->attrs->eattrs, EA_KRT_METRIC, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
krt_import_control(struct proto *P, rte **new, ea_list **attrs UNUSED, struct linpool *pool UNUSED)
|
krt_import_control(struct proto *P, rte **new, struct linpool *pool UNUSED)
|
||||||
{
|
{
|
||||||
// struct krt_proto *p = (struct krt_proto *) P;
|
// struct krt_proto *p = (struct krt_proto *) P;
|
||||||
rte *e = *new;
|
rte *e = *new;
|
||||||
|
@ -975,7 +970,7 @@ krt_import_control(struct proto *P, rte **new, ea_list **attrs UNUSED, struct li
|
||||||
|
|
||||||
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, net *net,
|
||||||
rte *new, rte *old, struct ea_list *eattrs)
|
rte *new, rte *old)
|
||||||
{
|
{
|
||||||
struct krt_proto *p = (struct krt_proto *) P;
|
struct krt_proto *p = (struct krt_proto *) P;
|
||||||
|
|
||||||
|
@ -988,7 +983,7 @@ krt_rt_notify(struct proto *P, struct channel *ch UNUSED, net *net,
|
||||||
else
|
else
|
||||||
net->n.flags &= ~KRF_INSTALLED;
|
net->n.flags &= ~KRF_INSTALLED;
|
||||||
if (p->initialized) /* Before first scan we don't touch the routes */
|
if (p->initialized) /* Before first scan we don't touch the routes */
|
||||||
krt_replace_rte(p, net, new, old, eattrs);
|
krt_replace_rte(p, net, new, old);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
@ -139,7 +139,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, struct ea_list *eattrs);
|
void krt_replace_rte(struct krt_proto *p, net *n, rte *new, rte *old);
|
||||||
int krt_sys_get_attr(eattr *a, byte *buf, int buflen);
|
int krt_sys_get_attr(eattr *a, byte *buf, int buflen);
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue