diff options
-rw-r--r-- | doc/bird.sgml | 2 | ||||
-rw-r--r-- | filter/test.conf | 1 | ||||
-rw-r--r-- | nest/config.Y | 2 | ||||
-rw-r--r-- | nest/protocol.h | 1 | ||||
-rw-r--r-- | nest/route.h | 36 | ||||
-rw-r--r-- | nest/rt-attr.c | 7 | ||||
-rw-r--r-- | nest/rt-table.c | 55 | ||||
-rw-r--r-- | proto/babel/babel.c | 95 | ||||
-rw-r--r-- | proto/babel/babel.h | 1 | ||||
-rw-r--r-- | proto/bgp/attrs.c | 7 | ||||
-rw-r--r-- | proto/bgp/bgp.c | 1 | ||||
-rw-r--r-- | proto/bgp/bgp.h | 1 | ||||
-rw-r--r-- | proto/ospf/ospf.c | 72 | ||||
-rw-r--r-- | proto/ospf/rt.c | 52 | ||||
-rw-r--r-- | proto/rip/rip.c | 74 | ||||
-rw-r--r-- | proto/rip/rip.h | 1 | ||||
-rw-r--r-- | sysdep/bsd/krt-sock.c | 19 | ||||
-rw-r--r-- | sysdep/linux/netlink.c | 26 | ||||
-rw-r--r-- | sysdep/unix/krt.c | 88 | ||||
-rw-r--r-- | sysdep/unix/krt.h | 7 |
20 files changed, 246 insertions, 302 deletions
diff --git a/doc/bird.sgml b/doc/bird.sgml index 1d5ae056..4df1d94f 100644 --- a/doc/bird.sgml +++ b/doc/bird.sgml @@ -1747,7 +1747,7 @@ Common route attributes are: <tag><label id="rta-source"><m/enum/ source</tag> what protocol has told me about this route. Possible values: - <cf/RTS_DUMMY/, <cf/RTS_STATIC/, <cf/RTS_INHERIT/, <cf/RTS_DEVICE/, + <cf/RTS_STATIC/, <cf/RTS_INHERIT/, <cf/RTS_DEVICE/, <cf/RTS_RIP/, <cf/RTS_OSPF/, <cf/RTS_OSPF_IA/, <cf/RTS_OSPF_EXT1/, <cf/RTS_OSPF_EXT2/, <cf/RTS_BGP/, <cf/RTS_PIPE/, <cf/RTS_BABEL/. diff --git a/filter/test.conf b/filter/test.conf index 484628e5..2a5a2d98 100644 --- a/filter/test.conf +++ b/filter/test.conf @@ -398,7 +398,6 @@ bt_test_suite(t_ip_set, "Testing sets of ip address"); function t_enum() { - bt_assert(format(RTS_DUMMY) = "(enum 30)0"); bt_assert(format(RTS_STATIC) = "(enum 30)1"); bt_assert(format(NET_IP4) = "(enum 36)1"); bt_assert(format(NET_VPN6) = "(enum 36)4"); diff --git a/nest/config.Y b/nest/config.Y index 72bc7930..92a80589 100644 --- a/nest/config.Y +++ b/nest/config.Y @@ -130,7 +130,7 @@ CF_KEYWORDS(SORTED, TRIE, MIN, MAX, SETTLE, TIME) /* For r_args_channel */ CF_KEYWORDS(IPV4, IPV4_MC, IPV4_MPLS, IPV6, IPV6_MC, IPV6_MPLS, IPV6_SADR, VPN4, VPN4_MC, VPN4_MPLS, VPN6, VPN6_MC, VPN6_MPLS, ROA4, ROA6, FLOW4, FLOW6, MPLS, PRI, SEC) -CF_ENUM(T_ENUM_RTS, RTS_, DUMMY, STATIC, INHERIT, DEVICE, STATIC_DEVICE, REDIRECT, +CF_ENUM(T_ENUM_RTS, RTS_, STATIC, INHERIT, DEVICE, STATIC_DEVICE, REDIRECT, RIP, OSPF, OSPF_IA, OSPF_EXT1, OSPF_EXT2, BGP, PIPE, BABEL) CF_ENUM(T_ENUM_SCOPE, SCOPE_, HOST, LINK, SITE, ORGANIZATION, UNIVERSE, UNDEFINED) CF_ENUM(T_ENUM_RTD, RTD_, UNICAST, BLACKHOLE, UNREACHABLE, PROHIBIT) diff --git a/nest/protocol.h b/nest/protocol.h index 6ee97b7c..62fd2b66 100644 --- a/nest/protocol.h +++ b/nest/protocol.h @@ -241,6 +241,7 @@ struct proto { struct rte * (*rte_modify)(struct rte *, struct linpool *); void (*rte_insert)(struct network *, struct rte *); void (*rte_remove)(struct network *, struct rte *); + u32 (*rte_igp_metric)(struct rte *); /* Hic sunt protocol-specific data */ }; diff --git a/nest/route.h b/nest/route.h index 19c13538..9fd3bdcc 100644 --- a/nest/route.h +++ b/nest/route.h @@ -263,20 +263,6 @@ typedef struct rte { byte pflags; /* Protocol-specific flags */ btime lastmod; /* Last modified */ union { /* Protocol-dependent data (metrics etc.) */ -#ifdef CONFIG_RIP - struct { - struct iface *from; /* Incoming iface */ - u8 metric; /* RIP metric */ - u16 tag; /* External route tag */ - } rip; -#endif -#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_BGP struct { u8 suppressed; /* Used for deterministic MED comparison */ @@ -284,20 +270,6 @@ typedef struct rte { struct rtable *base_table; /* Base table for Flowspec validation */ } bgp; #endif -#ifdef CONFIG_BABEL - struct { - u16 seqno; /* Babel seqno */ - u16 metric; /* Babel metric */ - u64 router_id; /* Babel router id */ - } babel; -#endif - struct { /* Routes generated by krt sync (both temporary and inherited ones) */ - s8 src; /* Alleged route source (see krt.h) */ - u8 proto; /* Kernel source protocol ID */ - u8 seen; /* Seen during last scan */ - u8 best; /* Best route in network, propagated to core */ - u32 metric; /* Kernel metric */ - } krt; } u; } rte; @@ -498,7 +470,6 @@ typedef struct rta { struct nexthop nh; /* Next hop */ } rta; -#define RTS_DUMMY 0 /* Dummy route to be removed soon */ #define RTS_STATIC 1 /* Normal static route */ #define RTS_INHERIT 2 /* Route inherited from kernel */ #define RTS_DEVICE 3 /* Device route */ @@ -546,8 +517,8 @@ typedef struct eattr { byte flags; /* Protocol-dependent flags */ byte type; /* Attribute type and several flags (EAF_...) */ union { - u32 data; - const struct adata *ptr; /* Attribute data elsewhere */ + uintptr_t data; + const struct adata *ptr; /* Attribute data elsewhere */ } u; } eattr; @@ -578,6 +549,7 @@ const char *ea_custom_name(uint ea); #define EAF_TYPE_AS_PATH 0x06 /* BGP AS path (encoding per RFC 1771:4.3) */ #define EAF_TYPE_BITFIELD 0x09 /* 32-bit embedded bitfield */ #define EAF_TYPE_INT_SET 0x0a /* Set of u32's (e.g., a community list) */ +#define EAF_TYPE_PTR 0x0d /* Pointer to an object */ #define EAF_TYPE_EC_SET 0x0e /* Set of pairs of u32's - ext. community list */ #define EAF_TYPE_LC_SET 0x12 /* Set of triplets of u32's - large community list */ #define EAF_TYPE_UNDEF 0x1f /* `force undefined' entry */ @@ -632,7 +604,7 @@ struct ea_walk_state { eattr *ea_find(ea_list *, unsigned ea); eattr *ea_walk(struct ea_walk_state *s, uint id, uint max); -int ea_get_int(ea_list *, unsigned ea, int def); +uintptr_t ea_get_int(ea_list *, unsigned ea, uintptr_t def); void ea_dump(ea_list *); void ea_sort(ea_list *); /* Sort entries in all sub-lists */ unsigned ea_scan(ea_list *); /* How many bytes do we need for merged ea_list */ diff --git a/nest/rt-attr.c b/nest/rt-attr.c index 4057bf37..1bece201 100644 --- a/nest/rt-attr.c +++ b/nest/rt-attr.c @@ -61,7 +61,6 @@ const adata null_adata; /* adata of length 0 */ const char * const rta_src_names[RTS_MAX] = { - [RTS_DUMMY] = "", [RTS_STATIC] = "static", [RTS_INHERIT] = "inherit", [RTS_DEVICE] = "device", @@ -541,8 +540,8 @@ ea_walk(struct ea_walk_state *s, uint id, uint max) * by calling ea_find() to find the attribute, extracting its value or returning * a provided default if no such attribute is present. */ -int -ea_get_int(ea_list *e, unsigned id, int def) +uintptr_t +ea_get_int(ea_list *e, unsigned id, uintptr_t def) { eattr *a = ea_find(e, id); if (!a) @@ -1260,7 +1259,7 @@ rta_do_cow(rta *o, linpool *lp) void rta_dump(rta *a) { - static char *rts[] = { "RTS_DUMMY", "RTS_STATIC", "RTS_INHERIT", "RTS_DEVICE", + static char *rts[] = { "", "RTS_STATIC", "RTS_INHERIT", "RTS_DEVICE", "RTS_STAT_DEV", "RTS_REDIR", "RTS_RIP", "RTS_OSPF", "RTS_OSPF_IA", "RTS_OSPF_EXT1", "RTS_OSPF_EXT2", "RTS_BGP", "RTS_PIPE", "RTS_BABEL" }; diff --git a/nest/rt-table.c b/nest/rt-table.c index 65ff2a59..a5a8c421 100644 --- a/nest/rt-table.c +++ b/nest/rt-table.c @@ -1686,26 +1686,6 @@ rte_update_unlock(void) lp_flush(rte_update_pool); } -static inline void -rte_hide_dummy_routes(net *net, rte **dummy) -{ - if (net->routes && net->routes->attrs->source == RTS_DUMMY) - { - *dummy = net->routes; - net->routes = (*dummy)->next; - } -} - -static inline void -rte_unhide_dummy_routes(net *net, rte **dummy) -{ - if (*dummy) - { - (*dummy)->next = net->routes; - net->routes = *dummy; - } -} - /** * rte_update - enter a new update to a routing table * @table: table to be updated @@ -1754,7 +1734,6 @@ rte_update2(struct channel *c, const net_addr *n, rte *new, struct rte_src *src) // struct proto *p = c->proto; struct proto_stats *stats = &c->stats; const struct filter *filter = c->in_filter; - rte *dummy = NULL; net *nn; ASSERT(c->channel_state == CS_UP); @@ -1833,9 +1812,7 @@ rte_update2(struct channel *c, const net_addr *n, rte *new, struct rte_src *src) recalc: /* And recalculate the best route */ - rte_hide_dummy_routes(nn, &dummy); rte_recalculate(c, nn, new, src); - rte_unhide_dummy_routes(nn, &dummy); rte_update_unlock(); return; @@ -3686,36 +3663,12 @@ rt_get_igp_metric(rte *rt) if (ea) return ea->u.data; - rta *a = rt->attrs; - -#ifdef CONFIG_OSPF - if ((a->source == RTS_OSPF) || - (a->source == RTS_OSPF_IA) || - (a->source == RTS_OSPF_EXT1)) - return rt->u.ospf.metric1; -#endif - -#ifdef CONFIG_RIP - if (a->source == RTS_RIP) - return rt->u.rip.metric; -#endif - -#ifdef CONFIG_BGP - if (a->source == RTS_BGP) - { - u64 metric = bgp_total_aigp_metric(rt); - return (u32) MIN(metric, (u64) IGP_METRIC_UNKNOWN); - } -#endif - -#ifdef CONFIG_BABEL - if (a->source == RTS_BABEL) - return rt->u.babel.metric; -#endif - - if (a->source == RTS_DEVICE) + if (rt->attrs->source == RTS_DEVICE) return 0; + if (rt->src->proto->rte_igp_metric) + return rt->src->proto->rte_igp_metric(rt); + return IGP_METRIC_UNKNOWN; } diff --git a/proto/babel/babel.c b/proto/babel/babel.c index 09d8ad7e..30809000 100644 --- a/proto/babel/babel.c +++ b/proto/babel/babel.c @@ -648,6 +648,29 @@ babel_announce_rte(struct babel_proto *p, struct babel_entry *e) .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, }; /* @@ -660,10 +683,6 @@ babel_announce_rte(struct babel_proto *p, struct babel_entry *e) rta *a = rta_lookup(&a0); rte *rte = rte_get_temp(a, p->p.main_source); - 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); e->unreachable = 0; rte_update2(c, e->n.addr, rte, p->p.main_source); @@ -680,7 +699,6 @@ babel_announce_rte(struct babel_proto *p, struct babel_entry *e) rta *a = rta_lookup(&a0); rte *rte = rte_get_temp(a, p->p.main_source); - memset(&rte->u.babel, 0, sizeof(rte->u.babel)); rte->pflags = 0; e->unreachable = 1; @@ -2009,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->attrs->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 @@ -2017,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; @@ -2240,27 +2267,6 @@ babel_preexport(struct proto *P, struct rte *new) 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. @@ -2275,10 +2281,22 @@ babel_rt_notify(struct proto *P, struct channel *c UNUSED, struct network *net, if (new) { /* Update */ - uint internal = (new->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) { @@ -2321,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); } @@ -2363,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/bgp/attrs.c b/proto/bgp/attrs.c index 09c0bc57..6963833a 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 diff --git a/proto/bgp/bgp.c b/proto/bgp/bgp.c index b5a31ab7..52400762 100644 --- a/proto/bgp/bgp.c +++ b/proto/bgp/bgp.c @@ -1679,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 9d25da21..26e04966 100644 --- a/proto/bgp/bgp.h +++ b/proto/bgp/bgp.h @@ -584,6 +584,7 @@ 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 *); int bgp_get_attr(const struct eattr *e, byte *buf, int buflen); diff --git a/proto/ospf/ospf.c b/proto/ospf/ospf.c index 03b16350..f9aa6cd1 100644 --- a/proto/ospf/ospf.c +++ b/proto/ospf/ospf.c @@ -108,11 +108,9 @@ #include "ospf.h" static int ospf_preexport(struct proto *P, rte *new); -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 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) @@ -500,26 +498,6 @@ ospf_preexport(struct proto *P, rte *e) 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 @@ -609,16 +587,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_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 cda464e0..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 */ @@ -2062,23 +2062,45 @@ again1: if (reload || ort_changed(nf, &a0)) { - rta *a = rta_lookup(&a0); - rte *e = rte_get_temp(a, p->p.main_source); + 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/rip/rip.c b/proto/rip/rip.c index f2e56e93..0556939a 100644 --- a/proto/rip/rip.c +++ b/proto/rip/rip.c @@ -188,12 +188,28 @@ rip_announce_rte(struct rip_proto *p, struct rip_entry *en) a0.nh.iface = rt->from->ifa->iface; } + 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, + }; + rta *a = rta_lookup(&a0); rte *e = rte_get_temp(a, p->p.main_source); - 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); rte_update(&p->p, en->n.addr, e); @@ -307,8 +323,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 +356,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->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 +1085,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 +1124,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 +1200,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->attrs->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/sysdep/bsd/krt-sock.c b/sysdep/bsd/krt-sock.c index 521f43f3..efdb18a3 100644 --- a/sysdep/bsd/krt-sock.c +++ b/sysdep/bsd/krt-sock.c @@ -582,16 +582,21 @@ krt_read_route(struct ks_msg *msg, struct krt_proto *p, int scan) done: e = rte_get_temp(&a); e->net = net; - e->u.krt.src = src; - e->u.krt.proto = src2; - e->u.krt.seen = 0; - e->u.krt.best = 0; - e->u.krt.metric = 0; + + ea_list *ea = alloca(sizeof(ea_list) + 1 * sizeof(eattr)); + *ea = (ea_list) { .count = 1, .next = e->attrs->eattrs }; + e->attrs->eattrs = ea; + + ea->attrs[0] = (eattr) { + .id = EA_KRT_SOURCE, + .type = EAF_TYPE_INT, + .u.data = src2, + }; if (scan) - krt_got_route(p, e); + krt_got_route(p, e, src); else - krt_got_route_async(p, e, new); + krt_got_route_async(p, e, new, src); } static void diff --git a/sysdep/linux/netlink.c b/sysdep/linux/netlink.c index d8ac2e82..e103c8ef 100644 --- a/sysdep/linux/netlink.c +++ b/sysdep/linux/netlink.c @@ -1397,8 +1397,6 @@ nl_send_route(struct krt_proto *p, rte *e, int op, int dest, struct nexthop *nh) if (p->af == AF_MPLS) priority = 0; - else if (a->source == RTS_DUMMY) - priority = e->u.krt.metric; else if (KRT_CF->sys.metric) priority = KRT_CF->sys.metric; else if ((op != NL_OP_DELETE) && (ea = ea_find(eattrs, EA_KRT_METRIC))) @@ -1582,16 +1580,26 @@ nl_announce_route(struct nl_parse_state *s) { rte *e = rte_get_temp(s->attrs, s->proto->p.main_source); e->net = s->net; - e->u.krt.src = s->krt_src; - e->u.krt.proto = s->krt_proto; - e->u.krt.seen = 0; - e->u.krt.best = 0; - e->u.krt.metric = s->krt_metric; + + ea_list *ea = alloca(sizeof(ea_list) + 2 * sizeof(eattr)); + *ea = (ea_list) { .count = 2, .next = e->attrs->eattrs }; + e->attrs->eattrs = ea; + + ea->attrs[0] = (eattr) { + .id = EA_KRT_SOURCE, + .type = EAF_TYPE_INT, + .u.data = s->krt_proto, + }; + ea->attrs[1] = (eattr) { + .id = EA_KRT_METRIC, + .type = EAF_TYPE_INT, + .u.data = s->krt_metric, + }; if (s->scan) - krt_got_route(s->proto, e); + krt_got_route(s->proto, e, s->krt_src); else - krt_got_route_async(s->proto, e, s->new); + krt_got_route_async(s->proto, e, s->new, s->krt_src); s->net = NULL; s->attrs = NULL; diff --git a/sysdep/unix/krt.c b/sysdep/unix/krt.c index c03fa047..495ab986 100644 --- a/sysdep/unix/krt.c +++ b/sysdep/unix/krt.c @@ -277,22 +277,23 @@ static struct tbf rl_alien = TBF_DEFAULT_LOG_LIMITS; * the same key. */ +static inline u32 +krt_metric(rte *a) +{ + eattr *ea = ea_find(a->attrs->eattrs, EA_KRT_METRIC); + return ea ? ea->u.data : 0; +} + static inline int krt_same_key(rte *a, rte *b) { - return a->u.krt.metric == b->u.krt.metric; + return (krt_metric(a) == krt_metric(b)); } static inline int krt_uptodate(rte *a, rte *b) { - if (a->attrs != b->attrs) - return 0; - - if (a->u.krt.proto != b->u.krt.proto) - return 0; - - return 1; + return (a->attrs == b->attrs); } static void @@ -301,8 +302,6 @@ krt_learn_announce_update(struct krt_proto *p, rte *e) net *n = e->net; rta *aa = rta_clone(e->attrs); rte *ee = rte_get_temp(aa, p->p.main_source); - ee->pflags = EA_ID_FLAG(EA_KRT_SOURCE) | EA_ID_FLAG(EA_KRT_METRIC); - ee->u.krt = e->u.krt; rte_update(&p->p, n->n.addr, ee); } @@ -331,7 +330,7 @@ krt_learn_scan(struct krt_proto *p, rte *e) { krt_trace_in_rl(&rl_alien, p, e, "[alien] seen"); rte_free(e); - m->u.krt.seen = 1; + m->pflags |= KRT_REF_SEEN; } else { @@ -347,7 +346,7 @@ krt_learn_scan(struct krt_proto *p, rte *e) { e->next = n->routes; n->routes = e; - e->u.krt.seen = 1; + e->pflags |= KRT_REF_SEEN; } } @@ -377,24 +376,23 @@ again: ee = &n->routes; while (e = *ee) { - if (e->u.krt.best) + if (e->pflags & KRT_REF_BEST) old_best = e; - if (!e->u.krt.seen) + if (!(e->pflags & KRT_REF_SEEN)) { *ee = e->next; rte_free(e); continue; } - if (!best || best->u.krt.metric > e->u.krt.metric) + if (!best || krt_metric(best) > krt_metric(e)) { best = e; pbest = ee; } - e->u.krt.seen = 0; - e->u.krt.best = 0; + e->pflags &= ~(KRT_REF_SEEN | KRT_REF_BEST); ee = &e->next; } if (!n->routes) @@ -408,18 +406,18 @@ again: goto again; } - best->u.krt.best = 1; + best->pflags |= KRT_REF_BEST; *pbest = best->next; best->next = n->routes; n->routes = best; if ((best != old_best) || p->reload) { - DBG("%I/%d: announcing (metric=%d)\n", n->n.prefix, n->n.pxlen, best->u.krt.metric); + DBG("%I/%d: announcing (metric=%d)\n", n->n.prefix, n->n.pxlen, krt_metric(best)); krt_learn_announce_update(p, best); } else - DBG("%I/%d: uptodate (metric=%d)\n", n->n.prefix, n->n.pxlen, best->u.krt.metric); + DBG("%I/%d: uptodate (metric=%d)\n", n->n.prefix, n->n.pxlen, krt_metric(best)); } FIB_ITERATE_END; @@ -479,18 +477,18 @@ krt_learn_async(struct krt_proto *p, rte *e, int new) bestp = &n->routes; for(gg=&n->routes; g=*gg; gg=&g->next) { - if (best->u.krt.metric > g->u.krt.metric) + if (krt_metric(best) > krt_metric(g)) { best = g; bestp = gg; } - g->u.krt.best = 0; + g->pflags &= ~KRT_REF_BEST; } if (best) { - best->u.krt.best = 1; + best->pflags |= KRT_REF_BEST; *bestp = best->next; best->next = n->routes; n->routes = best; @@ -531,12 +529,6 @@ krt_dump(struct proto *P) rt_dump(p->krt_table); } -static void -krt_dump_attrs(rte *e) -{ - debug(" [m=%d,p=%d]", e->u.krt.metric, e->u.krt.proto); -} - #endif /* @@ -627,13 +619,14 @@ krt_same_dest(rte *k, rte *e) */ void -krt_got_route(struct krt_proto *p, rte *e) +krt_got_route(struct krt_proto *p, rte *e, s8 src) { rte *new = NULL, *rt_free = NULL; net *n = e->net; + e->pflags = 0; #ifdef KRT_ALLOW_LEARN - switch (e->u.krt.src) + switch (src) { case KRT_SRC_KERNEL: goto ignore; @@ -755,11 +748,12 @@ krt_prune(struct krt_proto *p) } void -krt_got_route_async(struct krt_proto *p, rte *e, int new) +krt_got_route_async(struct krt_proto *p, rte *e, int new, s8 src) { net *net = e->net; + e->pflags = 0; - switch (e->u.krt.src) + switch (src) { case KRT_SRC_BIRD: /* Should be filtered by the back end */ @@ -889,22 +883,6 @@ krt_scan_timer_kick(struct krt_proto *p) * Updates */ -static void -krt_make_tmp_attrs(struct rte *rt, struct linpool *pool) -{ - rte_init_tmp_attrs(rt, pool, 2); - rte_make_tmp_attr(rt, EA_KRT_SOURCE, EAF_TYPE_INT, rt->u.krt.proto); - rte_make_tmp_attr(rt, EA_KRT_METRIC, EAF_TYPE_INT, rt->u.krt.metric); -} - -static void -krt_store_tmp_attrs(struct rte *rt, struct linpool *pool) -{ - rte_init_tmp_attrs(rt, pool, 2); - rt->u.krt.proto = rte_store_tmp_attr(rt, EA_KRT_SOURCE); - rt->u.krt.metric = rte_store_tmp_attr(rt, EA_KRT_METRIC); -} - static int krt_preexport(struct proto *P, rte *e) { @@ -984,14 +962,6 @@ krt_feed_end(struct channel *C) } -static int -krt_rte_same(rte *a, rte *b) -{ - /* src is always KRT_SRC_ALIEN and type is irrelevant */ - return (a->u.krt.proto == b->u.krt.proto) && (a->u.krt.metric == b->u.krt.metric); -} - - /* * Protocol glue */ @@ -1050,9 +1020,6 @@ krt_init(struct proto_config *CF) p->p.if_notify = krt_if_notify; p->p.reload_routes = krt_reload_routes; p->p.feed_end = krt_feed_end; - p->p.make_tmp_attrs = krt_make_tmp_attrs; - p->p.store_tmp_attrs = krt_store_tmp_attrs; - p->p.rte_same = krt_rte_same; krt_sys_init(p); return &p->p; @@ -1210,6 +1177,5 @@ struct protocol proto_unix_kernel = { .get_attr = krt_get_attr, #ifdef KRT_ALLOW_LEARN .dump = krt_dump, - .dump_attrs = krt_dump_attrs, #endif }; diff --git a/sysdep/unix/krt.h b/sysdep/unix/krt.h index 62228f08..20858cd7 100644 --- a/sysdep/unix/krt.h +++ b/sysdep/unix/krt.h @@ -24,6 +24,9 @@ struct kif_proto; #define EA_KRT_SOURCE EA_CODE(PROTOCOL_KERNEL, 0) #define EA_KRT_METRIC EA_CODE(PROTOCOL_KERNEL, 1) +#define KRT_REF_SEEN 0x1 /* Seen in table */ +#define KRT_REF_BEST 0x2 /* Best in table */ + /* Whenever we recognize our own routes, we allow learing of foreign routes */ #ifdef CONFIG_SELF_CONSCIOUS @@ -76,8 +79,8 @@ extern pool *krt_pool; struct proto_config * kif_init_config(int class); void kif_request_scan(void); -void krt_got_route(struct krt_proto *p, struct rte *e); -void krt_got_route_async(struct krt_proto *p, struct rte *e, int new); +void krt_got_route(struct krt_proto *p, struct rte *e, s8 src); +void krt_got_route_async(struct krt_proto *p, struct rte *e, int new, s8 src); static inline int krt_get_sync_error(struct krt_proto *p, struct rte *e) |