This module provides the lwIP PPP (Point-to-Point Protocol) integration documentation.
Overview
The lwIP PPP module enables IP communication over serial or USB-based links by implementing the Point-to-Point Protocol (PPP). This library provides both PPP client and server roles, supporting multiple link types such as:
- PPP over Serial (PPPoS)
- PPP over Ethernet (PPPoE)
- PPP over L2TP (PPPoL2TP)
The original lwIP PPP implementation is documented here: PPP in lwIP
Features
For detail information about PPP feature, refer to Section 1 in PPP in lwIP.
Configuration
Configuration options for the lwIP PPP module are available in the FSP configuration editor. Detailed parameter descriptions can be found in the following document:
Build Time Configurations for Source
The following build time configurations are defined in lwip/pppopts.h:
| Configuration | Options | Default | Description |
| PPPoL2TP |
| LwIP support PPPoL2TP |
| Disabled | Enable PPP over L2TP (Layer 2 Tunneling Protocol) support. |
| LwIP support PPPoL2TP AUTH |
| Disabled | Enable PPP Over L2TP Auth (enable MD5 support) |
| Authentication |
| PPP support PAP |
| Disabled | Enable Password Authentication Protocol. |
| PPP support CHAP |
| Disabled | Enable Challenge Handshake Authentication Protocol. |
| PPP support MSCHAP |
| Disabled | Enable Microsoft Challenge Handshake Authentication Protocol (MS-CHAP) for enhanced PPP authentication with stronger security than standard CHAP. Required for MPPE encryption. Automatically enables CHAP support. |
| PPP support EAP |
| Disabled | Enable Extensible Authentication Protocol. |
| PPP support MD5-RANDM |
-
(CHAP_SUPPORT || EAP_SUPPORT || PPPOL2TP_AUTH_SUPPORT)
-
Enabled
-
Disabled
| (CHAP_SUPPORT || EAP_SUPPORT || PPPOL2TP_AUTH_SUPPORT) | Enable MD5-RANDM support for PPP authentication. |
| Use external PolarSSL library |
| Disabled | Use an external PolarSSL library for cryptographic operations in PPP authentication. |
| Use external mbedTLS library |
| Disabled | Use external mbedTLS library for cryptographic operations in PPP authentication and TLS connections. |
| Max username length | Username length must be between 1 and 256. | 256 | Maximum length of hostname or name for auth. |
| Max secret length | Secret length must be between 1 and 256. | 256 | Maximum length of password or secret. |
| Internal memory pools |
| PPP num connections | Must be a positive integer (minimum 1). Specifies the number of concurrent PPP connections supported. | 1 | Number of simultaneously active PPP connections (requires the PPP_SUPPORT option). |
| PPP num API messages | Must be a positive integer (minimum 1). Represents the number of available PPP API message buffers. | 5 | Number of concurrent PPP API messages. |
| PPPoL2TP num connections | At least 1 PPPoL2TP connection is required. Please enter a positive integer value. | 1 | Number of concurrently active PPPoL2TP interfaces (only used with PPPOL2TP_SUPPORT==1). |
| PPP num timeouts per PCB | Enter a positive integer greater than 1 | 2 + PPP_IPV4_SUPPORT + PPP_IPV6_SUPPORT + CCP_SUPPORT | The number of sys_timeouts running in parallel per ppp_pcb. See the detailed explanation at the end of ppp_impl.h about simultaneous timers analysis. |
| Debugging |
| PPP debug |
-
LWIP_DBG_OFF
-
Enabled
-
Disabled
| LWIP_DBG_OFF | Enable debugging in PPP. |
| PPP packet print support |
| Disabled | Enable PPP print packet support. It displays exchanged packet content in debug trace. |
| Notification/Callback Options |
| PPP phase notifications |
| Disabled | Enable PPP notify phase support. |
| Compression/Optimization |
| Enable Link Quality Reporting (LQR) |
| Disabled | Support Link Quality Report. Do nothing except exchanging some LCP packets. |
| Enable VJ header compression |
| Disabled | Support VJ header compression. |
| Role Configuration |
| Enable PPP server mode |
| Disabled | Enable PPP server mode. When enabled, the device acts as a PPP server and waits for the client to initiate the connection. |
| PPP local hostname | Name must be a valid C symbol | lwip_ppp | Local hostname used for authentication purposes. This name identifies the PPP peer when acting as a client or server. |
| MRU/MTU |
| PPP max MRU | Value must be positive integer. | 1500 | This is the upper limit value to which we set our interface MTU. If the peer sends a larger number, we will just ignore it as we are not required to maximize the use of the peer capacity. |
| PPP min MRU | Value must be positive integer. | 128 | Peer must be able to receive at least our minimum MTU. |
| PPPoL2TP default MRU | Value must be positive integer. | 1450 | Default MTU and MRU for L2TP. |
| Timing/Retry Settings |
| FSM default timeout | Value must be between 0 and 255 | 6 | Default timeout (in seconds) for Finite State Machine (FSM) retransmissions. |
| FSM max terminate requests | Value must be between 0 and 255 | 2 | Maximum number of Terminate-Request packets sent before giving up. |
| FSM max configure requests | Value must be between 0 and 255 | 10 | Maximum number of Configure-Request packets sent before giving up. |
| FSM max NAK loops | Value must be between 0 and 255 | 5 | Maximum number of NAK loops allowed during negotiation. |
| PAP default timeout | Value must be between 0 and 255 | 6 | Default timeout (in seconds) for PAP authentication response. |
| PAP max transmits | Value must be between 0 and 255 | 10 | Maximum number of PAP Authenticate-Request transmissions before giving up. |
| PAP request timeout | Value must be between 0 and 255 | 30 | Request timeout (in seconds) before retransmitting PAP Authenticate-Request. |
| CHAP default timeout | Value must be between 0 and 255 | 6 | Default timeout (in seconds) for CHAP challenge response. |
| CHAP max transmits | Value must be between 0 and 255 | 10 | Maximum number of CHAP Challenge-Requests transmitted before giving up. |
| CHAP re-challenge time | Value must be between 0 and 255 | 0 | Interval (in seconds) between periodic CHAP re-challenges. If this option is > 0, rechallenge the peer every n seconds. |
| EAP request time | Value must be between 0 and 255 | 6 | Default request timeout (in seconds) for EAP authentication. |
| EAP allowed requests | Value must be between 0 and 255 | 10 | Maximum number of EAP Request retries before failure. |
| EAP default timeout | Value must be between 0 and 255 | 6 | Timeout (in seconds) for EAP packet acknowledgment. |
| EAP max transmits | Value must be between 0 and 255 | 10 | Maximum number of EAP packet retransmissions. |
| LCP loopback fail threshold | Value must be between 0 and 255 | 10 | Number of failed echo responses before declaring link down. |
| LCP echo interval | Value must be between 0 and 255 | 0 | Time interval (in seconds) between LCP echo requests. |
| LCP max echo failures | Value must be between 0 and 255 | 3 | Number of consecutive failed echo replies before declaring link dead. |
| PPP max idle flag | Value must be positive integer. | 100 | Max Xmit idle time (in ms) before resend flag char. |
| LwIP support PPP API |
| Disabled | Enable high-level PPP API functions. |
| PPP support CCP |
| Disabled | Enable Compression Control Protocol (CCP) for PPP data compression to reduce bandwidth usage. |
| PPP support MPPE |
| Disabled | Enable Microsoft Point-to-Point Encryption (MPPE) for PPP data encryption and security. Automatically enables CCP and MS-CHAP support. |
Specific configuration of PPPoE can be found in the following document:
Build Time Configurations for Source
The following build time configurations are defined in lwip/pppoe_opts.h:
| Configuration | Options | Default | Description |
| LwIP support PPPoE SCNAME |
| Disabled | Enable PPP Over Ethernet Service Name and Concentrator Name support. |
| PPPoE num connections | At least 1 PPPoE connection is required. Please enter a positive integer value. | 1 | Number of concurrently active PPPoE interfaces (only used with PPPOE_SUPPORT==1). |
Specific configuration of PPPoS can be found in the following documents:
- For LwIP PPP on USB:
Build Time Configurations for Source
The following build time configurations are defined in lwip/pppos_usb_opts.h:
| Configuration | Options | Default | Description |
| PPPoS num connections | At least 1 PPPoS connection is required. Please enter a positive integer value. | MEMP_NUM_PPP_PCB | Number of concurrently active PPPoS interfaces (only used with PPPOS_SUPPORT==1). |
| IRQ safe |
| Disabled | If enabled, call pppos_input() using tcpip_callback(). |
| Enable FCS lookup table |
| Enabled | Keep a 256*2 byte table to speed up FCS calculation for PPPoS. |
| PPP MRU | Value must be positive integer. | 1500 | MRU value we want to negotiate (peer MTU). It only affects PPPoS because PPPoE value is derived from the Ethernet interface MTU and PPPoL2TP have a separate setting. |
- For LwIP PPP on UART:
Build Time Configurations for Source
The following build time configurations are defined in lwip/pppos_uart_opts.h:
| Configuration | Options | Default | Description |
| PPPoS num connections | At least 1 PPPoS connection is required. Please enter a positive integer value. | MEMP_NUM_PPP_PCB | Number of concurrently active PPPoS interfaces (only used with PPPOS_SUPPORT==1). |
| IRQ safe |
| Disabled | If enabled, call pppos_input() using tcpip_callback(). |
| Enable FCS lookup table |
| Enabled | Keep a 256*2 byte table to speed up FCS calculation for PPPoS. |
| PPP MRU | Value must be positive integer. | 1500 | MRU value we want to negotiate (peer MTU). It only affects PPPoS because PPPoE value is derived from the Ethernet interface MTU and PPPoL2TP have a separate setting. |
- Note
- The configuration options for PPPoS on USB and UART are the same. This is the general configuration for PPPoS usage.
Examples
Basic LwIP PPPoS on Uart Example
The following demonstrates a basic example of LwIP PPPoS on Uart.
#define LWIP_PPP_UART_EXAMPLE_RING_BUF_SIZE (2048U)
#define LWIP_PPP_UART_EXAMPLE_READ_BUF_SIZE (64U)
uint8_t g_uart_buf[LWIP_PPP_UART_EXAMPLE_READ_BUF_SIZE] = {0};
typedef struct st_uart_ring_buffer
{
uint8_t g_buf[LWIP_PPP_UART_EXAMPLE_RING_BUF_SIZE];
uint32_t head;
uint32_t tail;
} uart_ring_buffer_t;
static uart_ring_buffer_t g_uart_ring_buffer = {.g_buf = {0}, .head = 0, .tail = 0};
static void uart_ring_buffer_put (uart_ring_buffer_t * rb, uint8_t data)
{
uint32_t next_head = (rb->head + 1) % LWIP_PPP_UART_EXAMPLE_RING_BUF_SIZE;
if (next_head != rb->tail)
{
rb->g_buf[rb->head] = data;
rb->head = next_head;
}
}
static bool uart_ring_buffer_get (uart_ring_buffer_t * rb, uint8_t * data)
{
if (rb->head == rb->tail)
{
return false;
}
*data = rb->g_buf[rb->tail];
rb->tail = (rb->tail + 1) % LWIP_PPP_UART_EXAMPLE_RING_BUF_SIZE;
return true;
}
{
{
uart_ring_buffer_put(&g_uart_ring_buffer, (uint8_t) p_args->
data);
}
{
rm_lwip_pppos_specific_cfg_t * p_pppos_cfg =
(rm_lwip_pppos_specific_cfg_t *) ppp_uart.p_cfg->p_extended_cfg;
assert(FSP_SUCCESS == err);
}
else
{
}
}
static void pppos_uart_input_example (void)
{
uint8_t rx_byte;
while (uart_ring_buffer_get(&g_uart_ring_buffer, &rx_byte))
{
pppos_input(ppp_uart.p_ctrl->p_ppp_pcb, &rx_byte, 1);
}
}
void pppos_uart_init (void)
{
struct netif pppos_netif;
lwip_init();
rm_lwip_pppos_specific_cfg_t * p_pppos_cfg =
(rm_lwip_pppos_specific_cfg_t *) ppp_uart.p_cfg->p_extended_cfg;
assert(FSP_SUCCESS == err);
err =
R_SCI_UART_Read(p_uart->p_ctrl, g_uart_buf, LWIP_PPP_UART_EXAMPLE_READ_BUF_SIZE);
assert(FSP_SUCCESS == err);
ppp_uart.p_ctrl->p_ppp_pcb =
pppos_create(&pppos_netif, pppos_output_uart, pppos_uart_link_status, (void *) &ppp_uart);
if (ppp_uart.p_ctrl->p_ppp_pcb == NULL)
{
printf("Could not create PPP control interface");
return;
}
ppp_set_default(ppp_uart.p_ctrl->p_ppp_pcb);
#if PPP_AUTH_SUPPORT
ppp_set_auth(ppp_uart.p_ctrl->p_ppp_pcb, PPPAUTHTYPE_PAP, "g_ppp_uart_user", "g_ppp_uart_pass");
#endif
ppp_connect(ppp_uart.p_ctrl->p_ppp_pcb, 0);
}
u32_t pppos_output_uart (ppp_pcb * pcb, const void * data, u32_t len, void * ctx)
{
LWIP_UNUSED_ARG(pcb);
rm_lwip_ppp_instance_t * p_instance = (rm_lwip_ppp_instance_t *) ctx;
rm_lwip_pppos_specific_cfg_t * p_pppos_cfg =
(rm_lwip_pppos_specific_cfg_t *) p_instance->p_cfg->p_extended_cfg;
return (err == FSP_SUCCESS) ? len : 0;
}
void pppos_uart_link_status (ppp_pcb * pcb, int err_code, void * ctx)
{
struct netif * pppif = ppp_netif(pcb);
LWIP_UNUSED_ARG(ctx);
switch (err_code)
{
case PPPERR_NONE:
{
#if LWIP_DNS
const ip_addr_t * ns;
#endif
printf("status_cb: Connected\n");
#if PPP_IPV4_SUPPORT
printf(" our_ipaddr = %s\n", ip4addr_ntoa(netif_ip4_addr(pppif)));
printf(" his_ipaddr = %s\n", ip4addr_ntoa(netif_ip4_gw(pppif)));
printf(" netmask = %s\n", ip4addr_ntoa(netif_ip4_netmask(pppif)));
#endif
#if PPP_IPV6_SUPPORT
printf(" our6_ipaddr = %s\n", ip6addr_ntoa(netif_ip6_addr(pppif, 0)));
#endif
#if LWIP_DNS
ns = dns_getserver(0);
printf(" dns1 = %s\n", ipaddr_ntoa(ns));
ns = dns_getserver(1);
printf(" dns2 = %s\n", ipaddr_ntoa(ns));
#endif
break;
}
case PPPERR_PARAM:
{
printf("ppp_link_status_cb: PPPERR_PARAM\n");
break;
}
case PPPERR_OPEN:
{
printf("ppp_link_status_cb: PPPERR_OPEN\n");
break;
}
case PPPERR_DEVICE:
{
printf("ppp_link_status_cb: PPPERR_DEVICE\n");
break;
}
case PPPERR_ALLOC:
{
printf("ppp_link_status_cb: PPPERR_ALLOC\n");
break;
}
case PPPERR_USER:
{
printf("ppp_link_status_cb: PPPERR_USER\n");
break;
}
case PPPERR_CONNECT:
{
printf("ppp_link_status_cb: PPPERR_CONNECT\n");
break;
}
case PPPERR_AUTHFAIL:
{
printf("ppp_link_status_cb: PPPERR_AUTHFAIL\n");
break;
}
case PPPERR_PROTOCOL:
{
printf("ppp_link_status_cb: PPPERR_PROTOCOL\n");
break;
}
case PPPERR_PEERDEAD:
{
printf("ppp_link_status_cb: PPPERR_PEERDEAD\n");
break;
}
case PPPERR_IDLETIMEOUT:
{
printf("ppp_link_status_cb: PPPERR_IDLETIMEOUT\n");
break;
}
case PPPERR_CONNECTTIME:
{
printf("ppp_link_status_cb: PPPERR_CONNECTTIME\n");
break;
}
case PPPERR_LOOPBACK:
{
printf("ppp_link_status_cb: PPPERR_LOOPBACK\n");
break;
}
default:
{
printf("ppp_link_status_cb: unknown errCode %d\n", err_code);
break;
}
}
}
void rm_lwip_pppos_uart_example (void)
{
pppos_uart_init();
while (1)
{
sys_check_timeouts();
pppos_uart_input_example();
}
}
Basic LwIP PPPoS on USB Example
The following demonstrates a basic example of LwIP PPPoS on USB.
#define LWIP_PPP_USB_EXAMPLE_RING_BUF_SIZE (2048U)
#define LWIP_PPP_USB_EXAMPLE_LENGTH (0x07U)
#define LWIP_PPP_USB_EXAMPLE_READ_BUF_SIZE (64U)
usb_event_info_t event_info;
uint8_t g_usb_buf[LWIP_PPP_USB_EXAMPLE_READ_BUF_SIZE] = {0};
typedef struct st_usb_ring_buffer
{
uint8_t g_buf[LWIP_PPP_USB_EXAMPLE_RING_BUF_SIZE];
uint32_t head;
uint32_t tail;
} usb_ring_buffer_t;
static usb_ring_buffer_t g_usb_ring_buffer = {.g_buf = {0}, .head = 0, .tail = 0};
static void usb_ring_buffer_put (usb_ring_buffer_t * rb, uint8_t data)
{
uint32_t next_head = (rb->head + 1) % LWIP_PPP_USB_EXAMPLE_RING_BUF_SIZE;
if (next_head != rb->tail)
{
rb->g_buf[rb->head] = data;
rb->head = next_head;
}
}
static bool usb_ring_buffer_get (usb_ring_buffer_t * rb, uint8_t * data)
{
if (rb->head == rb->tail)
{
return false;
}
*data = rb->g_buf[rb->tail];
rb->tail = (rb->tail + 1) % LWIP_PPP_USB_EXAMPLE_RING_BUF_SIZE;
return true;
}
static bool usb_ring_buffer_put_block (uint8_t * data, uint32_t len)
{
for (uint32_t i = 0; i < len; i++)
{
usb_ring_buffer_put(&g_usb_ring_buffer, data[i]);
}
return true;
}
void user_usb_handler (void)
{
rm_lwip_pppos_specific_cfg_t * p_pppos_cfg =
(rm_lwip_pppos_specific_cfg_t *) ppp_usb.p_cfg->p_extended_cfg;
assert(FSP_SUCCESS == err);
switch (usb_event)
{
{
assert(FSP_SUCCESS == err);
break;
}
{
if (event_info.data_size > 0)
{
usb_ring_buffer_put_block(g_usb_buf, event_info.data_size);
}
assert(FSP_SUCCESS == err);
break;
}
{
{
assert(FSP_SUCCESS == err);
}
{
assert(FSP_SUCCESS == err);
}
{
assert(FSP_SUCCESS == err);
}
else
{
}
break;
}
{
break;
}
default:
{
break;
}
}
}
static void pppos_usb_input_example (void)
{
uint8_t rx_byte;
while (usb_ring_buffer_get(&g_usb_ring_buffer, &rx_byte))
{
pppos_input(ppp_usb.p_ctrl->p_ppp_pcb, &rx_byte, 1);
}
}
void pppos_usb_init (void)
{
struct netif pppos_netif;
lwip_init();
rm_lwip_pppos_specific_cfg_t * p_pppos_cfg =
(rm_lwip_pppos_specific_cfg_t *) ppp_usb.p_cfg->p_extended_cfg;
assert(FSP_SUCCESS == err);
ppp_usb.p_ctrl->p_ppp_pcb = pppos_create(&pppos_netif, pppos_output_usb, pppos_usb_link_status, (void *) &ppp_usb);
if (ppp_usb.p_ctrl->p_ppp_pcb == NULL)
{
printf("Could not create PPP control interface");
return;
}
ppp_set_default(ppp_usb.p_ctrl->p_ppp_pcb);
#if PPP_AUTH_SUPPORT
ppp_set_auth(ppp_usb.p_ctrl->p_ppp_pcb, PPPAUTHTYPE_PAP, "g_ppp_usb_user", "g_ppp_usb_pass");
#endif
ppp_connect(ppp_usb.p_ctrl->p_ppp_pcb, 0);
}
u32_t pppos_output_usb (ppp_pcb * pcb, const void * data, u32_t len, void * ctx)
{
LWIP_UNUSED_ARG(pcb);
rm_lwip_ppp_instance_t * p_instance = (rm_lwip_ppp_instance_t *) ctx;
rm_lwip_pppos_specific_cfg_t * p_pppos_cfg =
(rm_lwip_pppos_specific_cfg_t *) p_instance->p_cfg->p_extended_cfg;
return (err == FSP_SUCCESS) ? len : 0;
}
void pppos_usb_link_status (ppp_pcb * pcb, int err_code, void * ctx)
{
struct netif * pppif = ppp_netif(pcb);
LWIP_UNUSED_ARG(ctx);
switch (err_code)
{
case PPPERR_NONE:
{
#if LWIP_DNS
const ip_addr_t * ns;
#endif
printf("status_cb: Connected\n");
#if PPP_IPV4_SUPPORT
printf(" our_ipaddr = %s\n", ip4addr_ntoa(netif_ip4_addr(pppif)));
printf(" his_ipaddr = %s\n", ip4addr_ntoa(netif_ip4_gw(pppif)));
printf(" netmask = %s\n", ip4addr_ntoa(netif_ip4_netmask(pppif)));
#endif
#if PPP_IPV6_SUPPORT
printf(" our6_ipaddr = %s\n", ip6addr_ntoa(netif_ip6_addr(pppif, 0)));
#endif
#if LWIP_DNS
ns = dns_getserver(0);
printf(" dns1 = %s\n", ipaddr_ntoa(ns));
ns = dns_getserver(1);
printf(" dns2 = %s\n", ipaddr_ntoa(ns));
#endif
break;
}
case PPPERR_PARAM:
{
printf("ppp_link_status_cb: PPPERR_PARAM\n");
break;
}
case PPPERR_OPEN:
{
printf("ppp_link_status_cb: PPPERR_OPEN\n");
break;
}
case PPPERR_DEVICE:
{
printf("ppp_link_status_cb: PPPERR_DEVICE\n");
break;
}
case PPPERR_ALLOC:
{
printf("ppp_link_status_cb: PPPERR_ALLOC\n");
break;
}
case PPPERR_USER:
{
printf("ppp_link_status_cb: PPPERR_USER\n");
break;
}
case PPPERR_CONNECT:
{
printf("ppp_link_status_cb: PPPERR_CONNECT\n");
break;
}
case PPPERR_AUTHFAIL:
{
printf("ppp_link_status_cb: PPPERR_AUTHFAIL\n");
break;
}
case PPPERR_PROTOCOL:
{
printf("ppp_link_status_cb: PPPERR_PROTOCOL\n");
break;
}
case PPPERR_PEERDEAD:
{
printf("ppp_link_status_cb: PPPERR_PEERDEAD\n");
break;
}
case PPPERR_IDLETIMEOUT:
{
printf("ppp_link_status_cb: PPPERR_IDLETIMEOUT\n");
break;
}
case PPPERR_CONNECTTIME:
{
printf("ppp_link_status_cb: PPPERR_CONNECTTIME\n");
break;
}
case PPPERR_LOOPBACK:
{
printf("ppp_link_status_cb: PPPERR_LOOPBACK\n");
break;
}
default:
{
printf("ppp_link_status_cb: unknown errCode %d\n", err_code);
break;
}
}
}
void rm_lwip_pppos_usb_example (void)
{
pppos_usb_init();
while (1)
{
sys_check_timeouts();
user_usb_handler();
pppos_usb_input_example();
}
}