Commit 3d709f69 authored by Ido Schimmel's avatar Ido Schimmel Committed by David S. Miller

ipv6: Use hash-threshold instead of modulo-N

Now that each nexthop stores its region boundary in the multipath hash
function's output space, we can use hash-threshold instead of modulo-N
in multipath selection.

This reduces the number of checks we need to perform during lookup, as
dead and linkdown nexthops are assigned a negative region boundary. In
addition, in contrast to modulo-N, only flows near region boundaries are
affected when a nexthop is added or removed.
Signed-off-by: default avatarIdo Schimmel <idosch@mellanox.com>
Acked-by: default avatarDavid Ahern <dsahern@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 7696c06a
...@@ -455,7 +455,6 @@ static struct rt6_info *rt6_multipath_select(struct rt6_info *match, ...@@ -455,7 +455,6 @@ static struct rt6_info *rt6_multipath_select(struct rt6_info *match,
int strict) int strict)
{ {
struct rt6_info *sibling, *next_sibling; struct rt6_info *sibling, *next_sibling;
int route_choosen;
/* We might have already computed the hash for ICMPv6 errors. In such /* We might have already computed the hash for ICMPv6 errors. In such
* case it will always be non-zero. Otherwise now is the time to do it. * case it will always be non-zero. Otherwise now is the time to do it.
...@@ -463,28 +462,19 @@ static struct rt6_info *rt6_multipath_select(struct rt6_info *match, ...@@ -463,28 +462,19 @@ static struct rt6_info *rt6_multipath_select(struct rt6_info *match,
if (!fl6->mp_hash) if (!fl6->mp_hash)
fl6->mp_hash = rt6_multipath_hash(fl6, NULL); fl6->mp_hash = rt6_multipath_hash(fl6, NULL);
route_choosen = fl6->mp_hash % (match->rt6i_nsiblings + 1); if (fl6->mp_hash <= atomic_read(&match->rt6i_nh_upper_bound))
/* Don't change the route, if route_choosen == 0 return match;
* (siblings does not include ourself)
*/
if (route_choosen)
list_for_each_entry_safe(sibling, next_sibling,
&match->rt6i_siblings, rt6i_siblings) {
route_choosen--;
if (route_choosen == 0) {
struct inet6_dev *idev = sibling->rt6i_idev;
if (sibling->rt6i_nh_flags & RTNH_F_DEAD) list_for_each_entry_safe(sibling, next_sibling, &match->rt6i_siblings,
break; rt6i_siblings) {
if (sibling->rt6i_nh_flags & RTNH_F_LINKDOWN && if (fl6->mp_hash > atomic_read(&sibling->rt6i_nh_upper_bound))
idev->cnf.ignore_routes_with_linkdown) continue;
break;
if (rt6_score_route(sibling, oif, strict) < 0) if (rt6_score_route(sibling, oif, strict) < 0)
break; break;
match = sibling; match = sibling;
break; break;
} }
}
return match; return match;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment