Browse Source

multinic support: Add bootdev cmdline argument

This introduces a new cmdline argument bootdev, to support the case
where multiple nics need to be up before the netroot handler is called.
Cases involved might be bonding, iscsi multipathing, bonding, ...
This argument is required to decide which interface is the primary to
use for dhcp root-path, default gw, etc.

When multiple ip= items are present on the cmdline, the ip= parser
now enforces the presence of <dev> further demands that the new argument
bootdev contains the name of the primary interface. Configurtion if of
course still delegated to netroot but in is enhance to ensure that netroot
"waits" for all required interfaces to be up.

Example: root=dhcp ip=eth0:dhcp ip=client-ip:::netmask::eth1:off bootdev=eth0

First, the ip= cmdline parser ensures that all ip items contain a <dev> then
checks the ip items and checks as well that an ip= item for the given bootdev
was found.

When the first netroot starts, probably for eth1, it checks wheter interface
configuration for all interfaces is available. If not it exits. The second
start of netroot (eth0, which was a bit delayed because of dhcp) sees that
all interfaces are present, configures them and continues.
master
Philippe Seewer 16 years ago
parent
commit
8ecd9d010a
  1. 8
      modules.d/40network/net-genrules.sh
  2. 34
      modules.d/40network/netroot
  3. 63
      modules.d/40network/parse-ip-opts.sh
  4. 6
      modules.d/40network/write-ifcfg.sh

8
modules.d/40network/net-genrules.sh

