Skip to content

Commit c0fe3b5

Browse files
authored
Merge pull request #4911 from mikaleppanen/lwip_ipv4v6_ppp
Support cellular IPv4v6 dual stack in LWIP
2 parents 3f347ed + 32131b6 commit c0fe3b5

30 files changed

+993
-421
lines changed

features/FEATURE_LWIP/lwip-interface/EthernetInterface.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ nsapi_error_t EthernetInterface::connect()
4949
return mbed_lwip_bringup_2(_dhcp, false,
5050
_ip_address[0] ? _ip_address : 0,
5151
_netmask[0] ? _netmask : 0,
52-
_gateway[0] ? _gateway : 0);
52+
_gateway[0] ? _gateway : 0,
53+
DEFAULT_STACK);
5354
}
5455

5556
nsapi_error_t EthernetInterface::disconnect()

features/FEATURE_LWIP/lwip-interface/lwip-sys/arch/cc.h

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,66 @@ void assert_printf(char *msg, int line, char *file);
117117
#endif // MBED_CONF_LWIP_USE_MBED_TRACE
118118
#endif
119119

120+
#if TRACE_TO_ASCII_HEX_DUMP
121+
#define TRACE_TO_ASCII_HEX_DUMPF(prefix, len, data) trace_to_ascii_hex_dump(prefix, len, data)
122+
void trace_to_ascii_hex_dump(char* prefix, int len, char *data);
123+
#else
124+
#define TRACE_TO_ASCII_HEX_DUMPF(prefix, len, data) ((void)0)
125+
#endif
126+
120127
#include "cmsis.h"
121128
#define LWIP_PLATFORM_HTONS(x) __REV16(x)
122129
#define LWIP_PLATFORM_HTONL(x) __REV(x)
123130

131+
/* Define the memory area for the lwip's memory pools */
132+
#ifndef MEMP_SECTION
133+
#if defined(TARGET_LPC4088) || defined(TARGET_LPC4088_DM)
134+
# if defined (__ICCARM__)
135+
# define MEMP_SECTION
136+
# elif defined(TOOLCHAIN_GCC_CR)
137+
# define MEMP_SECTION __attribute__((section(".data.$RamPeriph32")))
138+
# else
139+
# define MEMP_SECTION __attribute__((section("AHBSRAM0"),aligned))
140+
# endif
141+
#elif defined(TARGET_LPC1768)
142+
# if defined (__ICCARM__)
143+
# define MEMP_SECTION
144+
# elif defined(TOOLCHAIN_GCC_CR)
145+
# define MEMP_SECTION __attribute__((section(".data.$RamPeriph32")))
146+
# else
147+
# define MEMP_SECTION __attribute__((section("AHBSRAM1"),aligned))
148+
# endif
149+
#endif
150+
#endif
151+
152+
#ifdef MEMP_SECTION
153+
#define SET_MEMP_SECTION(name) extern uint8_t MEMP_SECTION name[]
154+
155+
#if defined (__ICCARM__)
156+
#pragma default_variable_attributes = @ ".ethusbram"
157+
#endif
158+
SET_MEMP_SECTION(memp_memory_REASSDATA_base);
159+
SET_MEMP_SECTION(memp_memory_TCP_PCB_LISTEN_base);
160+
SET_MEMP_SECTION(memp_memory_PBUF_POOL_base);
161+
SET_MEMP_SECTION(memp_memory_NETCONN_base);
162+
SET_MEMP_SECTION(memp_memory_IGMP_GROUP_base);
163+
SET_MEMP_SECTION(memp_memory_UDP_PCB_base);
164+
SET_MEMP_SECTION(memp_memory_TCP_PCB_base);
165+
SET_MEMP_SECTION(memp_memory_FRAG_PBUF_base);
166+
SET_MEMP_SECTION(memp_memory_PBUF_base);
167+
SET_MEMP_SECTION(memp_memory_MLD6_GROUP_base);
168+
SET_MEMP_SECTION(memp_memory_IP6_REASSDATA_base);
169+
SET_MEMP_SECTION(memp_memory_NETBUF_base);
170+
SET_MEMP_SECTION(memp_memory_TCPIP_MSG_INPKT_base);
171+
SET_MEMP_SECTION(memp_memory_SYS_TIMEOUT_base);
172+
SET_MEMP_SECTION(memp_memory_TCP_SEG_base);
173+
SET_MEMP_SECTION(memp_memory_TCPIP_MSG_API_base);
174+
SET_MEMP_SECTION(memp_memory_PPP_PCB_base);
175+
SET_MEMP_SECTION(memp_memory_PPPOS_PCB_base);
176+
SET_MEMP_SECTION(memp_memory_PPP_PCB_base);
177+
#if defined (__ICCARM__)
178+
#pragma default_variable_attributes =
179+
#endif
180+
#endif
181+
124182
#endif /* __CC_H__ */

