On Sat, Jul 24, 2010 at 07:04:43PM +0100, Stefan Hajnoczi wrote: > CCed to the gpxe-devel@etherboot.org mailing list. The original mail went to > g...@etherboot.org. > > Here is the dhcp multiple interface patch from Lars Kellogg-Stedman > <l...@oddbit.com> inline for easy reviewing:
Please use gPXE coding style, see net/netdevice.c for examples. Whitespace is used like this: static void foo ( int arg ) { if ( arg > 2 ) bar(); /* no spaces when function has no arguments */ } > > diff --git a/src/hci/commands/dhcp_cmd.c b/src/hci/commands/dhcp_cmd.c > index 96aac8d..a494068 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,87 @@ FILE_LICENCE ( GPL2_OR_LATER ); > */ > static void dhcp_syntax ( char **argv ) { > printf ( "Usage:\n" > - " %s <interface>\n" > + " %s [-c] <interface> [<interface> ...]\n" > + " %s any\n" > "\n" > "Configure a network interface using DHCP\n", > - argv[0] ); > + argv[0], argv[0] ); > +} > + > +/** > + * Given a device name, attempt to configure that device using dhcp. > + * > + * @netdev_name Name of the network device > + */ > +static int dhcp_one_device_name (char *netdev_name) { > + int rc; > + struct net_device *netdev; > + > + netdev = find_netdev ( netdev_name ); > + > + if ( ! netdev ) { > + printf ( "No such interface: %s\n", netdev_name ); > + return 2; > + } > + > + /* Perform DHCP */ > + if ( ( rc = dhcp ( netdev ) ) != 0 ) { > + printf ( "Could not configure %s: %s\n", netdev->name, > + strerror ( rc ) ); If DHCP fails the device should be closed. The dhcp() function will automatically open the netdev. Having multiple netdevs open simultaneously can cause out-of-memory situations because gPXE only claims a small chunk of memory to use as its heap. Previously the command didn't close single netdevs. gPXE aborts script execution if a command fails, so I don't think existing users will be able to detect this change. > + return 1; > + } > + > + return 0; > +} > + > +/** > + * Call dhcp_one_device_name() for each name in argv. > + * > + * @argc Number of devices > + * @argv List of device names > + * @keep_going If TRUE, ignore errors caused by unknown device > names. > + */ > +static int dhcp_each_device_name (int argc, char *argv[], int keep_going) { > + int i; > + > + for (i=0; i<argc; i++) { > + switch ( dhcp_one_device_name ( argv[i] ) ) { > + case 0: > + return 0; > + case 1: > + break; > + case 2: > + if (! keep_going) > + return 1; > + } > + } > + > + printf( "Could not configure any interface.\n" ); > + return 1; > +} > + > +/** > + * Call dhcp_one_device_name() for each device in net_devices. > + */ > +static int dhcp_each_device () { Please use a void argument list to mark a function with no arguments. In C giving no argument list means the compiler doesn't type-check calls, you could get away with using the function like this: dhcp_each_device ( "hello", 123 ); > + struct net_device *netdev; > + > + for_each_netdev ( netdev ) { > + switch ( dhcp_one_device_name ( netdev->name ) ) { > + case 0: > + return 0; > + case 1: > + break; > + case 2: > + /* we should never get here, since we're working > + * from a list of known device names. > + */ > + return 1; If dhcp_one_device_name() doesn't do find_netdev(), then this switch statement can turn into a simple if statement: if ( ! dhcp_one_device_name ( netdev ) ) return 0; And the change to dhcp_each_device_name() would make the code nicer too, I think. > + } > + } > + > + printf( "Could not configure any interface.\n" ); > + return 1; > } > > /** > @@ -61,16 +139,18 @@ static void dhcp_syntax ( char **argv ) { > static int dhcp_exec ( int argc, char **argv ) { > static struct option longopts[] = { > { "help", 0, NULL, 'h' }, > + { "continue", 0, NULL, 'c' }, > { NULL, 0, NULL, 0 }, > }; > - const char *netdev_txt; > - struct net_device *netdev; > int c; > - int rc; > + int keep_going = 0; > > /* Parse options */ > - while ( ( c = getopt_long ( argc, argv, "h", longopts, NULL ) ) >= 0 ){ > + while ( ( c = getopt_long ( argc, argv, "ch", longopts, NULL ) ) >= 0 ){ > switch ( c ) { > + case 'c': > + keep_going = 1; > + break; > case 'h': > /* Display help text */ > default: > @@ -81,27 +161,19 @@ static int dhcp_exec ( int argc, char **argv ) { > } > > /* Need exactly one interface name remaining after the options */ > - if ( optind != ( argc - 1 ) ) { > + 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; > + if (strcmp(argv[optind], "any") == 0) { > + return dhcp_each_device (); > + } else { > + return dhcp_each_device_name (argc-optind, argv+optind, > keep_going); > } I'd move dhcp_each_device_name() outside an "else"... > > - /* Perform DHCP */ > - if ( ( rc = dhcp ( netdev ) ) != 0 ) { > - printf ( "Could not configure %s: %s\n", netdev->name, > - strerror ( rc ) ); > - return 1; > - } > - > - return 0; > + /* we should never get here. */ > + return 1; ...and drop these two lines of dead code. > } > > /** _______________________________________________ gPXE-devel mailing list gPXE-devel@etherboot.org http://etherboot.org/mailman/listinfo/gpxe-devel