aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvik Sil <aviksil@linux.vnet.ibm.com>2013-12-27 14:46:17 +0530
committerAvik Sil <aviksil@linux.vnet.ibm.com>2014-01-20 17:19:47 +0530
commitd81ffe71dbd2777c3ea5a2f13f7e4b27049e695c (patch)
tree1ca8a93b2e669577059c2ef505c9f8cd5b35e90c
parenta8c1a27c16b786bd5b6ccb93bfd7ca0354067f2a (diff)
downloadSLOF-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.h11
-rw-r--r--clients/net-snk/app/netapps/netboot.c67
-rw-r--r--clients/net-snk/app/netapps/ping.c2
-rw-r--r--clients/net-snk/app/netlib/dhcp.c30
-rw-r--r--clients/net-snk/app/netlib/dhcp.h2
-rw-r--r--clients/net-snk/app/netlib/dhcpv6.c5
-rw-r--r--clients/net-snk/app/netlib/dhcpv6.h3
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 {