features/FEATURE_LWIP/lwip-interface/lwip-sys/arch/lwip_sys_arch.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -590,4 +590,23 @@ void assert_printf(char *msg, int line, char *file) {
590590
}
591591
#endif // MBED_CONF_LWIP_USE_MBED_TRACE
592592

593+
#if TRACE_TO_ASCII_HEX_DUMP
594+
void trace_to_ascii_hex_dump(char *prefix, int len, char *data)
595+
{
596+
int line_len = 0;
597+
598+
for (int i = 0; i < len; i++) {
599+
if ((line_len % 16) == 0) {
600+
if (line_len != 0) {
601+
LWIP_PLATFORM_DIAG(("\n"));
602+
}
603+
LWIP_PLATFORM_DIAG(("%s %06x", prefix, line_len));
604+
}
605+
line_len++;
606+
LWIP_PLATFORM_DIAG((" %02x", data[i]));
607+
}
608+
LWIP_PLATFORM_DIAG(("\n"));
609+
}
610+
#endif
611+
593612
#endif /* LWIP_DEBUG */

features/FEATURE_LWIP/lwip-interface/lwip-sys/lwip_random.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@
1414
* limitations under the License.
1515
*/
1616

17+
#include "lwip/opt.h"
18+
#include "lwip/debug.h"
19+
#include "lwip/def.h"
1720
#include "lwip_random.h"
1821

1922
#if FEATURE_COMMON_PAL

features/FEATURE_LWIP/lwip-interface/lwip-sys/lwip_random.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,6 @@
1717
#ifndef LWIP_HDR_RANDOM_H
1818
#define LWIP_HDR_RANDOM_H
1919

