]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[ipv6] Match user expectations for IPv6 settings priorities
authorMichael Brown <mcb30@ipxe.org>
Tue, 19 Jul 2016 15:57:32 +0000 (16:57 +0100)
committerMichael Brown <mcb30@ipxe.org>
Tue, 19 Jul 2016 16:07:53 +0000 (17:07 +0100)
A reasonable user expectation is that ${net0/ip6} should show the
"highest-priority" of the IPv6 addresses, even when multiple IPv6
addresses are active.  The expected order of priority is likely to be
manually-assigned addresses first, then stateful DHCPv6 addresses,
then SLAAC addresses, and lastly link-local addresses.

Using ${priority} to enforce an ordering is undesirable since that
would affect the priority assigned to each of the net<N> blocks as a
whole, so use the sibling ordering capability instead.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/include/ipxe/ipv6.h
src/net/ipv6.c
src/net/ndp.c
src/net/udp/dhcpv6.c

index 86c8ff924b00030ef86003bf9f13878297ca4749..4dd03f0583c60ca1e7835c3bb530476c8cc0cccc 100644 (file)
@@ -238,6 +238,18 @@ static inline void ipv6_all_routers ( struct in6_addr *addr ) {
        addr->s6_addr[15] = 2;
 }
 
+/** IPv6 settings sibling order */
+enum ipv6_settings_order {
+       /** No address */
+       IPV6_ORDER_PREFIX_ONLY = -4,
+       /** Link-local address */
+       IPV6_ORDER_LINK_LOCAL = -3,
+       /** Address assigned via SLAAC */
+       IPV6_ORDER_SLAAC = -2,
+       /** Address assigned via DHCPv6 */
+       IPV6_ORDER_DHCPV6 = -1,
+};
+
 /** IPv6 link-local address settings block name */
 #define IPV6_SETTINGS_NAME "link"
 
index cdd6640c7e4764cf5841a672a1f79f25ef1e5510..04ba3d8bb5fe971f1791e86584caad4be1947a7c 100644 (file)
@@ -1185,6 +1185,7 @@ static int ipv6_register_settings ( struct net_device *netdev ) {
        ref_init ( &ipv6set->refcnt, NULL );
        settings_init ( &ipv6set->settings, &ipv6_settings_operations,
                        &ipv6set->refcnt, &ipv6_scope );
+       ipv6set->settings.order = IPV6_ORDER_LINK_LOCAL;
 
        /* Register settings */
        if ( ( rc = register_settings ( &ipv6set->settings, parent,
index c488acc73eae6bf76310b83511db350acd25a23a..a35a1219e12bec923e018be116b4a02ac5ccea55 100644 (file)
@@ -981,17 +981,28 @@ static int ndp_register_settings ( struct net_device *netdev,
        size_t option_len;
        unsigned int prefixes;
        unsigned int instance;
+       int order;
        int rc;
 
        /* Count number of prefix options.  We can assume that the
         * options are well-formed, otherwise they would have been
         * rejected prior to being stored.
         */
+       order = IPV6_ORDER_PREFIX_ONLY;
        for ( prefixes = 0, offset = 0 ; offset < len ; offset += option_len ) {
+
+               /* Skip non-prefix options */
                option = ( ( ( void * ) options ) + offset );
                option_len = ( option->header.blocks * NDP_OPTION_BLKSZ );
-               if ( option->header.type == NDP_OPT_PREFIX )
-                       prefixes++;
+               if ( option->header.type != NDP_OPT_PREFIX )
+                       continue;
+
+               /* Count number of prefixes */
+               prefixes++;
+
+               /* Increase overall order if we have SLAAC addresses */
+               if ( option->prefix.flags & NDP_PREFIX_AUTONOMOUS )
+                       order = IPV6_ORDER_SLAAC;
        }
 
        /* Allocate and initialise structure */
@@ -1004,6 +1015,7 @@ static int ndp_register_settings ( struct net_device *netdev,
        ref_init ( &ndpset->refcnt, NULL );
        settings_init ( &ndpset->settings, &ndp_settings_operations,
                        &ndpset->refcnt, &ndp_settings_scope );
+       ndpset->settings.order = order;
        memcpy ( &ndpset->router, router, sizeof ( ndpset->router ) );
        ndpset->lifetime = lifetime;
        ndpset->len = len;
@@ -1028,6 +1040,9 @@ static int ndp_register_settings ( struct net_device *netdev,
                settings_init ( &prefset->settings,
                                &ndp_prefix_settings_operations,
                                &ndpset->refcnt, &ndp_settings_scope );
+               prefset->settings.order =
+                       ( ( option->prefix.flags & NDP_PREFIX_AUTONOMOUS ) ?
+                         IPV6_ORDER_SLAAC : IPV6_ORDER_PREFIX_ONLY );
                prefset->prefix = &option->prefix;
                snprintf ( prefset->name, sizeof ( prefset->name ), "%d",
                           instance++ );
index ac7010422784b558450961a6209c7a6493101cf9..a2c69aaae46673637a925cb3d7a95f08ab59dfbf 100644 (file)
@@ -375,6 +375,7 @@ static int dhcpv6_register ( struct in6_addr *lease,
        ref_init ( &dhcpv6set->refcnt, NULL );
        settings_init ( &dhcpv6set->settings, &dhcpv6_settings_operations,
                        &dhcpv6set->refcnt, &dhcpv6_scope );
+       dhcpv6set->settings.order = IPV6_ORDER_DHCPV6;
        data = ( ( ( void * ) dhcpv6set ) + sizeof ( *dhcpv6set ) );
        len = options->len;
        memcpy ( data, options->data, len );