Skip to contentSkip to conversation

network configuration

PATCH In review Seewer Philippe 1 participant 1 message Mar 14, 2009

lore
Share & tools
lore
#0 lore raw

PATCH 1/2 network configuration

Add udev based, asynchronous network configuration.

Before udevd starts, ip= and BOOTIF= are checked, parsed and if necessary the current udev networking rule overwriten to fire events only for the selected device.

Actual network configurations from ip= or dhcp are written to tempfiles instead of directly applied to the interface. These tempfiles are executed later by mininm.sh after reading the interface-name through the fifo. This way we can sequentially test wich interface works for mounting the root-fs, without going through all interfaces when we do dhcp.

---

dracut                               |    2 +-
modules.d/40network/check            |    5 ++
modules.d/40network/dhclient-script  |   33 ++++++--------
modules.d/40network/ifup             |   76 ++++++++++++++++++++++------------
modules.d/40network/initnet.sh       |   37 ++++++++++++++++
modules.d/40network/install          |    8 ++-
modules.d/40network/kill-dhclient.sh |    5 ++-
modules.d/40network/mininm.sh        |   21 +++++++++
modules.d/40network/run-dhclient.sh  |    8 ----
9 files changed, 136 insertions(+), 59 deletions(-)
dracut +0 -0
index eb3ff24..fd09628 100755
@@ -63,7 +63,7 @@ trap 'rm -rf "$initdir"' 0 # clean up after ourselves no matter how we die.

export initdir hookdirs dsrc dracutmodules modules

# Create some directory structure first
-for d in bin sbin usr/bin usr/sbin usr/lib etc proc sys sysroot dev/pts; do +for d in bin sbin usr/bin usr/sbin usr/lib etc proc sys sysroot dev/pts tmp; do

    mkdir -p "$initdir/$d"; 

done

modules.d/40network/check new file +4 -0
new file mode 100755
index 0000000..b7378c3
@@ -0,0 +1,5 @@
+#!/bin/sh
+#
+# This is not a module that should be selected when we try to
+# autoconfigure the initrd +exit 1
modules.d/40network/dhclient-script +0 -0
index 103e5f0..5dd1201 100755
@@ -1,27 +1,22 @@

#!/bin/sh
-# very simple dhclient-script. All it cares about is bringing the interface -# up, and it does not even try to do anything else.
+#
+# Does not actually configure the interface. Instead we just write the +# the necessary steps into an up-script, telling mininm.sh through the +# FIFO that the interface can be used.

case $reason in
- PREINIT) /sbin/ip link set "$interface" up ;;
+ PREINIT) ip link set "$interface" up ;;
BOUND) ipopts="$new_ip_address"
- [ "$new_interface_mtu" ] && ip link set $interface mtu $new_interface_mtu
+ [ "$new_interface_mtu" ] && echo ip link set $interface mtu $new_interface_mtu > /tmp/net.$interface.up

	[ "$new_subnet_mask" ] && ipopts="$ipopts/$new_subnet_mask"
	[ "$new_broadcast_address" ] && ipopts="$ipopts broadcast $new_broadcast_address"

- /sbin/ip addr add $ipopts dev $interface
- [ "$new_routers" ] && /sbin/ip route add default via ${new_routers%%,*} dev $interface
- [ "$new_domain_name" ] && echo "domain $new_domain_name" > /etc/resolv.conf
- if [ "$new_domain_search" ]; then
- echo "search $new_domain_search" |sed 's/,//g' >> /etc/resolv.conf
- elif [ "$new_domain_name" ]; then
- echo "search $new_domain_name" >> /etc/resolv.conf
- fi
- for s in $new_domain_name_servers; do
- echo "nameserver $s" >> /etc/resolv.conf
- done
- set |grep -e '^new_[a-z_]=' |while read line; do
- echo "${line%%=*}=\'${line#*=}\'">>/net.$interface.dhcpopts
- done
- >/net.$interface.up ;;
+
+ echo ip addr add $ipopts dev $interface >> /tmp/net.$interface.up
+
+ [ "$new_routers" ] && echo ip route add default via ${new_routers%%,*} dev $interface >> /tmp/net.$interface.up
+
+ exec 3<>/tmp/iface.fifo
+ echo $interface > /tmp/iface.fifo