20-
#include "lwip/opt.h"
21-
#include "lwip/debug.h"
22-
#include "lwip/def.h"
23-
2420
#ifdef __cplusplus
2521
extern "C" {
2622
#endif

features/FEATURE_LWIP/lwip-interface/lwip-sys/lwip_tcp_isn.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@
7070
* Author: David van Moolenbroek <[email protected]>
7171
*/
7272

73-
#include "lwip_tcp_isn.h"
73+
#include "lwip/opt.h"
7474
#include "lwip/ip_addr.h"
7575
#include "lwip/sys.h"
7676
#include <string.h>
@@ -122,13 +122,16 @@ lwip_init_tcp_isn(u32_t boot_time, const u8_t *secret_16_bytes)
122122
* @param remote_port The remote port number, in host-byte order.
123123
* @return The ISN to use for the new TCP connection.
124124
*/
125+
125126
u32_t
126-
lwip_hook_tcp_isn(const ip_addr_t *local_ip, u16_t local_port,
127-
const ip_addr_t *remote_ip, u16_t remote_port)
127+
lwip_hook_tcp_isn(const void *local_ip_ptr, u16_t local_port,
128+
const void *remote_ip_ptr, u16_t remote_port)
128129
{
129130
lwip_md5_context ctx;
130131
u8_t output[16];
131132
u32_t isn;
133+
const ip_addr_t *local_ip = local_ip_ptr;
134+
const ip_addr_t *remote_ip = remote_ip_ptr;
132135

133136
#if LWIP_IPV4 && LWIP_IPV6
134137
if (IP_IS_V6(local_ip))

features/FEATURE_LWIP/lwip-interface/lwip-sys/lwip_tcp_isn.h

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,16 +30,14 @@
3030
#ifndef LWIP_HDR_CONTRIB_ADDONS_TCP_ISN_H
3131
#define LWIP_HDR_CONTRIB_ADDONS_TCP_ISN_H
3232

33-
#include "lwip/opt.h"
34-
#include "lwip/ip_addr.h"
35-
3633
#ifdef __cplusplus
3734
extern "C" {
3835
#endif
3936

40-
void lwip_init_tcp_isn(u32_t boot_time, const u8_t *secret_16_bytes);
41-
u32_t lwip_hook_tcp_isn(const ip_addr_t *local_ip, u16_t local_port,
42-
const ip_addr_t *remote_ip, u16_t remote_port);
37+
void lwip_init_tcp_isn(uint32_t boot_time, const uint8_t *secret_16_bytes);
38+
uint32_t lwip_hook_tcp_isn(const void *local_ip, uint16_t local_port,
39+
const void *remote_ip, uint16_t remote_port);
40+
4341

4442
#ifdef __cplusplus
4543
}

features/FEATURE_LWIP/lwip-interface/lwip/CHANGELOG

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ HISTORY
1515

1616
++ Bugfixes:
1717

18+
2017-01-11: David van Moolenbroek
19+
* Lots of IPv6 related fixes and improvements
20+
1821
2017-03-08
1922
* tcp: do not keep sending SYNs when getting ACKs
2023

features/FEATURE_LWIP/lwip-interface/lwip/src/core/ipv4/lwip_ip4.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1048,6 +1048,8 @@ ip4_debug_print(struct pbuf *p)
10481048
{
10491049
struct ip_hdr *iphdr = (struct ip_hdr *)p->payload;
10501050

1051+
TRACE_TO_ASCII_HEX_DUMPF("IP>", lwip_ntohs(IPH_LEN(iphdr)), (char *) iphdr);
1052+
10511053
LWIP_DEBUGF(IP_DEBUG, ("IP header:\n"));
10521054
LWIP_DEBUGF(IP_DEBUG, ("+-------------------------------+\n"));
10531055
LWIP_DEBUGF(IP_DEBUG, ("|%2"S16_F" |%2"S16_F" | 0x%02"X16_F" | %5"U16_F" | (v, hl, tos, len)\n",

features/FEATURE_LWIP/lwip-interface/lwip/src/core/ipv6/lwip_ip6.c

Lines changed: 87 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@
7272
* this is a tricky case because with multiple netifs, link-local addresses only have
7373
* meaning within a particular subnet/link.
7474
* 3) tries to match the destination subnet to a configured address
75-
* 4) tries to find a router
75+
* 4) tries to find a router-announced route
7676
* 5) tries to match the source address to the netif
7777
* 6) returns the default netif, if configured
7878
*
@@ -134,22 +134,29 @@ ip6_route(const ip6_addr_t *src, const ip6_addr_t *dest)
134134
}
135135
#endif
136136

137-
/* See if the destination subnet matches a configured address. */
137+
/* See if the destination subnet matches a configured address. In accordance
138+
* with RFC 5942, dynamically configured addresses do not have an implied
139+
* local subnet, and thus should be considered /128 assignments. However, as
140+
* such, the destination address may still match a local address, and so we
141+
* still need to check for exact matches here. By (lwIP) policy, statically
142+
* configured addresses do always have an implied local /64 subnet. */
138143
for (netif = netif_list; netif != NULL; netif = netif->next) {
139144
if (!netif_is_up(netif) || !netif_is_link_up(netif)) {
140145
continue;
141146
}
142147
for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
143148
if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
144-
ip6_addr_netcmp(dest, netif_ip6_addr(netif, i))) {
149+
ip6_addr_netcmp(dest, netif_ip6_addr(netif, i)) &&
150+
(netif_ip6_addr_isstatic(netif, i) ||
151+
ip6_addr_nethostcmp(dest, netif_ip6_addr(netif, i)))) {
145152
return netif;
146153
}
147154
}
148155
}
149156

