lwIP Wiki
(made the code example more compilable)
(Cleaned up the code flow, adding lots more comments to describe what is happening.)
Line 1: Line 1:
===PPP from an application perspective===
+
=PPP from an application perspective=
   
There are two ways to use lwIP with PPP support. Either PPPoE (PPP over Ethernet) or PPP-over-serial.
+
There are two ways to use lwIP with PPP support. Either PPPoE (PPP over Ethernet) or PPP-over-serial.
lwIP supports being run in a threaded environment, where ppp is a separate task that runs alongside the main
+
lwIP supports being run in a threaded environment, where ppp is a separate task that runs alongside the main
 
lwIP thread. lwIP also supports being run from a main loop, with lwIP functions being called from the main loop.
 
lwIP thread. lwIP also supports being run from a main loop, with lwIP functions being called from the main loop.
   
Line 23: Line 23:
   
   
= With Task Support =
+
=== With Task Support ===
 
In addition to sio_write(), sio_read() and sio_read_abort() are required.
 
In addition to sio_write(), sio_read() and sio_read_abort() are required.
   
Line 48: Line 48:
   
   
= With no Task Support =
+
=== With no Task Support ===
 
You need to receive the serial data in your main thread, then from your main thread call
 
You need to receive the serial data in your main thread, then from your main thread call
 
pppos_input(int pd, u_char* data, int len);
 
pppos_input(int pd, u_char* data, int len);
   
   
= Example Task Application code =
+
=== Example Task Application code ===
   
  +
This example shows the initialization of the TCP and PPP threads. It assumes that you will do your socket handling
  +
in the context of the main() function.
   
 
<code>
 
<code>
Line 70: Line 72:
 
const char *password = "mypassword";
 
const char *password = "mypassword";
 
 
/* initialise lwIP */
+
/* initialise lwIP. This creates a new thread, tcpip_thread, that
  +
* communicates with the pppInputThread (see below) */
 
tcpip_init(tcpip_init_done, &setup);
 
tcpip_init(tcpip_init_done, &setup);
 
while (!setup) {
 
while (!setup) {
Line 76: Line 79:
 
}
 
}
 
 
/* initialise PPP */
+
/* initialise PPP. This needs to be done only once after boot up, to
  +
* initialize global variables, etc. */
 
pppInit();
 
pppInit();
  +
</code>
  +
  +
<code> /* set the method of authentication. Use PPPAUTHTYPE_PAP, or
  +
* PPPAUTHTYPE_CHAP for more security .
  +
* If this is not called, the default is PPPAUTHTYPE_NONE.
 
*/
 
pppSetAuth(PPPAUTHTYPE_ANY, username, password);
 
pppSetAuth(PPPAUTHTYPE_ANY, username, password);
  +
</code>
  +
  +
<code> /* call the board specific function that will open the specific serial
  +
* port hardware, for example, configuring pins, I/Os, UART, USART,
  +
* clocks, etc. This function is not part of lwip or ppp. You need to
  +
* supply this or find an example for your hardware.
  +
*/
  +
OpenMySerialPortOrUART(PPP_SERIAL_PORT, ...);
  +
</code>
  +
  +
<code> /* call the board specific function that will connect to the modem,
  +
* ie dialing phone numbers, sending configuration AT commands, etc.
  +
* This function is not part of lwip or ppp. You need to supply this
  +
* or find an example for your hardware. */
  +
DialOutMyModem(PPP_SERIAL_PORT, ...);
 
 
 
/** Open a new PPP connection using the given I/O device.
 
/** Open a new PPP connection using the given I/O device.
 
* This initializes the PPP control block but does not
 
* This initializes the PPP control block but does not
* attempt to negotiate the LCP session. If this port
+
* attempt to negotiate the LCP session.
* connects to a modem, the modem connection must be
 
* established before calling this.
 
 
* Return a new PPP connection descriptor on success or
 
* Return a new PPP connection descriptor on success or
* an error code (negative) on failure. */
+
* an error code (negative) on failure.
  +
* This call creates one new thread per call, to service the particular
  +
* serial port, serviced by the pppInputThread function.
  +
*/
 
if (pd = pppOverSerialOpen(PPP_SERIAL_PORT, linkStatusCB, &connected) >= 0) {
 
if (pd = pppOverSerialOpen(PPP_SERIAL_PORT, linkStatusCB, &connected) >= 0) {
while (!connected && timeout(60 seconds)) {
+
// the thread was successfully started.
  +
</code>
  +
  +
<code> while (!connected && timeout(60 seconds)) {
  +
sleep(100 ms);
 
}
 
}
 
 
if (timeout) {
+
if (!timeout) {
pppClose(pd);
+
// We are connected on lwIP over PPP!
  +
 
while (working) {
 
/* create some socket connections,
  +
* do writes and reads on the sockets, close them, etc */
  +
}
 
}
 
}
  +
/* calling pppClose will end the pppInputThread associated with pd*/
 
pppClose(pd);
 
}
 
}
  +
</code>
 
  +
while (1) {
 
  +
<code> // shut down the rest of your hardware.
/* We are connected on lwIP over PPP, create some socket connections etc */
 
}
 
 
pppClose(pd);
 
 
}
 
}
 
 

Revision as of 00:33, 26 September 2012

PPP from an application perspective

