diff options
| author | Xin Long <lucien.xin@gmail.com> | 2017-11-17 01:27:18 -0500 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2017-11-17 20:32:41 -0500 |
| commit | cebe84c6190d741045a322f5343f717139993c08 (patch) | |
| tree | 6952c7525c7c0a52d8125d2ce1ba473f75055f15 | |
| parent | e39d5246111399dbc6e11cd39fd8580191b86c47 (diff) | |
route: also update fnhe_genid when updating a route cache
Now when ip route flush cache and it turn out all fnhe_genid != genid.
If a redirect/pmtu icmp packet comes and the old fnhe is found and all
it's members but fnhe_genid will be updated.
Then next time when it looks up route and tries to rebind this fnhe to
the new dst, the fnhe will be flushed due to fnhe_genid != genid. It
causes this redirect/pmtu icmp packet acutally not to be applied.
This patch is to also reset fnhe_genid when updating a route cache.
Fixes: 5aad1de5ea2c ("ipv4: use separate genid for next hop exceptions")
Acked-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
Signed-off-by: Xin Long <lucien.xin@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
| -rw-r--r-- | net/ipv4/route.c | 9 |
1 files changed, 7 insertions, 2 deletions
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 11cf2fe43308..43b69af242e1 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c | |||
| @@ -651,9 +651,12 @@ static void update_or_create_fnhe(struct fib_nh *nh, __be32 daddr, __be32 gw, | |||
| 651 | struct fnhe_hash_bucket *hash; | 651 | struct fnhe_hash_bucket *hash; |
| 652 | struct fib_nh_exception *fnhe; | 652 | struct fib_nh_exception *fnhe; |
| 653 | struct rtable *rt; | 653 | struct rtable *rt; |
| 654 | u32 genid, hval; | ||
| 654 | unsigned int i; | 655 | unsigned int i; |
| 655 | int depth; | 656 | int depth; |
| 656 | u32 hval = fnhe_hashfun(daddr); | 657 | |
| 658 | genid = fnhe_genid(dev_net(nh->nh_dev)); | ||
| 659 | hval = fnhe_hashfun(daddr); | ||
| 657 | 660 | ||
| 658 | spin_lock_bh(&fnhe_lock); | 661 | spin_lock_bh(&fnhe_lock); |
| 659 | 662 | ||
| @@ -676,6 +679,8 @@ static void update_or_create_fnhe(struct fib_nh *nh, __be32 daddr, __be32 gw, | |||
| 676 | } | 679 | } |
| 677 | 680 | ||
| 678 | if (fnhe) { | 681 | if (fnhe) { |
| 682 | if (fnhe->fnhe_genid != genid) | ||
| 683 | fnhe->fnhe_genid = genid; | ||
| 679 | if (gw) | 684 | if (gw) |
| 680 | fnhe->fnhe_gw = gw; | 685 | fnhe->fnhe_gw = gw; |
| 681 | if (pmtu) | 686 | if (pmtu) |
| @@ -699,7 +704,7 @@ static void update_or_create_fnhe(struct fib_nh *nh, __be32 daddr, __be32 gw, | |||
| 699 | fnhe->fnhe_next = hash->chain; | 704 | fnhe->fnhe_next = hash->chain; |
| 700 | rcu_assign_pointer(hash->chain, fnhe); | 705 | rcu_assign_pointer(hash->chain, fnhe); |
| 701 | } | 706 | } |
| 702 | fnhe->fnhe_genid = fnhe_genid(dev_net(nh->nh_dev)); | 707 | fnhe->fnhe_genid = genid; |
| 703 | fnhe->fnhe_daddr = daddr; | 708 | fnhe->fnhe_daddr = daddr; |
| 704 | fnhe->fnhe_gw = gw; | 709 | fnhe->fnhe_gw = gw; |
| 705 | fnhe->fnhe_pmtu = pmtu; | 710 | fnhe->fnhe_pmtu = pmtu; |
