[En-Nut-Discussion] PPP Retrying when no PPP/GPRS is available

Brett Abbott Brett.Abbott at digital-telemetry.com
Wed Sep 24 02:34:10 CEST 2003


Hi

Using the PPP in version 3.3.0, you may find that when a PPP service 
(such as a GPRS modem) only partially responds to a Dial command, or the 
ifconfig fails, the lcp state engine may time out.  Repeated attempts to 
redial (atd99*** etc) then seem to fall on deaf ears.  A specific 
example of this is when the initial chat command is acknowledged (ie. 
OK, CONNECT) and then no reponse comes from the PPP engine, it will send 
9 retries before going to bed..

Will the kind assistance from Harald, Ive tracked down that in this 
timeout scenario, the lcp state is set to STOPPED.  When STOPPED, the 
subsequent  request to perform an "if (NutNetIfConfig("ppp", 0, 0, 0)) " 
will not result in any outgoing packets and the ppp thread will remain 
STOPPED.

Also, there is a (useful) workaround in place using a the global 
variable ppp_hackup.  When set to 0, the ppp engine does not attempt to 
talk with the interface.  We use this to allow chat commands to control 
the modem.  Note that when set to 1 (when calling NutNetIfConfig), even 
if the engine is STOPPED, any characters sent to the interface (like ATD 
to reconnect) are absorbed by the ppp engine and rejected as invalid, 
never reaching the modem.

The quick fix to this is a two parter.....

First we set the global variable to 0 (ppp_hackup=0), then we tickle the 
ppp state machine by setting the lcp_status to STARTING (Using the 
lcp_lowerdown function).  The ppp_hackup setting stops the newly woken 
ppp state machine from saying hi to the modem until we've redone our 
dial command.  We redial if needed then reprod the engine using "if 
(NutNetIfConfig("ppp", 0, 0, 0)) "

Ideally you ought to close the engine and go through a proper 
restart/retry but this ought to solve the problem for now.  Ive taken 
this approach rather than solving it nicely as I know Harald is soon to 
modify/improve the way this functionality is to work.

I would like to propose the "ideal" solution but Im still reading the 
PPP text book and would greatfully receive thoughts on how it really 
ought to be solved.

I include the modified source showing the workaround.  Also refer you to 
the pppd.c sample in the CVS repository.

Additionally, I am writing commands to pause the PPP interface, 
interogate the modem status (ie. go into command mode), execute a 
command such as "Signal Strength" and then return to Data Mode (ATO) and 
resume PPP.  Has anyone else done this?  (the ppp_hackup supports this). 
 Perhaps it is better named "ppp_pause".  In the ideal world, I guess 
this is done by putting the engine into a known PAUSE state as it is 
possible to have more than one PPP interface.


Many Thanks in advance.
Brett


// If the link is lost, it will try to reopen link   
if( dcb->dcb_ipcp_state != PPPS_OPENED )  // only proceed if the ppp 
isnt opened
{
    // Put your code here to ensure the modem is hungup, perhaps :
    // sleep 1 second, +++, sleep 1 second, ATH<CR>

    // Tell the modem to connect to PPP
    if (NutChat(pppcom,"'' 'at+cgdcont=1,\"IP\",\"yourAPN\"' 'OK' 
'atd*99***1#' 'CONNECT'") == 0)
    {
        // attempt to configure the network interface

        if (NutNetIfConfig("ppp", 0, 0, 0)) {
            fprintf(tcpip1, "PPP failed\r\n");
            fflush(tcpip1);

            // WORKAROUND CODE STARTS HERE ---- Note ppp_hackup is local 
to the ppp code and to work like this you must
            //                             include the library code in 
your source or place this code in the library
            pppdev = NutDeviceLookup("ppp");
            ppp_hackup=0;
            rc=NutPppIOCtl(pppdev, LCP_LOWERDOWN, 0);
            // WORKAROUND CODE ENDS HERE
                               
            NutSleep(5000);
            continue; // go back and try again
        } else {
        // Worked               
                   
            // * Set name server and default route. Actually the PPP 
interface
            // * should do this, but the current release doesn't.
            dcb = devPpp.dev_dcb;
            NutDnsConfig2(0, 0, dcb->dcb_ip_dns1, dcb->dcb_ip_dns2);
            NutIpRouteAdd(0, 0, dcb->dcb_remote_ip, &devPpp);

            if((rip = NutDnsGetHostByName(INETSERVER)) != 0) {
                fprintf(tcpip1, "%s: %s\r\n", INETSERVER, inet_ntoa(rip));
                fflush(tcpip1);   
            }
        }
    } else {
        // Error with chat
                   
        fprintf(tcpip1,"...error in chat \r\n"); fflush(tcpip1);
        NutSleep(5000);
        continue;
    }
}

 
-----------------------------------------------------------------
Brett Abbott, Managing Director, Digital Telemetry Limited
Email: Brett.Abbott at digital-telemetry.com
PO Box 24 036 Manners Street, Wellington, New Zealand
Phone +64 (4) 5666-860  Mobile +64 (21) 656-144
------------------- Commercial in confidence --------------------





More information about the En-Nut-Discussion mailing list