route.c (96916090f488986a4ebb8e9ffa6a3b50881d5ccd) route.c (0bbeafd0118fc3ae54990064760c889d41dc21d6)
1/*
2 * INET An implementation of the TCP/IP protocol suite for the LINUX
3 * operating system. INET is implemented using the BSD Socket
4 * interface as the means of communication with the user level.
5 *
6 * ROUTE - implementation of the IP router.
7 *
8 * Version: $Id: route.c,v 1.103 2002/01/12 07:44:09 davem Exp $

--- 1416 unchanged lines hidden (view full) ---

1425
1426 for (i = 0; i < ARRAY_SIZE(mtu_plateau); i++)
1427 if (old_mtu > mtu_plateau[i])
1428 return mtu_plateau[i];
1429 return 68;
1430}
1431
1432unsigned short ip_rt_frag_needed(struct net *net, struct iphdr *iph,
1/*
2 * INET An implementation of the TCP/IP protocol suite for the LINUX
3 * operating system. INET is implemented using the BSD Socket
4 * interface as the means of communication with the user level.
5 *
6 * ROUTE - implementation of the IP router.
7 *
8 * Version: $Id: route.c,v 1.103 2002/01/12 07:44:09 davem Exp $

--- 1416 unchanged lines hidden (view full) ---

1425
1426 for (i = 0; i < ARRAY_SIZE(mtu_plateau); i++)
1427 if (old_mtu > mtu_plateau[i])
1428 return mtu_plateau[i];
1429 return 68;
1430}
1431
1432unsigned short ip_rt_frag_needed(struct net *net, struct iphdr *iph,
1433 unsigned short new_mtu)
1433 unsigned short new_mtu,
1434 struct net_device *dev)
1434{
1435{
1435 int i;
1436 int i, k;
1436 unsigned short old_mtu = ntohs(iph->tot_len);
1437 struct rtable *rth;
1437 unsigned short old_mtu = ntohs(iph->tot_len);
1438 struct rtable *rth;
1439 int ikeys[2] = { dev->ifindex, 0 };
1438 __be32 skeys[2] = { iph->saddr, 0, };
1439 __be32 daddr = iph->daddr;
1440 unsigned short est_mtu = 0;
1441
1442 if (ipv4_config.no_pmtu_disc)
1443 return 0;
1444
1440 __be32 skeys[2] = { iph->saddr, 0, };
1441 __be32 daddr = iph->daddr;
1442 unsigned short est_mtu = 0;
1443
1444 if (ipv4_config.no_pmtu_disc)
1445 return 0;
1446
1445 for (i = 0; i < 2; i++) {
1446 unsigned hash = rt_hash(daddr, skeys[i], 0);
1447 for (k = 0; k < 2; k++) {
1448 for (i = 0; i < 2; i++) {
1449 unsigned hash = rt_hash(daddr, skeys[i], ikeys[k]);
1447
1450
1448 rcu_read_lock();
1449 for (rth = rcu_dereference(rt_hash_table[hash].chain); rth;
1450 rth = rcu_dereference(rth->u.dst.rt_next)) {
1451 if (rth->fl.fl4_dst == daddr &&
1452 rth->fl.fl4_src == skeys[i] &&
1453 rth->rt_dst == daddr &&
1454 rth->rt_src == iph->saddr &&
1455 rth->fl.iif == 0 &&
1456 !(dst_metric_locked(&rth->u.dst, RTAX_MTU)) &&
1457 net_eq(dev_net(rth->u.dst.dev), net) &&
1458 rth->rt_genid == atomic_read(&rt_genid)) {
1451 rcu_read_lock();
1452 for (rth = rcu_dereference(rt_hash_table[hash].chain); rth;
1453 rth = rcu_dereference(rth->u.dst.rt_next)) {
1459 unsigned short mtu = new_mtu;
1460
1454 unsigned short mtu = new_mtu;
1455
1456 if (rth->fl.fl4_dst != daddr ||
1457 rth->fl.fl4_src != skeys[i] ||
1458 rth->rt_dst != daddr ||
1459 rth->rt_src != iph->saddr ||
1460 rth->fl.oif != ikeys[k] ||
1461 rth->fl.iif != 0 ||
1462 dst_metric_locked(&rth->u.dst, RTAX_MTU) ||
1463 !net_eq(dev_net(rth->u.dst.dev), net) ||
1464 rth->rt_genid != atomic_read(&rt_genid))
1465 continue;
1466
1461 if (new_mtu < 68 || new_mtu >= old_mtu) {
1462
1463 /* BSD 4.2 compatibility hack :-( */
1464 if (mtu == 0 &&
1465 old_mtu >= rth->u.dst.metrics[RTAX_MTU-1] &&
1466 old_mtu >= 68 + (iph->ihl << 2))
1467 old_mtu -= iph->ihl << 2;
1468

