1 #include "test_ip6.h"
2
3 #include "lwip/ethip6.h"
4 #include "lwip/ip6.h"
5 #include "lwip/icmp6.h"
6 #include "lwip/inet_chksum.h"
7 #include "lwip/nd6.h"
8 #include "lwip/stats.h"
9 #include "lwip/prot/ethernet.h"
10 #include "lwip/prot/ip.h"
11 #include "lwip/prot/ip6.h"
12
13 #include "lwip/tcpip.h"
14
15 #if LWIP_IPV6 /* allow to build the unit tests without IPv6 support */
16
17 static struct netif test_netif6;
18 static int linkoutput_ctr;
19 static int linkoutput_byte_ctr;
20
21 static err_t
default_netif_linkoutput(struct netif * netif,struct pbuf * p)22 default_netif_linkoutput(struct netif *netif, struct pbuf *p)
23 {
24 fail_unless(netif == &test_netif6);
25 fail_unless(p != NULL);
26 linkoutput_ctr++;
27 linkoutput_byte_ctr += p->tot_len;
28 return ERR_OK;
29 }
30
31 static err_t
default_netif_init(struct netif * netif)32 default_netif_init(struct netif *netif)
33 {
34 fail_unless(netif != NULL);
35 netif->linkoutput = default_netif_linkoutput;
36 netif->output_ip6 = ethip6_output;
37 netif->mtu = 1500;
38 netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHERNET | NETIF_FLAG_MLD6;
39 netif->hwaddr_len = ETH_HWADDR_LEN;
40 return ERR_OK;
41 }
42
43 static void
default_netif_add(void)44 default_netif_add(void)
45 {
46 struct netif *n;
47 fail_unless(netif_default == NULL);
48 n = netif_add_noaddr(&test_netif6, NULL, default_netif_init, NULL);
49 fail_unless(n == &test_netif6);
50 netif_set_default(&test_netif6);
51 }
52
53 static void
default_netif_remove(void)54 default_netif_remove(void)
55 {
56 fail_unless(netif_default == &test_netif6);
57 netif_remove(&test_netif6);
58 }
59
60 static void
ip6_test_handle_timers(int count)61 ip6_test_handle_timers(int count)
62 {
63 int i;
64 for (i = 0; i < count; i++) {
65 nd6_tmr();
66 }
67 }
68
69 /* Helper functions */
70 static void
create_ip6_input_fragment(u32_t ip_id,u16_t start,u16_t len,int last,u8_t next_hdr)71 create_ip6_input_fragment(u32_t ip_id, u16_t start, u16_t len, int last, u8_t next_hdr)
72 {
73 struct pbuf* p;
74 struct netif* input_netif = netif_list; /* just use any netif */
75 fail_unless((start & 7) == 0);
76 fail_unless(((len & 7) == 0) || last);
77 fail_unless(input_netif != NULL);
78
79 p = pbuf_alloc(PBUF_RAW, len + sizeof(struct ip6_frag_hdr) +
80 sizeof(struct ip6_hdr), PBUF_RAM);
81 fail_unless(p != NULL);
82 if (p != NULL) {
83 err_t err;
84 struct ip6_frag_hdr* fraghdr;
85
86 struct ip6_hdr* ip6hdr = (struct ip6_hdr*)p->payload;
87 IP6H_VTCFL_SET(ip6hdr, 6, 0, 0);
88 IP6H_PLEN_SET(ip6hdr, len + sizeof(struct ip6_frag_hdr));
89 IP6H_NEXTH_SET(ip6hdr, IP6_NEXTH_FRAGMENT);
90 IP6H_HOPLIM_SET(ip6hdr, 64);
91 ip6_addr_copy_to_packed(ip6hdr->src, *netif_ip6_addr(input_netif, 0));
92 ip6hdr->src.addr[3]++;
93 ip6_addr_copy_to_packed(ip6hdr->dest, *netif_ip6_addr(input_netif, 0));
94
95 fraghdr = (struct ip6_frag_hdr*)(ip6hdr + 1);
96 fraghdr->_nexth = next_hdr;
97 fraghdr->reserved = 0;
98 if (last) {
99 fraghdr->_fragment_offset = htons(start & ~7);
100 } else {
101 fraghdr->_fragment_offset = htons((start & ~7) | 1);
102 }
103 fraghdr->_identification = htonl(ip_id);
104
105 err = ip6_input(p, input_netif);
106 if (err != ERR_OK) {
107 pbuf_free(p);
108 }
109 fail_unless(err == ERR_OK);
110 }
111 }
112
113 /* Setups/teardown functions */
114
115 static void
ip6_setup(void)116 ip6_setup(void)
117 {
118 default_netif_add();
119 lwip_check_ensure_no_alloc(SKIP_POOL(MEMP_SYS_TIMEOUT));
120 }
121
122 static void
ip6_teardown(void)123 ip6_teardown(void)
124 {
125 if (netif_list->loop_first != NULL) {
126 pbuf_free(netif_list->loop_first);
127 netif_list->loop_first = NULL;
128 }
129 netif_list->loop_last = NULL;
130 /* poll until all memory is released... */
131 tcpip_thread_poll_one();
132 default_netif_remove();
133 lwip_check_ensure_no_alloc(SKIP_POOL(MEMP_SYS_TIMEOUT));
134 }
135
136
137 /* Test functions */
138
139 static void
test_ip6_ll_addr_iter(int expected_ctr1,int expected_ctr2)140 test_ip6_ll_addr_iter(int expected_ctr1, int expected_ctr2)
141 {
142 fail_unless(linkoutput_ctr == 0);
143
144 /* test that nothing is sent with link uo but netif down */
145 netif_set_link_up(&test_netif6);
146 ip6_test_handle_timers(500);
147 fail_unless(linkoutput_ctr == 0);
148 netif_set_link_down(&test_netif6);
149 fail_unless(linkoutput_ctr == 0);
150
151 /* test that nothing is sent with link down but netif up */
152 netif_set_up(&test_netif6);
153 ip6_test_handle_timers(500);
154 fail_unless(linkoutput_ctr == 0);
155 netif_set_down(&test_netif6);
156 fail_unless(linkoutput_ctr == 0);
157
158 /* test what is sent with link up + netif up */
159 netif_set_link_up(&test_netif6);
160 netif_set_up(&test_netif6);
161 ip6_test_handle_timers(500);
162 fail_unless(linkoutput_ctr == expected_ctr1);
163 netif_set_down(&test_netif6);
164 netif_set_link_down(&test_netif6);
165 fail_unless(linkoutput_ctr == expected_ctr1);
166 linkoutput_ctr = 0;
167
168 netif_set_up(&test_netif6);
169 netif_set_link_up(&test_netif6);
170 ip6_test_handle_timers(500);
171 fail_unless(linkoutput_ctr == expected_ctr2);
172 netif_set_link_down(&test_netif6);
173 netif_set_down(&test_netif6);
174 fail_unless(linkoutput_ctr == expected_ctr2);
175 linkoutput_ctr = 0;
176 }
177
START_TEST(test_ip6_ll_addr)178 START_TEST(test_ip6_ll_addr)
179 {
180 LWIP_UNUSED_ARG(_i);
181
182 linkoutput_ctr = 0;
183
184 /* test without link-local address */
185 test_ip6_ll_addr_iter(0, 0);
186
187 /* test with link-local address */
188 netif_create_ip6_linklocal_address(&test_netif6, 1);
189 test_ip6_ll_addr_iter(3 + LWIP_IPV6_DUP_DETECT_ATTEMPTS + LWIP_IPV6_MLD, 3);
190 }
191 END_TEST
192
START_TEST(test_ip6_aton_ipv4mapped)193 START_TEST(test_ip6_aton_ipv4mapped)
194 {
195 int ret;
196 ip_addr_t addr;
197 ip6_addr_t addr6;
198 const ip_addr_t addr_expected = IPADDR6_INIT_HOST(0, 0, 0xFFFF, 0xD4CC65D2);
199 const char *full_ipv6_addr = "0:0:0:0:0:FFFF:D4CC:65D2";
200 const char *shortened_ipv6_addr = "::FFFF:D4CC:65D2";
201 const char *full_ipv4_mapped_addr = "0:0:0:0:0:FFFF:212.204.101.210";
202 const char *shortened_ipv4_mapped_addr = "::FFFF:212.204.101.210";
203 const char *bogus_ipv4_mapped_addr = "::FFFF:212.204.101.2101";
204 LWIP_UNUSED_ARG(_i);
205
206 /* check IPv6 representation */
207 memset(&addr6, 0, sizeof(addr6));
208 ret = ip6addr_aton(full_ipv6_addr, &addr6);
209 fail_unless(ret == 1);
210 fail_unless(memcmp(&addr6, &addr_expected, 16) == 0);
211 memset(&addr, 0, sizeof(addr));
212 ret = ipaddr_aton(full_ipv6_addr, &addr);
213 fail_unless(ret == 1);
214 fail_unless(memcmp(&addr, &addr_expected, 16) == 0);
215
216 /* check shortened IPv6 representation */
217 memset(&addr6, 0, sizeof(addr6));
218 ret = ip6addr_aton(shortened_ipv6_addr, &addr6);
219 fail_unless(ret == 1);
220 fail_unless(memcmp(&addr6, &addr_expected, 16) == 0);
221 memset(&addr, 0, sizeof(addr));
222 ret = ipaddr_aton(shortened_ipv6_addr, &addr);
223 fail_unless(ret == 1);
224 fail_unless(memcmp(&addr, &addr_expected, 16) == 0);
225
226 /* checked shortened mixed representation */
227 memset(&addr6, 0, sizeof(addr6));
228 ret = ip6addr_aton(shortened_ipv4_mapped_addr, &addr6);
229 fail_unless(ret == 1);
230 fail_unless(memcmp(&addr6, &addr_expected, 16) == 0);
231 memset(&addr, 0, sizeof(addr));
232 ret = ipaddr_aton(shortened_ipv4_mapped_addr, &addr);
233 fail_unless(ret == 1);
234 fail_unless(memcmp(&addr, &addr_expected, 16) == 0);
235
236 /* checked mixed representation */
237 memset(&addr6, 0, sizeof(addr6));
238 ret = ip6addr_aton(full_ipv4_mapped_addr, &addr6);
239 fail_unless(ret == 1);
240 fail_unless(memcmp(&addr6, &addr_expected, 16) == 0);
241 memset(&addr, 0, sizeof(addr));
242 ret = ipaddr_aton(full_ipv4_mapped_addr, &addr);
243 fail_unless(ret == 1);
244 fail_unless(memcmp(&addr, &addr_expected, 16) == 0);
245
246 /* checked bogus mixed representation */
247 memset(&addr6, 0, sizeof(addr6));
248 ret = ip6addr_aton(bogus_ipv4_mapped_addr, &addr6);
249 fail_unless(ret == 0);
250 memset(&addr, 0, sizeof(addr));
251 ret = ipaddr_aton(bogus_ipv4_mapped_addr, &addr);
252 fail_unless(ret == 0);
253 }
254 END_TEST
255
START_TEST(test_ip6_ntoa_ipv4mapped)256 START_TEST(test_ip6_ntoa_ipv4mapped)
257 {
258 const ip_addr_t addr = IPADDR6_INIT_HOST(0, 0, 0xFFFF, 0xD4CC65D2);
259 char buf[128];
260 char *str;
261 LWIP_UNUSED_ARG(_i);
262
263 str = ip6addr_ntoa_r(ip_2_ip6(&addr), buf, sizeof(buf));
264 fail_unless(str == buf);
265 fail_unless(!strcmp(str, "::FFFF:212.204.101.210"));
266 }
267 END_TEST
268
269 struct test_addr_and_str {
270 ip_addr_t addr;
271 const char *str;
272 };
273
START_TEST(test_ip6_ntoa)274 START_TEST(test_ip6_ntoa)
275 {
276 struct test_addr_and_str tests[] = {
277 {IPADDR6_INIT_HOST(0xfe800000, 0x00000000, 0xb2a1a2ff, 0xfea3a4a5), "FE80::B2A1:A2FF:FEA3:A4A5"}, /* test shortened zeros */
278 {IPADDR6_INIT_HOST(0xfe800000, 0xff000000, 0xb2a1a2ff, 0xfea3a4a5), "FE80:0:FF00:0:B2A1:A2FF:FEA3:A4A5"}, /* don't omit single zero blocks */
279 {IPADDR6_INIT_HOST(0xfe800000, 0xff000000, 0xb2000000, 0x0000a4a5), "FE80:0:FF00:0:B200::A4A5"}, /* omit longest zero block */
280 };
281 char buf[128];
282 char *str;
283 size_t i;
284 LWIP_UNUSED_ARG(_i);
285
286 for (i = 0; i < LWIP_ARRAYSIZE(tests); i++) {
287 str = ip6addr_ntoa_r(ip_2_ip6(&tests[i].addr), buf, sizeof(buf));
288 fail_unless(str == buf);
289 fail_unless(!strcmp(str, tests[i].str));
290 }
291 }
292 END_TEST
293
START_TEST(test_ip6_lladdr)294 START_TEST(test_ip6_lladdr)
295 {
296 u8_t zeros[128];
297 const u8_t test_mac_addr[6] = {0xb0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5};
298 const u32_t expected_ip6_addr_1[4] = {PP_HTONL(0xfe800000), 0, PP_HTONL(0xb2a1a2ff), PP_HTONL(0xfea3a4a5)};
299 const u32_t expected_ip6_addr_2[4] = {PP_HTONL(0xfe800000), 0, PP_HTONL(0x0000b0a1), PP_HTONL(0xa2a3a4a5)};
300 LWIP_UNUSED_ARG(_i);
301 memset(zeros, 0, sizeof(zeros));
302
303 fail_unless(test_netif6.hwaddr_len == 6);
304 fail_unless(!memcmp(test_netif6.hwaddr, zeros, 6));
305
306 fail_unless(test_netif6.ip6_addr_state[0] == 0);
307 fail_unless(!memcmp(netif_ip6_addr(&test_netif6, 0), zeros, sizeof(ip6_addr_t)));
308
309 /* set specific mac addr */
310 memcpy(test_netif6.hwaddr, test_mac_addr, 6);
311
312 /* create link-local addr based on mac (EUI-48) */
313 netif_create_ip6_linklocal_address(&test_netif6, 1);
314 fail_unless(IP_IS_V6(&test_netif6.ip6_addr[0]));
315 fail_unless(!memcmp(&netif_ip6_addr(&test_netif6, 0)->addr, expected_ip6_addr_1, 16));
316 #if LWIP_IPV6_SCOPES
317 fail_unless(netif_ip6_addr(&test_netif6, 0)->zone == (test_netif6.num + 1));
318 #endif
319 /* reset address */
320 memset(&test_netif6.ip6_addr[0], 0, sizeof(ip6_addr_t));
321 test_netif6.ip6_addr_state[0] = 0;
322
323 /* create link-local addr based interface ID */
324 netif_create_ip6_linklocal_address(&test_netif6, 0);
325 fail_unless(IP_IS_V6(&test_netif6.ip6_addr[0]));
326 fail_unless(!memcmp(&netif_ip6_addr(&test_netif6, 0)->addr, expected_ip6_addr_2, 16));
327 #if LWIP_IPV6_SCOPES
328 fail_unless(netif_ip6_addr(&test_netif6, 0)->zone == (test_netif6.num + 1));
329 #endif
330 /* reset address */
331 memset(&test_netif6.ip6_addr[0], 0, sizeof(ip6_addr_t));
332 test_netif6.ip6_addr_state[0] = 0;
333
334 /* reset mac address */
335 memset(&test_netif6.hwaddr, 0, sizeof(test_netif6.hwaddr));
336 }
337 END_TEST
338
339 static struct pbuf *cloned_pbuf = NULL;
clone_output(struct netif * netif,struct pbuf * p,const ip6_addr_t * addr)340 static err_t clone_output(struct netif *netif, struct pbuf *p, const ip6_addr_t *addr) {
341 LWIP_UNUSED_ARG(netif);
342 LWIP_UNUSED_ARG(addr);
343 cloned_pbuf = pbuf_clone(PBUF_RAW, PBUF_RAM, p);
344 return ERR_OK;
345 }
346
347 /* Reproduces bug #58553 */
START_TEST(test_ip6_dest_unreachable_chained_pbuf)348 START_TEST(test_ip6_dest_unreachable_chained_pbuf)
349 {
350
351 ip_addr_t my_addr = IPADDR6_INIT_HOST(0x20010db8, 0x0, 0x0, 0x1);
352 ip_addr_t peer_addr = IPADDR6_INIT_HOST(0x20010db8, 0x0, 0x0, 0x4);
353 /* Create chained pbuf with UDP data that will get destination unreachable */
354 u8_t udp_hdr[] = {
355 0x60, 0x00, 0x27, 0x03, 0x00, 0x2d, 0x11, 0x40,
356 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00,
357 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
358 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00,
359 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
360 0x01, 0xff, 0x03, 0xff, 0x00, 0x2d, 0x00, 0x00,
361 };
362 struct pbuf *header = pbuf_alloc(PBUF_RAW, sizeof(udp_hdr), PBUF_ROM);
363 u8_t udp_payload[] = "abcdefghijklmnopqrstuvwxyz0123456789";
364 struct pbuf *data = pbuf_alloc(PBUF_RAW, sizeof(udp_payload), PBUF_ROM);
365 u8_t *icmpptr;
366 struct ip6_hdr *outhdr;
367 struct icmp6_hdr *icmp6hdr;
368 LWIP_UNUSED_ARG(_i);
369
370 fail_unless(header);
371 header->payload = udp_hdr;
372 fail_unless(data);
373 data->payload = udp_payload;
374 pbuf_cat(header, data);
375 data = NULL;
376
377 /* Configure and enable local address */
378 netif_set_up(&test_netif6);
379 netif_ip6_addr_set(&test_netif6, 0, ip_2_ip6(&my_addr));
380 netif_ip6_addr_set_state(&test_netif6, 0, IP6_ADDR_VALID);
381 test_netif6.output_ip6 = clone_output;
382
383 /* Process packet and send ICMPv6 reply for unreachable UDP port */
384 ip6_input(header, &test_netif6);
385 header = NULL;
386
387 /* Verify ICMP reply packet contents */
388 fail_unless(cloned_pbuf);
389 fail_unless(cloned_pbuf->len == IP6_HLEN + ICMP6_HLEN + sizeof(udp_hdr) + sizeof(udp_payload));
390 outhdr = (struct ip6_hdr*) cloned_pbuf->payload;
391 fail_unless(ip6_addr_packed_eq(ip_2_ip6(&my_addr), &outhdr->src, IP6_NO_ZONE));
392 fail_unless(ip6_addr_packed_eq(ip_2_ip6(&peer_addr), &outhdr->dest, IP6_NO_ZONE));
393 icmpptr = &((u8_t*)cloned_pbuf->payload)[IP6_HLEN];
394 icmp6hdr = (struct icmp6_hdr*) icmpptr;
395 fail_unless(icmp6hdr->type == ICMP6_TYPE_DUR);
396 fail_unless(icmp6hdr->code == ICMP6_DUR_PORT);
397 fail_unless(icmp6hdr->data == lwip_htonl(0));
398 icmpptr += ICMP6_HLEN;
399 fail_unless(memcmp(icmpptr, udp_hdr, sizeof(udp_hdr)) == 0, "mismatch in copied ip6/udp header");
400 icmpptr += sizeof(udp_hdr);
401 fail_unless(memcmp(icmpptr, udp_payload, sizeof(udp_payload)) == 0, "mismatch in copied udp payload");
402 pbuf_free(cloned_pbuf);
403 }
404 END_TEST
405
406 /* Reproduces bug #57374 */
START_TEST(test_ip6_frag_pbuf_len_assert)407 START_TEST(test_ip6_frag_pbuf_len_assert)
408 {
409 ip_addr_t my_addr = IPADDR6_INIT_HOST(0x20010db8, 0x0, 0x0, 0x1);
410 ip_addr_t peer_addr = IPADDR6_INIT_HOST(0x20010db8, 0x0, 0x0, 0x4);
411 struct pbuf *payload, *hdr;
412 err_t err;
413 int i;
414 LWIP_UNUSED_ARG(_i);
415
416 /* Configure and enable local address */
417 test_netif6.mtu = 1500;
418 netif_set_up(&test_netif6);
419 netif_ip6_addr_set(&test_netif6, 0, ip_2_ip6(&my_addr));
420 netif_ip6_addr_set_state(&test_netif6, 0, IP6_ADDR_VALID);
421
422 /* Create packet with lots of small pbufs around mtu limit */
423 payload = pbuf_alloc(PBUF_RAW, 1400, PBUF_POOL);
424 fail_unless(payload != NULL);
425 for (i = 0; i < 16; i++) {
426 struct pbuf *p = pbuf_alloc(PBUF_RAW, 32, PBUF_RAM);
427 fail_unless(p != NULL);
428 pbuf_cat(payload, p);
429 }
430 /* Prefix with header like UDP would */
431 hdr = pbuf_alloc(PBUF_IP, 8, PBUF_RAM);
432 fail_unless(hdr != NULL);
433 pbuf_chain(hdr, payload);
434
435 /* Send it and don't crash while fragmenting */
436 err = ip6_output_if_src(hdr, ip_2_ip6(&my_addr), ip_2_ip6(&peer_addr), 15, 0, IP_PROTO_UDP, &test_netif6);
437 fail_unless(err == ERR_OK);
438
439 pbuf_free(hdr);
440 pbuf_free(payload);
441 }
442 END_TEST
443
direct_output(struct netif * netif,struct pbuf * p,const ip6_addr_t * addr)444 static err_t direct_output(struct netif *netif, struct pbuf *p, const ip6_addr_t *addr) {
445 LWIP_UNUSED_ARG(addr);
446 return netif->linkoutput(netif, p);
447 }
448
START_TEST(test_ip6_frag)449 START_TEST(test_ip6_frag)
450 {
451 ip_addr_t my_addr = IPADDR6_INIT_HOST(0x20010db8, 0x0, 0x0, 0x1);
452 ip_addr_t peer_addr = IPADDR6_INIT_HOST(0x20010db8, 0x0, 0x0, 0x4);
453 struct pbuf *data;
454 err_t err;
455 LWIP_UNUSED_ARG(_i);
456
457 /* Configure and enable local address */
458 test_netif6.mtu = 1500;
459 netif_set_up(&test_netif6);
460 netif_ip6_addr_set(&test_netif6, 0, ip_2_ip6(&my_addr));
461 netif_ip6_addr_set_state(&test_netif6, 0, IP6_ADDR_VALID);
462 test_netif6.output_ip6 = direct_output;
463 /* Reset counters after multicast traffic */
464 linkoutput_ctr = 0;
465 linkoutput_byte_ctr = 0;
466
467 /* Verify that 8000 byte payload is split into six packets */
468 data = pbuf_alloc(PBUF_IP, 8000, PBUF_RAM);
469 fail_unless(data != NULL);
470 err = ip6_output_if_src(data, ip_2_ip6(&my_addr), ip_2_ip6(&peer_addr),
471 15, 0, IP_PROTO_UDP, &test_netif6);
472 fail_unless(err == ERR_OK);
473 fail_unless(linkoutput_ctr == 6);
474 fail_unless(linkoutput_byte_ctr == (8000 + (6 * (IP6_HLEN + IP6_FRAG_HLEN))));
475 pbuf_free(data);
476 }
477 END_TEST
478
test_ip6_reass_helper(u32_t ip_id,const u16_t * segments,size_t num_segs,u16_t seglen)479 static void test_ip6_reass_helper(u32_t ip_id, const u16_t *segments, size_t num_segs, u16_t seglen)
480 {
481 ip_addr_t my_addr = IPADDR6_INIT_HOST(0x20010db8, 0x0, 0x0, 0x1);
482 size_t i;
483
484 memset(&lwip_stats.mib2, 0, sizeof(lwip_stats.mib2));
485 memset(&lwip_stats.ip6_frag, 0, sizeof(lwip_stats.ip6_frag));
486
487 netif_set_up(&test_netif6);
488 netif_ip6_addr_set(&test_netif6, 0, ip_2_ip6(&my_addr));
489 netif_ip6_addr_set_state(&test_netif6, 0, IP6_ADDR_VALID);
490
491 for (i = 0; i < num_segs; i++) {
492 u16_t seg = segments[i];
493 int last = seg + 1U == num_segs;
494 create_ip6_input_fragment(ip_id, seg * seglen, seglen, last, IP6_NEXTH_UDP);
495 fail_unless(lwip_stats.ip6_frag.recv == i + 1);
496 fail_unless(lwip_stats.ip6_frag.err == 0);
497 fail_unless(lwip_stats.ip6_frag.memerr == 0);
498 fail_unless(lwip_stats.ip6_frag.drop == 0);
499 if (i + 1 == num_segs) {
500 fail_unless(lwip_stats.mib2.ip6reasmoks == 1);
501 }
502 else {
503 fail_unless(lwip_stats.mib2.ip6reasmoks == 0);
504 }
505 }
506 }
507
START_TEST(test_ip6_reass)508 START_TEST(test_ip6_reass)
509 {
510 #define NUM_SEGS 9
511 const u16_t t1[NUM_SEGS] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
512 const u16_t t2[NUM_SEGS] = { 8, 0, 1, 2, 3, 4, 7, 6, 5 };
513 const u16_t t3[NUM_SEGS] = { 1, 2, 3, 4, 5, 6, 7, 8, 0 };
514 const u16_t t4[NUM_SEGS] = { 8, 2, 4, 6, 7, 5, 3, 1, 0 };
515 LWIP_UNUSED_ARG(_i);
516
517 test_ip6_reass_helper(128, t1, NUM_SEGS, 200);
518 test_ip6_reass_helper(129, t2, NUM_SEGS, 208);
519 test_ip6_reass_helper(130, t3, NUM_SEGS, 8);
520 test_ip6_reass_helper(130, t4, NUM_SEGS, 1448);
521 }
522
523 /** Create the suite including all tests for this module */
524 Suite *
ip6_suite(void)525 ip6_suite(void)
526 {
527 testfunc tests[] = {
528 TESTFUNC(test_ip6_ll_addr),
529 TESTFUNC(test_ip6_aton_ipv4mapped),
530 TESTFUNC(test_ip6_ntoa_ipv4mapped),
531 TESTFUNC(test_ip6_ntoa),
532 TESTFUNC(test_ip6_lladdr),
533 TESTFUNC(test_ip6_dest_unreachable_chained_pbuf),
534 TESTFUNC(test_ip6_frag_pbuf_len_assert),
535 TESTFUNC(test_ip6_frag),
536 TESTFUNC(test_ip6_reass)
537 };
538 return create_suite("IPv6", tests, sizeof(tests)/sizeof(testfunc), ip6_setup, ip6_teardown);
539 }
540
541 #else /* LWIP_IPV6 */
542
543 /* allow to build the unit tests without IPv6 support */
START_TEST(test_ip6_dummy)544 START_TEST(test_ip6_dummy)
545 {
546 LWIP_UNUSED_ARG(_i);
547 }
548 END_TEST
549
550 Suite *
ip6_suite(void)551 ip6_suite(void)
552 {
553 testfunc tests[] = {
554 TESTFUNC(test_ip6_dummy),
555 };
556 return create_suite("IPv6", tests, sizeof(tests)/sizeof(testfunc), NULL, NULL);
557 }
558 #endif /* LWIP_IPV6 */
559