diff --git a/lib/nexthop.c b/lib/nexthop.c index 474abee309..8e16e70590 100644 --- a/lib/nexthop.c +++ b/lib/nexthop.c @@ -314,14 +314,52 @@ unsigned int nexthop_level(struct nexthop *nexthop) return rv; } -uint32_t nexthop_hash(struct nexthop *nexthop) +uint32_t nexthop_hash(const struct nexthop *nexthop) { - uint32_t key; + uint32_t key = 0x45afe398; - key = jhash_1word(nexthop->vrf_id, 0x45afe398); - key = jhash_1word(nexthop->ifindex, key); - key = jhash_1word(nexthop->type, key); - key = jhash(&nexthop->gate, sizeof(union g_addr), key); + key = jhash_3words(nexthop->type, nexthop->vrf_id, + nexthop->nh_label_type, key); + /* gate and blackhole are together in a union */ + key = jhash(&nexthop->gate, sizeof(nexthop->gate), key); + key = jhash(&nexthop->src, sizeof(nexthop->src), key); + key = jhash(&nexthop->rmap_src, sizeof(nexthop->rmap_src), key); + if (nexthop->nh_label) { + int labels = nexthop->nh_label->num_labels; + int i = 0; + + while (labels >= 3) { + key = jhash_3words(nexthop->nh_label->label[i], + nexthop->nh_label->label[i + 1], + nexthop->nh_label->label[i + 2], + key); + labels -= 3; + i += 3; + } + + if (labels >= 2) { + key = jhash_2words(nexthop->nh_label->label[i], + nexthop->nh_label->label[i + 1], + key); + labels -= 2; + i += 2; + } + + if (labels >= 1) + key = jhash_1word(nexthop->nh_label->label[i], key); + } + + switch (nexthop->type) { + case NEXTHOP_TYPE_IPV4_IFINDEX: + case NEXTHOP_TYPE_IPV6_IFINDEX: + case NEXTHOP_TYPE_IFINDEX: + key = jhash_1word(nexthop->ifindex, key); + break; + case NEXTHOP_TYPE_BLACKHOLE: + case NEXTHOP_TYPE_IPV4: + case NEXTHOP_TYPE_IPV6: + break; + } return key; } diff --git a/lib/nexthop.h b/lib/nexthop.h index 9cdb040fc4..24b0953191 100644 --- a/lib/nexthop.h +++ b/lib/nexthop.h @@ -136,7 +136,7 @@ void nexthop_del_labels(struct nexthop *); * Returns: * 32-bit hash of nexthop */ -uint32_t nexthop_hash(struct nexthop *nexthop); +uint32_t nexthop_hash(const struct nexthop *nexthop); extern bool nexthop_same(const struct nexthop *nh1, const struct nexthop *nh2); diff --git a/lib/nexthop_group.c b/lib/nexthop_group.c index 5fb4ea5234..fa89b7708c 100644 --- a/lib/nexthop_group.c +++ b/lib/nexthop_group.c @@ -25,6 +25,7 @@ #include #include #include +#include #ifndef VTYSH_EXTRACT_PL #include "lib/nexthop_group_clippy.c" @@ -147,6 +148,21 @@ void copy_nexthops(struct nexthop **tnh, const struct nexthop *nh, } } +uint32_t nexthop_group_hash(const struct nexthop_group *nhg) +{ + struct nexthop *nh; + uint32_t key = 0; + + /* + * We are not interested in hashing over any recursively + * resolved nexthops + */ + for (nh = nhg->nexthop; nh; nh = nh->next) + key = jhash_1word(nexthop_hash(nh), key); + + return key; +} + static void nhgc_delete_nexthops(struct nexthop_group_cmd *nhgc) { struct nexthop *nexthop; diff --git a/lib/nexthop_group.h b/lib/nexthop_group.h index d96d0ab9f5..f68033c20c 100644 --- a/lib/nexthop_group.h +++ b/lib/nexthop_group.h @@ -47,6 +47,8 @@ void nexthop_del(struct nexthop_group *nhg, struct nexthop *nexthop); void copy_nexthops(struct nexthop **tnh, const struct nexthop *nh, struct nexthop *rparent); +uint32_t nexthop_group_hash(const struct nexthop_group *nhg); + /* The following for loop allows to iterate over the nexthop * structure of routes. *