From duwde@isec.com.br Mon Feb 17 05:13:08 2003 Return-Path: Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 3FEEA37B401 for ; Mon, 17 Feb 2003 05:13:08 -0800 (PST) Received: from bsd.masp.srv.br (bsd.masp.srv.br [200.223.149.86]) by mx1.FreeBSD.org (Postfix) with SMTP id 3900643F75 for ; Mon, 17 Feb 2003 05:13:06 -0800 (PST) (envelope-from duwde@isec.com.br) Received: (qmail 61295 invoked from network); 17 Feb 2003 13:21:11 -0000 Received: from unknown (HELO astral.home.isec.com.br) (200.164.0.100) by bsd.masp.srv.br with SMTP; 17 Feb 2003 13:21:11 -0000 Received: (from duwde@localhost) by astral.home.isec.com.br (8.12.6/8.12.6/Submit) id h1HDEtvN001044; Mon, 17 Feb 2003 10:14:55 -0300 (BRT) (envelope-from duwde) Message-Id: <200302171314.h1HDEtvN001044@astral.home.isec.com.br> Date: Mon, 17 Feb 2003 10:14:55 -0300 (BRT) From: Fabio Vilan Dias Reply-To: Fabio Vilan Dias To: FreeBSD-gnats-submit@freebsd.org Cc: Subject: [PATCH] User-PPP MTU/MRU - LCP Problem X-Send-Pr-Version: 3.113 X-GNATS-Notify: >Number: 48378 >Category: bin >Synopsis: [PATCH] User-PPP MTU/MRU - LCP Problem >Confidential: no >Severity: serious >Priority: medium >Responsible: brian >State: closed >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Mon Feb 17 05:20:06 PST 2003 >Closed-Date: Tue Jun 29 14:20:38 GMT 2004 >Last-Modified: Tue Jun 29 14:20:38 GMT 2004 >Originator: Fabio Vilan Dias >Release: FreeBSD 4.7-STABLE i386 >Organization: ISec.com.br >Environment: System: FreeBSD astral.home.isec.com.br 4.7-STABLE FreeBSD 4.7-STABLE #0: Mon Feb 10 02:03:52 BRST 2003 root@astral.home.isec.com.br:/usr/obj/usr/src/sys/ASTRAL i386 >Description: There is a very specific bug in user-ppp LCP negotiation that if the peer NAKs and REJs our requested MRU and if it doesn't ask for any specific MRU, the standard compiled default MRU (1500) is assigned to the peer mru (variable lcp->his_mru in lcp.c), but if we're using PPPoE, for example, the his_mru will never be updated to the new 1492 value, so the tun0 MTU will be incorrectly set to 1500 instead of 1492. Even setting "set mru max 1492" and "set mtu max 1492" won't fix the problem and you'll end up with a tun0 mtu of 1500. You can see a ppp.log of this problem here: http://www.isec.com.br/ppp-lcp-bug/ppp-broken-mtu-1500.log >How-To-Repeat: Just try to simulate a LCP negotiation only NAKing and REJing the peer MRU request, and don't ask for any specific MRU value. Or you can follow the source code in lcp.c and see that when this behavior exists, the variable lcp->his_mru will be wrong if you have PPPoE (or use the "set mru max" and/or "set mtu max" command) because it's supposed to be updated when : a) you ack a peer req, b) you nak a peer req, c) your peer ack your req. But those things may not happen at all if the peer NAKs an REJk only, and if it doesn't ask for any MRU at all. >Fix: Here's a simple patch that checks if the lcp->his_mru is less than the mru after a MRU Reject, if so, we update the lcp->his_mru because it'll be used to set the tun0 MTU in bundle.c, so it MUST be updated to the proper value. Remember, again, that this bug will only happen if the peer only NAK, REJ and doesn't ask for any MRU from us... if it does, there's already some code that will update the lcp->his_mru to the proper value and the bug won't happen. Anyway this MUST be fixed. *** lcp.c.orig Mon Jan 6 15:51:17 2003 --- lcp.c Mon Feb 17 08:35:47 2003 *************** *** 786,791 **** --- 786,795 ---- lcp->want_mru = mru; break; case MODE_REJ: + /* Fabio Vilan: Fix his_mru if the peer has never ACK or REQ any MRU */ + if (lcp->his_mru > mru) + lcp->his_mru = mru; + lcp->his_reject |= (1 << opt->hdr.id); break; } >Release-Note: >Audit-Trail: Responsible-Changed-From-To: freebsd-bugs->brian Responsible-Changed-By: johan Responsible-Changed-When: Sat Feb 22 03:24:16 PST 2003 Responsible-Changed-Why: Over to ppp maintainer. http://www.freebsd.org/cgi/query-pr.cgi?pr=48378 From: Archie Cobbs To: Fabio Vilan Cc: freebsd-gnats-submit@FreeBSD.org Subject: Re: bin/48378: [PATCH] User-PPP MTU/MRU - LCP Problem Date: Wed, 23 Apr 2003 17:30:01 -0700 (PDT) Fabio Vilan wrote: > It's PR #48378 > http://www.freebsd.org/cgi/query-pr.cgi?pr=48378 Fabio, I looked at your bug and have some questions. First, the local MRU and the peer MRU are negotiated separately and are completely independent variables. When the local side receives a config-nak or config-rej, the MRU being referred to is the local MRU, not the peer's MRU. So changing 'lcp->his_anything' in response to a config-nak or config-rej makes no sense. On the other hand, the peer is implicitly asking for his MRU to be 1500, because the MRU is omitted from his config-req, and we accept that with a config-ack. To get what you want to happen, we should be config-nak'ing the peer's config-request with an MRU of 1492 or whatever. Moreover, there is a larger issue here. Nothing ever stops a PPP device from imposing its own, smaller MTU than the peer's requested MRU; i.e., "MRU" means "you can send me frames *no bigger* than this". If ppp is incapable of sending 1500 byte frames down a PPPoE link, then it should know that implicitly and self-impose a lower limit of 1492 (this is of course link-dependent). So ppp should just accept the peer's MRU of 1500 and secretly change that to 1492 if it needs to. Not sure what the right patch for this would be, but it probably is more complicated. Cheers, -Archie P.S. Have you tried MPD? It behaves differently (not necessarily better) __________________________________________________________________________ Archie Cobbs * Precision I/O * http://www.precisionio.com From: "Yuriy N. Shkandybin" To: , Cc: Subject: Re: bin/48378: [PATCH] User-PPP MTU/MRU - LCP Problem Date: Mon, 28 Jul 2003 13:20:59 +0400 This is a multi-part message in MIME format. ------=_NextPart_000_00A8_01C3550B.15B831E0 Content-Type: text/plain; charset="koi8-r" Content-Transfer-Encoding: quoted-printable Hello. Let in ppp.conf there is=20 set mtu max 1476=20 set mtu 1476. When exchanging MRU information, in certain cases client doesn't send REQ, NAK or even REJ It's send NOP or ACK and thus lcp->his_mru can't be set and mtu(=3D1500) = will be incorrect and mssfixup won't work. I've tested this with pppd 2.3.5(FreeBSD) and pppd 2.4.1(Debian) Both was sending only ACK and NOP. When i've tried same with ppp, it sends REQ's, so it's ok. As solution to handle such cases might be setting default switch in case = TY_MRU: default: maxmtu =3D p ? physical_DeviceMTU(p) : 0; if (lcp->cfg.max_mtu && (!maxmtu || maxmtu > lcp->cfg.max_mtu)) maxmtu =3D lcp->cfg.max_mtu; wantmtu =3D lcp->cfg.mtu; if (maxmtu && wantmtu > maxmtu) { log_Printf(LogWARN, "%s: Reducing configured MTU from %u to = %u\n", fp->link->name, wantmtu, maxmtu); wantmtu =3D maxmtu; } if (maxmtu && mru > maxmtu) lcp->his_mru =3D maxmtu; else if (wantmtu && mru < wantmtu) { /* Push him up to MTU or MIN_MRU */ lcp->his_mru =3D wantmtu; } else lcp->his_mru =3D mru; break; Jura P.S. MPD can't mssfixup! ------=_NextPart_000_00A8_01C3550B.15B831E0 Content-Type: text/html; charset="koi8-r" Content-Transfer-Encoding: quoted-printable
Hello.
Let in ppp.conf there is
set mtu max 1476
set mtu 1476.
When exchanging MRU = information,
in certain cases client doesn't send = REQ, NAK or=20 even REJ
It's send NOP or ACK and thus = lcp->his_mru can't be set and mtu(=3D1500) will be incorrect = and=20 mssfixup won't work.
 
