Skip to content

Commit 398958a

Browse files
idoschdavem330
authored andcommitted
ipv6: Add support for non-equal-cost multipath
The use of hash-threshold instead of modulo-N makes it trivial to add support for non-equal-cost multipath. Instead of dividing the multipath hash function's output space equally between the nexthops, each nexthop is assigned a region size which is proportional to its weight. Signed-off-by: Ido Schimmel <[email protected]> Acked-by: David Ahern <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 3d709f6 commit 398958a

File tree

2 files changed

+8
-4
lines changed

2 files changed

+8
-4
lines changed

include/net/ip6_fib.h

+1
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@ struct rt6_info {
171171
u32 rt6i_metric;
172172
u32 rt6i_pmtu;
173173
/* more non-fragment space at head required */
174+
int rt6i_nh_weight;
174175
unsigned short rt6i_nfheader_len;
175176
u8 rt6i_protocol;
176177
u8 exception_bucket_flushed:1,

net/ipv6/route.c

+7-4
Original file line numberDiff line numberDiff line change
@@ -2594,6 +2594,7 @@ static struct rt6_info *ip6_route_info_create(struct fib6_config *cfg,
25942594
#endif
25952595

25962596
rt->rt6i_metric = cfg->fc_metric;
2597+
rt->rt6i_nh_weight = 1;
25972598

25982599
/* We cannot add true routes via loopback here,
25992600
they would result in kernel looping; promote them to reject routes
@@ -3507,11 +3508,11 @@ static int rt6_multipath_total_weight(const struct rt6_info *rt)
35073508
int total = 0;
35083509

35093510
if (!rt6_is_dead(rt))
3510-
total++;
3511+
total += rt->rt6i_nh_weight;
35113512

35123513
list_for_each_entry(iter, &rt->rt6i_siblings, rt6i_siblings) {
35133514
if (!rt6_is_dead(iter))
3514-
total++;
3515+
total += iter->rt6i_nh_weight;
35153516
}
35163517

35173518
return total;
@@ -3522,7 +3523,7 @@ static void rt6_upper_bound_set(struct rt6_info *rt, int *weight, int total)
35223523
int upper_bound = -1;
35233524

35243525
if (!rt6_is_dead(rt)) {
3525-
(*weight)++;
3526+
*weight += rt->rt6i_nh_weight;
35263527
upper_bound = DIV_ROUND_CLOSEST_ULL((u64) (*weight) << 31,
35273528
total) - 1;
35283529
}
@@ -4024,6 +4025,8 @@ static int ip6_route_multipath_add(struct fib6_config *cfg,
40244025
goto cleanup;
40254026
}
40264027

4028+
rt->rt6i_nh_weight = rtnh->rtnh_hops + 1;
4029+
40274030
err = ip6_route_info_append(&rt6_nh_list, rt, &r_cfg);
40284031
if (err) {
40294032
dst_release_immediate(&rt->dst);
@@ -4246,7 +4249,7 @@ static int rt6_add_nexthop(struct sk_buff *skb, struct rt6_info *rt)
42464249
if (!rtnh)
42474250
goto nla_put_failure;
42484251

4249-
rtnh->rtnh_hops = 0;
4252+
rtnh->rtnh_hops = rt->rt6i_nh_weight - 1;
42504253
rtnh->rtnh_ifindex = rt->dst.dev ? rt->dst.dev->ifindex : 0;
42514254

42524255
if (rt6_nexthop_info(skb, rt, &flags, true) < 0)

0 commit comments

Comments
 (0)