|
@@ -41,6 +41,38 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
41
|
41
|
/** Define inline IPv6 address */
|
42
|
42
|
#define IPV6(...) { __VA_ARGS__ }
|
43
|
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
|
+
|
44
|
76
|
/** The unspecified IPv6 address */
|
45
|
77
|
static const struct in6_addr sample_unspecified = {
|
46
|
78
|
.s6_addr = IPV6 ( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
@@ -53,6 +85,18 @@ static const struct in6_addr sample_link_local = {
|
53
|
85
|
0x00, 0x00, 0x69, 0xff, 0xfe, 0x50, 0x58, 0x45 ),
|
54
|
86
|
};
|
55
|
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
|
+
|
56
|
100
|
/** A sample global IPv6 address */
|
57
|
101
|
static const struct in6_addr sample_global = {
|
58
|
102
|
.s6_addr = IPV6 ( 0x20, 0x01, 0x0b, 0xa8, 0x00, 0x00, 0x01, 0xd4,
|
|
@@ -65,6 +109,31 @@ static const struct in6_addr sample_multicast = {
|
65
|
109
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 ),
|
66
|
110
|
};
|
67
|
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
|
+
|
68
|
137
|
/**
|
69
|
138
|
* Report an inet6_ntoa() test result
|
70
|
139
|
*
|
|
@@ -133,6 +202,148 @@ static void inet6_aton_fail_okx ( const char *text, const char *file,
|
133
|
202
|
#define inet6_aton_fail_ok( text ) \
|
134
|
203
|
inet6_aton_fail_okx ( text, __FILE__, __LINE__ )
|
135
|
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
|
+
|
136
|
347
|
/**
|
137
|
348
|
* Perform IPv6 self-tests
|
138
|
349
|
*
|
|
@@ -142,16 +353,34 @@ static void ipv6_test_exec ( void ) {
|
142
|
353
|
/* Address testing macros */
|
143
|
354
|
ok ( IN6_IS_ADDR_UNSPECIFIED ( &sample_unspecified ) );
|
144
|
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 ) );
|
145
|
358
|
ok ( ! IN6_IS_ADDR_UNSPECIFIED ( &sample_global ) );
|
146
|
359
|
ok ( ! IN6_IS_ADDR_UNSPECIFIED ( &sample_multicast ) );
|
147
|
360
|
ok ( ! IN6_IS_ADDR_MULTICAST ( &sample_unspecified ) );
|
148
|
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 ) );
|
149
|
364
|
ok ( ! IN6_IS_ADDR_MULTICAST ( &sample_global ) );
|
150
|
365
|
ok ( IN6_IS_ADDR_MULTICAST ( &sample_multicast ) );
|
151
|
366
|
ok ( ! IN6_IS_ADDR_LINKLOCAL ( &sample_unspecified ) );
|
152
|
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 ) );
|
153
|
370
|
ok ( ! IN6_IS_ADDR_LINKLOCAL ( &sample_global ) );
|
154
|
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 ) );
|
155
|
384
|
|
156
|
385
|
/* inet6_ntoa() tests */
|
157
|
386
|
inet6_ntoa_ok ( IPV6 ( 0x20, 0x01, 0x0b, 0xa8, 0x00, 0x00, 0x01, 0xd4,
|
|
@@ -228,6 +457,58 @@ static void ipv6_test_exec ( void ) {
|
228
|
457
|
inet6_aton_fail_ok ( "2001:db8::1::2" );
|
229
|
458
|
inet6_aton_fail_ok ( "2001:ba8:0:1d4:::6950:5845" );
|
230
|
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 );
|
231
|
512
|
}
|
232
|
513
|
|
233
|
514
|
/** IPv6 self-test */
|