--- 9 unchanged lines hidden (view full) ---

1478 }
1479 rth->u.dst.metrics[RTAX_MTU-1] = mtu;
1480 dst_set_expires(&rth->u.dst,
1481 ip_rt_mtu_expires);
1482 }
1483 est_mtu = mtu;
1484 }
1485 }
1467 if (new_mtu < 68 || new_mtu >= old_mtu) {
1468
1469 /* BSD 4.2 compatibility hack :-( */
1470 if (mtu == 0 &&
1471 old_mtu >= rth->u.dst.metrics[RTAX_MTU-1] &&
1472 old_mtu >= 68 + (iph->ihl << 2))
1473 old_mtu -= iph->ihl << 2;
1474

--- 9 unchanged lines hidden (view full) ---

1484 }
1485 rth->u.dst.metrics[RTAX_MTU-1] = mtu;
1486 dst_set_expires(&rth->u.dst,
1487 ip_rt_mtu_expires);
1488 }
1489 est_mtu = mtu;
1490 }
1491 }
1492 rcu_read_unlock();
1486 }
1493 }
1487 rcu_read_unlock();
1488 }
1489 return est_mtu ? : new_mtu;
1490}
1491
1492static void ip_rt_update_pmtu(struct dst_entry *dst, u32 mtu)
1493{
1494 if (dst->metrics[RTAX_MTU-1] > mtu && mtu >= 68 &&
1495 !(dst_metric_locked(dst, RTAX_MTU))) {

--- 106 unchanged lines hidden (view full) ---

1602 if (fi) {
1603 if (FIB_RES_GW(*res) &&
1604 FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK)
1605 rt->rt_gateway = FIB_RES_GW(*res);
1606 memcpy(rt->u.dst.metrics, fi->fib_metrics,
1607 sizeof(rt->u.dst.metrics));
1608 if (fi->fib_mtu == 0) {
1609 rt->u.dst.metrics[RTAX_MTU-1] = rt->u.dst.dev->mtu;
1494 }
1495 return est_mtu ? : new_mtu;
1496}
1497
1498static void ip_rt_update_pmtu(struct dst_entry *dst, u32 mtu)
1499{
1500 if (dst->metrics[RTAX_MTU-1] > mtu && mtu >= 68 &&
1501 !(dst_metric_locked(dst, RTAX_MTU))) {

--- 106 unchanged lines hidden (view full) ---

1608 if (fi) {
1609 if (FIB_RES_GW(*res) &&
1610 FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK)
1611 rt->rt_gateway = FIB_RES_GW(*res);
1612 memcpy(rt->u.dst.metrics, fi->fib_metrics,
1613 sizeof(rt->u.dst.metrics));
1614 if (fi->fib_mtu == 0) {
1615 rt->u.dst.metrics[RTAX_MTU-1] = rt->u.dst.dev->mtu;
1610 if (rt->u.dst.metrics[RTAX_LOCK-1] & (1 << RTAX_MTU) &&
1616 if (dst_metric_locked(&rt->u.dst, RTAX_MTU) &&
1611 rt->rt_gateway != rt->rt_dst &&
1612 rt->u.dst.dev->mtu > 576)
1613 rt->u.dst.metrics[RTAX_MTU-1] = 576;
1614 }
1615#ifdef CONFIG_NET_CLS_ROUTE
1616 rt->u.dst.tclassid = FIB_RES_NH(*res).nh_tclassid;
1617#endif
1618 } else

--- 1471 unchanged lines hidden ---
1617 rt->rt_gateway != rt->rt_dst &&
1618 rt->u.dst.dev->mtu > 576)
1619 rt->u.dst.metrics[RTAX_MTU-1] = 576;
1620 }
1621#ifdef CONFIG_NET_CLS_ROUTE
1622 rt->u.dst.tclassid = FIB_RES_NH(*res).nh_tclassid;
1623#endif
1624 } else

--- 1471 unchanged lines hidden ---