[cloud] Allow aws-import script to run on Python 3.6
[ipxe.git] / src / tests / ipv6_test.c
1 /*
2 * Copyright (C) 2013 Michael Brown <mbrown@fensystems.co.uk>.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301, USA.
18 *
19 * You can also choose to distribute this program under the terms of
20 * the Unmodified Binary Distribution Licence (as given in the file
21 * COPYING.UBDL), provided that you have satisfied its requirements.
22 */
23
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25
26 /** @file
27 *
28 * IPv6 tests
29 *
30 */
31
32 /* Forcibly enable assertions */
33 #undef NDEBUG
34
35 #include <stdint.h>
36 #include <string.h>
37 #include <byteswap.h>
38 #include <ipxe/ipv6.h>
39 #include <ipxe/test.h>
40
41 /** Define inline IPv6 address */
42 #define IPV6(...) { __VA_ARGS__ }
43
44 /** An IPv6 test routing table entry */
45 struct ipv6_test_route {
46 /** Local address */
47 const char *address;
48 /** Prefix length */
49 unsigned int prefix_len;
50 /** Router address (if any) */
51 const char *router;
52 };
53
54 /** An IPv6 test routing table */
55 struct ipv6_test_table {
56 /** Test routing table entries */
57 const struct ipv6_test_route *routes;
58 /** Number of table entries */
59 unsigned int count;
60 /** Constructed routing table */
61 struct list_head list;
62 };
63
64 /** Define a test routing table */
65 #define TABLE( name, ... ) \
66 static const struct ipv6_test_route name ## _routes[] = { \
67 __VA_ARGS__ \
68 }; \
69 static struct ipv6_test_table name = { \
70 .routes = name ## _routes, \
71 .count = ( sizeof ( name ## _routes ) / \
72 sizeof ( name ## _routes[0] ) ), \
73 .list = LIST_HEAD_INIT ( name.list ), \
74 };
75
76 /** The unspecified IPv6 address */
77 static const struct in6_addr sample_unspecified = {
78 .s6_addr = IPV6 ( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
79 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ),
80 };
81
82 /** A sample link-local IPv6 address */
83 static const struct in6_addr sample_link_local = {
84 .s6_addr = IPV6 ( 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
85 0x00, 0x00, 0x69, 0xff, 0xfe, 0x50, 0x58, 0x45 ),
86 };
87
88 /** A sample site-local IPv6 address */
89 static const struct in6_addr sample_site_local = {
90 .s6_addr = IPV6 ( 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
91 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 ),
92 };
93
94 /** A sample ULA IPv6 address */
95 static const struct in6_addr sample_ula = {
96 .s6_addr = IPV6 ( 0xfd, 0x44, 0x91, 0x12, 0x64, 0x42, 0x00, 0x00,
97 0x00, 0x00, 0x69, 0xff, 0xfe, 0x50, 0x58, 0x45 ),
98 };
99
100 /** A sample global IPv6 address */
101 static const struct in6_addr sample_global = {
102 .s6_addr = IPV6 ( 0x20, 0x01, 0x0b, 0xa8, 0x00, 0x00, 0x01, 0xd4,
103 0x00, 0x00, 0x00, 0x00, 0x69, 0x50, 0x58, 0x45 ),
104 };
105
106 /** A sample multicast IPv6 address */
107 static const struct in6_addr sample_multicast = {
108 .s6_addr = IPV6 ( 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
109 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 ),
110 };
111
112 /** Dummy network device used for routing tests */
113 static struct net_device ipv6_test_netdev = {
114 .refcnt = REF_INIT ( ref_no_free ),
115 .index = 42,
116 .state = NETDEV_OPEN,
117 };
118
119 /** Routing table with only a link-local address */
120 TABLE ( table_link_local,
121 { "fe80::69ff:fe50:5845", 64, NULL } );
122
123 /** Routing table with a global address */
124 TABLE ( table_normal,
125 { "fe80::69ff:fe50:5845", 64, NULL },
126 { "2001:db8:3::1", 64, "fe80::1" } );
127
128 /** Routing table with multiple addresses and routers */
129 TABLE ( table_multi,
130 { "fe80::69ff:fe50:5845", 64, NULL },
131 { "2001:db8:3::1", 64, "fe80::1" },
132 { "2001:db8:5::1", 64, NULL },
133 { "2001:db8:42::1", 64, "fe80::2" },
134 { "fd44:9112:6442::69ff:fe50:5845", 64, "fe80::1" },
135 { "fd70:6ba9:50ae::69ff:fe50:5845", 64, "fe80::3" } );
136
137 /**
138 * Report an inet6_ntoa() test result
139 *
140 * @v addr IPv6 address
141 * @v text Expected textual representation
142 * @v file Test code file
143 * @v line Test code line
144 */
145 static void inet6_ntoa_okx ( const struct in6_addr *addr, const char *text,
146 const char *file, unsigned int line ) {
147 char *actual;
148
149 actual = inet6_ntoa ( addr );
150 DBG ( "inet6_ntoa ( %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x ) "
151 "= %s\n", ntohs ( addr->s6_addr16[0] ),
152 ntohs ( addr->s6_addr16[1] ), ntohs ( addr->s6_addr16[2] ),
153 ntohs ( addr->s6_addr16[3] ), ntohs ( addr->s6_addr16[4] ),
154 ntohs ( addr->s6_addr16[5] ), ntohs ( addr->s6_addr16[6] ),
155 ntohs ( addr->s6_addr16[7] ), actual );
156 okx ( strcmp ( actual, text ) == 0, file, line );
157 }
158 #define inet6_ntoa_ok( addr, text ) do { \
159 static const struct in6_addr in = { \
160 .s6_addr = addr, \
161 }; \
162 inet6_ntoa_okx ( &in, text, __FILE__, __LINE__ ); \
163 } while ( 0 )
164
165 /**
166 * Report an inet6_aton() test result
167 *
168 * @v text Textual representation
169 * @v addr Expected IPv6 address
170 * @v file Test code file
171 * @v line Test code line
172 */
173 static void inet6_aton_okx ( const char *text, const struct in6_addr *addr,
174 const char *file, unsigned int line ) {
175 struct in6_addr actual;
176
177 okx ( inet6_aton ( text, &actual ) == 0, file, line );
178 DBG ( "inet6_aton ( \"%s\" ) = %s\n", text, inet6_ntoa ( &actual ) );
179 okx ( memcmp ( &actual, addr, sizeof ( actual ) ) == 0,
180 file, line );
181 }
182 #define inet6_aton_ok( text, addr ) do { \
183 static const struct in6_addr in = { \
184 .s6_addr = addr, \
185 }; \
186 inet6_aton_okx ( text, &in, __FILE__, __LINE__ ); \
187 } while ( 0 )
188
189 /**
190 * Report an inet6_aton() failure test result
191 *
192 * @v text Textual representation
193 * @v file Test code file
194 * @v line Test code line
195 */
196 static void inet6_aton_fail_okx ( const char *text, const char *file,
197 unsigned int line ) {
198 struct in6_addr dummy;
199
200 okx ( inet6_aton ( text, &dummy ) != 0, file, line );
201 }
202 #define inet6_aton_fail_ok( text ) \
203 inet6_aton_fail_okx ( text, __FILE__, __LINE__ )
204
205 /**
206 * Create test routing table
207 *
208 * @v table Test routing table
209 * @v file Test code file
210 * @v line Test code line
211 */
212 static void ipv6_table_okx ( struct ipv6_test_table *table, const char *file,
213 unsigned int line ) {
214 const struct ipv6_test_route *route;
215 struct in6_addr address;
216 struct in6_addr router;
217 struct list_head saved;
218 unsigned int i;
219
220 /* Sanity check */
221 okx ( list_empty ( &table->list ), file, line );
222
223 /* Save existing routing table */
224 INIT_LIST_HEAD ( &saved );
225 list_splice_init ( &ipv6_miniroutes, &saved );
226
227 /* Construct routing table */
228 for ( i = 0 ; i < table->count ; i++ ) {
229
230 /* Parse address and router (if applicable) */
231 route = &table->routes[i];
232 okx ( inet6_aton ( route->address, &address ) == 0,
233 file, line );
234 if ( route->router ) {
235 okx ( inet6_aton ( route->router, &router ) == 0,
236 file, line );
237 }
238
239 /* Add routing table entry */
240 okx ( ipv6_add_miniroute ( &ipv6_test_netdev, &address,
241 route->prefix_len,
242 ( route->router ?
243 &router : NULL ) ) == 0,
244 file, line );
245 }
246
247 /* Save constructed routing table */
248 list_splice_init ( &ipv6_miniroutes, &table->list );
249
250 /* Restore original routing table */
251 list_splice ( &saved, &ipv6_miniroutes );
252 }
253 #define ipv6_table_ok( table ) \
254 ipv6_table_okx ( table, __FILE__, __LINE__ )
255
256 /**
257 * Report an ipv6_route() test result
258 *
259 * @v table Test routing table
260 * @v dest Destination address
261 * @v src Expected source address, or NULL to expect failure
262 * @v next Expected next hop address, or NULL to expect destination
263 * @v file Test code file
264 * @v line Test code line
265 */
266 static void ipv6_route_okx ( struct ipv6_test_table *table, const char *dest,
267 const char *src, const char *next,
268 const char *file, unsigned int line ) {
269 struct in6_addr in_dest;
270 struct in6_addr in_src;
271 struct in6_addr in_next;
272 struct in6_addr *actual;
273 struct ipv6_miniroute *miniroute;
274 struct list_head saved;
275
276 /* Switch to test routing table */
277 INIT_LIST_HEAD ( &saved );
278 list_splice_init ( &ipv6_miniroutes, &saved );
279 list_splice_init ( &table->list, &ipv6_miniroutes );
280
281 /* Parse addresses */
282 okx ( inet6_aton ( dest, &in_dest ) == 0, file, line );
283 if ( src )
284 okx ( inet6_aton ( src, &in_src ) == 0, file, line );
285 if ( next ) {
286 okx ( inet6_aton ( next, &in_next ) == 0, file, line );
287 } else {
288 memcpy ( &in_next, &in_dest, sizeof ( in_next ) );
289 }
290
291 /* Perform routing */
292 actual = &in_dest;
293 miniroute = ipv6_route ( ipv6_test_netdev.index, &actual );
294
295 /* Validate result */
296 if ( src ) {
297
298 /* Check that a route was found */
299 okx ( miniroute != NULL, file, line );
300 DBG ( "ipv6_route ( %s ) = %s", dest, inet6_ntoa ( actual ) );
301 DBG ( " from %s\n", inet6_ntoa ( &miniroute->address ) );
302
303 /* Check that expected source address was used */
304 okx ( memcmp ( &miniroute->address, &in_src,
305 sizeof ( in_src ) ) == 0, file, line );
306
307 /* Check that expected next hop address was used */
308 okx ( memcmp ( actual, &in_next, sizeof ( *actual ) ) == 0,
309 file, line );
310
311 } else {
312
313 /* Routing is expected to fail */
314 okx ( miniroute == NULL, file, line );
315 }
316
317 /* Restore original routing table */
318 list_splice_init ( &ipv6_miniroutes, &table->list );
319 list_splice ( &saved, &ipv6_miniroutes );
320 }
321 #define ipv6_route_ok( table, dest, src, next ) \
322 ipv6_route_okx ( table, dest, src, next, __FILE__, __LINE__ )
323
324 /**
325 * Destroy test routing table
326 *
327 * @v table Test routing table
328 */
329 static void ipv6_table_del ( struct ipv6_test_table *table ) {
330 struct ipv6_miniroute *miniroute;
331 struct ipv6_miniroute *tmp;
332 struct list_head saved;
333
334 /* Switch to test routing table */
335 INIT_LIST_HEAD ( &saved );
336 list_splice_init ( &ipv6_miniroutes, &saved );
337 list_splice_init ( &table->list, &ipv6_miniroutes );
338
339 /* Delete all existing routes */
340 list_for_each_entry_safe ( miniroute, tmp, &ipv6_miniroutes, list )
341 ipv6_del_miniroute ( miniroute );
342
343 /* Restore original routing table */
344 list_splice ( &saved, &ipv6_miniroutes );
345 }
346
347 /**
348 * Perform IPv6 self-tests
349 *
350 */
351 static void ipv6_test_exec ( void ) {
352
353 /* Address testing macros */
354 ok ( IN6_IS_ADDR_UNSPECIFIED ( &sample_unspecified ) );
355 ok ( ! IN6_IS_ADDR_UNSPECIFIED ( &sample_link_local ) );
356 ok ( ! IN6_IS_ADDR_UNSPECIFIED ( &sample_site_local ) );
357 ok ( ! IN6_IS_ADDR_UNSPECIFIED ( &sample_ula ) );
358 ok ( ! IN6_IS_ADDR_UNSPECIFIED ( &sample_global ) );
359 ok ( ! IN6_IS_ADDR_UNSPECIFIED ( &sample_multicast ) );
360 ok ( ! IN6_IS_ADDR_MULTICAST ( &sample_unspecified ) );
361 ok ( ! IN6_IS_ADDR_MULTICAST ( &sample_link_local ) );
362 ok ( ! IN6_IS_ADDR_MULTICAST ( &sample_site_local ) );
363 ok ( ! IN6_IS_ADDR_MULTICAST ( &sample_ula ) );
364 ok ( ! IN6_IS_ADDR_MULTICAST ( &sample_global ) );
365 ok ( IN6_IS_ADDR_MULTICAST ( &sample_multicast ) );
366 ok ( ! IN6_IS_ADDR_LINKLOCAL ( &sample_unspecified ) );
367 ok ( IN6_IS_ADDR_LINKLOCAL ( &sample_link_local ) );
368 ok ( ! IN6_IS_ADDR_LINKLOCAL ( &sample_site_local ) );
369 ok ( ! IN6_IS_ADDR_LINKLOCAL ( &sample_ula ) );
370 ok ( ! IN6_IS_ADDR_LINKLOCAL ( &sample_global ) );
371 ok ( ! IN6_IS_ADDR_LINKLOCAL ( &sample_multicast ) );
372 ok ( ! IN6_IS_ADDR_SITELOCAL ( &sample_unspecified ) );
373 ok ( ! IN6_IS_ADDR_SITELOCAL ( &sample_link_local ) );
374 ok ( IN6_IS_ADDR_SITELOCAL ( &sample_site_local ) );
375 ok ( ! IN6_IS_ADDR_SITELOCAL ( &sample_ula ) );
376 ok ( ! IN6_IS_ADDR_SITELOCAL ( &sample_global ) );
377 ok ( ! IN6_IS_ADDR_SITELOCAL ( &sample_multicast ) );
378 ok ( ! IN6_IS_ADDR_ULA ( &sample_unspecified ) );
379 ok ( ! IN6_IS_ADDR_ULA ( &sample_link_local ) );
380 ok ( ! IN6_IS_ADDR_ULA ( &sample_site_local ) );
381 ok ( IN6_IS_ADDR_ULA ( &sample_ula ) );
382 ok ( ! IN6_IS_ADDR_ULA ( &sample_global ) );
383 ok ( ! IN6_IS_ADDR_ULA ( &sample_multicast ) );
384
385 /* inet6_ntoa() tests */
386 inet6_ntoa_ok ( IPV6 ( 0x20, 0x01, 0x0b, 0xa8, 0x00, 0x00, 0x01, 0xd4,
387 0x00, 0x00, 0x00, 0x00, 0x69, 0x50, 0x58, 0x45 ),
388 "2001:ba8:0:1d4::6950:5845" );
389 /* No zeros */
390 inet6_ntoa_ok ( IPV6 ( 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x01, 0x00, 0x01,
391 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01 ),
392 "2001:db8:1:1:1:1:1:1" );
393 /* Run of zeros */
394 inet6_ntoa_ok ( IPV6 ( 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00,
395 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 ),
396 "2001:db8::1" );
397 /* No "::" for single zero */
398 inet6_ntoa_ok ( IPV6 ( 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x01,
399 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01 ),
400 "2001:db8:0:1:1:1:1:1" );
401 /* Use "::" for longest run of zeros */
402 inet6_ntoa_ok ( IPV6 ( 0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
403 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 ),
404 "2001:0:0:1::1" );
405 /* Use "::" for leftmost equal-length run of zeros */
406 inet6_ntoa_ok ( IPV6 ( 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00,
407 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 ),
408 "2001:db8::1:0:0:1" );
409 /* Trailing run of zeros */
410 inet6_ntoa_ok ( IPV6 ( 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
411 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ),
412 "fe80::" );
413 /* Leading run of zeros */
414 inet6_ntoa_ok ( IPV6 ( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
415 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 ),
416 "::1" );
417 /* All zeros */
418 inet6_ntoa_ok ( IPV6 ( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
419 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ),
420 "::" );
421 /* Maximum length */
422 inet6_ntoa_ok ( IPV6 ( 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
423 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff ),
424 "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff" );
425
426 /* inet6_aton() tests */
427 inet6_aton_ok ( "2001:ba8:0:1d4::6950:5845",
428 IPV6 ( 0x20, 0x01, 0x0b, 0xa8, 0x00, 0x00, 0x01, 0xd4,
429 0x00, 0x00, 0x00, 0x00, 0x69, 0x50, 0x58, 0x45));
430 /* No zeros */
431 inet6_aton_ok ( "2001:db8:1:1:1:1:1:1",
432 IPV6 ( 0x20, 0x01, 0x0d, 0xb8, 0x00, 0x01, 0x00, 0x01,
433 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01));
434 /* All intervening zeros */
435 inet6_aton_ok ( "fe80::1",
436 IPV6 ( 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
437 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01));
438 /* Trailing run of zeros */
439 inet6_aton_ok ( "fe80::",
440 IPV6 ( 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
441 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00));
442 /* Leading run of zeros */
443 inet6_aton_ok ( "::1",
444 IPV6 ( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
445 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01));
446 /* All zeros */
447 inet6_aton_ok ( "::",
448 IPV6 ( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
449 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00));
450
451 /* inet6_aton() failure tests */
452 inet6_aton_fail_ok ( "20012:ba8:0:1d4::6950:5845" );
453 inet6_aton_fail_ok ( "200z:ba8:0:1d4::6950:5845" );
454 inet6_aton_fail_ok ( "2001.ba8:0:1d4::6950:5845" );
455 inet6_aton_fail_ok ( "2001:db8:1:1:1:1:1" );
456 inet6_aton_fail_ok ( "2001:db8:1:1:1:1:1:1:2" );
457 inet6_aton_fail_ok ( "2001:db8::1::2" );
458 inet6_aton_fail_ok ( "2001:ba8:0:1d4:::6950:5845" );
459 inet6_aton_fail_ok ( ":::" );
460
461 /* Create test routing tables */
462 ipv6_table_ok ( &table_link_local );
463 ipv6_table_ok ( &table_normal );
464 ipv6_table_ok ( &table_multi );
465
466 /* Routing table with only a link-local address */
467 ipv6_route_ok ( &table_link_local, "fe80::1",
468 "fe80::69ff:fe50:5845", NULL );
469 ipv6_route_ok ( &table_link_local, "2001:db8:1::1",
470 NULL, NULL );
471 ipv6_route_ok ( &table_link_local, "ff02::1",
472 "fe80::69ff:fe50:5845", NULL );
473
474 /** Routing table with a global address */
475 ipv6_route_ok ( &table_normal, "fe80::1",
476 "fe80::69ff:fe50:5845", NULL );
477 ipv6_route_ok ( &table_normal, "2001:db8:3::42",
478 "2001:db8:3::1", NULL );
479 ipv6_route_ok ( &table_normal, "2001:ba8:0:1d4::6950:5845",
480 "2001:db8:3::1", "fe80::1" );
481 ipv6_route_ok ( &table_normal, "ff02::1",
482 "fe80::69ff:fe50:5845", NULL );
483 ipv6_route_ok ( &table_normal, "ff0e::1",
484 "2001:db8:3::1", NULL );
485
486 /** Routing table with multiple addresses and routers */
487 ipv6_route_ok ( &table_multi, "fe80::1",
488 "fe80::69ff:fe50:5845", NULL );
489 ipv6_route_ok ( &table_multi, "2001:db8:3::17",
490 "2001:db8:3::1", NULL );
491 ipv6_route_ok ( &table_multi, "2001:db8:5::92",
492 "2001:db8:5::1", NULL );
493 ipv6_route_ok ( &table_multi, "2001:db8:42::17",
494 "2001:db8:42::1", NULL );
495 ipv6_route_ok ( &table_multi, "2001:db8:5:1::17",
496 "2001:db8:3::1", "fe80::1" );
497 ipv6_route_ok ( &table_multi, "fd44:9112:6442::1",
498 "fd44:9112:6442::69ff:fe50:5845", NULL );
499 ipv6_route_ok ( &table_multi, "fd70:6ba9:50ae::1",
500 "fd70:6ba9:50ae::69ff:fe50:5845", NULL );
501 ipv6_route_ok ( &table_multi, "fd40::3",
502 "fd44:9112:6442::69ff:fe50:5845", "fe80::1" );
503 ipv6_route_ok ( &table_multi, "fd70::2",
504 "fd70:6ba9:50ae::69ff:fe50:5845", "fe80::3" );
505 ipv6_route_ok ( &table_multi, "ff02::1",
506 "fe80::69ff:fe50:5845", NULL );
507
508 /* Destroy test routing tables */
509 ipv6_table_del ( &table_link_local );
510 ipv6_table_del ( &table_normal );
511 ipv6_table_del ( &table_multi );
512 }
513
514 /** IPv6 self-test */
515 struct self_test ipv6_test __self_test = {
516 .name = "ipv6",
517 .exec = ipv6_test_exec,
518 };