I've tested this with pppd 2.3.5(FreeBSD) and = pppd=20 2.4.1(Debian)
Both was sending only ACK and = NOP.
When i've tried same with ppp, it sends REQ's, = so it's=20 ok.
 
As solution to handle such cases might be = setting=20 default switch in case TY_MRU:
     =20 default:
        maxmtu =3D p ?=20 physical_DeviceMTU(p) : 0;
        = if=20 (lcp->cfg.max_mtu && (!maxmtu || maxmtu >=20 lcp->cfg.max_mtu))
        =  =20 maxmtu =3D = lcp->cfg.max_mtu;
       =20 wantmtu =3D = lcp->cfg.mtu;
        if=20 (maxmtu && wantmtu > maxmtu)=20 {
          = log_Printf(LogWARN,=20 "%s: Reducing configured MTU from %u to=20 %u\n",
          &nb= sp;         =20 fp->link->name, wantmtu,=20 maxmtu);
          = wantmtu =3D=20 maxmtu;
        }
 
        if=20 (maxmtu && mru >=20 maxmtu)
         =20 lcp->his_mru =3D = maxmtu;
        else if=20 (wantmtu && mru < wantmtu)=20 {
          /* Push him = up to=20 MTU or MIN_MRU = */
         =20 lcp->his_mru =3D = wantmtu;
        }=20 else
          = lcp->his_mru =3D=20 mru;
        break;
 
