/wicked

Framework for network configuration

Primary LanguageCGNU General Public License v2.0GPL-2.0

Presenting wicked network configuration
=======================================

This tool and library provides a new framework for network
configuration.

One of the bigger problems with network interface management today,
and with the ifup scripts in general, is that different layers of
network management get jumbled together into one single script,
or at most two different scripts, that interact with each other in a
not-really-well-defined way, with side effects that are difficult to
be aware of, obscure constraints and conventions, etc.  Several layers
of special hacks for a variety of different scenarios cover them like
barnacles.  Address configuration protocols are being used that are
implemented via daemons like dhcpcd, which interact rather poorly with
the rest of the infrastructure. Funky interface naming schemes that
require heavy udev support are introduced to achieve persistent
identification of interfaces.

In other words, a maintenance nightmare.

The idea of wicked is to decompose the problem in several ways. None
of them is entirely novel, but trying to put ideas from different
other projects together is hopefully going to create a better solution
overall.

One approach is to use a client/server model. This allows wicked to define
standardized facilities for things like address configuration that
are well integrated with the overall framework. For instance, with
address configuration, the admin may request that an interface should
be configured via dhcp or ipv4 zeroconf, and all the respective
addrconf service does is obtain the lease from its server, and pass it
on to the wicked server process, which installs the requested addresses
and routes.

The other approach to decomposing the problem is to enforce the layering
aspect. For any type of network interface, it is possible to define
a dbus service that configures the network interface's device layer -
be it a vlan, a bridge, a bond, or an paravirtualized NIC. Common
functionality, such as address configuration, is implemented by joint
services that are layered on top of these device specific services,
without having to implement them specifically.

The wicked framework implements these two aspects by using a variety
of dbus services, which get attached to a network interface depending
on its type.

To illustrate this point, here's a rough overview of the current
object hierarchy in wicked.

Each network interface is represented via a child object of
/org/opensuse/Network/Interfaces. The name of the child object is given
by its ifindex, so e.g. the loopback interface, which usually gets
ifindex 1, is /org/opensuse/Network/Interfaces/1, the first ethernet
interface registered is /org/opensuse/Network/Interfaces/2, etc.

Each network interface has a "class" associated with it, which is
used to select the dbus interfaces it supports. By default, each
network interface is of class "netif", and wickedd will automatically
attach all interfaces compatible with this class. In the current
implementation, this includes the following interfaces

org.opensuse.Network.Interface
        Generic network interface functions, such as taking the link
        up or down, assigning an MTU, etc.

org.opensuse.Network.Addrconf.ipv4.dhcp
org.opensuse.Network.Addrconf.ipv6.dhcp
org.opensuse.Network.Addrconf.ipv4.auto
org.opensuse.Network.Addrconf.ipv6.auto
        Address configuration services for DHCP, ipv6 autoconf, ipv4
        zeroconf, etc.

Beyond this, network interfaces may require/offer special configuration
mechanisms. For instance, for an Ethernet device, you may want to be
able to control the link speed, offloading of checksumming, etc. To
achieve this, ethernet devices have a class of their own, called
netif-ethernet, which is a subclass of netif. As a consequence, the dbus
interfaces assigned to an ethernet interface include all the services
listed above, plus org.opensuse.Network.Ethernet, which is a service
available only to objects belonging to the netif-ethernet class.

Similarly, there exist classes for interface types like bridges, vlans,
bonds, or infiniband.

Obviously, this begs the question, how do you interact with an interface
that needs to be created first - such as a VLAN, which is really a
virtual network interface that sits on top of an ethernet device.

For these, wicked defines factory interfaces, such as
org.opensuse.Network.VLAN.Factory. Such a factory interface offers a
single function that lets you create an interface of the requested type.
These factory interfaces are attached to the
/org/opensuse/Network/Interfaces list node.

Frequently Asked Questions
==========================

We have a FAQ section hosted in our GitHub's wiki, be sure to check that
out for common questions about usage or Wicked in general:

        https://github.com/openSUSE/wicked/wiki/FAQ

For any questions not answered on the FAQ, please read our section
below: "Where to discuss or report bugs"

What's currently supported
==========================

