From 950775f6fa3d569a9d7cd05e33538d35e895d688 Mon Sep 17 00:00:00 2001 From: Maria Matejka Date: Sun, 15 May 2022 18:09:30 +0200 Subject: Route destination field merged with nexthop attribute; splitting flowspec validation result out. As there is either a nexthop or another destination specification (or othing in case of ROAs and Flowspec), it may be merged together. This code is somehow quirky and should be replaced in future by better implementation of nexthop. Also flowspec validation result has its own attribute now as it doesn't have anything to do with route nexthop. --- nest/config.Y | 2 +- nest/rt-attr.c | 24 +++++++-------- nest/rt-dev.c | 5 +--- nest/rt-show.c | 5 ++-- nest/rt-table.c | 92 ++++++++++++++++++++++++++++----------------------------- nest/rt.h | 1 - 6 files changed, 61 insertions(+), 68 deletions(-) (limited to 'nest') 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); } diff --git a/nest/rt.h b/nest/rt.h index eb3f8454..6f15fec6 100644 --- a/nest/rt.h +++ b/nest/rt.h @@ -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 */ }; -- cgit v1.2.3