summaryrefslogtreecommitdiffstats
path: root/src/tests
diff options
context:
space:
mode:
Diffstat (limited to 'src/tests')
-rw-r--r--src/tests/ipv6_test.c281
1 files changed, 281 insertions, 0 deletions
diff --git a/src/tests/ipv6_test.c b/src/tests/ipv6_test.c
index 42b72961..9b3a744d 100644
--- a/src/tests/ipv6_test.c
+++ b/src/tests/ipv6_test.c
@@ -41,6 +41,38 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
/** Define inline IPv6 address */
#define IPV6(...) { __VA_ARGS__ }
+/** An IPv6 test routing table entry */
+struct ipv6_test_route {
+ /** Local address */
+ const char *address;
+ /** Prefix length */
+ unsigned int prefix_len;
+ /** Router address (if any) */
+ const char *router;
+};
+
+/** An IPv6 test routing table */
+struct ipv6_test_table {
+ /** Test routing table entries */
+ const struct ipv6_test_route *routes;
+ /** Number of table entries */
+ unsigned int count;
+ /** Constructed routing table */
+ struct list_head list;
+};
+
+/** Define a test routing table */
+#define TABLE( name, ... ) \
+ static const struct ipv6_test_route name ## _routes[] = { \
+ __VA_ARGS__ \
+ }; \
+ static struct ipv6_test_table name = { \
+ .routes = name ## _routes, \
+ .count = ( sizeof ( name ## _routes ) / \
+ sizeof ( name ## _routes[0] ) ), \
+ .list = LIST_HEAD_INIT ( name.list ), \
+ };
+
/** The unspecified IPv6 address */
static const struct in6_addr sample_unspecified = {
.s6_addr = IPV6 ( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -53,6 +85,18 @@ static const struct in6_addr sample_link_local = {
0x00, 0x00, 0x69, 0xff, 0xfe, 0x50, 0x58, 0x45 ),
};
+/** A sample site-local IPv6 address */
+static const struct in6_addr sample_site_local = {
+ .s6_addr = IPV6 ( 0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 ),
+};
+
+/** A sample ULA IPv6 address */
+static const struct in6_addr sample_ula = {
+ .s6_addr = IPV6 ( 0xfd, 0x44, 0x91, 0x12, 0x64, 0x42, 0x00, 0x00,
+ 0x00, 0x00, 0x69, 0xff, 0xfe, 0x50, 0x58, 0x45 ),
+};
+
/** A sample global IPv6 address */
static const struct in6_addr sample_global = {
.s6_addr = IPV6 ( 0x20, 0x01, 0x0b, 0xa8, 0x00, 0x00, 0x01, 0xd4,
@@ -65,6 +109,31 @@ static const struct in6_addr sample_multicast = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 ),
};
+/** Dummy network device used for routing tests */
+static struct net_device ipv6_test_netdev = {
+ .refcnt = REF_INIT ( ref_no_free ),
+ .index = 42,
+ .state = NETDEV_OPEN,
+};
+
+/** Routing table with only a link-local address */
+TABLE ( table_link_local,
+ { "fe80::69ff:fe50:5845", 64, NULL } );
+
+/** Routing table with a global address */
+TABLE ( table_normal,
+ { "fe80::69ff:fe50:5845", 64, NULL },
+ { "2001:db8:3::1", 64, "fe80::1" } );
+
+/** Routing table with multiple addresses and routers */
+TABLE ( table_multi,
+ { "fe80::69ff:fe50:5845", 64, NULL },
+ { "2001:db8:3::1", 64, "fe80::1" },
+ { "2001:db8:5::1", 64, NULL },
+ { "2001:db8:42::1", 64, "fe80::2" },
+ { "fd44:9112:6442::69ff:fe50:5845", 64, "fe80::1" },
+ { "fd70:6ba9:50ae::69ff:fe50:5845", 64, "fe80::3" } );
+
/**
* Report an inet6_ntoa() test result
*
@@ -134,6 +203,148 @@ static void inet6_aton_fail_okx ( const char *text, const char *file,
inet6_aton_fail_okx ( text, __FILE__, __LINE__ )
/**
+ * Create test routing table
+ *
+ * @v table Test routing table
+ * @v file Test code file
+ * @v line Test code line
+ */
+static void ipv6_table_okx ( struct ipv6_test_table *table, const char *file,
+ unsigned int line ) {
+ const struct ipv6_test_route *route;
+ struct in6_addr address;
+ struct in6_addr router;
+ struct list_head saved;
+ unsigned int i;
+
+ /* Sanity check */
+ okx ( list_empty ( &table->list ), file, line );
+
+ /* Save existing routing table */
+ INIT_LIST_HEAD ( &saved );
+ list_splice_init ( &ipv6_miniroutes, &saved );
+
+ /* Construct routing table */
+ for ( i = 0 ; i < table->count ; i++ ) {
+
+ /* Parse address and router (if applicable) */
+ route = &table->routes[i];
+ okx ( inet6_aton ( route->address, &address ) == 0,
+ file, line );
+ if ( route->router ) {
+ okx ( inet6_aton ( route->router, &router ) == 0,
+ file, line );
+ }
+
+ /* Add routing table entry */
+ okx ( ipv6_add_miniroute ( &ipv6_test_netdev, &address,
+ route->prefix_len,
+ ( route->router ?
+ &router : NULL ) ) == 0,
+ file, line );
+ }
+
+ /* Save constructed routing table */
+ list_splice_init ( &ipv6_miniroutes, &table->list );
+
+ /* Restore original routing table */
+ list_splice ( &saved, &ipv6_miniroutes );
+}
+#define ipv6_table_ok( table ) \
+ ipv6_table_okx ( table, __FILE__, __LINE__ )
+
+/**
+ * Report an ipv6_route() test result
+ *
+ * @v table Test routing table
+ * @v dest Destination address
+ * @v src Expected source address, or NULL to expect failure
+ * @v next Expected next hop address, or NULL to expect destination
+ * @v file Test code file
+ * @v line Test code line
+ */
+static void ipv6_route_okx ( struct ipv6_test_table *table, const char *dest,
+ const char *src, const char *next,
+ const char *file, unsigned int line ) {
+ struct in6_addr in_dest;
+ struct in6_addr in_src;
+ struct in6_addr in_next;
+ struct in6_addr *actual;
+ struct ipv6_miniroute *miniroute;
+ struct list_head saved;
+
+ /* Switch to test routing table */
+ INIT_LIST_HEAD ( &saved );
+ list_splice_init ( &ipv6_miniroutes, &saved );
+ list_splice_init ( &table->list, &ipv6_miniroutes );
+
+ /* Parse addresses */
+ okx ( inet6_aton ( dest, &in_dest ) == 0, file, line );
+ if ( src )
+ okx ( inet6_aton ( src, &in_src ) == 0, file, line );
+ if ( next ) {
+ okx ( inet6_aton ( next, &in_next ) == 0, file, line );
+ } else {
+ memcpy ( &in_next, &in_dest, sizeof ( in_next ) );
+ }
+
+ /* Perform routing */
+ actual = &in_dest;
+ miniroute = ipv6_route ( ipv6_test_netdev.index, &actual );
+
+ /* Validate result */
+ if ( src ) {
+
+ /* Check that a route was found */
+ okx ( miniroute != NULL, file, line );
+ DBG ( "ipv6_route ( %s ) = %s", dest, inet6_ntoa ( actual ) );
+ DBG ( " from %s\n", inet6_ntoa ( &miniroute->address ) );
+
+ /* Check that expected source address was used */
+ okx ( memcmp ( &miniroute->address, &in_src,
+ sizeof ( in_src ) ) == 0, file, line );
+
+ /* Check that expected next hop address was used */
+ okx ( memcmp ( actual, &in_next, sizeof ( *actual ) ) == 0,
+ file, line );
+
+ } else {
+
+ /* Routing is expected to fail */
+ okx ( miniroute == NULL, file, line );
+ }
+
+ /* Restore original routing table */
+ list_splice_init ( &ipv6_miniroutes, &table->list );
+ list_splice ( &saved, &ipv6_miniroutes );
+}
+#define ipv6_route_ok( table, dest, src, next ) \
+ ipv6_route_okx ( table, dest, src, next, __FILE__, __LINE__ )
+
+/**
+ * Destroy test routing table
+ *
+ * @v table Test routing table
+ */
+static void ipv6_table_del ( struct ipv6_test_table *table ) {
+ struct ipv6_miniroute *miniroute;
+ struct ipv6_miniroute *tmp;
+ struct list_head saved;
+
+ /* Switch to test routing table */
+ INIT_LIST_HEAD ( &saved );
+ list_splice_init ( &ipv6_miniroutes, &saved );
+ list_splice_init ( &table->list, &ipv6_miniroutes );
+
+ /* Delete all existing routes */
+ list_for_each_entry_safe ( miniroute, tmp, &ipv6_miniroutes, list )
+ ipv6_del_miniroute ( miniroute );
+
+ /* Restore original routing table */
+ list_splice ( &saved, &ipv6_miniroutes );
+}
+
+/**
* Perform IPv6 self-tests
*
*/
@@ -142,16 +353,34 @@ static void ipv6_test_exec ( void ) {
/* Address testing macros */
ok ( IN6_IS_ADDR_UNSPECIFIED ( &sample_unspecified ) );
ok ( ! IN6_IS_ADDR_UNSPECIFIED ( &sample_link_local ) );
+ ok ( ! IN6_IS_ADDR_UNSPECIFIED ( &sample_site_local ) );
+ ok ( ! IN6_IS_ADDR_UNSPECIFIED ( &sample_ula ) );
ok ( ! IN6_IS_ADDR_UNSPECIFIED ( &sample_global ) );
ok ( ! IN6_IS_ADDR_UNSPECIFIED ( &sample_multicast ) );
ok ( ! IN6_IS_ADDR_MULTICAST ( &sample_unspecified ) );
ok ( ! IN6_IS_ADDR_MULTICAST ( &sample_link_local ) );
+ ok ( ! IN6_IS_ADDR_MULTICAST ( &sample_site_local ) );
+ ok ( ! IN6_IS_ADDR_MULTICAST ( &sample_ula ) );
ok ( ! IN6_IS_ADDR_MULTICAST ( &sample_global ) );
ok ( IN6_IS_ADDR_MULTICAST ( &sample_multicast ) );
ok ( ! IN6_IS_ADDR_LINKLOCAL ( &sample_unspecified ) );
ok ( IN6_IS_ADDR_LINKLOCAL ( &sample_link_local ) );
+ ok ( ! IN6_IS_ADDR_LINKLOCAL ( &sample_site_local ) );
+ ok ( ! IN6_IS_ADDR_LINKLOCAL ( &sample_ula ) );
ok ( ! IN6_IS_ADDR_LINKLOCAL ( &sample_global ) );
ok ( ! IN6_IS_ADDR_LINKLOCAL ( &sample_multicast ) );
+ ok ( ! IN6_IS_ADDR_SITELOCAL ( &sample_unspecified ) );
+ ok ( ! IN6_IS_ADDR_SITELOCAL ( &sample_link_local ) );
+ ok ( IN6_IS_ADDR_SITELOCAL ( &sample_site_local ) );
+ ok ( ! IN6_IS_ADDR_SITELOCAL ( &sample_ula ) );
+ ok ( ! IN6_IS_ADDR_SITELOCAL ( &sample_global ) );
+ ok ( ! IN6_IS_ADDR_SITELOCAL ( &sample_multicast ) );
+ ok ( ! IN6_IS_ADDR_ULA ( &sample_unspecified ) );
+ ok ( ! IN6_IS_ADDR_ULA ( &sample_link_local ) );
+ ok ( ! IN6_IS_ADDR_ULA ( &sample_site_local ) );
+ ok ( IN6_IS_ADDR_ULA ( &sample_ula ) );
+ ok ( ! IN6_IS_ADDR_ULA ( &sample_global ) );
+ ok ( ! IN6_IS_ADDR_ULA ( &sample_multicast ) );
/* inet6_ntoa() tests */
inet6_ntoa_ok ( IPV6 ( 0x20, 0x01, 0x0b, 0xa8, 0x00, 0x00, 0x01, 0xd4,
@@ -228,6 +457,58 @@ static void ipv6_test_exec ( void ) {
inet6_aton_fail_ok ( "2001:db8::1::2" );
inet6_aton_fail_ok ( "2001:ba8:0:1d4:::6950:5845" );
inet6_aton_fail_ok ( ":::" );
+
+ /* Create test routing tables */
+ ipv6_table_ok ( &table_link_local );
+ ipv6_table_ok ( &table_normal );
+ ipv6_table_ok ( &table_multi );
+
+ /* Routing table with only a link-local address */
+ ipv6_route_ok ( &table_link_local, "fe80::1",
+ "fe80::69ff:fe50:5845", NULL );
+ ipv6_route_ok ( &table_link_local, "2001:db8:1::1",
+ NULL, NULL );
+ ipv6_route_ok ( &table_link_local, "ff02::1",
+ "fe80::69ff:fe50:5845", NULL );
+
+ /** Routing table with a global address */
+ ipv6_route_ok ( &table_normal, "fe80::1",
+ "fe80::69ff:fe50:5845", NULL );
+ ipv6_route_ok ( &table_normal, "2001:db8:3::42",
+ "2001:db8:3::1", NULL );
+ ipv6_route_ok ( &table_normal, "2001:ba8:0:1d4::6950:5845",
+ "2001:db8:3::1", "fe80::1" );
+ ipv6_route_ok ( &table_normal, "ff02::1",
+ "fe80::69ff:fe50:5845", NULL );
+ ipv6_route_ok ( &table_normal, "ff0e::1",
+ "2001:db8:3::1", NULL );
+
+ /** Routing table with multiple addresses and routers */
+ ipv6_route_ok ( &table_multi, "fe80::1",
+ "fe80::69ff:fe50:5845", NULL );
+ ipv6_route_ok ( &table_multi, "2001:db8:3::17",
+ "2001:db8:3::1", NULL );
+ ipv6_route_ok ( &table_multi, "2001:db8:5::92",
+ "2001:db8:5::1", NULL );
+ ipv6_route_ok ( &table_multi, "2001:db8:42::17",
+ "2001:db8:42::1", NULL );
+ ipv6_route_ok ( &table_multi, "2001:db8:5:1::17",
+ "2001:db8:3::1", "fe80::1" );
+ ipv6_route_ok ( &table_multi, "fd44:9112:6442::1",
+ "fd44:9112:6442::69ff:fe50:5845", NULL );
+ ipv6_route_ok ( &table_multi, "fd70:6ba9:50ae::1",
+ "fd70:6ba9:50ae::69ff:fe50:5845", NULL );
+ ipv6_route_ok ( &table_multi, "fd40::3",
+ "fd44:9112:6442::69ff:fe50:5845", "fe80::1" );
+ ipv6_route_ok ( &table_multi, "fd70::2",
+ "fd70:6ba9:50ae::69ff:fe50:5845", "fe80::3" );
+ ipv6_route_ok ( &table_multi, "ff02::1",
+ "fe80::69ff:fe50:5845", NULL );
+
+ /* Destroy test routing tables */
+ ipv6_table_del ( &table_link_local );
+ ipv6_table_del ( &table_normal );
+ ipv6_table_del ( &table_multi );
}
/** IPv6 self-test */