Skip site navigation (1)Skip section navigation (2)
Date:      02 Apr 2003 11:31:02 -0600
From:      Craig Boston <craig@xfoil.gank.org>
To:        freebsd-current@freebsd.org
Subject:   IPv6 MTU bug?
Message-ID:  <1049304662.10796.27.camel@owen1492.uf.corelab.com>

next in thread | raw e-mail | index | archive | help
I was trying some network diagnostics yesterday and needed to generate a
continuous stream of small packets going across a few routers.  So I
used ifconfig to set my MTU to some very low values (100, 300, 500, and
a few others).  I know there's probably a better way to accomplish that,
but couldn't think of any at the time so that's what I did :)

Anyway, when I was done, I reset the MTU on my ethernet interface back
to 1500.  IPv4 is working fine, but IPv6 is still acting like I have a
low MTU set.  All IPv6 TCP connections are limiting the MSS to around 28
bytes of data per packet, and ping6 complains with ping sizes more than
around 50.

I think I've tracked down the problem to this code in nd6.c,
specifically in nd6_setmtu(ifp).

Note that at this point ndi->maxmtu has just been set to
MIN([user-requested MTU], [biggest MTU possible for this interface
type]).  ndi->linkmtu hasn't been touched yet and is still set to
whatever the previous linkmtu was.

if (ndi->linkmtu == 0 ||
    ndi->maxmtu < ndi->linkmtu) {
        ndi->linkmtu = ndi->maxmtu;
        /* also adjust in6_maxmtu if necessary. */
        if (oldlinkmtu == 0) {
            /*
             * XXX: the case analysis is grotty, but
             * it is not efficient to call in6_setmaxmtu()
             * here when we are during the initialization
             * procedure.
             */
            if (in6_maxmtu < ndi->linkmtu)
                    in6_maxmtu = ndi->linkmtu;
        } else
                in6_setmaxmtu();
}

It looks to me that in the case of raising an interface's MTU,
ndi->maxmtu will be >= ndi->linkmtu, causing linkmtu to never get
reset.  I may be missing something, but I can't quite figure out the
logical reason for that test.

Luckily I had a kernel.debug lying around so I used gdb to peek into the
kernel memory.  In the nd_ifinfo for that interface, linkmtu=100 and
maxmtu=1500.  Once I manually reset linkmtu to 1500, IPv6 started
working properly again, without having to sacrifice my uptime :)

Anyway, the behavior looks like a bug, but the code makes it look like
this may be an intentional effect.  Any kernel networking gurus care to
comment?

Thanks,
Craig



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?1049304662.10796.27.camel>