]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[ifmgmt] Add ifconf() to carry out network device configuration
authorMichael Brown <mcb30@ipxe.org>
Mon, 4 Nov 2013 17:05:53 +0000 (17:05 +0000)
committerMichael Brown <mcb30@ipxe.org>
Tue, 5 Nov 2013 17:30:20 +0000 (17:30 +0000)
Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/include/usr/ifmgmt.h
src/usr/ifmgmt.c

index 0b265fea957e0f5054ddc2c3a80a76aff7302d05..db77f1f1b3818220c94d5d9853e160d270e05456 100644 (file)
 FILE_LICENCE ( GPL2_OR_LATER );
 
 struct net_device;
+struct net_device_configurator;
 
 extern int ifopen ( struct net_device *netdev );
+extern int ifconf ( struct net_device *netdev,
+                   struct net_device_configurator *configurator );
 extern void ifclose ( struct net_device *netdev );
 extern void ifstat ( struct net_device *netdev );
 extern int iflinkwait ( struct net_device *netdev, unsigned long timeout );
index cf7e6b6a348c8c8edd2887f31e00406100922069..cab1cd917a527d2ff0e1bb98cc38be660dde5f26 100644 (file)
@@ -29,6 +29,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
 #include <ipxe/job.h>
 #include <ipxe/monojob.h>
 #include <ipxe/nap.h>
+#include <ipxe/timer.h>
 #include <usr/ifmgmt.h>
 
 /** @file
@@ -37,6 +38,15 @@ FILE_LICENCE ( GPL2_OR_LATER );
  *
  */
 
+/** Default time to wait for link-up */
+#define LINK_WAIT_TIMEOUT ( 15 * TICKS_PER_SEC )
+
+/** Default unsuccessful configuration status code */
+#define EADDRNOTAVAIL_CONFIG __einfo_error ( EINFO_EADDRNOTAVAIL_CONFIG )
+#define EINFO_EADDRNOTAVAIL_CONFIG                                     \
+       __einfo_uniqify ( EINFO_EADDRNOTAVAIL, 0x01,                    \
+                         "No configuration methods succeeded" )
+
 /**
  * Open network device
  *
@@ -111,6 +121,8 @@ struct ifpoller {
        struct interface job;
        /** Network device */
        struct net_device *netdev;
+       /** Network device configurator (if applicable) */
+       struct net_device_configurator *configurator;
        /**
         * Check progress
         *
@@ -150,17 +162,21 @@ static struct interface_descriptor ifpoller_job_desc =
  * Poll network device until completion
  *
  * @v netdev           Network device
+ * @v configurator     Network device configurator (if applicable)
  * @v timeout          Timeout period, in ticks
  * @v progress         Method to check progress
  * @ret rc             Return status code
  */
-static int ifpoller_wait ( struct net_device *netdev, unsigned long timeout,
+static int ifpoller_wait ( struct net_device *netdev,
+                          struct net_device_configurator *configurator,
+                          unsigned long timeout,
                           int ( * progress ) ( struct ifpoller *ifpoller ) ) {
        static struct ifpoller ifpoller = {
                .job = INTF_INIT ( ifpoller_job_desc ),
        };
 
        ifpoller.netdev = netdev;
+       ifpoller.configurator = configurator;
        ifpoller.progress = progress;
        intf_plug_plug ( &monojob, &ifpoller.job );
        return monojob_wait ( "", timeout );
@@ -204,5 +220,74 @@ int iflinkwait ( struct net_device *netdev, unsigned long timeout ) {
 
        /* Wait for link-up */
        printf ( "Waiting for link-up on %s", netdev->name );
-       return ifpoller_wait ( netdev, timeout, iflinkwait_progress );
+       return ifpoller_wait ( netdev, NULL, timeout, iflinkwait_progress );
+}
+
+/**
+ * Check configuration progress
+ *
+ * @v ifpoller         Network device poller
+ * @ret ongoing_rc     Ongoing job status code (if known)
+ */
+static int ifconf_progress ( struct ifpoller *ifpoller ) {
+       struct net_device *netdev = ifpoller->netdev;
+       struct net_device_configurator *configurator = ifpoller->configurator;
+       struct net_device_configuration *config;
+       int rc;
+
+       /* Do nothing unless configuration has completed */
+       if ( netdev_configuration_in_progress ( netdev ) )
+               return 0;
+
+       /* Terminate with appropriate overall return status code */
+       if ( configurator ) {
+               config = netdev_configuration ( netdev, configurator );
+               rc = config->rc;
+       } else {
+               rc = ( netdev_configuration_ok ( netdev ) ?
+                      0 : -EADDRNOTAVAIL_CONFIG );
+       }
+       intf_close ( &ifpoller->job, rc );
+
+       return rc;
+}
+
+/**
+ * Perform network device configuration
+ *
+ * @v netdev           Network device
+ * @v configurator     Network device configurator, or NULL to use all
+ * @ret rc             Return status code
+ */
+int ifconf ( struct net_device *netdev,
+            struct net_device_configurator *configurator ) {
+       int rc;
+
+       /* Ensure device is open and link is up */
+       if ( ( rc = iflinkwait ( netdev, LINK_WAIT_TIMEOUT ) ) != 0 )
+               return rc;
+
+       /* Start configuration */
+       if ( configurator ) {
+               if ( ( rc = netdev_configure ( netdev, configurator ) ) != 0 ) {
+                       printf ( "Could not configure %s via %s: %s\n",
+                                netdev->name, configurator->name,
+                                strerror ( rc ) );
+                       return rc;
+               }
+       } else {
+               if ( ( rc = netdev_configure_all ( netdev ) ) != 0 ) {
+                       printf ( "Could not configure %s: %s\n",
+                                netdev->name, strerror ( rc ) );
+                       return rc;
+               }
+       }
+
+       /* Wait for configuration to complete */
+       printf ( "Configuring %s%s%s(%s %s)",
+                ( configurator ? "[" : "" ),
+                ( configurator ? configurator->name : "" ),
+                ( configurator ? "] " : "" ),
+                netdev->name, netdev->ll_protocol->ntoa ( netdev->ll_addr ) );
+       return ifpoller_wait ( netdev, configurator, 0, ifconf_progress );
 }