diff --git a/nest/route.h b/nest/route.h index a7a2782f..7b15fa3d 100644 --- a/nest/route.h +++ b/nest/route.h @@ -222,13 +222,6 @@ typedef struct rte { byte pflags; /* Protocol-specific flags */ btime lastmod; /* Last modified */ union { /* Protocol-dependent data (metrics etc.) */ -#ifdef CONFIG_OSPF - struct { - u32 metric1, metric2; /* OSPF Type 1 and Type 2 metrics */ - u32 tag; /* External route tag */ - u32 router_id; /* Router that originated this route */ - } ospf; -#endif #ifdef CONFIG_BABEL struct { u16 seqno; /* Babel seqno */ diff --git a/nest/rt-table.c b/nest/rt-table.c index a35ff93f..5d1932c5 100644 --- a/nest/rt-table.c +++ b/nest/rt-table.c @@ -48,6 +48,10 @@ #include "proto/rip/rip.h" #endif +#ifdef CONFIG_OSPF +#include "proto/ospf/ospf.h" +#endif + #ifdef CONFIG_BGP #include "proto/bgp/bgp.h" #endif @@ -2826,7 +2830,7 @@ rt_get_igp_metric(rte *rt) if ((a->source == RTS_OSPF) || (a->source == RTS_OSPF_IA) || (a->source == RTS_OSPF_EXT1)) - return rt->u.ospf.metric1; + return ea_find(rt->attrs->eattrs, EA_OSPF_METRIC1)->u.data; #endif #ifdef CONFIG_RIP diff --git a/proto/ospf/ospf.c b/proto/ospf/ospf.c index 21aa2ce9..3c0a9232 100644 --- a/proto/ospf/ospf.c +++ b/proto/ospf/ospf.c @@ -108,11 +108,8 @@ #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 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 void ospf_disp(timer *timer); @@ -378,10 +375,7 @@ 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; return P; } @@ -390,7 +384,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,28 +394,19 @@ 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) -{ - /* 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; -} - - void ospf_schedule_rtcalc(struct ospf_proto *p) { @@ -501,26 +488,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 @@ -607,16 +574,20 @@ ospf_get_route_info(rte * rte, byte * buf) } buf += bsprintf(buf, " %s", type); - buf += bsprintf(buf, " (%d/%d", rte->attrs->pref, rte->u.ospf.metric1); + buf += bsprintf(buf, " (%d/%d", rte->attrs->pref, ea_find(rte->attrs->eattrs, EA_OSPF_METRIC1)->u.data); if (rte->attrs->source == RTS_OSPF_EXT2) - buf += bsprintf(buf, "/%d", rte->u.ospf.metric2); + buf += bsprintf(buf, "/%d", ea_find(rte->attrs->eattrs, EA_OSPF_METRIC2)->u.data); 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) + 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 21243c94..521a6633 100644 --- a/proto/ospf/rt.c +++ b/proto/ospf/rt.c @@ -2053,25 +2053,50 @@ again1: if (reload || ort_changed(nf, &a0)) { - rte e0 = { - .attrs = rta_lookup(&a0), - .u.ospf.metric1 = nf->old_metric1 = nf->n.metric1, - .u.ospf.metric2 = nf->old_metric2 = nf->n.metric2, - .u.ospf.tag = nf->old_tag = nf->n.tag, - .u.ospf.router_id = nf->old_rid = nf->n.rid, - .pflags = EA_ID_FLAG(EA_OSPF_METRIC1) | EA_ID_FLAG(EA_OSPF_ROUTER_ID), + _Bool have_metric2 = (nf->n.type == RTS_OSPF_EXT2); + _Bool have_tag = (((nf->n.type == RTS_OSPF_EXT1) || (nf->n.type == RTS_OSPF_EXT2)) && nf->n.tag); + _Bool have_router_id = !!nf->n.rid; + + a0.eattrs = alloca(sizeof(ea_list) + (1 + have_metric2 + have_tag + have_router_id) * sizeof(eattr)); + memset(a0.eattrs, 0, sizeof(ea_list)); + + 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 (have_metric2) + a0.eattrs->attrs[a0.eattrs->count++] = (eattr) { + .id = EA_OSPF_METRIC2, + .type = EAF_TYPE_INT, + .u.data = nf->n.metric2, + }; + + if (have_tag) + a0.eattrs->attrs[a0.eattrs->count++] = (eattr) { + .id = EA_OSPF_TAG, + .type = EAF_TYPE_INT, + .u.data = nf->n.tag, + }; + + if (have_router_id) + a0.eattrs->attrs[a0.eattrs->count++] = (eattr) { + .id = EA_OSPF_ROUTER_ID, + .type = EAF_TYPE_ROUTER_ID, + .u.data = nf->n.rid, + }; + + rte e0 = { .attrs = rta_lookup(&a0), }; + rta_free(nf->old_rta); nf->old_rta = rta_clone(e0.attrs); - if (nf->n.type == RTS_OSPF_EXT2) - e0.pflags |= EA_ID_FLAG(EA_OSPF_METRIC2); - - /* Perhaps onfly if tag is non-zero? */ - if ((nf->n.type == RTS_OSPF_EXT1) || (nf->n.type == RTS_OSPF_EXT2)) - e0.pflags |= EA_ID_FLAG(EA_OSPF_TAG); - 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);