summaryrefslogtreecommitdiff
path: root/proto
diff options
context:
space:
mode:
Diffstat (limited to 'proto')
-rw-r--r--proto/babel/babel.c111
-rw-r--r--proto/babel/babel.h1
-rw-r--r--proto/bfd/io.c2
-rw-r--r--proto/bgp/attrs.c91
-rw-r--r--proto/bgp/bgp.c24
-rw-r--r--proto/bgp/bgp.h12
-rw-r--r--proto/bgp/packets.c17
-rw-r--r--proto/mrt/mrt.c10
-rw-r--r--proto/ospf/iface.c3
-rw-r--r--proto/ospf/ospf.c82
-rw-r--r--proto/ospf/rt.c54
-rw-r--r--proto/perf/perf.c4
-rw-r--r--proto/pipe/pipe.c30
-rw-r--r--proto/radv/radv.c4
-rw-r--r--proto/rip/rip.c80
-rw-r--r--proto/rip/rip.h1
-rw-r--r--proto/rpki/rpki.c6
-rw-r--r--proto/static/static.c13
18 files changed, 277 insertions, 268 deletions
diff --git a/proto/babel/babel.c b/proto/babel/babel.c
index 174fc9e2..30809000 100644
--- a/proto/babel/babel.c
+++ b/proto/babel/babel.c
@@ -641,13 +641,36 @@ babel_announce_rte(struct babel_proto *p, struct babel_entry *e)
if (r)
{
rta a0 = {
- .src = p->p.main_source,
.source = RTS_BABEL,
.scope = SCOPE_UNIVERSE,
.dest = RTD_UNICAST,
+ .pref = c->preference,
.from = r->neigh->addr,
.nh.gw = r->next_hop,
.nh.iface = r->neigh->ifa->iface,
+ .eattrs = alloca(sizeof(ea_list) + 3*sizeof(eattr)),
+ };
+
+ *a0.eattrs = (ea_list) { .count = 3 };
+ a0.eattrs->attrs[0] = (eattr) {
+ .id = EA_BABEL_METRIC,
+ .type = EAF_TYPE_INT,
+ .u.data = r->metric,
+ };
+
+ struct adata *ad = alloca(sizeof(struct adata) + sizeof(u64));
+ ad->length = sizeof(u64);
+ memcpy(ad->data, &(r->router_id), sizeof(u64));
+ a0.eattrs->attrs[1] = (eattr) {
+ .id = EA_BABEL_ROUTER_ID,
+ .type = EAF_TYPE_OPAQUE,
+ .u.ptr = ad,
+ };
+
+ a0.eattrs->attrs[2] = (eattr) {
+ .id = EA_BABEL_SEQNO,
+ .type = EAF_TYPE_INT,
+ .u.data = r->seqno,
};
/*
@@ -659,11 +682,7 @@ babel_announce_rte(struct babel_proto *p, struct babel_entry *e)
a0.nh.flags = RNF_ONLINK;
rta *a = rta_lookup(&a0);
- rte *rte = rte_get_temp(a);
- rte->u.babel.seqno = r->seqno;
- rte->u.babel.metric = r->metric;
- rte->u.babel.router_id = r->router_id;
- rte->pflags = EA_ID_FLAG(EA_BABEL_METRIC) | EA_ID_FLAG(EA_BABEL_ROUTER_ID);
+ rte *rte = rte_get_temp(a, p->p.main_source);
e->unreachable = 0;
rte_update2(c, e->n.addr, rte, p->p.main_source);
@@ -672,17 +691,15 @@ babel_announce_rte(struct babel_proto *p, struct babel_entry *e)
{
/* Unreachable */
rta a0 = {
- .src = p->p.main_source,
.source = RTS_BABEL,
.scope = SCOPE_UNIVERSE,
.dest = RTD_UNREACHABLE,
+ .pref = 1,
};
rta *a = rta_lookup(&a0);
- rte *rte = rte_get_temp(a);
- memset(&rte->u.babel, 0, sizeof(rte->u.babel));
+ rte *rte = rte_get_temp(a, p->p.main_source);
rte->pflags = 0;
- rte->pref = 1;
e->unreachable = 1;
rte_update2(c, e->n.addr, rte, p->p.main_source);
@@ -2010,7 +2027,13 @@ babel_dump(struct proto *P)
static void
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);
+ u64 rid = 0;
+ eattr *e = ea_find(rte->attrs->eattrs, EA_BABEL_ROUTER_ID);
+ if (e)
+ memcpy(&rid, e->u.ptr->data, sizeof(u64));
+
+ buf += bsprintf(buf, " (%d/%d) [%lR]", rte->attrs->pref,
+ ea_get_int(rte->attrs->eattrs, EA_BABEL_METRIC, BABEL_INFINITY), rid);
}
static int
@@ -2018,6 +2041,9 @@ babel_get_attr(const eattr *a, byte *buf, int buflen UNUSED)
{
switch (a->id)
{
+ case EA_BABEL_SEQNO:
+ return GA_FULL;
+
case EA_BABEL_METRIC:
bsprintf(buf, "metric: %d", a->u.data);
return GA_FULL;
@@ -2231,38 +2257,16 @@ babel_kick_timer(struct babel_proto *p)
static int
-babel_preexport(struct proto *P, struct rte **new, struct linpool *pool UNUSED)
+babel_preexport(struct proto *P, struct rte *new)
{
- struct rta *a = (*new)->attrs;
-
+ struct rta *a = new->attrs;
/* Reject our own unreachable routes */
- if ((a->dest == RTD_UNREACHABLE) && (a->src->proto == P))
+ if ((a->dest == RTD_UNREACHABLE) && (new->src->proto == P))
return -1;
return 0;
}
-static void
-babel_make_tmp_attrs(struct rte *rt, struct linpool *pool)
-{
- struct adata *id = lp_alloc_adata(pool, sizeof(u64));
- memcpy(id->data, &rt->u.babel.router_id, sizeof(u64));
-
- rte_init_tmp_attrs(rt, pool, 2);
- rte_make_tmp_attr(rt, EA_BABEL_METRIC, EAF_TYPE_INT, rt->u.babel.metric);
- rte_make_tmp_attr(rt, EA_BABEL_ROUTER_ID, EAF_TYPE_OPAQUE, (uintptr_t) id);
-}
-
-static void
-babel_store_tmp_attrs(struct rte *rt, struct linpool *pool)
-{
- rte_init_tmp_attrs(rt, pool, 2);
- rt->u.babel.metric = rte_store_tmp_attr(rt, EA_BABEL_METRIC);
-
- /* EA_BABEL_ROUTER_ID is read-only, we do not really save the value */
- rte_store_tmp_attr(rt, EA_BABEL_ROUTER_ID);
-}
-
/*
* babel_rt_notify - core tells us about new route (possibly our own),
* so store it into our data structures.
@@ -2277,10 +2281,22 @@ babel_rt_notify(struct proto *P, struct channel *c UNUSED, struct network *net,
if (new)
{
/* Update */
- uint internal = (new->attrs->src->proto == P);
- uint rt_seqno = internal ? new->u.babel.seqno : p->update_seqno;
+ uint rt_seqno;
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 = 0;
+
+ if (new->src->proto == P)
+ {
+ rt_seqno = ea_find(new->attrs->eattrs, EA_BABEL_SEQNO)->u.data;
+ eattr *e = ea_find(new->attrs->eattrs, EA_BABEL_ROUTER_ID);
+ if (e)
+ memcpy(&rt_router_id, e->u.ptr->data, sizeof(u64));
+ }
+ else
+ {
+ rt_seqno = p->update_seqno;
+ rt_router_id = p->router_id;
+ }
if (rt_metric > BABEL_INFINITY)
{
@@ -2323,15 +2339,16 @@ babel_rt_notify(struct proto *P, struct channel *c UNUSED, struct network *net,
static int
babel_rte_better(struct rte *new, struct rte *old)
{
- return new->u.babel.metric < old->u.babel.metric;
+ uint new_metric = ea_find(new->attrs->eattrs, EA_BABEL_SEQNO)->u.data;
+ uint old_metric = ea_find(old->attrs->eattrs, EA_BABEL_SEQNO)->u.data;
+
+ return new_metric < old_metric;
}
-static int
-babel_rte_same(struct rte *new, struct rte *old)
+static u32
+babel_rte_igp_metric(struct rte *rt)
{
- return ((new->u.babel.seqno == old->u.babel.seqno) &&
- (new->u.babel.metric == old->u.babel.metric) &&
- (new->u.babel.router_id == old->u.babel.router_id));
+ return ea_get_int(rt->attrs->eattrs, EA_BABEL_METRIC, BABEL_INFINITY);
}
@@ -2365,10 +2382,8 @@ babel_init(struct proto_config *CF)
P->if_notify = babel_if_notify;
P->rt_notify = babel_rt_notify;
P->preexport = babel_preexport;
- P->make_tmp_attrs = babel_make_tmp_attrs;
- P->store_tmp_attrs = babel_store_tmp_attrs;
P->rte_better = babel_rte_better;
- P->rte_same = babel_rte_same;
+ P->rte_igp_metric = babel_rte_igp_metric;
return P;
}
diff --git a/proto/babel/babel.h b/proto/babel/babel.h
index 84feb085..8b6da3c8 100644
--- a/proto/babel/babel.h
+++ b/proto/babel/babel.h
@@ -28,6 +28,7 @@
#define EA_BABEL_METRIC EA_CODE(PROTOCOL_BABEL, 0)
#define EA_BABEL_ROUTER_ID EA_CODE(PROTOCOL_BABEL, 1)
+#define EA_BABEL_SEQNO EA_CODE(PROTOCOL_BABEL, 2)
#define BABEL_MAGIC 42
#define BABEL_VERSION 2
diff --git a/proto/bfd/io.c b/proto/bfd/io.c
index 1cd9365a..e696cc89 100644
--- a/proto/bfd/io.c
+++ b/proto/bfd/io.c
@@ -482,6 +482,8 @@ birdloop_main(void *arg)
birdloop_set_current(loop);
+ tmp_init(loop->pool);
+
pthread_mutex_lock(&loop->mutex);
while (1)
{
diff --git a/proto/bgp/attrs.c b/proto/bgp/attrs.c
index 1f927cbd..65e87c96 100644
--- a/proto/bgp/attrs.c
+++ b/proto/bgp/attrs.c
@@ -374,6 +374,13 @@ bgp_init_aigp_metric(rte *e, u64 *metric, const struct adata **ad)
return *metric < IGP_METRIC_UNKNOWN;
}
+u32
+bgp_rte_igp_metric(struct rte *rt)
+{
+ u64 metric = bgp_total_aigp_metric(rt);
+ return (u32) MIN(metric, (u64) IGP_METRIC_UNKNOWN);
+}
+
/*
* Attribute hooks
@@ -1668,10 +1675,9 @@ bgp_free_prefix(struct bgp_channel *c, struct bgp_prefix *px)
*/
int
-bgp_preexport(struct proto *P, rte **new, struct linpool *pool UNUSED)
+bgp_preexport(struct proto *P, rte *e)
{
- rte *e = *new;
- struct proto *SRC = e->attrs->src->proto;
+ struct proto *SRC = e->src->proto;
struct bgp_proto *p = (struct bgp_proto *) P;
struct bgp_proto *src = (SRC->proto == &proto_bgp) ? (struct bgp_proto *) SRC : NULL;
@@ -1730,7 +1736,7 @@ bgp_preexport(struct proto *P, rte **new, struct linpool *pool UNUSED)
static ea_list *
bgp_update_attrs(struct bgp_proto *p, struct bgp_channel *c, rte *e, ea_list *attrs0, struct linpool *pool)
{
- struct proto *SRC = e->attrs->src->proto;
+ struct proto *SRC = e->src->proto;
struct bgp_proto *src = (SRC->proto == &proto_bgp) ? (void *) SRC : NULL;
struct bgp_export_state s = { .proto = p, .channel = c, .pool = pool, .src = src, .route = e, .mpls = c->desc->mpls };
ea_list *attrs = attrs0;
@@ -1854,7 +1860,7 @@ bgp_rt_notify(struct proto *P, struct channel *C, net *n, rte *new, rte *old)
if (new)
{
- struct ea_list *attrs = bgp_update_attrs(p, c, new, new->attrs->eattrs, bgp_linpool2);
+ struct ea_list *attrs = bgp_update_attrs(p, c, new, new->attrs->eattrs, tmp_linpool);
/* Error during attribute processing */
if (!attrs)
@@ -1862,14 +1868,12 @@ bgp_rt_notify(struct proto *P, struct channel *C, net *n, rte *new, rte *old)
/* If attributes are invalid, we fail back to withdraw */
buck = attrs ? bgp_get_bucket(c, attrs) : bgp_get_withdraw_bucket(c);
- path = new->attrs->src->global_id;
-
- lp_flush(bgp_linpool2);
+ path = new->src->global_id;
}
else
{
buck = bgp_get_withdraw_bucket(c);
- path = old->attrs->src->global_id;
+ path = old->src->global_id;
}
px = bgp_get_prefix(c, n->n.addr, c->add_path_tx ? path : 0);
@@ -1889,34 +1893,44 @@ bgp_get_neighbor(rte *r)
return as;
/* If AS_PATH is not defined, we treat rte as locally originated */
- struct bgp_proto *p = (void *) r->attrs->src->proto;
+ struct bgp_proto *p = (void *) r->src->proto;
return p->cf->confederation ?: p->local_as;
}
static inline int
rte_stale(rte *r)
{
- if (r->u.bgp.stale < 0)
+ if (r->pflags & BGP_REF_STALE)
+ return 1;
+
+ if (r->pflags & BGP_REF_NOT_STALE)
+ return 0;
+
+ /* If staleness is unknown, compute and cache it */
+ eattr *a = ea_find(r->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_COMMUNITY));
+ if (a && int_set_contains(a->u.ptr, BGP_COMM_LLGR_STALE))
{
- /* If staleness is unknown, compute and cache it */
- eattr *a = ea_find(r->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_COMMUNITY));
- r->u.bgp.stale = a && int_set_contains(a->u.ptr, BGP_COMM_LLGR_STALE);
+ r->pflags |= BGP_REF_STALE;
+ return 1;
+ }
+ else
+ {
+ r->pflags |= BGP_REF_NOT_STALE;
+ return 0;
}
-
- return r->u.bgp.stale;
}
int
bgp_rte_better(rte *new, rte *old)
{
- struct bgp_proto *new_bgp = (struct bgp_proto *) new->attrs->src->proto;
- struct bgp_proto *old_bgp = (struct bgp_proto *) old->attrs->src->proto;
+ struct bgp_proto *new_bgp = (struct bgp_proto *) new->src->proto;
+ struct bgp_proto *old_bgp = (struct bgp_proto *) old->src->proto;
eattr *x, *y;
u32 n, o;
/* Skip suppressed routes (see bgp_rte_recalculate()) */
- n = new->u.bgp.suppressed;
- o = old->u.bgp.suppressed;
+ n = new->pflags & BGP_REF_SUPPRESSED;
+ o = old->pflags & BGP_REF_SUPPRESSED;
if (n > o)
return 0;
if (n < o)
@@ -2054,23 +2068,20 @@ bgp_rte_better(rte *new, rte *old)
int
bgp_rte_mergable(rte *pri, rte *sec)
{
- struct bgp_proto *pri_bgp = (struct bgp_proto *) pri->attrs->src->proto;
- struct bgp_proto *sec_bgp = (struct bgp_proto *) sec->attrs->src->proto;
+ struct bgp_proto *pri_bgp = (struct bgp_proto *) pri->src->proto;
+ struct bgp_proto *sec_bgp = (struct bgp_proto *) sec->src->proto;
eattr *x, *y;
u32 p, s;
/* Skip suppressed routes (see bgp_rte_recalculate()) */
- if (pri->u.bgp.suppressed != sec->u.bgp.suppressed)
+ /* LLGR draft - depreference stale routes */
+ if (pri->pflags != sec->pflags)
return 0;
/* RFC 4271 9.1.2.1. Route resolvability test */
if (rte_resolvable(pri) != rte_resolvable(sec))
return 0;
- /* LLGR draft - depreference stale routes */
- if (rte_stale(pri) != rte_stale(sec))
- return 0;
-
/* Start with local preferences */
x = ea_find(pri->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_LOCAL_PREF));
y = ea_find(sec->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_LOCAL_PREF));
@@ -2133,13 +2144,13 @@ bgp_rte_mergable(rte *pri, rte *sec)
static inline int
same_group(rte *r, u32 lpref, u32 lasn)
{
- return (r->pref == lpref) && (bgp_get_neighbor(r) == lasn);
+ return (r->attrs->pref == lpref) && (bgp_get_neighbor(r) == lasn);
}
static inline int
use_deterministic_med(rte *r)
{
- struct proto *P = r->attrs->src->proto;
+ struct proto *P = r->src->proto;
return (P->proto == &proto_bgp) && ((struct bgp_proto *) P)->cf->deterministic_med;
}
@@ -2148,9 +2159,9 @@ bgp_rte_recalculate(rtable *table, net *net, rte *new, rte *old, rte *old_best)
{
rte *r, *s;
rte *key = new ? new : old;
- u32 lpref = key->pref;
+ u32 lpref = key->attrs->pref;
u32 lasn = bgp_get_neighbor(key);
- int old_suppressed = old ? old->u.bgp.suppressed : 0;
+ int old_suppressed = old ? !!(old->pflags & BGP_REF_SUPPRESSED) : 0;
/*
* Proper RFC 4271 path selection is a bit complicated, it cannot be
@@ -2202,11 +2213,11 @@ bgp_rte_recalculate(rtable *table, net *net, rte *new, rte *old, rte *old_best)
*/
if (new)
- new->u.bgp.suppressed = 1;
+ new->pflags |= BGP_REF_SUPPRESSED;
if (old)
{
- old->u.bgp.suppressed = 1;
+ old->pflags |= BGP_REF_SUPPRESSED;
/* The fast case - replace not best with worse (or remove not best) */
if (old_suppressed && !(new && bgp_rte_better(new, old)))
@@ -2218,7 +2229,7 @@ bgp_rte_recalculate(rtable *table, net *net, rte *new, rte *old, rte *old_best)
for (s=net->routes; rte_is_valid(s); s=s->next)
if (use_deterministic_med(s) && same_group(s, lpref, lasn))
{
- s->u.bgp.suppressed = 1;
+ s->pflags |= BGP_REF_SUPPRESSED;
if (!r || bgp_rte_better(s, r))
r = s;
}
@@ -2229,16 +2240,16 @@ bgp_rte_recalculate(rtable *table, net *net, rte *new, rte *old, rte *old_best)
/* Found if new is mergable with best-in-group */
if (new && (new != r) && bgp_rte_mergable(r, new))
- new->u.bgp.suppressed = 0;
+ new->pflags &= ~BGP_REF_SUPPRESSED;
/* Found all existing routes mergable with best-in-group */
for (s=net->routes; rte_is_valid(s); s=s->next)
if (use_deterministic_med(s) && same_group(s, lpref, lasn))
if ((s != r) && bgp_rte_mergable(r, s))
- s->u.bgp.suppressed = 0;
+ s->pflags &= ~BGP_REF_SUPPRESSED;
/* Found best-in-group */
- r->u.bgp.suppressed = 0;
+ r->pflags &= ~BGP_REF_SUPPRESSED;
/*
* There are generally two reasons why we have to force
@@ -2286,7 +2297,7 @@ bgp_rte_modify_stale(struct rte *r, struct linpool *pool)
r = rte_cow_rta(r, pool);
bgp_set_attr_ptr(&(r->attrs->eattrs), pool, BA_COMMUNITY, flags,
int_set_add(pool, ad, BGP_COMM_LLGR_STALE));
- r->u.bgp.stale = 1;
+ r->pflags |= BGP_REF_STALE;
return r;
}
@@ -2371,9 +2382,9 @@ bgp_get_route_info(rte *e, byte *buf)
eattr *o = ea_find(e->attrs->eattrs, EA_CODE(PROTOCOL_BGP, BA_ORIGIN));
u32 origas;
- buf += bsprintf(buf, " (%d", e->pref);
+ buf += bsprintf(buf, " (%d", e->attrs->pref);
- if (e->u.bgp.suppressed)
+ if (e->pflags & BGP_REF_SUPPRESSED)
buf += bsprintf(buf, "-");
if (rte_stale(e))
diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c
index 619a816b..52400762 100644
--- a/proto/bgp/bgp.c
+++ b/proto/bgp/bgp.c
@@ -126,9 +126,7 @@
#include "bgp.h"
-struct linpool *bgp_linpool; /* Global temporary pool */
-struct linpool *bgp_linpool2; /* Global temporary pool for bgp_rt_notify() */
-static list bgp_sockets; /* Global list of listening sockets */
+static list STATIC_LIST_INIT(bgp_sockets); /* Global list of listening sockets */
static void bgp_connect(struct bgp_proto *p);
@@ -161,10 +159,6 @@ bgp_open(struct bgp_proto *p)
uint flags = p->cf->free_bind ? SKF_FREEBIND : 0;
uint flag_mask = SKF_FREEBIND;
- /* FIXME: Add some global init? */
- if (!bgp_linpool)
- init_list(&bgp_sockets);
-
/* We assume that cf->iface is defined iff cf->local_ip is link-local */
WALK_LIST(bs, bgp_sockets)
@@ -204,12 +198,6 @@ bgp_open(struct bgp_proto *p)
add_tail(&bgp_sockets, &bs->n);
- if (!bgp_linpool)
- {
- bgp_linpool = lp_new_default(proto_pool);
- bgp_linpool2 = lp_new_default(proto_pool);
- }
-
return 0;
err:
@@ -238,15 +226,6 @@ bgp_close(struct bgp_proto *p)
rfree(bs->sk);
rem_node(&bs->n);
mb_free(bs);
-
- if (!EMPTY_LIST(bgp_sockets))
- return;
-
- rfree(bgp_linpool);
- bgp_linpool = NULL;
-
- rfree(bgp_linpool2);
- bgp_linpool2 = NULL;
}
static inline int
@@ -1700,6 +1679,7 @@ bgp_init(struct proto_config *CF)
P->rte_mergable = bgp_rte_mergable;
P->rte_recalculate = cf->deterministic_med ? bgp_rte_recalculate : NULL;
P->rte_modify = bgp_rte_modify_stale;
+ P->rte_igp_metric = bgp_rte_igp_metric;
p->cf = cf;
p->is_internal = (cf->local_as == cf->remote_as);
diff --git a/proto/bgp/bgp.h b/proto/bgp/bgp.h
index 4969c0b9..bff49c3a 100644
--- a/proto/bgp/bgp.h
+++ b/proto/bgp/bgp.h
@@ -20,7 +20,6 @@
#include "lib/hash.h"
#include "lib/socket.h"
-struct linpool;
struct eattr;
@@ -203,6 +202,10 @@ struct bgp_channel_config {
#define BGP_BFD_GRACEFUL 2 /* BFD down triggers graceful restart */
+/* rte->pflags */
+#define BGP_REF_SUPPRESSED 0x1 /* Used for deterministic MED comparison */
+#define BGP_REF_STALE 0x2 /* Route is LLGR_STATE */
+#define BGP_REF_NOT_STALE 0x4 /* Route is NOT LLGR_STATE */
struct bgp_af_caps {
u32 afi;
@@ -454,7 +457,6 @@ struct bgp_parse_state {
jmp_buf err_jmpbuf;
struct hostentry *hostentry;
- struct rtable *base_table;
adata *mpls_labels;
/* Cached state for bgp_rte_update() */
@@ -495,9 +497,6 @@ bgp_parse_error(struct bgp_parse_state *s, uint subcode)
longjmp(s->err_jmpbuf, 1);
}
-extern struct linpool *bgp_linpool;
-extern struct linpool *bgp_linpool2;
-
void bgp_start_timer(timer *t, uint value);
void bgp_check_config(struct bgp_config *c);
@@ -588,8 +587,9 @@ int bgp_rte_better(struct rte *, struct rte *);
int bgp_rte_mergable(rte *pri, rte *sec);
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);
+u32 bgp_rte_igp_metric(struct rte *);
void bgp_rt_notify(struct proto *P, struct channel *C, net *n, rte *new, rte *old);
-int bgp_preexport(struct proto *, struct rte **, struct linpool *);
+int bgp_preexport(struct proto *, struct rte *);
int bgp_get_attr(const struct eattr *e, byte *buf, int buflen);
void bgp_get_route_info(struct rte *, byte *buf);
int bgp_total_aigp_metric_(rte *e, u64 *metric, const struct adata **ad);
diff --git a/proto/bgp/packets.c b/proto/bgp/packets.c
index f13625e2..66f14150 100644
--- a/proto/bgp/packets.c
+++ b/proto/bgp/packets.c
@@ -1025,9 +1025,6 @@ bgp_apply_flow_validation(struct bgp_parse_state *s, const net_addr *n, rta *a)
int valid = rt_flowspec_check(c->base_table, c->c.table, n, a, s->proto->is_interior);
a->dest = valid ? RTD_NONE : RTD_UNREACHABLE;
- /* Set rte.bgp.base_table later from this state variable */
- s->base_table = c->base_table;
-
/* Invalidate cached rta if dest changes */
if (s->cached_rta && (s->cached_rta->dest != a->dest))
{
@@ -1386,8 +1383,6 @@ bgp_rte_update(struct bgp_parse_state *s, const net_addr *n, u32 path_id, rta *a
/* Prepare cached route attributes */
if (s->cached_rta == NULL)
{
- a0->src = s->last_src;
-
/* Workaround for rta_lookup() breaking eattrs */
ea_list *ea = a0->eattrs;
s->cached_rta = rta_lookup(a0);
@@ -1395,12 +1390,9 @@ bgp_rte_update(struct bgp_parse_state *s, const net_addr *n, u32 path_id, rta *a
}
rta *a = rta_clone(s->cached_rta);
- rte *e = rte_get_temp(a);
+ rte *e = rte_get_temp(a, s->last_src);
e->pflags = 0;
- e->u.bgp.suppressed = 0;
- e->u.bgp.stale = -1;
- e->u.bgp.base_table = s->base_table;
rte_update3(&s->channel->c, n, e, s->last_src);
}
@@ -2335,7 +2327,7 @@ again: ;
struct bgp_write_state s = {
.proto = p,
.channel = c,
- .pool = bgp_linpool,
+ .pool = tmp_linpool,
.mp_reach = (c->afi != BGP_AF_IPV4) || c->ext_next_hop,
.as4_session = p->as4_session,
.add_path = c->add_path_tx,
@@ -2464,8 +2456,6 @@ bgp_decode_nlri(struct bgp_parse_state *s, u32 afi, byte *nlri, uint len, ea_lis
s->last_id = 0;
s->last_src = s->proto->p.main_source;
- s->base_table = NULL;
-
/*
* IPv4 BGP and MP-BGP may be used together in one update, therefore we do not
* add BA_NEXT_HOP in bgp_decode_attrs(), but we add it here independently for
@@ -2481,6 +2471,7 @@ bgp_decode_nlri(struct bgp_parse_state *s, u32 afi, byte *nlri, uint len, ea_lis
a->scope = SCOPE_UNIVERSE;
a->from = s->proto->remote_ip;
a->eattrs = ea;
+ a->pref = c->c.preference;
c->desc->decode_next_hop(s, nh, nh_len, a);
bgp_finish_attrs(s, a);
@@ -2518,7 +2509,7 @@ bgp_rx_update(struct bgp_conn *conn, byte *pkt, uint len)
/* Initialize parse state */
struct bgp_parse_state s = {
.proto = p,
- .pool = bgp_linpool,
+ .pool = tmp_linpool,
.as4_session = p->as4_session,
};
diff --git a/proto/mrt/mrt.c b/proto/mrt/mrt.c
index 8d97c860..e885611a 100644
--- a/proto/mrt/mrt.c
+++ b/proto/mrt/mrt.c
@@ -472,9 +472,9 @@ mrt_rib_table_entry(struct mrt_table_dump_state *s, rte *r)
#ifdef CONFIG_BGP
/* Find peer index */
- if (r->attrs->src->proto->proto == &proto_bgp)
+ if (r->src->proto->proto == &proto_bgp)
{
- struct bgp_proto *p = (void *) r->attrs->src->proto;
+ struct bgp_proto *p = (void *) r->src->proto;
struct mrt_peer_entry *n =
HASH_FIND(s->peer_hash, PEER, p->remote_id, p->remote_as, p->remote_ip);
@@ -488,7 +488,7 @@ mrt_rib_table_entry(struct mrt_table_dump_state *s, rte *r)
/* Path Identifier */
if (s->add_path)
- mrt_put_u32(b, r->attrs->src->private_id);
+ mrt_put_u32(b, r->src->private_id);
/* Route Attributes */
mrt_put_u16(b, 0);
@@ -519,14 +519,12 @@ mrt_rib_table_dump(struct mrt_table_dump_state *s, net *n, int add_path)
continue;
/* Skip routes that should be reported in the other phase */
- if (!s->always_add_path && (!rt->attrs->src->private_id != !s->add_path))
+ if (!s->always_add_path && (!rt->src->private_id != !s->add_path))
{
s->want_add_path = 1;
continue;
}
- rte_make_tmp_attrs(&rt, s->linpool, NULL);
-
if (f_run(s->filter, &rt, s->linpool, 0) <= F_ACCEPT)
mrt_rib_table_entry(s, rt);
diff --git a/proto/ospf/iface.c b/proto/ospf/iface.c
index f38b8210..4cd45033 100644
--- a/proto/ospf/iface.c
+++ b/proto/ospf/iface.c
@@ -522,7 +522,10 @@ static inline void
add_nbma_node(struct ospf_iface *ifa, struct nbma_node *src, int found)
{
struct nbma_node *n = mb_alloc(ifa->pool, sizeof(struct nbma_node));
+
+ n->n = (node) {};
add_tail(&ifa->nbma_list, NODE n);
+
n->ip = src->ip;
n->eligible = src->eligible;
n->found = found;
diff --git a/proto/ospf/ospf.c b/proto/ospf/ospf.c
index ba8c2e2b..f9aa6cd1 100644
--- a/proto/ospf/ospf.c
+++ b/proto/ospf/ospf.c
@@ -107,12 +107,10 @@
#include <stdlib.h>
#include "ospf.h"
-static int ospf_preexport(struct proto *P, rte **new, struct linpool *pool);
-static void ospf_make_tmp_attrs(struct rte *rt, struct linpool *pool);
-static void ospf_store_tmp_attrs(struct rte *rt, struct linpool *pool);
+static int ospf_preexport(struct proto *P, rte *new);
static void ospf_reload_routes(struct channel *C);
static int ospf_rte_better(struct rte *new, struct rte *old);
-static int ospf_rte_same(struct rte *new, struct rte *old);
+static u32 ospf_rte_igp_metric(struct rte *rt);
static void ospf_disp(timer *timer);
@@ -378,10 +376,8 @@ ospf_init(struct proto_config *CF)
P->reload_routes = ospf_reload_routes;
P->feed_begin = ospf_feed_begin;
P->feed_end = ospf_feed_end;
- P->make_tmp_attrs = ospf_make_tmp_attrs;
- P->store_tmp_attrs = ospf_store_tmp_attrs;
P->rte_better = ospf_rte_better;
- P->rte_same = ospf_rte_same;
+ P->rte_igp_metric = ospf_rte_igp_metric;
return P;
}
@@ -390,7 +386,9 @@ ospf_init(struct proto_config *CF)
static int
ospf_rte_better(struct rte *new, struct rte *old)
{
- if (new->u.ospf.metric1 == LSINFINITY)
+ u32 new_metric1 = ea_get_int(new->attrs->eattrs, EA_OSPF_METRIC1, LSINFINITY);
+
+ if (new_metric1 == LSINFINITY)
return 0;
if(new->attrs->source < old->attrs->source) return 1;
@@ -398,27 +396,27 @@ ospf_rte_better(struct rte *new, struct rte *old)
if(new->attrs->source == RTS_OSPF_EXT2)
{
- if(new->u.ospf.metric2 < old->u.ospf.metric2) return 1;
- if(new->u.ospf.metric2 > old->u.ospf.metric2) return 0;
+ u32 old_metric2 = ea_get_int(old->attrs->eattrs, EA_OSPF_METRIC2, LSINFINITY);
+ u32 new_metric2 = ea_get_int(new->attrs->eattrs, EA_OSPF_METRIC2, LSINFINITY);
+ if(new_metric2 < old_metric2) return 1;
+ if(new_metric2 > old_metric2) return 0;
}
- if (new->u.ospf.metric1 < old->u.ospf.metric1)
+ u32 old_metric1 = ea_get_int(old->attrs->eattrs, EA_OSPF_METRIC1, LSINFINITY);
+ if (new_metric1 < old_metric1)
return 1;
return 0; /* Old is shorter or same */
}
-static int
-ospf_rte_same(struct rte *new, struct rte *old)
+static u32
+ospf_rte_igp_metric(struct rte *rt)
{
- /* new->attrs == old->attrs always */
- return
- new->u.ospf.metric1 == old->u.ospf.metric1 &&
- new->u.ospf.metric2 == old->u.ospf.metric2 &&
- new->u.ospf.tag == old->u.ospf.tag &&
- new->u.ospf.router_id == old->u.ospf.router_id;
-}
+ if (rt->attrs->source == RTS_OSPF_EXT2)
+ return IGP_METRIC_UNKNOWN;
+ return ea_get_int(rt->attrs->eattrs, EA_OSPF_METRIC1, LSINFINITY);
+}
void
ospf_schedule_rtcalc(struct ospf_proto *p)
@@ -484,14 +482,13 @@ ospf_disp(timer * timer)
* import to the filters.
*/
static int
-ospf_preexport(struct proto *P, rte **new, struct linpool *pool UNUSED)
+ospf_preexport(struct proto *P, rte *e)
{
struct ospf_proto *p = (struct ospf_proto *) P;
struct ospf_area *oa = ospf_main_area(p);
- rte *e = *new;
/* Reject our own routes */
- if (e->attrs->src->proto == P)
+ if (e->src->proto == P)
return -1;
/* Do not export routes to stub areas */
@@ -501,26 +498,6 @@ ospf_preexport(struct proto *P, rte **new, struct linpool *pool UNUSED)
return 0;
}
-static void
-ospf_make_tmp_attrs(struct rte *rt, struct linpool *pool)
-{
- rte_init_tmp_attrs(rt, pool, 4);
- rte_make_tmp_attr(rt, EA_OSPF_METRIC1, EAF_TYPE_INT, rt->u.ospf.metric1);
- rte_make_tmp_attr(rt, EA_OSPF_METRIC2, EAF_TYPE_INT, rt->u.ospf.metric2);
- rte_make_tmp_attr(rt, EA_OSPF_TAG, EAF_TYPE_INT, rt->u.ospf.tag);
- rte_make_tmp_attr(rt, EA_OSPF_ROUTER_ID, EAF_TYPE_ROUTER_ID, rt->u.ospf.router_id);
-}
-
-static void
-ospf_store_tmp_attrs(struct rte *rt, struct linpool *pool)
-{
- rte_init_tmp_attrs(rt, pool, 4);
- rt->u.ospf.metric1 = rte_store_tmp_attr(rt, EA_OSPF_METRIC1);
- rt->u.ospf.metric2 = rte_store_tmp_attr(rt, EA_OSPF_METRIC2);
- rt->u.ospf.tag = rte_store_tmp_attr(rt, EA_OSPF_TAG);
- rt->u.ospf.router_id = rte_store_tmp_attr(rt, EA_OSPF_ROUTER_ID);
-}
-
/**
* ospf_shutdown - Finish of OSPF instance
* @P: OSPF protocol instance
@@ -558,6 +535,9 @@ ospf_shutdown(struct proto *P)
}
FIB_WALK_END;
+ if (tm_active(p->disp_timer))
+ tm_stop(p->disp_timer);
+
return PS_DOWN;
}
@@ -607,16 +587,20 @@ ospf_get_route_info(rte * rte, byte * buf)
}
buf += bsprintf(buf, " %s", type);
- buf += bsprintf(buf, " (%d/%d", rte->pref, rte->u.ospf.metric1);
+ buf += bsprintf(buf, " (%d/%d", rte->attrs->pref, ea_get_int(rte->attrs->eattrs, EA_OSPF_METRIC1, LSINFINITY));
if (rte->attrs->source == RTS_OSPF_EXT2)
- buf += bsprintf(buf, "/%d", rte->u.ospf.metric2);
+ buf += bsprintf(buf, "/%d", ea_get_int(rte->attrs->eattrs, EA_OSPF_METRIC2, LSINFINITY));
buf += bsprintf(buf, ")");
- if ((rte->attrs->source == RTS_OSPF_EXT1 || rte->attrs->source == RTS_OSPF_EXT2) && rte->u.ospf.tag)
+ if (rte->attrs->source == RTS_OSPF_EXT1 || rte->attrs->source == RTS_OSPF_EXT2)
{
- buf += bsprintf(buf, " [%x]", rte->u.ospf.tag);
+ eattr *ea = ea_find(rte->attrs->eattrs, EA_OSPF_TAG);
+ if (ea && (ea->u.data > 0))
+ buf += bsprintf(buf, " [%x]", ea->u.data);
}
- if (rte->u.ospf.router_id)
- buf += bsprintf(buf, " [%R]", rte->u.ospf.router_id);
+
+ eattr *ea = ea_find(rte->attrs->eattrs, EA_OSPF_ROUTER_ID);
+ if (ea)
+ buf += bsprintf(buf, " [%R]", ea->u.data);
}
static int
diff --git a/proto/ospf/rt.c b/proto/ospf/rt.c
index faee49dc..471bb586 100644
--- a/proto/ospf/rt.c
+++ b/proto/ospf/rt.c
@@ -144,7 +144,7 @@ orta_compare(const struct ospf_proto *p, const orta *new, const orta *old)
{
int r;
- if (old->type == RTS_DUMMY)
+ if (!old->type)
return 1;
/* Prefer intra-area to inter-area to externals */
@@ -195,7 +195,7 @@ orta_compare_asbr(const struct ospf_proto *p, const orta *new, const orta *old)
{
int r;
- if (old->type == RTS_DUMMY)
+ if (!old->type)
return 1;
if (!p->rfc1583)
@@ -225,7 +225,7 @@ orta_compare_ext(const struct ospf_proto *p, const orta *new, const orta *old)
{
int r;
- if (old->type == RTS_DUMMY)
+ if (!old->type)
return 1;
/* 16.4 (6a) - prefer routes with lower type */
@@ -2053,32 +2053,54 @@ again1:
if (nf->n.type) /* Add the route */
{
rta a0 = {
- .src = p->p.main_source,
.source = nf->n.type,
.scope = SCOPE_UNIVERSE,
.dest = RTD_UNICAST,
.nh = *(nf->n.nhs),
+ .pref = p->p.main_channel->preference,
};
if (reload || ort_changed(nf, &a0))
{
- rta *a = rta_lookup(&a0);
- rte *e = rte_get_temp(a);
+ a0.eattrs = alloca(sizeof(ea_list) + 4 * sizeof(eattr));
+ memset(a0.eattrs, 0, sizeof(ea_list));
- rta_free(nf->old_rta);
- nf->old_rta = rta_clone(a);
- e->u.ospf.metric1 = nf->old_metric1 = nf->n.metric1;
- e->u.ospf.metric2 = nf->old_metric2 = nf->n.metric2;
- e->u.ospf.tag = nf->old_tag = nf->n.tag;
- e->u.ospf.router_id = nf->old_rid = nf->n.rid;
- e->pflags = EA_ID_FLAG(EA_OSPF_METRIC1) | EA_ID_FLAG(EA_OSPF_ROUTER_ID);
+ nf->old_metric1 = nf->n.metric1;
+ nf->old_metric2 = nf->n.metric2;
+ nf->old_tag = nf->n.tag;
+ nf->old_rid = nf->n.rid;
+
+ a0.eattrs->attrs[a0.eattrs->count++] = (eattr) {
+ .id = EA_OSPF_METRIC1,
+ .type = EAF_TYPE_INT,
+ .u.data = nf->n.metric1,
+ };
if (nf->n.type == RTS_OSPF_EXT2)
- e->pflags |= EA_ID_FLAG(EA_OSPF_METRIC2);
+ a0.eattrs->attrs[a0.eattrs->count++] = (eattr) {
+ .id = EA_OSPF_METRIC2,
+ .type = EAF_TYPE_INT,
+ .u.data = nf->n.metric2,
+ };
- /* Perhaps onfly if tag is non-zero? */
if ((nf->n.type == RTS_OSPF_EXT1) || (nf->n.type == RTS_OSPF_EXT2))
- e->pflags |= EA_ID_FLAG(EA_OSPF_TAG);
+ a0.eattrs->attrs[a0.eattrs->count++] = (eattr) {
+ .id = EA_OSPF_TAG,
+ .type = EAF_TYPE_INT,
+ .u.data = nf->n.tag,
+ };
+
+ a0.eattrs->attrs[a0.eattrs->count++] = (eattr) {
+ .id = EA_OSPF_ROUTER_ID,
+ .type = EAF_TYPE_ROUTER_ID,
+ .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);
+ nf->old_rta = rta_clone(a);
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);
diff --git a/proto/perf/perf.c b/proto/perf/perf.c
index ba401a8a..52784c14 100644
--- a/proto/perf/perf.c
+++ b/proto/perf/perf.c
@@ -143,10 +143,10 @@ perf_loop(void *data)
if (!p->attrs_per_rte || !(i % p->attrs_per_rte)) {
struct rta a0 = {
- .src = p->p.main_source,
.source = RTS_PERF,
.scope = SCOPE_UNIVERSE,
.dest = RTD_UNICAST,
+ .pref = p->p.main_channel->preference,
.nh.iface = p->ifa->iface,
.nh.gw = gw,
.nh.weight = 1,
@@ -161,7 +161,7 @@ perf_loop(void *data)
clock_gettime(CLOCK_MONOTONIC, &ts_generated);
for (uint i=0; i<N; i++) {
- rte *e = rte_get_temp(p->data[i].a);
+ rte *e = rte_get_temp(p->data[i].a, p->p.main_source);
e->pflags = 0;
rte_update(P, &(p->data[i].net), e);
diff --git a/proto/pipe/pipe.c b/proto/pipe/pipe.c
index f991d09a..97862780 100644
--- a/proto/pipe/pipe.c
+++ b/proto/pipe/pipe.c
@@ -43,6 +43,10 @@
#include "pipe.h"
+#ifdef CONFIG_BGP
+#include "proto/bgp/bgp.h"
+#endif
+
static void
pipe_rt_notify(struct proto *P, struct channel *src_ch, net *n, rte *new, rte *old)
{
@@ -65,34 +69,26 @@ pipe_rt_notify(struct proto *P, struct channel *src_ch, net *n, rte *new, rte *o
if (new)
{
+ src = new->src;
+
a = alloca(rta_size(new->attrs));
memcpy(a, new->attrs, rta_size(new->attrs));
- a->aflags = 0;
+ a->cached = 0;
a->hostentry = NULL;
- e = rte_get_temp(a);
- e->pflags = 0;
-
- /* Copy protocol specific embedded attributes. */
- memcpy(&(e->u), &(new->u), sizeof(e->u));
- e->pref = new->pref;
+ e = rte_get_temp(a, src);
e->pflags = new->pflags;
#ifdef CONFIG_BGP
/* Hack to cleanup cached value */
- if (e->attrs->src->proto->proto == &proto_bgp)
- {
- e->u.bgp.stale = -1;
- e->u.bgp.base_table = NULL;
- }
+ if (e->src->proto->proto == &proto_bgp)
+ e->pflags &= ~(BGP_REF_STALE | BGP_REF_NOT_STALE);
#endif
-
- src = a->src;
}
else
{
e = NULL;
- src = old->attrs->src;
+ src = old->src;
}
src_ch->table->pipe_busy = 1;
@@ -101,9 +97,9 @@ pipe_rt_notify(struct proto *P, struct channel *src_ch, net *n, rte *new, rte *o
}
static int
-pipe_preexport(struct proto *P, rte **ee, struct linpool *p UNUSED)
+pipe_preexport(struct proto *P, rte *e)
{
- struct proto *pp = (*ee)->sender->proto;
+ struct proto *pp = e->sender->proto;
if (pp == P)
return -1; /* Avoid local loops automatically */
diff --git a/proto/radv/radv.c b/proto/radv/radv.c
index 66e8eb4b..540ff2a7 100644
--- a/proto/radv/radv.c
+++ b/proto/radv/radv.c
@@ -391,12 +391,12 @@ radv_net_match_trigger(struct radv_config *cf, net *n)
}
int
-radv_preexport(struct proto *P, rte **new, struct linpool *pool UNUSED)
+radv_preexport(struct proto *P, rte *new)
{
// struct radv_proto *p = (struct radv_proto *) P;
struct radv_config *cf = (struct radv_config *) (P->cf);
- if (radv_net_match_trigger(cf, (*new)->net))
+ if (radv_net_match_trigger(cf, new->net))
return RIC_PROCESS;
if (cf->propagate_routes)
diff --git a/proto/rip/rip.c b/proto/rip/rip.c
index e1a235a0..a501a784 100644
--- a/proto/rip/rip.c
+++ b/proto/rip/rip.c
@@ -145,7 +145,7 @@ rip_announce_rte(struct rip_proto *p, struct rip_entry *en)
{
/* Update */
rta a0 = {
- .src = p->p.main_source,
+ .pref = p->p.main_channel->preference,
.source = RTS_RIP,
.scope = SCOPE_UNIVERSE,
.dest = RTD_UNICAST,
@@ -188,13 +188,27 @@ rip_announce_rte(struct rip_proto *p, struct rip_entry *en)
a0.nh.iface = rt->from->ifa->iface;
}
- rta *a = rta_lookup(&a0);
- rte *e = rte_get_temp(a);
+ a0.eattrs = alloca(sizeof(ea_list) + 3*sizeof(eattr));
+ memset(a0.eattrs, 0, sizeof(ea_list)); /* Zero-ing only the ea_list header */
+ a0.eattrs->count = 3;
+ a0.eattrs->attrs[0] = (eattr) {
+ .id = EA_RIP_METRIC,
+ .type = EAF_TYPE_INT,
+ .u.data = rt_metric,
+ };
+ a0.eattrs->attrs[1] = (eattr) {
+ .id = EA_RIP_TAG,
+ .type = EAF_TYPE_INT,
+ .u.data = rt_tag,
+ };
+ a0.eattrs->attrs[2] = (eattr) {
+ .id = EA_RIP_FROM,
+ .type = EAF_TYPE_PTR,
+ .u.data = (uintptr_t) a0.nh.iface,
+ };
- e->u.rip.from = a0.nh.iface;
- e->u.rip.metric = rt_metric;
- e->u.rip.tag = rt_tag;
- e->pflags = EA_ID_FLAG(EA_RIP_METRIC) | EA_ID_FLAG(EA_RIP_TAG);
+ rta *a = rta_lookup(&a0);
+ rte *e = rte_get_temp(a, p->p.main_source);
rte_update(&p->p, en->n.addr, e);
}
@@ -307,8 +321,9 @@ rip_rt_notify(struct proto *P, struct channel *ch UNUSED, struct network *net, s
if (new)
{
/* Update */
- u32 rt_metric = ea_get_int(new->attrs->eattrs, EA_RIP_METRIC, 1);
u32 rt_tag = ea_get_int(new->attrs->eattrs, EA_RIP_TAG, 0);
+ u32 rt_metric = ea_get_int(new->attrs->eattrs, EA_RIP_METRIC, 1);
+ struct iface *rt_from = (struct iface *) ea_get_int(new->attrs->eattrs, EA_RIP_FROM, 0);
if (rt_metric > p->infinity)
{
@@ -339,7 +354,7 @@ rip_rt_notify(struct proto *P, struct channel *ch UNUSED, struct network *net, s
en->valid = RIP_ENTRY_VALID;
en->metric = rt_metric;
en->tag = rt_tag;
- en->from = (new->attrs->src->proto == P) ? new->u.rip.from : NULL;
+ en->from = (new->src->proto == P) ? rt_from : NULL;
en->iface = new->attrs->nh.iface;
en->next_hop = new->attrs->nh.gw;
}
@@ -1068,37 +1083,24 @@ rip_reload_routes(struct channel *C)
rip_kick_timer(p);
}
-static void
-rip_make_tmp_attrs(struct rte *rt, struct linpool *pool)
-{
- rte_init_tmp_attrs(rt, pool, 2);
- rte_make_tmp_attr(rt, EA_RIP_METRIC, EAF_TYPE_INT, rt->u.rip.metric);
- rte_make_tmp_attr(rt, EA_RIP_TAG, EAF_TYPE_INT, rt->u.rip.tag);
-}
-
-static void
-rip_store_tmp_attrs(struct rte *rt, struct linpool *pool)
-{
- rte_init_tmp_attrs(rt, pool, 2);
- rt->u.rip.metric = rte_store_tmp_attr(rt, EA_RIP_METRIC);
- rt->u.rip.tag = rte_store_tmp_attr(rt, EA_RIP_TAG);
-}
-
static int
rip_rte_better(struct rte *new, struct rte *old)
{
- return new->u.rip.metric < old->u.rip.metric;
+ ASSERT_DIE(new->src == old->src);
+ struct rip_proto *p = (struct rip_proto *) new->src->proto;
+
+ u32 new_metric = ea_get_int(new->attrs->eattrs, EA_RIP_METRIC, p->infinity);
+ u32 old_metric = ea_get_int(old->attrs->eattrs, EA_RIP_METRIC, p->infinity);
+
+ return new_metric < old_metric;
}
-static int
-rip_rte_same(struct rte *new, struct rte *old)
+static u32
+rip_rte_igp_metric(struct rte *rt)
{
- return ((new->u.rip.metric == old->u.rip.metric) &&
- (new->u.rip.tag == old->u.rip.tag) &&
- (new->u.rip.from == old->u.rip.from));
+ return ea_get_int(rt->attrs->eattrs, EA_RIP_METRIC, IGP_METRIC_UNKNOWN);
}
-
static void
rip_postconfig(struct proto_config *CF)
{
@@ -1120,10 +1122,8 @@ rip_init(struct proto_config *CF)
P->rt_notify = rip_rt_notify;
P->neigh_notify = rip_neigh_notify;
P->reload_routes = rip_reload_routes;
- P->make_tmp_attrs = rip_make_tmp_attrs;
- P->store_tmp_attrs = rip_store_tmp_attrs;
P->rte_better = rip_rte_better;
- P->rte_same = rip_rte_same;
+ P->rte_igp_metric = rip_rte_igp_metric;
return P;
}
@@ -1198,10 +1198,14 @@ rip_reconfigure(struct proto *P, struct proto_config *CF)
static void
rip_get_route_info(rte *rte, byte *buf)
{
- buf += bsprintf(buf, " (%d/%d)", rte->pref, rte->u.rip.metric);
+ struct rip_proto *p = (struct rip_proto *) rte->src->proto;
+ u32 rt_metric = ea_get_int(rte->attrs->eattrs, EA_RIP_METRIC, p->infinity);
+ u32 rt_tag = ea_get_int(rte->attrs->eattrs, EA_RIP_TAG, 0);
+
+ buf += bsprintf(buf, " (%d/%d)", rte->attrs->pref, rt_metric);
- if (rte->u.rip.tag)
- bsprintf(buf, " [%04x]", rte->u.rip.tag);
+ if (rt_tag)
+ bsprintf(buf, " [%04x]", rt_tag);
}
static int
diff --git a/proto/rip/rip.h b/proto/rip/rip.h
index 8d347000..f8713c4a 100644
--- a/proto/rip/rip.h
+++ b/proto/rip/rip.h
@@ -197,6 +197,7 @@ struct rip_rte
#define EA_RIP_METRIC EA_CODE(PROTOCOL_RIP, 0)
#define EA_RIP_TAG EA_CODE(PROTOCOL_RIP, 1)
+#define EA_RIP_FROM EA_CODE(PROTOCOL_RIP, 2)
static inline int rip_is_v2(struct rip_proto *p)
{ return p->rip2; }
diff --git a/proto/rpki/rpki.c b/proto/rpki/rpki.c
index ab0837f3..be3d19ab 100644
--- a/proto/rpki/rpki.c
+++ b/proto/rpki/rpki.c
@@ -121,18 +121,18 @@ rpki_table_add_roa(struct rpki_cache *cache, struct channel *channel, const net_
struct rpki_proto *p = cache->p;
rta a0 = {
- .src = p->p.main_source,
+ .pref = channel->preference,
.source = RTS_RPKI,
.scope = SCOPE_UNIVERSE,
.dest = RTD_NONE,
};
rta *a = rta_lookup(&a0);
- rte *e = rte_get_temp(a);
+ rte *e = rte_get_temp(a, p->p.main_source);
e->pflags = 0;
- rte_update2(channel, &pfxr->n, e, a0.src);
+ rte_update2(channel, &pfxr->n, e, e->src);
}
void
diff --git a/proto/static/static.c b/proto/static/static.c
index 2789c1bb..6d3871cc 100644
--- a/proto/static/static.c
+++ b/proto/static/static.c
@@ -56,10 +56,11 @@ static void
static_announce_rte(struct static_proto *p, struct static_route *r)
{
rta *a = allocz(RTA_MAX_SIZE);
- a->src = static_get_source(p, r->index);
+ struct rte_src *src = static_get_source(p, r->index);
a->source = RTS_STATIC;
a->scope = SCOPE_UNIVERSE;
a->dest = r->dest;
+ a->pref = p->p.main_channel->preference;
if (r->dest == RTD_UNICAST)
{
@@ -102,7 +103,7 @@ static_announce_rte(struct static_proto *p, struct static_route *r)
return;
/* We skip rta_lookup() here */
- rte *e = rte_get_temp(a);
+ rte *e = rte_get_temp(a, src);
e->pflags = 0;
if (r->cmds)
@@ -119,7 +120,7 @@ static_announce_rte(struct static_proto *p, struct static_route *r)
e->net = NULL;
}
- rte_update2(p->p.main_channel, r->net, e, a->src);
+ rte_update2(p->p.main_channel, r->net, e, src);
r->state = SRS_CLEAN;
if (r->cmds)
@@ -131,7 +132,7 @@ withdraw:
if (r->state == SRS_DOWN)
return;
- rte_update2(p->p.main_channel, r->net, NULL, a->src);
+ rte_update2(p->p.main_channel, r->net, NULL, src);
r->state = SRS_DOWN;
}
@@ -721,9 +722,9 @@ static_get_route_info(rte *rte, byte *buf)
{
eattr *a = ea_find(rte->attrs->eattrs, EA_GEN_IGP_METRIC);
if (a)
- buf += bsprintf(buf, " (%d/%u)", rte->pref, a->u.data);
+ buf += bsprintf(buf, " (%d/%u)", rte->attrs->pref, a->u.data);
else
- buf += bsprintf(buf, " (%d)", rte->pref);
+ buf += bsprintf(buf, " (%d)", rte->attrs->pref);
}
static void