[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#703744: live-boot: Select BOOTIF device for real root network mount if defined



Source: live-boot
Version: 3.0.1-1
Severity: normal
Tags: patch

(To provide context independent of the previous bug I filed I've copied
the first paragraph below).

I'm trying to netboot an x86 system which has multiple NICs, though only
one is recognised by the BIOS/PXE boot firmware and as such the full
netboot process should happen over this interface. However, during
early-userspace live-boot attempts to probe a set of NICs which may or
may not contain the one used for PXE due to seemingly variable delays in
the NIC becoming available.

Currently live-boot appears to probe all interfaces which are available
at the time of script execution, which, at least in my configuration,
seems to be prone to racing. The attached patch provides an alternative
approach whilst still supporting the current behaviour: If BOOTIF is
present on the kernel commandline use the adapter associated with the
MAC to mount the real root after waiting for it to come up. Otherwise,
i.e. if BOOTIF is not supplied, use the current behaviour.

The logic for determining the interface to use from the MAC in BOOTIF
was already contained in scripts/boot/9990-networking.sh, but from what
I understand in order to provide the behaviour described above it's also
needed in scripts/boot/9990-select-eth-device.sh. In addition, the logic
was embedded in a function that performed other duties, so couldn't be
used directly.

The attached patch pulls the MAC->NIC logic out into a new function,
Device_from_bootif(), in scripts/boot/9990-networking.sh and then
sources /lib/live/boot/9990-networking.sh in
/lib/live/boot/9990-select-eth-device.sh for access.

I'm sure there will be revisions of the patch, as I've just now dived
head-long into live-boot to get this system up and running; I haven't
touched the codebase prior. I'm happy to revise as necessary if the
approach used can be made more tasteful.

Note: System information below isn't terribly relevant.

-- System Information:
Debian Release: 7.0
  APT prefers testing
  APT policy: (650, 'testing'), (600, 'unstable')
Architecture: amd64 (x86_64)

Kernel: Linux 3.7.2 (SMP w/8 CPU cores)
Locale: LANG=en_AU.UTF-8, LC_CTYPE=en_AU.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash
>From 9ba45f2e340b91ac8ddb1c786d823869aec0e581 Mon Sep 17 00:00:00 2001
From: Andrew Jeffery <andrewj@avalon.com.au>
Date: Thu, 21 Mar 2013 10:58:53 +1030
Subject: [PATCH 2/3] Netboot: Select BOOTIF device if defined

Avoid probing all the devices again if we know which device we've booted
from.
---
 scripts/boot/9990-networking.sh        |   99 +++++++++++++++++---------------
 scripts/boot/9990-select-eth-device.sh |   46 +++++++++------
 2 files changed, 82 insertions(+), 63 deletions(-)

diff --git a/scripts/boot/9990-networking.sh b/scripts/boot/9990-networking.sh
index f32ae6c..91bd73a 100755
--- a/scripts/boot/9990-networking.sh
+++ b/scripts/boot/9990-networking.sh
@@ -2,6 +2,57 @@
 
 #set -e
 
+Device_from_bootif ()
+{
+	# support for Syslinux IPAPPEND parameter
+	# it sets the BOOTIF variable on the kernel parameter
+
+	if [ -n "${BOOTIF}" ]
+	then
+	# pxelinux sets BOOTIF to a value based on the mac address of the
+	# network card used to PXE boot, so use this value for DEVICE rather
+	# than a hard-coded device name from initramfs.conf. this facilitates
+	# network booting when machines may have multiple network cards.
+	# pxelinux sets BOOTIF to 01-$mac_address
+
+	# strip off the leading "01-", which isn't part of the mac
+	# address
+	temp_mac=${BOOTIF#*-}
+
+	# convert to typical mac address format by replacing "-" with ":"
+	bootif_mac=""
+	IFS='-'
+	for x in $temp_mac
+	do
+		if [ -z "$bootif_mac" ]
+		then
+			bootif_mac="$x"
+		else
+			bootif_mac="$bootif_mac:$x"
+		fi
+	done
+	unset IFS
+
+	# look for devices with matching mac address, and set DEVICE to
+	# appropriate value if match is found.
+
+	for device in /sys/class/net/*
+	do
+		if [ -f "$device/address" ]
+		then
+		current_mac=$(cat "$device/address")
+
+			if [ "$bootif_mac" = "$current_mac" ]
+			then
+				DEVICE=${device##*/}
+				break
+			fi
+		fi
+	done
+	fi
+
+}
+
 do_netsetup ()
 {
 	modprobe -q af_packet # For DHCP
@@ -14,52 +65,8 @@ do_netsetup ()
 
 	if [ -z "${NETBOOT}" ] && [ -z "${FETCH}" ] && [ -z "${HTTPFS}" ] && [ -z "${FTPFS}" ]
 	then
-		# support for Syslinux IPAPPEND parameter
-		# it sets the BOOTIF variable on the kernel parameter
-
-		if [ -n "${BOOTIF}" ]
-		then
-			# pxelinux sets BOOTIF to a value based on the mac address of the
-			# network card used to PXE boot, so use this value for DEVICE rather
-			# than a hard-coded device name from initramfs.conf. this facilitates
-			# network booting when machines may have multiple network cards.
-			# pxelinux sets BOOTIF to 01-$mac_address
-
-			# strip off the leading "01-", which isn't part of the mac
-			# address
-			temp_mac=${BOOTIF#*-}
-
-			# convert to typical mac address format by replacing "-" with ":"
-			bootif_mac=""
-			IFS='-'
-			for x in $temp_mac
-			do
-				if [ -z "$bootif_mac" ]
-				then
-					bootif_mac="$x"
-				else
-					bootif_mac="$bootif_mac:$x"
-				fi
-			done
-			unset IFS
-
-			# look for devices with matching mac address, and set DEVICE to
-			# appropriate value if match is found.
-
-			for device in /sys/class/net/*
-			do
-				if [ -f "$device/address" ]
-				then
-					current_mac=$(cat "$device/address")
-
-					if [ "$bootif_mac" = "$current_mac" ]
-					then
-						DEVICE=${device##*/}
-						break
-					fi
-				fi
-			done
-		fi
+		# See if we can select the device from BOOTIF
+		Device_from_bootif
 
 		# if ethdevice was not specified on the kernel command line
 		# make sure we try to get a working network configuration
diff --git a/scripts/boot/9990-select-eth-device.sh b/scripts/boot/9990-select-eth-device.sh
index 5a769ce..dd55093 100755
--- a/scripts/boot/9990-select-eth-device.sh
+++ b/scripts/boot/9990-select-eth-device.sh
@@ -1,5 +1,8 @@
 #!/bin/sh
 
+# Source for Device_from_bootif()
+. /lib/live/boot/9990-networking.sh
+
 Select_eth_device ()
 {
 	# Boot type in initramfs's config
@@ -26,31 +29,40 @@ Select_eth_device ()
 
 	# Available Ethernet interfaces ?
 	l_interfaces=""
-	echo "Waiting for ethernet card(s) up... If this fails, maybe the ethernet card is not supported by the kernel `uname -r`?"
-	while [ -z "$l_interfaces" ]
-	do
-		l_interfaces="$(cd /sys/class/net/ && ls -d eth* 2>/dev/null)"
-	done
 
-	if [ $(echo $l_interfaces | wc -w) -lt 2 ]
+	# See if we can derive the boot device
+	Device_from_bootif
+
+	if [ -z "$DEVICE" ]
 	then
-		# only one interface : no choice
-		echo "DEVICE=$l_interfaces" >> /conf/param.conf
-		return
-	fi
+		echo "Waiting for ethernet card(s) up... If this fails, maybe the ethernet card is not supported by the kernel `uname -r`?"
+		while [ -z "$l_interfaces" ]
+		do
+			l_interfaces="$(cd /sys/class/net/ && ls -d eth* 2>/dev/null)"
+		done
 
-	# If user force to use specific device, write it
-	for ARGUMENT in ${_CMDLINE}
-	do
-		case "${ARGUMENT}" in
-			live-netdev=*)
+		if [ $(echo $l_interfaces | wc -w) -lt 2 ]
+		then
+			# only one interface : no choice
+			echo "DEVICE=$l_interfaces" >> /conf/param.conf
+			return
+		fi
+
+		# If user force to use specific device, write it
+		for ARGUMENT in ${_CMDLINE}
+		do
+			case "${ARGUMENT}" in
+				live-netdev=*)
 				NETDEV="${ARGUMENT#live-netdev=}"
 				echo "DEVICE=$NETDEV" >> /conf/param.conf
 				echo "Found live-netdev parameter, forcing to to use network device $NETDEV."
 				return
 				;;
-		esac
-	done
+			esac
+		done
+	else
+		l_interfaces="$DEVICE"
+	fi
 
 	found_eth_dev=""
 	while true
-- 
1.7.10.4


Reply to: