diff options
author | Avik Sil <aviksil@linux.vnet.ibm.com> | 2013-12-27 14:46:17 +0530 |
---|---|---|
committer | Avik Sil <aviksil@linux.vnet.ibm.com> | 2014-01-20 17:19:47 +0530 |
commit | d81ffe71dbd2777c3ea5a2f13f7e4b27049e695c (patch) | |
tree | 1ca8a93b2e669577059c2ef505c9f8cd5b35e90c | |
parent | a8c1a27c16b786bd5b6ccb93bfd7ca0354067f2a (diff) | |
download | SLOF-d81ffe71dbd2777c3ea5a2f13f7e4b27049e695c.zip SLOF-d81ffe71dbd2777c3ea5a2f13f7e4b27049e695c.tar.gz SLOF-d81ffe71dbd2777c3ea5a2f13f7e4b27049e695c.tar.bz2 |
Enable seamless netboot on IPv6 network
To boot from an IPv6 network user has to type "boot net:ipv6" from SLOF prompt. This
is inconvenient in auto-install environment. This patch addresses this issue by falling
back to IPv6 booting in case IPv4 booting fails (No DHCPv4 response).
Signed-off-by: Avik Sil <aviksil@linux.vnet.ibm.com>
-rw-r--r-- | clients/net-snk/app/netapps/netapps.h | 11 | ||||
-rw-r--r-- | clients/net-snk/app/netapps/netboot.c | 67 | ||||
-rw-r--r-- | clients/net-snk/app/netapps/ping.c | 2 | ||||
-rw-r--r-- | clients/net-snk/app/netlib/dhcp.c | 30 | ||||
-rw-r--r-- | clients/net-snk/app/netlib/dhcp.h | 2 | ||||
-rw-r--r-- | clients/net-snk/app/netlib/dhcpv6.c | 5 | ||||
-rw-r--r-- | clients/net-snk/app/netlib/dhcpv6.h | 3 |
7 files changed, 81 insertions, 39 deletions
diff --git a/clients/net-snk/app/netapps/netapps.h b/clients/net-snk/app/netapps/netapps.h index 8b0a5e7..18e607f 100644 --- a/clients/net-snk/app/netapps/netapps.h +++ b/clients/net-snk/app/netapps/netapps.h @@ -10,6 +10,14 @@ * IBM Corporation - initial implementation *****************************************************************************/ +#ifndef _NETAPPS_H_ +#define _NETAPPS_H_ + +#include <netlib/tftp.h> + +#define F_IPV4 4 +#define F_IPV6 6 + int netboot(int argc, char *argv[]); int netsave(int argc, char *argv[]); int netflash(int argc, char *argv[]); @@ -17,3 +25,6 @@ int bcmflash(int argc, char *argv[]); int mac_sync(int argc, char *argv[]); int net_eeprom_version( void ); int ping(int argc, char *argv[]); +int dhcp(char *ret_buffer, filename_ip_t * fn_ip, unsigned int retries, int flags); + +#endif diff --git a/clients/net-snk/app/netapps/netboot.c b/clients/net-snk/app/netapps/netboot.c index 6b7bc36..863e073 100644 --- a/clients/net-snk/app/netapps/netboot.c +++ b/clients/net-snk/app/netapps/netboot.c @@ -34,7 +34,7 @@ #define IP_INIT_DHCPV6_STATELESS 3 #define IP_INIT_IPV6_MANUAL 4 -#define DEFAULT_BOOT_RETRIES 600 +#define DEFAULT_BOOT_RETRIES 10 #define DEFAULT_TFTP_RETRIES 20 static int ip_version = 4; @@ -308,6 +308,63 @@ parse_args(const char *arg_str, obp_tftp_args_t *obp_tftp_args) } } +/** + * DHCP: Wrapper for obtaining IP and configuration info from DHCP server + * for both IPv4 and IPv6. + * (makes several attempts). + * + * @param ret_buffer buffer for returning BOOTP-REPLY packet data + * @param fn_ip contains the following configuration information: + * client MAC, client IP, TFTP-server MAC, + * TFTP-server IP, Boot file name + * @param retries No. of DHCP attempts + * @param flags flags for specifying type of dhcp attempt (IPv4/IPv6) + * ZERO - attempt DHCPv4 followed by DHCPv6 + * F_IPV4 - attempt only DHCPv4 + * F_IPV6 - attempt only DHCPv6 + * @return ZERO - IP and configuration info obtained; + * NON ZERO - error condition occurs. + */ +int dhcp(char *ret_buffer, filename_ip_t * fn_ip, unsigned int retries, int flags) +{ + int i = (int) retries+1; + int rc = -1; + + printf(" "); + + do { + printf("\b\b\b%03d", i-1); + if (getchar() == 27) { + printf("\nAborted\n"); + return -1; + } + if (!--i) { + printf("\nGiving up after %d DHCP requests\n", retries); + return -1; + } + if (!flags || (flags == F_IPV4)) { + ip_version = 4; + rc = dhcpv4(ret_buffer, fn_ip); + } + if ((!flags && (rc == -1)) || (flags == F_IPV6)) { + ip_version = 6; + set_ipv6_address(0); + rc = dhcpv6(ret_buffer, fn_ip); + if (rc == 0) { + printf("\n"); + memcpy(&fn_ip->own_ip6, get_ipv6_address(), 16); + break; + } + + } + if (rc != -1) /* either success or non-dhcp failure */ + break; + } while (1); + printf("\b\b\b\b"); + + return rc; +} + int netboot(int argc, char *argv[]) { @@ -439,12 +496,12 @@ netboot(int argc, char *argv[]) break; case IP_INIT_DHCP: printf(" Requesting IP address via DHCP: "); - rc = dhcp(ret_buffer, &fn_ip, obp_tftp_args.bootp_retries); + rc = dhcp(ret_buffer, &fn_ip, obp_tftp_args.bootp_retries, 0); break; case IP_INIT_DHCPV6_STATELESS: - set_ipv6_address(0); - rc = do_dhcpv6 (ret_buffer, &fn_ip, 10, DHCPV6_STATELESS); - memcpy(&fn_ip.own_ip6, get_ipv6_address(), 16); + printf(" Requesting information via DHCPv6: "); + rc = dhcp(ret_buffer, &fn_ip, + obp_tftp_args.bootp_retries, F_IPV6); break; case IP_INIT_IPV6_MANUAL: set_ipv6_address(&obp_tftp_args.ci6addr); diff --git a/clients/net-snk/app/netapps/ping.c b/clients/net-snk/app/netapps/ping.c index b810484..8376f48 100644 --- a/clients/net-snk/app/netapps/ping.c +++ b/clients/net-snk/app/netapps/ping.c @@ -152,7 +152,7 @@ ping(int argc, char *argv[]) if (!ping_args.client_ip.integer) { /* Get ip address for our mac address */ printf(" Requesting IP address via DHCP: "); - arp_failed = dhcp(0, &fn_ip, 30); + arp_failed = dhcp(0, &fn_ip, 30, F_IPV4); if (arp_failed == -1) { printf("\n DHCP: Could not get ip address\n"); diff --git a/clients/net-snk/app/netlib/dhcp.c b/clients/net-snk/app/netlib/dhcp.c index 0fa0615..22bf1f6 100644 --- a/clients/net-snk/app/netlib/dhcp.c +++ b/clients/net-snk/app/netlib/dhcp.c @@ -173,20 +173,8 @@ static char * response_buffer; /*>>>>>>>>>>>>>>>>>>>>>>>>>>>> IMPLEMENTATION <<<<<<<<<<<<<<<<<<<<<<<<<<<*/ -/** - * DHCP: Obtains IP and configuration info from DHCP server - * (makes several attempts). - * - * @param boot_device a socket number used to send and receive packets - * @param fn_ip contains the following configuration information: - * client MAC, client IP, TFTP-server MAC, - * TFTP-server IP, Boot file name - * @return ZERO - IP and configuration info obtained; - * NON ZERO - error condition occurs. - */ int32_t -dhcp(char *ret_buffer, filename_ip_t * fn_ip, unsigned int retries) { - int i = (int) retries+1; +dhcpv4(char *ret_buffer, filename_ip_t * fn_ip) { uint32_t dhcp_tftp_ip = 0; strcpy((char *) dhcp_filename, ""); @@ -194,20 +182,8 @@ dhcp(char *ret_buffer, filename_ip_t * fn_ip, unsigned int retries) { response_buffer = ret_buffer; - printf(" "); - - do { - printf("\b\b\b%03d", i-1); - if (getchar() == 27) { - printf("\nAborted\n"); - return -1; - } - if (!--i) { - printf("\nGiving up after %d DHCP requests\n", retries); - return -1; - } - } while (!dhcp_attempt()); - printf("\b\b\b\b"); + if (dhcp_attempt() == 0) + return -1; if (fn_ip->own_ip) { dhcp_own_ip = fn_ip->own_ip; diff --git a/clients/net-snk/app/netlib/dhcp.h b/clients/net-snk/app/netlib/dhcp.h index 73e0d01..3aab4ef 100644 --- a/clients/net-snk/app/netlib/dhcp.h +++ b/clients/net-snk/app/netlib/dhcp.h @@ -44,7 +44,7 @@ struct btphdr { }; int bootp(char *ret_buffer, filename_ip_t *, unsigned int); -int dhcp(char *ret_buffer, filename_ip_t *, unsigned int); +int dhcpv4(char *ret_buffer, filename_ip_t *); void dhcp_send_release(void); /* Handles DHCP-packets, which are detected by receive_ether. */ diff --git a/clients/net-snk/app/netlib/dhcpv6.c b/clients/net-snk/app/netlib/dhcpv6.c index 9749700..53cc7d3 100644 --- a/clients/net-snk/app/netlib/dhcpv6.c +++ b/clients/net-snk/app/netlib/dhcpv6.c @@ -95,7 +95,7 @@ dhcpv6_attempt(void) dhcpv6_state = DHCPV6_STATE_SELECT; // setting up a timer with a timeout of two seconds - for (sec = 0; sec < 4; sec++) { + for (sec = 0; sec < 2; sec++) { set_timer(TICKS_SEC); do { receive_ether(); @@ -115,8 +115,7 @@ dhcpv6_attempt(void) } int32_t -do_dhcpv6 ( char *ret_buffer, void *fn_ip, - unsigned int retries, uint8_t mode) +dhcpv6 ( char *ret_buffer, void *fn_ip) { my_fn_ip = (filename_ip_t *) fn_ip; if( !dhcpv6_attempt()) { diff --git a/clients/net-snk/app/netlib/dhcpv6.h b/clients/net-snk/app/netlib/dhcpv6.h index 0b7b9c7..078a9f1 100644 --- a/clients/net-snk/app/netlib/dhcpv6.h +++ b/clients/net-snk/app/netlib/dhcpv6.h @@ -77,8 +77,7 @@ #define DUID_LL 3 /* DUID based on Link-layer Address */ /* Prototypes */ -int32_t do_dhcpv6 ( char *ret_buffer, void *fn_ip, - unsigned int retries, uint8_t mode); +int32_t dhcpv6 ( char *ret_buffer, void *fn_ip); uint32_t handle_dhcpv6(uint8_t * , int32_t); struct dhcp6_gen_option { |