aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/route.c
diff options
context:
space:
mode:
authorHiroaki SHIMODA <shimoda.hiroaki@gmail.com>2011-03-09 15:09:58 -0500
committerDavid S. Miller <davem@davemloft.net>2011-03-13 21:37:49 -0400
commit46af31800b6916c92fffa529dc3c357008da957d (patch)
tree2c66ee7b78527da504a294f1bd8a2a899623fead /net/ipv4/route.c
parentbef55aebd560c5a6f8883c421abccee39978c58c (diff)
ipv4: Fix PMTU update.
On current net-next-2.6, when Linux receives ICMP Type: 3, Code: 4 (Destination unreachable (Fragmentation needed)), icmp_unreach -> ip_rt_frag_needed (peer->pmtu_expires is set here) -> tcp_v4_err -> do_pmtu_discovery -> ip_rt_update_pmtu (peer->pmtu_expires is already set, so check_peer_pmtu is skipped.) -> check_peer_pmtu check_peer_pmtu is skipped and MTU is not updated. To fix this, let check_peer_pmtu execute unconditionally. And some minor fixes 1) Avoid potential peer->pmtu_expires set to be zero. 2) In check_peer_pmtu, argument of time_before is reversed. 3) check_peer_pmtu expects peer->pmtu_orig is initialized as zero, but not initialized. Signed-off-by: Hiroaki SHIMODA <shimoda.hiroaki@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/route.c')
-rw-r--r--net/ipv4/route.c22
1 files changed, 17 insertions, 5 deletions
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 5655095a89e0..209989cf7d1b 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -1533,9 +1533,15 @@ unsigned short ip_rt_frag_needed(struct net *net, struct iphdr *iph,
1533 if (mtu < ip_rt_min_pmtu) 1533 if (mtu < ip_rt_min_pmtu)
1534 mtu = ip_rt_min_pmtu; 1534 mtu = ip_rt_min_pmtu;
1535 if (!peer->pmtu_expires || mtu < peer->pmtu_learned) { 1535 if (!peer->pmtu_expires || mtu < peer->pmtu_learned) {
1536 unsigned long pmtu_expires;
1537
1538 pmtu_expires = jiffies + ip_rt_mtu_expires;
1539 if (!pmtu_expires)
1540 pmtu_expires = 1UL;
1541
1536 est_mtu = mtu; 1542 est_mtu = mtu;
1537 peer->pmtu_learned = mtu; 1543 peer->pmtu_learned = mtu;
1538 peer->pmtu_expires = jiffies + ip_rt_mtu_expires; 1544 peer->pmtu_expires = pmtu_expires;
1539 } 1545 }
1540 1546
1541 inet_putpeer(peer); 1547 inet_putpeer(peer);
@@ -1549,7 +1555,7 @@ static void check_peer_pmtu(struct dst_entry *dst, struct inet_peer *peer)
1549{ 1555{
1550 unsigned long expires = peer->pmtu_expires; 1556 unsigned long expires = peer->pmtu_expires;
1551 1557
1552 if (time_before(expires, jiffies)) { 1558 if (time_before(jiffies, expires)) {
1553 u32 orig_dst_mtu = dst_mtu(dst); 1559 u32 orig_dst_mtu = dst_mtu(dst);
1554 if (peer->pmtu_learned < orig_dst_mtu) { 1560 if (peer->pmtu_learned < orig_dst_mtu) {
1555 if (!peer->pmtu_orig) 1561 if (!peer->pmtu_orig)
@@ -1574,14 +1580,20 @@ static void ip_rt_update_pmtu(struct dst_entry *dst, u32 mtu)
1574 if (mtu < ip_rt_min_pmtu) 1580 if (mtu < ip_rt_min_pmtu)
1575 mtu = ip_rt_min_pmtu; 1581 mtu = ip_rt_min_pmtu;
1576 if (!peer->pmtu_expires || mtu < peer->pmtu_learned) { 1582 if (!peer->pmtu_expires || mtu < peer->pmtu_learned) {
1583 unsigned long pmtu_expires;
1584
1585 pmtu_expires = jiffies + ip_rt_mtu_expires;
1586 if (!pmtu_expires)
1587 pmtu_expires = 1UL;
1588
1577 peer->pmtu_learned = mtu; 1589 peer->pmtu_learned = mtu;
1578 peer->pmtu_expires = jiffies + ip_rt_mtu_expires; 1590 peer->pmtu_expires = pmtu_expires;
1579 1591
1580 atomic_inc(&__rt_peer_genid); 1592 atomic_inc(&__rt_peer_genid);
1581 rt->rt_peer_genid = rt_peer_genid(); 1593 rt->rt_peer_genid = rt_peer_genid();
1582
1583 check_peer_pmtu(dst, peer);
1584 } 1594 }
1595 check_peer_pmtu(dst, peer);
1596
1585 inet_putpeer(peer); 1597 inet_putpeer(peer);
1586 } 1598 }
1587} 1599}