wicked currently supports

 -	configuration file backends to parse SUSE style
	/etc/sysconfig/network files.

 -	an internal configuration backend to represent network
	interface configuration in XML. The syntax evolved out
	of what netcf uses.

 -	bring-up and shutdown of "normal" network interfaces
	such as Ethernet, Infiniband etc, as well as VLAN,
	bridges, bonds, tun, tap, dummy, macvlan, macvtap, hsi,
	qeth, iucv and wireless (currently limited to one
	wpa-psk/eap network) devices.

 -	A built-in DHCPv4 client
 -	A built-in DHCPv6 client

 -	The nanny daemon (if enabled) helps to automatically
	bring up configured interfaces as soon as the device
	is available (interface hotplugging) and set up IP
	configuration when a link (carrier) is detected.


Where to get the sources/binaries
=================================

The git source repository is hosted at:

	https://github.com/openSUSE/wicked

Binary packages are build in the openSUSE build service in
the network:wicked project tree and can be found via:

	http://software.opensuse.org/package/wicked

The actual git master is built in the network:wicked:master
project automatically.

To build wicked from sources, try following commands:

	zypper in git-core rpm-build gcc make pkg-config \
		autoconf automake libtool systemd-devel \
		libnl3-devel dbus-1-devel libgcrypt-devel
	git clone https://github.com/openSUSE/wicked.git
	cd wicked
	./autogen.sh
	make rpmbuild

and then install the RPMs.


Where to discuss or report bugs
===============================

Please take a look at:

	http://bugs.opensuse.org

where you can find links to bugzilla and user forums.

There are currently two mailing lists:

	wicked-devel@opensuse.org

for discussions about development and

	wicked-commit@opensuse.org

to monitor git repository commits.

GitHub offers also an issue tracker, where you can discuss pull
requests and report git master issues, which are not yet in
openSUSE:Factory or any repository for released products.


What you can do
===============

Enable wicked using:

        systemctl enable --force wicked

This enables the wicked services, creates the
	network.service -> wicked.service
alias link and causes to start the network at the next boot.

To manually start the server process (again, as root), use:

        systemctl start wickedd.service

which starts wickedd (main server) and associated supplicants:

	/usr/lib/wicked/bin/wickedd-auto4 --systemd --foreground
	/usr/lib/wicked/bin/wickedd-dhcp4 --systemd --foreground
	/usr/lib/wicked/bin/wickedd-dhcp6 --systemd --foreground
	/usr/sbin/wickedd --systemd --foreground
	/usr/sbin/wickedd-nanny --systemd --foreground

You may then bring up the network using:

        systemctl start wicked.service

also using the network.service alias:

        systemctl start network.service

These commands are using default/system configuration sources as
defined in the /etc/wicked/client.xml file.

To enable debugging, you can currently set the WICKED_DEBUG variable
in /etc/sysconfig/network/config file, e.g. WICKED_DEBUG="all" or
to omit some, WICKED_DEBUG="all,-dbus,-objectmodel,-xpath,-xml"
before the wickedd service is started.


Showing interface status
========================

You can use the client utility to display interface information (xml):

        wicked show-xml all
        wicked show-xml <ifname>


Bringing up one interface
=========================

You can set up single interfaces, too. The easiest way is to call:

        wicked ifup eth0
        wicked ifup wlan0
        ...

since there is no configuration source specified, wicked client checks
its default sources of configuration defined in /etc/wicked/client.xml
that is:

        1) firmware:    ibft firmware
        2) compat:      ifcfg files - implemented for compatibility

whatever it gets from those sources for a given interface is applied.
The intended order of importance is firmware > compat. But this may be
changed in the future.

Please refer to the wicked(8) manpage for details.


Bringing up multiple interfaces
===============================

For bonds and bridges, it may make sense to define the entire device
topology in one file (ifcfg-bondX), and bring it up in one go.

For these, you simply define the device topology in one file, and tell
wicked to bring up the whole configuration by specifying the top level
interface names (of the bridge or bond):

	wicked ifup br0

which automatically sets up the bridge and its dependencies in the
appropriate order without a need to list the dependencies (ports, ...)
separately.

You can also bring up multiple interfaces in one call:

	wicked ifup bond0 br0 br1 br2

or also all interfaces:

	wicked ifup all

As an example, take a look at samples/suse/host5/ directory.
This configuration defines an Ethernet Bridge (ifcfg-bridge42)
with a Dummy port (ifcfg-dummy42).

