diff options
Diffstat (limited to 'nest')
-rw-r--r-- | nest/config.Y | 2 | ||||
-rw-r--r-- | nest/rt-attr.c | 24 | ||||
-rw-r--r-- | nest/rt-dev.c | 5 | ||||
-rw-r--r-- | nest/rt-show.c | 5 | ||||
-rw-r--r-- | nest/rt-table.c | 92 | ||||
-rw-r--r-- | nest/rt.h | 1 |
6 files changed, 61 insertions, 68 deletions
diff --git a/nest/config.Y b/nest/config.Y index c144f0f3..6a35cdd2 100644 --- a/nest/config.Y +++ b/nest/config.Y @@ -133,7 +133,7 @@ CF_KEYWORDS(IPV4, IPV4_MC, IPV4_MPLS, IPV6, IPV6_MC, IPV6_MPLS, IPV6_SADR, VPN4, 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) +CF_ENUM(T_ENUM_RTD, RTD_, BLACKHOLE, UNREACHABLE, PROHIBIT) CF_ENUM(T_ENUM_ROA, ROA_, UNKNOWN, VALID, INVALID) CF_ENUM_PX(T_ENUM_AF, AF_, AFI_, IPV4, IPV6) diff --git a/nest/rt-attr.c b/nest/rt-attr.c index cf3ab659..b5be936b 100644 --- a/nest/rt-attr.c +++ b/nest/rt-attr.c @@ -166,6 +166,12 @@ const char * rta_dest_names[RTD_MAX] = { [RTD_PROHIBIT] = "prohibited", }; +struct ea_class ea_gen_flowspec_valid = { + .name = "flowspec_valid", + .type = T_ENUM_FLOWSPEC_VALID, + .readonly = 1, +}; + pool *rta_pool; static slab *rta_slab; @@ -1246,20 +1252,13 @@ rta_alloc_hash(void) static inline uint rta_hash(rta *a) { - u64 h; - mem_hash_init(&h); -#define BMIX(f) mem_hash_mix_num(&h, a->f); - BMIX(dest); -#undef MIX - - return mem_hash_value(&h) ^ ea_hash(a->eattrs); + return ea_hash(a->eattrs); } static inline int rta_same(rta *x, rta *y) { - return (x->dest == y->dest && - ea_same(x->eattrs, y->eattrs)); + return ea_same(x->eattrs, y->eattrs); } static rta * @@ -1382,10 +1381,8 @@ rta_do_cow(rta *o, linpool *lp) void rta_dump(rta *a) { - static char *rtd[] = { "", " DEV", " HOLE", " UNREACH", " PROHIBIT" }; - - debug("uc=%d %s h=%04x", - a->uc, rtd[a->dest], a->hash_key); + debug("uc=%d h=%04x", + a->uc, a->hash_key); if (!a->cached) debug(" !CACHED"); if (a->eattrs) @@ -1449,6 +1446,7 @@ rta_init(void) ea_register_init(&ea_gen_source); ea_register_init(&ea_gen_nexthop); ea_register_init(&ea_gen_hostentry); + ea_register_init(&ea_gen_flowspec_valid); } /* diff --git a/nest/rt-dev.c b/nest/rt-dev.c index 9953e270..c50e018c 100644 --- a/nest/rt-dev.c +++ b/nest/rt-dev.c @@ -82,10 +82,7 @@ dev_ifa_notify(struct proto *P, uint flags, struct ifa *ad) /* Use iface ID as local source ID */ struct rte_src *src = rt_get_source(P, ad->iface->index); - rta a0 = { - .dest = RTD_UNICAST, - }; - + rta a0 = {}; struct nexthop_adata nhad = { .nh = { .iface = ad->iface, }, .ad = { .length = (void *) NEXTHOP_NEXT(&nhad.nh) - (void *) nhad.ad.data, }, diff --git a/nest/rt-show.c b/nest/rt-show.c index 32f7aa2d..0ad8f5c6 100644 --- a/nest/rt-show.c +++ b/nest/rt-show.c @@ -47,6 +47,7 @@ rt_show_rte(struct cli *c, byte *ia, rte *e, struct rt_show_data *d, int primary void (*get_route_info)(struct rte *, byte *buf); eattr *nhea = ea_find(a->eattrs, &ea_gen_nexthop); struct nexthop_adata *nhad = nhea ? (struct nexthop_adata *) nhea->u.ptr : NULL; + int dest = NEXTHOP_IS_REACHABLE(nhad) ? RTD_UNICAST : nhad->dest; tm_format_time(tm, &config->tf_route, e->lastmod); ip_addr a_from = ea_get_ip(a->eattrs, &ea_gen_from, IPA_NONE); @@ -68,10 +69,10 @@ rt_show_rte(struct cli *c, byte *ia, rte *e, struct rt_show_data *d, int primary if (d->last_table != d->tab) rt_show_table(c, d); - cli_printf(c, -1007, "%-20s %s [%s %s%s]%s%s", ia, rta_dest_name(a->dest), + cli_printf(c, -1007, "%-20s %s [%s %s%s]%s%s", ia, rta_dest_name(dest), e->src->proto->name, tm, from, primary ? (sync_error ? " !" : " *") : "", info); - if (a->dest == RTD_UNICAST) + if (dest == RTD_UNICAST) NEXTHOP_WALK(nh, nhad) { char mpls[MPLS_MAX_LABEL_STACK*12 + 5], *lsp = mpls; diff --git a/nest/rt-table.c b/nest/rt-table.c index d98f33e4..539e04d0 100644 --- a/nest/rt-table.c +++ b/nest/rt-table.c @@ -699,7 +699,7 @@ rte_trace(struct channel *c, rte *e, int dir, char *msg) { log(L_TRACE "%s.%s %c %s %N %uL %uG %s", c->proto->name, c->name ?: "?", dir, msg, e->net->n.addr, e->src->private_id, e->src->global_id, - rta_dest_name(e->attrs->dest)); + rta_dest_name(rte_dest(e))); } static inline void @@ -1177,26 +1177,17 @@ rte_validate(rte *e) return 0; } - if (net_type_match(n->n.addr, NB_DEST) == !e->attrs->dest) - { - /* Exception for flowspec that failed validation */ - if (net_is_flow(n->n.addr) && (e->attrs->dest == RTD_UNREACHABLE)) - return 1; - - log(L_WARN "Ignoring route %N with invalid dest %d received via %s", - n->n.addr, e->attrs->dest, e->sender->proto->name); - return 0; - } - eattr *nhea = ea_find(e->attrs->eattrs, &ea_gen_nexthop); - if ((!nhea) != (e->attrs->dest != RTD_UNICAST)) + int dest = nhea_dest(nhea); + + if (net_type_match(n->n.addr, NB_DEST) == !dest) { - log(L_WARN "Ignoring route %N with destination %d and %snexthop received via %s", - n->n.addr, e->attrs->dest, (nhea ? "" : "no "), e->sender->proto->name); + log(L_WARN "Ignoring route %N with invalid dest %d received via %s", + n->n.addr, dest, e->sender->proto->name); return 0; } - if ((e->attrs->dest == RTD_UNICAST) && + if ((dest == RTD_UNICAST) && !nexthop_is_sorted((struct nexthop_adata *) nhea->u.ptr)) { log(L_WARN "Ignoring unsorted multipath route %N received via %s", @@ -2431,26 +2422,27 @@ rta_apply_hostentry(rta *a, struct hostentry_adata *head) u32 *labels = head->labels; u32 lnum = (u32 *) (head->ad.data + head->ad.length) - labels; - a->dest = he->dest; - ea_set_attr_u32(&a->eattrs, &ea_gen_igp_metric, 0, he->igp_metric); - if (a->dest != RTD_UNICAST) + if (!he->src) { - /* No nexthop */ - ea_unset_attr(&a->eattrs, 0, &ea_gen_nexthop); + ea_set_dest(&a->eattrs, 0, RTD_UNREACHABLE); return; } - if (!lnum && he->nexthop_linkable) + eattr *he_nh_ea = ea_find(he->src->eattrs, &ea_gen_nexthop); + ASSERT_DIE(he_nh_ea); + + struct nexthop_adata *nhad = (struct nexthop_adata *) he_nh_ea->u.ptr; + int idest = nhea_dest(he_nh_ea); + + if ((idest != RTD_UNICAST) || + !lnum && he->nexthop_linkable) { /* Just link the nexthop chain, no label append happens. */ ea_copy_attr(&a->eattrs, he->src->eattrs, &ea_gen_nexthop); return; } - eattr *he_nh_ea = ea_find(he->src->eattrs, &ea_gen_nexthop); - struct nexthop_adata *nhad = (struct nexthop_adata *) he_nh_ea->u.ptr; - uint total_size = OFFSETOF(struct nexthop_adata, nh); NEXTHOP_WALK(nh, nhad) @@ -2467,10 +2459,14 @@ rta_apply_hostentry(rta *a, struct hostentry_adata *head) if (total_size == OFFSETOF(struct nexthop_adata, nh)) { - a->dest = RTD_UNREACHABLE; log(L_WARN "No valid nexthop remaining, setting route unreachable"); - ea_unset_attr(&a->eattrs, 0, &ea_gen_nexthop); + struct nexthop_adata nha = { + .ad.length = NEXTHOP_DEST_SIZE, + .dest = RTD_UNREACHABLE, + }; + + ea_set_attr_data(&a->eattrs, &ea_gen_nexthop, 0, &nha.ad.data, nha.ad.length); return; } @@ -2511,19 +2507,28 @@ rta_apply_hostentry(rta *a, struct hostentry_adata *head) static inline struct hostentry_adata * rta_next_hop_outdated(rta *a) { + /* First retrieve the hostentry */ eattr *heea = ea_find(a->eattrs, &ea_gen_hostentry); if (!heea) return NULL; struct hostentry_adata *head = (struct hostentry_adata *) heea->u.ptr; + /* If no nexthop is present, we have to create one */ + eattr *a_nh_ea = ea_find(a->eattrs, &ea_gen_nexthop); + if (!a_nh_ea) + return head; + + struct nexthop_adata *nhad = (struct nexthop_adata *) a_nh_ea->u.ptr; + + /* Shortcut for unresolvable hostentry */ if (!head->he->src) - return (a->dest != RTD_UNREACHABLE) ? head : NULL; + return NEXTHOP_IS_REACHABLE(nhad) ? head : NULL; + /* Comparing our nexthop with the hostentry nexthop */ eattr *he_nh_ea = ea_find(head->he->src->eattrs, &ea_gen_nexthop); - eattr *a_nh_ea = ea_find(a->eattrs, &ea_gen_nexthop); - return ((a->dest != head->he->dest) || + return ( (ea_get_int(a->eattrs, &ea_gen_igp_metric, IGP_METRIC_UNKNOWN) != head->he->igp_metric) || (!head->he->nexthop_linkable) || (!he_nh_ea != !a_nh_ea) || @@ -2682,16 +2687,16 @@ rt_flowspec_update_rte(rtable *tab, rte *r) const net_addr *n = r->net->n.addr; struct bgp_proto *p = (void *) r->src->proto; int valid = rt_flowspec_check(bc->base_table, tab, n, r->attrs, p->is_interior); - int dest = valid ? RTD_NONE : RTD_UNREACHABLE; - - if (dest == r->attrs->dest) + int old = rt_get_flowspec_valid(r); + if (old == valid) return NULL; rta *a = alloca(RTA_MAX_SIZE); memcpy(a, r->attrs, rta_size(r->attrs)); - a->dest = dest; a->cached = 0; + ea_set_attr_u32(&a->eattrs, &ea_gen_flowspec_valid, 0, valid); + rte *new = sl_alloc(rte_slab); memcpy(new, r, sizeof(rte)); new->attrs = rta_lookup(a); @@ -3524,7 +3529,6 @@ rt_update_hostentry(rtable *tab, struct hostentry *he) /* Reset the hostentry */ he->src = NULL; - he->dest = RTD_UNREACHABLE; he->nexthop_linkable = 0; he->igp_metric = 0; @@ -3545,16 +3549,12 @@ rt_update_hostentry(rtable *tab, struct hostentry *he) goto done; } - if (a->dest == RTD_UNICAST) - { - eattr *ea = ea_find(a->eattrs, &ea_gen_nexthop); - if (!ea) - { - log(L_WARN "No nexthop in unicast route"); - goto done; - } - - NEXTHOP_WALK(nh, (struct nexthop_adata *) ea->u.ptr) + eattr *nhea = ea_find(a->eattrs, &ea_gen_nexthop); + ASSERT_DIE(nhea); + struct nexthop_adata *nhad = (void *) nhea->u.ptr; + + if (NEXTHOP_IS_REACHABLE(nhad)) + NEXTHOP_WALK(nh, nhad) if (ipa_zero(nh->gw)) { if (if_local_addr(he->addr, nh->iface)) @@ -3567,10 +3567,8 @@ rt_update_hostentry(rtable *tab, struct hostentry *he) direct++; } - } he->src = rta_clone(a); - he->dest = a->dest; he->nexthop_linkable = !direct; he->igp_metric = rt_get_igp_metric(e); } @@ -144,7 +144,6 @@ struct hostentry { unsigned hash_key; /* Hash key */ unsigned uc; /* Use count */ struct rta *src; /* Source rta entry */ - byte dest; /* Chosen route destination type (RTD_...) */ byte nexthop_linkable; /* Nexthop list is completely non-device */ u32 igp_metric; /* Chosen route IGP metric */ }; |