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.