[gPXE-devel] [PATCH] [dhcp] Allow multiple interfaces in dhcp command

Lars Kellogg-Stedman lars at oddbit.com
Sat Jul 31 11:43:53 EDT 2010


> Looks good.  I would like to merge this commit.
> 
> Lars, can you please provide your Signed-off-by line (i.e. Signed-off-by: Lars
> Kellogg-Stedman <lars at oddbit.com>)?

Sure.  I've added it to the text of your message; let me know if this
isn't the right procedure:

From: Lars Kellogg-Stedman <lars at oddbit.com>

The "dhcp" command now accepts a list of interfaces and to try until one
succeeds:

 gPXE> dhcp net0 net1 net2

If an interface does not exist a message is printed and it is skipped.

If given the single parameter "any" as an interface name, all interfaces
are tried in a manner similar to autoboot:

 gPXE> dhcp any
 DHCP (net0 xx:xx:xx:xx:xx:xx)........ Connection timed out (...)
 Could not configure net0: Connection timed out (...)
 DHCP (net1 xx:xx:xx:xx:xx:xx).... ok
 gPXE>

Note that interfaces which fail to DHCP are closed.  This is usually
desirable since an open interface consumes memory.  On machines with
several interfaces it is possible to exhaust the heap if all interfaces
are open simultaneously.  This behavior differs from the previous "dhcp"
command implementation but should not be detectable to user scripts
since they abort when the dhcp command exits with an error.

Signed-off-by: Stefan Hajnoczi <stefanha at gmail.com>
Signed-off-by: Lars Kellogg-Stedman <lars at oddbit.com>
---

 src/hci/commands/dhcp_cmd.c |   99 +++++++++++++++++++++++++++++++++----------
 1 files changed, 77 insertions(+), 22 deletions(-)

diff --git a/src/hci/commands/dhcp_cmd.c b/src/hci/commands/dhcp_cmd.c
index 96aac8d..6f0a99f 100644
--- a/src/hci/commands/dhcp_cmd.c
+++ b/src/hci/commands/dhcp_cmd.c
@@ -31,6 +31,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
 #include <gpxe/in.h>
 #include <gpxe/command.h>
 #include <usr/dhcpmgmt.h>
+#include <usr/ifmgmt.h>
 
 /** @file
  *
@@ -45,10 +46,79 @@ FILE_LICENCE ( GPL2_OR_LATER );
  */
 static void dhcp_syntax ( char **argv ) {
 	printf ( "Usage:\n"
-		 "  %s <interface>\n"
+		 "  %s <interface> [<interface> ...]\n"
+		 "  %s any\n"
 		 "\n"
 		 "Configure a network interface using DHCP\n",
-		 argv[0] );
+		 argv[0], argv[0] );
+}
+
+/**
+ * Attempt to configure a device with dhcp
+ *
+ * @v netdev		Device to configure
+ * @ret rc		Exit code
+ */
+static int dhcp_one_device ( struct net_device *netdev ) {
+	int rc;
+
+	/* Perform DHCP */
+	if ( ( rc = dhcp ( netdev ) ) != 0 ) {
+		/* Close the device on error to avoid out-of-memory */
+		netdev_close ( netdev );
+
+		printf ( "Could not configure %s: %s\n", netdev->name,
+			 strerror ( rc ) );
+		return 1;
+	}
+
+	return 0;
+}
+
+/**
+ * Call dhcp_one_device() for each name in argv
+ *
+ * @v argc		Number of devices
+ * @v argv		List of device names
+ * @ret rc		Exit code
+ */
+static int dhcp_each_device_name ( int argc, char **argv ) {
+	int i;
+	char *netdev_name;
+	struct net_device *netdev;
+
+	for ( i = 0; i < argc; i++ ) {
+		netdev_name = argv[i];
+		netdev = find_netdev ( netdev_name );
+
+		if ( ! netdev ) {
+			printf ( "No such interface: %s\n", netdev_name );
+			continue;
+		}
+
+		if ( dhcp_one_device ( netdev ) == 0 )
+			return 0;
+	}
+
+	printf ( "Could not configure any interface.\n" );
+	return 1;
+}
+
+/**
+ * Call dhcp_one_device() for each device in net_devices
+ *
+ * @ret rc		Exit code
+ */
+static int dhcp_each_device ( void ) {
+	struct net_device *netdev;
+
+	for_each_netdev ( netdev ) {
+		if ( dhcp_one_device ( netdev ) == 0 )
+			return 0;
+	}
+
+	printf ( "Could not configure any interface.\n" );
+	return 1;
 }
 
 /**
@@ -63,10 +133,7 @@ static int dhcp_exec ( int argc, char **argv ) {
 		{ "help", 0, NULL, 'h' },
 		{ NULL, 0, NULL, 0 },
 	};
-	const char *netdev_txt;
-	struct net_device *netdev;
 	int c;
-	int rc;
 
 	/* Parse options */
 	while ( ( c = getopt_long ( argc, argv, "h", longopts, NULL ) ) >= 0 ){
@@ -80,28 +147,16 @@ static int dhcp_exec ( int argc, char **argv ) {
 		}
 	}
 
-	/* Need exactly one interface name remaining after the options */
-	if ( optind != ( argc - 1 ) ) {
+	/* Need one or more interface names remaining after the options */
+	if ( ( argc - optind ) < 1 ) {
 		dhcp_syntax ( argv );
 		return 1;
 	}
-	netdev_txt = argv[optind];
 
-	/* Parse arguments */
-	netdev = find_netdev ( netdev_txt );
-	if ( ! netdev ) {
-		printf ( "No such interface: %s\n", netdev_txt );
-		return 1;
-	}
-
-	/* Perform DHCP */
-	if ( ( rc = dhcp ( netdev ) ) != 0 ) {
-		printf ( "Could not configure %s: %s\n", netdev->name,
-			 strerror ( rc ) );
-		return 1;
-	}
+	if ( strcmp ( argv[optind], "any" ) == 0 )
+		return dhcp_each_device();
 
-	return 0;
+	return dhcp_each_device_name ( argc - optind, argv + optind );
 }
 
 /**
-- 
1.7.1



More information about the gPXE-devel mailing list