@ -20,6 +20,14 @@ fix_bootif() { @@ -20,6 +20,14 @@ fix_bootif() {
if [ -n "$BOOTIF" ] ; then
BOOTIF=$(fix_bootif "$BOOTIF")
printf 'ACTION=="add", SUBSYSTEM=="net", ATTR{address}=="%s", RUN+="/sbin/ifup $env{INTERFACE}"\n' "$BOOTIF"

# If we have to handle multiple interfaces, handle only them.
elif [ -n "$IFACES" ] ; then
for iface in $IFACES ; do
printf 'ACTION=="add", SUBSYSTEM=="net", KERNEL=="%s", RUN+="/sbin/ifup $env{INTERFACE}"\n' "$iface"
done

# Default: We don't know the interface to use, handle all
else
printf 'ACTION=="add", SUBSYSTEM=="net", RUN+="/sbin/ifup $env{INTERFACE}"\n'
fi

34
modules.d/40network/netroot

@ -30,7 +30,17 @@ fi @@ -30,7 +30,17 @@ fi
[ -d $NEWROOT/proc ] && exit 0
[ -z "$netroot" ] && exit 1

# Let's see if we have to wait for other interfaces
# Note: exit works just fine, since the last interface to be
# online'd should see all files
[ -e "/tmp/net.ifaces" ] && read IFACES < /tmp/net.ifaces
for iface in $IFACES ; do
[ -e /tmp/net.$iface.up ] || exit 1
done

# Set or override primary interface
netif=$1
[ -e "/tmp/net.bootdev" ] && read netif < /tmp/net.bootdev

# Figure out the handler for root=dhcp by recalling all netroot cmdline
# handlers
@ -41,6 +51,14 @@ if [ "$netroot" = "dhcp" ] ; then @@ -41,6 +51,14 @@ if [ "$netroot" = "dhcp" ] ; then
# Load dhcp options
[ -e /tmp/dhclient.$netif.dhcpopts ] && . /tmp/dhclient.$netif.dhcpopts

# If we have a specific bootdev with no dhcpoptions or empty root-path,
# we die. Otherwise we just warn
if [ -z "$new_root_path" ] ; then
[ -n "$BOOTDEV" ] && die "No dhcp root-path received for '$BOOTDEV'"
warn "No dhcp root-path received for '$BOOTDEV' trying other interfaces if available"
exit 1
fi

# Set netroot to new_root_path, so cmdline parsers don't call
netroot=$new_root_path

@ -63,7 +81,11 @@ if [ -z "$netroot" ] || [ ! -e "$handler" ] ; then @@ -63,7 +81,11 @@ if [ -z "$netroot" ] || [ ! -e "$handler" ] ; then
fi

# We're here, so we can assume that upping interfaces is now ok
. /tmp/net.$netif.up
[ -z "$IFACES" ] && IFACES="$netif"
for iface in $IFACES ; do
. /tmp/net.$iface.up
done

[ -e /tmp/net.$netif.gw ] && . /tmp/net.$netif.gw
[ -e /tmp/net.$netif.hostname ] && . /tmp/net.$netif.hostname
[ -e /tmp/net.$netif.resolv.conf ] && cp -f /tmp/net.$netif.resolv.conf /etc/resolv.conf
@ -75,17 +97,21 @@ source_all netroot @@ -75,17 +97,21 @@ source_all netroot
# XXX other variables to export?
if $handler $netif $netroot $NEWROOT; then
# Network rootfs mount successful
[ -f /tmp/dhclient.$netif.lease ] && cp /tmp/dhclient.$netif.lease /tmp/net.$netif.lease
[ -f /tmp/dhclient.$netif.dhcpopts ] && cp /tmp/dhclient.$netif.dhcpopts /tmp/net.$netif.dhcpopts
for iface in $IFACES ; do
[ -f /tmp/dhclient.$iface.lease ] && cp /tmp/dhclient.$iface.lease /tmp/net.$iface.lease
[ -f /tmp/dhclient.$iface.dhcpopts ] && cp /tmp/dhclient.$iface.dhcpopts /tmp/net.$iface.dhcpopts
done

# Save used netif for later use
echo $netif > /tmp/net.bootdev
[ ! -f /tmp/net.ifaces ] && echo $netif > /tmp/net.ifaces
else
warn "Mounting root via '$netif' failed"
# If we're trying with multiple interfaces, put that one down.
# ip down/flush ensures that routeing info goes away as well
if [ -z "$BOOTDEV" ] ; then
ip link set $netif down
ip addr flush dev $netif
echo "#empty" > /etc/resolv.conf
fi
fi
exit 0

63
modules.d/40network/parse-ip-opts.sh

@ -7,6 +7,10 @@ @@ -7,6 +7,10 @@
#
# ip=<client-IP-number>:<server-id>:<gateway-IP-number>:<netmask>:<client-hostname>:<interface>:[dhcp|on|any|none|off]
#
# When supplying more than only ip= line, <interface> is mandatory and
# bootdev= must contain the name of the primary interface to use for
# routing,dns,dhcp-options,etc.
#

# Sadly there's no easy way to split ':' separated lines into variables
ip_to_var() {
@ -47,6 +51,22 @@ if [ -n "$netroot" ] && [ -z "$(getarg ip=)" ] ; then @@ -47,6 +51,22 @@ if [ -n "$netroot" ] && [ -z "$(getarg ip=)" ] ; then
return;
fi

# Count ip= lines to decide whether we need bootdev= or not
if [ -z "$NEEDBOOTDEV" ] ; then
[ "$CMDLINE" ] || read CMDLINE < /proc/cmdline
local count=0
for p in $CMDLINE; do
[ "${p%%=*}" = "ip" ] && count=$(( $count + 1 ))
done
[ $count -gt 1 ] && NEEDBOOTDEV=1
fi

# If needed, check if bootdev= contains anything usable
if [ -n "$NEEDBOOTDEV" ] ; then
BOOTDEV=$(getarg bootdev=) || die "Please supply bootdev argument for multiple ip= lines"
[ -z "$BOOTDEV" ] && die "Bootdev argument is empty"
fi

# Check ip= lines
# XXX Would be nice if we could errorcheck ip addresses here as well
[ "$CMDLINE" ] || read CMDLINE < /proc/cmdline
@ -55,6 +75,9 @@ for p in $CMDLINE; do @@ -55,6 +75,9 @@ for p in $CMDLINE; do

ip_to_var ${p#ip=}

# We need to have an ip= line for the specified bootdev
[ -n "$NEEDBOOTDEV" ] && [ "$dev" = "$BOOTDEV" ] && BOOTDEVOK=1

# Empty autoconf defaults to 'dhcp'
if [ -z "$autoconf" ] ; then
warn "Empty autoconf values default to dhcp"
@ -72,34 +95,52 @@ for p in $CMDLINE; do @@ -72,34 +95,52 @@ for p in $CMDLINE; do
die "Sorry, automatic calculation of netmask is not yet supported"
;;
dhcp|on|any) \
[ -n "$NEEDBOOTDEV" ] && [ -z "$dev" ] && \
die "Sorry, '$p' does not make sense for multiple interface configurations"
[ -n "$ip" ] && \
die "For argument '$p'\nSorry, setting client-ip does not make sense for '$autoconf'"
;;
*) die "For argument '$p'\nSorry, unknown value '$autoconf'";;
esac

# We don't like duplicate device configs
if [ -n "$dev" ] ; then
# We don't like duplicate device configs
if [ -n "$IFACES" ] ; then
for i in $IFACES ; do
[ "$dev" = "$i" ] && die "For argument '$p'\nDuplication configurations for '$dev'"
done
fi
# IFACES list for later use
IFACES="$IFACES $dev"
fi

# Do we need DHCP? (It's simpler to check for a set ip. Checks above ensure that if
# ip is there, we're static)
[ -n "$NEEDDHCP" ] && [ -z "$ip" ] && DHCPOK="1"

# Do we need srv OR dhcp?
if [ -n "$DHCPORSERVER" ] ; then
[ -n "$DHCPOK" ] && SRVOK="1"
[ -n "$srv" ] && SRVOK="1"
# Small optimization for udev rules
[ -z "$NEEDBOOTDEV" ] && [ -n "$dev" ] && BOOTDEV=$dev

# Do we need to check for specific options?
if [ -n "$NEEDDHCP" ] || [ -n "$DHCPORSERVER" ] ; then
# Correct device? (Empty is ok as well)
[ "$dev" = "$BOOTDEV" ] || continue
# Server-ip is there?
[ -n "$DHCPORSERVER" ] && [ -n "$srv" ] && continue
# dhcp? (It's simpler to check for a set ip. Checks above ensure that if
# ip is there, we're static
[ -z "$ip" ] && continue
# Not good!
die "Server-ip or dhcp for netboot needed, but current arguments say otherwise"
fi

done

[ -n "$NEEDDHCP" ] && [ -z "$DHCPOK" ] && die "Server-ip or dhcp for netboot needed, but current arguments say otherwise"
# This ensures that BOOTDEV is always first in IFACES
if [ -n "$BOOTDEV" ] && [ -n "$IFACES" ] ; then
IFACES="${IFACES%$BOOTDEV*} ${IFACES#*$BOOTDEV}"
IFACES="$BOOTDEV $IFACES"
fi

# Store BOOTDEV and IFACES for later use
[ -n "$BOOTDEV" ] && echo $BOOTDEV > /tmp/net.bootdev
[ -n "$IFACES" ] && echo $IFACES > /tmp/net.ifaces

[ -n "$DHCPORSERVER" ] && [ -z "$SRVOK" ] && die "Server-ip or dhcp for netboot needed, but current arguments say otherwise"
# We need a ip= line for the configured bootdev=
[ -n "$NEEDBOOTDEV" ] && [ -z "$BOOTDEVOK" ] && die "Bootdev Argument '$BOOTDEV' not found"

6
modules.d/40network/write-ifcfg.sh

@ -1,10 +1,11 @@ @@ -1,10 +1,11 @@
#!/bin/sh

# Don't write anything if we don't know our bootdev
[ -f /tmp/net.bootdev ] || return 1
[ -f /tmp/net.ifaces ] || return 1

read netif < /tmp/net.bootdev
read IFACES < /tmp/net.ifaces

for netif in $IFACES ; do
cat /sys/class/net/$netif/address > /tmp/net.$netif.hwaddr
echo "# Generated by dracut initrd" > /tmp/net.$netif.ifcfg
echo "DEVICE=$netif" >> /tmp/net.$netif.ifcfg
@ -21,3 +22,4 @@ else @@ -21,3 +22,4 @@ else
echo "NETMASK=$mask" >> /tmp/net.$netif.ifcfg
[ -n "$gw" ] && echo "GATEWAY=$gw" >> /tmp/net.$netif.ifcfg
fi
done

Loading…
Cancel
Save