PPP interface for lwIP
生活随笔
收集整理的這篇文章主要介紹了
PPP interface for lwIP
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
//原文 地址 :http://www.nongnu.org/lwip/2_0_x/group__ppp.html
/* //協(xié)議說明,2017年6月29日14:19:18,suozhangPPP interface for lwIPAuthor: Sylvain RochetTable of Contents:1 - Supported PPP protocols and features 2 - Raw API PPP example for all protocols 3 - PPPoS input path (raw API, IRQ safe API, TCPIP API) 4 - Thread safe PPP API (PPPAPI) 5 - Notify phase callback (PPP_NOTIFY_PHASE) 6 - Upgrading from lwIP <= 1.4.x to lwIP >= 2.0.x1 Supported PPP protocols and features ======================================Supported Low level protocols: * PPP over serial using HDLC-like framing, such as wired dialup modemsor mobile telecommunications GPRS/EDGE/UMTS/HSPA+/LTE modems * PPP over Ethernet, such as xDSL modems * PPP over L2TP (Layer 2 Tunneling Protocol) LAC (L2TP Access Concentrator),IP tunnel over UDP, such as VPN accessSupported auth protocols: * PAP, Password Authentication Protocol * CHAP, Challenge-Handshake Authentication Protocol, also known as CHAP-MD5 * MSCHAPv1, Microsoft version of CHAP, version 1 * MSCHAPv2, Microsoft version of CHAP, version 2 * EAP, Extensible Authentication ProtocolSupported address protocols: * IPCP, IP Control Protocol, IPv4 addresses negotiation * IP6CP, IPv6 Control Protocol, IPv6 link-local addresses negotiationSupported encryption protocols: * MPPE, Microsoft Point-to-Point EncryptionSupported compression or miscellaneous protocols, for serial links only: * PFC, Protocol Field Compression * ACFC, Address-and-Control-Field-Compression * ACCM, Asynchronous-Control-Character-Map * VJ, Van Jacobson TCP/IP Header Compression*//* //2 Raw API PPP example for all protocols =======================================As usual, raw API for lwIP means the lightweight API which *MUST* only be used for NO_SYS=1 systems or called inside lwIP core thread for NO_SYS=0 systems.*//* Globals 全局變量* Globals 全局變量* ======= *//* The PPP control block */ ppp_pcb *ppp;/* The PPP IP interface */ struct netif ppp_netif;/* //PPP status callback 狀態(tài)回調(diào)函數(shù)* PPP status callback 狀態(tài)回調(diào)函數(shù)* ===================** PPP status callback is called on PPP status change (up, down, …) from lwIP* core thread*//* PPP status callback example */ static void status_cb(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_DNSconst ip_addr_t *ns;#endif /* LWIP_DNS */printf("status_cb: Connected\n");#if PPP_IPV4_SUPPORTprintf(" our_ipaddr = %s\n", ipaddr_ntoa(&pppif->ip_addr));printf(" his_ipaddr = %s\n", ipaddr_ntoa(&pppif->gw));printf(" netmask = %s\n", ipaddr_ntoa(&pppif->netmask));#if LWIP_DNSns = dns_getserver(0);printf(" dns1 = %s\n", ipaddr_ntoa(ns));ns = dns_getserver(1);printf(" dns2 = %s\n", ipaddr_ntoa(ns));#endif /* LWIP_DNS */#endif /* PPP_IPV4_SUPPORT */#if PPP_IPV6_SUPPORTprintf(" our6_ipaddr = %s\n", ip6addr_ntoa(netif_ip6_addr(pppif, 0)));#endif /* PPP_IPV6_SUPPORT */break;}case PPPERR_PARAM: {printf("status_cb: Invalid parameter\n");break;}case PPPERR_OPEN: {printf("status_cb: Unable to open PPP session\n");break;}case PPPERR_DEVICE: {printf("status_cb: Invalid I/O device for PPP\n");break;}case PPPERR_ALLOC: {printf("status_cb: Unable to allocate resources\n");break;}case PPPERR_USER: {printf("status_cb: User interrupt\n");break;}case PPPERR_CONNECT: {printf("status_cb: Connection lost\n");break;}case PPPERR_AUTHFAIL: {printf("status_cb: Failed authentication challenge\n");break;}case PPPERR_PROTOCOL: {printf("status_cb: Failed to meet protocol\n");break;}case PPPERR_PEERDEAD: {printf("status_cb: Connection timeout\n");break;}case PPPERR_IDLETIMEOUT: {printf("status_cb: Idle Timeout\n");break;}case PPPERR_CONNECTTIME: {printf("status_cb: Max connect time reached\n");break;}case PPPERR_LOOPBACK: {printf("status_cb: Loopback detected\n");break;}default: {printf("status_cb: Unknown error code %d\n", err_code);break;}}/** This should be in the switch case, this is put outside of the switch* case for example readability.*/if (err_code == PPPERR_NONE) {return;}/* ppp_close() was previously called, don't reconnect */if (err_code == PPPERR_USER) {/* ppp_free(); -- can be called here */return;}/** Try to reconnect in 30 seconds, if you need a modem chatscript you have* to do a much better signaling here ;-)*/ppp_connect(pcb, 30);/* OR ppp_listen(pcb); */ }/* 需要包含 頭文件 * Creating a new PPPoS session* ============================** In lwIP, PPPoS is not PPPoSONET, in lwIP PPPoS is PPPoSerial.*/#include "netif/ppp/pppos.h"/* PPP協(xié)議串口 輸出 回調(diào)函數(shù)* PPPoS serial output callback** ppp_pcb, PPP control block* data, buffer to write to serial port* len, length of the data buffer* ctx, optional user-provided callback context pointer** Return value: len if write succeed*/ static u32_t output_cb(ppp_pcb *pcb, u8_t *data, u32_t len, void *ctx) {return uart_write(UART, data, len); }/* 創(chuàng)建一個 PPPoS 通信 接口* Create a new PPPoS interface** ppp_netif, netif to use for this PPP link, i.e. PPP IP interface* output_cb, PPPoS serial output callback* status_cb, PPP status callback, called on PPP status change (up, down, …)* ctx_cb, optional user-provided callback context pointer 用戶自定義 回調(diào)函數(shù)指針*/ ppp = pppos_create(&ppp_netif,output_cb, status_cb, ctx_cb);/* 需要包含 頭文件 * Creating a new PPPoE session* ============================*/#include "netif/ppp/pppoe.h"/* //創(chuàng)建一個 PPPoE 接口* Create a new PPPoE interface** ppp_netif, netif to use for this PPP link, i.e. PPP IP interface* ethif, already existing and setup Ethernet interface to use* service_name, PPPoE service name discriminator (not supported yet)* concentrator_name, PPPoE concentrator name discriminator (not supported yet)* status_cb, PPP status callback, called on PPP status change (up, down, …)* ctx_cb, optional user-provided callback context pointer*/ ppp = pppoe_create(&ppp_netif,ðif,service_name, concentrator_name,status_cb, ctx_cb);/** Creating a new PPPoL2TP session* ===============================*/#include "netif/ppp/pppol2tp.h"/* //創(chuàng)建一個 PPPoL2TP 接口* Create a new PPPoL2TP interface** ppp_netif, netif to use for this PPP link, i.e. PPP IP interface* netif, optional already existing and setup output netif, necessary if you* want to set this interface as default route to settle the chicken* and egg problem with VPN links* ipaddr, IP to connect to* port, UDP port to connect to (usually 1701)* secret, L2TP secret to use* secret_len, size in bytes of the L2TP secret* status_cb, PPP status callback, called on PPP status change (up, down, …)* ctx_cb, optional user-provided callback context pointer*/ ppp = pppol2tp_create(&ppp_netif,struct netif *netif, ip_addr_t *ipaddr, u16_t port,u8_t *secret, u8_t secret_len,ppp_link_status_cb_fn link_status_cb, void *ctx_cb);/* 初始化 PPP 客戶端 連接 為默認(rèn)值* Initiate PPP client connection* ==============================*//* Set this interface as default route */ ppp_set_default(ppp);/** Basic PPP client configuration. Can only be set if PPP session is in the* dead state (i.e. disconnected). We don't need to provide thread-safe* equivalents through PPPAPI because those helpers are only changing* structure members while session is inactive for lwIP core. Configuration* only need to be done once.*//** 基礎(chǔ) 的PPP客戶端 配置。一定能被設(shè)置在PPP 死亡 狀態(tài)時,我們不需要提供線程安全* 通過PPPAPI等價物因為這些助手只是改變* 結(jié)構(gòu)而lwIP會話不活躍的核心成員。配置* 只需要做一次。 *//* Ask the peer for up to 2 DNS server addresses. */ //請求 DNS 服務(wù)器 地址 ppp_set_usepeerdns(ppp, 1);/* Auth configuration, this is pretty self-explanatory */ // 登陸用戶 和 密碼 ppp_set_auth(ppp, PPPAUTHTYPE_ANY, "login", "password");/** Initiate PPP negotiation, without waiting (holdoff=0), can only be called* if PPP session is in the dead state (i.e. disconnected).*/// 初始化 PPP 協(xié)商,沒有等待(holdoff =0 )一定能被調(diào)用 如果 PPP 是死亡狀態(tài)(即連接不成功) u16_t holdoff = 0; ppp_connect(ppp, holdoff);/* 初始化 PPP server 監(jiān)聽* Initiate PPP server listener* ============================*//** Basic PPP server configuration. Can only be set if PPP session is in the* dead state (i.e. disconnected). We don't need to provide thread-safe* equivalents through PPPAPI because those helpers are only changing* structure members while session is inactive for lwIP core. Configuration* only need to be done once.*/ ip4_addr_t addr;/* Set our address */ IP4_ADDR(&addr, 192,168,0,1); ppp_set_ipcp_ouraddr(ppp, &addr);/* Set peer(his) address */ IP4_ADDR(&addr, 192,168,0,2); ppp_set_ipcp_hisaddr(ppp, &addr);/* Set primary DNS server */ IP4_ADDR(&addr, 192,168,10,20); ppp_set_ipcp_dnsaddr(ppp, 0, &addr);/* Set secondary DNS server */ IP4_ADDR(&addr, 192,168,10,21); ppp_set_ipcp_dnsaddr(ppp, 1, &addr);/* Auth configuration, this is pretty self-explanatory */ ppp_set_auth(ppp, PPPAUTHTYPE_ANY, "login", "password");/* Require peer to authenticate */ ppp_set_auth_required(ppp, 1);/** Only for PPPoS, the PPP session should be up and waiting for input.** Note: for PPPoS, ppp_connect() and ppp_listen() are actually the same thing.* The listen call is meant for future support of PPPoE and PPPoL2TP server* mode, where we will need to negotiate the incoming PPPoE session or L2TP* session before initiating PPP itself. We need this call because there is* two passive modes for PPPoS, ppp_set_passive and ppp_set_silent.*/ ppp_set_silent(pppos, 1);/** Initiate PPP listener (i.e. wait for an incoming connection), can only* be called if PPP session is in the dead state (i.e. disconnected).*/ ppp_listen(ppp);/* 關(guān)閉 PPP 連接* Closing PPP connection* ======================*//** Initiate the end of the PPP session, without carrier lost signal* (nocarrier=0), meaning a clean shutdown of PPP protocols.* You can call this function at anytime.*/ u8_t nocarrier = 0; ppp_close(ppp, nocarrier); /** Then you must wait your status_cb() to be called, it may takes from a few* seconds to several tens of seconds depending on the current PPP state.*/ //你必須等待 status_cb() 被調(diào)用以后,他 可能需要根據(jù)當(dāng)前的狀態(tài)來做決定 這個過程可能需要 10S左右 /** Freeing a PPP connection* ========================*//** Free the PPP control block, can only be called if PPP session is in the* dead state (i.e. disconnected). You need to call ppp_close() before.*/ ppp_free(ppp);/* //PPP 數(shù)據(jù) 根據(jù)情況 "選擇" 函數(shù)分析,處理接口,suozhnag,2017年6月29日14:17:133 PPPoS input path (raw API, IRQ safe API, TCPIP API)=====================================================Received data on serial port should be sent to lwIP using the pppos_input()function or the pppos_input_tcpip() function.接收數(shù)據(jù)從串行端口上 應(yīng)該 設(shè)置 LWIP 使用 pppos_input() 接口。If NO_SYS is 1 and if PPP_INPROC_IRQ_SAFE is 0 (the default), pppos_input()is not IRQ safe and then *MUST* only be called inside your main loop.如果 沒有系統(tǒng)的情況下 并且 PPP_INPROC_IRQ_SAFE 設(shè)置為0(默認(rèn)),pppos_input()接口并不是安全 的 IRQ 那么 這個接口必須在 主循環(huán)中 調(diào)用。。Whatever the NO_SYS value, if PPP_INPROC_IRQ_SAFE is 1, pppos_input() is IRQsafe and can be safely called from an interrupt context, using that is goingto reduce your need of buffer if pppos_input() is called byte after byte inyour rx serial interrupt.無論是否使用系統(tǒng)運(yùn)行LWIP,如果PPP_INPROC_IRQ_SAFE是1,pppos_input IRQ()是 IRQ安全,可以安全地從一個中斷調(diào)用上下文,將減少你需要使用的緩沖區(qū),如果pppos_input()在串行接收中斷 每接收一個字節(jié)就調(diào)用一次。if NO_SYS is 0, the thread safe way outside an interrupt context is to usethe pppos_input_tcpip() function to pass input data to the lwIP core threadusing the TCPIP API. This is thread safe in all cases but you should avoidpassing data byte after byte because it uses heavy locking (mailbox) and itallocates pbuf, better fill them !如果使用 系統(tǒng) 來運(yùn)行 LWIP,使用pppos_input_tcpip()函數(shù)將輸入數(shù)據(jù)傳遞給lwIP核心線程TCPIP API(外部中斷上下文的線程安全的方法)。這是線程安全的在所有情況下,但你應(yīng)該避免每接收一個字節(jié)就調(diào)用一次,因為它使用重型鎖(郵箱)分配pbuf,更好的填補(bǔ)他們!if NO_SYS is 0 and if PPP_INPROC_IRQ_SAFE is 1, you may also use pppos_input()from an RX thread, however pppos_input() is not thread safe by itself. You cando that *BUT* you should NEVER call pppos_connect(), pppos_listen() andppp_free() if pppos_input() can still be running, doing this is NOT thread safeat all. Using PPP_INPROC_IRQ_SAFE from an RX thread is discouraged unless youreally know what you are doing, your move ;-)如果使用 系統(tǒng) 來運(yùn)行 LWIP,并且PPP_INPROC_IRQ_SAFE設(shè)置為1,你可能需要使用 pppos_input()來輸入數(shù)據(jù)從線程中接收,然而pppos_input()接口本身是不安全的。你誠摯的*BUT*你永遠(yuǎn)不應(yīng)該叫pppos_connect(),pppos_listen()和ppp_free()如果pppos_input()仍然可以運(yùn)行,這樣做并不是線程安全的。使用PPP_INPROC_IRQ_SAFE從接收數(shù)據(jù)線程中是意氣用事除非你知道你正在干什么。。2017年6月29日14:16:19,suozhang.*//** Fonction to call for received data** ppp, PPP control block* buffer, input buffer* buffer_len, buffer length in bytes*/ void pppos_input(ppp, buffer, buffer_len);//or 兩個接口 任選一個 void pppos_input_tcpip(ppp, buffer, buffer_len);/* //實現(xiàn) PPP 安全線程的接口,suozhang,2017年6月29日13:37:394 Thread safe PPP API (PPPAPI)==============================There is a thread safe API for all corresponding ppp_* functions, you have toenable LWIP_PPP_API in your lwipopts.h file, then seeinclude/netif/ppp/pppapi.h, this is actually pretty obvious.*//* //ppp 協(xié)議 階段狀態(tài) 回調(diào)函數(shù) ,可以用于設(shè)置LED燈 方便直觀 的看到 PPP協(xié)議處于什么階段,suozhang,2017年6月29日13:35:595 Notify phase callback (PPP_NOTIFY_PHASE)==========================================Notify phase callback, enabled using the PPP_NOTIFY_PHASE config option, letyou configure a callback that is called on each PPP internal state change.This is different from the status callback which only warns you aboutup(running) and down(dead) events.Notify phase callback can be used, for example, to set a LED pattern dependingon the current phase of the PPP session. Here is a callback example whichtries to mimic what we usually see on xDSL modems while they are negotiatingthe link, which should be self-explanatory:*/static void ppp_notify_phase_cb(ppp_pcb *pcb, u8_t phase, void *ctx) {switch (phase) {/* Session is down (either permanently or briefly) */case PPP_PHASE_DEAD:led_set(PPP_LED, LED_OFF);break;/* We are between two sessions */case PPP_PHASE_HOLDOFF:led_set(PPP_LED, LED_SLOW_BLINK);break;/* Session just started */case PPP_PHASE_INITIALIZE:led_set(PPP_LED, LED_FAST_BLINK);break;/* Session is running */case PPP_PHASE_RUNNING:led_set(PPP_LED, LED_ON);break;default:break;} }/* //suozhang, 在老的版本上升級 PPP 協(xié)議 說明,2017年6月29日13:31:05,suozhang6 Upgrading from lwIP <= 1.4.x to lwIP >= 2.0.x ===============================================PPP API was fully reworked between 1.4.x and 2.0.x releases. However porting from previous lwIP version is pretty easy:* Previous PPP API used an integer to identify PPP sessions, we are nowusing ppp_pcb* control block, therefore all functions changed from "int ppp"to "ppp_pcb *ppp"* struct netif was moved outside the PPP structure, you have to provide a netiffor PPP interface in pppoX_create() functions* PPP session are not started automatically after you created them anymore,you have to call ppp_connect(), this way you can configure the session beforestarting it.* Previous PPP API used CamelCase, we are now using snake_case.* Previous PPP API mixed PPPoS and PPPoE calls, this isn't the case anymore,PPPoS functions are now prefixed pppos_ and PPPoE functions are now prefixedpppoe_, common functions are now prefixed ppp_.* New PPPERR_ error codes added, check you have all of them in your statuscallback function* Only the following include files should now be used in user application:#include "netif/ppp/pppapi.h"#include "netif/ppp/pppos.h"#include "netif/ppp/pppoe.h"#include "netif/ppp/pppol2tp.h"Functions from ppp.h can be used, but you don't need to include this headerfile as it is already included by above header files.* PPP_INPROC_OWNTHREAD was broken by design and was removed, you have to createyour own serial rx thread* PPP_INPROC_MULTITHREADED option was misnamed and confusing and was renamedPPP_INPROC_IRQ_SAFE, please read the "PPPoS input path" documentation abovebecause you might have been fooled by that* If you used tcpip_callback_with_block() on ppp_ functions you may wish to usethe PPPAPI API instead.* ppp_sighup and ppp_close functions were merged using an optional argument"nocarrier" on ppp_close.* DNS servers are now only remotely asked if LWIP_DNS is set and ifppp_set_usepeerdns() is set to true, they are now automatically registeredusing the dns_setserver() function so you don't need to do that in the PPPcallback anymore.* PPPoS does not use the SIO API anymore, as such it now requires a serialoutput callback in place of sio_write* PPP_MAXIDLEFLAG is now in ms instead of jiffies*/
?
?
/* //協(xié)議說明,2017年6月29日14:19:18,suozhangPPP interface for lwIPAuthor: Sylvain RochetTable of Contents:1 - Supported PPP protocols and features 2 - Raw API PPP example for all protocols 3 - PPPoS input path (raw API, IRQ safe API, TCPIP API) 4 - Thread safe PPP API (PPPAPI) 5 - Notify phase callback (PPP_NOTIFY_PHASE) 6 - Upgrading from lwIP <= 1.4.x to lwIP >= 2.0.x1 Supported PPP protocols and features ======================================Supported Low level protocols: * PPP over serial using HDLC-like framing, such as wired dialup modemsor mobile telecommunications GPRS/EDGE/UMTS/HSPA+/LTE modems * PPP over Ethernet, such as xDSL modems * PPP over L2TP (Layer 2 Tunneling Protocol) LAC (L2TP Access Concentrator),IP tunnel over UDP, such as VPN accessSupported auth protocols: * PAP, Password Authentication Protocol * CHAP, Challenge-Handshake Authentication Protocol, also known as CHAP-MD5 * MSCHAPv1, Microsoft version of CHAP, version 1 * MSCHAPv2, Microsoft version of CHAP, version 2 * EAP, Extensible Authentication ProtocolSupported address protocols: * IPCP, IP Control Protocol, IPv4 addresses negotiation * IP6CP, IPv6 Control Protocol, IPv6 link-local addresses negotiationSupported encryption protocols: * MPPE, Microsoft Point-to-Point EncryptionSupported compression or miscellaneous protocols, for serial links only: * PFC, Protocol Field Compression * ACFC, Address-and-Control-Field-Compression * ACCM, Asynchronous-Control-Character-Map * VJ, Van Jacobson TCP/IP Header Compression*//* //2 Raw API PPP example for all protocols =======================================As usual, raw API for lwIP means the lightweight API which *MUST* only be used for NO_SYS=1 systems or called inside lwIP core thread for NO_SYS=0 systems.*//* Globals 全局變量* Globals 全局變量* ======= *//* The PPP control block */ ppp_pcb *ppp;/* The PPP IP interface */ struct netif ppp_netif;/* //PPP status callback 狀態(tài)回調(diào)函數(shù)* PPP status callback 狀態(tài)回調(diào)函數(shù)* ===================** PPP status callback is called on PPP status change (up, down, …) from lwIP* core thread*//* PPP status callback example */ static void status_cb(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_DNSconst ip_addr_t *ns;#endif /* LWIP_DNS */printf("status_cb: Connected\n");#if PPP_IPV4_SUPPORTprintf(" our_ipaddr = %s\n", ipaddr_ntoa(&pppif->ip_addr));printf(" his_ipaddr = %s\n", ipaddr_ntoa(&pppif->gw));printf(" netmask = %s\n", ipaddr_ntoa(&pppif->netmask));#if LWIP_DNSns = dns_getserver(0);printf(" dns1 = %s\n", ipaddr_ntoa(ns));ns = dns_getserver(1);printf(" dns2 = %s\n", ipaddr_ntoa(ns));#endif /* LWIP_DNS */#endif /* PPP_IPV4_SUPPORT */#if PPP_IPV6_SUPPORTprintf(" our6_ipaddr = %s\n", ip6addr_ntoa(netif_ip6_addr(pppif, 0)));#endif /* PPP_IPV6_SUPPORT */break;}case PPPERR_PARAM: {printf("status_cb: Invalid parameter\n");break;}case PPPERR_OPEN: {printf("status_cb: Unable to open PPP session\n");break;}case PPPERR_DEVICE: {printf("status_cb: Invalid I/O device for PPP\n");break;}case PPPERR_ALLOC: {printf("status_cb: Unable to allocate resources\n");break;}case PPPERR_USER: {printf("status_cb: User interrupt\n");break;}case PPPERR_CONNECT: {printf("status_cb: Connection lost\n");break;}case PPPERR_AUTHFAIL: {printf("status_cb: Failed authentication challenge\n");break;}case PPPERR_PROTOCOL: {printf("status_cb: Failed to meet protocol\n");break;}case PPPERR_PEERDEAD: {printf("status_cb: Connection timeout\n");break;}case PPPERR_IDLETIMEOUT: {printf("status_cb: Idle Timeout\n");break;}case PPPERR_CONNECTTIME: {printf("status_cb: Max connect time reached\n");break;}case PPPERR_LOOPBACK: {printf("status_cb: Loopback detected\n");break;}default: {printf("status_cb: Unknown error code %d\n", err_code);break;}}/** This should be in the switch case, this is put outside of the switch* case for example readability.*/if (err_code == PPPERR_NONE) {return;}/* ppp_close() was previously called, don't reconnect */if (err_code == PPPERR_USER) {/* ppp_free(); -- can be called here */return;}/** Try to reconnect in 30 seconds, if you need a modem chatscript you have* to do a much better signaling here ;-)*/ppp_connect(pcb, 30);/* OR ppp_listen(pcb); */ }/* 需要包含 頭文件 * Creating a new PPPoS session* ============================** In lwIP, PPPoS is not PPPoSONET, in lwIP PPPoS is PPPoSerial.*/#include "netif/ppp/pppos.h"/* PPP協(xié)議串口 輸出 回調(diào)函數(shù)* PPPoS serial output callback** ppp_pcb, PPP control block* data, buffer to write to serial port* len, length of the data buffer* ctx, optional user-provided callback context pointer** Return value: len if write succeed*/ static u32_t output_cb(ppp_pcb *pcb, u8_t *data, u32_t len, void *ctx) {return uart_write(UART, data, len); }/* 創(chuàng)建一個 PPPoS 通信 接口* Create a new PPPoS interface** ppp_netif, netif to use for this PPP link, i.e. PPP IP interface* output_cb, PPPoS serial output callback* status_cb, PPP status callback, called on PPP status change (up, down, …)* ctx_cb, optional user-provided callback context pointer 用戶自定義 回調(diào)函數(shù)指針*/ ppp = pppos_create(&ppp_netif,output_cb, status_cb, ctx_cb);/* 需要包含 頭文件 * Creating a new PPPoE session* ============================*/#include "netif/ppp/pppoe.h"/* //創(chuàng)建一個 PPPoE 接口* Create a new PPPoE interface** ppp_netif, netif to use for this PPP link, i.e. PPP IP interface* ethif, already existing and setup Ethernet interface to use* service_name, PPPoE service name discriminator (not supported yet)* concentrator_name, PPPoE concentrator name discriminator (not supported yet)* status_cb, PPP status callback, called on PPP status change (up, down, …)* ctx_cb, optional user-provided callback context pointer*/ ppp = pppoe_create(&ppp_netif,ðif,service_name, concentrator_name,status_cb, ctx_cb);/** Creating a new PPPoL2TP session* ===============================*/#include "netif/ppp/pppol2tp.h"/* //創(chuàng)建一個 PPPoL2TP 接口* Create a new PPPoL2TP interface** ppp_netif, netif to use for this PPP link, i.e. PPP IP interface* netif, optional already existing and setup output netif, necessary if you* want to set this interface as default route to settle the chicken* and egg problem with VPN links* ipaddr, IP to connect to* port, UDP port to connect to (usually 1701)* secret, L2TP secret to use* secret_len, size in bytes of the L2TP secret* status_cb, PPP status callback, called on PPP status change (up, down, …)* ctx_cb, optional user-provided callback context pointer*/ ppp = pppol2tp_create(&ppp_netif,struct netif *netif, ip_addr_t *ipaddr, u16_t port,u8_t *secret, u8_t secret_len,ppp_link_status_cb_fn link_status_cb, void *ctx_cb);/* 初始化 PPP 客戶端 連接 為默認(rèn)值* Initiate PPP client connection* ==============================*//* Set this interface as default route */ ppp_set_default(ppp);/** Basic PPP client configuration. Can only be set if PPP session is in the* dead state (i.e. disconnected). We don't need to provide thread-safe* equivalents through PPPAPI because those helpers are only changing* structure members while session is inactive for lwIP core. Configuration* only need to be done once.*//** 基礎(chǔ) 的PPP客戶端 配置。一定能被設(shè)置在PPP 死亡 狀態(tài)時,我們不需要提供線程安全* 通過PPPAPI等價物因為這些助手只是改變* 結(jié)構(gòu)而lwIP會話不活躍的核心成員。配置* 只需要做一次。 *//* Ask the peer for up to 2 DNS server addresses. */ //請求 DNS 服務(wù)器 地址 ppp_set_usepeerdns(ppp, 1);/* Auth configuration, this is pretty self-explanatory */ // 登陸用戶 和 密碼 ppp_set_auth(ppp, PPPAUTHTYPE_ANY, "login", "password");/** Initiate PPP negotiation, without waiting (holdoff=0), can only be called* if PPP session is in the dead state (i.e. disconnected).*/// 初始化 PPP 協(xié)商,沒有等待(holdoff =0 )一定能被調(diào)用 如果 PPP 是死亡狀態(tài)(即連接不成功) u16_t holdoff = 0; ppp_connect(ppp, holdoff);/* 初始化 PPP server 監(jiān)聽* Initiate PPP server listener* ============================*//** Basic PPP server configuration. Can only be set if PPP session is in the* dead state (i.e. disconnected). We don't need to provide thread-safe* equivalents through PPPAPI because those helpers are only changing* structure members while session is inactive for lwIP core. Configuration* only need to be done once.*/ ip4_addr_t addr;/* Set our address */ IP4_ADDR(&addr, 192,168,0,1); ppp_set_ipcp_ouraddr(ppp, &addr);/* Set peer(his) address */ IP4_ADDR(&addr, 192,168,0,2); ppp_set_ipcp_hisaddr(ppp, &addr);/* Set primary DNS server */ IP4_ADDR(&addr, 192,168,10,20); ppp_set_ipcp_dnsaddr(ppp, 0, &addr);/* Set secondary DNS server */ IP4_ADDR(&addr, 192,168,10,21); ppp_set_ipcp_dnsaddr(ppp, 1, &addr);/* Auth configuration, this is pretty self-explanatory */ ppp_set_auth(ppp, PPPAUTHTYPE_ANY, "login", "password");/* Require peer to authenticate */ ppp_set_auth_required(ppp, 1);/** Only for PPPoS, the PPP session should be up and waiting for input.** Note: for PPPoS, ppp_connect() and ppp_listen() are actually the same thing.* The listen call is meant for future support of PPPoE and PPPoL2TP server* mode, where we will need to negotiate the incoming PPPoE session or L2TP* session before initiating PPP itself. We need this call because there is* two passive modes for PPPoS, ppp_set_passive and ppp_set_silent.*/ ppp_set_silent(pppos, 1);/** Initiate PPP listener (i.e. wait for an incoming connection), can only* be called if PPP session is in the dead state (i.e. disconnected).*/ ppp_listen(ppp);/* 關(guān)閉 PPP 連接* Closing PPP connection* ======================*//** Initiate the end of the PPP session, without carrier lost signal* (nocarrier=0), meaning a clean shutdown of PPP protocols.* You can call this function at anytime.*/ u8_t nocarrier = 0; ppp_close(ppp, nocarrier); /** Then you must wait your status_cb() to be called, it may takes from a few* seconds to several tens of seconds depending on the current PPP state.*/ //你必須等待 status_cb() 被調(diào)用以后,他 可能需要根據(jù)當(dāng)前的狀態(tài)來做決定 這個過程可能需要 10S左右 /** Freeing a PPP connection* ========================*//** Free the PPP control block, can only be called if PPP session is in the* dead state (i.e. disconnected). You need to call ppp_close() before.*/ ppp_free(ppp);/* //PPP 數(shù)據(jù) 根據(jù)情況 "選擇" 函數(shù)分析,處理接口,suozhnag,2017年6月29日14:17:133 PPPoS input path (raw API, IRQ safe API, TCPIP API)=====================================================Received data on serial port should be sent to lwIP using the pppos_input()function or the pppos_input_tcpip() function.接收數(shù)據(jù)從串行端口上 應(yīng)該 設(shè)置 LWIP 使用 pppos_input() 接口。If NO_SYS is 1 and if PPP_INPROC_IRQ_SAFE is 0 (the default), pppos_input()is not IRQ safe and then *MUST* only be called inside your main loop.如果 沒有系統(tǒng)的情況下 并且 PPP_INPROC_IRQ_SAFE 設(shè)置為0(默認(rèn)),pppos_input()接口并不是安全 的 IRQ 那么 這個接口必須在 主循環(huán)中 調(diào)用。。Whatever the NO_SYS value, if PPP_INPROC_IRQ_SAFE is 1, pppos_input() is IRQsafe and can be safely called from an interrupt context, using that is goingto reduce your need of buffer if pppos_input() is called byte after byte inyour rx serial interrupt.無論是否使用系統(tǒng)運(yùn)行LWIP,如果PPP_INPROC_IRQ_SAFE是1,pppos_input IRQ()是 IRQ安全,可以安全地從一個中斷調(diào)用上下文,將減少你需要使用的緩沖區(qū),如果pppos_input()在串行接收中斷 每接收一個字節(jié)就調(diào)用一次。if NO_SYS is 0, the thread safe way outside an interrupt context is to usethe pppos_input_tcpip() function to pass input data to the lwIP core threadusing the TCPIP API. This is thread safe in all cases but you should avoidpassing data byte after byte because it uses heavy locking (mailbox) and itallocates pbuf, better fill them !如果使用 系統(tǒng) 來運(yùn)行 LWIP,使用pppos_input_tcpip()函數(shù)將輸入數(shù)據(jù)傳遞給lwIP核心線程TCPIP API(外部中斷上下文的線程安全的方法)。這是線程安全的在所有情況下,但你應(yīng)該避免每接收一個字節(jié)就調(diào)用一次,因為它使用重型鎖(郵箱)分配pbuf,更好的填補(bǔ)他們!if NO_SYS is 0 and if PPP_INPROC_IRQ_SAFE is 1, you may also use pppos_input()from an RX thread, however pppos_input() is not thread safe by itself. You cando that *BUT* you should NEVER call pppos_connect(), pppos_listen() andppp_free() if pppos_input() can still be running, doing this is NOT thread safeat all. Using PPP_INPROC_IRQ_SAFE from an RX thread is discouraged unless youreally know what you are doing, your move ;-)如果使用 系統(tǒng) 來運(yùn)行 LWIP,并且PPP_INPROC_IRQ_SAFE設(shè)置為1,你可能需要使用 pppos_input()來輸入數(shù)據(jù)從線程中接收,然而pppos_input()接口本身是不安全的。你誠摯的*BUT*你永遠(yuǎn)不應(yīng)該叫pppos_connect(),pppos_listen()和ppp_free()如果pppos_input()仍然可以運(yùn)行,這樣做并不是線程安全的。使用PPP_INPROC_IRQ_SAFE從接收數(shù)據(jù)線程中是意氣用事除非你知道你正在干什么。。2017年6月29日14:16:19,suozhang.*//** Fonction to call for received data** ppp, PPP control block* buffer, input buffer* buffer_len, buffer length in bytes*/ void pppos_input(ppp, buffer, buffer_len);//or 兩個接口 任選一個 void pppos_input_tcpip(ppp, buffer, buffer_len);/* //實現(xiàn) PPP 安全線程的接口,suozhang,2017年6月29日13:37:394 Thread safe PPP API (PPPAPI)==============================There is a thread safe API for all corresponding ppp_* functions, you have toenable LWIP_PPP_API in your lwipopts.h file, then seeinclude/netif/ppp/pppapi.h, this is actually pretty obvious.*//* //ppp 協(xié)議 階段狀態(tài) 回調(diào)函數(shù) ,可以用于設(shè)置LED燈 方便直觀 的看到 PPP協(xié)議處于什么階段,suozhang,2017年6月29日13:35:595 Notify phase callback (PPP_NOTIFY_PHASE)==========================================Notify phase callback, enabled using the PPP_NOTIFY_PHASE config option, letyou configure a callback that is called on each PPP internal state change.This is different from the status callback which only warns you aboutup(running) and down(dead) events.Notify phase callback can be used, for example, to set a LED pattern dependingon the current phase of the PPP session. Here is a callback example whichtries to mimic what we usually see on xDSL modems while they are negotiatingthe link, which should be self-explanatory:*/static void ppp_notify_phase_cb(ppp_pcb *pcb, u8_t phase, void *ctx) {switch (phase) {/* Session is down (either permanently or briefly) */case PPP_PHASE_DEAD:led_set(PPP_LED, LED_OFF);break;/* We are between two sessions */case PPP_PHASE_HOLDOFF:led_set(PPP_LED, LED_SLOW_BLINK);break;/* Session just started */case PPP_PHASE_INITIALIZE:led_set(PPP_LED, LED_FAST_BLINK);break;/* Session is running */case PPP_PHASE_RUNNING:led_set(PPP_LED, LED_ON);break;default:break;} }/* //suozhang, 在老的版本上升級 PPP 協(xié)議 說明,2017年6月29日13:31:05,suozhang6 Upgrading from lwIP <= 1.4.x to lwIP >= 2.0.x ===============================================PPP API was fully reworked between 1.4.x and 2.0.x releases. However porting from previous lwIP version is pretty easy:* Previous PPP API used an integer to identify PPP sessions, we are nowusing ppp_pcb* control block, therefore all functions changed from "int ppp"to "ppp_pcb *ppp"* struct netif was moved outside the PPP structure, you have to provide a netiffor PPP interface in pppoX_create() functions* PPP session are not started automatically after you created them anymore,you have to call ppp_connect(), this way you can configure the session beforestarting it.* Previous PPP API used CamelCase, we are now using snake_case.* Previous PPP API mixed PPPoS and PPPoE calls, this isn't the case anymore,PPPoS functions are now prefixed pppos_ and PPPoE functions are now prefixedpppoe_, common functions are now prefixed ppp_.* New PPPERR_ error codes added, check you have all of them in your statuscallback function* Only the following include files should now be used in user application:#include "netif/ppp/pppapi.h"#include "netif/ppp/pppos.h"#include "netif/ppp/pppoe.h"#include "netif/ppp/pppol2tp.h"Functions from ppp.h can be used, but you don't need to include this headerfile as it is already included by above header files.* PPP_INPROC_OWNTHREAD was broken by design and was removed, you have to createyour own serial rx thread* PPP_INPROC_MULTITHREADED option was misnamed and confusing and was renamedPPP_INPROC_IRQ_SAFE, please read the "PPPoS input path" documentation abovebecause you might have been fooled by that* If you used tcpip_callback_with_block() on ppp_ functions you may wish to usethe PPPAPI API instead.* ppp_sighup and ppp_close functions were merged using an optional argument"nocarrier" on ppp_close.* DNS servers are now only remotely asked if LWIP_DNS is set and ifppp_set_usepeerdns() is set to true, they are now automatically registeredusing the dns_setserver() function so you don't need to do that in the PPPcallback anymore.* PPPoS does not use the SIO API anymore, as such it now requires a serialoutput callback in place of sio_write* PPP_MAXIDLEFLAG is now in ms instead of jiffies*/
?
轉(zhuǎn)載于:https://www.cnblogs.com/suozhang/p/7094394.html
總結(jié)
以上是生活随笔為你收集整理的PPP interface for lwIP的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: requireJS文件夹
- 下一篇: CCAI 2017 中国人工智能大会 6