Bruce Dubbs wrote:
> Bryan Kadzban wrote:
>> Are the sources for this tarball in a source control repository 
>> somewhere? I might have missed where, in the discussion earlier
>> when it was being created. I don't see them in the book repository,
>> but that repository may not be the best place to keep track of
>> them, either.
> 
> No, they are not in a repository, although we could put them in the
> LFS svn as, say LFS/trunk/udev-lfs/.  What I have been doing is
> creating the tarballs and uploading to anduin.  I then put that link
> into the book or, at this stage, post to the list.

Yeah, I'd hate to lose the history.  It'd also make changes like what
I'm trying to do below a bit easier, because I could add the indirection
and rip out the installation of the persistent-net rules stuff in the
same commit -- if we go this way, of course.

(Note that the attached patches aren't complete: they don't do what I
describe above, removing the persistent-net rules files and rule-writing
scripts.  None of that would be necessary anymore with this setup.)

>> It's possible that $IFACE doesn't mean what I think it means, but
>> if so, I think this should continue to work if a system still has
>> ifconfig.ethX config files (they get "dereferenced" to ethX
>> directly if /sys/class/net/eth* exists).
>> 
>> People who know the service file interface better than I do --
>> help? :-)
> 
> When I rewrote the network scripts, I wanted to explicitly remove any
> link between the filename and the network device.

OK, I guess I don't see why that's important, but I don't have a
terribly complicated network setup either, so maybe I'm not the best
judge of that.  Not a huge deal.

> For instance a filename of ifconfig.world and ifconfig.internal would
> work fine.

Well, if you want to refer to two NICs as world and internal, then a
couple runs of "renameif" (or whatever the tool is that sends a
SIOCSIFNAME ioctl to a socket FD) would work as well.  Or a couple of
appropriate udev rules.  :-)

But I'm not *that* opposed to adding back IFNAME; it just seemed a bit
redundant.  So that's back, in v2 (attached).

> Adding a device to a bridge device like br0 created a lot more 
> complications, but by the time that happens, the admin should know
> what devices he has.

Yes, on one level: the admin knows what hardware is present, how each
piece of hardware connects to its given network, and therefore how to
configure each piece (or collection of pieces) of hardware.

But the admin can't know how those pieces of hardware map to eth* names
in the kernel, at least not reliably.  Not all NICs are discovered in a
predictable order by the kernel.  USB prevents that, for one, and there
are probably other buses that don't work very well either.  PCI may or
may not be guaranteed to always enumerate consistently; it does tend to
in practice, but I don't know if that's a guarantee, or just what almost
every motherboard does.