+	;;
    *) ;;

esac

modules.d/40network/ifup +0 -0
index 067bdf5..a8a6055 100755
@@ -1,36 +1,58 @@

#!/bin/sh
+#
+# Simple ifup script called through udev when a new network interface +# is discovered. Either forks away dhclient or writes the necessary +# up-script for mininm.sh later on. We can do dhcp asynchronously +# because the necessary event and configuration for mininm.sh are +# generated inside dhclient-script. This is a speedup optimization. +# We assume here that if there's network drivers inside the initrd, +# the user wants something. So a missing ip= option is treated as +# ip=dhcp.
+# Warning: Implementations bootp and arp do not exist yet.

-# bail immediatly if the interface is already up -[ -f "/net.$1.up" ] && exit 0
+ifup_static() {
+ local IFS=':'
+ read client server gw netmask hostname device autoconf
+
+ [ -z "$device" ] || [ "$device" = "$1" ] || return 0;
+
+ [ "$client" ] || return 0;
+ [ "$netmask" ] && client="$client/$netmask"
+
+ echo ip link set $1 up > /tmp/net.$1.up
+ echo ip addr add $client dev $1 >> /tmp/net.$1.up
+
+ [ "$gw" ] && echo ip route add default via $gw dev $1 >> /tmp/net.$1.up
+
+ exec 3<>/tmp/iface.fifo
+ echo $1 > /tmp/iface.fifo
+}
+
+# bail immediatly if the interface is already configured +[ -f "/tmp/net.$1.up" ] && exit 0

# loopback is always handled the same way
[ "$1" = "lo" ] && {
-    /sbin/ip link set lo up
-    /sbin/ip addr add 127.0.0.1/8 dev lo
+    ip link set lo up
+    ip addr add 127.0.0.1/8 dev lo
    exit 0
}

-# spin through the kernel command line, looking for ip= lines -for p in $(cat /proc/cmdline); do

-    [ "${p%ip=*}" ] || continue
-    p=${p#ip=}
-    case $p in

- none|off) exit 0;; # we were told to not configure anything
- dhcp|on|any) >/net.$1.dhcp; exit 0;; - bootp|rarp|both) exit 0;; #dunno how to do this
- *) echo ${ip#ip=} | \
- (IFS=':' read client server gw netmask hostname device autoconf
- if [ -z "$device" -o "$device" = "$1" ]; then
- case $autoconf in

-			dhcp|on|any) >/net.$1.dhcp ;;
-			none|off|'') # do some basic configuration
-			    /sbin/ip link set $1 up
-			    /sbin/ip addr add $client/$netmask dev $1
-			    [ "$gw" ] && /sbin/ip route add default via $gw dev $1
-			    >/net.$1.up ;;

- esac
- fi
- ) ;;
- *) continue;;
- esac
+# get ip= option
+for p in $(cat /tmp/cmdline); do
+ [ "${p%%=*}" = "ip" ] || continue
+ IP=${p#*=} + break;
done
+
+
+# set autoconf to dhcp if empty, or no ip= is provided +autoconf=${IP##*:*:*:*:*:*:}
+[ "$autoconf" ] || autoconf="dhcp"
+
+# Let's do something
+case $autoconf in + bootp|rarp|both) exit 0;;
+ on|any|dhcp) dhclient -q $1 &;;
+ *) echo $IP | ifup_static $1 ;;
+esac