150-
/* Get the netif for a suitable router. */
157+
/* Get the netif for a suitable router-announced route. */
151158
netif = nd6_find_route(dest);
152-
if ((netif != NULL) && netif_is_up(netif) && netif_is_link_up(netif)) {
159+
if (netif != NULL) {
153160
return netif;
154161
}
155162

@@ -194,9 +201,22 @@ ip6_route(const ip6_addr_t *src, const ip6_addr_t *dest)
194201

195202
/**
196203
* @ingroup ip6
197-
* Select the best IPv6 source address for a given destination
198-
* IPv6 address. Loosely follows RFC 3484. "Strong host" behavior
199-
* is assumed.
204+
* Select the best IPv6 source address for a given destination IPv6 address.
205+
*
206+
* This implementation follows RFC 6724 Sec. 5 to the following extent:
207+
* - Rules 1, 2, 3: fully implemented
208+
* - Rules 4, 5, 5.5: not applicable
209+
* - Rule 6: not implemented
210+
* - Rule 7: not applicable
211+
* - Rule 8: limited to "prefer /64 subnet match over non-match"
212+
*
213+
* For Rule 2, we deliberately deviate from RFC 6724 Sec. 3.1 by considering
214+
* ULAs to be of smaller scope than global addresses, to avoid that a preferred
215+
* ULA is picked over a deprecated global address when given a global address
216+
* as destination, as that would likely result in broken two-way communication.
217+
*
218+
* As long as temporary addresses are not supported (as used in Rule 7), a
219+
* proper implementation of Rule 8 would obviate the need to implement Rule 6.
200220
*
201221
* @param netif the netif on which to send a packet
202222
* @param dest the destination we are trying to reach
@@ -206,73 +226,72 @@ ip6_route(const ip6_addr_t *src, const ip6_addr_t *dest)
206226
const ip_addr_t *
207227
ip6_select_source_address(struct netif *netif, const ip6_addr_t *dest)
208228
{
209-
const ip_addr_t *src = NULL;
210-
u8_t i;
211-
212-
/* If dest is link-local, choose a link-local source. */
213-
if (ip6_addr_islinklocal(dest) || ip6_addr_ismulticast_linklocal(dest) || ip6_addr_ismulticast_iflocal(dest)) {
214-
for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
215-
if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
216-
ip6_addr_islinklocal(netif_ip6_addr(netif, i))) {
217-
return netif_ip_addr6(netif, i);
218-
}
219-
}
229+
const ip_addr_t *best_addr;
230+
const ip6_addr_t *cand_addr;
231+
s8_t dest_scope, cand_scope;
232+
s8_t best_scope = IP6_MULTICAST_SCOPE_RESERVED;
233+
u8_t i, cand_pref, cand_bits;
234+
u8_t best_pref = 0;
235+
u8_t best_bits = 0;
236+
237+
/* Start by determining the scope of the given destination address. These
238+
* tests are hopefully (roughly) in order of likeliness to match. */
239+
if (ip6_addr_isglobal(dest)) {
240+
dest_scope = IP6_MULTICAST_SCOPE_GLOBAL;
241+
} else if (ip6_addr_islinklocal(dest) || ip6_addr_isloopback(dest)) {
242+
dest_scope = IP6_MULTICAST_SCOPE_LINK_LOCAL;
243+
} else if (ip6_addr_isuniquelocal(dest)) {
244+
dest_scope = IP6_MULTICAST_SCOPE_ORGANIZATION_LOCAL;
245+
} else if (ip6_addr_ismulticast(dest)) {
246+
dest_scope = ip6_addr_multicast_scope(dest);
247+
} else if (ip6_addr_issitelocal(dest)) {
248+
dest_scope = IP6_MULTICAST_SCOPE_SITE_LOCAL;
249+
} else {
250+
/* no match, consider scope global */
251+
dest_scope = IP6_MULTICAST_SCOPE_GLOBAL;
220252
}
221253

222-
/* Choose a site-local with matching prefix. */
223-
if (ip6_addr_issitelocal(dest) || ip6_addr_ismulticast_sitelocal(dest)) {
224-
for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
225-
if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
226-
ip6_addr_issitelocal(netif_ip6_addr(netif, i)) &&
227-
ip6_addr_netcmp(dest, netif_ip6_addr(netif, i))) {
228-
return netif_ip_addr6(netif, i);
229-
}
230-
}
231-
}
254+
best_addr = NULL;
232255

