Hello,
Reading the ip tunnel code, i have seen that the max mtu was 0xfff8
instead of 0xffff (in ipip.c/ip_gre.c/sit.c). If it is a bug, the
following patch fix it. At the same time, i did some beautifications
replacing some 68 by IP_MIN_MTU.
--- linux-2.3.99-pre3/include/linux/ip.h Sat Mar 18 15:11:22 2000
+++ linux-2.3.99-pre3_patch/include/linux/ip.h Mon Apr 3 01:45:18 2000
@@ -67,6 +67,9 @@
#define MAXTTL 255
#define IPDEFTTL 64
+#define IP_MIN_MTU 68 /* rfc791.fragmentation */
+#define IP_MAX_MTU 0xFFFF /* rfc791.3.1.total_length */
+
/* struct timestamp, struct route and MAX_ROUTES are removed.
REASONS: it is clear that nobody used them because:
--- linux-2.3.99-pre3/net/ipv4/ip_gre.c Fri Mar 17 13:56:20 2000
+++ linux-2.3.99-pre3_patch/net/ipv4/ip_gre.c Mon Apr 3 01:48:03 2000
@@ -91,7 +91,7 @@
that is ALL. :-) Well, it does not remove the problem completely,
but exponential growth of network traffic is changed to linear
(branches, that exceed pmtu are pruned) and tunnel mtu
- fastly degrades to value <68, where looping stops.
+ fastly degrades to value <68 (IP_MIN_MTU), where looping stops.
Yes, it is not good if there exists a router in the loop,
which does not force DF, even when encapsulating packets have DF set.
But it is not our problem! Nobody could accuse us, we made
@@ -450,7 +450,7 @@
case ICMP_FRAG_NEEDED:
/* And it is the only really necesary thing :-) */
rel_info = ntohs(skb->h.icmph->un.frag.mtu);
- if (rel_info < grehlen+68)
+ if (rel_info < grehlen+IP_MIN_MTU)
return;
rel_info -= grehlen;
/* BSD 4.2 MORE DOES NOT EXIST IN NATURE. */
@@ -708,7 +708,7 @@
mtu = rt->u.dst.pmtu - tunnel->hlen;
if (skb->protocol == __constant_htons(ETH_P_IP)) {
- if (skb->dst && mtu < skb->dst->pmtu && mtu >= 68)
+ if (skb->dst && mtu < skb->dst->pmtu && mtu >= IP_MIN_MTU)
skb->dst->pmtu = mtu;
df |= (old_iph->frag_off&__constant_htons(IP_DF));
@@ -976,7 +976,7 @@
static int ipgre_tunnel_change_mtu(struct net_device *dev, int new_mtu)
{
struct ip_tunnel *tunnel = (struct ip_tunnel*)dev->priv;
- if (new_mtu < 68 || new_mtu > 0xFFF8 - tunnel->hlen)
+ if (new_mtu < IP_MIN_MTU || new_mtu > IP_MAX_MTU - tunnel->hlen)
return -EINVAL;
dev->mtu = new_mtu;
return 0;
--- linux-2.3.99-pre3/net/ipv4/ipip.c Mon Apr 3 01:52:40 2000
+++ linux-2.3.99-pre3_patch/net/ipv4/ipip.c Mon Apr 3 01:46:59 2000
@@ -384,7 +384,7 @@
case ICMP_FRAG_NEEDED:
/* And it is the only really necesary thing :-) */
rel_info = ntohs(skb->h.icmph->un.frag.mtu);
- if (rel_info < hlen+68)
+ if (rel_info < hlen+IP_MIN_MTU)
return;
rel_info -= hlen;
/* BSD 4.2 MORE DOES NOT EXIST IN NATURE. */
@@ -553,7 +553,7 @@
}
mtu = rt->u.dst.pmtu - sizeof(struct iphdr);
- if (mtu < 68) {
+ if (mtu < IP_MIN_MTU) {
tunnel->stat.collisions++;
ip_rt_put(rt);
goto tx_error;
@@ -761,7 +761,7 @@
static int ipip_tunnel_change_mtu(struct net_device *dev, int new_mtu)
{
- if (new_mtu < 68 || new_mtu > 0xFFF8 - sizeof(struct iphdr))
+ if (new_mtu < IP_MIN_MTU || new_mtu > IP_MAX_MTU - sizeof(struct iphdr))
return -EINVAL;
dev->mtu = new_mtu;
return 0;
--- linux-2.3.99-pre3/net/ipv6/sit.c Mon Apr 3 01:52:40 2000
+++ linux-2.3.99-pre3_patch/net/ipv6/sit.c Mon Apr 3 01:49:02 2000
@@ -471,7 +471,7 @@
}
mtu = rt->u.dst.pmtu - sizeof(struct iphdr);
- if (mtu < 68) {
+ if (mtu < IP_MIN_MTU) {
tunnel->stat.collisions++;
ip_rt_put(rt);
goto tx_error;
@@ -689,7 +689,7 @@
static int ipip6_tunnel_change_mtu(struct net_device *dev, int new_mtu)
{
- if (new_mtu < IPV6_MIN_MTU || new_mtu > 0xFFF8 - sizeof(struct iphdr))
+ if (new_mtu < IPV6_MIN_MTU || new_mtu > IP_MAX_MTU-sizeof(struct iphdr))
return -EINVAL;
dev->mtu = new_mtu;
return 0;
|