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
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
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
"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
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:
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
iface wlan0-office inet static
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
Alexey Feldgendler <email@example.com>
[ICQ: 115226275] http://feldgendler.livejournal.com