There are two ways to use lwIP with PPP support. Either PPPoE (PPP over Ethernet) or PPP-over-serial. lwIP supports being run in a threaded environment, where ppp is a separate task that runs alongside the main lwIP thread. lwIP also supports being run from a main loop, with lwIP functions being called from the main loop.

PPP over serial

To setup a PPP connection over a serial link you will need to provide the Serial IO functions.

Both the thread environment and a main loop require implemented sio_write() to be implemented.

/**
 * Writes to the serial device.
 * 
 * @param fd serial device handle
 * @param data pointer to data to send
 * @param len length (in bytes) of data to send
 * @return number of bytes actually sent
 * 
 * @note This function will block until all data can be sent.
 */
u32_t sio_write(sio_fd_t fd, u8_t *data, u32_t len);


With Task Support

In addition to sio_write(), sio_read() and sio_read_abort() are required.

/**
 * Reads from the serial device.
 * 
 * @param fd serial device handle
 * @param data pointer to data buffer for receiving
 * @param len maximum length (in bytes) of data to receive
 * @return number of bytes actually received - may be 0 if aborted by sio_read_abort
 * 
 * @note This function will block until data can be received. The blocking
 * can be cancelled by calling sio_read_abort().
 */
u32_t sio_read(sio_fd_t fd, u8_t *data, u32_t len);

/**
 * Aborts a blocking sio_read() call.
 * 
 * @param fd serial device handle
 */
void  sio_read_abort(sio_fd_t fd);


With no Task Support

You need to receive the serial data in your main thread, then from your main thread call

pppos_input(int pd, u_char* data, int len);


Example Task Application code

This example shows the initialization of the TCP and PPP threads. It assumes that you will do your socket handling in the context of the main() function.


#include "ppp/ppp.h"

#define PPP_SERIAL_PORT 0

static void linkStatusCB(void* ctx, int errCode, void* arg);

int main(void) {
    int connected = 0;
    int setup = 0;
    int pd;
    const char *username = "myuser";
    const char *password = "mypassword";
    
    /* initialise lwIP. This creates a new thread, tcpip_thread, that 
     * communicates with the pppInputThread (see below) */
    tcpip_init(tcpip_init_done, &setup);
    while (!setup) {
        sleep(1);
    }

    /* initialise PPP. This needs to be done only once after boot up, to 
     * initialize global variables, etc. */
    pppInit();

    /* set the method of authentication. Use PPPAUTHTYPE_PAP, or
     * PPPAUTHTYPE_CHAP for more security .
     * If this is not called, the default is PPPAUTHTYPE_NONE. 
     */
    pppSetAuth(PPPAUTHTYPE_ANY, username, password);

    /* call the board specific function that will open the specific serial
     * port hardware, for example, configuring pins, I/Os, UART, USART, 
     * clocks, etc. This function is not part of lwip or ppp.  You need to
     * supply this or find an example for your hardware.
     */ 
     OpenMySerialPortOrUART(PPP_SERIAL_PORT, ...);

    /* call the board specific function that will connect to the modem,
     * ie dialing phone numbers, sending configuration AT commands, etc. 
     * This function is not part of lwip or ppp. You need to supply this
     * or find an example for your hardware. */
     DialOutMyModem(PPP_SERIAL_PORT, ...);     

    /** Open a new PPP connection using the given I/O device.
     * This initializes the PPP control block but does not
     * attempt to negotiate the LCP session.  
     * Return a new PPP connection descriptor on success or
     * an error code (negative) on failure. 
     * This call creates one new thread per call, to service the particular
     * serial port, serviced by the pppInputThread function.
     */
    if (pd = pppOverSerialOpen(PPP_SERIAL_PORT, linkStatusCB, &connected) >= 0) {
        // the thread was successfully started.

        while (!connected && timeout(60 seconds)) {
          sleep(100 ms);
        }
        
        if (!timeout) {
            // We are connected on lwIP over PPP!
     
            while (working) {
            /* create some socket connections, 
             * do writes and reads on the sockets, close them, etc */
            }
        }
        /* calling pppClose will end the pppInputThread associated with pd*/
        pppClose(pd);
    }

    // shut down the rest of your hardware.
}

static void tcpip_init_done(void *arg)
{
    if (arg) {
        *((bool *)arg) = 1;
    }
}


static void linkStatusCB(void *ctx, int errCode, void *arg) {
   //DTRACE("ctx = 0x%04X, errCode = %d arg = 0x%04X", ctx, errCode, arg);
   int *connected = (int *) ctx;

   struct ppp_addrs *addrs = arg;


   if (errCode == PPPERR_NONE) {
       /* We are connected */
       *connected = 1;
       syslog(LOG_DEBUG, "ip_addr = %s", inet_ntoa(addrs->our_ipaddr));
       syslog(LOG_DEBUG, "netmask = %s", inet_ntoa(addrs->netmask));
       syslog(LOG_DEBUG, "dns1    = %s", inet_ntoa(addrs->dns1));
       syslog(LOG_DEBUG, "dns2    = %s", inet_ntoa(addrs->dns2));
   } else {
       /* We have lost connection */
   }
}


PPP support history in lwIP

HEAD Unspecified.
1.2 Unspecified.

External references

  • RFC 1661 The Point-to-Point Protocol (PPP)

See also