233-
/* Choose a unique-local with matching prefix. */
234-
if (ip6_addr_isuniquelocal(dest) || ip6_addr_ismulticast_orglocal(dest)) {
235-
for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
236-
if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
237-
ip6_addr_isuniquelocal(netif_ip6_addr(netif, i)) &&
238-
ip6_addr_netcmp(dest, netif_ip6_addr(netif, i))) {
239-
return netif_ip_addr6(netif, i);
240-
}
256+
for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
257+
/* Consider only valid (= preferred and deprecated) addresses. */
258+
if (!ip6_addr_isvalid(netif_ip6_addr_state(netif, i))) {
259+
continue;
241260
}
242-
}
243-
244-
/* Choose a global with best matching prefix. */
245-
if (ip6_addr_isglobal(dest) || ip6_addr_ismulticast_global(dest)) {
246-
for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
247-
if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
248-
ip6_addr_isglobal(netif_ip6_addr(netif, i))) {
249-
if (src == NULL) {
250-
src = netif_ip_addr6(netif, i);
251-
}
252-
else {
253-
/* Replace src only if we find a prefix match. */
254-
/* @todo find longest matching prefix. */
255-
if ((!(ip6_addr_netcmp(ip_2_ip6(src), dest))) &&
256-
ip6_addr_netcmp(netif_ip6_addr(netif, i), dest)) {
257-
src = netif_ip_addr6(netif, i);
258-
}
259-
}
260-
}
261+
/* Determine the scope of this candidate address. Same ordering idea. */
262+
cand_addr = netif_ip6_addr(netif, i);
263+
if (ip6_addr_isglobal(cand_addr)) {
264+
cand_scope = IP6_MULTICAST_SCOPE_GLOBAL;
265+
} else if (ip6_addr_islinklocal(cand_addr)) {
266+
cand_scope = IP6_MULTICAST_SCOPE_LINK_LOCAL;
267+
} else if (ip6_addr_isuniquelocal(cand_addr)) {
268+
cand_scope = IP6_MULTICAST_SCOPE_ORGANIZATION_LOCAL;
269+
} else if (ip6_addr_issitelocal(cand_addr)) {
270+
cand_scope = IP6_MULTICAST_SCOPE_SITE_LOCAL;
271+
} else {
272+
/* no match, treat as low-priority global scope */
273+
cand_scope = IP6_MULTICAST_SCOPE_RESERVEDF;
261274
}
262-
if (src != NULL) {
263-
return src;
275+
cand_pref = ip6_addr_ispreferred(netif_ip6_addr_state(netif, i));
276+
/* @todo compute the actual common bits, for longest matching prefix. */
277+
cand_bits = ip6_addr_netcmp(cand_addr, dest); /* just 1 or 0 for now */
278+
if (cand_bits && ip6_addr_nethostcmp(cand_addr, dest)) {
279+
return netif_ip_addr6(netif, i); /* Rule 1 */
264280
}
265-
}
266-
267-
/* Last resort: see if arbitrary prefix matches. */
268-
for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
269-
if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
270-
ip6_addr_netcmp(dest, netif_ip6_addr(netif, i))) {
271-
return netif_ip_addr6(netif, i);
281+
if ((best_addr == NULL) || /* no alternative yet */
282+
((cand_scope < best_scope) && (cand_scope >= dest_scope)) ||
283+
((cand_scope > best_scope) && (best_scope < dest_scope)) || /* Rule 2 */
284+
((cand_scope == best_scope) && ((cand_pref > best_pref) || /* Rule 3 */
285+
((cand_pref == best_pref) && (cand_bits > best_bits))))) { /* Rule 8 */
286+
/* We found a new "winning" candidate. */
287+
best_addr = netif_ip_addr6(netif, i);
288+
best_scope = cand_scope;
289+
best_pref = cand_pref;
290+
best_bits = cand_bits;
272291
}
273292
}
274293

275-
return NULL;
294+
return best_addr; /* may be NULL */
276295
}
277296

278297
#if LWIP_IPV6_FORWARD
@@ -1082,6 +1101,8 @@ ip6_debug_print(struct pbuf *p)
10821101
{
10831102
struct ip6_hdr *ip6hdr = (struct ip6_hdr *)p->payload;
10841103

1104+
TRACE_TO_ASCII_HEX_DUMPF("IP>", IP6H_PLEN(ip6hdr) + 40, (char *) ip6hdr);
1105+
10851106
LWIP_DEBUGF(IP6_DEBUG, ("IPv6 header:\n"));
10861107
LWIP_DEBUGF(IP6_DEBUG, ("+-------------------------------+\n"));
10871108
LWIP_DEBUGF(IP6_DEBUG, ("| %2"U16_F" | %3"U16_F" | %7"U32_F" | (ver, class, flow)\n",

0 commit comments

Comments
 (0)