|
@@ -2594,6 +2594,7 @@ static struct rt6_info *ip6_route_info_create(struct fib6_config *cfg,
|
|
#endif
|
|
#endif
|
|
|
|
|
|
rt->rt6i_metric = cfg->fc_metric;
|
|
rt->rt6i_metric = cfg->fc_metric;
|
|
|
|
+ rt->rt6i_nh_weight = 1;
|
|
|
|
|
|
/* We cannot add true routes via loopback here,
|
|
/* We cannot add true routes via loopback here,
|
|
they would result in kernel looping; promote them to reject routes
|
|
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)
|
|
int total = 0;
|
|
int total = 0;
|
|
|
|
|
|
if (!rt6_is_dead(rt))
|
|
if (!rt6_is_dead(rt))
|
|
- total++;
|
|
|
|
|
|
+ total += rt->rt6i_nh_weight;
|
|
|
|
|
|
list_for_each_entry(iter, &rt->rt6i_siblings, rt6i_siblings) {
|
|
list_for_each_entry(iter, &rt->rt6i_siblings, rt6i_siblings) {
|
|
if (!rt6_is_dead(iter))
|
|
if (!rt6_is_dead(iter))
|
|
- total++;
|
|
|
|
|
|
+ total += iter->rt6i_nh_weight;
|
|
}
|
|
}
|
|
|
|
|
|
return total;
|
|
return total;
|
|
@@ -3522,7 +3523,7 @@ static void rt6_upper_bound_set(struct rt6_info *rt, int *weight, int total)
|
|
int upper_bound = -1;
|
|
int upper_bound = -1;
|
|
|
|
|
|
if (!rt6_is_dead(rt)) {
|
|
if (!rt6_is_dead(rt)) {
|
|
- (*weight)++;
|
|
|
|
|
|
+ *weight += rt->rt6i_nh_weight;
|
|
upper_bound = DIV_ROUND_CLOSEST_ULL((u64) (*weight) << 31,
|
|
upper_bound = DIV_ROUND_CLOSEST_ULL((u64) (*weight) << 31,
|
|
total) - 1;
|
|
total) - 1;
|
|
}
|
|
}
|
|
@@ -4024,6 +4025,8 @@ static int ip6_route_multipath_add(struct fib6_config *cfg,
|
|
goto cleanup;
|
|
goto cleanup;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ rt->rt6i_nh_weight = rtnh->rtnh_hops + 1;
|
|
|
|
+
|
|
err = ip6_route_info_append(&rt6_nh_list, rt, &r_cfg);
|
|
err = ip6_route_info_append(&rt6_nh_list, rt, &r_cfg);
|
|
if (err) {
|
|
if (err) {
|
|
dst_release_immediate(&rt->dst);
|
|
dst_release_immediate(&rt->dst);
|
|
@@ -4246,7 +4249,7 @@ static int rt6_add_nexthop(struct sk_buff *skb, struct rt6_info *rt)
|
|
if (!rtnh)
|
|
if (!rtnh)
|
|
goto nla_put_failure;
|
|
goto nla_put_failure;
|
|
|
|
|
|
- rtnh->rtnh_hops = 0;
|
|
|
|
|
|
+ rtnh->rtnh_hops = rt->rt6i_nh_weight - 1;
|
|
rtnh->rtnh_ifindex = rt->dst.dev ? rt->dst.dev->ifindex : 0;
|
|
rtnh->rtnh_ifindex = rt->dst.dev ? rt->dst.dev->ifindex : 0;
|
|
|
|
|
|
if (rt6_nexthop_info(skb, rt, &flags, true) < 0)
|
|
if (rt6_nexthop_info(skb, rt, &flags, true) < 0)
|