[remove] the doc folder of lwIP 2.1.2
Signed-off-by: liuxianliang <liuxianliang@rt-thread.com>
This commit is contained in:
parent
be64fcba86
commit
0d8f90788f
@ -1,9 +0,0 @@
|
||||
doxygen/ - Configuration files and scripts to create the lwIP doxygen source
|
||||
documentation (found at http://www.nongnu.org/lwip/)
|
||||
|
||||
savannah.txt - How to obtain the current development source code.
|
||||
contrib.txt - How to contribute to lwIP as a developer.
|
||||
rawapi.txt - The documentation for the core API of lwIP.
|
||||
Also provides an overview about the other APIs and multithreading.
|
||||
sys_arch.txt - The documentation for a system abstraction layer of lwIP.
|
||||
ppp.txt - Documentation of the PPP interface for lwIP.
|
@ -1,122 +0,0 @@
|
||||
void
|
||||
eth_mac_irq()
|
||||
{
|
||||
/* Service MAC IRQ here */
|
||||
|
||||
/* Allocate pbuf from pool (avoid using heap in interrupts) */
|
||||
struct pbuf* p = pbuf_alloc(PBUF_RAW, eth_data_count, PBUF_POOL);
|
||||
|
||||
if(p != NULL) {
|
||||
/* Copy ethernet frame into pbuf */
|
||||
pbuf_take(p, eth_data, eth_data_count);
|
||||
|
||||
/* Put in a queue which is processed in main loop */
|
||||
if(!queue_try_put(&queue, p)) {
|
||||
/* queue is full -> packet loss */
|
||||
pbuf_free(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static err_t
|
||||
netif_output(struct netif *netif, struct pbuf *p)
|
||||
{
|
||||
LINK_STATS_INC(link.xmit);
|
||||
|
||||
/* Update SNMP stats (only if you use SNMP) */
|
||||
MIB2_STATS_NETIF_ADD(netif, ifoutoctets, p->tot_len);
|
||||
int unicast = ((p->payload[0] & 0x01) == 0);
|
||||
if (unicast) {
|
||||
MIB2_STATS_NETIF_INC(netif, ifoutucastpkts);
|
||||
} else {
|
||||
MIB2_STATS_NETIF_INC(netif, ifoutnucastpkts);
|
||||
}
|
||||
|
||||
lock_interrupts();
|
||||
pbuf_copy_partial(p, mac_send_buffer, p->tot_len, 0);
|
||||
/* Start MAC transmit here */
|
||||
unlock_interrupts();
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
netif_status_callback(struct netif *netif)
|
||||
{
|
||||
printf("netif status changed %s\n", ip4addr_ntoa(netif_ip4_addr(netif)));
|
||||
}
|
||||
|
||||
static err_t
|
||||
netif_init(struct netif *netif)
|
||||
{
|
||||
netif->linkoutput = netif_output;
|
||||
netif->output = etharp_output;
|
||||
netif->output_ip6 = ethip6_output;
|
||||
netif->mtu = ETHERNET_MTU;
|
||||
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET | NETIF_FLAG_IGMP | NETIF_FLAG_MLD6;
|
||||
MIB2_INIT_NETIF(netif, snmp_ifType_ethernet_csmacd, 100000000);
|
||||
|
||||
SMEMCPY(netif->hwaddr, your_mac_address_goes_here, ETH_HWADDR_LEN);
|
||||
netif->hwaddr_len = ETH_HWADDR_LEN;
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
void
|
||||
main(void)
|
||||
{
|
||||
struct netif netif;
|
||||
|
||||
lwip_init();
|
||||
|
||||
netif_add(&netif, IP4_ADDR_ANY, IP4_ADDR_ANY, IP4_ADDR_ANY, NULL, netif_init, netif_input);
|
||||
netif.name[0] = 'e';
|
||||
netif.name[1] = '0';
|
||||
netif_create_ip6_linklocal_address(&netif, 1);
|
||||
netif.ip6_autoconfig_enabled = 1;
|
||||
netif_set_status_callback(&netif, netif_status_callback);
|
||||
netif_set_default(&netif);
|
||||
netif_set_up(&netif);
|
||||
|
||||
/* Start DHCP and HTTPD */
|
||||
dhcp_start(&netif );
|
||||
httpd_init();
|
||||
|
||||
while(1) {
|
||||
/* Check link state, e.g. via MDIO communication with PHY */
|
||||
if(link_state_changed()) {
|
||||
if(link_is_up()) {
|
||||
netif_set_link_up(&netif);
|
||||
} else {
|
||||
netif_set_link_down(&netif);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for received frames, feed them to lwIP */
|
||||
lock_interrupts();
|
||||
struct pbuf* p = queue_try_get(&queue);
|
||||
unlock_interrupts();
|
||||
|
||||
if(p != NULL) {
|
||||
LINK_STATS_INC(link.recv);
|
||||
|
||||
/* Update SNMP stats (only if you use SNMP) */
|
||||
MIB2_STATS_NETIF_ADD(netif, ifinoctets, p->tot_len);
|
||||
int unicast = ((p->payload[0] & 0x01) == 0);
|
||||
if (unicast) {
|
||||
MIB2_STATS_NETIF_INC(netif, ifinucastpkts);
|
||||
} else {
|
||||
MIB2_STATS_NETIF_INC(netif, ifinnucastpkts);
|
||||
}
|
||||
|
||||
if(netif.input(p, &netif) != ERR_OK) {
|
||||
pbuf_free(p);
|
||||
}
|
||||
}
|
||||
|
||||
/* Cyclic lwIP timers check */
|
||||
sys_check_timeouts();
|
||||
|
||||
/* your application goes here */
|
||||
}
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
typedef struct my_custom_pbuf
|
||||
{
|
||||
struct pbuf_custom p;
|
||||
void* dma_descriptor;
|
||||
} my_custom_pbuf_t;
|
||||
|
||||
LWIP_MEMPOOL_DECLARE(RX_POOL, 10, sizeof(my_custom_pbuf_t), "Zero-copy RX PBUF pool");
|
||||
|
||||
void my_pbuf_free_custom(void* p)
|
||||
{
|
||||
SYS_ARCH_DECL_PROTECT(old_level);
|
||||
|
||||
my_custom_pbuf_t* my_puf = (my_custom_pbuf_t*)p;
|
||||
|
||||
// invalidate data cache here - lwIP and/or application may have written into buffer!
|
||||
// (invalidate is faster than flushing, and noone needs the correct data in the buffer)
|
||||
invalidate_cpu_cache(p->payload, p->tot_len);
|
||||
|
||||
SYS_ARCH_PROTECT(old_level);
|
||||
free_rx_dma_descriptor(my_pbuf->dma_descriptor);
|
||||
LWIP_MEMPOOL_FREE(RX_POOL, my_pbuf);
|
||||
SYS_ARCH_UNPROTECT(old_level);
|
||||
}
|
||||
|
||||
void eth_rx_irq()
|
||||
{
|
||||
dma_descriptor* dma_desc = get_RX_DMA_descriptor_from_ethernet();
|
||||
my_custom_pbuf_t* my_pbuf = (my_custom_pbuf_t*)LWIP_MEMPOOL_ALLOC(RX_POOL);
|
||||
|
||||
my_pbuf->p.custom_free_function = my_pbuf_free_custom;
|
||||
my_pbuf->dma_descriptor = dma_desc;
|
||||
|
||||
invalidate_cpu_cache(dma_desc->rx_data, dma_desc->rx_length);
|
||||
|
||||
struct pbuf* p = pbuf_alloced_custom(PBUF_RAW,
|
||||
dma_desc->rx_length,
|
||||
PBUF_REF,
|
||||
&my_pbuf->p,
|
||||
dma_desc->rx_data,
|
||||
dma_desc->max_buffer_size);
|
||||
|
||||
if(netif->input(p, netif) != ERR_OK) {
|
||||
pbuf_free(p);
|
||||
}
|
||||
}
|
@ -1,58 +0,0 @@
|
||||
1 Introduction
|
||||
|
||||
This document describes some guidelines for people participating
|
||||
in lwIP development.
|
||||
|
||||
2 How to contribute to lwIP
|
||||
|
||||
Here is a short list of suggestions to anybody working with lwIP and
|
||||
trying to contribute bug reports, fixes, enhancements, platform ports etc.
|
||||
First of all as you may already know lwIP is a volunteer project so feedback
|
||||
to fixes or questions might often come late. Hopefully the bug and patch tracking
|
||||
features of Savannah help us not lose users' input.
|
||||
|
||||
2.1 Source code style:
|
||||
|
||||
1. do not use tabs.
|
||||
2. indentation is two spaces per level (i.e. per tab).
|
||||
3. end debug messages with a trailing newline (\n).
|
||||
4. one space between keyword and opening bracket.
|
||||
5. no space between function and opening bracket.
|
||||
6. one space and no newline before opening curly braces of a block.
|
||||
7. closing curly brace on a single line.
|
||||
8. spaces surrounding assignment and comparisons.
|
||||
9. don't initialize static and/or global variables to zero, the compiler takes care of that.
|
||||
10. use current source code style as further reference.
|
||||
|
||||
2.2 Source code documentation style:
|
||||
|
||||
1. JavaDoc compliant and Doxygen compatible.
|
||||
2. Function documentation above functions in .c files, not .h files.
|
||||
(This forces you to synchronize documentation and implementation.)
|
||||
3. Use current documentation style as further reference.
|
||||
|
||||
2.3 Bug reports and patches:
|
||||
|
||||
1. Make sure you are reporting bugs or send patches against the latest
|
||||
sources. (From the latest release and/or the current Git sources.)
|
||||
2. If you think you found a bug make sure it's not already filed in the
|
||||
bugtracker at Savannah.
|
||||
3. If you have a fix put the patch on Savannah. If it is a patch that affects
|
||||
both core and arch specific stuff please separate them so that the core can
|
||||
be applied separately while leaving the other patch 'open'. The preferred way
|
||||
is to NOT touch archs you can't test and let maintainers take care of them.
|
||||
This is a good way to see if they are used at all - the same goes for unix
|
||||
netifs except tapif.
|
||||
4. Do not file a bug and post a fix to it to the patch area. Either a bug report
|
||||
or a patch will be enough.
|
||||
If you correct an existing bug then attach the patch to the bug rather than creating a new entry in the patch area.
|
||||
5. Patches should be specific to a single change or to related changes. Do not mix bugfixes with spelling and other
|
||||
trivial fixes unless the bugfix is trivial too. Do not reorganize code and rename identifiers in the same patch you
|
||||
change behaviour if not necessary. A patch is easier to read and understand if it's to the point and short than
|
||||
if it's not to the point and long :) so the chances for it to be applied are greater.
|
||||
|
||||
2.4 Platform porters:
|
||||
|
||||
1. If you have ported lwIP to a platform (an OS, a uC/processor or a combination of these) and
|
||||
you think it could benefit others[1] you might want discuss this on the mailing list. You
|
||||
can also ask for Git access to submit and maintain your port in the contrib Git module.
|
@ -1 +0,0 @@
|
||||
doxygen lwip.Doxyfile
|
@ -1,3 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
doxygen lwip.Doxyfile
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,403 +0,0 @@
|
||||
/**
|
||||
* @defgroup lwip lwIP
|
||||
*
|
||||
* @defgroup infrastructure Infrastructure
|
||||
*
|
||||
* @defgroup api APIs
|
||||
* lwIP provides three Application Program's Interfaces (APIs) for programs
|
||||
* to use for communication with the TCP/IP code:
|
||||
* - low-level "core" / "callback" or @ref callbackstyle_api.
|
||||
* - higher-level @ref sequential_api.
|
||||
* - BSD-style @ref socket.
|
||||
*
|
||||
* The raw TCP/IP interface allows the application program to integrate
|
||||
* better with the TCP/IP code. Program execution is event based by
|
||||
* having callback functions being called from within the TCP/IP
|
||||
* code. The TCP/IP code and the application program both run in the same
|
||||
* thread. The sequential API has a much higher overhead and is not very
|
||||
* well suited for small systems since it forces a multithreaded paradigm
|
||||
* on the application.
|
||||
*
|
||||
* The raw TCP/IP interface is not only faster in terms of code execution
|
||||
* time but is also less memory intensive. The drawback is that program
|
||||
* development is somewhat harder and application programs written for
|
||||
* the raw TCP/IP interface are more difficult to understand. Still, this
|
||||
* is the preferred way of writing applications that should be small in
|
||||
* code size and memory usage.
|
||||
*
|
||||
* All APIs can be used simultaneously by different application
|
||||
* programs. In fact, the sequential API is implemented as an application
|
||||
* program using the raw TCP/IP interface.
|
||||
*
|
||||
* Do not confuse the lwIP raw API with raw Ethernet or IP sockets.
|
||||
* The former is a way of interfacing the lwIP network stack (including
|
||||
* TCP and UDP), the latter refers to processing raw Ethernet or IP data
|
||||
* instead of TCP connections or UDP packets.
|
||||
*
|
||||
* Raw API applications may never block since all packet processing
|
||||
* (input and output) as well as timer processing (TCP mainly) is done
|
||||
* in a single execution context.
|
||||
*
|
||||
* @defgroup callbackstyle_api "raw" APIs
|
||||
* @ingroup api
|
||||
* Non thread-safe APIs, callback style for maximum performance and minimum
|
||||
* memory footprint.
|
||||
* Program execution is driven by callbacks functions, which are then
|
||||
* invoked by the lwIP core when activity related to that application
|
||||
* occurs. A particular application may register to be notified via a
|
||||
* callback function for events such as incoming data available, outgoing
|
||||
* data sent, error notifications, poll timer expiration, connection
|
||||
* closed, etc. An application can provide a callback function to perform
|
||||
* processing for any or all of these events. Each callback is an ordinary
|
||||
* C function that is called from within the TCP/IP code. Every callback
|
||||
* function is passed the current TCP or UDP connection state as an
|
||||
* argument. Also, in order to be able to keep program specific state,
|
||||
* the callback functions are called with a program specified argument
|
||||
* that is independent of the TCP/IP state.
|
||||
* The raw API (sometimes called native API) is an event-driven API designed
|
||||
* to be used without an operating system that implements zero-copy send and
|
||||
* receive. This API is also used by the core stack for interaction between
|
||||
* the various protocols. It is the only API available when running lwIP
|
||||
* without an operating system.
|
||||
*
|
||||
* @defgroup sequential_api Sequential-style APIs
|
||||
* @ingroup api
|
||||
* Sequential-style APIs, blocking functions. More overhead, but can be called
|
||||
* from any thread except TCPIP thread.
|
||||
* The sequential API provides a way for ordinary, sequential, programs
|
||||
* to use the lwIP stack. It is quite similar to the BSD socket API. The
|
||||
* model of execution is based on the blocking open-read-write-close
|
||||
* paradigm. Since the TCP/IP stack is event based by nature, the TCP/IP
|
||||
* code and the application program must reside in different execution
|
||||
* contexts (threads).
|
||||
*
|
||||
* @defgroup socket Socket API
|
||||
* @ingroup api
|
||||
* BSD-style socket API.\n
|
||||
* Thread-safe, to be called from non-TCPIP threads only.\n
|
||||
* Can be activated by defining @ref LWIP_SOCKET to 1.\n
|
||||
* Header is in posix/sys/socket.h\n
|
||||
* The socket API is a compatibility API for existing applications,
|
||||
* currently it is built on top of the sequential API. It is meant to
|
||||
* provide all functions needed to run socket API applications running
|
||||
* on other platforms (e.g. unix / windows etc.). However, due to limitations
|
||||
* in the specification of this API, there might be incompatibilities
|
||||
* that require small modifications of existing programs.
|
||||
*
|
||||
* @defgroup netifs NETIFs
|
||||
*
|
||||
* @defgroup apps Applications
|
||||
*/
|
||||
|
||||
/**
|
||||
* @mainpage Overview
|
||||
* @verbinclude "README"
|
||||
*/
|
||||
|
||||
/**
|
||||
* @page upgrading Upgrading
|
||||
* @verbinclude "UPGRADING"
|
||||
*/
|
||||
|
||||
/**
|
||||
* @page changelog Changelog
|
||||
*
|
||||
* 2.1.0
|
||||
* -----
|
||||
* * Support TLS via new @ref altcp_api connection API (https, smtps, mqtt over TLS)
|
||||
* * Switch to cmake as the main build system (Makefile file lists are still
|
||||
* maintained for now)
|
||||
* * Improve IPv6 support: support address scopes, support stateless DHCPv6, bugfixes
|
||||
* * Add debug helper asserts to ensure threading/locking requirements are met
|
||||
* * Add sys_mbox_trypost_fromisr() and tcpip_callbackmsg_trycallback_fromisr()
|
||||
* (for FreeRTOS, mainly)
|
||||
* * socket API: support poll(), sendmsg() and recvmsg(); fix problems on close
|
||||
*
|
||||
* Detailed Changelog
|
||||
* ------------------
|
||||
* @verbinclude "CHANGELOG"
|
||||
*/
|
||||
|
||||
/**
|
||||
* @page contrib How to contribute to lwIP
|
||||
* @verbinclude "contrib.txt"
|
||||
*/
|
||||
|
||||
/**
|
||||
* @page pitfalls Common pitfalls
|
||||
*
|
||||
* Multiple Execution Contexts in lwIP code
|
||||
* ========================================
|
||||
*
|
||||
* The most common source of lwIP problems is to have multiple execution contexts
|
||||
* inside the lwIP code.
|
||||
*
|
||||
* lwIP can be used in two basic modes: @ref lwip_nosys (no OS/RTOS
|
||||
* running on target system) or @ref lwip_os (there is an OS running
|
||||
* on the target system).
|
||||
*
|
||||
* See also: @ref multithreading (especially the part about @ref LWIP_ASSERT_CORE_LOCKED()!)
|
||||
*
|
||||
* Mainloop Mode
|
||||
* -------------
|
||||
* In mainloop mode, only @ref callbackstyle_api can be used.
|
||||
* The user has two possibilities to ensure there is only one
|
||||
* exection context at a time in lwIP:
|
||||
*
|
||||
* 1) Deliver RX ethernet packets directly in interrupt context to lwIP
|
||||
* by calling netif->input directly in interrupt. This implies all lwIP
|
||||
* callback functions are called in IRQ context, which may cause further
|
||||
* problems in application code: IRQ is blocked for a long time, multiple
|
||||
* execution contexts in application code etc. When the application wants
|
||||
* to call lwIP, it only needs to disable interrupts during the call.
|
||||
* If timers are involved, even more locking code is needed to lock out
|
||||
* timer IRQ and ethernet IRQ from each other, assuming these may be nested.
|
||||
*
|
||||
* 2) Run lwIP in a mainloop. There is example code here: @ref lwip_nosys.
|
||||
* lwIP is _ONLY_ called from mainloop callstacks here. The ethernet IRQ
|
||||
* has to put received telegrams into a queue which is polled in the
|
||||
* mainloop. Ensure lwIP is _NEVER_ called from an interrupt, e.g.
|
||||
* some SPI IRQ wants to forward data to udp_send() or tcp_write()!
|
||||
*
|
||||
* OS Mode
|
||||
* -------
|
||||
* In OS mode, @ref callbackstyle_api AND @ref sequential_api can be used.
|
||||
* @ref sequential_api are designed to be called from threads other than
|
||||
* the TCPIP thread, so there is nothing to consider here.
|
||||
* But @ref callbackstyle_api functions must _ONLY_ be called from
|
||||
* TCPIP thread. It is a common error to call these from other threads
|
||||
* or from IRQ contexts. Ethernet RX needs to deliver incoming packets
|
||||
* in the correct way by sending a message to TCPIP thread, this is
|
||||
* implemented in tcpip_input().
|
||||
* Again, ensure lwIP is _NEVER_ called from an interrupt, e.g.
|
||||
* some SPI IRQ wants to forward data to udp_send() or tcp_write()!
|
||||
*
|
||||
* 1) tcpip_callback() can be used get called back from TCPIP thread,
|
||||
* it is safe to call any @ref callbackstyle_api from there.
|
||||
*
|
||||
* 2) Use @ref LWIP_TCPIP_CORE_LOCKING. All @ref callbackstyle_api
|
||||
* functions can be called when lwIP core lock is aquired, see
|
||||
* @ref LOCK_TCPIP_CORE() and @ref UNLOCK_TCPIP_CORE().
|
||||
* These macros cannot be used in an interrupt context!
|
||||
* Note the OS must correctly handle priority inversion for this.
|
||||
*
|
||||
* Cache / DMA issues
|
||||
* ==================
|
||||
*
|
||||
* DMA-capable ethernet hardware and zero-copy RX
|
||||
* ----------------------------------------------
|
||||
*
|
||||
* lwIP changes the content of RECEIVED pbufs in the TCP code path.
|
||||
* This implies one or more cacheline(s) of the RX pbuf become dirty
|
||||
* and need to be flushed before the memory is handed over to the
|
||||
* DMA ethernet hardware for the next telegram to be received.
|
||||
* See http://lists.nongnu.org/archive/html/lwip-devel/2017-12/msg00070.html
|
||||
* for a more detailed explanation.
|
||||
* Also keep in mind the user application may also write into pbufs,
|
||||
* so it is generally a bug not to flush the data cache before handing
|
||||
* a buffer to DMA hardware.
|
||||
*
|
||||
* DMA-capable ethernet hardware and cacheline alignment
|
||||
* -----------------------------------------------------
|
||||
* Nice description about DMA capable hardware and buffer handling:
|
||||
* http://www.pebblebay.com/a-guide-to-using-direct-memory-access-in-embedded-systems-part-two/
|
||||
* Read especially sections "Cache coherency" and "Buffer alignment".
|
||||
*/
|
||||
|
||||
/**
|
||||
* @page bugs Reporting bugs
|
||||
* Please report bugs in the lwIP bug tracker at savannah.\n
|
||||
* BEFORE submitting, please check if the bug has already been reported!\n
|
||||
* https://savannah.nongnu.org/bugs/?group=lwip
|
||||
*/
|
||||
|
||||
/**
|
||||
* @page zerocopyrx Zero-copy RX
|
||||
* The following code is an example for zero-copy RX ethernet driver:
|
||||
* @include ZeroCopyRx.c
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup lwip_nosys Mainloop mode ("NO_SYS")
|
||||
* @ingroup lwip
|
||||
* Use this mode if you do not run an OS on your system. \#define NO_SYS to 1.
|
||||
* Feed incoming packets to netif->input(pbuf, netif) function from mainloop,
|
||||
* *not* *from* *interrupt* *context*. You can allocate a @ref pbuf in interrupt
|
||||
* context and put them into a queue which is processed from mainloop.\n
|
||||
* Call sys_check_timeouts() periodically in the mainloop.\n
|
||||
* Porting: implement all functions in @ref sys_time, @ref sys_prot and
|
||||
* @ref compiler_abstraction.\n
|
||||
* You can only use @ref callbackstyle_api in this mode.\n
|
||||
* Sample code:\n
|
||||
* @include NO_SYS_SampleCode.c
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup lwip_os OS mode (TCPIP thread)
|
||||
* @ingroup lwip
|
||||
* Use this mode if you run an OS on your system. It is recommended to
|
||||
* use an RTOS that correctly handles priority inversion and
|
||||
* to use @ref LWIP_TCPIP_CORE_LOCKING.\n
|
||||
* Porting: implement all functions in @ref sys_layer.\n
|
||||
* You can use @ref callbackstyle_api together with @ref tcpip_callback,
|
||||
* and all @ref sequential_api.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @page sys_init System initalization
|
||||
A truly complete and generic sequence for initializing the lwIP stack
|
||||
cannot be given because it depends on additional initializations for
|
||||
your runtime environment (e.g. timers).
|
||||
|
||||
We can give you some idea on how to proceed when using the raw API.
|
||||
We assume a configuration using a single Ethernet netif and the
|
||||
UDP and TCP transport layers, IPv4 and the DHCP client.
|
||||
|
||||
Call these functions in the order of appearance:
|
||||
|
||||
- lwip_init(): Initialize the lwIP stack and all of its subsystems.
|
||||
|
||||
- netif_add(struct netif *netif, ...):
|
||||
Adds your network interface to the netif_list. Allocate a struct
|
||||
netif and pass a pointer to this structure as the first argument.
|
||||
Give pointers to cleared ip_addr structures when using DHCP,
|
||||
or fill them with sane numbers otherwise. The state pointer may be NULL.
|
||||
|
||||
The init function pointer must point to a initialization function for
|
||||
your Ethernet netif interface. The following code illustrates its use.
|
||||
|
||||
@code{.c}
|
||||
err_t netif_if_init(struct netif *netif)
|
||||
{
|
||||
u8_t i;
|
||||
|
||||
for (i = 0; i < ETHARP_HWADDR_LEN; i++) {
|
||||
netif->hwaddr[i] = some_eth_addr[i];
|
||||
}
|
||||
init_my_eth_device();
|
||||
return ERR_OK;
|
||||
}
|
||||
@endcode
|
||||
|
||||
For Ethernet drivers, the input function pointer must point to the lwIP
|
||||
function ethernet_input() declared in "netif/etharp.h". Other drivers
|
||||
must use ip_input() declared in "lwip/ip.h".
|
||||
|
||||
- netif_set_default(struct netif *netif)
|
||||
Registers the default network interface.
|
||||
|
||||
- netif_set_link_up(struct netif *netif)
|
||||
This is the hardware link state; e.g. whether cable is plugged for wired
|
||||
Ethernet interface. This function must be called even if you don't know
|
||||
the current state. Having link up and link down events is optional but
|
||||
DHCP and IPv6 discover benefit well from those events.
|
||||
|
||||
- netif_set_up(struct netif *netif)
|
||||
This is the administrative (= software) state of the netif, when the
|
||||
netif is fully configured this function must be called.
|
||||
|
||||
- dhcp_start(struct netif *netif)
|
||||
Creates a new DHCP client for this interface on the first call.
|
||||
You can peek in the netif->dhcp struct for the actual DHCP status.
|
||||
|
||||
- sys_check_timeouts()
|
||||
When the system is running, you have to periodically call
|
||||
sys_check_timeouts() which will handle all timers for all protocols in
|
||||
the stack; add this to your main loop or equivalent.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @page multithreading Multithreading
|
||||
* lwIP started targeting single-threaded environments. When adding multi-
|
||||
* threading support, instead of making the core thread-safe, another
|
||||
* approach was chosen: there is one main thread running the lwIP core
|
||||
* (also known as the "tcpip_thread"). When running in a multithreaded
|
||||
* environment, raw API functions MUST only be called from the core thread
|
||||
* since raw API functions are not protected from concurrent access (aside
|
||||
* from pbuf- and memory management functions). Application threads using
|
||||
* the sequential- or socket API communicate with this main thread through
|
||||
* message passing.
|
||||
*
|
||||
* As such, the list of functions that may be called from
|
||||
* other threads or an ISR is very limited! Only functions
|
||||
* from these API header files are thread-safe:
|
||||
* - api.h
|
||||
* - netbuf.h
|
||||
* - netdb.h
|
||||
* - netifapi.h
|
||||
* - pppapi.h
|
||||
* - sockets.h
|
||||
* - sys.h
|
||||
*
|
||||
* Additionaly, memory (de-)allocation functions may be
|
||||
* called from multiple threads (not ISR!) with NO_SYS=0
|
||||
* since they are protected by @ref SYS_LIGHTWEIGHT_PROT and/or
|
||||
* semaphores.
|
||||
*
|
||||
* Netconn or Socket API functions are thread safe against the
|
||||
* core thread but they are not reentrant at the control block
|
||||
* granularity level. That is, a UDP or TCP control block must
|
||||
* not be shared among multiple threads without proper locking.
|
||||
*
|
||||
* If @ref SYS_LIGHTWEIGHT_PROT is set to 1 and
|
||||
* @ref LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT is set to 1,
|
||||
* pbuf_free() may also be called from another thread or
|
||||
* an ISR (since only then, mem_free - for PBUF_RAM - may
|
||||
* be called from an ISR: otherwise, the HEAP is only
|
||||
* protected by semaphores).
|
||||
*
|
||||
* How to get threading done right
|
||||
* -------------------------------
|
||||
*
|
||||
* It is strongly recommended to implement the LWIP_ASSERT_CORE_LOCKED()
|
||||
* macro in an application that uses multithreading. lwIP code has
|
||||
* several places where a check for a correct thread context is
|
||||
* implemented which greatly helps the user to get threading done right.
|
||||
* See the example sys_arch.c files in unix and Win32 port
|
||||
* in the contrib repository.
|
||||
*
|
||||
* In short: Copy the functions sys_mark_tcpip_thread() and
|
||||
* sys_check_core_locking() to your port and modify them to work with your OS.
|
||||
* Then let @ref LWIP_ASSERT_CORE_LOCKED() and @ref LWIP_MARK_TCPIP_THREAD()
|
||||
* point to these functions.
|
||||
*
|
||||
* If you use @ref LWIP_TCPIP_CORE_LOCKING, you also need to copy and adapt
|
||||
* the functions sys_lock_tcpip_core() and sys_unlock_tcpip_core().
|
||||
* Let @ref LOCK_TCPIP_CORE() and @ref UNLOCK_TCPIP_CORE() point
|
||||
* to these functions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @page optimization Optimization hints
|
||||
The first thing you want to optimize is the lwip_standard_checksum()
|
||||
routine from src/core/inet.c. You can override this standard
|
||||
function with the \#define LWIP_CHKSUM your_checksum_routine().
|
||||
|
||||
There are C examples given in inet.c or you might want to
|
||||
craft an assembly function for this. RFC1071 is a good
|
||||
introduction to this subject.
|
||||
|
||||
Other significant improvements can be made by supplying
|
||||
assembly or inline replacements for htons() and htonl()
|
||||
if you're using a little-endian architecture.
|
||||
\#define lwip_htons(x) your_htons()
|
||||
\#define lwip_htonl(x) your_htonl()
|
||||
If you \#define them to htons() and htonl(), you should
|
||||
\#define LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS to prevent lwIP from
|
||||
defining htonx / ntohx compatibility macros.
|
||||
|
||||
Check your network interface driver if it reads at
|
||||
a higher speed than the maximum wire-speed. If the
|
||||
hardware isn't serviced frequently and fast enough
|
||||
buffer overflows are likely to occur.
|
||||
|
||||
E.g. when using the cs8900 driver, call cs8900if_service(ethif)
|
||||
as frequently as possible. When using an RTOS let the cs8900 interrupt
|
||||
wake a high priority task that services your driver using a binary
|
||||
semaphore or event flag. Some drivers might allow additional tuning
|
||||
to match your application and network.
|
||||
|
||||
For a production release it is recommended to set LWIP_STATS to 0.
|
||||
Note that speed performance isn't influenced much by simply setting
|
||||
high values to the memory options.
|
||||
*/
|
@ -1,10 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>Redirection</title>
|
||||
<meta http-equiv="refresh" content="0; url=html/index.html" />
|
||||
</head>
|
||||
<body>
|
||||
<a href="html/index.html">index.html</a>
|
||||
</body>
|
||||
</html>
|
Binary file not shown.
@ -1,112 +0,0 @@
|
||||
Multicast DNS for lwIP
|
||||
|
||||
Author: Erik Ekman
|
||||
|
||||
|
||||
Note! The MDNS responder does not have all features required by the standards.
|
||||
See notes in src/apps/mdns/mdns.c for what is left. It is however usable in normal
|
||||
cases - but watch out if many devices on the same network try to use the same
|
||||
host/service instance names.
|
||||
|
||||
|
||||
How to enable:
|
||||
==============
|
||||
|
||||
MDNS support does not depend on DNS.
|
||||
MDNS supports using IPv4 only, v6 only, or v4+v6.
|
||||
|
||||
To enable MDNS responder, set
|
||||
LWIP_MDNS_RESPONDER = 1
|
||||
in lwipopts.h and add src/apps/mdns/mdns.c to your list of files to build.
|
||||
|
||||
The max number of services supported per netif is defined by MDNS_MAX_SERVICES,
|
||||
default is 1.
|
||||
|
||||
Increase MEMP_NUM_UDP_PCB by 1. MDNS needs one PCB.
|
||||
Increase LWIP_NUM_NETIF_CLIENT_DATA by 1 (MDNS needs one entry on netif).
|
||||
|
||||
MDNS with IPv4 requires LWIP_IGMP = 1, and preferably LWIP_AUTOIP = 1.
|
||||
MDNS with IPv6 requires LWIP_IPV6_MLD = 1, and that a link-local address is
|
||||
generated.
|
||||
|
||||
The MDNS code puts its structs on the stack where suitable to reduce dynamic
|
||||
memory allocation. It may use up to 1kB of stack.
|
||||
|
||||
MDNS (like other apps) needs a strncasecmp() implementation. If you have one, define
|
||||
'lwip_strnicmp' to it. Otherwise the code will provide an implementation
|
||||
for you.
|
||||
|
||||
|
||||
How to use:
|
||||
===========
|
||||
|
||||
Call mdns_resp_init() during system initialization.
|
||||
This opens UDP sockets on port 5353 for IPv4 and IPv6.
|
||||
|
||||
|
||||
To start responding on a netif, run
|
||||
mdns_resp_add_netif(struct netif *netif, char *hostname, u32_t dns_ttl)
|
||||
|
||||
The hostname will be copied. If this returns successfully, the netif will join
|
||||
the multicast groups and any MDNS/legacy DNS requests sent unicast or multicast
|
||||
to port 5353 will be handled:
|
||||
- <hostname>.local type A, AAAA or ANY returns relevant IP addresses
|
||||
- Reverse lookups (PTR in-addr.arpa, ip6.arpa) of netif addresses
|
||||
returns <hostname>.local
|
||||
Answers will use the supplied TTL (in seconds)
|
||||
MDNS allows UTF-8 names, but it is recommended to stay within ASCII,
|
||||
since the default case-insensitive comparison assumes this.
|
||||
|
||||
Call mdns_resp_announce() every time the IP address on the netif has changed.
|
||||
|
||||
Call mdns_resp_restart() every time the network interface comes up after being
|
||||
down, for example cable connected after being disconnected, administrative
|
||||
interface comes up after being down, or the device wakes up from sleep.
|
||||
|
||||
To stop responding on a netif, run
|
||||
mdns_resp_remove_netif(struct netif *netif)
|
||||
|
||||
|
||||
Adding services:
|
||||
================
|
||||
|
||||
The netif first needs to be registered. Then run
|
||||
mdns_resp_add_service(struct netif *netif, char *name, char *service,
|
||||
u16_t proto, u16_t port, u32_t dns_ttl,
|
||||
service_get_txt_fn_t txt_fn, void *txt_userdata);
|
||||
|
||||
The name and service pointers will be copied. Name refers to the name of the
|
||||
service instance, and service is the type of service, like _http
|
||||
proto can be DNSSD_PROTO_UDP or DNSSD_PROTO_TCP which represent _udp and _tcp.
|
||||
If this call returns successfully, the following queries will be answered:
|
||||
- _services._dns-sd._udp.local type PTR returns <service>.<proto>.local
|
||||
- <service>.<proto>.local type PTR returns <name>.<service>.<proto>.local
|
||||
- <name>.<service>.<proto>.local type SRV returns hostname and port of service
|
||||
- <name>.<service>.<proto>.local type TXT builds text strings by calling txt_fn
|
||||
with the supplied userdata. The callback adds strings to the reply by calling
|
||||
mdns_resp_add_service_txtitem(struct mdns_service *service, char *txt,
|
||||
int txt_len). Example callback method:
|
||||
|
||||
static void srv_txt(struct mdns_service *service, void *txt_userdata)
|
||||
{
|
||||
res = mdns_resp_add_service_txtitem(service, "path=/", 6);
|
||||
LWIP_ERROR("mdns add service txt failed\n", (res == ERR_OK), return);
|
||||
}
|
||||
|
||||
Since a hostname struct is used for TXT storage each single item can be max
|
||||
63 bytes long, and the total max length (including length bytes for each
|
||||
item) is 255 bytes.
|
||||
|
||||
If your device runs a webserver on port 80, an example call might be:
|
||||
|
||||
mdns_resp_add_service(netif, "myweb", "_http"
|
||||
DNSSD_PROTO_TCP, 80, 3600, srv_txt, NULL);
|
||||
|
||||
which will publish myweb._http._tcp.local for any hosts looking for web servers,
|
||||
and point them to <hostname>.local:80
|
||||
|
||||
Relevant information will be sent as additional records to reduce number of
|
||||
requests required from a client.
|
||||
|
||||
To remove a service from a netif, run
|
||||
mdns_resp_del_service(struct netif *netif, s8_t slot)
|
@ -1,162 +0,0 @@
|
||||
MQTT client for lwIP
|
||||
|
||||
Author: Erik Andersson
|
||||
|
||||
Details of the MQTT protocol can be found at:
|
||||
http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html
|
||||
|
||||
-----------------------------------------------------------------
|
||||
1. Initial steps, reserve memory and make connection to server:
|
||||
|
||||
1.1: Provide storage
|
||||
|
||||
Static allocation:
|
||||
mqtt_client_t static_client;
|
||||
example_do_connect(&static_client);
|
||||
|
||||
Dynamic allocation:
|
||||
mqtt_client_t *client = mqtt_client_new();
|
||||
if(client != NULL) {
|
||||
example_do_connect(&client);
|
||||
}
|
||||
|
||||
1.2: Establish Connection with server
|
||||
|
||||
void example_do_connect(mqtt_client_t *client)
|
||||
{
|
||||
struct mqtt_connect_client_info_t ci;
|
||||
err_t err;
|
||||
|
||||
/* Setup an empty client info structure */
|
||||
memset(&ci, 0, sizeof(ci));
|
||||
|
||||
/* Minimal amount of information required is client identifier, so set it here */
|
||||
ci.client_id = "lwip_test";
|
||||
|
||||
/* Initiate client and connect to server, if this fails immediately an error code is returned
|
||||
otherwise mqtt_connection_cb will be called with connection result after attempting
|
||||
to establish a connection with the server.
|
||||
For now MQTT version 3.1.1 is always used */
|
||||
|
||||
err = mqtt_client_connect(client, ip_addr, MQTT_PORT, mqtt_connection_cb, 0, &ci);
|
||||
|
||||
/* For now just print the result code if something goes wrong */
|
||||
if(err != ERR_OK) {
|
||||
printf("mqtt_connect return %d\n", err);
|
||||
}
|
||||
}
|
||||
|
||||
Connection to server can also be probed by calling mqtt_client_is_connected(client)
|
||||
|
||||
-----------------------------------------------------------------
|
||||
2. Implementing the connection status callback
|
||||
|
||||
|
||||
static void mqtt_connection_cb(mqtt_client_t *client, void *arg, mqtt_connection_status_t status)
|
||||
{
|
||||
err_t err;
|
||||
if(status == MQTT_CONNECT_ACCEPTED) {
|
||||
printf("mqtt_connection_cb: Successfully connected\n");
|
||||
|
||||
/* Setup callback for incoming publish requests */
|
||||
mqtt_set_inpub_callback(client, mqtt_incoming_publish_cb, mqtt_incoming_data_cb, arg);
|
||||
|
||||
/* Subscribe to a topic named "subtopic" with QoS level 1, call mqtt_sub_request_cb with result */
|
||||
err = mqtt_subscribe(client, "subtopic", 1, mqtt_sub_request_cb, arg);
|
||||
|
||||
if(err != ERR_OK) {
|
||||
printf("mqtt_subscribe return: %d\n", err);
|
||||
}
|
||||
} else {
|
||||
printf("mqtt_connection_cb: Disconnected, reason: %d\n", status);
|
||||
|
||||
/* Its more nice to be connected, so try to reconnect */
|
||||
example_do_connect(client);
|
||||
}
|
||||
}
|
||||
|
||||
static void mqtt_sub_request_cb(void *arg, err_t result)
|
||||
{
|
||||
/* Just print the result code here for simplicity,
|
||||
normal behaviour would be to take some action if subscribe fails like
|
||||
notifying user, retry subscribe or disconnect from server */
|
||||
printf("Subscribe result: %d\n", result);
|
||||
}
|
||||
|
||||
-----------------------------------------------------------------
|
||||
3. Implementing callbacks for incoming publish and data
|
||||
|
||||
/* The idea is to demultiplex topic and create some reference to be used in data callbacks
|
||||
Example here uses a global variable, better would be to use a member in arg
|
||||
If RAM and CPU budget allows it, the easiest implementation might be to just take a copy of
|
||||
the topic string and use it in mqtt_incoming_data_cb
|
||||
*/
|
||||
static int inpub_id;
|
||||
static void mqtt_incoming_publish_cb(void *arg, const char *topic, u32_t tot_len)
|
||||
{
|
||||
printf("Incoming publish at topic %s with total length %u\n", topic, (unsigned int)tot_len);
|
||||
|
||||
/* Decode topic string into a user defined reference */
|
||||
if(strcmp(topic, "print_payload") == 0) {
|
||||
inpub_id = 0;
|
||||
} else if(topic[0] == 'A') {
|
||||
/* All topics starting with 'A' might be handled at the same way */
|
||||
inpub_id = 1;
|
||||
} else {
|
||||
/* For all other topics */
|
||||
inpub_id = 2;
|
||||
}
|
||||
}
|
||||
|
||||
static void mqtt_incoming_data_cb(void *arg, const u8_t *data, u16_t len, u8_t flags)
|
||||
{
|
||||
printf("Incoming publish payload with length %d, flags %u\n", len, (unsigned int)flags);
|
||||
|
||||
if(flags & MQTT_DATA_FLAG_LAST) {
|
||||
/* Last fragment of payload received (or whole part if payload fits receive buffer
|
||||
See MQTT_VAR_HEADER_BUFFER_LEN) */
|
||||
|
||||
/* Call function or do action depending on reference, in this case inpub_id */
|
||||
if(inpub_id == 0) {
|
||||
/* Don't trust the publisher, check zero termination */
|
||||
if(data[len-1] == 0) {
|
||||
printf("mqtt_incoming_data_cb: %s\n", (const char *)data);
|
||||
}
|
||||
} else if(inpub_id == 1) {
|
||||
/* Call an 'A' function... */
|
||||
} else {
|
||||
printf("mqtt_incoming_data_cb: Ignoring payload...\n");
|
||||
}
|
||||
} else {
|
||||
/* Handle fragmented payload, store in buffer, write to file or whatever */
|
||||
}
|
||||
}
|
||||
|
||||
-----------------------------------------------------------------
|
||||
4. Using outgoing publish
|
||||
|
||||
|
||||
void example_publish(mqtt_client_t *client, void *arg)
|
||||
{
|
||||
const char *pub_payload= "PubSubHubLubJub";
|
||||
err_t err;
|
||||
u8_t qos = 2; /* 0 1 or 2, see MQTT specification */
|
||||
u8_t retain = 0; /* No don't retain such crappy payload... */
|
||||
err = mqtt_publish(client, "pub_topic", pub_payload, strlen(pub_payload), qos, retain, mqtt_pub_request_cb, arg);
|
||||
if(err != ERR_OK) {
|
||||
printf("Publish err: %d\n", err);
|
||||
}
|
||||
}
|
||||
|
||||
/* Called when publish is complete either with sucess or failure */
|
||||
static void mqtt_pub_request_cb(void *arg, err_t result)
|
||||
{
|
||||
if(result != ERR_OK) {
|
||||
printf("Publish result: %d\n", result);
|
||||
}
|
||||
}
|
||||
|
||||
-----------------------------------------------------------------
|
||||
5. Disconnecting
|
||||
|
||||
Simply call mqtt_disconnect(client)
|
@ -1,529 +0,0 @@
|
||||
PPP interface for lwIP
|
||||
|
||||
Author: Sylvain Rochet
|
||||
|
||||
Table 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.x
|
||||
|
||||
|
||||
|
||||
1 Supported PPP protocols and features
|
||||
======================================
|
||||
|
||||
Supported Low level protocols:
|
||||
* PPP over serial using HDLC-like framing, such as wired dialup modems
|
||||
or 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 access
|
||||
|
||||
Supported 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 Protocol
|
||||
|
||||
Supported address protocols:
|
||||
* IPCP, IP Control Protocol, IPv4 addresses negotiation
|
||||
* IP6CP, IPv6 Control Protocol, IPv6 link-local addresses negotiation
|
||||
|
||||
Supported encryption protocols:
|
||||
* MPPE, Microsoft Point-to-Point Encryption
|
||||
|
||||
Supported 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
|
||||
* =======
|
||||
*/
|
||||
|
||||
/* The PPP control block */
|
||||
ppp_pcb *ppp;
|
||||
|
||||
/* The PPP IP interface */
|
||||
struct netif ppp_netif;
|
||||
|
||||
|
||||
/*
|
||||
* PPP status callback
|
||||
* ===================
|
||||
*
|
||||
* 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_DNS
|
||||
const ip_addr_t *ns;
|
||||
#endif /* LWIP_DNS */
|
||||
printf("status_cb: Connected\n");
|
||||
#if PPP_IPV4_SUPPORT
|
||||
printf(" 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_DNS
|
||||
ns = 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_SUPPORT
|
||||
printf(" 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"
|
||||
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
ppp = pppos_create(&ppp_netif,
|
||||
output_cb, status_cb, ctx_cb);
|
||||
|
||||
|
||||
/*
|
||||
* Creating a new PPPoE session
|
||||
* ============================
|
||||
*/
|
||||
|
||||
#include "netif/ppp/pppoe.h"
|
||||
|
||||
/*
|
||||
* 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"
|
||||
|
||||
/*
|
||||
* 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);
|
||||
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* Ask the peer for up to 2 DNS server addresses. */
|
||||
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).
|
||||
*/
|
||||
u16_t holdoff = 0;
|
||||
ppp_connect(ppp, holdoff);
|
||||
|
||||
|
||||
/*
|
||||
* 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);
|
||||
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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);
|
||||
|
||||
|
||||
|
||||
3 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.
|
||||
|
||||
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.
|
||||
|
||||
Whatever the NO_SYS value, if PPP_INPROC_IRQ_SAFE is 1, pppos_input() is IRQ
|
||||
safe and can be safely called from an interrupt context, using that is going
|
||||
to reduce your need of buffer if pppos_input() is called byte after byte in
|
||||
your rx serial interrupt.
|
||||
|
||||
if NO_SYS is 0, the thread safe way outside an interrupt context is to use
|
||||
the pppos_input_tcpip() function to pass input data to the lwIP core thread
|
||||
using the TCPIP API. This is thread safe in all cases but you should avoid
|
||||
passing data byte after byte because it uses heavy locking (mailbox) and it
|
||||
allocates pbuf, better fill them !
|
||||
|
||||
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 can
|
||||
do that *BUT* you should NEVER call pppos_connect(), pppos_listen() and
|
||||
ppp_free() if pppos_input() can still be running, doing this is NOT thread safe
|
||||
at all. Using PPP_INPROC_IRQ_SAFE from an RX thread is discouraged unless you
|
||||
really know what you are doing, your move ;-)
|
||||
|
||||
|
||||
/*
|
||||
* 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);
|
||||
|
||||
|
||||
|
||||
4 Thread safe PPP API (PPPAPI)
|
||||
==============================
|
||||
|
||||
There is a thread safe API for all corresponding ppp_* functions, you have to
|
||||
enable LWIP_PPP_API in your lwipopts.h file, then see
|
||||
include/netif/ppp/pppapi.h, this is actually pretty obvious.
|
||||
|
||||
|
||||
|
||||
5 Notify phase callback (PPP_NOTIFY_PHASE)
|
||||
==========================================
|
||||
|
||||
Notify phase callback, enabled using the PPP_NOTIFY_PHASE config option, let
|
||||
you configure a callback that is called on each PPP internal state change.
|
||||
This is different from the status callback which only warns you about
|
||||
up(running) and down(dead) events.
|
||||
|
||||
Notify phase callback can be used, for example, to set a LED pattern depending
|
||||
on the current phase of the PPP session. Here is a callback example which
|
||||
tries to mimic what we usually see on xDSL modems while they are negotiating
|
||||
the 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
6 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 now
|
||||
using 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 netif
|
||||
for 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 before
|
||||
starting 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 prefixed
|
||||
pppoe_, common functions are now prefixed ppp_.
|
||||
|
||||
* New PPPERR_ error codes added, check you have all of them in your status
|
||||
callback 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 header
|
||||
file as it is already included by above header files.
|
||||
|
||||
* PPP_INPROC_OWNTHREAD was broken by design and was removed, you have to create
|
||||
your own serial rx thread
|
||||
|
||||
* PPP_INPROC_MULTITHREADED option was misnamed and confusing and was renamed
|
||||
PPP_INPROC_IRQ_SAFE, please read the "PPPoS input path" documentation above
|
||||
because you might have been fooled by that
|
||||
|
||||
* If you used tcpip_callback_with_block() on ppp_ functions you may wish to use
|
||||
the 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 if
|
||||
ppp_set_usepeerdns() is set to true, they are now automatically registered
|
||||
using the dns_setserver() function so you don't need to do that in the PPP
|
||||
callback anymore.
|
||||
|
||||
* PPPoS does not use the SIO API anymore, as such it now requires a serial
|
||||
output callback in place of sio_write
|
||||
|
||||
* PPP_MAXIDLEFLAG is now in ms instead of jiffies
|
@ -1,120 +0,0 @@
|
||||
Daily Use Guide for using Savannah for lwIP
|
||||
|
||||
Table of Contents:
|
||||
|
||||
1 - Obtaining lwIP from the Git repository
|
||||
2 - Committers/developers Git access using SSH
|
||||
3 - Merging a development branch to master branch
|
||||
4 - How to release lwIP
|
||||
|
||||
|
||||
|
||||
1 Obtaining lwIP from the Git repository
|
||||
----------------------------------------
|
||||
|
||||
To perform an anonymous Git clone of the master branch (this is where
|
||||
bug fixes and incremental enhancements occur), do this:
|
||||
git clone git://git.savannah.nongnu.org/lwip.git
|
||||
|
||||
Or, obtain a stable branch (updated with bug fixes only) as follows:
|
||||
git clone --branch DEVEL-1_4_1 git://git.savannah.nongnu.org/lwip.git
|
||||
|
||||
Or, obtain a specific (fixed) release as follows:
|
||||
git clone --branch STABLE-1_4_1 git://git.savannah.nongnu.org/lwip.git
|
||||
|
||||
|
||||
2 Committers/developers Git access using SSH
|
||||
--------------------------------------------
|
||||
|
||||
The Savannah server uses SSH (Secure Shell) protocol 2 authentication and encryption.
|
||||
As such, Git commits to the server occur through a SSH tunnel for project members.
|
||||
To create a SSH2 key pair in UNIX-like environments, do this:
|
||||
ssh-keygen
|
||||
|
||||
Under Windows, a recommended SSH client is "PuTTY", freely available with good
|
||||
documentation and a graphic user interface. Use its key generator.
|
||||
|
||||
Now paste the id_rsa.pub contents into your Savannah account public key list. Wait
|
||||
a while so that Savannah can update its configuration (This can take minutes).
|
||||
|
||||
Try to login using SSH:
|
||||
ssh -v your_login@git.sv.gnu.org
|
||||
|
||||
If it tells you:
|
||||
Linux vcs.savannah.gnu.org 2.6.32-5-xen-686 #1 SMP Wed Jun 17 17:10:03 UTC 2015 i686
|
||||
|
||||
Interactive shell login is not possible for security reasons.
|
||||
VCS commands are allowed.
|
||||
Last login: Tue May 15 23:10:12 2012 from 82.245.102.129
|
||||
You tried to execute:
|
||||
Sorry, you are not allowed to execute that command.
|
||||
Shared connection to git.sv.gnu.org closed.
|
||||
|
||||
then you could login; Savannah refuses to give you a shell - which is OK, as we
|
||||
are allowed to use SSH for Git only. Now, you should be able to do this:
|
||||
git clone your_login@git.sv.gnu.org:/srv/git/lwip.git
|
||||
|
||||
After which you can edit your local files with bug fixes or new features and
|
||||
commit them. Make sure you know what you are doing when using Git to make
|
||||
changes on the repository. If in doubt, ask on the lwip-members mailing list.
|
||||
|
||||
(If SSH asks about authenticity of the host, you can check the key
|
||||
fingerprint against https://savannah.nongnu.org/git/?group=lwip
|
||||
|
||||
|
||||
3 - Merging a development branch to master branch
|
||||
-------------------------------------------------
|
||||
|
||||
Merging is a straightforward process in Git. How to merge all changes in a
|
||||
development branch since our last merge from main:
|
||||
|
||||
Checkout the master branch:
|
||||
git checkout master
|
||||
|
||||
Merge the development branch to master:
|
||||
git merge your-development-branch
|
||||
|
||||
Resolve any conflict.
|
||||
|
||||
Commit the merge result.
|
||||
git commit -a
|
||||
|
||||
Push your commits:
|
||||
git push
|
||||
|
||||
|
||||
4 How to release lwIP
|
||||
---------------------
|
||||
|
||||
First, tag the release using Git: (I use release number 1.4.1 throughout
|
||||
this example).
|
||||
git tag -a STABLE-1_4_1
|
||||
|
||||
Share the tag reference by pushing it to remote:
|
||||
git push origin STABLE-1_4_1
|
||||
|
||||
Prepare the release:
|
||||
cp -r lwip lwip-1.4.1
|
||||
rm -rf lwip-1.4.1/.git lwip-1.4.1/.gitattributes
|
||||
|
||||
Archive the current directory using tar, gzip'd, bzip2'd and zip'd.
|
||||
tar czvf lwip-1.4.1.tar.gz lwip-1.4.1
|
||||
tar cjvf lwip-1.4.1.tar.bz2 lwip-1.4.1
|
||||
zip -r lwip-1.4.1.zip lwip-1.4.1
|
||||
|
||||
Now, sign the archives with a detached GPG binary signature as follows:
|
||||
gpg -b lwip-1.4.1.tar.gz
|
||||
gpg -b lwip-1.4.1.tar.bz2
|
||||
gpg -b lwip-1.4.1.zip
|
||||
|
||||
Upload these files using anonymous FTP:
|
||||
ncftp ftp://savannah.gnu.org/incoming/savannah/lwip
|
||||
ncftp> mput *1.4.1.*
|
||||
|
||||
Additionally, you may post a news item on Savannah, like this:
|
||||
|
||||
A new 1.4.1 release is now available here:
|
||||
http://savannah.nongnu.org/files/?group=lwip&highlight=1.4.1
|
||||
|
||||
You will have to submit this via the user News interface, then approve
|
||||
this via the Administrator News interface.
|
Loading…
x
Reference in New Issue
Block a user