aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/route.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/route.c')
-rw-r--r--net/ipv4/route.c185
1 files changed, 39 insertions, 146 deletions
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 67b08745daf9..677d65253e4c 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -669,7 +669,7 @@ static inline int rt_fast_clean(struct rtable *rth)
669static inline int rt_valuable(struct rtable *rth) 669static inline int rt_valuable(struct rtable *rth)
670{ 670{
671 return (rth->rt_flags & (RTCF_REDIRECTED | RTCF_NOTIFY)) || 671 return (rth->rt_flags & (RTCF_REDIRECTED | RTCF_NOTIFY)) ||
672 (rt_has_peer(rth) && rt_peer_ptr(rth)->pmtu_expires); 672 rth->dst.expires;
673} 673}
674 674
675static int rt_may_expire(struct rtable *rth, unsigned long tmo1, unsigned long tmo2) 675static int rt_may_expire(struct rtable *rth, unsigned long tmo1, unsigned long tmo2)
@@ -1242,13 +1242,6 @@ skip_hashing:
1242 return rt; 1242 return rt;
1243} 1243}
1244 1244
1245static atomic_t __rt_peer_genid = ATOMIC_INIT(0);
1246
1247static u32 rt_peer_genid(void)
1248{
1249 return atomic_read(&__rt_peer_genid);
1250}
1251
1252void rt_bind_peer(struct rtable *rt, __be32 daddr, int create) 1245void rt_bind_peer(struct rtable *rt, __be32 daddr, int create)
1253{ 1246{
1254 struct inet_peer_base *base; 1247 struct inet_peer_base *base;
@@ -1262,8 +1255,6 @@ void rt_bind_peer(struct rtable *rt, __be32 daddr, int create)
1262 if (peer) { 1255 if (peer) {
1263 if (!rt_set_peer(rt, peer)) 1256 if (!rt_set_peer(rt, peer))
1264 inet_putpeer(peer); 1257 inet_putpeer(peer);
1265 else
1266 rt->rt_peer_genid = rt_peer_genid();
1267 } 1258 }
1268} 1259}
1269 1260
@@ -1323,30 +1314,6 @@ static void rt_del(unsigned int hash, struct rtable *rt)
1323 spin_unlock_bh(rt_hash_lock_addr(hash)); 1314 spin_unlock_bh(rt_hash_lock_addr(hash));
1324} 1315}
1325 1316
1326static void check_peer_redir(struct dst_entry *dst, struct inet_peer *peer)
1327{
1328 struct rtable *rt = (struct rtable *) dst;
1329 __be32 orig_gw = rt->rt_gateway;
1330 struct neighbour *n;
1331
1332 dst_confirm(&rt->dst);
1333
1334 rt->rt_gateway = peer->redirect_learned.a4;
1335
1336 n = ipv4_neigh_lookup(&rt->dst, NULL, &rt->rt_gateway);
1337 if (!n) {
1338 rt->rt_gateway = orig_gw;
1339 return;
1340 }
1341 if (!(n->nud_state & NUD_VALID)) {
1342 neigh_event_send(n, NULL);
1343 } else {
1344 rt->rt_flags |= RTCF_REDIRECTED;
1345 call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, n);
1346 }
1347 neigh_release(n);
1348}
1349
1350/* called in rcu_read_lock() section */ 1317/* called in rcu_read_lock() section */
1351void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw, 1318void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw,
1352 __be32 saddr, struct net_device *dev) 1319 __be32 saddr, struct net_device *dev)
@@ -1355,7 +1322,6 @@ void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw,
1355 struct in_device *in_dev = __in_dev_get_rcu(dev); 1322 struct in_device *in_dev = __in_dev_get_rcu(dev);
1356 __be32 skeys[2] = { saddr, 0 }; 1323 __be32 skeys[2] = { saddr, 0 };
1357 int ikeys[2] = { dev->ifindex, 0 }; 1324 int ikeys[2] = { dev->ifindex, 0 };
1358 struct inet_peer *peer;
1359 struct net *net; 1325 struct net *net;
1360 1326
1361 if (!in_dev) 1327 if (!in_dev)
@@ -1388,6 +1354,8 @@ void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw,
1388 rthp = &rt_hash_table[hash].chain; 1354 rthp = &rt_hash_table[hash].chain;
1389 1355
1390 while ((rt = rcu_dereference(*rthp)) != NULL) { 1356 while ((rt = rcu_dereference(*rthp)) != NULL) {
1357 struct neighbour *n;
1358
1391 rthp = &rt->dst.rt_next; 1359 rthp = &rt->dst.rt_next;
1392 1360
1393 if (rt->rt_key_dst != daddr || 1361 if (rt->rt_key_dst != daddr ||
@@ -1401,13 +1369,16 @@ void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw,
1401 rt->rt_gateway != old_gw) 1369 rt->rt_gateway != old_gw)
1402 continue; 1370 continue;
1403 1371
1404 peer = rt_get_peer_create(rt, rt->rt_dst); 1372 n = ipv4_neigh_lookup(&rt->dst, NULL, &new_gw);
1405 if (peer) { 1373 if (n) {
1406 if (peer->redirect_learned.a4 != new_gw) { 1374 if (!(n->nud_state & NUD_VALID)) {
1407 peer->redirect_learned.a4 = new_gw; 1375 neigh_event_send(n, NULL);
1408 atomic_inc(&__rt_peer_genid); 1376 } else {
1377 rt->rt_gateway = new_gw;
1378 rt->rt_flags |= RTCF_REDIRECTED;
1379 call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, n);
1409 } 1380 }
1410 check_peer_redir(&rt->dst, peer); 1381 neigh_release(n);
1411 } 1382 }
1412 } 1383 }
1413 } 1384 }
@@ -1425,23 +1396,6 @@ reject_redirect:
1425 ; 1396 ;
1426} 1397}
1427 1398
1428static bool peer_pmtu_expired(struct inet_peer *peer)
1429{
1430 unsigned long orig = ACCESS_ONCE(peer->pmtu_expires);
1431
1432 return orig &&
1433 time_after_eq(jiffies, orig) &&
1434 cmpxchg(&peer->pmtu_expires, orig, 0) == orig;
1435}
1436
1437static bool peer_pmtu_cleaned(struct inet_peer *peer)
1438{
1439 unsigned long orig = ACCESS_ONCE(peer->pmtu_expires);
1440
1441 return orig &&
1442 cmpxchg(&peer->pmtu_expires, orig, 0) == orig;
1443}
1444
1445static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst) 1399static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst)
1446{ 1400{
1447 struct rtable *rt = (struct rtable *)dst; 1401 struct rtable *rt = (struct rtable *)dst;
@@ -1451,16 +1405,13 @@ static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst)
1451 if (dst->obsolete > 0) { 1405 if (dst->obsolete > 0) {
1452 ip_rt_put(rt); 1406 ip_rt_put(rt);
1453 ret = NULL; 1407 ret = NULL;
1454 } else if (rt->rt_flags & RTCF_REDIRECTED) { 1408 } else if ((rt->rt_flags & RTCF_REDIRECTED) ||
1409 rt->dst.expires) {
1455 unsigned int hash = rt_hash(rt->rt_key_dst, rt->rt_key_src, 1410 unsigned int hash = rt_hash(rt->rt_key_dst, rt->rt_key_src,
1456 rt->rt_oif, 1411 rt->rt_oif,
1457 rt_genid(dev_net(dst->dev))); 1412 rt_genid(dev_net(dst->dev)));
1458 rt_del(hash, rt); 1413 rt_del(hash, rt);
1459 ret = NULL; 1414 ret = NULL;
1460 } else if (rt_has_peer(rt)) {
1461 struct inet_peer *peer = rt_peer_ptr(rt);
1462 if (peer_pmtu_expired(peer))
1463 dst_metric_set(dst, RTAX_MTU, peer->pmtu_orig);
1464 } 1415 }
1465 } 1416 }
1466 return ret; 1417 return ret;
@@ -1604,50 +1555,17 @@ out: kfree_skb(skb);
1604 return 0; 1555 return 0;
1605} 1556}
1606 1557
1607static void check_peer_pmtu(struct dst_entry *dst, struct inet_peer *peer)
1608{
1609 unsigned long expires = ACCESS_ONCE(peer->pmtu_expires);
1610
1611 if (!expires)
1612 return;
1613 if (time_before(jiffies, expires)) {
1614 u32 orig_dst_mtu = dst_mtu(dst);
1615 if (peer->pmtu_learned < orig_dst_mtu) {
1616 if (!peer->pmtu_orig)
1617 peer->pmtu_orig = dst_metric_raw(dst, RTAX_MTU);
1618 dst_metric_set(dst, RTAX_MTU, peer->pmtu_learned);
1619 }
1620 } else if (cmpxchg(&peer->pmtu_expires, expires, 0) == expires)
1621 dst_metric_set(dst, RTAX_MTU, peer->pmtu_orig);
1622}
1623
1624static void ip_rt_update_pmtu(struct dst_entry *dst, u32 mtu) 1558static void ip_rt_update_pmtu(struct dst_entry *dst, u32 mtu)
1625{ 1559{
1626 struct rtable *rt = (struct rtable *) dst; 1560 struct rtable *rt = (struct rtable *) dst;
1627 struct inet_peer *peer;
1628 1561
1629 dst_confirm(dst); 1562 dst_confirm(dst);
1630 1563
1631 peer = rt_get_peer_create(rt, rt->rt_dst); 1564 if (mtu < ip_rt_min_pmtu)
1632 if (peer) { 1565 mtu = ip_rt_min_pmtu;
1633 unsigned long pmtu_expires = ACCESS_ONCE(peer->pmtu_expires);
1634
1635 if (mtu < ip_rt_min_pmtu)
1636 mtu = ip_rt_min_pmtu;
1637 if (!pmtu_expires || mtu < peer->pmtu_learned) {
1638
1639 pmtu_expires = jiffies + ip_rt_mtu_expires;
1640 if (!pmtu_expires)
1641 pmtu_expires = 1UL;
1642
1643 peer->pmtu_learned = mtu;
1644 peer->pmtu_expires = pmtu_expires;
1645 1566
1646 atomic_inc(&__rt_peer_genid); 1567 rt->rt_pmtu = mtu;
1647 rt->rt_peer_genid = rt_peer_genid(); 1568 dst_set_expires(&rt->dst, ip_rt_mtu_expires);
1648 }
1649 check_peer_pmtu(dst, peer);
1650 }
1651} 1569}
1652 1570
1653void ipv4_update_pmtu(struct sk_buff *skb, struct net *net, u32 mtu, 1571void ipv4_update_pmtu(struct sk_buff *skb, struct net *net, u32 mtu,
@@ -1679,30 +1597,12 @@ void ipv4_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, u32 mtu)
1679} 1597}
1680EXPORT_SYMBOL_GPL(ipv4_sk_update_pmtu); 1598EXPORT_SYMBOL_GPL(ipv4_sk_update_pmtu);
1681 1599
1682static void ipv4_validate_peer(struct rtable *rt)
1683{
1684 if (rt->rt_peer_genid != rt_peer_genid()) {
1685 struct inet_peer *peer = rt_get_peer(rt, rt->rt_dst);
1686
1687 if (peer) {
1688 check_peer_pmtu(&rt->dst, peer);
1689
1690 if (peer->redirect_learned.a4 &&
1691 peer->redirect_learned.a4 != rt->rt_gateway)
1692 check_peer_redir(&rt->dst, peer);
1693 }
1694
1695 rt->rt_peer_genid = rt_peer_genid();
1696 }
1697}
1698
1699static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie) 1600static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie)
1700{ 1601{
1701 struct rtable *rt = (struct rtable *) dst; 1602 struct rtable *rt = (struct rtable *) dst;
1702 1603
1703 if (rt_is_expired(rt)) 1604 if (rt_is_expired(rt))
1704 return NULL; 1605 return NULL;
1705 ipv4_validate_peer(rt);
1706 return dst; 1606 return dst;
1707} 1607}
1708 1608
@@ -1728,11 +1628,8 @@ static void ipv4_link_failure(struct sk_buff *skb)
1728 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_UNREACH, 0); 1628 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_UNREACH, 0);
1729 1629
1730 rt = skb_rtable(skb); 1630 rt = skb_rtable(skb);
1731 if (rt && rt_has_peer(rt)) { 1631 if (rt)
1732 struct inet_peer *peer = rt_peer_ptr(rt); 1632 dst_set_expires(&rt->dst, 0);
1733 if (peer_pmtu_cleaned(peer))
1734 dst_metric_set(&rt->dst, RTAX_MTU, peer->pmtu_orig);
1735 }
1736} 1633}
1737 1634
1738static int ip_rt_bug(struct sk_buff *skb) 1635static int ip_rt_bug(struct sk_buff *skb)
@@ -1812,7 +1709,13 @@ static unsigned int ipv4_default_advmss(const struct dst_entry *dst)
1812static unsigned int ipv4_mtu(const struct dst_entry *dst) 1709static unsigned int ipv4_mtu(const struct dst_entry *dst)
1813{ 1710{
1814 const struct rtable *rt = (const struct rtable *) dst; 1711 const struct rtable *rt = (const struct rtable *) dst;
1815 unsigned int mtu = dst_metric_raw(dst, RTAX_MTU); 1712 unsigned int mtu = rt->rt_pmtu;
1713
1714 if (mtu && time_after_eq(jiffies, rt->dst.expires))
1715 mtu = 0;
1716
1717 if (!mtu)
1718 mtu = dst_metric_raw(dst, RTAX_MTU);
1816 1719
1817 if (mtu && rt_is_output_route(rt)) 1720 if (mtu && rt_is_output_route(rt))
1818 return mtu; 1721 return mtu;
@@ -1843,19 +1746,10 @@ static void rt_init_metrics(struct rtable *rt, const struct flowi4 *fl4,
1843 peer = inet_getpeer_v4(base, rt->rt_dst, 0); 1746 peer = inet_getpeer_v4(base, rt->rt_dst, 0);
1844 if (peer) { 1747 if (peer) {
1845 __rt_set_peer(rt, peer); 1748 __rt_set_peer(rt, peer);
1846 rt->rt_peer_genid = rt_peer_genid();
1847 if (inet_metrics_new(peer)) 1749 if (inet_metrics_new(peer))
1848 memcpy(peer->metrics, fi->fib_metrics, 1750 memcpy(peer->metrics, fi->fib_metrics,
1849 sizeof(u32) * RTAX_MAX); 1751 sizeof(u32) * RTAX_MAX);
1850 dst_init_metrics(&rt->dst, peer->metrics, false); 1752 dst_init_metrics(&rt->dst, peer->metrics, false);
1851
1852 check_peer_pmtu(&rt->dst, peer);
1853
1854 if (peer->redirect_learned.a4 &&
1855 peer->redirect_learned.a4 != rt->rt_gateway) {
1856 rt->rt_gateway = peer->redirect_learned.a4;
1857 rt->rt_flags |= RTCF_REDIRECTED;
1858 }
1859 } else { 1753 } else {
1860 if (fi->fib_metrics != (u32 *) dst_default_metrics) { 1754 if (fi->fib_metrics != (u32 *) dst_default_metrics) {
1861 rt->fi = fi; 1755 rt->fi = fi;
@@ -1955,8 +1849,8 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr,
1955 rth->rt_iif = dev->ifindex; 1849 rth->rt_iif = dev->ifindex;
1956 rth->rt_oif = 0; 1850 rth->rt_oif = 0;
1957 rth->rt_mark = skb->mark; 1851 rth->rt_mark = skb->mark;
1852 rth->rt_pmtu = 0;
1958 rth->rt_gateway = daddr; 1853 rth->rt_gateway = daddr;
1959 rth->rt_peer_genid = 0;
1960 rt_init_peer(rth, dev_net(dev)->ipv4.peers); 1854 rt_init_peer(rth, dev_net(dev)->ipv4.peers);
1961 rth->fi = NULL; 1855 rth->fi = NULL;
1962 if (our) { 1856 if (our) {
@@ -2081,8 +1975,8 @@ static int __mkroute_input(struct sk_buff *skb,
2081 rth->rt_iif = in_dev->dev->ifindex; 1975 rth->rt_iif = in_dev->dev->ifindex;
2082 rth->rt_oif = 0; 1976 rth->rt_oif = 0;
2083 rth->rt_mark = skb->mark; 1977 rth->rt_mark = skb->mark;
1978 rth->rt_pmtu = 0;
2084 rth->rt_gateway = daddr; 1979 rth->rt_gateway = daddr;
2085 rth->rt_peer_genid = 0;
2086 rt_init_peer(rth, &res->table->tb_peers); 1980 rt_init_peer(rth, &res->table->tb_peers);
2087 rth->fi = NULL; 1981 rth->fi = NULL;
2088 1982
@@ -2260,8 +2154,8 @@ local_input:
2260 rth->rt_iif = dev->ifindex; 2154 rth->rt_iif = dev->ifindex;
2261 rth->rt_oif = 0; 2155 rth->rt_oif = 0;
2262 rth->rt_mark = skb->mark; 2156 rth->rt_mark = skb->mark;
2157 rth->rt_pmtu = 0;
2263 rth->rt_gateway = daddr; 2158 rth->rt_gateway = daddr;
2264 rth->rt_peer_genid = 0;
2265 rt_init_peer(rth, net->ipv4.peers); 2159 rt_init_peer(rth, net->ipv4.peers);
2266 rth->fi = NULL; 2160 rth->fi = NULL;
2267 if (res.type == RTN_UNREACHABLE) { 2161 if (res.type == RTN_UNREACHABLE) {
@@ -2337,7 +2231,6 @@ int ip_route_input_common(struct sk_buff *skb, __be32 daddr, __be32 saddr,
2337 rth->rt_mark == skb->mark && 2231 rth->rt_mark == skb->mark &&
2338 net_eq(dev_net(rth->dst.dev), net) && 2232 net_eq(dev_net(rth->dst.dev), net) &&
2339 !rt_is_expired(rth)) { 2233 !rt_is_expired(rth)) {
2340 ipv4_validate_peer(rth);
2341 if (noref) { 2234 if (noref) {
2342 dst_use_noref(&rth->dst, jiffies); 2235 dst_use_noref(&rth->dst, jiffies);
2343 skb_dst_set_noref(skb, &rth->dst); 2236 skb_dst_set_noref(skb, &rth->dst);
@@ -2459,8 +2352,8 @@ static struct rtable *__mkroute_output(const struct fib_result *res,
2459 rth->rt_iif = orig_oif ? : dev_out->ifindex; 2352 rth->rt_iif = orig_oif ? : dev_out->ifindex;
2460 rth->rt_oif = orig_oif; 2353 rth->rt_oif = orig_oif;
2461 rth->rt_mark = fl4->flowi4_mark; 2354 rth->rt_mark = fl4->flowi4_mark;
2355 rth->rt_pmtu = 0;
2462 rth->rt_gateway = fl4->daddr; 2356 rth->rt_gateway = fl4->daddr;
2463 rth->rt_peer_genid = 0;
2464 rt_init_peer(rth, (res->table ? 2357 rt_init_peer(rth, (res->table ?
2465 &res->table->tb_peers : 2358 &res->table->tb_peers :
2466 dev_net(dev_out)->ipv4.peers)); 2359 dev_net(dev_out)->ipv4.peers));
@@ -2717,7 +2610,6 @@ struct rtable *__ip_route_output_key(struct net *net, struct flowi4 *flp4)
2717 (IPTOS_RT_MASK | RTO_ONLINK)) && 2610 (IPTOS_RT_MASK | RTO_ONLINK)) &&
2718 net_eq(dev_net(rth->dst.dev), net) && 2611 net_eq(dev_net(rth->dst.dev), net) &&
2719 !rt_is_expired(rth)) { 2612 !rt_is_expired(rth)) {
2720 ipv4_validate_peer(rth);
2721 dst_use(&rth->dst, jiffies); 2613 dst_use(&rth->dst, jiffies);
2722 RT_CACHE_STAT_INC(out_hit); 2614 RT_CACHE_STAT_INC(out_hit);
2723 rcu_read_unlock_bh(); 2615 rcu_read_unlock_bh();
@@ -2794,6 +2686,7 @@ struct dst_entry *ipv4_blackhole_route(struct net *net, struct dst_entry *dst_or
2794 rt->rt_iif = ort->rt_iif; 2686 rt->rt_iif = ort->rt_iif;
2795 rt->rt_oif = ort->rt_oif; 2687 rt->rt_oif = ort->rt_oif;
2796 rt->rt_mark = ort->rt_mark; 2688 rt->rt_mark = ort->rt_mark;
2689 rt->rt_pmtu = ort->rt_pmtu;
2797 2690
2798 rt->rt_genid = rt_genid(net); 2691 rt->rt_genid = rt_genid(net);
2799 rt->rt_flags = ort->rt_flags; 2692 rt->rt_flags = ort->rt_flags;
@@ -2896,13 +2789,13 @@ static int rt_fill_info(struct net *net,
2896 const struct inet_peer *peer = rt_peer_ptr(rt); 2789 const struct inet_peer *peer = rt_peer_ptr(rt);
2897 inet_peer_refcheck(peer); 2790 inet_peer_refcheck(peer);
2898 id = atomic_read(&peer->ip_id_count) & 0xffff; 2791 id = atomic_read(&peer->ip_id_count) & 0xffff;
2899 expires = ACCESS_ONCE(peer->pmtu_expires); 2792 }
2900 if (expires) { 2793 expires = rt->dst.expires;
2901 if (time_before(jiffies, expires)) 2794 if (expires) {
2902 expires -= jiffies; 2795 if (time_before(jiffies, expires))
2903 else 2796 expires -= jiffies;
2904 expires = 0; 2797 else
2905 } 2798 expires = 0;
2906 } 2799 }
2907 2800
2908 if (rt_is_input_route(rt)) { 2801 if (rt_is_input_route(rt)) {