[PATCH 1/2] network configuration

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

 



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(-)

diff --git a/dracut b/dracut
index eb3ff24..fd09628 100755
--- a/dracut
+++ b/dracut
@@ -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

diff --git a/modules.d/40network/check b/modules.d/40network/check
new file mode 100755
index 0000000..b7378c3
--- /dev/null
+++ b/modules.d/40network/check
@@ -0,0 +1,5 @@
+#!/bin/sh
+#
+# This is not a module that should be selected when we try to
+# autoconfigure the initrd +exit 1
diff --git a/modules.d/40network/dhclient-script b/modules.d/40network/dhclient-script
index 103e5f0..5dd1201 100755
--- a/modules.d/40network/dhclient-script
+++ b/modules.d/40network/dhclient-script
@@ -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
diff --git a/modules.d/40network/ifup b/modules.d/40network/ifup
index 067bdf5..a8a6055 100755
--- a/modules.d/40network/ifup
+++ b/modules.d/40network/ifup
@@ -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
diff --git a/modules.d/40network/initnet.sh b/modules.d/40network/initnet.sh
new file mode 100755
index 0000000..1bbbe0e
--- /dev/null
+++ b/modules.d/40network/initnet.sh
@@ -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
diff --git a/modules.d/40network/install b/modules.d/40network/install
index 3152f0d..ecb5e6c 100755
--- a/modules.d/40network/install
+++ b/modules.d/40network/install
@@ -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"
diff --git a/modules.d/40network/kill-dhclient.sh b/modules.d/40network/kill-dhclient.sh
index d519013..ea9b7af 100755
--- a/modules.d/40network/kill-dhclient.sh
+++ b/modules.d/40network/kill-dhclient.sh
@@ -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
diff --git a/modules.d/40network/mininm.sh b/modules.d/40network/mininm.sh
new file mode 100755
index 0000000..c878982
--- /dev/null
+++ b/modules.d/40network/mininm.sh
@@ -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
+
diff --git a/modules.d/40network/run-dhclient.sh b/modules.d/40network/run-dhclient.sh
deleted file mode 100755
index afab037..0000000
--- a/modules.d/40network/run-dhclient.sh
+++ /dev/null
@@ -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 majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Kernel]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux SCSI]

  Powered by Linux