So we need to do something to let the config map to the hardware.  So
far, we've used Debian's support for assigning fixed-for-all-time
interface names, but this requires renaming interfaces.  And for the
last couple years, upstream udev has not liked doing that; it's full of
hacks to try to work around namespace collisions, the code to do it for
device node files has been gone for a *long* time (the answer there is
"add symlinks", though of course that won't work for NICs), etc.
They've also removed the rules and scripts from systemd entirely, of
course (not that I agree that was a good thing, but I can't change their
minds).

And then, of course, the most recent udev releases broke it by not
actually running IMPORT{program} rule expressions in test mode anymore.

But that's not the only way to accomplish the mapping.  We could do
something closer to the symlink route, where instead of an FS-based
symlink, we use a bootscript function (or maybe better, external shell
script?  that way the admin can use it as well) to indirect through the
mapping, just like the /dev/disk/by-{path,id}/* links do for disks.  The
only extra bit of complexity there is the tool to do the mapping.

(I've also moved it to a new script in this version.  A potential future
improvement: make the script look at flags and be able to dump out the
full mapping, with all NICs, MACs, and paths, for use after plugging in
a new NIC, before configuration.)

> I don't see that as a requirement for setting the persistent net
> rules before the first boot.

Well, see above.  Setting up the rules before the first boot is probably
only needed for remote machines, I suspect, but if we can get rid of it
entirely (and I think we can), why not?  :-)

I'm also trying to avoid perpetually fixing the immediate problem.  If
we get away from the config-file-based mapping entirely, then it no
longer matters what upstream does, as long as the IMPORTs still run at
runtime, and the udev db remains queryable.

> I'm generally in favor of keeping things as simple as possible.
> Adding a level of indirection is not simple.

Agreed, but I think it's a *lot* simpler than what the existing config
is doing: writing temporary rules files to /etc or /run, copying them to
/etc after the rootfs is mounted read-write (if they got put in /run),
re-reading the rules files every time they change, and going through
*crazy* contortions inside udevd to get the rename to happen correctly,
while still mishandling a bunch of cases.  (E.g. broken rules that map
multiple pieces of hardware to the same name will choose one at random
each boot, and likely hang the boot for a long time while the udev
helper binary hangs around handling the other device, before timing
out.)

Instead, this stores away the required info as devices are discovered,
and asks for it as needed when trying to configure those devices later.

> Would you please explain the scenario where you think this
> indirection would be useful?

Most of it's above.  It's for the same reason you shouldn't ever put
/dev/sdXY in your fstab; it's not guaranteed to stay the same device.
The first time you boot with a USB network device plugged in, the
ordering will change.

But additionally, with our existing setup, it's impossible to replace a
network card without manually reconfiguring the network stuff (since the
write_net_rules script will never re-use an interface name, and the new
card will have a different MAC).  With this, if the admin uses the
device path instead of the MAC address, everything continues to work
after the reboot.  (Of course you can't move a NIC between slots, so
it's not perfect.)

(Also I sort of like the idea of being able to do "ip addr show dev
$(find-nic mac-xx:xx:xx:xx:xx:xx)" at runtime.  It'd be nicer if
IFNAMSIZ was not hardcoded to 16 (forcing all names to be <16 bytes
long), since then we could just use those names directly, and create
aliases instead of FS symlinks.  But there's no fixing the length limit
now, unfortunately.)
Index: udev-config/55-lfs.rules
===================================================================
--- udev-config/55-lfs.rules    (revision 9920)
+++ udev-config/55-lfs.rules    (working copy)
@@ -12,3 +12,8 @@
 KERNEL=="isdn[0-9]*",       GROUP="dialout"
 KERNEL=="isdnctrl[0-9]*",   GROUP="dialout"
 KERNEL=="dcbri[0-9]*",      GROUP="dialout"
+
+# This causes device path and address information to be stored in the udev
+# database for network cards, for use by the bootscripts
+SUBSYSTEM=="net", IMPORT{builtin}="path_id"
+SUBSYSTEM=="net", ENV{ID_ADDRESS}="$attr{address}"
Index: bootscripts/lfs/lib/services/init-functions
===================================================================
--- bootscripts/lfs/sbin/find-nic       (revision 0)
+++ bootscripts/lfs/sbin/find-nic       (revision 0)
@@ -0,0 +1,53 @@
+#!/bin/sh
+
+################################################################################
+# find-nic                                                                     
#
+# Usage: find-nic [ mac-{address} | path-{path_id path} ]                      
#
+#                                                                              
#
+# Purpose: Find the "real" network device name whose MAC or path is given.     
#
+#          Used to map persistent identifiers to the real device so that       
#
+#          configuration can be stable while physical devices move around.     
#
+#          Prints the real device name to stdout, or prints nothing if none.   
#
+#                                                                              
#
+# Inputs: Accepts a single string value in the form mac-XX:XX:XX:XX:XX:XX or   
#
+#         path-XXXXXXXXXX (matching udev's ID_PATH environment key)            
#
+#                                                                              
#
+# Exit status:                                                                 
#
+#       0 - Found a matching physical device; prints it                        
#
+#       1 - No matching physical device found; nothing printed                 
#
+#       2 - Don't know how to map the given string to a physical device        
#
+################################################################################
+
+# Accept real interfaces as well as identifiers
+if [ -e /sys/class/net/"${1}" ] ; then
+  echo "${1}"
+  exit 0
+fi
+
+real_device=""
+id="${1#*-}"
+
+case "$1" in
+  mac-*)
+    for dev in /sys/class/net/* ; do
+      if /sbin/udevadm info -q env -p "$dev" | grep -q "ID_ADDRESS=${id}\$" ; 
then
+        echo "${dev##*/}"
+        exit 0
+      fi
+    done
+    exit 1
+    ;;
+  path-*)
+    for dev in /sys/class/net/* ; do
+      if /sbin/udevadm info -q env -p "$dev" | grep -q "ID_PATH=${id}\$" ; then
+        echo "${dev##*/}"
+        exit 0
+      fi
+    done
+    exit 1
+    ;;
+  *)
+    echo "Don't know how to dereference $1." >&2
+    exit 2
+    ;;
+esac
Index: bootscripts/lfs/sbin/ifup
===================================================================
--- bootscripts/lfs/sbin/ifup   (revision 9920)
+++ bootscripts/lfs/sbin/ifup   (working copy)
@@ -81,11 +81,24 @@
 
 . $file
 
-if [ "$IFACE" = "" ]; then
-   log_failure_msg2 "${file} does not define an interface [IFACE]."
+if ! real_device=$(find-nic "$IFACE") ; then
+   log_failure_msg "${IFACE} could not be found."
    exit 1
 fi
 
+IFACE="${real_device}"
+
+real_components=""
+for identifier in ${INTERFACE_COMPONENTS} ; do
+   if ! real_device=$(find-nic "${identifier}") ; then
+     log_failure_msg "${identifier} (component ID for ${1}) could not be 
found."
+     exit 1
+   fi
+   real_components="${real_components} ${real_device}"
+done
+
+INTERFACE_COMPONENTS="${real_components}"
+
 # Do not process this service if started by boot, and ONBOOT
 # is not set to yes
 if [ "${IN_BOOT}" = "1" -a "${ONBOOT}" != "yes" ]; then
