• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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