From de1fd2bfc4324a3c267f630d6a435c8f1983760d Mon Sep 17 00:00:00 2001 From: liuxianliang Date: Sat, 20 Jun 2020 14:01:09 +0800 Subject: [PATCH] [add] lwIP 2.1.2 transplantation on RT-Thread. Signed-off-by: liuxianliang --- components/net/Kconfig | 6 +- components/net/SConscript | 2 +- components/net/lwip-2.1.2/README_RT-THREAD.md | 89 ++ components/net/lwip-2.1.2/SConscript | 265 +++++ .../net/lwip-2.1.2/src/apps/ping/ping.c | 245 ++++ .../net/lwip-2.1.2/src/apps/tftp/tftp_port.c | 87 ++ .../src/arch/include/arch/bpstruct.h | 35 + .../net/lwip-2.1.2/src/arch/include/arch/cc.h | 103 ++ .../src/arch/include/arch/epstruct.h | 35 + .../lwip-2.1.2/src/arch/include/arch/perf.h | 52 + .../src/arch/include/arch/sys_arch.h | 64 ++ components/net/lwip-2.1.2/src/arch/sys_arch.c | 844 ++++++++++++++ .../lwip-2.1.2/src/include/netif/ethernetif.h | 52 + components/net/lwip-2.1.2/src/lwipopts.h | 644 +++++++++++ components/net/lwip-2.1.2/src/lwippools.h | 10 + .../net/lwip-2.1.2/src/netif/ethernetif.c | 1000 +++++++++++++++++ 16 files changed, 3531 insertions(+), 2 deletions(-) create mode 100644 components/net/lwip-2.1.2/README_RT-THREAD.md create mode 100644 components/net/lwip-2.1.2/SConscript create mode 100644 components/net/lwip-2.1.2/src/apps/ping/ping.c create mode 100644 components/net/lwip-2.1.2/src/apps/tftp/tftp_port.c create mode 100644 components/net/lwip-2.1.2/src/arch/include/arch/bpstruct.h create mode 100644 components/net/lwip-2.1.2/src/arch/include/arch/cc.h create mode 100644 components/net/lwip-2.1.2/src/arch/include/arch/epstruct.h create mode 100644 components/net/lwip-2.1.2/src/arch/include/arch/perf.h create mode 100644 components/net/lwip-2.1.2/src/arch/include/arch/sys_arch.h create mode 100644 components/net/lwip-2.1.2/src/arch/sys_arch.c create mode 100644 components/net/lwip-2.1.2/src/include/netif/ethernetif.h create mode 100644 components/net/lwip-2.1.2/src/lwipopts.h create mode 100644 components/net/lwip-2.1.2/src/lwippools.h create mode 100644 components/net/lwip-2.1.2/src/netif/ethernetif.c diff --git a/components/net/Kconfig b/components/net/Kconfig index 1d5bbd9462..d17fd7cbd5 100644 --- a/components/net/Kconfig +++ b/components/net/Kconfig @@ -120,9 +120,13 @@ config RT_USING_LWIP config RT_USING_LWIP210 bool "lwIP v2.1.0" + + config RT_USING_LWIP212 + bool "lwIP v2.1.2" + endchoice - if (RT_USING_LWIP210 || RT_USING_LWIP202) + if (RT_USING_LWIP210 || RT_USING_LWIP202 || RT_USING_LWIP212) config RT_USING_LWIP_IPV6 bool "IPV6 protocol" default n diff --git a/components/net/SConscript b/components/net/SConscript index 0c59cd1c3c..5df3d847e7 100644 --- a/components/net/SConscript +++ b/components/net/SConscript @@ -8,7 +8,7 @@ cwd = GetCurrentDir() list = os.listdir(cwd) # the default version of LWIP is 2.0.2 -if not GetDepend('RT_USING_LWIP141') and not GetDepend('RT_USING_LWIP202') and not GetDepend('RT_USING_LWIP210'): +if not GetDepend('RT_USING_LWIP141') and not GetDepend('RT_USING_LWIP202') and not GetDepend('RT_USING_LWIP210') and not GetDepend('RT_USING_LWIP212'): AddDepend('RT_USING_LWIP202') for d in list: diff --git a/components/net/lwip-2.1.2/README_RT-THREAD.md b/components/net/lwip-2.1.2/README_RT-THREAD.md new file mode 100644 index 0000000000..c91be2c7f0 --- /dev/null +++ b/components/net/lwip-2.1.2/README_RT-THREAD.md @@ -0,0 +1,89 @@ +# lwip 移植说明 + +为了适配 RT-Thread 网卡设备,RT-Thread 团队基于原 [lwip](http://savannah.nongnu.org/projects/lwip/) 进行了一些修改,本文档记录了相关修改内容。 + +> 本 lwip-2.1.2 版本基于 [lwip STABLE-2_1_2_RELEASE](https://git.savannah.gnu.org/git/lwip.git) 版本移植而来。 + + +| Date | Author | Notes | +| :---- | :---- | :---- | +| 2019-09-02 | MurphyZhao | 增加 lwip 2.1.2 移植说明 | +| 2020-06-18 | xiangxistu | 增加部分 lwIP 2.1.2 移植说明 | + +## 修改内容 + +### src/api + +- `src/api/sockets.c` 增加 `lwip_tryget_socket` 函数,作为 `tryget_socket` 函数的全局实现 +- `src/api/sockets.c` 在 `alloc_socket` 函数中,增加 SAL 移植函数 `rt_wqueue_init` + +``` +#ifdef SAL_USING_POSIX + rt_wqueue_init(&sockets[i].wait_head); +#endif +``` + +### src/app + +- 增加 `ping/ping.c`,便于在 finsh/msh 中使用 ping 功能 +- 增加 `tftp/tftp_port.c`,便于在 finsh/msh 中使用 tftp_server 功能 + +### src/arch + +增加 `src/arch` 目录,存储对接 RT-Thread 设备框架的移植文件,从 lwip-2.0.2 版本中的移植文件修改而来。 + + + +以及相对于 lwIP2.0.2 的增加修改内容: + + +* 在 `src/arch/sys_arch.c` 中增加 MTU 与 etharp_output 的初始化 + +* 在 `src/arch/sys_arch.c` 中增加新添加的邮箱函数 + + 对邮箱机制的新增加的 sys_mbox_trypost_fromisr 函数予以实现 + +* 在 `src/arch/sys_arch.c` 中增加新添加的内存堆函数 + + 对内存堆的新增加的 mem_overflow_check_raw 与 mem_overflow_init_raw 函数予以实现 + +* 在 `src/arch/cc.h` 中增加对 lwIP 使用的标准错误代码宏的处理,不再使用 lwIP 内置的错误宏 + + +### src/core + +- 在 `src/core/dns.c` 的 `dns_setserver` 函数中增加 RT-Thread netdev 相关的移植 +- 在 `src/core/netif.c` 中增加 RT-Thread netdev 相关的移植 + +### src/include + +- 在 `src/include/lwip/priv/sockets_priv.h` 中增加 SAL 相关的移植 + + 在 `lwip_sock` 结构体中增加 ` rt_wqueue_t wait_head;` 成员 + +- 在 `src/include/lwip/prot/ieee.h` 中增加 EAPOL, EAP over LAN 标识 + +- 在 `src/include/lwip/init.h` 中的版本号后增加 `U` 标识 + +- 在 `src/include/lwip/sockets.h` 中增加 `LWIP_SOCKET_SELECT`,解决开启 RT_USING_POSIX 时的冲突 + +- 在 `src/include/lwip/arch.h` 中修改 ` `为 `"sys/types.h" `,解决编译冲突 + + 并添加 typedef int ssize_t 定义,补足因 libc 与 dfs 未开启时 ssize_t 的定义不足问题 + +- 在 `src/include/netif/` 中增加 `ethernetif.h`,用于对接 RT-Thread 网卡设备 + +### src/netif + +- 在 `src/netif/` 中增加 `ethernetif.c`,用于对接 RT-Thread 网卡设备 +- 在 `src/netif/lowpan6.c` 中增加 `LWIP_6LOWPAN` 宏定义,以防止编译错误 + +### src + +- 在 src 目录下,增加 `src/lwipopts.h`,用于 lwip 功能裁剪以及配置设置 +- 在 src 目录下,增加 `src/lwippools.h`,用于定义 `LWIP_MALLOC_MEMPOOL` + +### 其它 + +- 增加 SConscript 文件,用于 scons 构建 +- 增加 README_RT-THREAD.md 文件,用于记录相对原 lwip 源码的改动 diff --git a/components/net/lwip-2.1.2/SConscript b/components/net/lwip-2.1.2/SConscript new file mode 100644 index 0000000000..04f59167d5 --- /dev/null +++ b/components/net/lwip-2.1.2/SConscript @@ -0,0 +1,265 @@ +from building import * + +# get current directory +cwd = GetCurrentDir() + +# 1. The minimum set of files needed for lwIP. +lwipcore_SRCS = Split(""" +src/core/init.c +src/core/def.c +src/core/dns.c +src/core/inet_chksum.c +src/core/ip.c +src/core/memp.c +src/core/netif.c +src/core/pbuf.c +src/core/raw.c +src/core/stats.c +src/core/sys.c +src/core/tcp.c +src/core/tcp_in.c +src/core/tcp_out.c +src/core/timeouts.c +src/core/udp.c +""") + +# 1.1 +lwipcore_altcp_SRCS = Split(""" +src/core/altcp.c +src/core/altcp_alloc.c +src/core/altcp_tcp.c +""") + +# 1.2 +lwipcore4_SRCS = Split(""" +src/core/ipv4/autoip.c +src/core/ipv4/dhcp.c +src/core/ipv4/etharp.c +src/core/ipv4/icmp.c +src/core/ipv4/igmp.c +src/core/ipv4/ip4_frag.c +src/core/ipv4/ip4.c +src/core/ipv4/ip4_addr.c +""") + +# 1.3 +lwipcore6_SRCS = Split(""" +src/core/ipv6/dhcp6.c +src/core/ipv6/ethip6.c +src/core/ipv6/icmp6.c +src/core/ipv6/inet6.c +src/core/ipv6/ip6.c +src/core/ipv6/ip6_addr.c +src/core/ipv6/ip6_frag.c +src/core/ipv6/mld6.c +src/core/ipv6/nd6.c +""") + +# 2. APIFILES: The files which implement the sequential and socket APIs. +lwipapi_SRCS = Split(""" +src/api/api_lib.c +src/api/api_msg.c +src/api/err.c +src/api/if_api.c +src/api/netbuf.c +src/api/netdb.c +src/api/netifapi.c +src/api/sockets.c +src/api/tcpip.c +""") + +# 3. Files implementing various generic network interface functions +lwipnetif_SRCS = Split(""" +src/netif/ethernet.c +src/netif/ethernetif.c +""") + +# 3.1 Files implementing an IEEE 802.1D bridge by using a multilayer netif approach +lwipnetif_bridgeif_SRCS = Split(""" +src/netif/bridgeif.c +src/netif/bridgeif_fdb.c +""") + +# 3.2 A generic implementation of the SLIP (Serial Line IP) protocol. +lwipnetif_slipif_SRCS = Split(""" +src/netif/slipif.c +""") + +# 4. 6LoWPAN +lwipsixlowpan_SRCS = Split(""" +src/netif/lowpan6.c +""") + +# 4.1 A 6LoWPAN over Bluetooth Low Energy (BLE) implementation as netif, +# according to RFC-7668. +lwipsixlowpan_ble_SRCS = Split(""" +src/netif/lowpan6_ble.c +""") + +# 4.2 Common 6LowPAN routines for IPv6. +lwipsixlowpan_ipv6_SRCS = Split(""" +src/netif/lowpan6_common.c +""") + +# 4.3 A netif implementing the ZigBee Encapsulation Protocol (ZEP). +lwipsixlowpan_zep_SRCS = Split(""" +src/netif/zepif.c +""") + +# 5. PPP +lwipppp_SRCS = Split(""" +src/netif/ppp/auth.c +src/netif/ppp/ccp.c +src/netif/ppp/chap-md5.c +src/netif/ppp/chap_ms.c +src/netif/ppp/chap-new.c +src/netif/ppp/demand.c +src/netif/ppp/eap.c +src/netif/ppp/ecp.c +src/netif/ppp/eui64.c +src/netif/ppp/fsm.c +src/netif/ppp/ipcp.c +src/netif/ppp/ipv6cp.c +src/netif/ppp/lcp.c +src/netif/ppp/magic.c +src/netif/ppp/mppe.c +src/netif/ppp/multilink.c +src/netif/ppp/ppp.c +src/netif/ppp/pppapi.c +src/netif/ppp/pppcrypt.c +src/netif/ppp/pppoe.c +src/netif/ppp/pppol2tp.c +src/netif/ppp/pppos.c +src/netif/ppp/upap.c +src/netif/ppp/utils.c +src/netif/ppp/vj.c +src/netif/ppp/polarssl/arc4.c +src/netif/ppp/polarssl/des.c +src/netif/ppp/polarssl/md4.c +src/netif/ppp/polarssl/md5.c +src/netif/ppp/polarssl/sha1.c +""") + +# 6. SNMPv3 agent +lwipsnmp_SRCS = Split(""" +src/apps/snmp/snmp_asn1.c +src/apps/snmp/snmp_core.c +src/apps/snmp/snmp_mib2.c +src/apps/snmp/snmp_mib2_icmp.c +src/apps/snmp/snmp_mib2_interfaces.c +src/apps/snmp/snmp_mib2_ip.c +src/apps/snmp/snmp_mib2_snmp.c +src/apps/snmp/snmp_mib2_system.c +src/apps/snmp/snmp_mib2_tcp.c +src/apps/snmp/snmp_mib2_udp.c +src/apps/snmp/snmp_snmpv2_framework.c +src/apps/snmp/snmp_snmpv2_usm.c +src/apps/snmp/snmp_msg.c +src/apps/snmp/snmpv3.c +src/apps/snmp/snmp_netconn.c +src/apps/snmp/snmp_pbuf_stream.c +src/apps/snmp/snmp_raw.c +src/apps/snmp/snmp_scalar.c +src/apps/snmp/snmp_table.c +src/apps/snmp/snmp_threadsync.c +src/apps/snmp/snmp_traps.c +""") + +# 7. HTTP server + client +lwiphttp_SRCS = Split(""" +src/apps/http/altcp_proxyconnect.c +src/apps/http/fs.c +src/apps/http/http_client.c +src/apps/http/httpd.c +""") + +# 8. MAKEFSDATA HTTP server host utility +lwipmakefsdata_SRCS = Split(""" +src/apps/http/makefsdata/makefsdata.c +""") + +# 9. IPERF server +lwipiperf_SRCS = Split(""" +src/apps/lwiperf/lwiperf.c +""") + +# 10. SMTP client +lwipsmtp_SRCS = Split(""" +src/apps/smtp/smtp.c +""") + +# 11. SNTP client +lwipsntp_SRCS = Split(""" +src/apps/sntp/sntp.c +""") + +# 12. MDNS responder +lwipmdns_SRCS = Split(""" +src/apps/mdns/mdns.c +""") + +# 13. NetBIOS name server +lwipnetbios_SRCS = Split(""" +src/apps/netbiosns/netbiosns.c +""") + +# 14. TFTP server files +lwiptftp_SRCS = Split(""" +src/apps/tftp/tftp_server.c +src/apps/tftp/tftp_port.c +""") + +# 15. MQTT client files +lwipmqtt_SRCS = Split(""" +src/apps/mqtt/mqtt.c +""") + +# 16. ARM MBEDTLS related files of lwIP rep +lwipmbedtls_SRCS = Split(""" +src/apps/altcp_tls/altcp_tls_mbedtls.c +src/apps/altcp_tls/altcp_tls_mbedtls_mem.c +src/apps/snmp/snmpv3_mbedtls.c +""") + +# 17. ping +lwipping_SRCS = Split(""" +src/apps/ping/ping.c +""") + +src = Split(""" +src/arch/sys_arch.c +""") + +src += lwipcore_SRCS # rm mem.c +src += lwipcore_altcp_SRCS +src += lwipapi_SRCS +src += lwipnetif_SRCS +src += lwipsixlowpan_SRCS + +src += lwipcore4_SRCS + +path = [cwd + '/src', + cwd + '/src/include', + cwd + '/src/arch/include', + cwd + '/src/include/netif'] + +if not GetDepend('RT_USING_SAL'): + path += [cwd + '/src/include/compat/posix'] + +if GetDepend(['RT_LWIP_SNMP']): + src += lwipsnmp_SRCS + path += [cwd + '/src/apps/snmp'] + +if GetDepend(['RT_LWIP_PPP']): + src += lwipppp_SRCS + path += [cwd + '/src/netif/ppp'] + +if GetDepend(['RT_USING_LWIP_IPV6']): + src += lwipcore6_SRCS + +if GetDepend(['RT_LWIP_USING_PING']): + src += lwipping_SRCS + +group = DefineGroup('lwIP', src, depend = ['RT_USING_LWIP', 'RT_USING_LWIP212'], CPPPATH = path) + +Return('group') diff --git a/components/net/lwip-2.1.2/src/apps/ping/ping.c b/components/net/lwip-2.1.2/src/apps/ping/ping.c new file mode 100644 index 0000000000..6d3cfe0fc3 --- /dev/null +++ b/components/net/lwip-2.1.2/src/apps/ping/ping.c @@ -0,0 +1,245 @@ +/* + * netutils: ping implementation + */ + +#include + +#ifdef RT_LWIP_ICMP /* don't build if not configured for use in rtconfig.h */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * PING_DEBUG: Enable debugging for PING. + */ +#ifndef PING_DEBUG +#define PING_DEBUG LWIP_DBG_ON +#endif + +/** ping receive timeout - in milliseconds */ +#define PING_RCV_TIMEO (2 * RT_TICK_PER_SECOND) +/** ping delay - in milliseconds */ +#define PING_DELAY (1 * RT_TICK_PER_SECOND) + +/** ping identifier - must fit on a u16_t */ +#ifndef PING_ID +#define PING_ID 0xAFAF +#endif + +/** ping additional data size to include in the packet */ +#ifndef PING_DATA_SIZE +#define PING_DATA_SIZE 32 +#endif + +/* ping variables */ +static u16_t ping_seq_num; +struct _ip_addr +{ + rt_uint8_t addr0, addr1, addr2, addr3; +}; + +/** Prepare a echo ICMP request */ +static void ping_prepare_echo( struct icmp_echo_hdr *iecho, u16_t len) +{ + size_t i; + size_t data_len = len - sizeof(struct icmp_echo_hdr); + + ICMPH_TYPE_SET(iecho, ICMP_ECHO); + ICMPH_CODE_SET(iecho, 0); + iecho->chksum = 0; + iecho->id = PING_ID; + iecho->seqno = htons(++ping_seq_num); + + /* fill the additional data buffer with some data */ + for (i = 0; i < data_len; i++) + { + ((char*) iecho)[sizeof(struct icmp_echo_hdr) + i] = (char) i; + } + +#ifdef RT_LWIP_USING_HW_CHECKSUM + iecho->chksum = 0; +#else + iecho->chksum = inet_chksum(iecho, len); +#endif + +} + +/* Ping using the socket ip */ +err_t lwip_ping_send(int s, ip_addr_t *addr, int size) +{ + int err; + struct icmp_echo_hdr *iecho; + struct sockaddr_in to; + int ping_size = sizeof(struct icmp_echo_hdr) + size; + LWIP_ASSERT("ping_size is too big", ping_size <= 0xffff); + + iecho = rt_malloc(ping_size); + if (iecho == RT_NULL) + { + return ERR_MEM; + } + + ping_prepare_echo(iecho, (u16_t) ping_size); + + to.sin_len = sizeof(to); + to.sin_family = AF_INET; +#if LWIP_IPV4 && LWIP_IPV6 + to.sin_addr.s_addr = addr->u_addr.ip4.addr; +#elif LWIP_IPV4 + to.sin_addr.s_addr = addr->addr; +#elif LWIP_IPV6 +#error Not supported IPv6. +#endif + + err = lwip_sendto(s, iecho, ping_size, 0, (struct sockaddr*) &to, sizeof(to)); + rt_free(iecho); + + return (err == ping_size ? ERR_OK : ERR_VAL); +} + +int lwip_ping_recv(int s, int *ttl) +{ + char buf[64]; + int fromlen = sizeof(struct sockaddr_in), len; + struct sockaddr_in from; + struct ip_hdr *iphdr; + struct icmp_echo_hdr *iecho; + + while ((len = lwip_recvfrom(s, buf, sizeof(buf), 0, (struct sockaddr*) &from, (socklen_t*) &fromlen)) > 0) + { + if (len >= (int)(sizeof(struct ip_hdr) + sizeof(struct icmp_echo_hdr))) + { + iphdr = (struct ip_hdr *) buf; + iecho = (struct icmp_echo_hdr *) (buf + (IPH_HL(iphdr) * 4)); + if ((iecho->id == PING_ID) && (iecho->seqno == htons(ping_seq_num))) + { + *ttl = iphdr->_ttl; + return len; + } + } + } + + return len; +} + +#ifndef RT_USING_NETDEV + +/* using the lwIP custom ping */ +rt_err_t ping(char* target_name, rt_uint32_t times, rt_size_t size) +{ +#if LWIP_VERSION_MAJOR >= 2U + struct timeval timeout = { PING_RCV_TIMEO / RT_TICK_PER_SECOND, PING_RCV_TIMEO % RT_TICK_PER_SECOND }; +#else + int timeout = PING_RCV_TIMEO * 1000UL / RT_TICK_PER_SECOND; +#endif + + int s, ttl, recv_len; + ip_addr_t target_addr; + rt_uint32_t send_times; + rt_tick_t recv_start_tick; + struct addrinfo hint, *res = NULL; + struct sockaddr_in *h = NULL; + struct in_addr ina; + + send_times = 0; + ping_seq_num = 0; + + if (size == 0) + { + size = PING_DATA_SIZE; + } + + memset(&hint, 0, sizeof(hint)); + /* convert URL to IP */ + if (lwip_getaddrinfo(target_name, NULL, &hint, &res) != 0) + { + rt_kprintf("ping: unknown host %s\n", target_name); + return -RT_ERROR; + } + memcpy(&h, &res->ai_addr, sizeof(struct sockaddr_in *)); + memcpy(&ina, &h->sin_addr, sizeof(ina)); + lwip_freeaddrinfo(res); + if (inet_aton(inet_ntoa(ina), &target_addr) == 0) + { + rt_kprintf("ping: unknown host %s\n", target_name); + return -RT_ERROR; + } + /* new a socket */ + if ((s = lwip_socket(AF_INET, SOCK_RAW, IP_PROTO_ICMP)) < 0) + { + rt_kprintf("ping: create socket failed\n"); + return -RT_ERROR; + } + + lwip_setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)); + + while (1) + { + int elapsed_time; + + if (lwip_ping_send(s, &target_addr, size) == ERR_OK) + { + recv_start_tick = rt_tick_get(); + if ((recv_len = lwip_ping_recv(s, &ttl)) >= 0) + { + elapsed_time = (rt_tick_get() - recv_start_tick) * 1000UL / RT_TICK_PER_SECOND; + rt_kprintf("%d bytes from %s icmp_seq=%d ttl=%d time=%d ms\n", recv_len, inet_ntoa(ina), send_times, + ttl, elapsed_time); + } + else + { + rt_kprintf("From %s icmp_seq=%d timeout\n", inet_ntoa(ina), send_times); + } + } + else + { + rt_kprintf("Send %s - error\n", inet_ntoa(ina)); + } + + send_times++; + if (send_times >= times) + { + /* send ping times reached, stop */ + break; + } + + rt_thread_delay(PING_DELAY); /* take a delay */ + } + + lwip_close(s); + + return RT_EOK; +} +#ifdef RT_USING_FINSH +#include + +FINSH_FUNCTION_EXPORT(ping, ping network host); + +int cmd_ping(int argc, char **argv) +{ + if (argc == 1) + { + rt_kprintf("Please input: ping \n"); + } + else + { + ping(argv[1], 4, 0); + } + + return 0; +} +FINSH_FUNCTION_EXPORT_ALIAS(cmd_ping, __cmd_ping, ping network host); +#endif /* RT_USING_FINSH */ + +#endif /* RT_USING_NETDEV */ + +#endif /* RT_LWIP_ICMP */ + diff --git a/components/net/lwip-2.1.2/src/apps/tftp/tftp_port.c b/components/net/lwip-2.1.2/src/apps/tftp/tftp_port.c new file mode 100644 index 0000000000..129cc7da17 --- /dev/null +++ b/components/net/lwip-2.1.2/src/apps/tftp/tftp_port.c @@ -0,0 +1,87 @@ +/* + * File : tftp_port.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2017, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + * 2017-08-17 armink first version. + */ + + +#include +#include +#include + +static struct tftp_context ctx; + +static void* tftp_open(const char* fname, const char* mode, u8_t write) +{ + int fd = -1; + + if (!rt_strcmp(mode, "octet")) + { + if (write) + { + fd = open(fname, O_WRONLY | O_CREAT, 0); + } + else + { + fd = open(fname, O_RDONLY, 0); + } + } + else + { + rt_kprintf("tftp: No support this mode(%s).", mode); + } + + return (void *) fd; +} + +static int tftp_write(void* handle, struct pbuf* p) +{ + int fd = (int) handle; + + return write(fd, p->payload, p->len); +} + +#if defined(RT_USING_FINSH) +#include + +static void tftp_server(uint8_t argc, char **argv) +{ + ctx.open = tftp_open; + ctx.close = (void (*)(void *)) close; + ctx.read = (int (*)(void *, void *, int)) read; + ctx.write = tftp_write; + + if (tftp_init(&ctx) == ERR_OK) + { + rt_kprintf("TFTP server start successfully.\n"); + } + else + { + rt_kprintf("TFTP server start failed.\n"); + } +} +FINSH_FUNCTION_EXPORT(tftp_server, start tftp server.); + +#if defined(FINSH_USING_MSH) +MSH_CMD_EXPORT(tftp_server, start tftp server.); +#endif /* defined(FINSH_USING_MSH) */ + +#endif /* defined(RT_USING_FINSH) */ diff --git a/components/net/lwip-2.1.2/src/arch/include/arch/bpstruct.h b/components/net/lwip-2.1.2/src/arch/include/arch/bpstruct.h new file mode 100644 index 0000000000..74ead358fa --- /dev/null +++ b/components/net/lwip-2.1.2/src/arch/include/arch/bpstruct.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#if defined(__ICCARM__) +#pragma pack(1) +#endif diff --git a/components/net/lwip-2.1.2/src/arch/include/arch/cc.h b/components/net/lwip-2.1.2/src/arch/include/arch/cc.h new file mode 100644 index 0000000000..c1b4cf7d29 --- /dev/null +++ b/components/net/lwip-2.1.2/src/arch/include/arch/cc.h @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2001, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + * $Id: cc.h,v 1.1.1.1 2004/12/16 14:17:13 bear Exp $ + */ +#ifndef __ARCH_CC_H__ +#define __ARCH_CC_H__ + +#include +#include + +#define U16_F "hu" +#define S16_F "hd" +#define X16_F "hx" +#define U32_F "lu" +#define S32_F "ld" +#define X32_F "lx" + +#ifdef RT_USING_LIBC +#if defined(__CC_ARM) || defined(__CLANG_ARM) || defined(__IAR_SYSTEMS_ICC__) +#include +#else +#include +/* some errno not defined in newlib */ +#define ENSRNOTFOUND 163 /* Domain name not found */ +/* WARNING: ESHUTDOWN also not defined in newlib. We chose + 180 here because the number "108" which is used + in arch.h has been assigned to another error code. */ +#define ESHUTDOWN 180 +#endif /* __CC_ARM/__IAR_SYSTEMS_ICC__ */ +#endif /* RT_USING_LIBC */ + +#if defined(RT_USING_LIBC) || defined(RT_USING_MINILIBC) || defined(RT_LIBC_USING_TIME) +#include +#define LWIP_TIMEVAL_PRIVATE 0 +#else +#define LWIP_TIMEVAL_PRIVATE 1 +#endif + +#if defined(__CC_ARM) /* ARMCC compiler */ +#define PACK_STRUCT_FIELD(x) x +#define PACK_STRUCT_STRUCT __attribute__ ((__packed__)) +#define PACK_STRUCT_BEGIN +#define PACK_STRUCT_END +#elif defined(__IAR_SYSTEMS_ICC__) /* IAR Compiler */ +#define PACK_STRUCT_BEGIN +#define PACK_STRUCT_STRUCT +#define PACK_STRUCT_END +#define PACK_STRUCT_FIELD(x) x +#define PACK_STRUCT_USE_INCLUDES +#elif defined(__GNUC__) /* GNU GCC Compiler */ +#define PACK_STRUCT_FIELD(x) x +#define PACK_STRUCT_STRUCT __attribute__((packed)) +#define PACK_STRUCT_BEGIN +#define PACK_STRUCT_END +#elif defined(_MSC_VER) +#define PACK_STRUCT_FIELD(x) x +#define PACK_STRUCT_STRUCT +#define PACK_STRUCT_BEGIN +#define PACK_STRUCT_END +#endif + +void sys_arch_assert(const char* file, int line); +#define LWIP_PLATFORM_DIAG(x) do {rt_kprintf x;} while(0) +#define LWIP_PLATFORM_ASSERT(x) do {rt_kprintf(x); sys_arch_assert(__FILE__, __LINE__);}while(0) + +#include "string.h" + +#define SYS_ARCH_DECL_PROTECT(level) +#define SYS_ARCH_PROTECT(level) rt_enter_critical() +#define SYS_ARCH_UNPROTECT(level) rt_exit_critical() + +#endif /* __ARCH_CC_H__ */ + diff --git a/components/net/lwip-2.1.2/src/arch/include/arch/epstruct.h b/components/net/lwip-2.1.2/src/arch/include/arch/epstruct.h new file mode 100644 index 0000000000..f6390959ea --- /dev/null +++ b/components/net/lwip-2.1.2/src/arch/include/arch/epstruct.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2001-2003 Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + */ + +#if defined(__ICCARM__) +#pragma pack() +#endif diff --git a/components/net/lwip-2.1.2/src/arch/include/arch/perf.h b/components/net/lwip-2.1.2/src/arch/include/arch/perf.h new file mode 100644 index 0000000000..675f1f65dc --- /dev/null +++ b/components/net/lwip-2.1.2/src/arch/include/arch/perf.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2001, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + * $Id: perf.h,v 1.1.1.1 2004/12/16 14:17:13 bear Exp $ + */ +#ifndef __ARCH_PERF_H__ +#define __ARCH_PERF_H__ + +//#include + +#define PERF_START /* null definition */ +#define PERF_STOP(x) /* null definition */ + +/* +void perf_print(unsigned long c1l, unsigned long c1h, + unsigned long c2l, unsigned long c2h, + char *key); + +void perf_print_times(struct tms *start, struct tms *end, char *key); + +void perf_init(char *fname); +*/ +#endif /* __ARCH_PERF_H__ */ diff --git a/components/net/lwip-2.1.2/src/arch/include/arch/sys_arch.h b/components/net/lwip-2.1.2/src/arch/include/arch/sys_arch.h new file mode 100644 index 0000000000..1e97f8a5ac --- /dev/null +++ b/components/net/lwip-2.1.2/src/arch/include/arch/sys_arch.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2001, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + * $Id: sys_arch.h,v 1.3 2005/03/13 16:03:23 bear Exp $ + */ +#ifndef __ARCH_SYS_ARCH_H__ +#define __ARCH_SYS_ARCH_H__ + +#include "arch/cc.h" + +#include + +#ifndef BYTE_ORDER +#define BYTE_ORDER LITTLE_ENDIAN +#endif + +#define SYS_MBOX_NULL RT_NULL +#define SYS_SEM_NULL RT_NULL + +typedef u32_t sys_prot_t; + +#define SYS_MBOX_SIZE 10 +#define SYS_LWIP_TIMER_NAME "timer" +#define SYS_LWIP_MBOX_NAME "mbox" +#define SYS_LWIP_SEM_NAME "sem" +#define SYS_LWIP_MUTEX_NAME "mu" + +typedef rt_sem_t sys_sem_t; +typedef rt_mutex_t sys_mutex_t; +typedef rt_mailbox_t sys_mbox_t; +typedef rt_thread_t sys_thread_t; + +// err_t sys_mbox_trypost_fromisr(sys_mbox_t *q, void *msg); + +#endif /* __ARCH_SYS_ARCH_H__ */ diff --git a/components/net/lwip-2.1.2/src/arch/sys_arch.c b/components/net/lwip-2.1.2/src/arch/sys_arch.c new file mode 100644 index 0000000000..0633501bb6 --- /dev/null +++ b/components/net/lwip-2.1.2/src/arch/sys_arch.c @@ -0,0 +1,844 @@ +/* + * COPYRIGHT (C) 2006-2018, RT-Thread Development Team + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * Change Logs: + * Date Author Notes + * 2012-12-8 Bernard add file header + * export bsd socket symbol for RT-Thread Application Module + * 2017-11-15 Bernard add lock for init_done callback. + * 2018-11-02 MurphyZhao port to lwip2.1.0 + */ + +#include + +#include "lwip/sys.h" +#include "lwip/opt.h" +#include "lwip/stats.h" +#include "lwip/err.h" +#include "arch/sys_arch.h" +#include "lwip/debug.h" +#include "lwip/netif.h" +#include "lwip/netifapi.h" +#include "lwip/tcpip.h" +#include "netif/ethernetif.h" +#include "lwip/sio.h" +#include "lwip/init.h" +#include "lwip/dhcp.h" +#include "lwip/inet.h" + +#include "netif/etharp.h" + +#include +#include + +/* + * Initialize the network interface device + * + * @return the operation status, ERR_OK on OK, ERR_IF on error + */ +static err_t netif_device_init(struct netif *netif) +{ + struct eth_device *ethif; + + ethif = (struct eth_device *)netif->state; + if (ethif != RT_NULL) + { + rt_device_t device; + + /* get device object */ + device = (rt_device_t) ethif; + if (rt_device_init(device) != RT_EOK) + { + return ERR_IF; + } + + /* copy device flags to netif flags */ + netif->flags = ethif->flags; + netif->mtu = ETHERNET_MTU; + + /* set output */ + netif->output = etharp_output; + + return ERR_OK; + } + + return ERR_IF; +} +/* + * Initialize the ethernetif layer and set network interface device up + */ +static void tcpip_init_done_callback(void *arg) +{ + rt_device_t device; + struct eth_device *ethif; + ip4_addr_t ipaddr, netmask, gw; + struct rt_list_node* node; + struct rt_object* object; + struct rt_object_information *information; + + LWIP_ASSERT("invalid arg.\n",arg); + + IP4_ADDR(&gw, 0,0,0,0); + IP4_ADDR(&ipaddr, 0,0,0,0); + IP4_ADDR(&netmask, 0,0,0,0); + + /* enter critical */ + rt_enter_critical(); + + /* for each network interfaces */ + information = rt_object_get_information(RT_Object_Class_Device); + RT_ASSERT(information != RT_NULL); + for (node = information->object_list.next; + node != &(information->object_list); + node = node->next) + { + object = rt_list_entry(node, struct rt_object, list); + device = (rt_device_t)object; + if (device->type == RT_Device_Class_NetIf) + { + ethif = (struct eth_device *)device; + + /* leave critical */ + rt_exit_critical(); + LOCK_TCPIP_CORE(); + + netif_add(ethif->netif, &ipaddr, &netmask, &gw, + ethif, netif_device_init, tcpip_input); + + if (netif_default == RT_NULL) + netif_set_default(ethif->netif); + +#if LWIP_DHCP + /* set interface up */ + netif_set_up(ethif->netif); + /* if this interface uses DHCP, start the DHCP client */ + dhcp_start(ethif->netif); +#else + /* set interface up */ + netif_set_up(ethif->netif); +#endif + + if (ethif->flags & ETHIF_LINK_PHYUP) + { + netif_set_link_up(ethif->netif); + } + + UNLOCK_TCPIP_CORE(); + /* enter critical */ + rt_enter_critical(); + } + } + + /* leave critical */ + rt_exit_critical(); + rt_sem_release((rt_sem_t)arg); +} + +/** + * LwIP system initialization + */ +extern int eth_system_device_init_private(void); +int lwip_system_init(void) +{ + rt_err_t rc; + struct rt_semaphore done_sem; + static rt_bool_t init_ok = RT_FALSE; + + if (init_ok) + { + rt_kprintf("lwip system already init.\n"); + return 0; + } + + eth_system_device_init_private(); + + /* set default netif to NULL */ + netif_default = RT_NULL; + + rc = rt_sem_init(&done_sem, "done", 0, RT_IPC_FLAG_FIFO); + + if (rc != RT_EOK) + { + LWIP_ASSERT("Failed to create semaphore", 0); + + return -1; + } + + tcpip_init(tcpip_init_done_callback, (void *)&done_sem); + + /* waiting for initialization done */ + if (rt_sem_take(&done_sem, RT_WAITING_FOREVER) != RT_EOK) + { + rt_sem_detach(&done_sem); + + return -1; + } + rt_sem_detach(&done_sem); + + /* set default ip address */ +#if !LWIP_DHCP + if (netif_default != RT_NULL) + { + struct ip4_addr ipaddr, netmask, gw; + + ipaddr.addr = inet_addr(RT_LWIP_IPADDR); + gw.addr = inet_addr(RT_LWIP_GWADDR); + netmask.addr = inet_addr(RT_LWIP_MSKADDR); + + netifapi_netif_set_addr(netif_default, &ipaddr, &netmask, &gw); + } +#endif + rt_kprintf("lwIP-%d.%d.%d initialized!\n", LWIP_VERSION_MAJOR, LWIP_VERSION_MINOR, LWIP_VERSION_REVISION); + + init_ok = RT_TRUE; + + return 0; +} +INIT_PREV_EXPORT(lwip_system_init); + +void sys_init(void) +{ + /* nothing on RT-Thread porting */ +} + +void lwip_sys_init(void) +{ + lwip_system_init(); +} + +/* + * Create a new semaphore + * + * @return the operation status, ERR_OK on OK; others on error + */ +err_t sys_sem_new(sys_sem_t *sem, u8_t count) +{ + static unsigned short counter = 0; + char tname[RT_NAME_MAX]; + sys_sem_t tmpsem; + + RT_DEBUG_NOT_IN_INTERRUPT; + + rt_snprintf(tname, RT_NAME_MAX, "%s%d", SYS_LWIP_SEM_NAME, counter); + counter ++; + + tmpsem = rt_sem_create(tname, count, RT_IPC_FLAG_FIFO); + if (tmpsem == RT_NULL) + return ERR_MEM; + else + { + *sem = tmpsem; + + return ERR_OK; + } +} + +/* + * Deallocate a semaphore + */ +void sys_sem_free(sys_sem_t *sem) +{ + RT_DEBUG_NOT_IN_INTERRUPT; + rt_sem_delete(*sem); +} + +/* + * Signal a semaphore + */ +void sys_sem_signal(sys_sem_t *sem) +{ + rt_sem_release(*sem); +} + +/* + * Block the thread while waiting for the semaphore to be signaled + * + * @return If the timeout argument is non-zero, it will return the number of milliseconds + * spent waiting for the semaphore to be signaled; If the semaphore isn't signaled + * within the specified time, it will return SYS_ARCH_TIMEOUT; If the thread doesn't + * wait for the semaphore, it will return zero + */ +u32_t sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout) +{ + rt_err_t ret; + s32_t t; + u32_t tick; + + RT_DEBUG_NOT_IN_INTERRUPT; + + /* get the begin tick */ + tick = rt_tick_get(); + if (timeout == 0) + t = RT_WAITING_FOREVER; + else + { + /* convert msecond to os tick */ + if (timeout < (1000/RT_TICK_PER_SECOND)) + t = 1; + else + t = timeout / (1000/RT_TICK_PER_SECOND); + } + + ret = rt_sem_take(*sem, t); + + if (ret == -RT_ETIMEOUT) + return SYS_ARCH_TIMEOUT; + else + { + if (ret == RT_EOK) + ret = 1; + } + + /* get elapse msecond */ + tick = rt_tick_get() - tick; + + /* convert tick to msecond */ + tick = tick * (1000 / RT_TICK_PER_SECOND); + if (tick == 0) + tick = 1; + + return tick; +} + +#ifndef sys_sem_valid +/** Check if a semaphore is valid/allocated: + * return 1 for valid, 0 for invalid + */ +int sys_sem_valid(sys_sem_t *sem) +{ + return (int)(*sem); +} +#endif + +#ifndef sys_sem_set_invalid +/** Set a semaphore invalid so that sys_sem_valid returns 0 + */ +void sys_sem_set_invalid(sys_sem_t *sem) +{ + *sem = RT_NULL; +} +#endif + +/* ====================== Mutex ====================== */ + +/** Create a new mutex + * @param mutex pointer to the mutex to create + * @return a new mutex + */ +err_t sys_mutex_new(sys_mutex_t *mutex) +{ + static unsigned short counter = 0; + char tname[RT_NAME_MAX]; + sys_mutex_t tmpmutex; + + RT_DEBUG_NOT_IN_INTERRUPT; + + rt_snprintf(tname, RT_NAME_MAX, "%s%d", SYS_LWIP_MUTEX_NAME, counter); + counter ++; + + tmpmutex = rt_mutex_create(tname, RT_IPC_FLAG_FIFO); + if (tmpmutex == RT_NULL) + return ERR_MEM; + else + { + *mutex = tmpmutex; + + return ERR_OK; + } +} + +/** Lock a mutex + * @param mutex the mutex to lock + */ +void sys_mutex_lock(sys_mutex_t *mutex) +{ + RT_DEBUG_NOT_IN_INTERRUPT; + rt_mutex_take(*mutex, RT_WAITING_FOREVER); + + return; +} + +/** Unlock a mutex + * @param mutex the mutex to unlock + */ +void sys_mutex_unlock(sys_mutex_t *mutex) +{ + rt_mutex_release(*mutex); +} + +/** Delete a semaphore + * @param mutex the mutex to delete + */ +void sys_mutex_free(sys_mutex_t *mutex) +{ + RT_DEBUG_NOT_IN_INTERRUPT; + + rt_mutex_delete(*mutex); +} + +#ifndef sys_mutex_valid +/** Check if a mutex is valid/allocated: + * return 1 for valid, 0 for invalid + */ +int sys_mutex_valid(sys_mutex_t *mutex) +{ + return (int)(*mutex); +} +#endif + +#ifndef sys_mutex_set_invalid +/** Set a mutex invalid so that sys_mutex_valid returns 0 + */ +void sys_mutex_set_invalid(sys_mutex_t *mutex) +{ + *mutex = RT_NULL; +} +#endif + +/* ====================== Mailbox ====================== */ + +/* + * Create an empty mailbox for maximum "size" elements + * + * @return the operation status, ERR_OK on OK; others on error + */ +err_t sys_mbox_new(sys_mbox_t *mbox, int size) +{ + static unsigned short counter = 0; + char tname[RT_NAME_MAX]; + sys_mbox_t tmpmbox; + + RT_DEBUG_NOT_IN_INTERRUPT; + + rt_snprintf(tname, RT_NAME_MAX, "%s%d", SYS_LWIP_MBOX_NAME, counter); + counter ++; + + tmpmbox = rt_mb_create(tname, size, RT_IPC_FLAG_FIFO); + if (tmpmbox != RT_NULL) + { + *mbox = tmpmbox; + + return ERR_OK; + } + + return ERR_MEM; +} + +/* + * Deallocate a mailbox + */ +void sys_mbox_free(sys_mbox_t *mbox) +{ + RT_DEBUG_NOT_IN_INTERRUPT; + + rt_mb_delete(*mbox); + + return; +} + +/** Post a message to an mbox - may not fail + * -> blocks if full, only used from tasks not from ISR + * @param mbox mbox to posts the message + * @param msg message to post (ATTENTION: can be NULL) + */ +void sys_mbox_post(sys_mbox_t *mbox, void *msg) +{ + RT_DEBUG_NOT_IN_INTERRUPT; + + rt_mb_send_wait(*mbox, (rt_uint32_t)msg, RT_WAITING_FOREVER); + + return; +} + +/* + * Try to post the "msg" to the mailbox + * + * @return return ERR_OK if the "msg" is posted, ERR_MEM if the mailbox is full + */ +err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg) +{ + if (rt_mb_send(*mbox, (rt_uint32_t)msg) == RT_EOK) + return ERR_OK; + + return ERR_MEM; +} + +err_t +sys_mbox_trypost_fromisr(sys_mbox_t *q, void *msg) +{ + return sys_mbox_trypost(q, msg); +} + +/** Wait for a new message to arrive in the mbox + * @param mbox mbox to get a message from + * @param msg pointer where the message is stored + * @param timeout maximum time (in milliseconds) to wait for a message + * @return time (in milliseconds) waited for a message, may be 0 if not waited + or SYS_ARCH_TIMEOUT on timeout + * The returned time has to be accurate to prevent timer jitter! + */ +u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout) +{ + rt_err_t ret; + s32_t t; + u32_t tick; + + RT_DEBUG_NOT_IN_INTERRUPT; + + /* get the begin tick */ + tick = rt_tick_get(); + + if(timeout == 0) + t = RT_WAITING_FOREVER; + else + { + /* convirt msecond to os tick */ + if (timeout < (1000/RT_TICK_PER_SECOND)) + t = 1; + else + t = timeout / (1000/RT_TICK_PER_SECOND); + } + + ret = rt_mb_recv(*mbox, (rt_ubase_t *)msg, t); + if(ret != RT_EOK) + { + return SYS_ARCH_TIMEOUT; + } + + /* get elapse msecond */ + tick = rt_tick_get() - tick; + + /* convert tick to msecond */ + tick = tick * (1000 / RT_TICK_PER_SECOND); + if (tick == 0) + tick = 1; + + return tick; +} + +/** Wait for a new message to arrive in the mbox + * @param mbox mbox to get a message from + * @param msg pointer where the message is stored + * @param timeout maximum time (in milliseconds) to wait for a message + * @return 0 (milliseconds) if a message has been received + * or SYS_MBOX_EMPTY if the mailbox is empty + */ +u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg) +{ + int ret; + + ret = rt_mb_recv(*mbox, (rt_ubase_t *)msg, 0); + + if(ret == -RT_ETIMEOUT) + return SYS_ARCH_TIMEOUT; + else + { + if (ret == RT_EOK) + ret = 1; + } + + return ret; +} + +#ifndef sys_mbox_valid +/** Check if an mbox is valid/allocated: + * return 1 for valid, 0 for invalid + */ +int sys_mbox_valid(sys_mbox_t *mbox) +{ + return (int)(*mbox); +} +#endif + +#ifndef sys_mbox_set_invalid +/** Set an mbox invalid so that sys_mbox_valid returns 0 + */ +void sys_mbox_set_invalid(sys_mbox_t *mbox) +{ + *mbox = RT_NULL; +} +#endif + +/* ====================== System ====================== */ + +/* + * Start a new thread named "name" with priority "prio" that will begin + * its execution in the function "thread()". The "arg" argument will be + * passed as an argument to the thread() function + */ +sys_thread_t sys_thread_new(const char *name, + lwip_thread_fn thread, + void *arg, + int stacksize, + int prio) +{ + rt_thread_t t; + + RT_DEBUG_NOT_IN_INTERRUPT; + + /* create thread */ + t = rt_thread_create(name, thread, arg, stacksize, prio, 20); + RT_ASSERT(t != RT_NULL); + + /* startup thread */ + rt_thread_startup(t); + + return t; +} + +sys_prot_t sys_arch_protect(void) +{ + rt_base_t level; + + /* disable interrupt */ + level = rt_hw_interrupt_disable(); + + return level; +} + +void sys_arch_unprotect(sys_prot_t pval) +{ + /* enable interrupt */ + rt_hw_interrupt_enable(pval); + + return; +} + +void sys_arch_assert(const char *file, int line) +{ + rt_kprintf("\nAssertion: %d in %s, thread %s\n", + line, file, rt_thread_self()->name); + RT_ASSERT(0); +} + +u32_t sys_jiffies(void) +{ + return rt_tick_get(); +} + +u32_t sys_now(void) +{ + return rt_tick_get() * (1000 / RT_TICK_PER_SECOND); +} + +#if MEM_OVERFLOW_CHECK || MEMP_OVERFLOW_CHECK +/** + * Check if a mep element was victim of an overflow or underflow + * (e.g. the restricted area after/before it has been altered) + * + * @param p the mem element to check + * @param size allocated size of the element + * @param descr1 description of the element source shown on error + * @param descr2 description of the element source shown on error + */ +void +mem_overflow_check_raw(void *p, size_t size, const char *descr1, const char *descr2) +{ +#if MEM_SANITY_REGION_AFTER_ALIGNED || MEM_SANITY_REGION_BEFORE_ALIGNED + u16_t k; + u8_t *m; + +#if MEM_SANITY_REGION_AFTER_ALIGNED > 0 + m = (u8_t *)p + size; + for (k = 0; k < MEM_SANITY_REGION_AFTER_ALIGNED; k++) { + if (m[k] != 0xcd) { + char errstr[128]; + snprintf(errstr, sizeof(errstr), "detected mem overflow in %s%s", descr1, descr2); + LWIP_ASSERT(errstr, 0); + } + } +#endif /* MEM_SANITY_REGION_AFTER_ALIGNED > 0 */ + +#if MEM_SANITY_REGION_BEFORE_ALIGNED > 0 + m = (u8_t *)p - MEM_SANITY_REGION_BEFORE_ALIGNED; + for (k = 0; k < MEM_SANITY_REGION_BEFORE_ALIGNED; k++) { + if (m[k] != 0xcd) { + char errstr[128]; + snprintf(errstr, sizeof(errstr), "detected mem underflow in %s%s", descr1, descr2); + LWIP_ASSERT(errstr, 0); + } + } +#endif /* MEM_SANITY_REGION_BEFORE_ALIGNED > 0 */ +#else + LWIP_UNUSED_ARG(p); + LWIP_UNUSED_ARG(desc); + LWIP_UNUSED_ARG(descr); +#endif +} + +/** + * Initialize the restricted area of a mem element. + */ +void +mem_overflow_init_raw(void *p, size_t size) +{ +#if MEM_SANITY_REGION_BEFORE_ALIGNED > 0 || MEM_SANITY_REGION_AFTER_ALIGNED > 0 + u8_t *m; +#if MEM_SANITY_REGION_BEFORE_ALIGNED > 0 + m = (u8_t *)p - MEM_SANITY_REGION_BEFORE_ALIGNED; + memset(m, 0xcd, MEM_SANITY_REGION_BEFORE_ALIGNED); +#endif +#if MEM_SANITY_REGION_AFTER_ALIGNED > 0 + m = (u8_t *)p + size; + memset(m, 0xcd, MEM_SANITY_REGION_AFTER_ALIGNED); +#endif +#else /* MEM_SANITY_REGION_BEFORE_ALIGNED > 0 || MEM_SANITY_REGION_AFTER_ALIGNED > 0 */ + LWIP_UNUSED_ARG(p); + LWIP_UNUSED_ARG(desc); +#endif /* MEM_SANITY_REGION_BEFORE_ALIGNED > 0 || MEM_SANITY_REGION_AFTER_ALIGNED > 0 */ +} +#endif /* MEM_OVERFLOW_CHECK || MEMP_OVERFLOW_CHECK */ + +RT_WEAK +void mem_init(void) +{ +} + +void *mem_calloc(mem_size_t count, mem_size_t size) +{ + return rt_calloc(count, size); +} + +void *mem_trim(void *mem, mem_size_t size) +{ + // return rt_realloc(mem, size); + /* not support trim yet */ + return mem; +} + +void *mem_malloc(mem_size_t size) +{ + return rt_malloc(size); +} + +void mem_free(void *mem) +{ + rt_free(mem); +} + +#ifdef RT_LWIP_PPP +u32_t sio_read(sio_fd_t fd, u8_t *buf, u32_t size) +{ + u32_t len; + + RT_ASSERT(fd != RT_NULL); + + len = rt_device_read((rt_device_t)fd, 0, buf, size); + if (len <= 0) + return 0; + + return len; +} + +u32_t sio_write(sio_fd_t fd, u8_t *buf, u32_t size) +{ + RT_ASSERT(fd != RT_NULL); + + return rt_device_write((rt_device_t)fd, 0, buf, size); +} + +void sio_read_abort(sio_fd_t fd) +{ + rt_kprintf("read_abort\n"); +} + +void ppp_trace(int level, const char *format, ...) +{ + va_list args; + rt_size_t length; + static char rt_log_buf[RT_CONSOLEBUF_SIZE]; + + va_start(args, format); + length = rt_vsprintf(rt_log_buf, format, args); + rt_device_write((rt_device_t)rt_console_get_device(), 0, rt_log_buf, length); + va_end(args); +} +#endif + +/* + * export bsd socket symbol for RT-Thread Application Module + */ +#if LWIP_SOCKET +#include +RTM_EXPORT(lwip_accept); +RTM_EXPORT(lwip_bind); +RTM_EXPORT(lwip_shutdown); +RTM_EXPORT(lwip_getpeername); +RTM_EXPORT(lwip_getsockname); +RTM_EXPORT(lwip_getsockopt); +RTM_EXPORT(lwip_setsockopt); +RTM_EXPORT(lwip_close); +RTM_EXPORT(lwip_connect); +RTM_EXPORT(lwip_listen); +RTM_EXPORT(lwip_recv); +RTM_EXPORT(lwip_read); +RTM_EXPORT(lwip_recvfrom); +RTM_EXPORT(lwip_send); +RTM_EXPORT(lwip_sendto); +RTM_EXPORT(lwip_socket); +RTM_EXPORT(lwip_write); +RTM_EXPORT(lwip_select); +RTM_EXPORT(lwip_ioctl); +RTM_EXPORT(lwip_fcntl); + +RTM_EXPORT(lwip_htons); +RTM_EXPORT(lwip_htonl); + +#if LWIP_DNS +#include +RTM_EXPORT(lwip_gethostbyname); +RTM_EXPORT(lwip_gethostbyname_r); +RTM_EXPORT(lwip_freeaddrinfo); +RTM_EXPORT(lwip_getaddrinfo); +#endif + +#endif + +#if LWIP_DHCP +#include +RTM_EXPORT(dhcp_start); +RTM_EXPORT(dhcp_renew); +RTM_EXPORT(dhcp_stop); +#endif + +#if LWIP_NETIF_API +#include +RTM_EXPORT(netifapi_netif_set_addr); +#endif + +#if LWIP_NETIF_LINK_CALLBACK +RTM_EXPORT(netif_set_link_callback); +#endif + +#if LWIP_NETIF_STATUS_CALLBACK +RTM_EXPORT(netif_set_status_callback); +#endif + +RTM_EXPORT(netif_find); +RTM_EXPORT(netif_set_addr); +RTM_EXPORT(netif_set_ipaddr); +RTM_EXPORT(netif_set_gw); +RTM_EXPORT(netif_set_netmask); diff --git a/components/net/lwip-2.1.2/src/include/netif/ethernetif.h b/components/net/lwip-2.1.2/src/include/netif/ethernetif.h new file mode 100644 index 0000000000..244bafdd1b --- /dev/null +++ b/components/net/lwip-2.1.2/src/include/netif/ethernetif.h @@ -0,0 +1,52 @@ +#ifndef __NETIF_ETHERNETIF_H__ +#define __NETIF_ETHERNETIF_H__ + +#include "lwip/netif.h" +#include + +#define NIOCTL_GADDR 0x01 +#ifndef RT_LWIP_ETH_MTU +#define ETHERNET_MTU 1500 +#else +#define ETHERNET_MTU RT_LWIP_ETH_MTU +#endif + +/* eth flag with auto_linkup or phy_linkup */ +#define ETHIF_LINK_AUTOUP 0x0000 +#define ETHIF_LINK_PHYUP 0x0100 + +struct eth_device +{ + /* inherit from rt_device */ + struct rt_device parent; + + /* network interface for lwip */ + struct netif *netif; + struct rt_semaphore tx_ack; + + rt_uint16_t flags; + rt_uint8_t link_changed; + rt_uint8_t link_status; + + /* eth device interface */ + struct pbuf* (*eth_rx)(rt_device_t dev); + rt_err_t (*eth_tx)(rt_device_t dev, struct pbuf* p); +}; + +#ifdef __cplusplus +extern "C" { +#endif + + rt_err_t eth_device_ready(struct eth_device* dev); + rt_err_t eth_device_init(struct eth_device * dev, const char *name); + rt_err_t eth_device_init_with_flag(struct eth_device *dev, const char *name, rt_uint16_t flag); + rt_err_t eth_device_linkchange(struct eth_device* dev, rt_bool_t up); + void eth_device_deinit(struct eth_device *dev); + + int eth_system_device_init(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __NETIF_ETHERNETIF_H__ */ diff --git a/components/net/lwip-2.1.2/src/lwipopts.h b/components/net/lwip-2.1.2/src/lwipopts.h new file mode 100644 index 0000000000..220bb6fa41 --- /dev/null +++ b/components/net/lwip-2.1.2/src/lwipopts.h @@ -0,0 +1,644 @@ +#ifndef __LWIPOPTS_H__ +#define __LWIPOPTS_H__ + +#include + +#define ERRNO 1 + +#define LWIP_SOCKET_SELECT 1 +#define LWIP_SOCKET_POLL 1 + +#define LWIP_IPV4 1 + +#ifdef RT_USING_LWIP_IPV6 +#define LWIP_IPV6 1 +#else +#define LWIP_IPV6 0 +#endif /* RT_USING_LWIP_IPV6 */ + +#define NO_SYS 0 +#define LWIP_SOCKET 1 +#define LWIP_NETCONN 1 + +#ifdef RT_LWIP_IGMP +#define LWIP_IGMP 1 +#else +#define LWIP_IGMP 0 +#endif + +#ifdef RT_LWIP_ICMP +#define LWIP_ICMP 1 +#else +#define LWIP_ICMP 0 +#endif + +#ifdef RT_LWIP_SNMP +#define LWIP_SNMP 1 +#else +#define LWIP_SNMP 0 +#endif + +#ifdef RT_LWIP_DNS +#define LWIP_DNS 1 +#else +#define LWIP_DNS 0 +#endif + +#define LWIP_HAVE_LOOPIF 0 + +#define LWIP_PLATFORM_BYTESWAP 0 + +#ifndef BYTE_ORDER +#define BYTE_ORDER LITTLE_ENDIAN +#endif + +/* #define RT_LWIP_DEBUG */ + +#ifdef RT_LWIP_DEBUG +#define LWIP_DEBUG +#endif + +/* ---------- Debug options ---------- */ +#ifdef LWIP_DEBUG +#ifdef RT_LWIP_SYS_DEBUG +#define SYS_DEBUG LWIP_DBG_ON +#else +#define SYS_DEBUG LWIP_DBG_OFF +#endif + +#ifdef RT_LWIP_ETHARP_DEBUG +#define ETHARP_DEBUG LWIP_DBG_ON +#else +#define ETHARP_DEBUG LWIP_DBG_OFF +#endif + +#ifdef RT_LWIP_PPP_DEBUG +#define PPP_DEBUG LWIP_DBG_ON +#else +#define PPP_DEBUG LWIP_DBG_OFF +#endif + +#ifdef RT_LWIP_MEM_DEBUG +#define MEM_DEBUG LWIP_DBG_ON +#else +#define MEM_DEBUG LWIP_DBG_OFF +#endif + +#ifdef RT_LWIP_MEMP_DEBUG +#define MEMP_DEBUG LWIP_DBG_ON +#else +#define MEMP_DEBUG LWIP_DBG_OFF +#endif + +#ifdef RT_LWIP_PBUF_DEBUG +#define PBUF_DEBUG LWIP_DBG_ON +#else +#define PBUF_DEBUG LWIP_DBG_OFF +#endif + +#ifdef RT_LWIP_API_LIB_DEBUG +#define API_LIB_DEBUG LWIP_DBG_ON +#else +#define API_LIB_DEBUG LWIP_DBG_OFF +#endif + +#ifdef RT_LWIP_API_MSG_DEBUG +#define API_MSG_DEBUG LWIP_DBG_ON +#else +#define API_MSG_DEBUG LWIP_DBG_OFF +#endif + +#ifdef RT_LWIP_TCPIP_DEBUG +#define TCPIP_DEBUG LWIP_DBG_ON +#else +#define TCPIP_DEBUG LWIP_DBG_OFF +#endif + +#ifdef RT_LWIP_NETIF_DEBUG +#define NETIF_DEBUG LWIP_DBG_ON +#else +#define NETIF_DEBUG LWIP_DBG_OFF +#endif + +#ifdef RT_LWIP_SOCKETS_DEBUG +#define SOCKETS_DEBUG LWIP_DBG_ON +#else +#define SOCKETS_DEBUG LWIP_DBG_OFF +#endif + +#ifdef RT_LWIP_DNS_DEBUG +#define DNS_DEBUG LWIP_DBG_ON +#else +#define DNS_DEBUG LWIP_DBG_OFF +#endif + +#ifdef RT_LWIP_AUTOIP_DEBUG +#define AUTOIP_DEBUG LWIP_DBG_ON +#else +#define AUTOIP_DEBUG LWIP_DBG_OFF +#endif + +#ifdef RT_LWIP_DHCP_DEBUG +#define DHCP_DEBUG LWIP_DBG_ON +#else +#define DHCP_DEBUG LWIP_DBG_OFF +#endif + +#ifdef RT_LWIP_IP_DEBUG +#define IP_DEBUG LWIP_DBG_ON +#else +#define IP_DEBUG LWIP_DBG_OFF +#endif + +#ifdef RT_LWIP_IP_REASS_DEBUG +#define IP_REASS_DEBUG LWIP_DBG_ON +#else +#define IP_REASS_DEBUG LWIP_DBG_OFF +#endif + +#ifdef RT_LWIP_ICMP_DEBUG +#define ICMP_DEBUG LWIP_DBG_ON +#else +#define ICMP_DEBUG LWIP_DBG_OFF +#endif + +#ifdef RT_LWIP_IGMP_DEBUG +#define IGMP_DEBUG LWIP_DBG_ON +#else +#define IGMP_DEBUG LWIP_DBG_OFF +#endif + +#ifdef RT_LWIP_UDP_DEBUG +#define UDP_DEBUG LWIP_DBG_ON +#else +#define UDP_DEBUG LWIP_DBG_OFF +#endif + +#ifdef RT_LWIP_TCP_DEBUG +#define TCP_DEBUG LWIP_DBG_ON +#else +#define TCP_DEBUG LWIP_DBG_OFF +#endif + +#ifdef RT_LWIP_TCP_INPUT_DEBUG +#define TCP_INPUT_DEBUG LWIP_DBG_ON +#else +#define TCP_INPUT_DEBUG LWIP_DBG_OFF +#endif + +#ifdef RT_LWIP_TCP_OUTPUT_DEBUG +#define TCP_OUTPUT_DEBUG LWIP_DBG_ON +#else +#define TCP_OUTPUT_DEBUG LWIP_DBG_OFF +#endif + +#ifdef RT_LWIP_TCP_RTO_DEBUG +#define TCP_RTO_DEBUG LWIP_DBG_ON +#else +#define TCP_RTO_DEBUG LWIP_DBG_OFF +#endif + +#ifdef RT_LWIP_TCP_CWND_DEBUG +#define TCP_CWND_DEBUG LWIP_DBG_ON +#else +#define TCP_CWND_DEBUG LWIP_DBG_OFF +#endif + +#ifdef RT_LWIP_TCP_WND_DEBUG +#define TCP_WND_DEBUG LWIP_DBG_ON +#else +#define TCP_WND_DEBUG LWIP_DBG_OFF +#endif + +#ifdef RT_LWIP_TCP_FR_DEBUG +#define TCP_FR_DEBUG LWIP_DBG_ON +#else +#define TCP_FR_DEBUG LWIP_DBG_OFF +#endif + +#ifdef RT_LWIP_TCP_QLEN_DEBUG +#define TCP_QLEN_DEBUG LWIP_DBG_ON +#else +#define TCP_QLEN_DEBUG LWIP_DBG_OFF +#endif + +#ifdef RT_LWIP_TCP_RST_DEBUG +#define TCP_RST_DEBUG LWIP_DBG_ON +#else +#define TCP_RST_DEBUG LWIP_DBG_OFF +#endif + +#endif /* LWIP_DEBUG */ + +#define LWIP_DBG_TYPES_ON (LWIP_DBG_ON|LWIP_DBG_TRACE|LWIP_DBG_STATE|LWIP_DBG_FRESH|LWIP_DBG_HALT) + +# ifndef __STRICT_ANSI__ +# define SSIZE_MAX LONG_MAX +# endif + +#ifdef RT_USING_LIBC +#define LWIP_NO_UNISTD_H 0 +#else +#define LWIP_NO_UNISTD_H 1 +#endif + +/* ---------- Memory options ---------- */ +#define MEM_ALIGNMENT 4 +#define MEMP_OVERFLOW_CHECK 1 //// +#define LWIP_ALLOW_MEM_FREE_FROM_OTHER_CONTEXT 1 //// +//#define MEM_LIBC_MALLOC 1 +//#define MEM_USE_POOLS 1 +//#define MEMP_USE_CUSTOM_POOLS 1 +//#define MEM_SIZE (1024*64) + +#define MEMP_MEM_MALLOC 0 + +/* MEMP_NUM_PBUF: the number of memp struct pbufs. If the application + sends a lot of data out of ROM (or other static memory), this + should be set high. */ +#define MEMP_NUM_PBUF 32 //16 + +/* the number of struct netconns */ +#ifdef RT_MEMP_NUM_NETCONN +#define MEMP_NUM_NETCONN RT_MEMP_NUM_NETCONN +#endif + +/* the number of UDP protocol control blocks. One per active RAW "connection". */ +#ifdef RT_LWIP_RAW_PCB_NUM +#define MEMP_NUM_RAW_PCB RT_LWIP_RAW_PCB_NUM +#endif + +/* the number of UDP protocol control blocks. One per active UDP "connection". */ +#ifdef RT_LWIP_UDP_PCB_NUM +#define MEMP_NUM_UDP_PCB RT_LWIP_UDP_PCB_NUM +#endif + +/* the number of simulatenously active TCP connections. */ +#ifdef RT_LWIP_TCP_PCB_NUM +#define MEMP_NUM_TCP_PCB RT_LWIP_TCP_PCB_NUM +#endif + +/* the number of simultaneously queued TCP */ +#ifdef RT_LWIP_TCP_SEG_NUM +#define MEMP_NUM_TCP_SEG RT_LWIP_TCP_SEG_NUM +#else +#define MEMP_NUM_TCP_SEG TCP_SND_QUEUELEN +#endif + +/* + * You can re-define following setting in rtcofnig.h to overwrite the default + * setting in the lwip opts.h + */ +/* MEMP_NUM_NETBUF: the number of struct netbufs. */ +// #define MEMP_NUM_NETBUF 2 +/* MEMP_NUM_NETCONN: the number of struct netconns. */ +// #define MEMP_NUM_NETCONN 4 + +/* MEMP_NUM_TCPIP_MSG_*: the number of struct tcpip_msg, which is used + for sequential API communication and incoming packets. Used in + src/api/tcpip.c. */ +// #define MEMP_NUM_TCPIP_MSG_API 16 +// #define MEMP_NUM_TCPIP_MSG_INPKT 16 + +/* ---------- Pbuf options ---------- */ +/* PBUF_POOL_SIZE: the number of buffers in the pbuf pool. */ +#ifdef RT_LWIP_PBUF_NUM +#define PBUF_POOL_SIZE RT_LWIP_PBUF_NUM +#endif + +/* PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. */ +#ifdef RT_LWIP_PBUF_POOL_BUFSIZE +#define PBUF_POOL_BUFSIZE RT_LWIP_PBUF_POOL_BUFSIZE +#endif + +/* PBUF_LINK_HLEN: the number of bytes that should be allocated for a + link level header. */ +#define PBUF_LINK_HLEN 16 + +#ifdef RT_LWIP_ETH_PAD_SIZE +#define ETH_PAD_SIZE RT_LWIP_ETH_PAD_SIZE +#endif + +/** SYS_LIGHTWEIGHT_PROT + * define SYS_LIGHTWEIGHT_PROT in lwipopts.h if you want inter-task protection + * for certain critical regions during buffer allocation, deallocation and memory + * allocation and deallocation. + */ +#define SYS_LIGHTWEIGHT_PROT (NO_SYS==0) + +#ifdef LWIP_USING_NAT +#define IP_NAT 1 +#else +#define IP_NAT 0 +#endif + +/* ---------- TCP options ---------- */ +#ifdef RT_LWIP_TCP +#define LWIP_TCP 1 +#else +#define LWIP_TCP 0 +#endif + +#define TCP_TTL 255 + +/* Controls if TCP should queue segments that arrive out of + order. Define to 0 if your device is low on memory. */ +#define TCP_QUEUE_OOSEQ 1 + +/* TCP Maximum segment size. */ +#define TCP_MSS 1460 + +/* TCP sender buffer space (bytes). */ +#ifdef RT_LWIP_TCP_SND_BUF +#define TCP_SND_BUF RT_LWIP_TCP_SND_BUF +#else +#define TCP_SND_BUF (TCP_MSS * 2) +#endif + +/* TCP sender buffer space (pbufs). This must be at least = 2 * + TCP_SND_BUF/TCP_MSS for things to work. */ +#define TCP_SND_QUEUELEN (4 * TCP_SND_BUF/TCP_MSS) + +/* TCP writable space (bytes). This must be less than or equal + to TCP_SND_BUF. It is the amount of space which must be + available in the tcp snd_buf for select to return writable */ +#define TCP_SNDLOWAT (TCP_SND_BUF/2) +#define TCP_SNDQUEUELOWAT TCP_SND_QUEUELEN/2 + +/* TCP receive window. */ +#ifdef RT_LWIP_TCP_WND +#define TCP_WND RT_LWIP_TCP_WND +#else +#define TCP_WND (TCP_MSS * 2) +#endif + +/* Maximum number of retransmissions of data segments. */ +#define TCP_MAXRTX 12 + +/* Maximum number of retransmissions of SYN segments. */ +#define TCP_SYNMAXRTX 4 + +/* tcpip thread options */ +#ifdef RT_LWIP_TCPTHREAD_PRIORITY +#define TCPIP_MBOX_SIZE RT_LWIP_TCPTHREAD_MBOX_SIZE +#define TCPIP_THREAD_PRIO RT_LWIP_TCPTHREAD_PRIORITY +#define TCPIP_THREAD_STACKSIZE RT_LWIP_TCPTHREAD_STACKSIZE +#else +#define TCPIP_MBOX_SIZE 8 +#define TCPIP_THREAD_PRIO 128 +#define TCPIP_THREAD_STACKSIZE 4096 +#endif +#define TCPIP_THREAD_NAME "tcpip" +#define DEFAULT_TCP_RECVMBOX_SIZE 10 + +/* ---------- ARP options ---------- */ +#define LWIP_ARP 1 +#define ARP_TABLE_SIZE 10 +#define ARP_QUEUEING 1 + +/* ---------- Checksum options ---------- */ +#ifdef RT_LWIP_USING_HW_CHECKSUM +#define CHECKSUM_GEN_IP 0 +#define CHECKSUM_GEN_UDP 0 +#define CHECKSUM_GEN_TCP 0 +#define CHECKSUM_GEN_ICMP 0 +#define CHECKSUM_CHECK_IP 0 +#define CHECKSUM_CHECK_UDP 0 +#define CHECKSUM_CHECK_TCP 0 +#define CHECKSUM_CHECK_ICMP 0 +#endif + +/* ---------- IP options ---------- */ +/* Define IP_FORWARD to 1 if you wish to have the ability to forward + IP packets across network interfaces. If you are going to run lwIP + on a device with only one network interface, define this to 0. */ +#define IP_FORWARD 0 + +/* IP reassembly and segmentation.These are orthogonal even + * if they both deal with IP fragments */ +#ifdef RT_LWIP_REASSEMBLY_FRAG +#define IP_REASSEMBLY 1 +#define IP_FRAG 1 +#define IP_REASS_MAX_PBUFS 10 +#define MEMP_NUM_REASSDATA 10 +#else +#define IP_REASSEMBLY 0 +#define IP_FRAG 0 +#endif + +/* ---------- ICMP options ---------- */ +#define ICMP_TTL 255 + +/* ---------- DHCP options ---------- */ +/* Define LWIP_DHCP to 1 if you want DHCP configuration of + interfaces. */ +#ifdef RT_LWIP_DHCP +#define LWIP_DHCP 1 +#else +#define LWIP_DHCP 0 +#endif + +/* 1 if you want to do an ARP check on the offered address + (recommended). */ +#define DHCP_DOES_ARP_CHECK (LWIP_DHCP) + +/* ---------- AUTOIP options ------- */ +#define LWIP_AUTOIP 0 +#define LWIP_DHCP_AUTOIP_COOP (LWIP_DHCP && LWIP_AUTOIP) + +/* ---------- UDP options ---------- */ +#ifdef RT_LWIP_UDP +#define LWIP_UDP 1 +#else +#define LWIP_UDP 0 +#endif + +#define LWIP_UDPLITE 0 +#define UDP_TTL 255 +#define DEFAULT_UDP_RECVMBOX_SIZE 1 + +/* ---------- RAW options ---------- */ +#ifdef RT_LWIP_RAW +#define LWIP_RAW 1 +#else +#define LWIP_RAW 0 +#endif + +#define DEFAULT_RAW_RECVMBOX_SIZE 1 +#define DEFAULT_ACCEPTMBOX_SIZE 10 + +/* ---------- Statistics options ---------- */ +#ifdef RT_LWIP_STATS +#define LWIP_STATS 1 +#define LWIP_STATS_DISPLAY 1 +#else +#define LWIP_STATS 0 +#endif + +#if LWIP_STATS +#define LINK_STATS 1 +#define IP_STATS 1 +#define ICMP_STATS 1 +#define IGMP_STATS 1 +#define IPFRAG_STATS 1 +#define UDP_STATS 1 +#define TCP_STATS 1 +#define MEM_STATS 1 +#define MEMP_STATS 1 +#define PBUF_STATS 1 +#define SYS_STATS 1 +#define MIB2_STATS 1 +#endif /* LWIP_STATS */ + +/* ---------- PPP options ---------- */ +#ifdef RT_LWIP_PPP +#define PPP_SUPPORT 1 /* Set > 0 for PPP */ +#else +#define PPP_SUPPORT 0 /* Set > 0 for PPP */ +#endif + +#if PPP_SUPPORT +#define NUM_PPP 1 /* Max PPP sessions. */ + +/* Select modules to enable. Ideally these would be set in the makefile but + * we're limited by the command line length so you need to modify the settings + * in this file. + */ +#ifdef RT_LWIP_PPPOE +#define PPPOE_SUPPORT 1 +#else +#define PPPOE_SUPPORT 0 +#endif + +#ifdef RT_LWIP_PPPOS +#define PPPOS_SUPPORT 1 +#else +#define PPPOS_SUPPORT 0 +#endif + +#define PAP_SUPPORT 1 /* Set > 0 for PAP. */ +#define CHAP_SUPPORT 1 /* Set > 0 for CHAP. */ +#define MSCHAP_SUPPORT 0 /* Set > 0 for MSCHAP (NOT FUNCTIONAL!) */ +#define CBCP_SUPPORT 0 /* Set > 0 for CBCP (NOT FUNCTIONAL!) */ +#define CCP_SUPPORT 0 /* Set > 0 for CCP (NOT FUNCTIONAL!) */ +#define VJ_SUPPORT 1 /* Set > 0 for VJ header compression. */ +#define MD5_SUPPORT 1 /* Set > 0 for MD5 (see also CHAP) */ + +#endif /* PPP_SUPPORT */ + +/** + * LWIP_POSIX_SOCKETS_IO_NAMES==1: Enable POSIX-style sockets functions names. + * Disable this option if you use a POSIX operating system that uses the same + * names (read, write & close). (only used if you use sockets.c) + */ +#ifndef LWIP_POSIX_SOCKETS_IO_NAMES +#define LWIP_POSIX_SOCKETS_IO_NAMES 0 +#endif + +/** + * LWIP_TCP_KEEPALIVE==1: Enable TCP_KEEPIDLE, TCP_KEEPINTVL and TCP_KEEPCNT + * options processing. Note that TCP_KEEPIDLE and TCP_KEEPINTVL have to be set + * in seconds. (does not require sockets.c, and will affect tcp.c) + */ +#ifndef LWIP_TCP_KEEPALIVE +#define LWIP_TCP_KEEPALIVE 1 +#endif + +/** + * LWIP_NETIF_HOSTNAME==1: Support netif hostname + */ +#ifndef LWIP_NETIF_HOSTNAME +#define LWIP_NETIF_HOSTNAME 1 +#endif + +/** + * LWIP_NETIF_API==1: Support netif api (in netifapi.c) + */ +#ifndef LWIP_NETIF_API +#define LWIP_NETIF_API 1 +#endif + +#ifdef LWIP_IGMP +#include +#define LWIP_RAND rand +#endif +/* + ------------------------------------ + ---------- Socket options ---------- + ------------------------------------ +*/ +/* + * LWIP_SOCKET==1: Enable Socket API (require to use sockets.c) + */ +#ifndef LWIP_SOCKET +#define LWIP_SOCKET 1 +#endif + +/* + * LWIP_COMPAT_SOCKETS==1: Enable BSD-style sockets functions names. + * (only used if you use sockets.c) + */ +#ifdef SAL_USING_POSIX +#define LWIP_COMPAT_SOCKETS 0 +#else +#ifndef LWIP_COMPAT_SOCKETS +#define LWIP_COMPAT_SOCKETS 1 +#endif +#endif + +/** + * LWIP_SO_SNDTIMEO==1: Enable send timeout for sockets/netconns and + * SO_SNDTIMEO processing. + */ +#ifndef LWIP_SO_SNDTIMEO +#define LWIP_SO_SNDTIMEO 1 +#endif + +/** + * LWIP_SO_RCVTIMEO==1: Enable receive timeout for sockets/netconns and + * SO_RCVTIMEO processing. + */ +#ifndef LWIP_SO_RCVTIMEO +#define LWIP_SO_RCVTIMEO 1 +#endif + +/** + * LWIP_SO_RCVBUF==1: Enable SO_RCVBUF processing. + */ +#ifndef LWIP_SO_RCVBUF +#define LWIP_SO_RCVBUF 1 +#endif + +/** + * If LWIP_SO_RCVBUF is used, this is the default value for recv_bufsize. + */ +#ifndef RECV_BUFSIZE_DEFAULT +#define RECV_BUFSIZE_DEFAULT 8192 +#endif + +/** + * SO_REUSE==1: Enable SO_REUSEADDR option. + */ +#ifndef SO_REUSE +#define SO_REUSE 0 +#endif + +/* + ------------------------------------ + ------- Applications options ------- + ------------------------------------ +*/ + +/** + * Max. length of TFTP filename + */ +#ifdef RT_LWIP_TFTP_MAX_FILENAME_LEN +#define TFTP_MAX_FILENAME_LEN RT_LWIP_TFTP_MAX_FILENAME_LEN +#elif defined(RT_DFS_ELM_MAX_LFN) +#define TFTP_MAX_FILENAME_LEN RT_DFS_ELM_MAX_LFN +#else +#define TFTP_MAX_FILENAME_LEN 64 +#endif + + +#endif /* __LWIPOPTS_H__ */ diff --git a/components/net/lwip-2.1.2/src/lwippools.h b/components/net/lwip-2.1.2/src/lwippools.h new file mode 100644 index 0000000000..6583863de3 --- /dev/null +++ b/components/net/lwip-2.1.2/src/lwippools.h @@ -0,0 +1,10 @@ +#if 1 + LWIP_MALLOC_MEMPOOL_START + LWIP_MALLOC_MEMPOOL((unsigned char)128, 256) + LWIP_MALLOC_MEMPOOL((unsigned char)128, 512) + LWIP_MALLOC_MEMPOOL((unsigned char)128, 1024) + LWIP_MALLOC_MEMPOOL((unsigned char)128, 1514) + LWIP_MALLOC_MEMPOOL((unsigned char)128, 1536) + LWIP_MALLOC_MEMPOOL((unsigned char)128, 4096) + LWIP_MALLOC_MEMPOOL_END +#endif diff --git a/components/net/lwip-2.1.2/src/netif/ethernetif.c b/components/net/lwip-2.1.2/src/netif/ethernetif.c new file mode 100644 index 0000000000..8a40b29016 --- /dev/null +++ b/components/net/lwip-2.1.2/src/netif/ethernetif.c @@ -0,0 +1,1000 @@ +/* + * Copyright (c) 2001-2004 Swedish Institute of Computer Science. + * COPYRIGHT (C) 2006-2018, RT-Thread Development Team + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT + * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + * This file is part of the lwIP TCP/IP stack. + * + * Author: Adam Dunkels + * + * Change Logs: + * Date Author Notes + * 2010-07-07 Bernard fix send mail to mailbox issue. + * 2011-07-30 mbbill port lwIP 1.4.0 to RT-Thread + * 2012-04-10 Bernard add more compatible with RT-Thread. + * 2012-11-12 Bernard The network interface can be initialized + * after lwIP initialization. + * 2013-02-28 aozima fixed list_tcps bug: ipaddr_ntoa isn't reentrant. + * 2016-08-18 Bernard port to lwIP 2.0.0 + * 2018-11-02 MurphyZhao port to lwIP 2.1.0 + */ + +#include "lwip/opt.h" + +#include "lwip/opt.h" +#include "lwip/debug.h" +#include "lwip/def.h" +#include "lwip/mem.h" +#include "lwip/pbuf.h" +#include "lwip/sys.h" +#include "lwip/netif.h" +#include "lwip/stats.h" +#include "lwip/tcpip.h" +#include "lwip/dhcp.h" +#include "lwip/netifapi.h" + +#include "netif/etharp.h" +#include "netif/ethernetif.h" + +#include "lwip/inet.h" + +#if LWIP_IPV6 +#include "lwip/ethip6.h" +#endif /* LWIP_IPV6 */ + +#define netifapi_netif_set_link_up(n) netifapi_netif_common(n, netif_set_link_up, NULL) +#define netifapi_netif_set_link_down(n) netifapi_netif_common(n, netif_set_link_down, NULL) + +#ifndef RT_LWIP_ETHTHREAD_PRIORITY +#define RT_ETHERNETIF_THREAD_PREORITY 0x90 +#else +#define RT_ETHERNETIF_THREAD_PREORITY RT_LWIP_ETHTHREAD_PRIORITY +#endif + +#ifndef LWIP_NO_TX_THREAD +/** + * Tx message structure for Ethernet interface + */ +struct eth_tx_msg +{ + struct netif *netif; + struct pbuf *buf; +}; + +static struct rt_mailbox eth_tx_thread_mb; +static struct rt_thread eth_tx_thread; +#ifndef RT_LWIP_ETHTHREAD_MBOX_SIZE +static char eth_tx_thread_mb_pool[32 * 4]; +static char eth_tx_thread_stack[512]; +#else +static char eth_tx_thread_mb_pool[RT_LWIP_ETHTHREAD_MBOX_SIZE * 4]; +static char eth_tx_thread_stack[RT_LWIP_ETHTHREAD_STACKSIZE]; +#endif +#endif + +#ifndef LWIP_NO_RX_THREAD +static struct rt_mailbox eth_rx_thread_mb; +static struct rt_thread eth_rx_thread; +#ifndef RT_LWIP_ETHTHREAD_MBOX_SIZE +static char eth_rx_thread_mb_pool[48 * 4]; +static char eth_rx_thread_stack[1024]; +#else +static char eth_rx_thread_mb_pool[RT_LWIP_ETHTHREAD_MBOX_SIZE * 4]; +static char eth_rx_thread_stack[RT_LWIP_ETHTHREAD_STACKSIZE]; +#endif +#endif + +#ifdef RT_USING_NETDEV + +#include "lwip/ip.h" +#include "lwip/init.h" +#include "lwip/netdb.h" +#include + +static int lwip_netdev_set_up(struct netdev *netif) +{ + netif_set_up((struct netif *)netif->user_data); + return ERR_OK; +} + +static int lwip_netdev_set_down(struct netdev *netif) +{ + netif_set_down((struct netif *)netif->user_data); + return ERR_OK; +} + +static int lwip_netdev_set_addr_info(struct netdev *netif, ip_addr_t *ip_addr, ip_addr_t *netmask, ip_addr_t *gw) +{ + if (ip_addr && netmask && gw) + { + netif_set_addr((struct netif *)netif->user_data, ip_2_ip4(ip_addr), ip_2_ip4(netmask), ip_2_ip4(gw)); + } + else + { + if (ip_addr) + { + netif_set_ipaddr((struct netif *)netif->user_data, ip_2_ip4(ip_addr)); + } + + if (netmask) + { + netif_set_netmask((struct netif *)netif->user_data, ip_2_ip4(netmask)); + } + + if (gw) + { + netif_set_gw((struct netif *)netif->user_data, ip_2_ip4(gw)); + } + } + + return ERR_OK; +} + +#ifdef RT_LWIP_DNS +static int lwip_netdev_set_dns_server(struct netdev *netif, uint8_t dns_num, ip_addr_t *dns_server) +{ + extern void dns_setserver(uint8_t dns_num, const ip_addr_t *dns_server); + dns_setserver(dns_num, dns_server); + return ERR_OK; +} +#endif /* RT_LWIP_DNS */ + +#ifdef RT_LWIP_DHCP +static int lwip_netdev_set_dhcp(struct netdev *netif, rt_bool_t is_enabled) +{ + netdev_low_level_set_dhcp_status(netif, is_enabled); + return ERR_OK; +} +#endif /* RT_LWIP_DHCP */ + +#ifdef RT_USING_FINSH +#ifdef RT_LWIP_USING_PING +extern int lwip_ping_recv(int s, int *ttl); +extern err_t lwip_ping_send(int s, ip_addr_t *addr, int size); + +int lwip_netdev_ping(struct netdev *netif, const char *host, size_t data_len, + uint32_t timeout, struct netdev_ping_resp *ping_resp) +{ + int s, ttl, recv_len, result = 0; + int elapsed_time; + rt_tick_t recv_start_tick; +#if LWIP_VERSION_MAJOR >= 2U + struct timeval recv_timeout = { timeout / RT_TICK_PER_SECOND, timeout % RT_TICK_PER_SECOND }; +#else + int recv_timeout = timeout * 1000UL / RT_TICK_PER_SECOND; +#endif + ip_addr_t target_addr; + struct addrinfo hint, *res = RT_NULL; + struct sockaddr_in *h = RT_NULL; + struct in_addr ina; + + RT_ASSERT(netif); + RT_ASSERT(host); + RT_ASSERT(ping_resp); + + rt_memset(&hint, 0x00, sizeof(hint)); + /* convert URL to IP */ + if (lwip_getaddrinfo(host, RT_NULL, &hint, &res) != 0) + { + return -RT_ERROR; + } + rt_memcpy(&h, &res->ai_addr, sizeof(struct sockaddr_in *)); + rt_memcpy(&ina, &h->sin_addr, sizeof(ina)); + lwip_freeaddrinfo(res); + if (inet_aton(inet_ntoa(ina), &target_addr) == 0) + { + return -RT_ERROR; + } + rt_memcpy(&(ping_resp->ip_addr), &target_addr, sizeof(ip_addr_t)); + + /* new a socket */ + if ((s = lwip_socket(AF_INET, SOCK_RAW, IP_PROTO_ICMP)) < 0) + { + return -RT_ERROR; + } + + lwip_setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &recv_timeout, sizeof(recv_timeout)); + + if (lwip_ping_send(s, &target_addr, data_len) == ERR_OK) + { + recv_start_tick = rt_tick_get(); + if ((recv_len = lwip_ping_recv(s, &ttl)) >= 0) + { + elapsed_time = (rt_tick_get() - recv_start_tick) * 1000UL / RT_TICK_PER_SECOND; + ping_resp->data_len = recv_len; + ping_resp->ttl = ttl; + ping_resp->ticks = elapsed_time; + } + else + { + result = -RT_ETIMEOUT; + goto __exit; + } + } + else + { + result = -RT_ETIMEOUT; + goto __exit; + } + +__exit: + lwip_close(s); + + return result; +} +#endif /* RT_LWIP_USING_PING */ + +#if defined (RT_LWIP_TCP) || defined (RT_LWIP_UDP) +void lwip_netdev_netstat(struct netdev *netif) +{ + extern void list_tcps(void); + extern void list_udps(void); + +#ifdef RT_LWIP_TCP + list_tcps(); +#endif +#ifdef RT_LWIP_UDP + list_udps(); +#endif +} +#endif /* RT_LWIP_TCP || RT_LWIP_UDP */ +#endif /* RT_USING_FINSH */ + +static int lwip_netdev_set_default(struct netdev *netif) +{ + netif_set_default((struct netif *)netif->user_data); + return ERR_OK; +} + +const struct netdev_ops lwip_netdev_ops = +{ + lwip_netdev_set_up, + lwip_netdev_set_down, + + lwip_netdev_set_addr_info, +#ifdef RT_LWIP_DNS + lwip_netdev_set_dns_server, +#else + NULL, +#endif /* RT_LWIP_DNS */ + +#ifdef RT_LWIP_DHCP + lwip_netdev_set_dhcp, +#else + NULL, +#endif /* RT_LWIP_DHCP */ + +#ifdef RT_USING_FINSH +#ifdef RT_LWIP_USING_PING + lwip_netdev_ping, +#else + NULL, +#endif /* RT_LWIP_USING_PING */ + +#if defined (RT_LWIP_TCP) || defined (RT_LWIP_UDP) + lwip_netdev_netstat, +#endif /* RT_LWIP_TCP || RT_LWIP_UDP */ +#endif /* RT_USING_FINSH */ + + lwip_netdev_set_default, +}; + +static int netdev_add(struct netif *lwip_netif) +{ +#define LWIP_NETIF_NAME_LEN 2 + int result = 0; + struct netdev *netdev = RT_NULL; + char name[LWIP_NETIF_NAME_LEN + 1] = {0}; + + RT_ASSERT(lwip_netif); + + netdev = (struct netdev *)rt_calloc(1, sizeof(struct netdev)); + if (netdev == RT_NULL) + { + return -ERR_IF; + } + +#ifdef SAL_USING_LWIP + extern int sal_lwip_netdev_set_pf_info(struct netdev *netdev); + /* set the lwIP network interface device protocol family information */ + sal_lwip_netdev_set_pf_info(netdev); +#endif /* SAL_USING_LWIP */ + + rt_strncpy(name, lwip_netif->name, LWIP_NETIF_NAME_LEN); + result = netdev_register(netdev, name, (void *)lwip_netif); + + /* Update netdev info after registered */ + netdev->flags = lwip_netif->flags; + netdev->mtu = lwip_netif->mtu; + netdev->ops = &lwip_netdev_ops; + netdev->hwaddr_len = lwip_netif->hwaddr_len; + rt_memcpy(netdev->hwaddr, lwip_netif->hwaddr, lwip_netif->hwaddr_len); + netdev->ip_addr = lwip_netif->ip_addr; + netdev->gw = lwip_netif->gw; + netdev->netmask = lwip_netif->netmask; + +#ifdef RT_LWIP_DHCP + netdev_low_level_set_dhcp_status(netdev, RT_TRUE); +#endif + + return result; +} + +static void netdev_del(struct netif *lwip_netif) +{ + char name[LWIP_NETIF_NAME_LEN + 1]; + struct netdev *netdev; + + RT_ASSERT(lwip_netif); + + rt_strncpy(name, lwip_netif->name, LWIP_NETIF_NAME_LEN); + netdev = netdev_get_by_name(name); + netdev_unregister(netdev); + rt_free(netdev); +} + +/* synchronize lwIP network interface device and network interface device flags */ +static int netdev_flags_sync(struct netif *lwip_netif) +{ + struct netdev *netdev = NULL; + + RT_ASSERT(lwip_netif); + + netdev = netdev_get_by_name(lwip_netif->name); + if (netdev == RT_NULL) + { + return -ERR_IF; + } + + netdev->mtu = lwip_netif->mtu; + netdev->flags |= lwip_netif->flags; + + return ERR_OK; +} +#endif /* RT_USING_NETDEV */ + +static err_t ethernetif_linkoutput(struct netif *netif, struct pbuf *p) +{ +#ifndef LWIP_NO_TX_THREAD + struct eth_tx_msg msg; + struct eth_device* enetif; + + RT_ASSERT(netif != RT_NULL); + enetif = (struct eth_device*)netif->state; + + /* send a message to eth tx thread */ + msg.netif = netif; + msg.buf = p; + if (rt_mb_send(ð_tx_thread_mb, (rt_uint32_t) &msg) == RT_EOK) + { + /* waiting for ack */ + rt_sem_take(&(enetif->tx_ack), RT_WAITING_FOREVER); + } +#else + struct eth_device* enetif; + + RT_ASSERT(netif != RT_NULL); + enetif = (struct eth_device*)netif->state; + + if (enetif->eth_tx(&(enetif->parent), p) != RT_EOK) + { + return ERR_IF; + } +#endif + return ERR_OK; +} + +static err_t eth_netif_device_init(struct netif *netif) +{ + struct eth_device *ethif; + + ethif = (struct eth_device*)netif->state; + if (ethif != RT_NULL) + { + rt_device_t device; + +#ifdef RT_USING_NETDEV + /* network interface device register */ + netdev_add(netif); +#endif /* RT_USING_NETDEV */ + + /* get device object */ + device = (rt_device_t) ethif; + if (rt_device_init(device) != RT_EOK) + { + return ERR_IF; + } + + /* copy device flags to netif flags */ + netif->flags = (ethif->flags & 0xff); + netif->mtu = ETHERNET_MTU; + + /* set output */ + netif->output = etharp_output; + +#if LWIP_IPV6 + netif->output_ip6 = ethip6_output; + netif->ip6_autoconfig_enabled = 1; + netif_create_ip6_linklocal_address(netif, 1); + +#if LWIP_IPV6_MLD + netif->flags |= NETIF_FLAG_MLD6; + + /* + * For hardware/netifs that implement MAC filtering. + * All-nodes link-local is handled by default, so we must let the hardware know + * to allow multicast packets in. + * Should set mld_mac_filter previously. */ + if (netif->mld_mac_filter != NULL) + { + ip6_addr_t ip6_allnodes_ll; + ip6_addr_set_allnodes_linklocal(&ip6_allnodes_ll); + netif->mld_mac_filter(netif, &ip6_allnodes_ll, NETIF_ADD_MAC_FILTER); + } +#endif /* LWIP_IPV6_MLD */ + +#endif /* LWIP_IPV6 */ + + /* set default netif */ + if (netif_default == RT_NULL) + netif_set_default(ethif->netif); + +#if LWIP_DHCP + /* set interface up */ + netif_set_up(ethif->netif); + /* if this interface uses DHCP, start the DHCP client */ + dhcp_start(ethif->netif); +#else + /* set interface up */ + netif_set_up(ethif->netif); +#endif + + if (ethif->flags & ETHIF_LINK_PHYUP) + { + /* set link_up for this netif */ + netif_set_link_up(ethif->netif); + } + + return ERR_OK; + } + + return ERR_IF; +} + +/* Keep old drivers compatible in RT-Thread */ +rt_err_t eth_device_init_with_flag(struct eth_device *dev, const char *name, rt_uint16_t flags) +{ + struct netif* netif; +#if LWIP_NETIF_HOSTNAME +#define LWIP_HOSTNAME_LEN 16 + char *hostname = RT_NULL; + netif = (struct netif*) rt_calloc (1, sizeof(struct netif) + LWIP_HOSTNAME_LEN); +#else + netif = (struct netif*) rt_calloc (1, sizeof(struct netif)); +#endif + if (netif == RT_NULL) + { + rt_kprintf("malloc netif failed\n"); + return -RT_ERROR; + } + + /* set netif */ + dev->netif = netif; + /* device flags, which will be set to netif flags when initializing */ + dev->flags = flags; + /* link changed status of device */ + dev->link_changed = 0x00; + dev->parent.type = RT_Device_Class_NetIf; + /* register to RT-Thread device manager */ + rt_device_register(&(dev->parent), name, RT_DEVICE_FLAG_RDWR); + rt_sem_init(&(dev->tx_ack), name, 0, RT_IPC_FLAG_FIFO); + + /* set name */ + netif->name[0] = name[0]; + netif->name[1] = name[1]; + + /* set hw address to 6 */ + netif->hwaddr_len = 6; + /* maximum transfer unit */ + netif->mtu = ETHERNET_MTU; + + /* set linkoutput */ + netif->linkoutput = ethernetif_linkoutput; + + /* get hardware MAC address */ + rt_device_control(&(dev->parent), NIOCTL_GADDR, netif->hwaddr); + +#if LWIP_NETIF_HOSTNAME + /* Initialize interface hostname */ + hostname = (char *)netif + sizeof(struct netif); + rt_sprintf(hostname, "rtthread_%02x%02x", name[0], name[1]); + netif->hostname = hostname; +#endif /* LWIP_NETIF_HOSTNAME */ + + /* if tcp thread has been started up, we add this netif to the system */ + if (rt_thread_find("tcpip") != RT_NULL) + { + ip4_addr_t ipaddr, netmask, gw; + +#if !LWIP_DHCP + ipaddr.addr = inet_addr(RT_LWIP_IPADDR); + gw.addr = inet_addr(RT_LWIP_GWADDR); + netmask.addr = inet_addr(RT_LWIP_MSKADDR); +#else + IP4_ADDR(&ipaddr, 0, 0, 0, 0); + IP4_ADDR(&gw, 0, 0, 0, 0); + IP4_ADDR(&netmask, 0, 0, 0, 0); +#endif + netifapi_netif_add(netif, &ipaddr, &netmask, &gw, dev, eth_netif_device_init, tcpip_input); + } + +#ifdef RT_USING_NETDEV + /* network interface device flags synchronize */ + netdev_flags_sync(netif); +#endif /* RT_USING_NETDEV */ + + return RT_EOK; +} + +rt_err_t eth_device_init(struct eth_device * dev, const char *name) +{ + rt_uint16_t flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP; + +#if LWIP_IGMP + /* IGMP support */ + flags |= NETIF_FLAG_IGMP; +#endif + + return eth_device_init_with_flag(dev, name, flags); +} + +void eth_device_deinit(struct eth_device *dev) +{ + struct netif* netif = dev->netif; + +#if LWIP_DHCP + dhcp_stop(netif); + dhcp_cleanup(netif); +#endif + netif_set_down(netif); + netif_remove(netif); +#ifdef RT_USING_NETDEV + netdev_del(netif); +#endif + rt_device_close(&(dev->parent)); + rt_device_unregister(&(dev->parent)); + rt_sem_detach(&(dev->tx_ack)); + rt_free(netif); +} + +#ifndef LWIP_NO_RX_THREAD +rt_err_t eth_device_ready(struct eth_device* dev) +{ + if (dev->netif) + /* post message to Ethernet thread */ + return rt_mb_send(ð_rx_thread_mb, (rt_uint32_t)dev); + else + return ERR_OK; /* netif is not initialized yet, just return. */ +} + +rt_err_t eth_device_linkchange(struct eth_device* dev, rt_bool_t up) +{ + rt_uint32_t level; + + RT_ASSERT(dev != RT_NULL); + + level = rt_hw_interrupt_disable(); + dev->link_changed = 0x01; + if (up == RT_TRUE) + dev->link_status = 0x01; + else + dev->link_status = 0x00; + rt_hw_interrupt_enable(level); + + /* post message to ethernet thread */ + return rt_mb_send(ð_rx_thread_mb, (rt_uint32_t)dev); +} +#else +/* NOTE: please not use it in interrupt when no RxThread exist */ +rt_err_t eth_device_linkchange(struct eth_device* dev, rt_bool_t up) +{ + if (up == RT_TRUE) + netifapi_netif_set_link_up(dev->netif); + else + netifapi_netif_set_link_down(dev->netif); + + return RT_EOK; +} +#endif + +#ifndef LWIP_NO_TX_THREAD +/* Ethernet Tx Thread */ +static void eth_tx_thread_entry(void* parameter) +{ + struct eth_tx_msg* msg; + + while (1) + { + if (rt_mb_recv(ð_tx_thread_mb, (rt_ubase_t *)&msg, RT_WAITING_FOREVER) == RT_EOK) + { + struct eth_device* enetif; + + RT_ASSERT(msg->netif != RT_NULL); + RT_ASSERT(msg->buf != RT_NULL); + + enetif = (struct eth_device*)msg->netif->state; + if (enetif != RT_NULL) + { + /* call driver's interface */ + if (enetif->eth_tx(&(enetif->parent), msg->buf) != RT_EOK) + { + /* transmit eth packet failed */ + } + } + + /* send ACK */ + rt_sem_release(&(enetif->tx_ack)); + } + } +} +#endif + +#ifndef LWIP_NO_RX_THREAD +/* Ethernet Rx Thread */ +static void eth_rx_thread_entry(void* parameter) +{ + struct eth_device* device; + + while (1) + { + if (rt_mb_recv(ð_rx_thread_mb, (rt_ubase_t *)&device, RT_WAITING_FOREVER) == RT_EOK) + { + struct pbuf *p; + + /* check link status */ + if (device->link_changed) + { + int status; + rt_uint32_t level; + + level = rt_hw_interrupt_disable(); + status = device->link_status; + device->link_changed = 0x00; + rt_hw_interrupt_enable(level); + + if (status) + netifapi_netif_set_link_up(device->netif); + else + netifapi_netif_set_link_down(device->netif); + } + + /* receive all of buffer */ + while (1) + { + if(device->eth_rx == RT_NULL) break; + + p = device->eth_rx(&(device->parent)); + if (p != RT_NULL) + { + /* notify to upper layer */ + if( device->netif->input(p, device->netif) != ERR_OK ) + { + LWIP_DEBUGF(NETIF_DEBUG, ("ethernetif_input: Input error\n")); + pbuf_free(p); + p = NULL; + } + } + else break; + } + } + else + { + LWIP_ASSERT("Should not happen!\n",0); + } + } +} +#endif + +/* this function does not need, + * use eth_system_device_init_private() + * call by lwip_system_init(). + */ +int eth_system_device_init(void) +{ + return 0; +} + +int eth_system_device_init_private(void) +{ + rt_err_t result = RT_EOK; + + /* initialize Rx thread. */ +#ifndef LWIP_NO_RX_THREAD + /* initialize mailbox and create Ethernet Rx thread */ + result = rt_mb_init(ð_rx_thread_mb, "erxmb", + ð_rx_thread_mb_pool[0], sizeof(eth_rx_thread_mb_pool)/4, + RT_IPC_FLAG_FIFO); + RT_ASSERT(result == RT_EOK); + + result = rt_thread_init(ð_rx_thread, "erx", eth_rx_thread_entry, RT_NULL, + ð_rx_thread_stack[0], sizeof(eth_rx_thread_stack), + RT_ETHERNETIF_THREAD_PREORITY, 16); + RT_ASSERT(result == RT_EOK); + result = rt_thread_startup(ð_rx_thread); + RT_ASSERT(result == RT_EOK); +#endif + + /* initialize Tx thread */ +#ifndef LWIP_NO_TX_THREAD + /* initialize mailbox and create Ethernet Tx thread */ + result = rt_mb_init(ð_tx_thread_mb, "etxmb", + ð_tx_thread_mb_pool[0], sizeof(eth_tx_thread_mb_pool)/4, + RT_IPC_FLAG_FIFO); + RT_ASSERT(result == RT_EOK); + + result = rt_thread_init(ð_tx_thread, "etx", eth_tx_thread_entry, RT_NULL, + ð_tx_thread_stack[0], sizeof(eth_tx_thread_stack), + RT_ETHERNETIF_THREAD_PREORITY, 16); + RT_ASSERT(result == RT_EOK); + + result = rt_thread_startup(ð_tx_thread); + RT_ASSERT(result == RT_EOK); +#endif + + return (int)result; +} + +void set_if(char* netif_name, char* ip_addr, char* gw_addr, char* nm_addr) +{ + ip4_addr_t *ip; + ip4_addr_t addr; + struct netif * netif = netif_list; + + if(strlen(netif_name) > sizeof(netif->name)) + { + rt_kprintf("network interface name too long!\r\n"); + return; + } + + while(netif != RT_NULL) + { + if(strncmp(netif_name, netif->name, sizeof(netif->name)) == 0) + break; + + netif = netif->next; + if( netif == RT_NULL ) + { + rt_kprintf("network interface: %s not found!\r\n", netif_name); + return; + } + } + + ip = (ip4_addr_t *)&addr; + + /* set ip address */ + if ((ip_addr != RT_NULL) && ip4addr_aton(ip_addr, &addr)) + { + netif_set_ipaddr(netif, ip); + } + + /* set gateway address */ + if ((gw_addr != RT_NULL) && ip4addr_aton(gw_addr, &addr)) + { + netif_set_gw(netif, ip); + } + + /* set netmask address */ + if ((nm_addr != RT_NULL) && ip4addr_aton(nm_addr, &addr)) + { + netif_set_netmask(netif, ip); + } +} + +#ifdef RT_USING_FINSH +#include +FINSH_FUNCTION_EXPORT(set_if, set network interface address); + +#if LWIP_DNS +#include +void set_dns(uint8_t dns_num, char* dns_server) +{ + ip_addr_t addr; + + if ((dns_server != RT_NULL) && ipaddr_aton(dns_server, &addr)) + { + dns_setserver(dns_num, &addr); + } +} +FINSH_FUNCTION_EXPORT(set_dns, set DNS server address); +#endif + +void list_if(void) +{ + rt_ubase_t index; + struct netif * netif; + + rt_enter_critical(); + + netif = netif_list; + + while( netif != RT_NULL ) + { + rt_kprintf("network interface: %c%c%s\n", + netif->name[0], + netif->name[1], + (netif == netif_default)?" (Default)":""); + rt_kprintf("MTU: %d\n", netif->mtu); + rt_kprintf("MAC: "); + for (index = 0; index < netif->hwaddr_len; index ++) + rt_kprintf("%02x ", netif->hwaddr[index]); + rt_kprintf("\nFLAGS:"); + if (netif->flags & NETIF_FLAG_UP) rt_kprintf(" UP"); + else rt_kprintf(" DOWN"); + if (netif->flags & NETIF_FLAG_LINK_UP) rt_kprintf(" LINK_UP"); + else rt_kprintf(" LINK_DOWN"); + if (netif->flags & NETIF_FLAG_ETHARP) rt_kprintf(" ETHARP"); + if (netif->flags & NETIF_FLAG_BROADCAST) rt_kprintf(" BROADCAST"); + if (netif->flags & NETIF_FLAG_IGMP) rt_kprintf(" IGMP"); + rt_kprintf("\n"); + rt_kprintf("ip address: %s\n", ipaddr_ntoa(&(netif->ip_addr))); + rt_kprintf("gw address: %s\n", ipaddr_ntoa(&(netif->gw))); + rt_kprintf("net mask : %s\n", ipaddr_ntoa(&(netif->netmask))); +#if LWIP_IPV6 + { + ip6_addr_t *addr; + int addr_state; + int i; + + addr = (ip6_addr_t *)&netif->ip6_addr[0]; + addr_state = netif->ip6_addr_state[0]; + + rt_kprintf("\nipv6 link-local: %s state:%02X %s\n", ip6addr_ntoa(addr), + addr_state, ip6_addr_isvalid(addr_state)?"VALID":"INVALID"); + + for(i=1; iip6_addr[i]; + addr_state = netif->ip6_addr_state[i]; + + rt_kprintf("ipv6[%d] address: %s state:%02X %s\n", i, ip6addr_ntoa(addr), + addr_state, ip6_addr_isvalid(addr_state)?"VALID":"INVALID"); + } + + } + rt_kprintf("\r\n"); +#endif /* LWIP_IPV6 */ + netif = netif->next; + } + +#if LWIP_DNS + { + const ip_addr_t *ip_addr; + + for(index=0; index +#include + +void list_tcps(void) +{ + rt_uint32_t num = 0; + struct tcp_pcb *pcb; + char local_ip_str[16]; + char remote_ip_str[16]; + + extern struct tcp_pcb *tcp_active_pcbs; + extern union tcp_listen_pcbs_t tcp_listen_pcbs; + extern struct tcp_pcb *tcp_tw_pcbs; + + rt_enter_critical(); + rt_kprintf("Active PCB states:\n"); + for(pcb = tcp_active_pcbs; pcb != NULL; pcb = pcb->next) + { + strcpy(local_ip_str, ipaddr_ntoa(&(pcb->local_ip))); + strcpy(remote_ip_str, ipaddr_ntoa(&(pcb->remote_ip))); + + rt_kprintf("#%d %s:%d <==> %s:%d snd_nxt 0x%08X rcv_nxt 0x%08X ", + num++, + local_ip_str, + pcb->local_port, + remote_ip_str, + pcb->remote_port, + pcb->snd_nxt, + pcb->rcv_nxt); + rt_kprintf("state: %s\n", tcp_debug_state_str(pcb->state)); + } + + rt_kprintf("Listen PCB states:\n"); + num = 0; + for(pcb = (struct tcp_pcb *)tcp_listen_pcbs.pcbs; pcb != NULL; pcb = pcb->next) + { + rt_kprintf("#%d local port %d ", num++, pcb->local_port); + rt_kprintf("state: %s\n", tcp_debug_state_str(pcb->state)); + } + + rt_kprintf("TIME-WAIT PCB states:\n"); + num = 0; + for(pcb = tcp_tw_pcbs; pcb != NULL; pcb = pcb->next) + { + strcpy(local_ip_str, ipaddr_ntoa(&(pcb->local_ip))); + strcpy(remote_ip_str, ipaddr_ntoa(&(pcb->remote_ip))); + + rt_kprintf("#%d %s:%d <==> %s:%d snd_nxt 0x%08X rcv_nxt 0x%08X ", + num++, + local_ip_str, + pcb->local_port, + remote_ip_str, + pcb->remote_port, + pcb->snd_nxt, + pcb->rcv_nxt); + rt_kprintf("state: %s\n", tcp_debug_state_str(pcb->state)); + } + rt_exit_critical(); +} +FINSH_FUNCTION_EXPORT(list_tcps, list all of tcp connections); +#endif /* LWIP_TCP */ + +#if LWIP_UDP +#include "lwip/udp.h" +void list_udps(void) +{ + struct udp_pcb *pcb; + rt_uint32_t num = 0; + char local_ip_str[16]; + char remote_ip_str[16]; + + rt_enter_critical(); + rt_kprintf("Active UDP PCB states:\n"); + for (pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) + { + strcpy(local_ip_str, ipaddr_ntoa(&(pcb->local_ip))); + strcpy(remote_ip_str, ipaddr_ntoa(&(pcb->remote_ip))); + + rt_kprintf("#%d %d %s:%d <==> %s:%d \n", + num, (int)pcb->flags, + local_ip_str, + pcb->local_port, + remote_ip_str, + pcb->remote_port); + + num++; + } + rt_exit_critical(); +} +FINSH_FUNCTION_EXPORT(list_udps, list all of udp connections); +#endif /* LWIP_UDP */ + +#endif