aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/networking/ip-sysctl.txt10
-rw-r--r--include/net/netns/ipv4.h3
-rw-r--r--net/ipv4/fib_semantics.c34
-rw-r--r--net/ipv4/sysctl_net_ipv4.c11
4 files changed, 53 insertions, 5 deletions
diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
index b183e2b606c8..6c7f365b1515 100644
--- a/Documentation/networking/ip-sysctl.txt
+++ b/Documentation/networking/ip-sysctl.txt
@@ -63,6 +63,16 @@ fwmark_reflect - BOOLEAN
63 fwmark of the packet they are replying to. 63 fwmark of the packet they are replying to.
64 Default: 0 64 Default: 0
65 65
66fib_multipath_use_neigh - BOOLEAN
67 Use status of existing neighbor entry when determining nexthop for
68 multipath routes. If disabled, neighbor information is not used and
69 packets could be directed to a failed nexthop. Only valid for kernels
70 built with CONFIG_IP_ROUTE_MULTIPATH enabled.
71 Default: 0 (disabled)
72 Possible values:
73 0 - disabled
74 1 - enabled
75
66route/max_size - INTEGER 76route/max_size - INTEGER
67 Maximum number of routes allowed in the kernel. Increase 77 Maximum number of routes allowed in the kernel. Increase
68 this when using large numbers of interfaces and/or routes. 78 this when using large numbers of interfaces and/or routes.
diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h
index a69cde3ce460..d061ffeb1e71 100644
--- a/include/net/netns/ipv4.h
+++ b/include/net/netns/ipv4.h
@@ -133,6 +133,9 @@ struct netns_ipv4 {
133 struct fib_rules_ops *mr_rules_ops; 133 struct fib_rules_ops *mr_rules_ops;
134#endif 134#endif
135#endif 135#endif
136#ifdef CONFIG_IP_ROUTE_MULTIPATH
137 int sysctl_fib_multipath_use_neigh;
138#endif
136 atomic_t rt_genid; 139 atomic_t rt_genid;
137}; 140};
138#endif 141#endif
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index d97268e8ff10..ab64d9f2eef9 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -1559,21 +1559,45 @@ int fib_sync_up(struct net_device *dev, unsigned int nh_flags)
1559} 1559}
1560 1560
1561#ifdef CONFIG_IP_ROUTE_MULTIPATH 1561#ifdef CONFIG_IP_ROUTE_MULTIPATH
1562static bool fib_good_nh(const struct fib_nh *nh)
1563{
1564 int state = NUD_REACHABLE;
1565
1566 if (nh->nh_scope == RT_SCOPE_LINK) {
1567 struct neighbour *n;
1568
1569 rcu_read_lock_bh();
1570
1571 n = __ipv4_neigh_lookup_noref(nh->nh_dev, nh->nh_gw);
1572 if (n)
1573 state = n->nud_state;
1574
1575 rcu_read_unlock_bh();
1576 }
1577
1578 return !!(state & NUD_VALID);
1579}
1562 1580
1563void fib_select_multipath(struct fib_result *res, int hash) 1581void fib_select_multipath(struct fib_result *res, int hash)
1564{ 1582{
1565 struct fib_info *fi = res->fi; 1583 struct fib_info *fi = res->fi;
1584 struct net *net = fi->fib_net;
1585 bool first = false;
1566 1586
1567 for_nexthops(fi) { 1587 for_nexthops(fi) {
1568 if (hash > atomic_read(&nh->nh_upper_bound)) 1588 if (hash > atomic_read(&nh->nh_upper_bound))
1569 continue; 1589 continue;
1570 1590
1571 res->nh_sel = nhsel; 1591 if (!net->ipv4.sysctl_fib_multipath_use_neigh ||
1572 return; 1592 fib_good_nh(nh)) {
1593 res->nh_sel = nhsel;
1594 return;
1595 }
1596 if (!first) {
1597 res->nh_sel = nhsel;
1598 first = true;
1599 }
1573 } endfor_nexthops(fi); 1600 } endfor_nexthops(fi);
1574
1575 /* Race condition: route has just become dead. */
1576 res->nh_sel = 0;
1577} 1601}
1578#endif 1602#endif
1579 1603
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
index 1e1fe6086dd9..bb0419582b8d 100644
--- a/net/ipv4/sysctl_net_ipv4.c
+++ b/net/ipv4/sysctl_net_ipv4.c
@@ -960,6 +960,17 @@ static struct ctl_table ipv4_net_table[] = {
960 .mode = 0644, 960 .mode = 0644,
961 .proc_handler = proc_dointvec, 961 .proc_handler = proc_dointvec,
962 }, 962 },
963#ifdef CONFIG_IP_ROUTE_MULTIPATH
964 {
965 .procname = "fib_multipath_use_neigh",
966 .data = &init_net.ipv4.sysctl_fib_multipath_use_neigh,
967 .maxlen = sizeof(int),
968 .mode = 0644,
969 .proc_handler = proc_dointvec_minmax,
970 .extra1 = &zero,
971 .extra2 = &one,
972 },
973#endif
963 { } 974 { }
964}; 975};
965 976