diff options
author | Michael Brown <mcb30@ipxe.org> | 2013-11-04 17:05:53 +0000 |
---|---|---|
committer | Michael Brown <mcb30@ipxe.org> | 2013-11-05 17:30:20 +0000 |
commit | 26b87b221b45ccf53257962f4de030fbe855d634 (patch) | |
tree | 09e4d8e0b3b2d205ec7faa15c41677e81e0279ea | |
parent | 3a67224c622332c4e75484b4510780e7818ac2e4 (diff) | |
download | ipxe-26b87b221b45ccf53257962f4de030fbe855d634.zip ipxe-26b87b221b45ccf53257962f4de030fbe855d634.tar.gz ipxe-26b87b221b45ccf53257962f4de030fbe855d634.tar.bz2 |
[ifmgmt] Add ifconf() to carry out network device configuration
Signed-off-by: Michael Brown <mcb30@ipxe.org>
-rw-r--r-- | src/include/usr/ifmgmt.h | 3 | ||||
-rw-r--r-- | src/usr/ifmgmt.c | 89 |
2 files changed, 90 insertions, 2 deletions
diff --git a/src/include/usr/ifmgmt.h b/src/include/usr/ifmgmt.h index 0b265fe..db77f1f 100644 --- a/src/include/usr/ifmgmt.h +++ b/src/include/usr/ifmgmt.h @@ -10,8 +10,11 @@ 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 ); diff --git a/src/usr/ifmgmt.c b/src/usr/ifmgmt.c index cf7e6b6..cab1cd9 100644 --- a/src/usr/ifmgmt.c +++ b/src/usr/ifmgmt.c @@ -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 ); } |