aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorXin Long <lucien.xin@gmail.com>2018-04-01 10:40:35 -0400
committerDavid S. Miller <davem@davemloft.net>2018-04-01 20:57:39 -0400
commit6174a30df1b902e1fedbd728f5343937e83e64e6 (patch)
treee8df044f9eccb9ad38268b1f5a0561dc6b2c50ab
parent781492abce1bd3ef3fb01271772d6b77e260d193 (diff)
route: check sysctl_fib_multipath_use_neigh earlier than hash
Prior to this patch, when one packet is hashed into path [1] (hash <= nh_upper_bound) and it's neigh is dead, it will try path [2]. However, if path [2]'s neigh is alive but it's hash > nh_upper_bound, it will not return this alive path. This packet will never be sent even if path [2] is alive. 3.3.3.1/24: nexthop via 1.1.1.254 dev eth1 weight 1 <--[1] (dead neigh) nexthop via 2.2.2.254 dev eth2 weight 1 <--[2] With sysctl_fib_multipath_use_neigh set is supposed to find an available path respecting to the l3/l4 hash. But if there is no available route with this hash, it should at least return an alive route even with other hash. This patch is to fix it by processing fib_multipath_use_neigh earlier than the hash check, so that it will at least return an alive route if there is when fib_multipath_use_neigh is enabled. It's also compatible with before when there are alive routes with the l3/l4 hash. Fixes: a6db4494d218 ("net: ipv4: Consider failed nexthops in multipath routes") Reported-by: Jianlin Shi <jishi@redhat.com> Signed-off-by: Xin Long <lucien.xin@gmail.com> Acked-by: David Ahern <dsa@cumulusnetworks.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/ipv4/fib_semantics.c20
1 files changed, 11 insertions, 9 deletions
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index e7c602c600ac..c27122f01b87 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -1746,18 +1746,20 @@ void fib_select_multipath(struct fib_result *res, int hash)
1746 bool first = false; 1746 bool first = false;
1747 1747
1748 for_nexthops(fi) { 1748 for_nexthops(fi) {
1749 if (net->ipv4.sysctl_fib_multipath_use_neigh) {
1750 if (!fib_good_nh(nh))
1751 continue;
1752 if (!first) {
1753 res->nh_sel = nhsel;
1754 first = true;
1755 }
1756 }
1757
1749 if (hash > atomic_read(&nh->nh_upper_bound)) 1758 if (hash > atomic_read(&nh->nh_upper_bound))
1750 continue; 1759 continue;
1751 1760
1752 if (!net->ipv4.sysctl_fib_multipath_use_neigh || 1761 res->nh_sel = nhsel;
1753 fib_good_nh(nh)) { 1762 return;
1754 res->nh_sel = nhsel;
1755 return;
1756 }
1757 if (!first) {
1758 res->nh_sel = nhsel;
1759 first = true;
1760 }
1761 } endfor_nexthops(fi); 1763 } endfor_nexthops(fi);
1762} 1764}
1763#endif 1765#endif