#include <stddef.h>
+const char * const rta_src_names[RTS_MAX] = {
+ [RTS_DUMMY] = "",
+ [RTS_STATIC] = "static",
+ [RTS_INHERIT] = "inherit",
+ [RTS_DEVICE] = "device",
+ [RTS_STATIC_DEVICE] = "static-device",
+ [RTS_REDIRECT] = "redirect",
+ [RTS_RIP] = "RIP",
+ [RTS_OSPF] = "OSPF",
+ [RTS_OSPF_IA] = "OSPF-IA",
+ [RTS_OSPF_EXT1] = "OSPF-E1",
+ [RTS_OSPF_EXT2] = "OSPF-E2",
+ [RTS_BGP] = "BGP",
+ [RTS_PIPE] = "pipe",
+ [RTS_BABEL] = "Babel",
+ [RTS_RPKI] = "RPKI",
+};
+
+const char * rta_dest_names[RTD_MAX] = {
+ [RTD_NONE] = "",
+ [RTD_UNICAST] = "unicast",
+ [RTD_BLACKHOLE] = "blackhole",
+ [RTD_UNREACHABLE] = "unreachable",
+ [RTD_PROHIBIT] = "prohibited",
+};
+
pool *rta_pool;
static slab *rta_slab_[4];
static HASH(struct rte_src) src_hash;
-struct protocol *attr_class_to_protocol[EAP_MAX];
-
-
static void
rte_src_init(void)
{
for (; x; x = x->next)
{
h ^= ipa_hash(x->gw) ^ (h << 5) ^ (h >> 9);
- for (int i=0; i<x->labels; i++)
+
+ for (int i = 0; i < x->labels; i++)
h ^= x->label[i] ^ (h << 6) ^ (h >> 7);
}
{
for (; x && y; x = x->next, y = y->next)
{
- if (!ipa_equal(x->gw, y->gw) || (x->iface != y->iface) || (x->weight != y->weight) || (x->labels != y->labels))
+ if (!ipa_equal(x->gw, y->gw) || (x->iface != y->iface) ||
+ (x->flags != y->flags) || (x->weight != y->weight) ||
+ (x->labels != y->labels))
return 0;
- for (int i=0; i<x->labels; i++)
+
+ for (int i = 0; i < x->labels; i++)
if (x->label[i] != y->label[i])
return 0;
}
- return 1;
+ return x == y;
}
static int
if (!y)
return -1;
+ /* Should we also compare flags ? */
+
r = ((int) y->weight) - ((int) x->weight);
if (r)
return r;
if (r)
return r;
- for (int i=0; i<y->labels; i++)
+ for (int i = 0; i < y->labels; i++)
{
r = ((int) y->label[i]) - ((int) x->label[i]);
if (r)
}
void
-nexthop_insert(struct nexthop *n, struct nexthop *x)
+nexthop_insert(struct nexthop **n, struct nexthop *x)
{
- struct nexthop tmp;
- memcpy(&tmp, n, sizeof(struct nexthop));
- if (nexthop_compare_node(n, x) > 0) /* Insert to the included nexthop */
- {
- memcpy(n, x, sizeof(struct nexthop));
- memcpy(x, &tmp, sizeof(struct nexthop));
- n->next = x;
- return;
- }
-
- for (struct nexthop **nn = &(n->next); *nn; nn = &((*nn)->next))
+ for (; *n; n = &((*n)->next))
{
- int cmp = nexthop_compare_node(*nn, x);
+ int cmp = nexthop_compare_node(*n, x);
if (cmp < 0)
continue;
-
- if (cmp > 0)
- {
- x->next = *nn;
- *nn = x;
- }
-
- return;
+ else if (cmp > 0)
+ break;
+ else
+ return;
}
+ x->next = *n;
+ *n = x;
}
int
static inline slab *
nexthop_slab(struct nexthop *nh)
{
- return nexthop_slab_[nh->labels > 2 ? 3 : nh->labels];
+ return nexthop_slab_[MIN(nh->labels, 3)];
}
static struct nexthop *
n->gw = o->gw;
n->iface = o->iface;
n->next = NULL;
+ n->flags = o->flags;
n->weight = o->weight;
+ n->labels = o->labels;
+ for (int i=0; i<o->labels; i++)
+ n->label[i] = o->label[i];
*last = n;
last = &(n->next);
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;
}
byte buf[CLI_MSG_SIZE];
byte *pos = buf, *end = buf + sizeof(buf);
- if (p = attr_class_to_protocol[EA_PROTO(e->id)])
+ if (EA_IS_CUSTOM(e->id))
+ {
+ const char *name = ea_custom_name(e->id);
+ if (name)
+ {
+ pos += bsprintf(pos, "%s", name);
+ status = GA_NAME;
+ }
+ else
+ pos += bsprintf(pos, "%02x.", EA_PROTO(e->id));
+ }
+ else if (p = class_to_protocol[EA_PROTO(e->id)])
{
pos += bsprintf(pos, "%s.", p->name);
if (p->get_attr)
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)
*a->pprev = a->next;
if (a->next)
a->next->pprev = a->pprev;
- a->aflags = 0; /* Poison the entry */
rt_unlock_hostentry(a->hostentry);
rt_unlock_source(a->src);
if (a->nh.next)
nexthop_free(a->nh.next);
ea_free(a->eattrs);
+ a->aflags = 0; /* Poison the entry */
sl_free(rta_slab(a), a);
}
{
rta *r = lp_alloc(lp, rta_size(o));
memcpy(r, o, rta_size(o));
+ for (struct nexthop **nhn = &(r->nh.next), *nho = o->nh.next; nho; nho = nho->next)
+ {
+ *nhn = lp_alloc(lp, nexthop_size(nho));
+ memcpy(*nhn, nho, nexthop_size(nho));
+ nhn = &((*nhn)->next);
+ }
r->aflags = 0;
r->uc = 0;
return r;
static char *rts[] = { "RTS_DUMMY", "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" };
+ "RTS_OSPF_EXT2", "RTS_BGP", "RTS_PIPE", "RTS_BABEL" };
static char *rtd[] = { "", " DEV", " HOLE", " UNREACH", " PROHIBIT" };
debug("p=%s uc=%d %s %s%s h=%04x",
}
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", rta_src_names[a->source], ip_scope_text(a->scope));
- 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]);
}
rta_slab_[0] = sl_new(rta_pool, sizeof(rta));
rta_slab_[1] = sl_new(rta_pool, sizeof(rta) + sizeof(u32));
rta_slab_[2] = sl_new(rta_pool, sizeof(rta) + sizeof(u32)*2);
- rta_slab_[3] = sl_new(rta_pool, sizeof(rta) + sizeof(u32)*NEXTHOP_MAX_LABEL_STACK);
+ rta_slab_[3] = sl_new(rta_pool, sizeof(rta) + sizeof(u32)*MPLS_MAX_LABEL_STACK);
nexthop_slab_[0] = sl_new(rta_pool, sizeof(struct nexthop));
nexthop_slab_[1] = sl_new(rta_pool, sizeof(struct nexthop) + sizeof(u32));
nexthop_slab_[2] = sl_new(rta_pool, sizeof(struct nexthop) + sizeof(u32)*2);
- nexthop_slab_[3] = sl_new(rta_pool, sizeof(struct nexthop) + sizeof(u32)*NEXTHOP_MAX_LABEL_STACK);
+ nexthop_slab_[3] = sl_new(rta_pool, sizeof(struct nexthop) + sizeof(u32)*MPLS_MAX_LABEL_STACK);
rta_alloc_hash();
rte_src_init();