return;
default: {
+ uint64_t xor_hash = 0;
RouteNextHop *nh;
- ORDERED_SET_FOREACH(nh, route->nexthops)
- route_nexthop_hash_func(nh, state);
+ ORDERED_SET_FOREACH(nh, route->nexthops) {
+ struct siphash nh_state = *ASSERT_PTR(state);
+
+ route_nexthop_hash_func(nh, &nh_state);
+ xor_hash ^= siphash24_finalize(&nh_state);
+ }
+
+ siphash24_compress_typesafe(xor_hash, state);
}}
}
return route_nexthop_compare_func_full(&a->nexthop, &b->nexthop, /* with_weight= */ false);
default: {
+ r = CMP(ordered_set_size(a->nexthops), ordered_set_size(b->nexthops));
+ if (r != 0)
+ return r;
+
RouteNextHop *nh;
- ORDERED_SET_FOREACH(nh, a->nexthops) {
- r = CMP(nh, (RouteNextHop*) ordered_set_get(a->nexthops, nh));
- if (r != 0)
- return r;
- }
+ ORDERED_SET_FOREACH(nh, a->nexthops)
+ if (!ordered_set_get(b->nexthops, nh))
+ return 1;
+
return 0;
}}
}
#include "networkd-address.h"
#include "networkd-manager.h"
#include "networkd-network.h"
+#include "networkd-route.h"
#include "networkd-route-nexthop.h"
#include "ordered-set.h"
#include "set.h"
ASSERT_EQ(nh->weight, expected_weight);
}
+TEST(route_nexthops_compare) {
+ _cleanup_ordered_set_free_ OrderedSet *a_nexthops = NULL, *b_nexthops = NULL;
+ Route a = { .family = AF_INET }, b = { .family = AF_INET };
+ _cleanup_set_free_ Set *routes = NULL;
+
+ ASSERT_OK_EQ(parse_mpr("10.0.0.1@1 10", &a_nexthops), 1);
+ ASSERT_OK_EQ(parse_mpr("10.0.0.2@2 20", &a_nexthops), 1);
+ ASSERT_OK_EQ(parse_mpr("10.0.0.1@1 10", &b_nexthops), 1);
+ ASSERT_OK_EQ(parse_mpr("10.0.0.2@2 20", &b_nexthops), 1);
+
+ a.nexthops = a_nexthops;
+ b.nexthops = b_nexthops;
+ ASSERT_EQ(route_nexthops_compare_func(&a, &b), 0);
+
+ b_nexthops = ordered_set_free(b_nexthops);
+ ASSERT_OK_EQ(parse_mpr("10.0.0.1@1 10", &b_nexthops), 1);
+ ASSERT_OK_EQ(parse_mpr("10.0.0.3@2 20", &b_nexthops), 1);
+ b.nexthops = b_nexthops;
+ ASSERT_NE(route_nexthops_compare_func(&a, &b), 0);
+
+ b_nexthops = ordered_set_free(b_nexthops);
+ ASSERT_OK_EQ(parse_mpr("10.0.0.1@1 10", &b_nexthops), 1);
+ ASSERT_OK_EQ(parse_mpr("10.0.0.2@2 30", &b_nexthops), 1);
+ b.nexthops = b_nexthops;
+ ASSERT_NE(route_nexthops_compare_func(&a, &b), 0);
+
+ b_nexthops = ordered_set_free(b_nexthops);
+ ASSERT_OK_EQ(parse_mpr("10.0.0.2@2 20", &b_nexthops), 1);
+ ASSERT_OK_EQ(parse_mpr("10.0.0.1@1 10", &b_nexthops), 1);
+ b.nexthops = b_nexthops;
+ ASSERT_EQ(route_nexthops_compare_func(&a, &b), 0);
+
+ ASSERT_NOT_NULL(routes = set_new(&route_hash_ops));
+ ASSERT_OK_POSITIVE(set_put(routes, &a));
+ ASSERT_PTR_EQ(set_get(routes, &b), &a);
+ ASSERT_OK_ZERO(set_put(routes, &b));
+
+ ASSERT_OK_EQ(parse_mpr("10.0.0.3@3 30", &b_nexthops), 1);
+ ASSERT_NE(route_nexthops_compare_func(&a, &b), 0);
+}
+
TEST(config_parse_multipath_route) {
_cleanup_ordered_set_free_ OrderedSet *nexthops = NULL;