Index: bootscripts/lfs/sbin/ifdown
===================================================================
--- bootscripts/lfs/sbin/ifdown (revision 9920)
+++ bootscripts/lfs/sbin/ifdown (working copy)
@@ -62,11 +62,24 @@
 
 . ${file}
 
-if [ "$IFACE" = "" ]; then
-   log_failure_msg "${file} does not define an interface [IFACE]."
+if ! real_device=$(find-nic "$IFACE") ; then
+   log_failure_msg "${IFACE} could not be found."
    exit 1
 fi
 
+IFACE="${real_device}"
+
+real_components=""
+for identifier in ${INTERFACE_COMPONENTS} ; do
+   if ! real_device=$(find-nic "${identifier}") ; then
+     log_failure_msg "${identifier} (component ID for ${1}) could not be 
found."
+     exit 1
+   fi
+   real_components="${real_components} ${real_device}"
+done
+
+INTERFACE_COMPONENTS="${real_components}"
+
 # We only need to first service to bring down the interface
 S=`echo ${SERVICE} | cut -f1 -d" "`
 
Index: bootscripts/lfs/sbin/ifup.8
===================================================================
--- bootscripts/lfs/sbin/ifup.8 (revision 9920)
+++ bootscripts/lfs/sbin/ifup.8 (working copy)
@@ -41,6 +41,29 @@
                 PREFIX=24
                 BROADCAST=192.168.1.255
 
+       ifup firstif
+              Bring up the interface defined in the file
+              /etc/sysconfig/ifconfig.firstif, and handle its
+              interface name changing from one ifup run to the
+              next by asking udev to look up the MAC address.
+
+                ONBOOT=no
+                IFACE=mac-XX:XX:XX:XX:XX:XX
+                SERVICE=ipv4-static
+                IP=192.168.1.22
+                GATEWAY=192.168.1.1
+                PREFIX=24
+                BROADCAST=192.168.1.255
+
+       ifup secondif
+              Same as above, but find the real interface name
+              by looking at the udev ID_PATH value instead of
+              the interface's MAC address.
+
+                ONBOOT=no
+                IFACE=path-pci-0000:00:13.1-usb-0:2.1:1.1
+                <...>
+
        ifdown eth0:2
               Bring down the interface defined in the file
               /etc/sysconfig/ifconfig.eth0:2
@@ -79,6 +95,12 @@
        ly.  It runs scripts defined by the SERVICE variable in 
        the network configuration file.
 
+       The program will handle network devices moving around from
+       run to run, if IFACE is a mac-* or path-* persistent
+       identifier rather than an interface name.  These persistent
+       identifiers are dereferenced each time ifup or ifdown runs,
+       by querying the udev database.
+
        The configuration files must have the following environ-
        ment variables set:
 
@@ -104,7 +123,10 @@
        INTERFACE_COMPONENTS - A list of component interfaces
                  only needed for a compound device such as a bridge.  
                  This list is normally a single value, e.g. eth0, 
-                 for use with a virtual host such as kvm.
+                 for use with a virtual host such as kvm.  The
+                 entries in this list may be either interface names
+                 or persistent identifiers; the latter are
+                 dereferenced at runtime as needed.
 
        Other paramters that are service specific include:
 
Index: bootscripts/Makefile
===================================================================
--- bootscripts/Makefile        (revision 9920)
+++ bootscripts/Makefile        (working copy)
@@ -50,6 +50,7 @@
        install -m ${MODE} lfs/init.d/udev_retry    ${EXTDIR}/rc.d/init.d/
        install -m ${MODE} lfs/sbin/ifup            ${SBIN}
        install -m ${MODE} lfs/sbin/ifdown          ${SBIN}
+       install -m ${MODE} lfs/sbin/find-nic        ${SBIN}
        install -m ${MODE} lfs/sbin/ifup.8          ${MAN8}
        ln -sf  ifup.8                              ${MAN8}/ifdown.8
        install -m ${MODE} lfs/lib/services/ipv4-static-route  ${LIBDIR}
@@ -126,8 +127,8 @@
 
 uninstall:
        rm -rf ${DESTDIR}/lib/services ${DESTDIR}/lib/lsb ${EXTDIR}/rc.d 
${EXTDIR}/init.d \
-               ${SBIN}/ifup ${SBIN}/ifdown ${MAN8}/ifup.8 ${MAN8}/ifdown.8 \
-               ${EXTDIR}/sysconfig/rc 
+               ${SBIN}/ifup ${SBIN}/ifdown ${SBIN}/find-nic ${MAN8}/ifup.8 \
+               ${MAN8}/ifdown.8 \ ${EXTDIR}/sysconfig/rc 
 
 .PHONY: all create-dirs install files links rcS rc0 rc1 rc2 rc3 rc4 rc5 rc6 
uninstall
 

Attachment: signature.asc
Description: OpenPGP digital signature

-- 
http://linuxfromscratch.org/mailman/listinfo/lfs-dev
FAQ: http://www.linuxfromscratch.org/faq/
Unsubscribe: See the above information page

Reply via email to