diff options
Diffstat (limited to 'nest/rt-attr.c')
-rw-r--r-- | nest/rt-attr.c | 63 |
1 files changed, 62 insertions, 1 deletions
diff --git a/nest/rt-attr.c b/nest/rt-attr.c index ce6fe85d..c1f9c793 100644 --- a/nest/rt-attr.c +++ b/nest/rt-attr.c @@ -57,9 +57,65 @@ pool *rta_pool; static slab *rta_slab; +static slab *mpnh_slab; struct protocol *attr_class_to_protocol[EAP_MAX]; +static inline unsigned int +mpnh_hash(struct mpnh *x) +{ + unsigned int h = 0; + for (; x; x = x->next) + h ^= ipa_hash(x->gw); + + return h; +} + +int +mpnh__same(struct mpnh *x, struct mpnh *y) +{ + for (; x && y; x = x->next, y = y->next) + if (!ipa_equal(x->gw, y->gw) || (x->iface != y->iface) || (x->weight != y->weight)) + return 0; + + return x == y; +} + +static struct mpnh * +mpnh_copy(struct mpnh *o) +{ + struct mpnh *first = NULL; + struct mpnh **last = &first; + + for (; o; o = o->next) + { + struct mpnh *n = sl_alloc(mpnh_slab); + n->gw = o->gw; + n->iface = o->iface; + n->next = NULL; + n->weight = o->weight; + + *last = n; + last = &(n->next); + } + + return first; +} + +static void +mpnh_free(struct mpnh *o) +{ + struct mpnh *n; + + while (o) + { + n = o->next; + sl_free(mpnh_slab, o); + o = n; + } +} + + /* * Extended Attributes */ @@ -587,7 +643,8 @@ rta_alloc_hash(void) static inline unsigned int rta_hash(rta *a) { - return (a->proto->hash_key ^ ipa_hash(a->gw) ^ ea_hash(a->eattrs)) & 0xffff; + return (a->proto->hash_key ^ ipa_hash(a->gw) ^ + mpnh_hash(a->nexthops) ^ ea_hash(a->eattrs)) & 0xffff; } static inline int @@ -604,6 +661,7 @@ rta_same(rta *x, rta *y) ipa_equal(x->from, y->from) && x->iface == y->iface && x->hostentry == y->hostentry && + mpnh_same(x->nexthops, y->nexthops) && ea_same(x->eattrs, y->eattrs)); } @@ -614,6 +672,7 @@ rta_copy(rta *o) memcpy(r, o, sizeof(rta)); r->uc = 1; + r->nexthops = mpnh_copy(o->nexthops); r->eattrs = ea_list_copy(o->eattrs); return r; } @@ -707,6 +766,7 @@ rta__free(rta *a) a->next->pprev = a->pprev; a->aflags = 0; /* Poison the entry */ rt_unlock_hostentry(a->hostentry); + mpnh_free(a->nexthops); ea_free(a->eattrs); sl_free(rta_slab, a); } @@ -798,6 +858,7 @@ rta_init(void) { rta_pool = rp_new(&root_pool, "Attributes"); rta_slab = sl_new(rta_pool, sizeof(rta)); + mpnh_slab = sl_new(rta_pool, sizeof(struct mpnh)); rta_alloc_hash(); } |