modules.d/40network/initnet.sh new file +37 -0
new file mode 100755
index 0000000..1bbbe0e
@@ -0,0 +1,37 @@
+#!/bin/sh
+#
+# Makes sure the network fifo is there and creates special udev rules
+# to fire only for network devices we need or want. This is an
+# optimization, it is not strictly necessary.
+
+fix_bootif() {
+    local macaddr=${1##??-}
+    local IFS='-'
+    macaddr=$(for i in ${macaddr} ; do echo -n $i:; done)
+    macaddr=${macaddr%:}
+    echo $macaddr
+}
+
+dst="/lib/udev/rules.d"
+[ -d /etc/udev/rules.d ] && dst="/etc/udev/rules.d"
+
+#Assume the user knows what he's doing when providing a devicename
+BOOTDEV=$(getarg 'ip=')
+[ "$BOOTDEV" ] && [ ! "$BOOTDEV" = "${BOOTDEV#*:}" ] && {
+echo $BOOTDEV
+    BOOTDEV=${BOOTDEV#*:*:*:*:}
+    BOOTDEV=${BOOTDEV%:*}
+
+    [ "$BOOTDEV" ] && printf 'ACTION=="add", SUBSYSTEM=="net", INTERFACE_NAME=="%s", RUN+="/sbin/ifup $env{INTERFACE}"\n' "$BOOTDEV" > $dst/60-net.rules
+}
+
+#Prefer mac-address to bootdev, overwrite if provided
+BOOTIF=$(getarg 'BOOTIF=')
+[ "$BOOTIF" ] && {
+    BOOTIF=$(fix_bootif "$BOOTIF")
+
+    printf 'ACTION=="add", SUBSYSTEM=="net", ATTR{address}=="%s", RUN+="/sbin/ifup $env{INTERFACE}"\n' "$BOOTIF" > $dst/60-net.rules
+}
+
+#Syncronization FIFO for mininm.sh
+mkfifo /tmp/iface.fifo
modules.d/40network/install +0 -0
index 3152f0d..ecb5e6c 100755
@@ -1,8 +1,10 @@

#!/bin/bash
-dracut_install ip dhclient
+dracut_install ip dhclient mkfifo
inst "$moddir/ifup" "/sbin/ifup"
inst "$moddir/dhclient-script" "/sbin/dhclient-script" -instmods =networking ecb arc4
+instmods =net ecb arc4 af_packet
inst_rules "$moddir/60-net.rules"
+
+inst_hook pre-udev 10 "$moddir/initnet.sh" inst_hook pre-pivot 10 "$moddir/kill-dhclient.sh" -inst_hook pre-mount 70 "$moddir/run-dhclient.sh" +inst_hook mount 40 "$moddir/mininm.sh"

modules.d/40network/kill-dhclient.sh +0 -0
index d519013..ea9b7af 100755
@@ -1,4 +1,7 @@

#!/bin/sh
+#
+# Dracut initrd should be free of side effects. Kill any runaway +# dhclients.

pid=$(pidof dhclient)
-[[ $pid ]] && kill $pid
+[[ $pid ]] && kill $pid
\ No newline at end of file

modules.d/40network/mininm.sh new file +20 -0
new file mode 100755
index 0000000..c878982
@@ -0,0 +1,21 @@
+#!/bin/sh
+#
+# Mini network manager: Should be called before trying to mount
+# something. Receives names of ready interfaces through a blocking
+# FIFO, configures that interface and hopes mount will
+# succeed. Otherwise we return here from the init loop and try the
+# next interface. +
+#No Netboot? bail out
+[ $NETBOOT ] || continue;
+
+#Deconfigure running interface. Means we've tried one and
+#failed. Ensures that the default route is cleared as well.
+[ $NETIF ] && ip link set $NETIF down
+
+#Read or wait for next ready interface
+read NETIF < /tmp/iface.fifo;
+
+#Configure interface
+[ -e /tmp/net.$NETIF.up ] && . /tmp/net.$NETIF.up
+
modules.d/40network/run-dhclient.sh deleted +0 -8
deleted file mode 100755
index afab037..0000000
@@ -1,8 +0,0 @@
-#!/bin/sh
-for i in /net.*.dhcp; do
-    dev=${i#net.}; dev=${i%.dhcp}
-    [ -f "/net.$dev.up" ] && continue
-    dhclient -1 -q $dev &
-done
-wait
-    \ No newline at end of file

--
To unsubscribe from this list: send the line "unsubscribe initramfs" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html