diff --git a/nest/rt-attr.c b/nest/rt-attr.c index d8a91e39..e6f70ad8 100644 --- a/nest/rt-attr.c +++ b/nest/rt-attr.c @@ -899,6 +899,8 @@ ea_do_sort(ea_list *e) while (ss); } +static _Bool eattr_same_value(const eattr *a, const eattr *b); + /** * In place discard duplicates and undefs in sorted ea_list. We use stable sort * for this reason. @@ -909,6 +911,30 @@ ea_do_prune(ea_list *e) eattr *s, *d, *l, *s0; int i = 0; +#if 0 + debug("[[prune]] "); + ea_dump(e); + debug(" ----> "); +#endif + + /* Prepare underlay stepper */ + uint ulc = 0; + for (ea_list *u = e->next; u; u = u->next) + ulc++; + + struct { eattr *cur, *end; } uls[ulc]; + { + ea_list *u = e->next; + for (uint i = 0; i < ulc; i++) + { + ASSERT_DIE(u->flags & EALF_SORTED); + uls[i].cur = u->attrs; + uls[i].end = u->attrs + u->count; + u = u->next; + /* debug(" [[prev %d: %p to %p]] ", i, uls[i].cur, uls[i].end); */ + } + } + s = d = e->attrs; /* Beginning of the list. @s is source, @d is destination. */ l = e->attrs + e->count; /* End of the list */ @@ -919,11 +945,38 @@ ea_do_prune(ea_list *e) /* Find a consecutive block of the same attribute */ while (s < l && s->id == s[-1].id) s++; - /* Now s0 is the most recent version, s[-1] the oldest one */ - /* Drop undefs unless this is a true overlay */ - if (s0->undef && (s[-1].undef || !e->next)) + + /* Find the attribute's underlay version */ + eattr *prev = NULL; + for (uint i = 0; i < ulc; i++) + { + while ((uls[i].cur < uls[i].end) && (uls[i].cur->id < s0->id)) + { + uls[i].cur++; + /* debug(" [[prev %d: %p (%s/%d)]] ", i, uls[i].cur, ea_class_global[uls[i].cur->id]->name, uls[i].cur->id); */ + } + + if ((uls[i].cur >= uls[i].end) || (uls[i].cur->id > s0->id)) + continue; + + prev = uls[i].cur; + break; + } + + /* Drop identicals */ + if (prev && eattr_same_value(s0, prev)) + { + /* debug(" [[drop identical %s]] ", ea_class_global[s0->id]->name); */ continue; + } + + /* Drop undefs (identical undefs already dropped before) */ + if (!prev && s0->undef) + { + /* debug(" [[drop undef %s]] ", ea_class_global[s0->id]->name); */ + continue; + } /* Copy the newest version to destination */ *d = *s0; @@ -1027,13 +1080,52 @@ ea_merge(ea_list *e, ea_list *t, int overlay) ea_list * ea_normalize(ea_list *e, int overlay) { +#if 0 + debug("(normalize)"); + ea_dump(e); + debug(" ----> "); +#endif ea_list *t = tmp_alloc(ea_scan(e, overlay)); ea_merge(e, t, overlay); ea_sort(t); +#if 0 + ea_dump(t); + debug("\n"); +#endif return t->count ? t : t->next; } +static _Bool +eattr_same_value(const eattr *a, const eattr *b) +{ + if ( + a->id != b->id || + a->flags != b->flags || + a->type != b->type || + a->undef != b->undef + ) + return 0; + + if (a->undef) + return 1; + + if (a->type & EAF_EMBEDDED) + return a->u.data == b->u.data; + else + return adata_same(a->u.ptr, b->u.ptr); +} + +static _Bool +eattr_same(const eattr *a, const eattr *b) +{ + return + eattr_same_value(a, b) && + a->originated == b->originated && + a->fresh == b->fresh; +} + + /** * ea_same - compare two &ea_list's * @x: attribute list @@ -1054,19 +1146,8 @@ ea_same(ea_list *x, ea_list *y) if (x->count != y->count) return 0; for(c=0; ccount; c++) - { - eattr *a = &x->attrs[c]; - eattr *b = &y->attrs[c]; - - if (a->id != b->id || - a->flags != b->flags || - a->type != b->type || - a->originated != b->originated || - a->fresh != b->fresh || - a->undef != b->undef || - ((a->type & EAF_EMBEDDED) ? a->u.data != b->u.data : !adata_same(a->u.ptr, b->u.ptr))) - return 0; - } + if (!eattr_same(&x->attrs[c], &y->attrs[c])) + return 0; return 1; } @@ -1421,14 +1502,22 @@ ea_dump(ea_list *e) for(i=0; icount; i++) { eattr *a = &e->attrs[i]; - debug(" %04x.%02x", a->id, a->flags); + struct ea_class *clp = (a->id < ea_class_max) ? ea_class_global[a->id] : NULL; + if (clp) + debug(" %s", clp->name); + else + debug(" 0x%x", a->id); + + debug(".%02x", a->flags); debug("=%c", "?iO?IRP???S??pE?" "??L???N?????????" "?o???r??????????" [a->type]); if (a->originated) debug("o"); - if (a->type & EAF_EMBEDDED) + if (a->undef) + debug(":undef"); + else if (a->type & EAF_EMBEDDED) debug(":%08x", a->u.data); else if (a->id == ea_gen_nexthop.id) nexthop_dump(a->u.ptr); @@ -1439,6 +1528,7 @@ ea_dump(ea_list *e) for(j=0; ju.ptr->data[j]); } + debug(" "); } if (e = e->next) debug(" | "); diff --git a/nest/rt-table.c b/nest/rt-table.c index ea0ab99b..ec1cd71c 100644 --- a/nest/rt-table.c +++ b/nest/rt-table.c @@ -503,6 +503,12 @@ rte_store(const rte *r, struct netindex *i, struct rtable_private *tab) else e->attrs = rta_lookup(e->attrs, 1); +#if 0 + debug("(store) %N ", i->addr); + ea_dump(e->attrs); + debug("\n"); +#endif + return s; } @@ -1769,6 +1775,13 @@ rte_update(struct channel *c, const net_addr *n, rte *new, struct rte_src *src) ea_clone(new->attrs) : ea_lookup(new->attrs, 0); +#if 0 + debug("%s.%s -(prefilter)-> %s: %N ", c->proto->name, c->name, c->table->name, n); + if (new) ea_dump(new->attrs); + else debug("withdraw"); + debug("\n"); +#endif + const struct filter *filter = c->in_filter; struct channel_import_stats *stats = &c->import_stats; struct mpls_fec *fec = NULL; @@ -2351,7 +2364,9 @@ rt_refresh_trace(struct rtable_private *tab, struct rt_import_hook *ih, const ch void rte_dump(struct rte_storage *e) { - debug("%-1N ", e->rte.net); + debug("(%u) %-1N", NET_TO_INDEX(e->rte.net)->index, e->rte.net); + debug("ID=%d ", e->rte.id); + debug("SENDER=%s ", e->rte.sender->req->name); debug("PF=%02x ", e->rte.pflags); debug("SRC=%uG ", e->rte.src->global_id); ea_dump(e->rte.attrs);