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

Time to rethink ifupdown

Greetings to everybody on this list, it's my first post here.

ifupdown, the official Debian network configuration tool, is great for configuring interfaces like Ethernet adapters. However, as time goes, more and more use cases occur which are hard to fulfill with ifupdown as it is. My guess is that it's time to rethink the philosophy behind ifupdown and give it some natural development.

First, I'll summarize the problems with the current ifupdown (use cases not covered).

1. When we run ifup, we express our intention to bring an interface up. In many cases, the fact that we wish the interface to come up is not enough. The interface can actually come or not come up, and significant amount of time can have passed between the user ordering the interface to come up and the interface actually starting working. A typical example is dial-on-demand, where the phone number can be redialled several times before actual connection. This is currently handled by either blocking ifup for an indefinite amount of time (bad: blocks handling of other interfaces with ifup -a, causes conflicts with other instances of ifup upon the ifstate file) or by forking off a process which tries to connect. The disadvantage of the latter approach is that ifup immediately considers the interface as being up, runs the up scripts and updates ifstate. Running the up scripts before their time has many negative consequences, such as putting unreachable DNS addresses into /etc/resolv.conf using resolvconf, setting up unusable routes etc.

2. While the interface is up from the ifupdown POV, it can periodically go down and up again because of network problems (a common example is pppd's automatic redialling). In these cases, the down and up scripts are not executed though they should (see above about routes, resolv.conf etc).

3. If the interface really dies and there is no way to revive it (e.g. an USB device has been physically disconnected), and the daemon like pppd exists even though it's been told to "auto-reconnect", ifupdown will never know, so the interface state will remain inconsistent [http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=263749].

4. There is a number of "supervisor" daemons which monitor the media for the ability to connect, and try to connect when it's possible. An example is ifplugd which monitors for Ethernet link state. These are usually configured so as to control ifup/ifdown, but actually they need to be controlled from ifup/ifdown themselves: ifup should start the daemon for a device, and ifdown should stop it. This has the advantage of passing the information from /etc/network/interfaces to the daemon and not having to duplicate it elsewhere. This is especially the case for wpasupplicant.

5. Though ifupdown has a notion of "mappers" to resolve physical interfaces into their logical avatars, a mapper is required to be synchronous: it's supposed to give an answer and finish quickly. Acually, there are cases when the answer is not known at the time of expressing the intention to bring the interface up by running ifup. Sometimes, it's possible to find out the logical interface only when the interface actually goes up. This is the case with waproamd and wpasupplicant which monitor the media in hope of finding a usable WiFi network -- you can't know in advance which network it will be.

Having summarized the conceptual problems of the current ifupdown, I'll describe my vision of what it should look like.

In the /etc/network/interfaces file, there is a new method "tristate" (a better name is welcome) similar to "manual". The difference is that the post-up commands are not run automatically after the up commands (ifup just exits after running the up commands). The up commands are supposed to start a background process whose responsibility is to invoke a callback by running "ifup --notify $IFACE". This finalizes the transition and makes ifup run post-up commands and mark the interface as completely up. Between the user-initiated ifup invocation and this callback, the interface is thought to be "half-up", i.e. indeterminate.

If the connection happens to disappear while the interface is up from the ifupdown POV, it's the responsibility of the background process to run "ifdown --notify $IFACE". This marks the interface as "half-up" again and executes the pre-down commands.

Running ifdown executes the down, then post-down commands. It's the responsibility of background process to run "ifdown --notify $IFACE" (if the link was active), then die. The user-invoked ifdown doesn't run the pre-down commands.

"ifup --notify" and "ifdown --notify" should be idempotent, i.e. "ifup --notify" should not run the post-up commands if the interface is already marked as "full-up".

The built-in methods involving external commands should be reformulated this way. This means that at least pon/poff should be given options to invoke the callbacks on connection/disconnection. "ifup --notify" should accept extra parameters like "param=value" which are passed to post-up scripts as "IF_PARAM=value" environment variables. This will allow, e.g., pppd to provide autoconfigured settings like DNS address to the post-up scripts.

The /etc/network/interfaces file, in addition to ifaces and mappings, allows a new type of stanza: supervisor. The syntax is simple: a headline "supervisor <NAME>" with regular lines like pre-up, up, post-up, pre-down, down, post-down. A supervisor is considered a physical interface in the sense that you can do ifup/ifdown upon it, and that it can correspond to a logical interface at a given moment. However, the connection between a supervisor and a logical interface is not static (as in case of a mapping) but dynamic. A supervisor starts "disconnected" (not associated with a logical interface) -- this is the same as "half-up" for "tristate" interfaces. Here is an example:

supervisor wlan0
    up waproamd -M -i $IFACE    # Start up a waproamd instance
    down waproamd -k -i $IFACE  # Kill a running waproamd
    # We assume that waproamd is configured to run proper callbacks

iface wlan0-home inet dhcp
    wireless-essid "HomeNet"

iface wlan0-office inet static
    wireless-essid "OfficeNet"

The daemon is expected to run the following callbacks: "ifup --notify $IFACE=$LOGICAL" to associate the supervisor with a logical interface, and "ifdown --notify $IFACE" to set the supervisor back into the "disconnected" state. The former first runs the explicit ("up") or built-in (like running ifconfig) up actions on the logical interface, then post-up on the logical interface, then post-up on the supervisor. The latter runs pre-down on the supervisor, then pre-up on the logical interface, then the explicit or built-in actions on the logical interface. The pre-up or post-down actions on the logical interface are never run. When running post-up and pre-down actions on the supervisor, the $LOGICAL variable should be available.

The details need to be worked out, of course. For now, I'd love to hear your opinion on the idea in general. If the general direction of ifupdown development is accepted, I can offer my help in both detailed design and implementation.

Alexey Feldgendler <alexey@feldgendler.ru>
[ICQ: 115226275] http://feldgendler.livejournal.com

Reply to: