summaryrefslogtreecommitdiff
path: root/nest/rt-attr.c
diff options
context:
space:
mode:
Diffstat (limited to 'nest/rt-attr.c')
-rw-r--r--nest/rt-attr.c65
1 files changed, 35 insertions, 30 deletions
diff --git a/nest/rt-attr.c b/nest/rt-attr.c
index 881687de..73ca4748 100644
--- a/nest/rt-attr.c
+++ b/nest/rt-attr.c
@@ -88,9 +88,6 @@ static struct idm src_ids;
static HASH(struct rte_src) src_hash;
-struct protocol *attr_class_to_protocol[EAP_MAX];
-
-
static void
rte_src_init(void)
{
@@ -553,29 +550,47 @@ ea_do_sort(ea_list *e)
while (ss);
}
+/**
+ * In place discard duplicates, undefs and temporary attributes in sorted
+ * ea_list. We use stable sort for this reason.
+ **/
static inline void
ea_do_prune(ea_list *e)
{
eattr *s, *d, *l, *s0;
int i = 0;
- /* Discard duplicates and undefs. Do you remember sorting was stable? */
- s = d = e->attrs;
- l = e->attrs + e->count;
+ s = d = e->attrs; /* Beginning of the list. @s is source, @d is destination. */
+ l = e->attrs + e->count; /* End of the list */
+
+ /* Walk from begin to end. */
while (s < l)
{
s0 = s++;
+ /* Find a consecutive block of the same attribute */
while (s < l && s->id == s[-1].id)
s++;
- /* s0 is the most recent version, s[-1] the oldest one */
- if ((s0->type & EAF_TYPE_MASK) != EAF_TYPE_UNDEF)
- {
- *d = *s0;
- d->type = (d->type & ~(EAF_ORIGINATED|EAF_FRESH)) | (s[-1].type & EAF_ORIGINATED);
- d++;
- i++;
- }
+
+ /* Now s0 is the most recent version, s[-1] the oldest one */
+ /* Drop undefs */
+ if ((s0->type & EAF_TYPE_MASK) == EAF_TYPE_UNDEF)
+ continue;
+
+ /* Drop temporary attributes */
+ if (s0->type & EAF_TEMP)
+ continue;
+
+ /* Copy the newest version to destination */
+ *d = *s0;
+
+ /* Preserve info whether it originated locally */
+ d->type = (d->type & ~(EAF_ORIGINATED|EAF_FRESH)) | (s[-1].type & EAF_ORIGINATED);
+
+ /* Next destination */
+ d++;
+ i++;
}
+
e->count = i;
}
@@ -851,7 +866,7 @@ ea_show(struct cli *c, eattr *e)
byte buf[CLI_MSG_SIZE];
byte *pos = buf, *end = buf + sizeof(buf);
- if (p = attr_class_to_protocol[EA_PROTO(e->id)])
+ if (p = class_to_protocol[EA_PROTO(e->id)])
{
pos += bsprintf(pos, "%s.", p->name);
if (p->get_attr)
@@ -1131,15 +1146,7 @@ rta_lookup(rta *o)
ASSERT(!(o->aflags & RTAF_CACHED));
if (o->eattrs)
- {
- if (o->eattrs->next) /* Multiple ea_list's, need to merge them */
- {
- ea_list *ml = alloca(ea_scan(o->eattrs));
- ea_merge(o->eattrs, ml);
- o->eattrs = ml;
- }
- ea_sort(o->eattrs);
- }
+ ea_normalize(o->eattrs);
h = rta_hash(o);
for(r=rta_hash_table[h & rta_cache_mask]; r; r=r->next)
@@ -1253,17 +1260,15 @@ rta_dump_all(void)
}
void
-rta_show(struct cli *c, rta *a, ea_list *eal)
+rta_show(struct cli *c, rta *a)
{
static char *src_names[] = { "dummy", "static", "inherit", "device", "static-device", "redirect",
"RIP", "OSPF", "OSPF-IA", "OSPF-E1", "OSPF-E2", "BGP", "pipe" };
- int i;
cli_printf(c, -1008, "\tType: %s %s", src_names[a->source], ip_scope_text(a->scope));
- if (!eal)
- eal = a->eattrs;
- for(; eal; eal=eal->next)
- for(i=0; i<eal->count; i++)
+
+ for(ea_list *eal = a->eattrs; eal; eal=eal->next)
+ for(int i=0; i<eal->count; i++)
ea_show(c, &eal->attrs[i]);
}