tech-net archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: ICMP_UNREACH_NEEDFRAG returns iface MTU instead of route?



>> It seems that the ICMP fragmentation needed packet contains the
>> interface MTU rather than the route MTU if the route MTU is lower
>> than the iface's:

Yes.  I agree with Darren on this; see PR 44508, and my thread bringing
it up (right here on tech-net) on 2012-06-14.  Since neither of those
apparently did much, it's unlikely this thread will do much either.
But I didn't give patches before; this time I have them, at least for
the versions I run (4.0.1 and 5.2).

4.0.1's is

commit 4e8da79fceebe279dbf150348fb79dd20d10f9e2
Author: Mouse <mouse%Rodents-Montreal.ORG@localhost>
Date:   Fri Apr 1 21:44:21 2011 -0400

    Get "need to frag but DF set" MTU values righter.
    
    This affects the case where the route's MTU is lower than the
    interface's; it would formerly use the interface's MTU, which causes
    PMTU-D to loop, since the generated ICMPs contain a nonworking MTU.

diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c
index d088151..7724373 100644
--- a/sys/netinet/ip_input.c
+++ b/sys/netinet/ip_input.c
@@ -1843,6 +1843,7 @@ ip_forward(struct mbuf *m, int srcrt)
        int error, type = 0, code = 0, destmtu = 0;
        struct mbuf *mcopy;
        n_long dest;
+       int rmtu;
 
        /*
         * We are now in the output path.
@@ -1934,9 +1935,10 @@ ip_forward(struct mbuf *m, int srcrt)
                }
        }
 
+       rmtu = 0;
        error = ip_output(m, (struct mbuf *)0, &ipforward_rt,
-           (IP_FORWARDING | (ip_directedbcast ? IP_ALLOWBROADCAST : 0)),
-           (struct ip_moptions *)NULL, (struct socket *)NULL);
+           (IP_FORWARDING | IP_RETURNMTU | (ip_directedbcast ? 
IP_ALLOWBROADCAST : 0)),
+           (struct ip_moptions *)NULL, (struct socket *)NULL, &rmtu);
 
        if (error)
                ipstat.ips_cantforward++;
@@ -1997,7 +1999,7 @@ ip_forward(struct mbuf *m, int srcrt)
                            &ipsecerror);
 #endif
 
-                       destmtu = ipforward_rt.ro_rt->rt_ifp->if_mtu;
+                       destmtu = rmtu ? : ipforward_rt.ro_rt->rt_ifp->if_mtu;
 #if defined(IPSEC) || defined(FAST_IPSEC)
                        if (sp != NULL) {
                                /* count IPsec header size */

5.2's is

commit d7138d8a1fa119cbc83621176524e81bfcacb5ba
Author: Mouse <mouse%Rodents-Montreal.ORG@localhost>
Date:   Fri Feb 15 18:52:37 2013 -0500

    Get "need to frag but DF set" MTU values righter.

diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c
index 8cd094d..f1920cb 100644
--- a/sys/netinet/ip_input.c
+++ b/sys/netinet/ip_input.c
@@ -1847,6 +1847,7 @@ ip_forward(struct mbuf *m, int srcrt)
                struct sockaddr         dst;
                struct sockaddr_in      dst4;
        } u;
+       int rmtu;
 
        /*
         * We are now in the output path.
@@ -1926,8 +1927,8 @@ ip_forward(struct mbuf *m, int srcrt)
        }
 
        error = ip_output(m, NULL, &ipforward_rt,
-           (IP_FORWARDING | (ip_directedbcast ? IP_ALLOWBROADCAST : 0)),
-           (struct ip_moptions *)NULL, (struct socket *)NULL);
+           (IP_FORWARDING | IP_RETURNMTU | (ip_directedbcast ? 
IP_ALLOWBROADCAST : 0)),
+           (struct ip_moptions *)NULL, (struct socket *)NULL, &rmtu);
 
        if (error)
                IP_STATINC(IP_STAT_CANTFORWARD);
@@ -1974,6 +1975,8 @@ ip_forward(struct mbuf *m, int srcrt)
                if ((rt = rtcache_validate(&ipforward_rt)) != NULL)
                        destmtu = rt->rt_ifp->if_mtu;
 
+               if (rmtu && (rmtu < destmtu)) destmtu = rmtu;
+
 #if defined(IPSEC) || defined(FAST_IPSEC)
                {
                        /*

/~\ The ASCII                             Mouse
\ / Ribbon Campaign
 X  Against HTML                mouse%rodents-montreal.org@localhost
/ \ Email!           7D C8 61 52 5D E7 2D 39  4E F1 31 3E E8 B3 27 4B


Home | Main Index | Thread Index | Old Index