7 1 - Supported PPP protocols and features
8 2 - Raw API PPP example for all protocols
9 3 - PPPoS input path (raw API, IRQ safe API, TCPIP API)
10 4 - Thread safe PPP API (PPPAPI)
11 5 - Notify phase callback (PPP_NOTIFY_PHASE)
12 6 - Upgrading from lwIP <= 1.4.x to lwIP >= 2.0.x
16 1 Supported PPP protocols and features
17 ======================================
19 Supported Low level protocols:
20 * PPP over serial using HDLC-like framing, such as wired dialup modems
21 or mobile telecommunications GPRS/EDGE/UMTS/HSPA+/LTE modems
22 * PPP over Ethernet, such as xDSL modems
23 * PPP over L2TP (Layer 2 Tunneling Protocol) LAC (L2TP Access Concentrator),
24 IP tunnel over UDP, such as VPN access
26 Supported auth protocols:
27 * PAP, Password Authentication Protocol
28 * CHAP, Challenge-Handshake Authentication Protocol, also known as CHAP-MD5
29 * MSCHAPv1, Microsoft version of CHAP, version 1
30 * MSCHAPv2, Microsoft version of CHAP, version 2
31 * EAP, Extensible Authentication Protocol
33 Supported address protocols:
34 * IPCP, IP Control Protocol, IPv4 addresses negotiation
35 * IP6CP, IPv6 Control Protocol, IPv6 link-local addresses negotiation
37 Supported encryption protocols:
38 * MPPE, Microsoft Point-to-Point Encryption
40 Supported compression or miscellaneous protocols, for serial links only:
41 * PFC, Protocol Field Compression
42 * ACFC, Address-and-Control-Field-Compression
43 * ACCM, Asynchronous-Control-Character-Map
44 * VJ, Van Jacobson TCP/IP Header Compression
48 2 Raw API PPP example for all protocols
49 =======================================
51 As usual, raw API for lwIP means the lightweight API which *MUST* only be used
52 for NO_SYS=1 systems or called inside lwIP core thread for NO_SYS=0 systems.
59 /* The PPP control block */
62 /* The PPP IP interface */
63 struct netif ppp_netif;
70 * PPP status callback is called on PPP status change (up, down, …) from lwIP
74 /* PPP status callback example */
75 static void status_cb(ppp_pcb *pcb, int err_code, void *ctx) {
76 struct netif *pppif = ppp_netif(pcb);
84 printf("status_cb: Connected\n");
86 printf(" our_ipaddr = %s\n", ipaddr_ntoa(&pppif->ip_addr));
87 printf(" his_ipaddr = %s\n", ipaddr_ntoa(&pppif->gw));
88 printf(" netmask = %s\n", ipaddr_ntoa(&pppif->netmask));
90 ns = dns_getserver(0);
91 printf(" dns1 = %s\n", ipaddr_ntoa(ns));
92 ns = dns_getserver(1);
93 printf(" dns2 = %s\n", ipaddr_ntoa(ns));
95 #endif /* PPP_IPV4_SUPPORT */
97 printf(" our6_ipaddr = %s\n", ip6addr_ntoa(netif_ip6_addr(pppif, 0)));
98 #endif /* PPP_IPV6_SUPPORT */
102 printf("status_cb: Invalid parameter\n");
106 printf("status_cb: Unable to open PPP session\n");
109 case PPPERR_DEVICE: {
110 printf("status_cb: Invalid I/O device for PPP\n");
114 printf("status_cb: Unable to allocate resources\n");
118 printf("status_cb: User interrupt\n");
121 case PPPERR_CONNECT: {
122 printf("status_cb: Connection lost\n");
125 case PPPERR_AUTHFAIL: {
126 printf("status_cb: Failed authentication challenge\n");
129 case PPPERR_PROTOCOL: {
130 printf("status_cb: Failed to meet protocol\n");
133 case PPPERR_PEERDEAD: {
134 printf("status_cb: Connection timeout\n");
137 case PPPERR_IDLETIMEOUT: {
138 printf("status_cb: Idle Timeout\n");
141 case PPPERR_CONNECTTIME: {
142 printf("status_cb: Max connect time reached\n");
145 case PPPERR_LOOPBACK: {
146 printf("status_cb: Loopback detected\n");
150 printf("status_cb: Unknown error code %d\n", err_code);
156 * This should be in the switch case, this is put outside of the switch
157 * case for example readability.
160 if (err_code == PPPERR_NONE) {
164 /* ppp_close() was previously called, don't reconnect */
165 if (err_code == PPPERR_USER) {
166 /* ppp_free(); -- can be called here */
171 * Try to reconnect in 30 seconds, if you need a modem chatscript you have
172 * to do a much better signaling here ;-)
174 ppp_connect(pcb, 30);
175 /* OR ppp_listen(pcb); */
180 * Creating a new PPPoS session
181 * ============================
183 * In lwIP, PPPoS is not PPPoSONET, in lwIP PPPoS is PPPoSerial.
186 #include "netif/ppp/pppos.h"
189 * PPPoS serial output callback
191 * ppp_pcb, PPP control block
192 * data, buffer to write to serial port
193 * len, length of the data buffer
194 * ctx, optional user-provided callback context pointer
196 * Return value: len if write succeed
198 static u32_t output_cb(ppp_pcb *pcb, u8_t *data, u32_t len, void *ctx) {
199 return uart_write(UART, data, len);
203 * Create a new PPPoS interface
205 * ppp_netif, netif to use for this PPP link, i.e. PPP IP interface
206 * output_cb, PPPoS serial output callback
207 * status_cb, PPP status callback, called on PPP status change (up, down, …)
208 * ctx_cb, optional user-provided callback context pointer
210 ppp = pppos_create(&ppp_netif,
211 output_cb, status_cb, ctx_cb);
215 * Creating a new PPPoE session
216 * ============================
219 #include "netif/ppp/pppoe.h"
222 * Create a new PPPoE interface
224 * ppp_netif, netif to use for this PPP link, i.e. PPP IP interface
225 * ethif, already existing and setup Ethernet interface to use
226 * service_name, PPPoE service name discriminator (not supported yet)
227 * concentrator_name, PPPoE concentrator name discriminator (not supported yet)
228 * status_cb, PPP status callback, called on PPP status change (up, down, …)
229 * ctx_cb, optional user-provided callback context pointer
231 ppp = pppoe_create(&ppp_netif,
233 service_name, concentrator_name,
238 * Creating a new PPPoL2TP session
239 * ===============================
242 #include "netif/ppp/pppol2tp.h"
245 * Create a new PPPoL2TP interface
247 * ppp_netif, netif to use for this PPP link, i.e. PPP IP interface
248 * netif, optional already existing and setup output netif, necessary if you
249 * want to set this interface as default route to settle the chicken
250 * and egg problem with VPN links
251 * ipaddr, IP to connect to
252 * port, UDP port to connect to (usually 1701)
253 * secret, L2TP secret to use
254 * secret_len, size in bytes of the L2TP secret
255 * status_cb, PPP status callback, called on PPP status change (up, down, …)
256 * ctx_cb, optional user-provided callback context pointer
258 ppp = pppol2tp_create(&ppp_netif,
259 struct netif *netif, ip_addr_t *ipaddr, u16_t port,
260 u8_t *secret, u8_t secret_len,
261 ppp_link_status_cb_fn link_status_cb, void *ctx_cb);
265 * Initiate PPP client connection
266 * ==============================
269 /* Set this interface as default route */
270 ppp_set_default(ppp);
273 * Basic PPP client configuration. Can only be set if PPP session is in the
274 * dead state (i.e. disconnected). We don't need to provide thread-safe
275 * equivalents through PPPAPI because those helpers are only changing
276 * structure members while session is inactive for lwIP core. Configuration
277 * only need to be done once.
280 /* Ask the peer for up to 2 DNS server addresses. */
281 ppp_set_usepeerdns(ppp, 1);
283 /* Auth configuration, this is pretty self-explanatory */
284 ppp_set_auth(ppp, PPPAUTHTYPE_ANY, "login", "password");
287 * Initiate PPP negotiation, without waiting (holdoff=0), can only be called
288 * if PPP session is in the dead state (i.e. disconnected).
291 ppp_connect(ppp, holdoff);
295 * Initiate PPP server listener
296 * ============================
300 * Basic PPP server configuration. Can only be set if PPP session is in the
301 * dead state (i.e. disconnected). We don't need to provide thread-safe
302 * equivalents through PPPAPI because those helpers are only changing
303 * structure members while session is inactive for lwIP core. Configuration
304 * only need to be done once.
308 /* Set our address */
309 IP4_ADDR(&addr, 192,168,0,1);
310 ppp_set_ipcp_ouraddr(ppp, &addr);
312 /* Set peer(his) address */
313 IP4_ADDR(&addr, 192,168,0,2);
314 ppp_set_ipcp_hisaddr(ppp, &addr);
316 /* Set primary DNS server */
317 IP4_ADDR(&addr, 192,168,10,20);
318 ppp_set_ipcp_dnsaddr(ppp, 0, &addr);
320 /* Set secondary DNS server */
321 IP4_ADDR(&addr, 192,168,10,21);
322 ppp_set_ipcp_dnsaddr(ppp, 1, &addr);
324 /* Auth configuration, this is pretty self-explanatory */
325 ppp_set_auth(ppp, PPPAUTHTYPE_ANY, "login", "password");
327 /* Require peer to authenticate */
328 ppp_set_auth_required(ppp, 1);
331 * Only for PPPoS, the PPP session should be up and waiting for input.
333 * Note: for PPPoS, ppp_connect() and ppp_listen() are actually the same thing.
334 * The listen call is meant for future support of PPPoE and PPPoL2TP server
335 * mode, where we will need to negotiate the incoming PPPoE session or L2TP
336 * session before initiating PPP itself. We need this call because there is
337 * two passive modes for PPPoS, ppp_set_passive and ppp_set_silent.
339 ppp_set_silent(pppos, 1);
342 * Initiate PPP listener (i.e. wait for an incoming connection), can only
343 * be called if PPP session is in the dead state (i.e. disconnected).
349 * Closing PPP connection
350 * ======================
354 * Initiate the end of the PPP session, without carrier lost signal
355 * (nocarrier=0), meaning a clean shutdown of PPP protocols.
356 * You can call this function at anytime.
359 ppp_close(ppp, nocarrier);
361 * Then you must wait your status_cb() to be called, it may takes from a few
362 * seconds to several tens of seconds depending on the current PPP state.
366 * Freeing a PPP connection
367 * ========================
371 * Free the PPP control block, can only be called if PPP session is in the
372 * dead state (i.e. disconnected). You need to call ppp_close() before.
378 3 PPPoS input path (raw API, IRQ safe API, TCPIP API)
379 =====================================================
381 Received data on serial port should be sent to lwIP using the pppos_input()
382 function or the pppos_input_tcpip() function.
384 If NO_SYS is 1 and if PPP_INPROC_IRQ_SAFE is 0 (the default), pppos_input()
385 is not IRQ safe and then *MUST* only be called inside your main loop.
387 Whatever the NO_SYS value, if PPP_INPROC_IRQ_SAFE is 1, pppos_input() is IRQ
388 safe and can be safely called from an interrupt context, using that is going
389 to reduce your need of buffer if pppos_input() is called byte after byte in
390 your rx serial interrupt.
392 if NO_SYS is 0, the thread safe way outside an interrupt context is to use
393 the pppos_input_tcpip() function to pass input data to the lwIP core thread
394 using the TCPIP API. This is thread safe in all cases but you should avoid
395 passing data byte after byte because it uses heavy locking (mailbox) and it
396 allocates pbuf, better fill them !
398 if NO_SYS is 0 and if PPP_INPROC_IRQ_SAFE is 1, you may also use pppos_input()
399 from an RX thread, however pppos_input() is not thread safe by itself. You can
400 do that *BUT* you should NEVER call pppos_connect(), pppos_listen() and
401 ppp_free() if pppos_input() can still be running, doing this is NOT thread safe
402 at all. Using PPP_INPROC_IRQ_SAFE from an RX thread is discouraged unless you
403 really know what you are doing, your move ;-)
407 * Fonction to call for received data
409 * ppp, PPP control block
410 * buffer, input buffer
411 * buffer_len, buffer length in bytes
413 void pppos_input(ppp, buffer, buffer_len);
417 void pppos_input_tcpip(ppp, buffer, buffer_len);
421 4 Thread safe PPP API (PPPAPI)
422 ==============================
424 There is a thread safe API for all corresponding ppp_* functions, you have to
425 enable LWIP_PPP_API in your lwipopts.h file, then see
426 include/netif/ppp/pppapi.h, this is actually pretty obvious.
430 5 Notify phase callback (PPP_NOTIFY_PHASE)
431 ==========================================
433 Notify phase callback, enabled using the PPP_NOTIFY_PHASE config option, let
434 you configure a callback that is called on each PPP internal state change.
435 This is different from the status callback which only warns you about
436 up(running) and down(dead) events.
438 Notify phase callback can be used, for example, to set a LED pattern depending
439 on the current phase of the PPP session. Here is a callback example which
440 tries to mimic what we usually see on xDSL modems while they are negotiating
441 the link, which should be self-explanatory:
443 static void ppp_notify_phase_cb(ppp_pcb *pcb, u8_t phase, void *ctx) {
446 /* Session is down (either permanently or briefly) */
448 led_set(PPP_LED, LED_OFF);
451 /* We are between two sessions */
452 case PPP_PHASE_HOLDOFF:
453 led_set(PPP_LED, LED_SLOW_BLINK);
456 /* Session just started */
457 case PPP_PHASE_INITIALIZE:
458 led_set(PPP_LED, LED_FAST_BLINK);
461 /* Session is running */
462 case PPP_PHASE_RUNNING:
463 led_set(PPP_LED, LED_ON);
473 6 Upgrading from lwIP <= 1.4.x to lwIP >= 2.0.x
474 ===============================================
476 PPP API was fully reworked between 1.4.x and 2.0.x releases. However porting
477 from previous lwIP version is pretty easy:
479 * Previous PPP API used an integer to identify PPP sessions, we are now
480 using ppp_pcb* control block, therefore all functions changed from "int ppp"
483 * struct netif was moved outside the PPP structure, you have to provide a netif
484 for PPP interface in pppoX_create() functions
486 * PPP session are not started automatically after you created them anymore,
487 you have to call ppp_connect(), this way you can configure the session before
490 * Previous PPP API used CamelCase, we are now using snake_case.
492 * Previous PPP API mixed PPPoS and PPPoE calls, this isn't the case anymore,
493 PPPoS functions are now prefixed pppos_ and PPPoE functions are now prefixed
494 pppoe_, common functions are now prefixed ppp_.
496 * New PPPERR_ error codes added, check you have all of them in your status
499 * Only the following include files should now be used in user application:
500 #include "netif/ppp/pppapi.h"
501 #include "netif/ppp/pppos.h"
502 #include "netif/ppp/pppoe.h"
503 #include "netif/ppp/pppol2tp.h"
505 Functions from ppp.h can be used, but you don't need to include this header
506 file as it is already included by above header files.
508 * PPP_INPROC_OWNTHREAD was broken by design and was removed, you have to create
509 your own serial rx thread
511 * PPP_INPROC_MULTITHREADED option was misnamed and confusing and was renamed
512 PPP_INPROC_IRQ_SAFE, please read the "PPPoS input path" documentation above
513 because you might have been fooled by that
515 * If you used tcpip_callback_with_block() on ppp_ functions you may wish to use
516 the PPPAPI API instead.
518 * ppp_sighup and ppp_close functions were merged using an optional argument
519 "nocarrier" on ppp_close.
521 * DNS servers are now only remotely asked if LWIP_DNS is set and if
522 ppp_set_usepeerdns() is set to true, they are now automatically registered
523 using the dns_setserver() function so you don't need to do that in the PPP
526 * PPPoS does not use the SIO API anymore, as such it now requires a serial
527 output callback in place of sio_write
529 * PPP_MAXIDLEFLAG is now in ms instead of jiffies