diff --git a/modules.d/40network/check b/modules.d/40network/check index 79a6d978..3d450305 100755 --- a/modules.d/40network/check +++ b/modules.d/40network/check @@ -1,4 +1,4 @@ #!/bin/sh -which ip dhclient hostname >/dev/null 2>&1 || exit 1 +which ip dhclient hostname brctl >/dev/null 2>&1 || exit 1 exit 255 diff --git a/modules.d/40network/ifup b/modules.d/40network/ifup index 89017bb3..04508559 100755 --- a/modules.d/40network/ifup +++ b/modules.d/40network/ifup @@ -60,6 +60,14 @@ fi # $netif reads easier than $1 netif=$1 +# bridge this interface? +if [ -e /tmp/bridge.info ]; then + . /tmp/bridge.info + if [ "$netif" = "$ethname" ]; then + netif="$bridgename" + fi +fi + # bail immediately if the interface is already up # or we don't need the network [ -f "/tmp/net.$netif.up" ] && exit 0 @@ -77,6 +85,15 @@ fi # XXX need error handling like dhclient-script +# start bridge if necessary +if [ "$netif" = "$bridgename" ] && [ ! -e /tmp/net.$bridgename.up ]; then + ip link set $ethname up + # Create bridge and add eth to bridge + brctl addbr $bridgename + brctl setfd $bridgename 0 + brctl addif $bridgename $ethname +fi + # No ip lines default to dhcp ip=$(getarg ip) [ -z "$ip" ] && do_dhcp; diff --git a/modules.d/40network/install b/modules.d/40network/install index 0b76cbd7..729f1f14 100755 --- a/modules.d/40network/install +++ b/modules.d/40network/install @@ -1,5 +1,5 @@ #!/bin/bash -dracut_install ip dhclient hostname +dracut_install ip dhclient hostname brctl # Include wired net drivers, excluding wireless for modname in $(find "/lib/modules/$kernel/kernel/drivers" -name '*.ko'); do if nm -uPA $modname | grep -q eth_type_trans; then @@ -15,9 +15,12 @@ inst "$moddir/netroot" "/sbin/netroot" inst "$moddir/dhclient-script" "/sbin/dhclient-script" inst "$moddir/dhclient.conf" "/etc/dhclient.conf" instmods ecb arc4 +# bridge modules +instmods bridge stp llc inst_hook pre-udev 60 "$moddir/net-genrules.sh" inst_hook cmdline 91 "$moddir/dhcp-root.sh" inst_hook cmdline 99 "$moddir/parse-ip-opts.sh" +inst_hook cmdline 98 "$moddir/parse-bridge.sh" inst_hook pre-pivot 10 "$moddir/kill-dhclient.sh" # TODO ifcfg config style is redhat specific, this should probably diff --git a/modules.d/40network/net-genrules.sh b/modules.d/40network/net-genrules.sh index dbd04741..04e0528b 100755 --- a/modules.d/40network/net-genrules.sh +++ b/modules.d/40network/net-genrules.sh @@ -14,6 +14,11 @@ fix_bootif() { # Write udev rules { + # bridge: attempt only the defined interface + if [ -e /tmp/bridge.info ]; then + . /tmp/bridge.info + IFACES=$ethname + fi # BOOTIF says everything, use only that one BOOTIF=$(getarg 'BOOTIF=') diff --git a/modules.d/40network/parse-bridge.sh b/modules.d/40network/parse-bridge.sh new file mode 100644 index 00000000..494da2d6 --- /dev/null +++ b/modules.d/40network/parse-bridge.sh @@ -0,0 +1,53 @@ +#!/bin/sh +# +# Format: +# bridge=: +# +# bridge without parameters assumes bridge=br0:eth0 +# + +# return if bridge already parsed +[ -n "$bridgename" ] && return + +# Check if bridge parameter is valid +if getarg ip= >/dev/null ; then + if [ -z "$netroot" ] ; then + die "No netboot configured, bridge is invalid" + fi +fi + +parsebridge() { + local v=${1}: + set -- + while [ -n "$v" ]; do + set -- "$@" "${v%%:*}" + v=${v#*:} + done + + unset bridgename ethname + case $# in + 0) bridgename=br0; ethname=eth0 ;; + 1) die "bridge= requires two parameters" ;; + 2) bridgename=$1; ethname=$2 ;; + *) die "bridge= requires two parameters" ;; + esac +} + +unset bridgename ethname + +# Parse bridge for bridgename and ethname +if getarg bridge >/dev/null; then + # Read bridge= parameters if they exist + bridge="$(getarg bridge=)" + if [ ! "$bridge" = "bridge" ]; then + parsebridge "$(getarg bridge=)" + fi + # Simple default bridge + if [ -z "$bridgename" ]; then + bridgename=br0 + ethname=eth0 + fi + echo "bridgename=$bridgename" > /tmp/bridge.info + echo "ethname=$ethname" >> /tmp/bridge.info + return +fi diff --git a/modules.d/40network/write-ifcfg.sh b/modules.d/40network/write-ifcfg.sh index c408076b..4fa59e0e 100755 --- a/modules.d/40network/write-ifcfg.sh +++ b/modules.d/40network/write-ifcfg.sh @@ -6,11 +6,14 @@ read IFACES < /tmp/net.ifaces for netif in $IFACES ; do + # bridge? + unset bridge + if [ "$netif" = "$bridgename" ]; then + bridge=yes + fi 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 - echo "HWADDR=$(cat /sys/class/net/$netif/address)" >> /tmp/net.$netif.ifcfg - echo "TYPE=Ethernet" >> /tmp/net.$netif.ifcfg echo "ONBOOT=yes" >> /tmp/net.$netif.ifcfg if [ -f /tmp/net.$netif.lease ]; then echo "BOOTPROTO=dhcp" >> /tmp/net.$netif.ifcfg @@ -22,4 +25,23 @@ for netif in $IFACES ; do echo "NETMASK=$mask" >> /tmp/net.$netif.ifcfg [ -n "$gw" ] && echo "GATEWAY=$gw" >> /tmp/net.$netif.ifcfg fi + + # bridge needs differente things written to ifcfg + if [ -z "$bridge" ]; then + # standard interface + echo "HWADDR=$(cat /sys/class/net/$netif/address)" >> /tmp/net.$netif.ifcfg + echo "TYPE=Ethernet" >> /tmp/net.$netif.ifcfg + echo "NAME=\"Boot Disk\"" >> /tmp/net.$netif.ifcfg + else + # bridge + echo "TYPE=Bridge" >> /tmp/net.$netif.ifcfg + echo "NAME=\"Boot Disk\"" >> /tmp/net.$netif.ifcfg + # write separate ifcfg file for the raw eth interface + echo "DEVICE=$ethname" >> /tmp/net.$ethname.ifcfg + echo "TYPE=Ethernet" >> /tmp/net.$ethname.ifcfg + echo "ONBOOT=yes" >> /tmp/net.$ethname.ifcfg + echo "HWADDR=$(cat /sys/class/net/$ethname/address)" >> /tmp/net.$ethname.ifcfg + echo "BRIDGE=$netif" >> /tmp/net.$ethname.ifcfg + echo "NAME=$ethname" >> /tmp/net.$ethname.ifcfg + fi done diff --git a/test/TEST-20-NFS/test.sh b/test/TEST-20-NFS/test.sh index 1811eca3..cd814241 100755 --- a/test/TEST-20-NFS/test.sh +++ b/test/TEST-20-NFS/test.sh @@ -125,6 +125,9 @@ test_nfsv3() { client_test "NFSv3 root=nfs:..." 52:54:00:12:34:04 \ "root=nfs:192.168.50.1:/nfs/client" 192.168.50.1 -wsize=4096 || return 1 + client_test "NFSv3 Bridge root=nfs:..." 52:54:00:12:34:04 \ + "root=nfs:192.168.50.1:/nfs/client bridge" 192.168.50.1 -wsize=4096 || return 1 + client_test "NFSv3 Legacy root=IP:path" 52:54:00:12:34:04 \ "root=192.168.50.1:/nfs/client" 192.168.50.1 -wsize=4096 || return 1 @@ -135,6 +138,9 @@ test_nfsv3() { client_test "NFSv3 root=dhcp DHCP path,options" \ 52:54:00:12:34:05 "root=dhcp" 192.168.50.1 wsize=4096 || return 1 + client_test "NFSv3 Bridge Customized root=dhcp DHCP path,options" \ + 52:54:00:12:34:05 "root=dhcp bridge=foobr0:eth0" 192.168.50.1 wsize=4096 || return 1 + client_test "NFSv3 root=dhcp DHCP IP:path,options" \ 52:54:00:12:34:06 "root=dhcp" 192.168.50.2 wsize=4096 || return 1 diff --git a/test/TEST-40-NBD/test.sh b/test/TEST-40-NBD/test.sh index c3d8bfc0..b3a580f1 100755 --- a/test/TEST-40-NBD/test.sh +++ b/test/TEST-40-NBD/test.sh @@ -106,6 +106,10 @@ test_run() { "root=nbd:192.168.50.1:2000:ext2:errors=panic" \ ext2 errors=panic || return 1 + client_test "NBD Bridge root=nbd:IP:port:fstype:fsopts" 52:54:00:12:34:00 \ + "root=nbd:192.168.50.1:2000:ext2:errors=panic bridge" \ + ext2 errors=panic || return 1 + # There doesn't seem to be a good way to validate the NBD options, so # just check that we don't screw up the other options @@ -125,6 +129,9 @@ test_run() { client_test "NBD root=dhcp DHCP root-path nbd:srv:port" 52:54:00:12:34:01 \ "root=dhcp" || return 1 + client_test "NBD Bridge root=dhcp DHCP root-path nbd:srv:port" 52:54:00:12:34:01 \ + "root=dhcp bridge" || return 1 + client_test "NBD root=dhcp DHCP root-path nbd:srv:port:fstype" \ 52:54:00:12:34:02 "root=dhcp" ext2 || return 1