Assuming you copy the files to standard ifcfg config directory
(that is to /etc/sysconfig/network/), simply call:

	wicked ifup bridge42

and the client will create and bring up the dummy42 first, create
the bridge and add the dummy interface as a port to the bridge.


For testing purposes, you can even use the --ifconfig parameter:

	wicked ifup --ifconfig compat:samples/suse/host5 bridge42

which will bring up the bridge using the config files directly
from the sample directory, but please note: --ifconfig parameter
list disables (overrides) the default configuration search path
and all following commands like "wicked ifstatus" have to use
the same --ifconfig parameter list.


Handling incremental changes
============================

With wicked, there is no need to actually take down an interface
to reconfigure it (unless it's required by the kernel). For instance,
in order to add another IP address or route to a statically configured
network interface, simply add it to the interface definition, and do
another "ifup" operation. The server will try hard to update only
those settings that changed. This applies to link-level options such as
the device mtu or the MAC address, as well as network level settings,
such as addresses, routes, or even address configuration mode (when
moving from a static configuration to, say, DHCP).

Things get tricky of course with virtual interfaces combining several
real devices, like bridges or bonds. For bonded devices, it's not
possible to change certain parameters while the device is up. Doing
that will result in an error.

However, what should still work, is the act of adding or removing the
child devices of a bond or bridge, or choosing a bond's primary interface.


Wicked extensions - address configuration
=========================================

It's not useful to require support for all interface types to be coded in
C. Languages like C are useful when you want to do slightly complex things,
but for many mundane tasks of system configuration, using shell scripts
is still the most natural thing to do.

For that reason, wicked is designed to be extensible via shell scripts.
These extensions can be defined in the config.xml file.

Currently, several diffent classes of extensions are supported:

 *      link configuration: these are scripts responsible for setting
        up a device's link layer according to the configuration
        provided by the client, and for tearing it down again.

 *      address configruation: these are scripts responsible for
        managing a device's address configuration.
        Usually address configuration and DHCP are managed by wicked
        itself, but can be implemented via extensions.

 *      firewall extension: these scripts can apply firewall rules

Typically, extensions have a start and a stop command, an optional
"pid file", and a set of environment variables that get passed to
the script.

To illustrate how this is supposed to work, let's look at how a
firewall extension is defined in etc/server.xml:

  <dbus-service interface="org.opensuse.Network.Firewall">
     <action name="firewallUp"   command="/etc/wicked/extensions/firewall up"/>
     <action name="firewallDown" command="/etc/wicked/extensions/firewall down"/>

     <!-- default environment for all calls to this extension script -->
     <putenv name="WICKED_OBJECT_PATH" value="$object-path"/>
     <putenv name="WICKED_INTERFACE_NAME" value="$property:name"/>
     <putenv name="WICKED_INTERFACE_INDEX" value="$property:index"/>
  </dbus-service>

The extension is attached to dbus-service interface and defines
commands to execute for the actions of this interface. Further,
the declaration can define and initialize environment variables
passed to the actions.

Wicked extensions - configuration files
=======================================

You can extend the handling of configuration files with scripts as well.
For example, DNS updates from leases are ultimately handled by the
extensions/resolver script, with behavior configured in server.xml:

        <system-updater name="resolver">
          <action name="backup" command="/etc/wicked/extensions/resolver backup"/>
          <action name="restore" command="/etc/wicked/extensions/resolver restore"/>
          <action name="install" command="/etc/wicked/extensions/resolver install"/>
          <action name="remove" command="/etc/wicked/extensions/resolver remove"/>
        </system-updater>

When an update arrives in wickedd, the system updater routines parse
the lease and call the appropriate commands (ie. backup, install, etc)
in the resolver script. This in turn configures the DNS settings
using /sbin/netconfig (if it exists on the system), or by manually writing
/etc/resolv.conf as a fallback.

Future wickedness
=================

In the future, it may be useful to extend what wicked supports beyond
the configuration of network interfaces itself.


A Note on the name
==================

Only after I started to show my code to a bunch of people, I found out that
there's a project called WICD, which aims to provide... a network connection
manager :-)

To make this absolutely plain, wicked is in no way related to WICD, for good
or bad. It's just coincidence.