summaryrefslogtreecommitdiff
path: root/nest
diff options
context:
space:
mode:
Diffstat (limited to 'nest')
-rw-r--r--nest/route.h4
-rw-r--r--nest/rt-attr.c10
-rw-r--r--nest/rt-dev.c3
-rw-r--r--nest/rt-show.c6
-rw-r--r--nest/rt-table.c51
5 files changed, 38 insertions, 36 deletions
diff --git a/nest/route.h b/nest/route.h
index aec867e2..1dea058f 100644
--- a/nest/route.h
+++ b/nest/route.h
@@ -236,6 +236,7 @@ struct hostentry {
typedef struct rte {
struct rte *next;
net *net; /* Network this RTE belongs to */
+ struct rte_src *src; /* Route source that created the route */
struct channel *sender; /* Channel used to send the route to the routing table */
struct rta *attrs; /* Attributes of this route */
u32 id; /* Table specific route id */
@@ -326,7 +327,7 @@ static inline net *net_get(rtable *tab, const net_addr *addr) { return (net *) f
void *net_route(rtable *tab, const net_addr *n);
int net_roa_check(rtable *tab, const net_addr *n, u32 asn);
rte *rte_find(net *net, struct rte_src *src);
-rte *rte_get_temp(struct rta *);
+rte *rte_get_temp(struct rta *, 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 */
int rt_examine(rtable *t, net_addr *a, struct proto *p, const struct filter *filter);
@@ -441,7 +442,6 @@ typedef struct rta {
u32 uc; /* Use count */
u32 hash_key; /* Hash over important fields */
struct ea_list *eattrs; /* Extended Attribute chain */
- struct rte_src *src; /* Route source that created the route */
struct hostentry *hostentry; /* Hostentry for recursive next-hops */
ip_addr from; /* Advertising router */
u32 igp_metric; /* IGP metric to next hop (for iBGP routes) */
diff --git a/nest/rt-attr.c b/nest/rt-attr.c
index 4198b552..4057bf37 100644
--- a/nest/rt-attr.c
+++ b/nest/rt-attr.c
@@ -1105,7 +1105,6 @@ rta_hash(rta *a)
mem_hash_init(&h);
#define MIX(f) mem_hash_mix(&h, &(a->f), sizeof(a->f));
#define BMIX(f) mem_hash_mix_num(&h, a->f);
- MIX(src);
MIX(hostentry);
MIX(from);
MIX(igp_metric);
@@ -1121,8 +1120,7 @@ rta_hash(rta *a)
static inline int
rta_same(rta *x, rta *y)
{
- return (x->src == y->src &&
- x->source == y->source &&
+ return (x->source == y->source &&
x->scope == y->scope &&
x->dest == y->dest &&
x->igp_metric == y->igp_metric &&
@@ -1212,7 +1210,6 @@ rta_lookup(rta *o)
r = rta_copy(o);
r->hash_key = h;
r->cached = 1;
- rt_lock_source(r->src);
rt_lock_hostentry(r->hostentry);
rta_insert(r);
@@ -1231,7 +1228,6 @@ rta__free(rta *a)
if (a->next)
a->next->pprev = a->pprev;
rt_unlock_hostentry(a->hostentry);
- rt_unlock_source(a->src);
if (a->nh.next)
nexthop_free(a->nh.next);
ea_free(a->eattrs);
@@ -1270,8 +1266,8 @@ rta_dump(rta *a)
"RTS_OSPF_EXT2", "RTS_BGP", "RTS_PIPE", "RTS_BABEL" };
static char *rtd[] = { "", " DEV", " HOLE", " UNREACH", " PROHIBIT" };
- debug("p=%s pref=%d uc=%d %s %s%s h=%04x",
- a->src->proto->name, a->pref, a->uc, rts[a->source], ip_scope_text(a->scope),
+ debug("pref=%d uc=%d %s %s%s h=%04x",
+ a->pref, a->uc, rts[a->source], ip_scope_text(a->scope),
rtd[a->dest], a->hash_key);
if (!a->cached)
debug(" !CACHED");
diff --git a/nest/rt-dev.c b/nest/rt-dev.c
index b8e945cf..e2e65926 100644
--- a/nest/rt-dev.c
+++ b/nest/rt-dev.c
@@ -83,7 +83,6 @@ dev_ifa_notify(struct proto *P, uint flags, struct ifa *ad)
struct rte_src *src = rt_get_source(P, ad->iface->index);
rta a0 = {
- .src = src,
.pref = c->preference,
.source = RTS_DEVICE,
.scope = SCOPE_UNIVERSE,
@@ -92,7 +91,7 @@ dev_ifa_notify(struct proto *P, uint flags, struct ifa *ad)
};
a = rta_lookup(&a0);
- e = rte_get_temp(a);
+ e = rte_get_temp(a, src);
e->pflags = 0;
rte_update2(c, net, e, src);
}
diff --git a/nest/rt-show.c b/nest/rt-show.c
index a0c675de..05065134 100644
--- a/nest/rt-show.c
+++ b/nest/rt-show.c
@@ -56,7 +56,7 @@ rt_show_rte(struct cli *c, byte *ia, rte *e, struct rt_show_data *d, int primary
if (d->verbose && !rta_is_cached(a) && a->eattrs)
ea_normalize(a->eattrs);
- get_route_info = a->src->proto->proto->get_route_info;
+ get_route_info = e->src->proto->proto->get_route_info;
if (get_route_info)
get_route_info(e, info);
else
@@ -66,7 +66,7 @@ rt_show_rte(struct cli *c, byte *ia, rte *e, struct rt_show_data *d, int primary
rt_show_table(c, d);
cli_printf(c, -1007, "%-20s %s [%s %s%s]%s%s", ia, rta_dest_name(a->dest),
- a->src->proto->name, tm, from, primary ? (sync_error ? " !" : " *") : "", info);
+ e->src->proto->name, tm, from, primary ? (sync_error ? " !" : " *") : "", info);
if (a->dest == RTD_UNICAST)
for (nh = &(a->nh); nh; nh = nh->next)
@@ -180,7 +180,7 @@ 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->src->proto))
goto skip;
if (f_run(d->filter, &e, c->show_pool, 0) > F_ACCEPT)
diff --git a/nest/rt-table.c b/nest/rt-table.c
index 0b06be92..a869bb18 100644
--- a/nest/rt-table.c
+++ b/nest/rt-table.c
@@ -264,7 +264,7 @@ rte_find(net *net, struct rte_src *src)
{
rte *e = net->routes;
- while (e && e->attrs->src != src)
+ while (e && e->src != src)
e = e->next;
return e;
}
@@ -279,13 +279,14 @@ rte_find(net *net, struct rte_src *src)
* the protocol.
*/
rte *
-rte_get_temp(rta *a)
+rte_get_temp(rta *a, struct rte_src *src)
{
rte *e = sl_alloc(rte_slab);
e->attrs = a;
e->id = 0;
e->flags = 0;
+ rt_lock_source(e->src = src);
return e;
}
@@ -295,6 +296,8 @@ rte_do_cow(rte *r)
rte *e = sl_alloc(rte_slab);
memcpy(e, r, sizeof(rte));
+
+ rt_lock_source(e->src);
e->attrs = rta_clone(r->attrs);
e->flags = 0;
return e;
@@ -341,6 +344,7 @@ rte_cow_rta(rte *r, linpool *lp)
void
rte_free(rte *e)
{
+ rt_unlock_source(e->src);
if (rta_is_cached(e->attrs))
rta_free(e->attrs);
sl_free(rte_slab, e);
@@ -349,6 +353,7 @@ rte_free(rte *e)
static inline void
rte_free_quick(rte *e)
{
+ rt_unlock_source(e->src);
rta_free(e->attrs);
sl_free(rte_slab, e);
}
@@ -473,7 +478,7 @@ void
rte_make_tmp_attrs(rte **r, linpool *lp, rta **old_attrs)
{
void (*make_tmp_attrs)(rte *r, linpool *lp);
- make_tmp_attrs = (*r)->attrs->src->proto->make_tmp_attrs;
+ make_tmp_attrs = (*r)->src->proto->make_tmp_attrs;
if (!make_tmp_attrs)
return;
@@ -502,7 +507,7 @@ static void
rte_store_tmp_attrs(rte *r, linpool *lp, rta *old_attrs)
{
void (*store_tmp_attrs)(rte *rt, linpool *lp);
- store_tmp_attrs = r->attrs->src->proto->store_tmp_attrs;
+ store_tmp_attrs = r->src->proto->store_tmp_attrs;
if (!store_tmp_attrs)
return;
@@ -536,16 +541,16 @@ rte_better(rte *new, rte *old)
return 1;
if (new->attrs->pref < old->attrs->pref)
return 0;
- if (new->attrs->src->proto->proto != old->attrs->src->proto->proto)
+ if (new->src->proto->proto != old->src->proto->proto)
{
/*
* If the user has configured protocol preferences, so that two different protocols
* have the same preference, try to break the tie by comparing addresses. Not too
* useful, but keeps the ordering of routes unambiguous.
*/
- return new->attrs->src->proto->proto > old->attrs->src->proto->proto;
+ return new->src->proto->proto > old->src->proto->proto;
}
- if (better = new->attrs->src->proto->rte_better)
+ if (better = new->src->proto->rte_better)
return better(new, old);
return 0;
}
@@ -561,10 +566,10 @@ rte_mergable(rte *pri, rte *sec)
if (pri->attrs->pref != sec->attrs->pref)
return 0;
- if (pri->attrs->src->proto->proto != sec->attrs->src->proto->proto)
+ if (pri->src->proto->proto != sec->src->proto->proto)
return 0;
- if (mergable = pri->attrs->src->proto->rte_mergable)
+ if (mergable = pri->src->proto->rte_mergable)
return mergable(pri, sec);
return 0;
@@ -1079,7 +1084,8 @@ rte_same(rte *x, rte *y)
return
x->attrs == y->attrs &&
x->pflags == y->pflags &&
- (!x->attrs->src->proto->rte_same || x->attrs->src->proto->rte_same(x, y)) &&
+ x->src == y->src &&
+ (!x->src->proto->rte_same || x->src->proto->rte_same(x, y)) &&
rte_is_filtered(x) == rte_is_filtered(y);
}
@@ -1100,7 +1106,7 @@ rte_recalculate(struct channel *c, net *net, rte *new, struct rte_src *src)
k = &net->routes; /* Find and remove original route from the same protocol */
while (old = *k)
{
- if (old->attrs->src == src)
+ if (old->src == src)
{
/* If there is the same route in the routing table but from
* a different sender, then there are two paths from the
@@ -1561,7 +1567,7 @@ static inline void
rte_discard(rte *old) /* Non-filtered route deletion, used during garbage collection */
{
rte_update_lock();
- rte_recalculate(old->sender, old->net, NULL, old->attrs->src);
+ rte_recalculate(old->sender, old->net, NULL, old->src);
rte_update_unlock();
}
@@ -1581,7 +1587,7 @@ rte_modify(rte *old)
new->flags = (old->flags & ~REF_MODIFY) | REF_COW;
}
- rte_recalculate(old->sender, old->net, new, old->attrs->src);
+ rte_recalculate(old->sender, old->net, new, old->src);
}
rte_update_unlock();
@@ -1707,8 +1713,8 @@ rte_dump(rte *e)
debug("%-1N ", n->n.addr);
debug("PF=%02x ", e->pflags);
rta_dump(e->attrs);
- if (e->attrs->src->proto->proto->dump_attrs)
- e->attrs->src->proto->proto->dump_attrs(e);
+ if (e->src->proto->proto->dump_attrs)
+ e->src->proto->proto->dump_attrs(e);
debug("\n");
}
@@ -2222,6 +2228,7 @@ rt_next_hop_update_rte(rtable *tab UNUSED, rte *old)
rte *e = sl_alloc(rte_slab);
memcpy(e, old, sizeof(rte));
e->attrs = rta_lookup(a);
+ rt_lock_source(e->src);
return e;
}
@@ -2248,8 +2255,8 @@ rt_next_hop_update_net(rtable *tab, net *n)
/* Call a pre-comparison hook */
/* Not really an efficient way to compute this */
- if (e->attrs->src->proto->rte_recalculate)
- e->attrs->src->proto->rte_recalculate(tab, n, new, e, NULL);
+ if (e->src->proto->rte_recalculate)
+ e->src->proto->rte_recalculate(tab, n, new, e, NULL);
if (e != old_best)
rte_free_quick(e);
@@ -2584,7 +2591,7 @@ rte_update_in(struct channel *c, const net_addr *n, rte *new, struct rte_src *sr
/* Find the old rte */
for (pos = &net->routes; old = *pos; pos = &old->next)
- if (old->attrs->src == src)
+ if (old->src == src)
{
if (new && rte_same(old, new))
{
@@ -2689,7 +2696,7 @@ rt_reload_channel(struct channel *c)
return 0;
}
- rte_update2(c, e->net->n.addr, rte_do_cow(e), e->attrs->src);
+ rte_update2(c, e->net->n.addr, rte_do_cow(e), e->src);
}
c->reload_next_rte = NULL;
@@ -2772,7 +2779,7 @@ rte_update_out(struct channel *c, const net_addr *n, rte *new, rte *old0, rte **
if (new)
{
net = net_get(tab, n);
- src = new->attrs->src;
+ src = new->src;
rte_store_tmp_attrs(new, rte_update_pool, NULL);
@@ -2782,7 +2789,7 @@ rte_update_out(struct channel *c, const net_addr *n, rte *new, rte *old0, rte **
else
{
net = net_find(tab, n);
- src = old0->attrs->src;
+ src = old0->src;
if (!net)
goto drop_withdraw;
@@ -2790,7 +2797,7 @@ rte_update_out(struct channel *c, const net_addr *n, rte *new, rte *old0, rte **
/* Find the old rte */
for (pos = &net->routes; old = *pos; pos = &old->next)
- if ((c->ra_mode != RA_ANY) || (old->attrs->src == src))
+ if ((c->ra_mode != RA_ANY) || (old->src == src))
{
if (new && rte_same(old, new))
{