Jura
 
P.S. MPD can't mssfixup!
 
------=_NextPart_000_00A8_01C3550B.15B831E0-- From: "Yuriy N. Shkandybin" To: Cc: Subject: Re: bin/48378: [PATCH] User-PPP MTU/MRU - LCP Problem Date: Mon, 28 Jul 2003 16:44:43 +0400 This is a multi-part message in MIME format. ------=_NextPart_000_010F_01C35527.8BA22250 Content-Type: text/plain; charset="koi8-r" Content-Transfer-Encoding: quoted-printable Hello. Let in ppp.conf there is=20 set mtu max 1476=20 set mtu 1476. When exchanging MRU information, in certain cases client doesn't send REQ, NAK or even REJ It's send NOP or ACK and thus lcp->his_mru can't be set and mtu(=3D1500) = will be incorrect and mssfixup won't work. I've tested this with pppd 2.3.5(FreeBSD) and pppd 2.4.1(Debian) Both was sending only ACK and NOP. When i've tried same with ppp, it sends REQ's, so it's ok. As solution to handle such cases might be setting default switch in case = TY_MRU: default: maxmtu =3D p ? physical_DeviceMTU(p) : 0; if (lcp->cfg.max_mtu && (!maxmtu || maxmtu > lcp->cfg.max_mtu)) maxmtu =3D lcp->cfg.max_mtu; wantmtu =3D lcp->cfg.mtu; if (maxmtu && wantmtu > maxmtu) { log_Printf(LogWARN, "%s: Reducing configured MTU from %u to = %u\n", fp->link->name, wantmtu, maxmtu); wantmtu =3D maxmtu; } if (maxmtu && mru > maxmtu) lcp->his_mru =3D maxmtu; else if (wantmtu && mru < wantmtu) { /* Push him up to MTU or MIN_MRU */ lcp->his_mru =3D wantmtu; } else lcp->his_mru =3D mru; break; Jura P.S. MPD can't mssfixup! ------=_NextPart_000_010F_01C35527.8BA22250 Content-Type: text/html; charset="koi8-r" Content-Transfer-Encoding: quoted-printable
Hello.
Let in ppp.conf there is
set mtu max 1476
set mtu 1476.
When exchanging MRU = information,
in certain cases client doesn't send = REQ, NAK or=20 even REJ
It's send NOP or ACK and thus = lcp->his_mru can't be set and mtu(=3D1500) will be incorrect = and=20 mssfixup won't work.
 
I've tested this with pppd 2.3.5(FreeBSD) and = pppd=20 2.4.1(Debian)
Both was sending only ACK and = NOP.
When i've tried same with ppp, it sends REQ's, = so it's=20 ok.
 
As solution to handle such cases might be = setting=20 default switch in case TY_MRU:
     =20 default:
        maxmtu =3D p ?=20 physical_DeviceMTU(p) : 0;
        = if=20 (lcp->cfg.max_mtu && (!maxmtu || maxmtu >=20 lcp->cfg.max_mtu))
        =  =20 maxmtu =3D = lcp->cfg.max_mtu;
       =20 wantmtu =3D = lcp->cfg.mtu;
        if=20 (maxmtu && wantmtu > maxmtu)=20 {
          = log_Printf(LogWARN,=20 "%s: Reducing configured MTU from %u to=20 %u\n",
          &nb= sp;         =20 fp->link->name, wantmtu,=20 maxmtu);
          = wantmtu =3D=20 maxmtu;
        }
 
        if=20 (maxmtu && mru >=20 maxmtu)
         =20 lcp->his_mru =3D = maxmtu;
        else if=20 (wantmtu && mru < wantmtu)=20 {
          /* Push him = up to=20 MTU or MIN_MRU = */
         =20 lcp->his_mru =3D = wantmtu;
        }=20 else
          = lcp->his_mru =3D=20 mru;
        break;
 
Jura
 
P.S. MPD can't mssfixup!
 
------=_NextPart_000_010F_01C35527.8BA22250-- State-Changed-From-To: open->closed State-Changed-By: brian State-Changed-When: Tue Jun 29 13:41:32 GMT 2004 State-Changed-Why: This bug seems to no longer be an issue. With both ``set mtu max 1492'' and ``set mru max 1492'', ppp behaves correctly in all instances: We ask for MRU 1492. If we get an ACK, fine. If we get a NAK with a value > 1492, we ask for 1492 again. If we get a REJ we stop asking (it's the peers problem!) If the peer asks for MRU <= 1492, we agree with them and set our MTU accordingly. If the peer asks for MRU > 1492 we NAK with 1492. If the peer keeps asking for > 1492 we never converge and fail negotiating LCP. http://www.freebsd.org/cgi/query-pr.cgi?pr=48378 >Unformatted: