summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjmg <jmg@FreeBSD.org>2006-09-10 17:49:09 +0000
committerjmg <jmg@FreeBSD.org>2006-09-10 17:49:09 +0000
commit6d7956e8013d8b162ecdc4f497aaf69b78b5e0e8 (patch)
treec27448a8a45ff7e63f731d2586f8c33c39389868
parent7478fd14ea33dc911d3612482f28bcbfab27e461 (diff)
downloadFreeBSD-src-6d7956e8013d8b162ecdc4f497aaf69b78b5e0e8.zip
FreeBSD-src-6d7956e8013d8b162ecdc4f497aaf69b78b5e0e8.tar.gz
make use of the host route's mtu for processing. This means we can now
support a network w/ split mtu's by assigning each host route the correct mtu. an aspiring programmer could write a daemon to probe hosts and find out if they support a larger mtu.
-rw-r--r--sys/netinet/ip_output.c43
1 files changed, 25 insertions, 18 deletions
diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c
index 8311732..f37c993 100644
--- a/sys/netinet/ip_output.c
+++ b/sys/netinet/ip_output.c
@@ -112,6 +112,7 @@ ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro,
struct ifnet *ifp = NULL; /* keep compiler happy */
struct mbuf *m0;
int hlen = sizeof (struct ip);
+ int mtu;
int len, error = 0;
struct sockaddr_in *dst = NULL; /* keep compiler happy */
struct in_ifaddr *ia = NULL;
@@ -172,7 +173,7 @@ again:
dst->sin_family != AF_INET ||
dst->sin_addr.s_addr != ip->ip_dst.s_addr)) {
RTFREE(ro->ro_rt);
- ro->ro_rt = (struct rtentry *)0;
+ ro->ro_rt = (struct rtentry *)NULL;
}
#ifdef IPFIREWALL_FORWARD
if (ro->ro_rt == NULL && fwd_tag == NULL) {
@@ -241,6 +242,24 @@ again:
else
isbroadcast = in_broadcast(dst->sin_addr, ifp);
}
+ /*
+ * Calculate MTU. If we have a route that is up, use that,
+ * otherwise use the interface's MTU.
+ */
+ if (ro->ro_rt->rt_flags & (RTF_UP | RTF_HOST)) {
+ /*
+ * This case can happen if the user changed the MTU
+ * of an interface after enabling IP on it. Because
+ * most netifs don't keep track of routes pointing to
+ * them, there is no way for one to update all its
+ * routes when the MTU is changed.
+ */
+ if (ro->ro_rt->rt_rmx.rmx_mtu > ifp->if_mtu)
+ ro->ro_rt->rt_rmx.rmx_mtu = ifp->if_mtu;
+ mtu = ro->ro_rt->rt_rmx.rmx_mtu;
+ } else {
+ mtu = ifp->if_mtu;
+ }
if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr))) {
struct in_multi *inm;
@@ -360,10 +379,10 @@ again:
*/
#ifdef ALTQ
if ((!ALTQ_IS_ENABLED(&ifp->if_snd)) &&
- ((ifp->if_snd.ifq_len + ip->ip_len / ifp->if_mtu + 1) >=
+ ((ifp->if_snd.ifq_len + ip->ip_len / mtu + 1) >=
ifp->if_snd.ifq_maxlen))
#else
- if ((ifp->if_snd.ifq_len + ip->ip_len / ifp->if_mtu + 1) >=
+ if ((ifp->if_snd.ifq_len + ip->ip_len / mtu + 1) >=
ifp->if_snd.ifq_maxlen)
#endif /* ALTQ */
{
@@ -388,7 +407,7 @@ again:
goto bad;
}
/* don't allow broadcast messages to be fragmented */
- if (ip->ip_len > ifp->if_mtu) {
+ if (ip->ip_len > mtu) {
error = EMSGSIZE;
goto bad;
}
@@ -497,7 +516,7 @@ passout:
* If small enough for interface, or the interface will take
* care of the fragmentation for us, we can just send directly.
*/
- if (ip->ip_len <= ifp->if_mtu ||
+ if (ip->ip_len <= mtu ||
(m->m_pkthdr.csum_flags & ifp->if_hwassist & CSUM_TSO) != 0 ||
((ip->ip_off & IP_DF) == 0 && (ifp->if_hwassist & CSUM_FRAGMENT))) {
ip->ip_len = htons(ip->ip_len);
@@ -542,18 +561,6 @@ passout:
/* Balk when DF bit is set or the interface didn't support TSO. */
if ((ip->ip_off & IP_DF) || (m->m_pkthdr.csum_flags & CSUM_TSO)) {
error = EMSGSIZE;
- /*
- * This case can happen if the user changed the MTU
- * of an interface after enabling IP on it. Because
- * most netifs don't keep track of routes pointing to
- * them, there is no way for one to update all its
- * routes when the MTU is changed.
- */
- if (ro != NULL &&
- (ro->ro_rt->rt_flags & (RTF_UP | RTF_HOST)) &&
- (ro->ro_rt->rt_rmx.rmx_mtu > ifp->if_mtu)) {
- ro->ro_rt->rt_rmx.rmx_mtu = ifp->if_mtu;
- }
ipstat.ips_cantfrag++;
goto bad;
}
@@ -562,7 +569,7 @@ passout:
* Too large for interface; fragment if possible. If successful,
* on return, m will point to a list of packets to be sent.
*/
- error = ip_fragment(ip, &m, ifp->if_mtu, ifp->if_hwassist, sw_csum);
+ error = ip_fragment(ip, &m, mtu, ifp->if_hwassist, sw_csum);
if (error)
goto bad;
for (; m; m = m0) {
OpenPOWER on IntegriCloud