diff options
Diffstat (limited to 'net/ipv4/fib_semantics.c')
-rw-r--r-- | net/ipv4/fib_semantics.c | 34 |
1 files changed, 29 insertions, 5 deletions
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 |
1562 | static 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 | ||
1563 | void fib_select_multipath(struct fib_result *res, int hash) | 1581 | void 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 | ||