[ipv6] Change return code handling from router solicits
authorMatthew Iselin <matthew@theiselins.net>
Mon, 18 Jul 2011 01:20:15 +0000 (11:20 +1000)
committerMarty Connor <mdc@etherboot.org>
Thu, 21 Jul 2011 11:30:13 +0000 (07:30 -0400)
Using 'rc' for flags causes "Error <code>" to be displayed when monojob_wait
completes, which is not very user-friendly. By adding the flags to struct
rsolicit_info we can pass this information around without having to special-case
return code handling.

DHCPv6 has been updated accordingly, and has also been updated to take a
pointer to a struct rsolicit_info, which reduces the number of duplicate
solicitations we do in a normal startup sequence.

Signed-off-by: Matthew Iselin <matthew@theiselins.net>
Signed-off-by: Marty Connor <mdc@etherboot.org>
src/include/gpxe/dhcp6.h
src/include/gpxe/ndp.h
src/net/ndp.c
src/net/udp/dhcp6.c
src/usr/ip6mgmt.c

index c280a4f..d43f98f 100644 (file)
@@ -206,7 +206,8 @@ struct dhcp6_duid_ll {
 };
 
 /** Start a DHCP6 transaction. */
-int start_dhcp6 ( struct job_interface *job, struct net_device *netdev, int onlyinfo );
+int start_dhcp6 ( struct job_interface *job, struct net_device *netdev,
+                 int onlyinfo, struct rsolicit_info *router );
 
 #endif
 
index 30b4f7a..8a69cf7 100644 (file)
@@ -40,6 +40,7 @@ struct rsolicit_info {
        struct in6_addr prefix;
        int prefix_length;
        int no_address; /* No address assignment takes place via this adv. */
+       int flags; /* RSOLICIT_CODE_* flags. */
 };
 
 struct neighbour_solicit {
index e8f96a4..9d58e91 100644 (file)
@@ -451,6 +451,7 @@ int ndp_process_radvert ( struct io_buffer *iobuf, struct sockaddr_tcpip *st_src
                pending->meta->prefix = prefix;
                pending->meta->prefix_length = prefix_len;
                pending->meta->no_address = ! can_autoconf;
+               pending->meta->flags = pending->code;
        }
 
        /* Configure a route based on this router if none exists. */
@@ -461,7 +462,7 @@ int ndp_process_radvert ( struct io_buffer *iobuf, struct sockaddr_tcpip *st_src
        }
 
        /* Completed without error. */
-       job_done ( &pending->job, pending->code );
+       job_done ( &pending->job, 0 );
        pending->state = RSOLICIT_STATE_INVALID;
 
        return 0;
index f5e54ed..94da1e9 100644 (file)
@@ -748,6 +748,9 @@ static struct xfer_interface_operations dhcp6_xfer_operations = {
  * @v netdev           Network device
  * @v onlyinfo         Only get information from the DHCPv6 server, not an
  *                     actual address.
+ * @v router           Router information, or NULL if none is available or
+ *                     needed. If provided, DHCP6 won't perform a router
+ *                     solicit automatically.
  * @ret rc             Return status code, or positive if cached
  *
  * On a return of 0, a background job has been started to perform the
@@ -755,7 +758,8 @@ static struct xfer_interface_operations dhcp6_xfer_operations = {
  * started; a positive return value indicates the success condition of
  * having fetched the appropriate data from cached information.
  */
-int start_dhcp6 ( struct job_interface *job, struct net_device *netdev, int onlyinfo ) {
+int start_dhcp6 ( struct job_interface *job, struct net_device *netdev,
+                 int onlyinfo, struct rsolicit_info *router ) {
        struct dhcp6_session *dhcp;
        int rc;
        
@@ -763,22 +767,25 @@ int start_dhcp6 ( struct job_interface *job, struct net_device *netdev, int only
        if ( ! dhcp )
                return -ENOMEM;
        
-       
-       /* Get information about routers on this network first. */
-       memset ( &dhcp->router, 0, sizeof ( dhcp->router ) );
-       rc = ndp_send_rsolicit ( netdev, &monojob, &dhcp->router );
-       if ( rc != 0 ) {
-               /* Couldn't TX a solicit for some reason... */
-               DBG ( "dhcp6: couldn't TX a router solicit?\n" );
+       if ( router != NULL ) {
+               dhcp->router = *router;
        } else {
-               rc = monojob_wait ( "" );
-       }
+               /* Get information about routers on this network first. */
+               memset ( &dhcp->router, 0, sizeof ( dhcp->router ) );
+               rc = ndp_send_rsolicit ( netdev, &monojob, &dhcp->router );
+               if ( rc != 0 ) {
+                       /* Couldn't TX a solicit for some reason... */
+                       DBG ( "dhcp6: couldn't TX a router solicit?\n" );
+               } else {
+                       rc = monojob_wait ( "dhcp6 is finding routers" );
+               }
        
-       /* If no router advertisement, set some sane defaults. */
-       if ( rc < 0 ) {
-               DBG ( "dhcp6: can't find a router on the network, continuing\n" );
-               dhcp->router.prefix_length = 128;
-               dhcp->router.no_address = 1;
+               /* If no router advertisement, set some sane defaults. */
+               if ( rc != 0 ) {
+                       DBG ( "dhcp6: can't find a router on the network, continuing\n" );
+                       dhcp->router.prefix_length = 128;
+                       dhcp->router.no_address = 1;
+               }
        }
        
        ref_init ( &dhcp->refcnt, dhcp6_free );
index ce029e7..e0f85ff 100644 (file)
@@ -27,6 +27,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
 #include <gpxe/icmp6.h>
 #include <gpxe/monojob.h>
 #include <gpxe/process.h>
+#include <gpxe/ndp.h>
 #include <usr/ifmgmt.h>
 #include <usr/ip6mgmt.h>
 #include <gpxe/dhcp6.h>
@@ -69,7 +70,7 @@ int ip6_autoconf ( struct net_device *netdev ) {
        /* TODO: send a few neighbour solicits on this address before we take
         * it (once NDP is implemented). */
        
-       DBG( "ipv6 autoconfig address is %s\n", inet6_ntoa(ip6addr) );
+       DBG ( "ipv6 autoconfig address is %s\n", inet6_ntoa(ip6addr) );
        
        /* Add as a route. It turns out Linux actually uses /64 for these, even
         * though they are technically a /10. It does make routing easier, as
@@ -77,19 +78,20 @@ int ip6_autoconf ( struct net_device *netdev ) {
        add_ipv6_address ( netdev, ip6addr, 64, ip6addr, ip6zero );
        
        /* Solicit routers on the network. */
-       if ( ( rc = ndp_send_rsolicit ( netdev, &monojob, NULL ) ) == 0 ) {
-               rc = monojob_wait ( "" );
+       struct rsolicit_info router;
+       if ( ( rc = ndp_send_rsolicit ( netdev, &monojob, &router ) ) == 0 ) {
+               rc = monojob_wait ( "finding routers and attempting stateless autoconfiguration" );
        }
        
-       if ( rc < 0 ) {
+       if ( rc != 0 ) {
                DBG ( "ipv6: router solicitation failed\n" );
                use_dhcp = 1;
                onlyinfo = 0;
        } else {
-               if ( rc & RSOLICIT_CODE_MANAGED ) {
+               if ( router.flags & RSOLICIT_CODE_MANAGED ) {
                        DBG ( "ipv6: should use dhcp6 server\n" );
                        use_dhcp = 1;
-               } else if ( rc & RSOLICIT_CODE_OTHERCONF ) {
+               } else if ( router.flags & RSOLICIT_CODE_OTHERCONF ) {
                        DBG ( "ipv6: use dhcp6 server for DNS settings\n" );
                        use_dhcp = 1;
                        onlyinfo = 1;
@@ -101,8 +103,8 @@ int ip6_autoconf ( struct net_device *netdev ) {
        /* Attempt DHCPv6 now, for addresses (if we don't already have one) and
         * DNS configuration. */
        if ( use_dhcp ) {
-               start_dhcp6 ( &monojob, netdev, onlyinfo );
-               rc = monojob_wait ( "" );
+               start_dhcp6 ( &monojob, netdev, onlyinfo, &router );
+               rc = monojob_wait ( "dhcp6" );
        }
        
        return rc;