[systemd-commits] 8 commits - Makefile.am src/libsystemd-network src/network

Tom Gundersen tomegun at kemper.freedesktop.org
Mon Jul 14 07:53:56 PDT 2014


 Makefile.am                              |   29 +
 src/libsystemd-network/sd-dhcp-server.c  |    2 
 src/libsystemd-network/sd-dhcp6-client.c |    2 
 src/network/networkd-bond.c              |  163 --------
 src/network/networkd-dummy.c             |  122 ------
 src/network/networkd-link.c              |   44 +-
 src/network/networkd-macvlan.c           |  160 --------
 src/network/networkd-manager.c           |    1 
 src/network/networkd-netdev-bond.c       |  129 +++++++
 src/network/networkd-netdev-bond.h       |   43 ++
 src/network/networkd-netdev-bridge.c     |   84 ++++
 src/network/networkd-netdev-bridge.h     |   26 +
 src/network/networkd-netdev-dummy.c      |   85 ++++
 src/network/networkd-netdev-dummy.h      |   26 +
 src/network/networkd-netdev-gperf.gperf  |    5 
 src/network/networkd-netdev-macvlan.c    |  130 +++++++
 src/network/networkd-netdev-macvlan.h    |   40 ++
 src/network/networkd-netdev-tunnel.c     |  536 +++++++++++++++++++++++++++++
 src/network/networkd-netdev-tunnel.h     |   29 +
 src/network/networkd-netdev-tuntap.c     |  162 ++++++++
 src/network/networkd-netdev-tuntap.h     |   27 +
 src/network/networkd-netdev-veth.c       |  143 +++++++
 src/network/networkd-netdev-veth.h       |   26 +
 src/network/networkd-netdev-vlan.c       |  133 +++++++
 src/network/networkd-netdev-vlan.h       |   28 +
 src/network/networkd-netdev-vxlan.c      |  142 +++++++
 src/network/networkd-netdev-vxlan.h      |   28 +
 src/network/networkd-netdev.c            |  303 ++++++----------
 src/network/networkd-netdev.h            |  170 +++++++++
 src/network/networkd-network.c           |    1 
 src/network/networkd-tunnel.c            |  569 -------------------------------
 src/network/networkd-tuntap.c            |  155 --------
 src/network/networkd-veth.c              |  154 --------
 src/network/networkd-vlan.c              |  149 --------
 src/network/networkd-vxlan.c             |  165 --------
 src/network/networkd.h                   |  160 --------
 src/network/test-network.c               |   17 
 37 files changed, 2164 insertions(+), 2024 deletions(-)

New commits:
commit 679b3605f0ea52ee56ae76e57dfd17bcfef5b122
Author: Tom Gundersen <teg at jklm.no>
Date:   Sun Jul 13 01:11:52 2014 +0200

    networkd: link - fix memory leak
    
    Make link_initialized() idempotent to avoid taking refs on several udev_device
    objects.

diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index 0947b0c..877b7a9 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -2122,6 +2122,9 @@ int link_initialized(Link *link, struct udev_device *device) {
         if (link->state != LINK_STATE_INITIALIZING)
                 return 0;
 
+        if (link->udev_device)
+                return 0;
+
         log_debug_link(link, "udev initialized link");
 
         link->udev_device = udev_device_ref(device);

commit 5347925a59530bd4e6616eb8c8d43a02c3e14c46
Author: Tom Gundersen <teg at jklm.no>
Date:   Sat Jul 12 23:15:17 2014 +0200

    test: network - skip if we don't have permissions to create netdevs

diff --git a/src/network/test-network.c b/src/network/test-network.c
index 75e70fa..08b37b1 100644
--- a/src/network/test-network.c
+++ b/src/network/test-network.c
@@ -111,15 +111,23 @@ static void test_deserialize_dhcp_routes(void) {
         }
 }
 
-static void test_load_config(Manager *manager) {
+static int test_load_config(Manager *manager) {
+        int r;
 /*  TODO: should_reload, is false if the config dirs do not exist, so
  *        so we can't do this test here, move it to a test for paths_check_timestamps
  *        directly
  *
  *        assert_se(network_should_reload(manager) == true);
 */
-        assert_se(manager_load_config(manager) >= 0);
+
+        r = manager_load_config(manager);
+        if (r == -EPERM)
+                return r;
+        assert_se(r >= 0);
+
         assert_se(manager_should_reload(manager) == false);
+
+        return 0;
 }
 
 static void test_network_get(Manager *manager, struct udev_device *loopback) {
@@ -181,6 +189,7 @@ int main(void) {
         _cleanup_manager_free_ Manager *manager = NULL;
         struct udev *udev;
         struct udev_device *loopback;
+        int r;
 
         test_deserialize_in_addr();
         test_deserialize_dhcp_routes();
@@ -188,7 +197,9 @@ int main(void) {
 
         assert_se(manager_new(&manager) >= 0);
 
-        test_load_config(manager);
+        r = test_load_config(manager);
+        if (r == -EPERM)
+                return EXIT_TEST_SKIP;
 
         udev = udev_new();
         assert_se(udev);

commit 1231c4d238844e77018caf5b5852f01d96373c47
Author: Tom Gundersen <teg at jklm.no>
Date:   Sat Jul 12 23:07:33 2014 +0200

    sd-dhcp-server: make gcc happy
    
    It complains about optoffset possibly being uninitialized. It is wrong,
    but let's just initialize it.

diff --git a/src/libsystemd-network/sd-dhcp-server.c b/src/libsystemd-network/sd-dhcp-server.c
index 5c32fdf..53cf0d7 100644
--- a/src/libsystemd-network/sd-dhcp-server.c
+++ b/src/libsystemd-network/sd-dhcp-server.c
@@ -362,7 +362,7 @@ int dhcp_server_send_packet(sd_dhcp_server *server,
 static int server_message_init(sd_dhcp_server *server, DHCPPacket **ret,
                                uint8_t type, size_t *_optoffset, DHCPRequest *req) {
         _cleanup_free_ DHCPPacket *packet = NULL;
-        size_t optoffset;
+        size_t optoffset = 0;
         int r;
 
         assert(server);

commit 4b4923e65423e60d755841b5b264730e8f3deab3
Author: Tom Gundersen <teg at jklm.no>
Date:   Sat Jul 12 23:07:33 2014 +0200

    sd-dhcp6-client: make gcc happy
    
    It complains about {max,init}_retransmit_time possibly being
    uninitialized. It is wrong, but let's just initialize it.

diff --git a/src/libsystemd-network/sd-dhcp6-client.c b/src/libsystemd-network/sd-dhcp6-client.c
index a83778e..4f60578 100644
--- a/src/libsystemd-network/sd-dhcp6-client.c
+++ b/src/libsystemd-network/sd-dhcp6-client.c
@@ -387,7 +387,7 @@ static int client_timeout_resend(sd_event_source *s, uint64_t usec,
                                  void *userdata) {
         int r = 0;
         sd_dhcp6_client *client = userdata;
-        usec_t time_now, init_retransmit_time, max_retransmit_time;
+        usec_t time_now, init_retransmit_time = 0, max_retransmit_time = 0;
         usec_t max_retransmit_duration = 0;
         uint8_t max_retransmit_count = 0;
         char time_string[FORMAT_TIMESPAN_MAX];

commit 3be1d7e0c5bf60658d34eb6311d4e77c6803578c
Author: Tom Gundersen <teg at jklm.no>
Date:   Sun Jul 6 14:07:34 2014 +0200

    networkd: netdev - introduce vtable for netdev kinds
    
    Split each netdev kind into its own .h/.c.

diff --git a/Makefile.am b/Makefile.am
index 420d514..fef6d24 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -4590,17 +4590,27 @@ libsystemd_networkd_core_la_CFLAGS = \
 libsystemd_networkd_core_la_SOURCES = \
 	src/libsystemd-network/network-internal.h \
 	src/network/networkd.h \
-	src/network/networkd-link.c \
+	src/network/networkd-netdev.h \
+	src/network/networkd-netdev-tunnel.h \
+	src/network/networkd-netdev-veth.h \
+	src/network/networkd-netdev-vxlan.h \
+	src/network/networkd-netdev-vlan.h \
+	src/network/networkd-netdev-macvlan.h \
+	src/network/networkd-netdev-dummy.h \
+	src/network/networkd-netdev-tuntap.h \
+	src/network/networkd-netdev-bond.h \
+	src/network/networkd-netdev-bridge.h \
 	src/network/networkd-netdev.c \
-	src/network/networkd-tunnel.c \
-	src/network/networkd-veth.c \
-	src/network/networkd-vxlan.c \
-	src/network/networkd-vlan.c \
-	src/network/networkd-macvlan.c \
-	src/network/networkd-dummy.c \
-	src/network/networkd-tuntap.c \
-	src/network/networkd-bond.c \
-	src/network/networkd-bridge.c \
+	src/network/networkd-netdev-tunnel.c \
+	src/network/networkd-netdev-veth.c \
+	src/network/networkd-netdev-vxlan.c \
+	src/network/networkd-netdev-vlan.c \
+	src/network/networkd-netdev-macvlan.c \
+	src/network/networkd-netdev-dummy.c \
+	src/network/networkd-netdev-tuntap.c \
+	src/network/networkd-netdev-bond.c \
+	src/network/networkd-netdev-bridge.c \
+	src/network/networkd-link.c \
 	src/network/networkd-network.c \
 	src/network/networkd-address.c \
 	src/network/networkd-route.c \
diff --git a/src/network/networkd-bond.c b/src/network/networkd-bond.c
deleted file mode 100644
index 1e15677..0000000
--- a/src/network/networkd-bond.c
+++ /dev/null
@@ -1,163 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
-    This file is part of systemd.
-
-    Copyright 2014  Tom Gundersen <teg at jklm.no>
-    Copyright 2014  Susant Sahani
-
-    systemd is free software; you can redistribute it and/or modify it
-    under the terms of the GNU Lesser General Public License as published by
-    the Free Software Foundation; either version 2.1 of the License, or
-    (at your option) any later version.
-
-    systemd is distributed in the hope that it will be useful, but
-    WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-    Lesser General Public License for more details.
-
-    You should have received a copy of the GNU Lesser General Public License
-    along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <netinet/ether.h>
-#include <arpa/inet.h>
-#include <linux/if_bonding.h>
-
-#include "conf-parser.h"
-#include "sd-rtnl.h"
-#include "networkd.h"
-#include "missing.h"
-
-static const char* const bond_mode_table[_NETDEV_BOND_MODE_MAX] = {
-        [NETDEV_BOND_MODE_BALANCE_RR] = "balance-rr",
-        [NETDEV_BOND_MODE_ACTIVE_BACKUP] = "active-backup",
-        [NETDEV_BOND_MODE_BALANCE_XOR] = "balance-xor",
-        [NETDEV_BOND_MODE_BROADCAST] = "broadcast",
-        [NETDEV_BOND_MODE_802_3AD] = "802.3ad",
-        [NETDEV_BOND_MODE_BALANCE_TLB] = "balance-tlb",
-        [NETDEV_BOND_MODE_BALANCE_ALB] = "balance-alb",
-};
-
-DEFINE_STRING_TABLE_LOOKUP(bond_mode, BondMode);
-DEFINE_CONFIG_PARSE_ENUM(config_parse_bond_mode, bond_mode, BondMode, "Failed to parse bond mode");
-
-static uint8_t bond_mode_to_kernel(BondMode mode) {
-        switch (mode) {
-        case NETDEV_BOND_MODE_BALANCE_RR:
-                return BOND_MODE_ROUNDROBIN;
-        case NETDEV_BOND_MODE_ACTIVE_BACKUP:
-                return BOND_MODE_ACTIVEBACKUP;
-        case NETDEV_BOND_MODE_BALANCE_XOR:
-                return BOND_MODE_XOR;
-        case NETDEV_BOND_MODE_BROADCAST:
-                return BOND_MODE_BROADCAST;
-        case NETDEV_BOND_MODE_802_3AD:
-                return BOND_MODE_8023AD;
-        case NETDEV_BOND_MODE_BALANCE_TLB:
-                return BOND_MODE_TLB;
-        case NETDEV_BOND_MODE_BALANCE_ALB:
-                return BOND_MODE_ALB;
-        default:
-                return (uint8_t) -1;
-        }
-}
-
-static int netdev_fill_bond_rtnl_message(NetDev *netdev, sd_rtnl_message *m) {
-        int r;
-
-        assert(m);
-
-        r = sd_rtnl_message_append_string(m, IFLA_IFNAME, netdev->ifname);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not append IFLA_IFNAME, attribute: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        r = sd_rtnl_message_open_container(m, IFLA_LINKINFO);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not append IFLA_LINKINFO attribute: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        r = sd_rtnl_message_open_container_union(m, IFLA_INFO_DATA,
-                                                 netdev_kind_to_string(netdev->kind));
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not append IFLA_INFO_DATA attribute: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        if (netdev->bond_mode != _NETDEV_BOND_MODE_INVALID) {
-                r = sd_rtnl_message_append_u8(m, IFLA_BOND_MODE,
-                                              bond_mode_to_kernel(netdev->bond_mode));
-                if (r < 0) {
-                        log_error_netdev(netdev,
-                                         "Could not append IFLA_BOND_MODE attribute: %s",
-                                         strerror(-r));
-                        return r;
-                }
-        }
-
-        r = sd_rtnl_message_close_container(m);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not append IFLA_LINKINFO attribute: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        r = sd_rtnl_message_close_container(m);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not append IFLA_LINKINFO attribute: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        return r;
-}
-
-int netdev_create_bond(NetDev *netdev, sd_rtnl_message_handler_t callback) {
-        _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
-        int r;
-
-        assert(netdev);
-        assert(netdev->kind == NETDEV_KIND_BOND);
-        assert(netdev->ifname);
-        assert(netdev->manager);
-        assert(netdev->manager->rtnl);
-
-        r = sd_rtnl_message_new_link(netdev->manager->rtnl, &m, RTM_NEWLINK, 0);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not allocate RTM_NEWLINK message: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        r = netdev_fill_bond_rtnl_message(netdev, m);
-        if(r < 0)
-                return r;
-
-        r = sd_rtnl_call_async(netdev->manager->rtnl, m, callback, netdev, 0, NULL);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not send rtnetlink message: %s", strerror(-r));
-                return r;
-        }
-
-        netdev_ref(netdev);
-
-        log_debug_netdev(netdev, "Creating bond netdev: %s",
-                         netdev_kind_to_string(netdev->kind));
-
-        netdev->state = NETDEV_STATE_CREATING;
-
-        return 0;
-}
diff --git a/src/network/networkd-bridge.c b/src/network/networkd-bridge.c
deleted file mode 100644
index 4c106ee..0000000
--- a/src/network/networkd-bridge.c
+++ /dev/null
@@ -1,116 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
-    This file is part of systemd.
-
-    Copyright 2014  Tom Gundersen <teg at jklm.no>
-    Copyright 2014  Susant Sahani
-
-    systemd is free software; you can redistribute it and/or modify it
-    under the terms of the GNU Lesser General Public License as published by
-    the Free Software Foundation; either version 2.1 of the License, or
-    (at your option) any later version.
-
-    systemd is distributed in the hope that it will be useful, but
-    WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-    Lesser General Public License for more details.
-
-    You should have received a copy of the GNU Lesser General Public License
-    along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <netinet/ether.h>
-#include <arpa/inet.h>
-#include <net/if.h>
-
-#include "sd-rtnl.h"
-#include "networkd.h"
-#include "missing.h"
-
-static int netdev_fill_bridge_rtnl_message(NetDev *netdev, sd_rtnl_message *m) {
-        int r;
-
-        assert(m);
-
-        r = sd_rtnl_message_append_string(m, IFLA_IFNAME, netdev->ifname);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not append IFLA_IFNAME, attribute: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        r = sd_rtnl_message_open_container(m, IFLA_LINKINFO);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not append IFLA_LINKINFO attribute: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        r = sd_rtnl_message_open_container_union(m, IFLA_INFO_DATA,
-                                                 netdev_kind_to_string(netdev->kind));
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not append IFLA_INFO_DATA attribute: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        r = sd_rtnl_message_close_container(m);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not append IFLA_LINKINFO attribute: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        r = sd_rtnl_message_close_container(m);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not append IFLA_LINKINFO attribute: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        return r;
-}
-
-int netdev_create_bridge(NetDev *netdev, sd_rtnl_message_handler_t callback) {
-        _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
-        int r;
-
-        assert(netdev);
-        assert(netdev->kind == NETDEV_KIND_BRIDGE);
-        assert(netdev->ifname);
-        assert(netdev->manager);
-        assert(netdev->manager->rtnl);
-
-        r = sd_rtnl_message_new_link(netdev->manager->rtnl, &m, RTM_NEWLINK, 0);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not allocate RTM_NEWLINK message: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        r = netdev_fill_bridge_rtnl_message(netdev, m);
-        if(r < 0)
-                return r;
-
-        r = sd_rtnl_call_async(netdev->manager->rtnl, m, callback, netdev, 0, NULL);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not send rtnetlink message: %s", strerror(-r));
-                return r;
-        }
-
-        netdev_ref(netdev);
-
-        log_debug_netdev(netdev, "Creating bridge netdev.");
-
-        netdev->state = NETDEV_STATE_CREATING;
-
-        return 0;
-}
diff --git a/src/network/networkd-dummy.c b/src/network/networkd-dummy.c
deleted file mode 100644
index 80fe41b..0000000
--- a/src/network/networkd-dummy.c
+++ /dev/null
@@ -1,122 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
-    This file is part of systemd.
-
-    Copyright 2014 Susant Sahani <susant at redhat.com>
-    Copyright 2014 Tom Gundersen
-
-    systemd is free software; you can redistribute it and/or modify it
-    under the terms of the GNU Lesser General Public License as published by
-    the Free Software Foundation; either version 2.1 of the License, or
-    (at your option) any later version.
-
-    systemd is distributed in the hope that it will be useful, but
-    WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-    Lesser General Public License for more details.
-
-    You should have received a copy of the GNU Lesser General Public License
-    along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <netinet/ether.h>
-#include <arpa/inet.h>
-#include <net/if.h>
-#include <linux/veth.h>
-
-#include "sd-rtnl.h"
-#include "networkd.h"
-
-
-static int netdev_fill_dummy_rtnl_message(NetDev *netdev, sd_rtnl_message *m) {
-        int r;
-
-        assert(netdev);
-        assert(m);
-
-        r = sd_rtnl_message_append_string(m, IFLA_IFNAME, netdev->ifname);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not append IFLA_IFNAME, attribute: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        if (netdev->mac) {
-                r = sd_rtnl_message_append_ether_addr(m, IFLA_ADDRESS, netdev->mac);
-                if (r < 0) {
-                        log_error_netdev(netdev,
-                                         "Colud not append IFLA_ADDRESS attribute: %s",
-                                         strerror(-r));
-                    return r;
-                }
-        }
-
-        r = sd_rtnl_message_open_container(m, IFLA_LINKINFO);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not append IFLA_LINKINFO attribute: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        r = sd_rtnl_message_open_container_union(m, IFLA_INFO_DATA,
-                                                 netdev_kind_to_string(netdev->kind));
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not append IFLA_INFO_DATA attribute: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        r = sd_rtnl_message_close_container(m);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not append IFLA_LINKINFO attribute: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        return r;
-}
-
-int netdev_create_dummy(NetDev *netdev, sd_rtnl_message_handler_t callback) {
-        _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
-        int r;
-
-        assert(netdev);
-        assert(netdev->ifname);
-        assert(netdev->manager);
-        assert(netdev->manager->rtnl);
-
-        r = sd_rtnl_message_new_link(netdev->manager->rtnl, &m, RTM_NEWLINK, 0);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not allocate RTM_NEWLINK message: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        if(netdev->kind != NETDEV_KIND_DUMMY)
-                return -ENOTSUP;
-
-        r = netdev_fill_dummy_rtnl_message(netdev, m);
-        if(r < 0)
-                return r;
-
-        r = sd_rtnl_call_async(netdev->manager->rtnl, m, callback, netdev, 0, NULL);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not send rtnetlink message: %s", strerror(-r));
-                return r;
-        }
-
-        netdev_ref(netdev);
-
-        log_debug_netdev(netdev, "Creating dummy netdev.");
-
-        netdev->state = NETDEV_STATE_CREATING;
-
-        return 0;
-}
diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index ccf8181..0947b0c 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -24,6 +24,7 @@
 #include <unistd.h>
 
 #include "networkd.h"
+#include "networkd-netdev.h"
 #include "libudev-private.h"
 #include "udev-util.h"
 #include "util.h"
diff --git a/src/network/networkd-macvlan.c b/src/network/networkd-macvlan.c
deleted file mode 100644
index 7c23426..0000000
--- a/src/network/networkd-macvlan.c
+++ /dev/null
@@ -1,160 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
-  This file is part of systemd.
-
-  Copyright 2013 Tom Gundersen <teg at jklm.no>
-
-  systemd is free software; you can redistribute it and/or modify it
-  under the terms of the GNU Lesser General Public License as published by
-  the Free Software Foundation; either version 2.1 of the License, or
-  (at your option) any later version.
-
-  systemd is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-  Lesser General Public License for more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <net/if.h>
-
-#include "networkd.h"
-#include "network-internal.h"
-#include "conf-parser.h"
-#include "list.h"
-
-static const char* const macvlan_mode_table[_NETDEV_MACVLAN_MODE_MAX] = {
-        [NETDEV_MACVLAN_MODE_PRIVATE] = "private",
-        [NETDEV_MACVLAN_MODE_VEPA] = "vepa",
-        [NETDEV_MACVLAN_MODE_BRIDGE] = "bridge",
-        [NETDEV_MACVLAN_MODE_PASSTHRU] = "passthru",
-};
-
-DEFINE_STRING_TABLE_LOOKUP(macvlan_mode, MacVlanMode);
-DEFINE_CONFIG_PARSE_ENUM(config_parse_macvlan_mode, macvlan_mode, MacVlanMode, "Failed to parse macvlan mode");
-
-int netdev_create_macvlan(NetDev *netdev, Link *link, sd_rtnl_message_handler_t callback) {
-        _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
-        const char *kind;
-        int r;
-
-        assert(netdev);
-        assert(netdev->kind == NETDEV_KIND_MACVLAN);
-        assert(link);
-        assert(callback);
-        assert(netdev->ifname);
-        assert(netdev->manager);
-        assert(netdev->manager->rtnl);
-
-        r = sd_rtnl_message_new_link(netdev->manager->rtnl, &req, RTM_NEWLINK, 0);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not allocate RTM_NEWLINK message: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        if (link) {
-                r = sd_rtnl_message_append_u32(req, IFLA_LINK, link->ifindex);
-                if (r < 0) {
-                        log_error_netdev(netdev,
-                                         "Could not append IFLA_LINK attribute: %s",
-                                         strerror(-r));
-                        return r;
-                }
-        }
-
-        r = sd_rtnl_message_append_string(req, IFLA_IFNAME, netdev->ifname);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not append IFLA_IFNAME attribute: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        if (netdev->mtu) {
-                r = sd_rtnl_message_append_u32(req, IFLA_MTU, netdev->mtu);
-                if (r < 0) {
-                        log_error_netdev(netdev,
-                                         "Could not append IFLA_MTU attribute: %s",
-                                         strerror(-r));
-                        return r;
-                }
-        }
-
-        if (netdev->mac) {
-                r = sd_rtnl_message_append_ether_addr(req, IFLA_ADDRESS, netdev->mac);
-                if (r < 0) {
-                        log_error_netdev(netdev,
-                                         "Colud not append IFLA_ADDRESS attribute: %s",
-                                         strerror(-r));
-                    return r;
-                }
-        }
-
-        r = sd_rtnl_message_open_container(req, IFLA_LINKINFO);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not open IFLA_LINKINFO container: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        kind = netdev_kind_to_string(netdev->kind);
-        if (!kind) {
-                log_error_netdev(netdev, "Invalid kind");
-                return -EINVAL;
-        }
-
-        r = sd_rtnl_message_open_container_union(req, IFLA_INFO_DATA, kind);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not open IFLA_INFO_DATA container: %s",
-                                  strerror(-r));
-                return r;
-        }
-
-        if (netdev->macvlan_mode != _NETDEV_MACVLAN_MODE_INVALID) {
-        r = sd_rtnl_message_append_u32(req, IFLA_MACVLAN_MODE, netdev->macvlan_mode);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not append IFLA_MACVLAN_MODE attribute: %s",
-                                 strerror(-r));
-                        return r;
-                }
-        }
-
-        r = sd_rtnl_message_close_container(req);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not close IFLA_INFO_DATA container %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        r = sd_rtnl_message_close_container(req);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not close IFLA_LINKINFO container %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        r = sd_rtnl_call_async(netdev->manager->rtnl, req, callback, link, 0, NULL);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not send rtnetlink message: %s", strerror(-r));
-                return r;
-        }
-
-        link_ref(link);
-
-        log_debug_netdev(netdev, "creating netdev");
-
-        netdev->state = NETDEV_STATE_CREATING;
-
-        return 0;
-}
diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c
index 46b803f..4d10524 100644
--- a/src/network/networkd-manager.c
+++ b/src/network/networkd-manager.c
@@ -25,6 +25,7 @@
 #include "conf-parser.h"
 #include "path-util.h"
 #include "networkd.h"
+#include "networkd-netdev.h"
 #include "network-internal.h"
 #include "libudev-private.h"
 #include "udev-util.h"
diff --git a/src/network/networkd-netdev-bond.c b/src/network/networkd-netdev-bond.c
new file mode 100644
index 0000000..89e3965
--- /dev/null
+++ b/src/network/networkd-netdev-bond.c
@@ -0,0 +1,129 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+    This file is part of systemd.
+
+    Copyright 2014  Tom Gundersen <teg at jklm.no>
+    Copyright 2014  Susant Sahani
+
+    systemd is free software; you can redistribute it and/or modify it
+    under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation; either version 2.1 of the License, or
+    (at your option) any later version.
+
+    systemd is distributed in the hope that it will be useful, but
+    WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <netinet/ether.h>
+#include <arpa/inet.h>
+#include <linux/if_bonding.h>
+
+#include "conf-parser.h"
+#include "sd-rtnl.h"
+#include "networkd-netdev-bond.h"
+#include "missing.h"
+
+static const char* const bond_mode_table[_NETDEV_BOND_MODE_MAX] = {
+        [NETDEV_BOND_MODE_BALANCE_RR] = "balance-rr",
+        [NETDEV_BOND_MODE_ACTIVE_BACKUP] = "active-backup",
+        [NETDEV_BOND_MODE_BALANCE_XOR] = "balance-xor",
+        [NETDEV_BOND_MODE_BROADCAST] = "broadcast",
+        [NETDEV_BOND_MODE_802_3AD] = "802.3ad",
+        [NETDEV_BOND_MODE_BALANCE_TLB] = "balance-tlb",
+        [NETDEV_BOND_MODE_BALANCE_ALB] = "balance-alb",
+};
+
+DEFINE_STRING_TABLE_LOOKUP(bond_mode, BondMode);
+DEFINE_CONFIG_PARSE_ENUM(config_parse_bond_mode, bond_mode, BondMode, "Failed to parse bond mode");
+
+static uint8_t bond_mode_to_kernel(BondMode mode) {
+        switch (mode) {
+        case NETDEV_BOND_MODE_BALANCE_RR:
+                return BOND_MODE_ROUNDROBIN;
+        case NETDEV_BOND_MODE_ACTIVE_BACKUP:
+                return BOND_MODE_ACTIVEBACKUP;
+        case NETDEV_BOND_MODE_BALANCE_XOR:
+                return BOND_MODE_XOR;
+        case NETDEV_BOND_MODE_BROADCAST:
+                return BOND_MODE_BROADCAST;
+        case NETDEV_BOND_MODE_802_3AD:
+                return BOND_MODE_8023AD;
+        case NETDEV_BOND_MODE_BALANCE_TLB:
+                return BOND_MODE_TLB;
+        case NETDEV_BOND_MODE_BALANCE_ALB:
+                return BOND_MODE_ALB;
+        default:
+                return (uint8_t) -1;
+        }
+}
+
+static int netdev_bond_fill_message_create(NetDev *netdev, sd_rtnl_message *m) {
+        int r;
+
+        assert(m);
+
+        r = sd_rtnl_message_append_string(m, IFLA_IFNAME, netdev->ifname);
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not append IFLA_IFNAME, attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        r = sd_rtnl_message_open_container(m, IFLA_LINKINFO);
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not append IFLA_LINKINFO attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        r = sd_rtnl_message_open_container_union(m, IFLA_INFO_DATA,
+                                                 netdev_kind_to_string(netdev->kind));
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not append IFLA_INFO_DATA attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        if (netdev->bond_mode != _NETDEV_BOND_MODE_INVALID) {
+                r = sd_rtnl_message_append_u8(m, IFLA_BOND_MODE,
+                                              bond_mode_to_kernel(netdev->bond_mode));
+                if (r < 0) {
+                        log_error_netdev(netdev,
+                                         "Could not append IFLA_BOND_MODE attribute: %s",
+                                         strerror(-r));
+                        return r;
+                }
+        }
+
+        r = sd_rtnl_message_close_container(m);
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not append IFLA_LINKINFO attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        r = sd_rtnl_message_close_container(m);
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not append IFLA_LINKINFO attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        return r;
+}
+
+const NetDevVTable bond_vtable = {
+        .fill_message_create = netdev_bond_fill_message_create,
+        .enslave = netdev_enslave,
+};
diff --git a/src/network/networkd-netdev-bond.h b/src/network/networkd-netdev-bond.h
new file mode 100644
index 0000000..03ef081
--- /dev/null
+++ b/src/network/networkd-netdev-bond.h
@@ -0,0 +1,43 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+  This file is part of systemd.
+
+  Copyright 2014 Tom Gundersen <teg at jklm.no>
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#pragma once
+
+#include "networkd-netdev.h"
+
+extern const NetDevVTable bond_vtable;
+
+typedef enum BondMode {
+        NETDEV_BOND_MODE_BALANCE_RR,
+        NETDEV_BOND_MODE_ACTIVE_BACKUP,
+        NETDEV_BOND_MODE_BALANCE_XOR,
+        NETDEV_BOND_MODE_BROADCAST,
+        NETDEV_BOND_MODE_802_3AD,
+        NETDEV_BOND_MODE_BALANCE_TLB,
+        NETDEV_BOND_MODE_BALANCE_ALB,
+        _NETDEV_BOND_MODE_MAX,
+        _NETDEV_BOND_MODE_INVALID = -1
+} BondMode;
+
+const char *bond_mode_to_string(BondMode d) _const_;
+BondMode bond_mode_from_string(const char *d) _pure_;
+
+int config_parse_bond_mode(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
diff --git a/src/network/networkd-netdev-bridge.c b/src/network/networkd-netdev-bridge.c
new file mode 100644
index 0000000..9a8bf57
--- /dev/null
+++ b/src/network/networkd-netdev-bridge.c
@@ -0,0 +1,84 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+    This file is part of systemd.
+
+    Copyright 2014  Tom Gundersen <teg at jklm.no>
+    Copyright 2014  Susant Sahani
+
+    systemd is free software; you can redistribute it and/or modify it
+    under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation; either version 2.1 of the License, or
+    (at your option) any later version.
+
+    systemd is distributed in the hope that it will be useful, but
+    WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <netinet/ether.h>
+#include <arpa/inet.h>
+#include <net/if.h>
+
+#include "sd-rtnl.h"
+#include "networkd-netdev-bridge.h"
+#include "missing.h"
+
+static int netdev_bridge_fill_message_create(NetDev *netdev, sd_rtnl_message *m) {
+        int r;
+
+        assert(netdev);
+        assert(netdev->ifname);
+        assert(m);
+
+        r = sd_rtnl_message_append_string(m, IFLA_IFNAME, netdev->ifname);
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not append IFLA_IFNAME, attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        r = sd_rtnl_message_open_container(m, IFLA_LINKINFO);
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not append IFLA_LINKINFO attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        r = sd_rtnl_message_open_container_union(m, IFLA_INFO_DATA, "bridge");
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not append IFLA_INFO_DATA attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        r = sd_rtnl_message_close_container(m);
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not append IFLA_LINKINFO attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        r = sd_rtnl_message_close_container(m);
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not append IFLA_LINKINFO attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        return r;
+}
+
+const NetDevVTable bridge_vtable = {
+        .fill_message_create = netdev_bridge_fill_message_create,
+        .enslave = netdev_enslave,
+};
diff --git a/src/network/networkd-netdev-bridge.h b/src/network/networkd-netdev-bridge.h
new file mode 100644
index 0000000..4d971c6
--- /dev/null
+++ b/src/network/networkd-netdev-bridge.h
@@ -0,0 +1,26 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+  This file is part of systemd.
+
+  Copyright 2014 Tom Gundersen <teg at jklm.no>
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#pragma once
+
+#include "networkd-netdev.h"
+
+extern const NetDevVTable bridge_vtable;
diff --git a/src/network/networkd-netdev-dummy.c b/src/network/networkd-netdev-dummy.c
new file mode 100644
index 0000000..100dbbf
--- /dev/null
+++ b/src/network/networkd-netdev-dummy.c
@@ -0,0 +1,85 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+    This file is part of systemd.
+
+    Copyright 2014 Susant Sahani <susant at redhat.com>
+    Copyright 2014 Tom Gundersen
+
+    systemd is free software; you can redistribute it and/or modify it
+    under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation; either version 2.1 of the License, or
+    (at your option) any later version.
+
+    systemd is distributed in the hope that it will be useful, but
+    WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <netinet/ether.h>
+#include <arpa/inet.h>
+#include <net/if.h>
+#include <linux/veth.h>
+
+#include "sd-rtnl.h"
+#include "networkd-netdev-dummy.h"
+
+static int netdev_dummy_fill_message_create(NetDev *netdev, sd_rtnl_message *m) {
+        int r;
+
+        assert(netdev);
+        assert(netdev->ifname);
+        assert(m);
+
+        r = sd_rtnl_message_append_string(m, IFLA_IFNAME, netdev->ifname);
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not append IFLA_IFNAME, attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        if (netdev->mac) {
+                r = sd_rtnl_message_append_ether_addr(m, IFLA_ADDRESS, netdev->mac);
+                if (r < 0) {
+                        log_error_netdev(netdev,
+                                         "Colud not append IFLA_ADDRESS attribute: %s",
+                                         strerror(-r));
+                    return r;
+                }
+        }
+
+        r = sd_rtnl_message_open_container(m, IFLA_LINKINFO);
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not append IFLA_LINKINFO attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        r = sd_rtnl_message_open_container_union(m, IFLA_INFO_DATA, "dummy");
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not append IFLA_INFO_DATA attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        r = sd_rtnl_message_close_container(m);
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not append IFLA_LINKINFO attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        return r;
+}
+
+const NetDevVTable dummy_vtable = {
+        .fill_message_create = netdev_dummy_fill_message_create,
+};
diff --git a/src/network/networkd-netdev-dummy.h b/src/network/networkd-netdev-dummy.h
new file mode 100644
index 0000000..dcbd3cc
--- /dev/null
+++ b/src/network/networkd-netdev-dummy.h
@@ -0,0 +1,26 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+  This file is part of systemd.
+
+  Copyright 2014 Tom Gundersen <teg at jklm.no>
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#pragma once
+
+#include "networkd-netdev.h"
+
+extern const NetDevVTable dummy_vtable;
diff --git a/src/network/networkd-netdev-gperf.gperf b/src/network/networkd-netdev-gperf.gperf
index a698ea8..090dfb3 100644
--- a/src/network/networkd-netdev-gperf.gperf
+++ b/src/network/networkd-netdev-gperf.gperf
@@ -1,7 +1,10 @@
 %{
 #include <stddef.h>
 #include "conf-parser.h"
-#include "networkd.h"
+#include "networkd-netdev.h"
+#include "networkd-netdev-tunnel.h"
+#include "networkd-netdev-bond.h"
+#include "networkd-netdev-macvlan.h"
 #include "network-internal.h"
 %}
 struct ConfigPerfItem;
diff --git a/src/network/networkd-netdev-macvlan.c b/src/network/networkd-netdev-macvlan.c
new file mode 100644
index 0000000..9eb66ff
--- /dev/null
+++ b/src/network/networkd-netdev-macvlan.c
@@ -0,0 +1,130 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+  This file is part of systemd.
+
+  Copyright 2013 Tom Gundersen <teg at jklm.no>
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <net/if.h>
+
+#include "networkd-netdev-macvlan.h"
+#include "network-internal.h"
+#include "conf-parser.h"
+#include "list.h"
+
+static const char* const macvlan_mode_table[_NETDEV_MACVLAN_MODE_MAX] = {
+        [NETDEV_MACVLAN_MODE_PRIVATE] = "private",
+        [NETDEV_MACVLAN_MODE_VEPA] = "vepa",
+        [NETDEV_MACVLAN_MODE_BRIDGE] = "bridge",
+        [NETDEV_MACVLAN_MODE_PASSTHRU] = "passthru",
+};
+
+DEFINE_STRING_TABLE_LOOKUP(macvlan_mode, MacVlanMode);
+DEFINE_CONFIG_PARSE_ENUM(config_parse_macvlan_mode, macvlan_mode, MacVlanMode, "Failed to parse macvlan mode");
+
+static int netdev_macvlan_fill_message_create(NetDev *netdev, Link *link, sd_rtnl_message *req) {
+        int r;
+
+        assert(netdev);
+        assert(netdev->kind == NETDEV_KIND_MACVLAN);
+        assert(link);
+        assert(netdev->ifname);
+
+        r = sd_rtnl_message_append_u32(req, IFLA_LINK, link->ifindex);
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not append IFLA_LINK attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        r = sd_rtnl_message_append_string(req, IFLA_IFNAME, netdev->ifname);
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not append IFLA_IFNAME attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        if (netdev->mtu) {
+                r = sd_rtnl_message_append_u32(req, IFLA_MTU, netdev->mtu);
+                if (r < 0) {
+                        log_error_netdev(netdev,
+                                         "Could not append IFLA_MTU attribute: %s",
+                                         strerror(-r));
+                        return r;
+                }
+        }
+
+        if (netdev->mac) {
+                r = sd_rtnl_message_append_ether_addr(req, IFLA_ADDRESS, netdev->mac);
+                if (r < 0) {
+                        log_error_netdev(netdev,
+                                         "Colud not append IFLA_ADDRESS attribute: %s",
+                                         strerror(-r));
+                    return r;
+                }
+        }
+
+        r = sd_rtnl_message_open_container(req, IFLA_LINKINFO);
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not open IFLA_LINKINFO container: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        r = sd_rtnl_message_open_container_union(req, IFLA_INFO_DATA, "macvlan");
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not open IFLA_INFO_DATA container: %s",
+                                  strerror(-r));
+                return r;
+        }
+
+        if (netdev->macvlan_mode != _NETDEV_MACVLAN_MODE_INVALID) {
+        r = sd_rtnl_message_append_u32(req, IFLA_MACVLAN_MODE, netdev->macvlan_mode);
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not append IFLA_MACVLAN_MODE attribute: %s",
+                                 strerror(-r));
+                        return r;
+                }
+        }
+
+        r = sd_rtnl_message_close_container(req);
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not close IFLA_INFO_DATA container %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        r = sd_rtnl_message_close_container(req);
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not close IFLA_LINKINFO container %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        return 0;
+}
+
+const NetDevVTable macvlan_vtable = {
+        .fill_message_create_on_link = netdev_macvlan_fill_message_create,
+};
diff --git a/src/network/networkd-netdev-macvlan.h b/src/network/networkd-netdev-macvlan.h
new file mode 100644
index 0000000..ea268cc
--- /dev/null
+++ b/src/network/networkd-netdev-macvlan.h
@@ -0,0 +1,40 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+  This file is part of systemd.
+
+  Copyright 2014 Tom Gundersen <teg at jklm.no>
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#pragma once
+
+#include "networkd-netdev.h"
+
+extern const NetDevVTable macvlan_vtable;
+
+typedef enum MacVlanMode {
+        NETDEV_MACVLAN_MODE_PRIVATE = MACVLAN_MODE_PRIVATE,
+        NETDEV_MACVLAN_MODE_VEPA = MACVLAN_MODE_VEPA,
+        NETDEV_MACVLAN_MODE_BRIDGE = MACVLAN_MODE_BRIDGE,
+        NETDEV_MACVLAN_MODE_PASSTHRU = MACVLAN_MODE_PASSTHRU,
+        _NETDEV_MACVLAN_MODE_MAX,
+        _NETDEV_MACVLAN_MODE_INVALID = -1
+} MacVlanMode;
+
+const char *macvlan_mode_to_string(MacVlanMode d) _const_;
+MacVlanMode macvlan_mode_from_string(const char *d) _pure_;
+
+int config_parse_macvlan_mode(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
diff --git a/src/network/networkd-netdev-tunnel.c b/src/network/networkd-netdev-tunnel.c
new file mode 100644
index 0000000..8acb746
--- /dev/null
+++ b/src/network/networkd-netdev-tunnel.c
@@ -0,0 +1,536 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+    This file is part of systemd.
+
+    Copyright 2014 Susant Sahani <susant at redhat.com>
+
+    systemd is free software; you can redistribute it and/or modify it
+    under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation; either version 2.1 of the License, or
+    (at your option) any later version.
+
+    systemd is distributed in the hope that it will be useful, but
+    WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <netinet/ether.h>
+#include <arpa/inet.h>
+#include <net/if.h>
+#include <linux/ip.h>
+#include <linux/if_tunnel.h>
+
+#include "sd-rtnl.h"
+#include "networkd-netdev-tunnel.h"
+#include "network-internal.h"
+#include "util.h"
+#include "missing.h"
+#include "conf-parser.h"
+
+static int netdev_ipip_fill_message_create(NetDev *netdev, Link *link, sd_rtnl_message *m) {
+        int r;
+
+        assert(netdev);
+        assert(netdev->kind == NETDEV_KIND_IPIP);
+        assert(netdev->ifname);
+        assert(netdev->manager);
+        assert(netdev->manager->rtnl);
+        assert(link);
+        assert(m);
+        assert(netdev->family == AF_INET);
+
+        r = sd_rtnl_message_append_string(m, IFLA_IFNAME, netdev->ifname);
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not append IFLA_IFNAME, attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        if(netdev->mtu) {
+                r = sd_rtnl_message_append_u32(m, IFLA_MTU, netdev->mtu);
+                if (r < 0) {
+                        log_error_netdev(netdev,
+                                         "Could not append IFLA_MTU attribute: %s",
+                                         strerror(-r));
+                        return r;
+                }
+        }
+
+        if (netdev->mac) {
+                r = sd_rtnl_message_append_ether_addr(m, IFLA_ADDRESS, netdev->mac);
+                if (r < 0) {
+                        log_error_netdev(netdev,
+                                         "Colud not append IFLA_ADDRESS attribute: %s",
+                                         strerror(-r));
+                    return r;
+                }
+        }
+
+        r = sd_rtnl_message_open_container(m, IFLA_LINKINFO);
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not append IFLA_LINKINFO attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        r = sd_rtnl_message_open_container_union(m, IFLA_INFO_DATA,
+                                                 netdev_kind_to_string(netdev->kind));
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not append IFLA_INFO_DATA attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        r = sd_rtnl_message_append_u32(m, IFLA_IPTUN_LINK, link->ifindex);
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not append IFLA_IPTUN_LINK attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        r = sd_rtnl_message_append_in_addr(m, IFLA_IPTUN_LOCAL, &netdev->local.in);
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not append IFLA_IPTUN_LOCAL attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        r = sd_rtnl_message_append_in_addr(m, IFLA_IPTUN_REMOTE, &netdev->remote.in);
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not append IFLA_IPTUN_REMOTE attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        r = sd_rtnl_message_append_u8(m, IFLA_IPTUN_TTL, netdev->ttl);
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not append IFLA_IPTUN_TTL  attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        r = sd_rtnl_message_close_container(m);
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not append IFLA_INFO_DATA attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        r = sd_rtnl_message_close_container(m);
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not append IFLA_LINKINFO attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        return r;
+}
+
+static int netdev_sit_fill_message_create(NetDev *netdev, Link *link, sd_rtnl_message *m) {
+        int r;
+
+        assert(netdev);
+        assert(netdev->kind == NETDEV_KIND_SIT);
+        assert(netdev->ifname);
+        assert(netdev->manager);
+        assert(netdev->manager->rtnl);
+        assert(link);
+        assert(m);
+        assert(netdev->family == AF_INET);
+
+        r = sd_rtnl_message_append_string(m, IFLA_IFNAME, netdev->ifname);
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not append IFLA_IFNAME, attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        if(netdev->mtu) {
+                r = sd_rtnl_message_append_u32(m, IFLA_MTU, netdev->mtu);
+                if (r < 0) {
+                        log_error_netdev(netdev,
+                                         "Could not append IFLA_MTU attribute: %s",
+                                         strerror(-r));
+                        return r;
+                }
+        }
+
+        if (netdev->mac) {
+                r = sd_rtnl_message_append_ether_addr(m, IFLA_ADDRESS, netdev->mac);
+                if (r < 0) {
+                        log_error_netdev(netdev,
+                                         "Colud not append IFLA_ADDRESS attribute: %s",
+                                         strerror(-r));
+                    return r;
+                }
+        }
+
+        r = sd_rtnl_message_open_container(m, IFLA_LINKINFO);
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not append IFLA_LINKINFO attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        r = sd_rtnl_message_open_container_union(m, IFLA_INFO_DATA,
+                                                 netdev_kind_to_string(netdev->kind));
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not append IFLA_INFO_DATA attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        r = sd_rtnl_message_append_u32(m, IFLA_IPTUN_LINK, link->ifindex);
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not append IFLA_IPTUN_LINK attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        r = sd_rtnl_message_append_in_addr(m, IFLA_IPTUN_LOCAL, &netdev->local.in);
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not append IFLA_IPTUN_LOCAL attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        r = sd_rtnl_message_append_in_addr(m, IFLA_IPTUN_REMOTE, &netdev->remote.in);
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not append IFLA_IPTUN_REMOTE attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        r = sd_rtnl_message_append_u8(m, IFLA_IPTUN_TTL, netdev->ttl);
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not append IFLA_IPTUN_TTL  attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        r = sd_rtnl_message_close_container(m);
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not append IFLA_INFO_DATA attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        r = sd_rtnl_message_close_container(m);
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not append IFLA_LINKINFO attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        return r;
+}
+
+static int netdev_gre_fill_message_create(NetDev *netdev, Link *link, sd_rtnl_message *m) {
+        int r;
+
+        assert(netdev);
+        assert(netdev->kind == NETDEV_KIND_GRE);
+        assert(netdev->ifname);
+        assert(netdev->manager);
+        assert(netdev->manager->rtnl);
+        assert(link);
+        assert(m);
+        assert(netdev->family == AF_INET);
+
+        r = sd_rtnl_message_append_string(m, IFLA_IFNAME, netdev->ifname);
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not append IFLA_IFNAME, attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        if(netdev->mtu) {
+                r = sd_rtnl_message_append_u32(m, IFLA_MTU, netdev->mtu);
+                if (r < 0) {
+                        log_error_netdev(netdev,
+                                         "Could not append IFLA_MTU attribute: %s",
+                                         strerror(-r));
+                        return r;
+                }
+        }
+
+        if (netdev->mac) {
+                r = sd_rtnl_message_append_ether_addr(m, IFLA_ADDRESS, netdev->mac);
+                if (r < 0) {
+                        log_error_netdev(netdev,
+                                         "Colud not append IFLA_ADDRESS attribute: %s",
+                                         strerror(-r));
+                    return r;
+                }
+        }
+
+        r = sd_rtnl_message_open_container(m, IFLA_LINKINFO);
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not append IFLA_LINKINFO attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        r = sd_rtnl_message_open_container_union(m, IFLA_INFO_DATA,
+                                                 netdev_kind_to_string(netdev->kind));
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not append IFLA_INFO_DATA attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        r = sd_rtnl_message_append_u32(m, IFLA_GRE_LINK, link->ifindex);
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not append IFLA_GRE_LINK attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        r = sd_rtnl_message_append_in_addr(m, IFLA_GRE_LOCAL, &netdev->local.in);
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not append IFLA_GRE_LOCAL attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        r = sd_rtnl_message_append_in_addr(m, IFLA_GRE_REMOTE, &netdev->remote.in);
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not append IFLA_GRE_REMOTE attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        r = sd_rtnl_message_append_u8(m, IFLA_GRE_TTL, netdev->ttl);
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not append IFLA_GRE_TTL attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        r = sd_rtnl_message_append_u8(m, IFLA_GRE_TOS, netdev->tos);
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not append IFLA_GRE_TOS attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        r = sd_rtnl_message_close_container(m);
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not append IFLA_INFO_DATA attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        r = sd_rtnl_message_close_container(m);
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not append IFLA_LINKINFO attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        return r;
+}
+
+static int netdev_vti_fill_message_create(NetDev *netdev, Link *link, sd_rtnl_message *m) {
+        int r;
+
+        assert(netdev);
+        assert(netdev->kind == NETDEV_KIND_VTI);
+        assert(netdev->ifname);
+        assert(netdev->manager);
+        assert(netdev->manager->rtnl);
+        assert(link);
+        assert(m);
+        assert(netdev->family == AF_INET);
+
+        r = sd_rtnl_message_append_string(m, IFLA_IFNAME, netdev->ifname);
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not append IFLA_IFNAME, attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        if(netdev->mtu) {
+                r = sd_rtnl_message_append_u32(m, IFLA_MTU, netdev->mtu);
+                if (r < 0) {
+                        log_error_netdev(netdev,
+                                         "Could not append IFLA_MTU attribute: %s",
+                                         strerror(-r));
+                        return r;
+                }
+        }
+
+        if (netdev->mac) {
+                r = sd_rtnl_message_append_ether_addr(m, IFLA_ADDRESS, netdev->mac);
+                if (r < 0) {
+                        log_error_netdev(netdev,
+                                         "Colud not append IFLA_ADDRESS attribute: %s",
+                                         strerror(-r));
+                    return r;
+                }
+        }
+
+        r = sd_rtnl_message_open_container(m, IFLA_LINKINFO);
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not append IFLA_LINKINFO attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        r = sd_rtnl_message_open_container_union(m, IFLA_INFO_DATA,
+                                                 netdev_kind_to_string(netdev->kind));
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not append IFLA_INFO_DATA attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        r = sd_rtnl_message_append_u32(m, IFLA_VTI_LINK, link->ifindex);
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not append IFLA_IPTUN_LINK attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        r = sd_rtnl_message_append_in_addr(m, IFLA_VTI_LOCAL, &netdev->local.in);
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not append IFLA_IPTUN_LOCAL attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        r = sd_rtnl_message_append_in_addr(m, IFLA_VTI_REMOTE, &netdev->remote.in);
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not append IFLA_IPTUN_REMOTE attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        r = sd_rtnl_message_close_container(m);
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not append IFLA_INFO_DATA attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        r = sd_rtnl_message_close_container(m);
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not append IFLA_LINKINFO attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        return r;
+}
+
+static int netdev_tunnel_verify(NetDev *netdev, const char *filename) {
+        assert(netdev);
+        assert(filename);
+
+        if (netdev->local.in.s_addr == INADDR_ANY) {
+               log_warning("Tunnel without local address configured in %s. Ignoring", filename);
+               return -EINVAL;
+        }
+
+        if (netdev->remote.in.s_addr == INADDR_ANY) {
+               log_warning("Tunnel without remote address configured in %s. Ignoring", filename);
+               return -EINVAL;
+        }
+
+        if (netdev->family != AF_INET) {
+              log_warning("Tunnel with invalid address family configured in %s. Ignoring", filename);
+              return -EINVAL;
+        }
+
+        return 0;
+}
+
+int config_parse_tunnel_address(const char *unit,
+                                const char *filename,
+                                unsigned line,
+                                const char *section,
+                                unsigned section_line,
+                                const char *lvalue,
+                                int ltype,
+                                const char *rvalue,
+                                void *data,
+                                void *userdata) {
+        NetDev *n = userdata;
+        union in_addr_union *addr = data;
+        int r;
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        r = net_parse_inaddr(rvalue, &n->family, addr);
+        if (r < 0) {
+                log_syntax(unit, LOG_ERR, filename, line, EINVAL,
+                           "Tunnel address is invalid, ignoring assignment: %s", rvalue);
+                return 0;
+        }
+
+        return 0;
+}
+
+const NetDevVTable ipip_vtable = {
+        .fill_message_create_on_link = netdev_ipip_fill_message_create,
+        .config_verify = netdev_tunnel_verify,
+};
+
+const NetDevVTable sit_vtable = {
+        .fill_message_create_on_link = netdev_sit_fill_message_create,
+        .config_verify = netdev_tunnel_verify,
+};
+
+const NetDevVTable vti_vtable = {
+        .fill_message_create_on_link = netdev_vti_fill_message_create,
+        .config_verify = netdev_tunnel_verify,
+};
+
+const NetDevVTable gre_vtable = {
+        .fill_message_create_on_link = netdev_gre_fill_message_create,
+        .config_verify = netdev_tunnel_verify,
+};
diff --git a/src/network/networkd-netdev-tunnel.h b/src/network/networkd-netdev-tunnel.h
new file mode 100644
index 0000000..b30204b
--- /dev/null
+++ b/src/network/networkd-netdev-tunnel.h
@@ -0,0 +1,29 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+  This file is part of systemd.
+
+  Copyright 2014 Tom Gundersen <teg at jklm.no>
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#pragma once
+
+#include "networkd-netdev.h"
+
+extern const NetDevVTable ipip_vtable;
+extern const NetDevVTable sit_vtable;
+extern const NetDevVTable vti_vtable;
+extern const NetDevVTable gre_vtable;
diff --git a/src/network/networkd-netdev-tuntap.c b/src/network/networkd-netdev-tuntap.c
new file mode 100644
index 0000000..8f60461
--- /dev/null
+++ b/src/network/networkd-netdev-tuntap.c
@@ -0,0 +1,162 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+    This file is part of systemd.
+
+    Copyright 2014 Susant Sahani <susant at redhat.com>
+
+    systemd is free software; you can redistribute it and/or modify it
+    under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation; either version 2.1 of the License, or
+    (at your option) any later version.
+
+    systemd is distributed in the hope that it will be useful, but
+    WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <sys/ioctl.h>
+#include <net/if.h>
+#include <linux/if_tun.h>
+
+#include "networkd-netdev-tuntap.h"
+
+#define TUN_DEV "/dev/net/tun"
+
+static int netdev_fill_tuntap_message(NetDev *netdev, struct ifreq *ifr) {
+
+        assert(netdev);
+        assert(ifr);
+
+        memset(ifr, 0, sizeof(*ifr));
+
+        if (netdev->kind == NETDEV_KIND_TAP)
+                ifr->ifr_flags |= IFF_TAP;
+        else
+                ifr->ifr_flags |= IFF_TUN;
+
+        if (!netdev->packet_info)
+                ifr->ifr_flags |= IFF_NO_PI;
+
+        if (netdev->one_queue)
+                ifr->ifr_flags |= IFF_ONE_QUEUE;
+
+        if (netdev->multi_queue)
+                ifr->ifr_flags |= IFF_MULTI_QUEUE;
+
+        strncpy(ifr->ifr_name, netdev->ifname, IFNAMSIZ-1);
+
+        return 0;
+}
+
+static int netdev_tuntap_add(NetDev *netdev, struct ifreq *ifr) {
+        _cleanup_close_ int fd;
+        const char *user;
+        const char *group;
+        uid_t uid;
+        gid_t gid;
+        int r = 0;
+
+        fd = open(TUN_DEV, O_RDWR);
+        if (fd < 0) {
+                log_error_netdev(netdev,
+                                 "Failed to open tun dev: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        r = ioctl(fd, TUNSETIFF, ifr);
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "TUNSETIFF failed on tun dev: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        if(netdev->user_name) {
+
+                user = netdev->user_name;
+
+                r = get_user_creds(&user, &uid, NULL, NULL, NULL);
+                if (r < 0) {
+                        log_error("Cannot resolve user name %s: %s",
+                                  netdev->user_name, strerror(-r));
+                        return 0;
+                }
+
+                r = ioctl(fd, TUNSETOWNER, uid);
+                if ( r < 0) {
+                        log_error_netdev(netdev,
+                                         "TUNSETOWNER failed on tun dev: %s",
+                                         strerror(-r));
+                }
+        }
+
+        if(netdev->group_name) {
+
+                group = netdev->group_name;
+
+                r = get_group_creds(&group, &gid);
+                if (r < 0) {
+                        log_error("Cannot resolve group name %s: %s",
+                                  netdev->group_name, strerror(-r));
+                        return 0;
+                }
+
+                r = ioctl(fd, TUNSETGROUP, gid);
+                if( r < 0) {
+                        log_error_netdev(netdev,
+                                         "TUNSETGROUP failed on tun dev: %s",
+                                         strerror(-r));
+                        return r;
+                }
+
+        }
+
+        r = ioctl(fd, TUNSETPERSIST, 1);
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "TUNSETPERSIST failed on tun dev: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        return r;
+}
+
+static int netdev_create_tuntap(NetDev *netdev) {
+        struct ifreq ifr;
+        int r;
+
+        assert(netdev);
+        assert(netdev->ifname);
+
+        switch(netdev->kind) {
+        case NETDEV_KIND_TUN:
+        case NETDEV_KIND_TAP:
+                break;
+        default:
+                return -ENOTSUP;
+        }
+
+        r = netdev_fill_tuntap_message(netdev, &ifr);
+        if(r < 0)
+                return r;
+
+        log_debug_netdev(netdev, "Creating tuntap netdev: %s",
+                         netdev_kind_to_string(netdev->kind));
+
+        return netdev_tuntap_add(netdev, &ifr);
+}
+
+const NetDevVTable tun_vtable = {
+        .create = netdev_create_tuntap,
+};
+
+const NetDevVTable tap_vtable = {
+        .create = netdev_create_tuntap,
+};
diff --git a/src/network/networkd-netdev-tuntap.h b/src/network/networkd-netdev-tuntap.h
new file mode 100644
index 0000000..2b6e48f
--- /dev/null
+++ b/src/network/networkd-netdev-tuntap.h
@@ -0,0 +1,27 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+  This file is part of systemd.
+
+  Copyright 2014 Tom Gundersen <teg at jklm.no>
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#pragma once
+
+#include "networkd-netdev.h"
+
+extern const NetDevVTable tun_vtable;
+extern const NetDevVTable tap_vtable;
diff --git a/src/network/networkd-netdev-veth.c b/src/network/networkd-netdev-veth.c
new file mode 100644
index 0000000..aca8022
--- /dev/null
+++ b/src/network/networkd-netdev-veth.c
@@ -0,0 +1,143 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+    This file is part of systemd.
+
+    Copyright 2014 Susant Sahani <susant at redhat.com>
+
+    systemd is free software; you can redistribute it and/or modify it
+    under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation; either version 2.1 of the License, or
+    (at your option) any later version.
+
+    systemd is distributed in the hope that it will be useful, but
+    WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <netinet/ether.h>
+#include <arpa/inet.h>
+#include <net/if.h>
+#include <linux/veth.h>
+
+#include "sd-rtnl.h"
+#include "networkd-netdev-veth.h"
+
+static int netdev_veth_fill_message_create(NetDev *netdev, sd_rtnl_message *m) {
+        int r;
+
+        assert(netdev);
+        assert(netdev->ifname);
+        assert(m);
+
+        r = sd_rtnl_message_append_string(m, IFLA_IFNAME, netdev->ifname);
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not append IFLA_IFNAME, attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        if (netdev->mac) {
+                r = sd_rtnl_message_append_ether_addr(m, IFLA_ADDRESS, netdev->mac);
+                if (r < 0) {
+                        log_error_netdev(netdev,
+                                         "Colud not append IFLA_ADDRESS attribute: %s",
+                                         strerror(-r));
+                    return r;
+                }
+        }
+
+        r = sd_rtnl_message_open_container(m, IFLA_LINKINFO);
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not append IFLA_LINKINFO attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        r = sd_rtnl_message_open_container_union(m, IFLA_INFO_DATA, "veth");
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not append IFLA_INFO_DATA attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        r = sd_rtnl_message_open_container(m, VETH_INFO_PEER);
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not append IFLA_IPTUN_LINK attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        if (netdev->ifname_peer) {
+                r = sd_rtnl_message_append_string(m, IFLA_IFNAME, netdev->ifname_peer);
+                if (r < 0) {
+                        log_error("Failed to add netlink interface name: %s", strerror(-r));
+                        return r;
+                }
+        }
+
+        if (netdev->mac_peer) {
+                r = sd_rtnl_message_append_ether_addr(m, IFLA_ADDRESS, netdev->mac_peer);
+                if (r < 0) {
+                        log_error_netdev(netdev,
+                                         "Colud not append IFLA_ADDRESS attribute: %s",
+                                         strerror(-r));
+                    return r;
+                }
+        }
+
+        r = sd_rtnl_message_close_container(m);
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not append IFLA_INFO_DATA attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        r = sd_rtnl_message_close_container(m);
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not append IFLA_LINKINFO attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        return r;
+}
+
+static int netdev_veth_verify(NetDev *netdev, const char *filename) {
+        int r;
+
+        assert(netdev);
+        assert(filename);
+
+        if (!netdev->ifname_peer) {
+                log_warning("Veth NetDev without peer name configured in %s. Ignoring",
+                            filename);
+                return -EINVAL;
+        }
+
+        if (!netdev->mac_peer) {
+                r = netdev_get_mac(netdev->ifname_peer, &netdev->mac_peer);
+                if (r < 0) {
+                        log_warning("Failed to generate predictable MAC address for %s. Ignoring",
+                                  netdev->ifname_peer);
+                        return -EINVAL;
+                }
+        }
+
+        return 0;
+}
+
+const NetDevVTable veth_vtable = {
+        .fill_message_create = netdev_veth_fill_message_create,
+        .config_verify = netdev_veth_verify,
+};
diff --git a/src/network/networkd-netdev-veth.h b/src/network/networkd-netdev-veth.h
new file mode 100644
index 0000000..93dcdfa
--- /dev/null
+++ b/src/network/networkd-netdev-veth.h
@@ -0,0 +1,26 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+  This file is part of systemd.
+
+  Copyright 2014 Tom Gundersen <teg at jklm.no>
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#pragma once
+
+#include "networkd-netdev.h"
+
+extern const NetDevVTable veth_vtable;
diff --git a/src/network/networkd-netdev-vlan.c b/src/network/networkd-netdev-vlan.c
new file mode 100644
index 0000000..20d0fd5
--- /dev/null
+++ b/src/network/networkd-netdev-vlan.c
@@ -0,0 +1,133 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+  This file is part of systemd.
+
+  Copyright 2013 Tom Gundersen <teg at jklm.no>
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <net/if.h>
+
+#include "networkd-netdev-vlan.h"
+#include "network-internal.h"
+#include "list.h"
+
+static int netdev_vlan_fill_message_create(NetDev *netdev, Link *link, sd_rtnl_message *req) {
+        int r;
+
+        assert(netdev);
+        assert(netdev->ifname);
+        assert(netdev->kind == NETDEV_KIND_VLAN);
+        assert(link);
+        assert(req);
+
+        r = sd_rtnl_message_append_u32(req, IFLA_LINK, link->ifindex);
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not append IFLA_LINK attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        r = sd_rtnl_message_append_string(req, IFLA_IFNAME, netdev->ifname);
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not append IFLA_IFNAME attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        if (netdev->mtu) {
+                r = sd_rtnl_message_append_u32(req, IFLA_MTU, netdev->mtu);
+                if (r < 0) {
+                        log_error_netdev(netdev,
+                                         "Could not append IFLA_MTU attribute: %s",
+                                         strerror(-r));
+                        return r;
+                }
+        }
+
+        if (netdev->mac) {
+                r = sd_rtnl_message_append_ether_addr(req, IFLA_ADDRESS, netdev->mac);
+                if (r < 0) {
+                        log_error_netdev(netdev,
+                                         "Colud not append IFLA_ADDRESS attribute: %s",
+                                         strerror(-r));
+                    return r;
+                }
+        }
+
+        r = sd_rtnl_message_open_container(req, IFLA_LINKINFO);
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not open IFLA_LINKINFO container: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        r = sd_rtnl_message_open_container_union(req, IFLA_INFO_DATA, "vlan");
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not open IFLA_INFO_DATA container: %s",
+                                  strerror(-r));
+                return r;
+        }
+
+        if (netdev->vlanid <= VLANID_MAX) {
+                r = sd_rtnl_message_append_u16(req, IFLA_VLAN_ID, netdev->vlanid);
+                if (r < 0) {
+                        log_error_netdev(netdev,
+                                         "Could not append IFLA_VLAN_ID attribute: %s",
+                                         strerror(-r));
+                        return r;
+                }
+        }
+
+        r = sd_rtnl_message_close_container(req);
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not close IFLA_INFO_DATA container %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        r = sd_rtnl_message_close_container(req);
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not close IFLA_LINKINFO container %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        return 0;
+}
+
+static int netdev_vlan_verify(NetDev *netdev, const char *filename) {
+        assert(netdev);
+        assert(filename);
+
+        if (netdev->vlanid > VLANID_MAX) {
+                log_warning("VLAN without valid Id configured in %s. Ignoring", filename);
+                return -EINVAL;
+        }
+
+        return 0;
+}
+
+const NetDevVTable vlan_vtable = {
+        .fill_message_create_on_link = netdev_vlan_fill_message_create,
+        .config_verify = netdev_vlan_verify,
+};
diff --git a/src/network/networkd-netdev-vlan.h b/src/network/networkd-netdev-vlan.h
new file mode 100644
index 0000000..95f630f
--- /dev/null
+++ b/src/network/networkd-netdev-vlan.h
@@ -0,0 +1,28 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+  This file is part of systemd.
+
+  Copyright 2014 Tom Gundersen <teg at jklm.no>
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#pragma once
+
+#include "networkd-netdev.h"
+
+#define VLANID_MAX 4094
+
+extern const NetDevVTable vlan_vtable;
diff --git a/src/network/networkd-netdev-vxlan.c b/src/network/networkd-netdev-vxlan.c
new file mode 100644
index 0000000..38692c6
--- /dev/null
+++ b/src/network/networkd-netdev-vxlan.c
@@ -0,0 +1,142 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+    This file is part of systemd.
+
+    Copyright 2014 Susant Sahani <susant at redhat.com>
+
+    systemd is free software; you can redistribute it and/or modify it
+    under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation; either version 2.1 of the License, or
+    (at your option) any later version.
+
+    systemd is distributed in the hope that it will be useful, but
+    WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <netinet/ether.h>
+#include <arpa/inet.h>
+#include <net/if.h>
+
+#include "sd-rtnl.h"
+#include "networkd-netdev-vxlan.h"
+#include "missing.h"
+
+static int netdev_vxlan_fill_message_create(NetDev *netdev, Link *link, sd_rtnl_message *m) {
+        int r;
+
+        assert(netdev);
+        assert(link);
+        assert(link->ifname);
+        assert(m);
+
+        r = sd_rtnl_message_append_string(m, IFLA_IFNAME, netdev->ifname);
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not append IFLA_IFNAME, attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        r = sd_rtnl_message_open_container(m, IFLA_LINKINFO);
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not append IFLA_LINKINFO attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        r = sd_rtnl_message_open_container_union(m, IFLA_INFO_DATA, "vxlan");
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not append IFLA_INFO_DATA attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        if (netdev->vlanid <= VXLAN_VID_MAX) {
+                r = sd_rtnl_message_append_u32(m, IFLA_VXLAN_ID, netdev->vxlanid);
+                if (r < 0) {
+                        log_error_netdev(netdev,
+                                         "Could not append IFLA_VXLAN_ID attribute: %s",
+                                         strerror(-r));
+                        return r;
+                }
+        }
+
+        r = sd_rtnl_message_append_in_addr(m, IFLA_VXLAN_GROUP, &netdev->group.in);
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not append IFLA_VXLAN_GROUP attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        r = sd_rtnl_message_append_u32(m, IFLA_VXLAN_LINK, link->ifindex);
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not append IFLA_VXLAN_LINK attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        if(netdev->ttl) {
+                r = sd_rtnl_message_append_u8(m, IFLA_VXLAN_TTL, netdev->ttl);
+                if (r < 0) {
+                        log_error_netdev(netdev,
+                                         "Could not append IFLA_VXLAN_TTL attribute: %s",
+                                         strerror(-r));
+                        return r;
+                }
+        }
+
+        if(netdev->tos) {
+                r = sd_rtnl_message_append_u8(m, IFLA_VXLAN_TOS, netdev->tos);
+                if (r < 0) {
+                        log_error_netdev(netdev,
+                                         "Could not append IFLA_VXLAN_TOS attribute: %s",
+                                         strerror(-r));
+                        return r;
+                }
+        }
+
+        r = sd_rtnl_message_append_u8(m, IFLA_VXLAN_LEARNING, netdev->learning);
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not append IFLA_VXLAN_LEARNING attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        r = sd_rtnl_message_close_container(m);
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not append IFLA_LINKINFO attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        return r;
+}
+
+static int netdev_vxlan_verify(NetDev *netdev, const char *filename) {
+        assert(netdev);
+        assert(filename);
+
+        if (netdev->vxlanid > VXLAN_VID_MAX) {
+                log_warning("VXLAN without valid Id configured in %s. Ignoring", filename);
+                return -EINVAL;
+        }
+
+        return 0;
+}
+
+const NetDevVTable vxlan_vtable = {
+        .fill_message_create_on_link = netdev_vxlan_fill_message_create,
+        .config_verify = netdev_vxlan_verify,
+};
diff --git a/src/network/networkd-netdev-vxlan.h b/src/network/networkd-netdev-vxlan.h
new file mode 100644
index 0000000..a2de271
--- /dev/null
+++ b/src/network/networkd-netdev-vxlan.h
@@ -0,0 +1,28 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+  This file is part of systemd.
+
+  Copyright 2014 Tom Gundersen <teg at jklm.no>
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#pragma once
+
+#include "networkd-netdev.h"
+
+#define VXLAN_VID_MAX (1u << 24) - 1
+
+extern const NetDevVTable vxlan_vtable;
diff --git a/src/network/networkd-netdev.c b/src/network/networkd-netdev.c
index ac47c03..a978317 100644
--- a/src/network/networkd-netdev.c
+++ b/src/network/networkd-netdev.c
@@ -21,7 +21,16 @@
 
 #include <net/if.h>
 
-#include "networkd.h"
+#include "networkd-netdev.h"
+#include "networkd-netdev-bridge.h"
+#include "networkd-netdev-bond.h"
+#include "networkd-netdev-vlan.h"
+#include "networkd-netdev-macvlan.h"
+#include "networkd-netdev-vxlan.h"
+#include "networkd-netdev-tunnel.h"
+#include "networkd-netdev-veth.h"
+#include "networkd-netdev-dummy.h"
+#include "networkd-netdev-tuntap.h"
 #include "network-internal.h"
 #include "path-util.h"
 #include "conf-files.h"
@@ -29,6 +38,22 @@
 #include "list.h"
 #include "siphash24.h"
 
+const NetDevVTable * const netdev_vtable[_NETDEV_KIND_MAX] = {
+        [NETDEV_KIND_BRIDGE] = &bridge_vtable,
+        [NETDEV_KIND_BOND] = &bond_vtable,
+        [NETDEV_KIND_VLAN] = &vlan_vtable,
+        [NETDEV_KIND_MACVLAN] = &macvlan_vtable,
+        [NETDEV_KIND_VXLAN] = &vxlan_vtable,
+        [NETDEV_KIND_IPIP] = &ipip_vtable,
+        [NETDEV_KIND_GRE] = &gre_vtable,
+        [NETDEV_KIND_SIT] = &sit_vtable,
+        [NETDEV_KIND_VTI] = &vti_vtable,
+        [NETDEV_KIND_VETH] = &veth_vtable,
+        [NETDEV_KIND_DUMMY] = &dummy_vtable,
+        [NETDEV_KIND_TUN] = &tun_vtable,
+        [NETDEV_KIND_TAP] = &tap_vtable,
+};
+
 static const char* const netdev_kind_table[_NETDEV_KIND_MAX] = {
         [NETDEV_KIND_BRIDGE] = "bridge",
         [NETDEV_KIND_BOND] = "bond",
@@ -246,7 +271,7 @@ static int netdev_create_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userda
         return 1;
 }
 
-static int netdev_enslave(NetDev *netdev, Link *link, sd_rtnl_message_handler_t callback) {
+int netdev_enslave(NetDev *netdev, Link *link, sd_rtnl_message_handler_t callback) {
         int r;
 
         assert(netdev);
@@ -276,27 +301,39 @@ static int netdev_enslave(NetDev *netdev, Link *link, sd_rtnl_message_handler_t
 
 /* the callback must be called, possibly after a timeout, as otherwise the Link will hang */
 int netdev_join(NetDev *netdev, Link *link, sd_rtnl_message_handler_t callback) {
+        int r;
 
         assert(netdev);
+        assert(netdev->manager);
+        assert(netdev->manager->rtnl);
+        assert(NETDEV_VTABLE(netdev));
 
-        switch(netdev->kind) {
-        case NETDEV_KIND_VLAN:
-                return netdev_create_vlan(netdev, link, callback);
-        case NETDEV_KIND_MACVLAN:
-                return netdev_create_macvlan(netdev, link, callback);
-        case NETDEV_KIND_VXLAN:
-                return netdev_create_vxlan(netdev, link, callback);
-        case NETDEV_KIND_IPIP:
-        case NETDEV_KIND_GRE:
-        case NETDEV_KIND_SIT:
-        case NETDEV_KIND_VTI:
-                return netdev_create_tunnel(netdev, link, callback);
-        case NETDEV_KIND_BRIDGE:
-        case NETDEV_KIND_BOND:
-                return netdev_enslave(netdev, link, callback);
-        default:
-                assert_not_reached("Enslaving by invalid netdev kind");
-        }
+        if (NETDEV_VTABLE(netdev)->fill_message_create_on_link) {
+                _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
+
+                r = sd_rtnl_message_new_link(netdev->manager->rtnl, &req,
+                                             RTM_NEWLINK, 0);
+                if (r < 0) {
+                        log_error_netdev(netdev,
+                                         "Could not allocate RTM_SETLINK message: %s",
+                                         strerror(-r));
+                        return r;
+                }
+
+                NETDEV_VTABLE(netdev)->fill_message_create_on_link(netdev, link, req);
+
+                r = sd_rtnl_call_async(netdev->manager->rtnl, req, callback, link, 0, NULL);
+                if (r < 0) {
+                        log_error_netdev(netdev,
+                                         "Could not send rtnetlink message: %s", strerror(-r));
+                        return r;
+                }
+
+                link_ref(link);
+        } else if (NETDEV_VTABLE(netdev)->enslave) {
+                return NETDEV_VTABLE(netdev)->enslave(netdev, link, callback);
+        } else
+                assert_not_reached("Joining link to netdev of invalid kind");
 
         return 0;
 }
@@ -406,7 +443,7 @@ int netdev_set_ifindex(NetDev *netdev, sd_rtnl_message *message) {
 
 #define HASH_KEY SD_ID128_MAKE(52,e1,45,bd,00,6f,29,96,21,c6,30,6d,83,71,04,48)
 
-static int netdev_get_mac(const char *ifname, struct ether_addr **ret) {
+int netdev_get_mac(const char *ifname, struct ether_addr **ret) {
         _cleanup_free_ struct ether_addr *mac = NULL;
         uint8_t result[8];
         size_t l, sz;
@@ -502,63 +539,16 @@ static int netdev_load_one(Manager *manager, const char *filename) {
                              NULL, NULL, NULL, NULL, NULL, NULL) <= 0)
                 return 0;
 
-        /* verify configuration */
-        switch (netdev->kind) {
-        case _NETDEV_KIND_INVALID:
-                log_warning("NetDev without Kind configured in %s. Ignoring", filename);
+        if (!NETDEV_VTABLE(netdev)) {
+                log_warning("NetDev with invalid Kind configured in %s. Igonring", filename);
                 return 0;
+        }
 
-        case NETDEV_KIND_VLAN:
-                if (netdev->vlanid > VLANID_MAX) {
-                        log_warning("VLAN without valid Id configured in %s. Ignoring", filename);
-                        return 0;
-                }
-                break;
-
-        case NETDEV_KIND_VXLAN:
-                if (netdev->vxlanid > VXLAN_VID_MAX) {
-                        log_warning("VXLAN without valid Id configured in %s. Ignoring", filename);
-                        return 0;
-                }
-                break;
-
-        case NETDEV_KIND_IPIP:
-        case NETDEV_KIND_GRE:
-        case NETDEV_KIND_SIT:
-        case NETDEV_KIND_VTI:
-                if (netdev->local.in.s_addr == INADDR_ANY) {
-                        log_warning("Tunnel without local address configured in %s. Ignoring", filename);
-                        return 0;
-                }
-                if (netdev->remote.in.s_addr == INADDR_ANY) {
-                        log_warning("Tunnel without remote address configured in %s. Ignoring", filename);
-                        return 0;
-                }
-                if (netdev->family != AF_INET) {
-                        log_warning("Tunnel with invalid address family configured in %s. Ignoring", filename);
-                        return 0;
-                }
-                break;
-
-        case NETDEV_KIND_VETH:
-                if (!netdev->ifname_peer) {
-                        log_warning("Veth NetDev without peer name configured "
-                                    "in %s. Ignoring", filename);
+        /* verify configuration */
+        if (NETDEV_VTABLE(netdev)->config_verify) {
+                r = NETDEV_VTABLE(netdev)->config_verify(netdev, filename);
+                if (r < 0)
                         return 0;
-                }
-
-                if (!netdev->mac_peer) {
-                        r = netdev_get_mac(netdev->ifname_peer, &netdev->mac_peer);
-                        if (r < 0) {
-                                log_error("Failed to generate predictable MAC address for %s",
-                                          netdev->ifname_peer);
-                                return r;
-                        }
-                }
-                break;
-
-        default:
-                break;
         }
 
         if (!netdev->ifname) {
@@ -604,36 +594,42 @@ static int netdev_load_one(Manager *manager, const char *filename) {
 
         LIST_HEAD_INIT(netdev->callbacks);
 
+        log_debug_netdev(netdev, "loaded %s", netdev_kind_to_string(netdev->kind));
+
         /* create netdev */
-        switch (netdev->kind) {
-        case NETDEV_KIND_VETH:
-                r = netdev_create_veth(netdev, netdev_create_handler);
-                if (r < 0)
+        if (NETDEV_VTABLE(netdev)->fill_message_create) {
+                _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
+
+                r = sd_rtnl_message_new_link(netdev->manager->rtnl, &m, RTM_NEWLINK, 0);
+                if (r < 0) {
+                        log_error_netdev(netdev,
+                                         "Could not allocate RTM_NEWLINK message: %s",
+                                         strerror(-r));
                         return r;
+                }
 
-                break;
-        case NETDEV_KIND_DUMMY:
-                r = netdev_create_dummy(netdev, netdev_create_handler);
+                r = NETDEV_VTABLE(netdev)->fill_message_create(netdev, m);
                 if (r < 0)
                         return r;
 
-                break;
-        case NETDEV_KIND_BRIDGE:
-                r = netdev_create_bridge(netdev, netdev_create_handler);
-                if (r < 0)
+                r = sd_rtnl_call_async(netdev->manager->rtnl, m, netdev_create_handler, netdev, 0, NULL);
+                if (r < 0) {
+                        log_error_netdev(netdev,
+                                         "Could not send rtnetlink message: %s", strerror(-r));
                         return r;
-                break;
-        case NETDEV_KIND_BOND:
-                r = netdev_create_bond(netdev, netdev_create_handler);
+                }
+
+                netdev_ref(netdev);
+
+                log_debug_netdev(netdev, "creating");
+
+                netdev->state = NETDEV_STATE_CREATING;
+        } else if (NETDEV_VTABLE(netdev)->create) {
+                r = NETDEV_VTABLE(netdev)->create(netdev);
                 if (r < 0)
                         return r;
-                break;
-        default:
-                break;
         }
 
-        log_debug_netdev(netdev, "loaded %s", netdev_kind_to_string(netdev->kind));
-
         netdev = NULL;
 
         return 0;
diff --git a/src/network/networkd-netdev.h b/src/network/networkd-netdev.h
new file mode 100644
index 0000000..a523522
--- /dev/null
+++ b/src/network/networkd-netdev.h
@@ -0,0 +1,170 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+  This file is part of systemd.
+
+  Copyright 2013 Tom Gundersen <teg at jklm.no>
+
+  systemd is free software; you can redistribute it and/or modify it
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
+  (at your option) any later version.
+
+  systemd is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#pragma once
+
+#include "networkd.h"
+#include "hashmap.h"
+#include "list.h"
+#include "set.h"
+#include "condition-util.h"
+#include "in-addr-util.h"
+
+typedef struct NetDevVTable NetDevVTable;
+
+typedef struct netdev_join_callback netdev_join_callback;
+
+struct netdev_join_callback {
+        sd_rtnl_message_handler_t callback;
+        Link *link;
+
+        LIST_FIELDS(netdev_join_callback, callbacks);
+};
+
+typedef enum NetDevKind {
+        NETDEV_KIND_BRIDGE,
+        NETDEV_KIND_BOND,
+        NETDEV_KIND_VLAN,
+        NETDEV_KIND_MACVLAN,
+        NETDEV_KIND_VXLAN,
+        NETDEV_KIND_IPIP,
+        NETDEV_KIND_GRE,
+        NETDEV_KIND_SIT,
+        NETDEV_KIND_VETH,
+        NETDEV_KIND_VTI,
+        NETDEV_KIND_DUMMY,
+        NETDEV_KIND_TUN,
+        NETDEV_KIND_TAP,
+        _NETDEV_KIND_MAX,
+        _NETDEV_KIND_INVALID = -1
+} NetDevKind;
+
+typedef enum NetDevState {
+        NETDEV_STATE_FAILED,
+        NETDEV_STATE_CREATING,
+        NETDEV_STATE_READY,
+        NETDEV_STATE_LINGER,
+        _NETDEV_STATE_MAX,
+        _NETDEV_STATE_INVALID = -1,
+} NetDevState;
+
+struct NetDev {
+        Manager *manager;
+
+        int n_ref;
+
+        char *filename;
+
+        Condition *match_host;
+        Condition *match_virt;
+        Condition *match_kernel;
+        Condition *match_arch;
+
+        char *description;
+        char *ifname;
+        char *ifname_peer;
+        char *user_name;
+        char *group_name;
+        size_t mtu;
+        struct ether_addr *mac;
+        struct ether_addr *mac_peer;
+        NetDevKind kind;
+
+        uint64_t vlanid;
+        uint64_t vxlanid;
+        int32_t macvlan_mode;
+        int32_t bond_mode;
+
+        int ifindex;
+        NetDevState state;
+
+        bool tunnel_pmtudisc;
+        bool learning;
+        bool one_queue;
+        bool multi_queue;
+        bool packet_info;
+
+        unsigned ttl;
+        unsigned tos;
+        unsigned char family;
+        union in_addr_union local;
+        union in_addr_union remote;
+        union in_addr_union group;
+
+        LIST_HEAD(netdev_join_callback, callbacks);
+};
+
+struct NetDevVTable {
+        /* fill in message to create netdev */
+        int (*fill_message_create)(NetDev *netdev, sd_rtnl_message *message);
+
+        /* fill in message to create netdev on top of a given link */
+        int (*fill_message_create_on_link)(NetDev *netdev, Link *link, sd_rtnl_message *message);
+
+        /* fill in message to enslave link by netdev */
+        int (*enslave)(NetDev *netdev, Link *link, sd_rtnl_message_handler_t callback);
+
+        /* create netdev, if not done via rtnl */
+        int (*create)(NetDev *netdev);
+
+        /* verify that compulsory configuration options were specified */
+        int (*config_verify)(NetDev *netdev, const char *filename);
+};
+
+extern const NetDevVTable * const netdev_vtable[_NETDEV_KIND_MAX];
+
+#define NETDEV_VTABLE(n) netdev_vtable[(n)->kind]
+
+int netdev_load(Manager *manager);
+void netdev_drop(NetDev *netdev);
+
+NetDev *netdev_unref(NetDev *netdev);
+NetDev *netdev_ref(NetDev *netdev);
+
+DEFINE_TRIVIAL_CLEANUP_FUNC(NetDev*, netdev_unref);
+#define _cleanup_netdev_unref_ _cleanup_(netdev_unrefp)
+
+int netdev_get(Manager *manager, const char *name, NetDev **ret);
+int netdev_set_ifindex(NetDev *netdev, sd_rtnl_message *newlink);
+int netdev_enslave(NetDev *netdev, Link *link, sd_rtnl_message_handler_t callback);
+int netdev_get_mac(const char *ifname, struct ether_addr **ret);
+int netdev_join(NetDev *netdev, Link *link, sd_rtnl_message_handler_t cb);
+
+const char *netdev_kind_to_string(NetDevKind d) _const_;
+NetDevKind netdev_kind_from_string(const char *d) _pure_;
+
+int config_parse_netdev_kind(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+
+/* gperf */
+const struct ConfigPerfItem* network_netdev_gperf_lookup(const char *key, unsigned length);
+
+/* Macros which append INTERFACE= to the message */
+
+#define log_full_netdev(level, netdev, fmt, ...) log_meta_object(level, __FILE__, __LINE__, __func__, "INTERFACE=", netdev->ifname, "%-*s: " fmt, IFNAMSIZ, netdev->ifname, ##__VA_ARGS__)
+#define log_debug_netdev(netdev, ...)       log_full_netdev(LOG_DEBUG, netdev, ##__VA_ARGS__)
+#define log_info_netdev(netdev, ...)        log_full_netdev(LOG_INFO, netdev, ##__VA_ARGS__)
+#define log_notice_netdev(netdev, ...)      log_full_netdev(LOG_NOTICE, netdev, ##__VA_ARGS__)
+#define log_warning_netdev(netdev, ...)     log_full_netdev(LOG_WARNING, netdev,## __VA_ARGS__)
+#define log_error_netdev(netdev, ...)       log_full_netdev(LOG_ERR, netdev, ##__VA_ARGS__)
+
+#define log_struct_netdev(level, netdev, ...) log_struct(level, "INTERFACE=%s", netdev->ifname, __VA_ARGS__)
+
+#define NETDEV(netdev) "INTERFACE=%s", netdev->ifname
diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c
index c108ad2..0375194 100644
--- a/src/network/networkd-network.c
+++ b/src/network/networkd-network.c
@@ -23,6 +23,7 @@
 #include <net/if.h>
 
 #include "networkd.h"
+#include "networkd-netdev.h"
 #include "network-internal.h"
 #include "path-util.h"
 #include "conf-files.h"
diff --git a/src/network/networkd-tunnel.c b/src/network/networkd-tunnel.c
deleted file mode 100644
index 5a244f6..0000000
--- a/src/network/networkd-tunnel.c
+++ /dev/null
@@ -1,569 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
-    This file is part of systemd.
-
-    Copyright 2014 Susant Sahani <susant at redhat.com>
-
-    systemd is free software; you can redistribute it and/or modify it
-    under the terms of the GNU Lesser General Public License as published by
-    the Free Software Foundation; either version 2.1 of the License, or
-    (at your option) any later version.
-
-    systemd is distributed in the hope that it will be useful, but
-    WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-    Lesser General Public License for more details.
-
-    You should have received a copy of the GNU Lesser General Public License
-    along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <netinet/ether.h>
-#include <arpa/inet.h>
-#include <net/if.h>
-#include <linux/ip.h>
-#include <linux/if_tunnel.h>
-
-#include "sd-rtnl.h"
-#include "networkd.h"
-#include "network-internal.h"
-#include "util.h"
-#include "missing.h"
-#include "conf-parser.h"
-
-
-static int netdev_fill_ipip_rtnl_message(Link *link, sd_rtnl_message *m) {
-        NetDev *netdev;
-        int r;
-
-        assert(link);
-        assert(link->network);
-        assert(link->network->tunnel);
-        assert(m);
-
-        netdev = link->network->tunnel;
-
-        assert(netdev->family == AF_INET);
-
-        r = sd_rtnl_message_append_string(m, IFLA_IFNAME, netdev->ifname);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not append IFLA_IFNAME, attribute: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        if(netdev->mtu) {
-                r = sd_rtnl_message_append_u32(m, IFLA_MTU, netdev->mtu);
-                if (r < 0) {
-                        log_error_netdev(netdev,
-                                         "Could not append IFLA_MTU attribute: %s",
-                                         strerror(-r));
-                        return r;
-                }
-        }
-
-        if (netdev->mac) {
-                r = sd_rtnl_message_append_ether_addr(m, IFLA_ADDRESS, netdev->mac);
-                if (r < 0) {
-                        log_error_netdev(netdev,
-                                         "Colud not append IFLA_ADDRESS attribute: %s",
-                                         strerror(-r));
-                    return r;
-                }
-        }
-
-        r = sd_rtnl_message_open_container(m, IFLA_LINKINFO);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not append IFLA_LINKINFO attribute: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        r = sd_rtnl_message_open_container_union(m, IFLA_INFO_DATA,
-                                                 netdev_kind_to_string(netdev->kind));
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not append IFLA_INFO_DATA attribute: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        r = sd_rtnl_message_append_u32(m, IFLA_IPTUN_LINK, link->ifindex);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not append IFLA_IPTUN_LINK attribute: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        r = sd_rtnl_message_append_in_addr(m, IFLA_IPTUN_LOCAL, &netdev->local.in);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not append IFLA_IPTUN_LOCAL attribute: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        r = sd_rtnl_message_append_in_addr(m, IFLA_IPTUN_REMOTE, &netdev->remote.in);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not append IFLA_IPTUN_REMOTE attribute: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        r = sd_rtnl_message_append_u8(m, IFLA_IPTUN_TTL, netdev->ttl);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not append IFLA_IPTUN_TTL  attribute: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        r = sd_rtnl_message_close_container(m);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not append IFLA_INFO_DATA attribute: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        r = sd_rtnl_message_close_container(m);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not append IFLA_LINKINFO attribute: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        return r;
-}
-
-static int netdev_fill_sit_rtnl_message(Link *link, sd_rtnl_message *m) {
-        NetDev *netdev;
-        int r;
-
-        assert(link);
-        assert(link->network);
-        assert(link->network->tunnel);
-        assert(m);
-
-        netdev = link->network->tunnel;
-
-        assert(netdev->family == AF_INET);
-
-        r = sd_rtnl_message_append_string(m, IFLA_IFNAME, netdev->ifname);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not append IFLA_IFNAME, attribute: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        if(netdev->mtu) {
-                r = sd_rtnl_message_append_u32(m, IFLA_MTU, netdev->mtu);
-                if (r < 0) {
-                        log_error_netdev(netdev,
-                                         "Could not append IFLA_MTU attribute: %s",
-                                         strerror(-r));
-                        return r;
-                }
-        }
-
-        if (netdev->mac) {
-                r = sd_rtnl_message_append_ether_addr(m, IFLA_ADDRESS, netdev->mac);
-                if (r < 0) {
-                        log_error_netdev(netdev,
-                                         "Colud not append IFLA_ADDRESS attribute: %s",
-                                         strerror(-r));
-                    return r;
-                }
-        }
-
-        r = sd_rtnl_message_open_container(m, IFLA_LINKINFO);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not append IFLA_LINKINFO attribute: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        r = sd_rtnl_message_open_container_union(m, IFLA_INFO_DATA,
-                                                 netdev_kind_to_string(netdev->kind));
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not append IFLA_INFO_DATA attribute: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        r = sd_rtnl_message_append_u32(m, IFLA_IPTUN_LINK, link->ifindex);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not append IFLA_IPTUN_LINK attribute: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        r = sd_rtnl_message_append_in_addr(m, IFLA_IPTUN_LOCAL, &netdev->local.in);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not append IFLA_IPTUN_LOCAL attribute: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        r = sd_rtnl_message_append_in_addr(m, IFLA_IPTUN_REMOTE, &netdev->remote.in);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not append IFLA_IPTUN_REMOTE attribute: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        r = sd_rtnl_message_append_u8(m, IFLA_IPTUN_TOS, netdev->tos);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not append IFLA_IPTUN_TOS attribute: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        r = sd_rtnl_message_append_u8(m, IFLA_IPTUN_PMTUDISC, netdev->tunnel_pmtudisc);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not append IFLA_IPTUN_PMTUDISC attribute: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        r = sd_rtnl_message_close_container(m);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not append IFLA_INFO_DATA attribute: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        r = sd_rtnl_message_close_container(m);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not append IFLA_LINKINFO attribute: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        return r;
-}
-
-static int netdev_fill_ipgre_rtnl_message(Link *link, sd_rtnl_message *m) {
-        NetDev *netdev;
-        int r;
-
-        assert(link);
-        assert(link->network);
-        assert(link->network->tunnel);
-        assert(m);
-
-        netdev = link->network->tunnel;
-
-        assert(netdev->family == AF_INET);
-
-        r = sd_rtnl_message_append_string(m, IFLA_IFNAME, netdev->ifname);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not append IFLA_IFNAME, attribute: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        if(netdev->mtu) {
-                r = sd_rtnl_message_append_u32(m, IFLA_MTU, netdev->mtu);
-                if (r < 0) {
-                        log_error_netdev(netdev,
-                                         "Could not append IFLA_MTU attribute: %s",
-                                         strerror(-r));
-                        return r;
-                }
-        }
-
-        if (netdev->mac) {
-                r = sd_rtnl_message_append_ether_addr(m, IFLA_ADDRESS, netdev->mac);
-                if (r < 0) {
-                        log_error_netdev(netdev,
-                                         "Colud not append IFLA_ADDRESS attribute: %s",
-                                         strerror(-r));
-                    return r;
-                }
-        }
-
-        r = sd_rtnl_message_open_container(m, IFLA_LINKINFO);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not append IFLA_LINKINFO attribute: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        r = sd_rtnl_message_open_container_union(m, IFLA_INFO_DATA,
-                                                 netdev_kind_to_string(netdev->kind));
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not append IFLA_INFO_DATA attribute: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        r = sd_rtnl_message_append_u32(m, IFLA_GRE_LINK, link->ifindex);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not append IFLA_GRE_LINK attribute: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        r = sd_rtnl_message_append_in_addr(m, IFLA_GRE_LOCAL, &netdev->local.in);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not append IFLA_GRE_LOCAL attribute: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        r = sd_rtnl_message_append_in_addr(m, IFLA_GRE_REMOTE, &netdev->remote.in);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not append IFLA_GRE_REMOTE attribute: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        r = sd_rtnl_message_append_u8(m, IFLA_GRE_TTL, netdev->ttl);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not append IFLA_GRE_TTL attribute: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        r = sd_rtnl_message_append_u8(m, IFLA_GRE_TOS, netdev->tos);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not append IFLA_GRE_TOS attribute: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        r = sd_rtnl_message_close_container(m);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not append IFLA_INFO_DATA attribute: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        r = sd_rtnl_message_close_container(m);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not append IFLA_LINKINFO attribute: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        return r;
-}
-
-static int netdev_fill_vti_rtnl_message(Link *link, sd_rtnl_message *m) {
-        NetDev *netdev;
-        int r;
-
-        assert(link);
-        assert(link->network);
-        assert(link->network->tunnel);
-        assert(m);
-
-        netdev = link->network->tunnel;
-
-        assert(netdev->family == AF_INET);
-
-        r = sd_rtnl_message_append_string(m, IFLA_IFNAME, netdev->ifname);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not append IFLA_IFNAME, attribute: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        if(netdev->mtu) {
-                r = sd_rtnl_message_append_u32(m, IFLA_MTU, netdev->mtu);
-                if (r < 0) {
-                        log_error_netdev(netdev,
-                                         "Could not append IFLA_MTU attribute: %s",
-                                         strerror(-r));
-                        return r;
-                }
-        }
-
-        if (netdev->mac) {
-                r = sd_rtnl_message_append_ether_addr(m, IFLA_ADDRESS, netdev->mac);
-                if (r < 0) {
-                        log_error_netdev(netdev,
-                                         "Colud not append IFLA_ADDRESS attribute: %s",
-                                         strerror(-r));
-                    return r;
-                }
-        }
-
-        r = sd_rtnl_message_open_container(m, IFLA_LINKINFO);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not append IFLA_LINKINFO attribute: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        r = sd_rtnl_message_open_container_union(m, IFLA_INFO_DATA,
-                                                 netdev_kind_to_string(netdev->kind));
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not append IFLA_INFO_DATA attribute: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        r = sd_rtnl_message_append_u32(m, IFLA_VTI_LINK, link->ifindex);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not append IFLA_IPTUN_LINK attribute: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        r = sd_rtnl_message_append_in_addr(m, IFLA_VTI_LOCAL, &netdev->local.in);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not append IFLA_IPTUN_LOCAL attribute: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        r = sd_rtnl_message_append_in_addr(m, IFLA_VTI_REMOTE, &netdev->remote.in);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not append IFLA_IPTUN_REMOTE attribute: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        r = sd_rtnl_message_close_container(m);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not append IFLA_INFO_DATA attribute: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        r = sd_rtnl_message_close_container(m);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not append IFLA_LINKINFO attribute: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        return r;
-}
-
-int netdev_create_tunnel(NetDev *netdev, Link *link, sd_rtnl_message_handler_t callback) {
-        _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
-        int r;
-
-        assert(netdev);
-        assert(netdev->ifname);
-        assert(netdev->manager);
-        assert(netdev->manager->rtnl);
-        assert(link);
-        assert(link->network);
-        assert(link->network->tunnel == netdev);
-
-        r = sd_rtnl_message_new_link(netdev->manager->rtnl, &m, RTM_NEWLINK, 0);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not allocate RTM_NEWLINK message: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        switch(netdev->kind) {
-        case NETDEV_KIND_IPIP:
-                r = netdev_fill_ipip_rtnl_message(link, m);
-                if(r < 0)
-                        return r;
-                break;
-        case NETDEV_KIND_SIT:
-                r = netdev_fill_sit_rtnl_message(link, m);
-                if(r < 0)
-                        return r;
-                break;
-        case NETDEV_KIND_VTI:
-                netdev_fill_vti_rtnl_message(link, m);
-                if(r < 0)
-                        return r;
-                break;
-        case NETDEV_KIND_GRE:
-                r = netdev_fill_ipgre_rtnl_message(link, m);
-                if(r < 0)
-                        return r;
-                break;
-        default:
-                return -ENOTSUP;
-        }
-
-        r = sd_rtnl_call_async(netdev->manager->rtnl, m, callback, link, 0, NULL);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not send rtnetlink message: %s", strerror(-r));
-                return r;
-        }
-
-        link_ref(link);
-
-        log_debug_netdev(netdev, "Creating tunnel netdev: %s",
-                         netdev_kind_to_string(netdev->kind));
-
-        netdev->state = NETDEV_STATE_CREATING;
-
-        return 0;
-}
-
-int config_parse_tunnel_address(const char *unit,
-                                const char *filename,
-                                unsigned line,
-                                const char *section,
-                                unsigned section_line,
-                                const char *lvalue,
-                                int ltype,
-                                const char *rvalue,
-                                void *data,
-                                void *userdata) {
-        NetDev *n = userdata;
-        union in_addr_union *addr = data;
-        int r;
-
-        assert(filename);
-        assert(lvalue);
-        assert(rvalue);
-        assert(data);
-
-        r = net_parse_inaddr(rvalue, &n->family, addr);
-        if (r < 0) {
-                log_syntax(unit, LOG_ERR, filename, line, EINVAL,
-                           "Tunnel address is invalid, ignoring assignment: %s", rvalue);
-                return 0;
-        }
-
-        return 0;
-}
diff --git a/src/network/networkd-tuntap.c b/src/network/networkd-tuntap.c
deleted file mode 100644
index ae2d5c1..0000000
--- a/src/network/networkd-tuntap.c
+++ /dev/null
@@ -1,155 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
-    This file is part of systemd.
-
-    Copyright 2014 Susant Sahani <susant at redhat.com>
-
-    systemd is free software; you can redistribute it and/or modify it
-    under the terms of the GNU Lesser General Public License as published by
-    the Free Software Foundation; either version 2.1 of the License, or
-    (at your option) any later version.
-
-    systemd is distributed in the hope that it will be useful, but
-    WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-    Lesser General Public License for more details.
-
-    You should have received a copy of the GNU Lesser General Public License
-    along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <sys/ioctl.h>
-#include <net/if.h>
-#include <linux/if_tun.h>
-
-#include "networkd.h"
-
-#define TUN_DEV "/dev/net/tun"
-
-
-static int netdev_fill_tuntap_message(NetDev *netdev, struct ifreq *ifr) {
-
-        assert(netdev);
-        assert(ifr);
-
-        memset(ifr, 0, sizeof(*ifr));
-
-        if (netdev->kind == NETDEV_KIND_TAP)
-                ifr->ifr_flags |= IFF_TAP;
-        else
-                ifr->ifr_flags |= IFF_TUN;
-
-        if (!netdev->packet_info)
-                ifr->ifr_flags |= IFF_NO_PI;
-
-        if (netdev->one_queue)
-                ifr->ifr_flags |= IFF_ONE_QUEUE;
-
-        if (netdev->multi_queue)
-                ifr->ifr_flags |= IFF_MULTI_QUEUE;
-
-        strncpy(ifr->ifr_name, netdev->ifname, IFNAMSIZ-1);
-
-        return 0;
-}
-
-static int netdev_tuntap_add(NetDev *netdev, struct ifreq *ifr) {
-        _cleanup_close_ int fd;
-        const char *user;
-        const char *group;
-        uid_t uid;
-        gid_t gid;
-        int r = 0;
-
-        fd = open(TUN_DEV, O_RDWR);
-        if (fd < 0) {
-                log_error_netdev(netdev,
-                                 "Failed to open tun dev: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        r = ioctl(fd, TUNSETIFF, ifr);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "TUNSETIFF failed on tun dev: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        if(netdev->user_name) {
-
-                user = netdev->user_name;
-
-                r = get_user_creds(&user, &uid, NULL, NULL, NULL);
-                if (r < 0) {
-                        log_error("Cannot resolve user name %s: %s",
-                                  netdev->user_name, strerror(-r));
-                        return 0;
-                }
-
-                r = ioctl(fd, TUNSETOWNER, uid);
-                if ( r < 0) {
-                        log_error_netdev(netdev,
-                                         "TUNSETOWNER failed on tun dev: %s",
-                                         strerror(-r));
-                }
-        }
-
-        if(netdev->group_name) {
-
-                group = netdev->group_name;
-
-                r = get_group_creds(&group, &gid);
-                if (r < 0) {
-                        log_error("Cannot resolve group name %s: %s",
-                                  netdev->group_name, strerror(-r));
-                        return 0;
-                }
-
-                r = ioctl(fd, TUNSETGROUP, gid);
-                if( r < 0) {
-                        log_error_netdev(netdev,
-                                         "TUNSETGROUP failed on tun dev: %s",
-                                         strerror(-r));
-                        return r;
-                }
-
-        }
-
-        r = ioctl(fd, TUNSETPERSIST, 1);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "TUNSETPERSIST failed on tun dev: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        return r;
-}
-
-int netdev_create_tuntap(NetDev *netdev) {
-        struct ifreq ifr;
-        int r;
-
-        assert(netdev);
-        assert(netdev->ifname);
-
-        switch(netdev->kind) {
-        case NETDEV_KIND_TUN:
-        case NETDEV_KIND_TAP:
-                break;
-        default:
-                return -ENOTSUP;
-        }
-
-        r = netdev_fill_tuntap_message(netdev, &ifr);
-        if(r < 0)
-                return r;
-
-        log_debug_netdev(netdev, "Creating tuntap netdev: %s",
-                         netdev_kind_to_string(netdev->kind));
-
-        return netdev_tuntap_add(netdev, &ifr);
-}
diff --git a/src/network/networkd-veth.c b/src/network/networkd-veth.c
deleted file mode 100644
index 50a5b67..0000000
--- a/src/network/networkd-veth.c
+++ /dev/null
@@ -1,154 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
-    This file is part of systemd.
-
-    Copyright 2014 Susant Sahani <susant at redhat.com>
-
-    systemd is free software; you can redistribute it and/or modify it
-    under the terms of the GNU Lesser General Public License as published by
-    the Free Software Foundation; either version 2.1 of the License, or
-    (at your option) any later version.
-
-    systemd is distributed in the hope that it will be useful, but
-    WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-    Lesser General Public License for more details.
-
-    You should have received a copy of the GNU Lesser General Public License
-    along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <netinet/ether.h>
-#include <arpa/inet.h>
-#include <net/if.h>
-#include <linux/veth.h>
-
-#include "sd-rtnl.h"
-#include "networkd.h"
-
-
-static int netdev_fill_veth_rtnl_message(NetDev *netdev, sd_rtnl_message *m) {
-        int r;
-
-        assert(netdev);
-        assert(m);
-
-        r = sd_rtnl_message_append_string(m, IFLA_IFNAME, netdev->ifname);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not append IFLA_IFNAME, attribute: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        if (netdev->mac) {
-                r = sd_rtnl_message_append_ether_addr(m, IFLA_ADDRESS, netdev->mac);
-                if (r < 0) {
-                        log_error_netdev(netdev,
-                                         "Colud not append IFLA_ADDRESS attribute: %s",
-                                         strerror(-r));
-                    return r;
-                }
-        }
-
-        r = sd_rtnl_message_open_container(m, IFLA_LINKINFO);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not append IFLA_LINKINFO attribute: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        r = sd_rtnl_message_open_container_union(m, IFLA_INFO_DATA,
-                                                 netdev_kind_to_string(netdev->kind));
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not append IFLA_INFO_DATA attribute: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        r = sd_rtnl_message_open_container(m, VETH_INFO_PEER);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not append IFLA_IPTUN_LINK attribute: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        if (netdev->ifname_peer) {
-                r = sd_rtnl_message_append_string(m, IFLA_IFNAME, netdev->ifname_peer);
-                if (r < 0) {
-                        log_error("Failed to add netlink interface name: %s", strerror(-r));
-                        return r;
-                }
-        }
-
-        if (netdev->mac_peer) {
-                r = sd_rtnl_message_append_ether_addr(m, IFLA_ADDRESS, netdev->mac_peer);
-                if (r < 0) {
-                        log_error_netdev(netdev,
-                                         "Colud not append IFLA_ADDRESS attribute: %s",
-                                         strerror(-r));
-                    return r;
-                }
-        }
-
-        r = sd_rtnl_message_close_container(m);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not append IFLA_INFO_DATA attribute: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        r = sd_rtnl_message_close_container(m);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not append IFLA_LINKINFO attribute: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        return r;
-}
-
-int netdev_create_veth(NetDev *netdev, sd_rtnl_message_handler_t callback) {
-        _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
-        int r;
-
-        assert(netdev);
-        assert(netdev->ifname);
-        assert(netdev->manager);
-        assert(netdev->manager->rtnl);
-        assert(netdev->kind == NETDEV_KIND_VETH);
-
-        r = sd_rtnl_message_new_link(netdev->manager->rtnl, &m, RTM_NEWLINK, 0);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not allocate RTM_NEWLINK message: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        r = netdev_fill_veth_rtnl_message(netdev, m);
-        if(r < 0)
-                return r;
-
-        r = sd_rtnl_call_async(netdev->manager->rtnl, m, callback, netdev, 0, NULL);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not send rtnetlink message: %s", strerror(-r));
-                return r;
-        }
-
-        netdev_ref(netdev);
-
-        log_debug_netdev(netdev, "Creating veth netdev: %s",
-                         netdev_kind_to_string(netdev->kind));
-
-        netdev->state = NETDEV_STATE_CREATING;
-
-        return 0;
-}
diff --git a/src/network/networkd-vlan.c b/src/network/networkd-vlan.c
deleted file mode 100644
index 8727b9f..0000000
--- a/src/network/networkd-vlan.c
+++ /dev/null
@@ -1,149 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
-  This file is part of systemd.
-
-  Copyright 2013 Tom Gundersen <teg at jklm.no>
-
-  systemd is free software; you can redistribute it and/or modify it
-  under the terms of the GNU Lesser General Public License as published by
-  the Free Software Foundation; either version 2.1 of the License, or
-  (at your option) any later version.
-
-  systemd is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-  Lesser General Public License for more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <net/if.h>
-
-#include "networkd.h"
-#include "network-internal.h"
-#include "list.h"
-
-int netdev_create_vlan(NetDev *netdev, Link *link, sd_rtnl_message_handler_t callback) {
-        _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
-        const char *kind;
-        int r;
-
-        assert(netdev);
-        assert(netdev->kind == NETDEV_KIND_VLAN);
-        assert(link);
-        assert(callback);
-        assert(netdev->ifname);
-        assert(netdev->manager);
-        assert(netdev->manager->rtnl);
-
-        r = sd_rtnl_message_new_link(netdev->manager->rtnl, &req, RTM_NEWLINK, 0);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not allocate RTM_NEWLINK message: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        if (link) {
-                r = sd_rtnl_message_append_u32(req, IFLA_LINK, link->ifindex);
-                if (r < 0) {
-                        log_error_netdev(netdev,
-                                         "Could not append IFLA_LINK attribute: %s",
-                                         strerror(-r));
-                        return r;
-                }
-        }
-
-        r = sd_rtnl_message_append_string(req, IFLA_IFNAME, netdev->ifname);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not append IFLA_IFNAME attribute: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        if (netdev->mtu) {
-                r = sd_rtnl_message_append_u32(req, IFLA_MTU, netdev->mtu);
-                if (r < 0) {
-                        log_error_netdev(netdev,
-                                         "Could not append IFLA_MTU attribute: %s",
-                                         strerror(-r));
-                        return r;
-                }
-        }
-
-        if (netdev->mac) {
-                r = sd_rtnl_message_append_ether_addr(req, IFLA_ADDRESS, netdev->mac);
-                if (r < 0) {
-                        log_error_netdev(netdev,
-                                         "Colud not append IFLA_ADDRESS attribute: %s",
-                                         strerror(-r));
-                    return r;
-                }
-        }
-
-        r = sd_rtnl_message_open_container(req, IFLA_LINKINFO);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not open IFLA_LINKINFO container: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        kind = netdev_kind_to_string(netdev->kind);
-        if (!kind) {
-                log_error_netdev(netdev, "Invalid kind");
-                return -EINVAL;
-        }
-
-        r = sd_rtnl_message_open_container_union(req, IFLA_INFO_DATA, kind);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not open IFLA_INFO_DATA container: %s",
-                                  strerror(-r));
-                return r;
-        }
-
-        if (netdev->vlanid <= VLANID_MAX) {
-                r = sd_rtnl_message_append_u16(req, IFLA_VLAN_ID, netdev->vlanid);
-                if (r < 0) {
-                        log_error_netdev(netdev,
-                                         "Could not append IFLA_VLAN_ID attribute: %s",
-                                         strerror(-r));
-                        return r;
-                }
-        }
-
-        r = sd_rtnl_message_close_container(req);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not close IFLA_INFO_DATA container %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        r = sd_rtnl_message_close_container(req);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not close IFLA_LINKINFO container %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        r = sd_rtnl_call_async(netdev->manager->rtnl, req, callback, link, 0, NULL);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not send rtnetlink message: %s", strerror(-r));
-                return r;
-        }
-
-        link_ref(link);
-
-        log_debug_netdev(netdev, "creating netdev");
-
-        netdev->state = NETDEV_STATE_CREATING;
-
-        return 0;
-}
diff --git a/src/network/networkd-vxlan.c b/src/network/networkd-vxlan.c
deleted file mode 100644
index 1604594..0000000
--- a/src/network/networkd-vxlan.c
+++ /dev/null
@@ -1,165 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
-    This file is part of systemd.
-
-    Copyright 2014 Susant Sahani <susant at redhat.com>
-
-    systemd is free software; you can redistribute it and/or modify it
-    under the terms of the GNU Lesser General Public License as published by
-    the Free Software Foundation; either version 2.1 of the License, or
-    (at your option) any later version.
-
-    systemd is distributed in the hope that it will be useful, but
-    WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-    Lesser General Public License for more details.
-
-    You should have received a copy of the GNU Lesser General Public License
-    along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <netinet/ether.h>
-#include <arpa/inet.h>
-#include <net/if.h>
-
-#include "sd-rtnl.h"
-#include "networkd.h"
-#include "missing.h"
-
-
-static int netdev_fill_vxlan_rtnl_message(NetDev *netdev, Link *link, sd_rtnl_message *m) {
-        int r;
-
-        assert(link);
-        assert(link->network);
-        assert(m);
-
-        r = sd_rtnl_message_append_string(m, IFLA_IFNAME, netdev->ifname);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not append IFLA_IFNAME, attribute: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        r = sd_rtnl_message_open_container(m, IFLA_LINKINFO);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not append IFLA_LINKINFO attribute: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        r = sd_rtnl_message_open_container_union(m, IFLA_INFO_DATA,
-                                                 netdev_kind_to_string(netdev->kind));
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not append IFLA_INFO_DATA attribute: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        if (netdev->vlanid <= VXLAN_VID_MAX) {
-                r = sd_rtnl_message_append_u32(m, IFLA_VXLAN_ID, netdev->vxlanid);
-                if (r < 0) {
-                        log_error_netdev(netdev,
-                                         "Could not append IFLA_VXLAN_ID attribute: %s",
-                                         strerror(-r));
-                        return r;
-                }
-        }
-
-        r = sd_rtnl_message_append_in_addr(m, IFLA_VXLAN_GROUP, &netdev->group.in);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not append IFLA_VXLAN_GROUP attribute: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        r = sd_rtnl_message_append_u32(m, IFLA_VXLAN_LINK, link->ifindex);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not append IFLA_VXLAN_LINK attribute: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        if(netdev->ttl) {
-                r = sd_rtnl_message_append_u8(m, IFLA_VXLAN_TTL, netdev->ttl);
-                if (r < 0) {
-                        log_error_netdev(netdev,
-                                         "Could not append IFLA_VXLAN_TTL attribute: %s",
-                                         strerror(-r));
-                        return r;
-                }
-        }
-
-        if(netdev->tos) {
-                r = sd_rtnl_message_append_u8(m, IFLA_VXLAN_TOS, netdev->tos);
-                if (r < 0) {
-                        log_error_netdev(netdev,
-                                         "Could not append IFLA_VXLAN_TOS attribute: %s",
-                                         strerror(-r));
-                        return r;
-                }
-        }
-
-        r = sd_rtnl_message_append_u8(m, IFLA_VXLAN_LEARNING, netdev->learning);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not append IFLA_VXLAN_LEARNING attribute: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        r = sd_rtnl_message_close_container(m);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not append IFLA_LINKINFO attribute: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        return r;
-}
-
-int netdev_create_vxlan(NetDev *netdev, Link *link, sd_rtnl_message_handler_t callback) {
-        _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
-        int r;
-
-        assert(netdev);
-        assert(!(netdev->kind == NETDEV_KIND_VXLAN) || (link && callback));
-        assert(netdev->ifname);
-        assert(netdev->manager);
-        assert(netdev->manager->rtnl);
-
-        r = sd_rtnl_message_new_link(netdev->manager->rtnl, &m, RTM_NEWLINK, 0);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not allocate RTM_NEWLINK message: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        r = netdev_fill_vxlan_rtnl_message(netdev, link, m);
-        if(r < 0)
-                return r;
-
-        r = sd_rtnl_call_async(netdev->manager->rtnl, m, callback, link, 0, NULL);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not send rtnetlink message: %s", strerror(-r));
-                return r;
-        }
-
-        link_ref(link);
-
-        log_debug_netdev(netdev, "Creating vxlan netdev: %s",
-                         netdev_kind_to_string(netdev->kind));
-
-        netdev->state = NETDEV_STATE_CREATING;
-
-        return 0;
-}
diff --git a/src/network/networkd.h b/src/network/networkd.h
index d891177..3f0ef5d 100644
--- a/src/network/networkd.h
+++ b/src/network/networkd.h
@@ -41,7 +41,6 @@
 #include "in-addr-util.h"
 
 #define CACHE_INFO_INFINITY_LIFE_TIME 0xFFFFFFFFU
-#define VXLAN_VID_MAX (1u << 24) - 1
 #define DHCP_ROUTE_METRIC 1024
 #define IPV4LL_ROUTE_METRIC 2048
 
@@ -53,109 +52,6 @@ typedef struct Route Route;
 typedef struct Manager Manager;
 typedef struct AddressPool AddressPool;
 
-typedef struct netdev_join_callback netdev_join_callback;
-
-struct netdev_join_callback {
-        sd_rtnl_message_handler_t callback;
-        Link *link;
-
-        LIST_FIELDS(netdev_join_callback, callbacks);
-};
-
-typedef enum MacVlanMode {
-        NETDEV_MACVLAN_MODE_PRIVATE = MACVLAN_MODE_PRIVATE,
-        NETDEV_MACVLAN_MODE_VEPA = MACVLAN_MODE_VEPA,
-        NETDEV_MACVLAN_MODE_BRIDGE = MACVLAN_MODE_BRIDGE,
-        NETDEV_MACVLAN_MODE_PASSTHRU = MACVLAN_MODE_PASSTHRU,
-        _NETDEV_MACVLAN_MODE_MAX,
-        _NETDEV_MACVLAN_MODE_INVALID = -1
-} MacVlanMode;
-
-typedef enum BondMode {
-        NETDEV_BOND_MODE_BALANCE_RR,
-        NETDEV_BOND_MODE_ACTIVE_BACKUP,
-        NETDEV_BOND_MODE_BALANCE_XOR,
-        NETDEV_BOND_MODE_BROADCAST,
-        NETDEV_BOND_MODE_802_3AD,
-        NETDEV_BOND_MODE_BALANCE_TLB,
-        NETDEV_BOND_MODE_BALANCE_ALB,
-        _NETDEV_BOND_MODE_MAX,
-        _NETDEV_BOND_MODE_INVALID = -1
-} BondMode;
-
-typedef enum NetDevKind {
-        NETDEV_KIND_BRIDGE,
-        NETDEV_KIND_BOND,
-        NETDEV_KIND_VLAN,
-        NETDEV_KIND_MACVLAN,
-        NETDEV_KIND_VXLAN,
-        NETDEV_KIND_IPIP,
-        NETDEV_KIND_GRE,
-        NETDEV_KIND_SIT,
-        NETDEV_KIND_VETH,
-        NETDEV_KIND_VTI,
-        NETDEV_KIND_DUMMY,
-        NETDEV_KIND_TUN,
-        NETDEV_KIND_TAP,
-        _NETDEV_KIND_MAX,
-        _NETDEV_KIND_INVALID = -1
-} NetDevKind;
-
-typedef enum NetDevState {
-        NETDEV_STATE_FAILED,
-        NETDEV_STATE_CREATING,
-        NETDEV_STATE_READY,
-        NETDEV_STATE_LINGER,
-        _NETDEV_STATE_MAX,
-        _NETDEV_STATE_INVALID = -1,
-} NetDevState;
-
-struct NetDev {
-        Manager *manager;
-
-        int n_ref;
-
-        char *filename;
-
-        Condition *match_host;
-        Condition *match_virt;
-        Condition *match_kernel;
-        Condition *match_arch;
-
-        char *description;
-        char *ifname;
-        char *ifname_peer;
-        char *user_name;
-        char *group_name;
-        size_t mtu;
-        struct ether_addr *mac;
-        struct ether_addr *mac_peer;
-        NetDevKind kind;
-
-        uint64_t vlanid;
-        uint64_t vxlanid;
-        int32_t macvlan_mode;
-        int32_t bond_mode;
-
-        int ifindex;
-        NetDevState state;
-
-        bool tunnel_pmtudisc;
-        bool learning;
-        bool one_queue;
-        bool multi_queue;
-        bool packet_info;
-
-        unsigned ttl;
-        unsigned tos;
-        unsigned char family;
-        union in_addr_union local;
-        union in_addr_union remote;
-        union in_addr_union group;
-
-        LIST_HEAD(netdev_join_callback, callbacks);
-};
-
 typedef enum DHCPSupport {
         DHCP_SUPPORT_NONE,
         DHCP_SUPPORT_BOTH,
@@ -363,51 +259,6 @@ int manager_address_pool_acquire(Manager *m, unsigned family, unsigned prefixlen
 DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free);
 #define _cleanup_manager_free_ _cleanup_(manager_freep)
 
-/* NetDev */
-
-#define VLANID_MAX 4094
-
-int netdev_load(Manager *manager);
-void netdev_drop(NetDev *netdev);
-
-NetDev *netdev_unref(NetDev *netdev);
-NetDev *netdev_ref(NetDev *netdev);
-
-DEFINE_TRIVIAL_CLEANUP_FUNC(NetDev*, netdev_unref);
-#define _cleanup_netdev_unref_ _cleanup_(netdev_unrefp)
-
-int netdev_get(Manager *manager, const char *name, NetDev **ret);
-int netdev_set_ifindex(NetDev *netdev, sd_rtnl_message *newlink);
-int netdev_join(NetDev *netdev, Link *link, sd_rtnl_message_handler_t cb);
-int netdev_create_tunnel(NetDev *netdev, Link *link, sd_rtnl_message_handler_t callback);
-int netdev_create_veth(NetDev *netdev, sd_rtnl_message_handler_t callback);
-int netdev_create_vxlan(NetDev *netdev, Link *link, sd_rtnl_message_handler_t callback);
-int netdev_create_vlan(NetDev *netdev, Link *link, sd_rtnl_message_handler_t callback);
-int netdev_create_macvlan(NetDev *netdev, Link *link, sd_rtnl_message_handler_t callback);
-int netdev_create_dummy(NetDev *netdev, sd_rtnl_message_handler_t callback);
-int netdev_create_tuntap(NetDev *netdev);
-int netdev_create_bond(NetDev *netdev, sd_rtnl_message_handler_t callback);
-int netdev_create_bridge(NetDev *netdev, sd_rtnl_message_handler_t callback);
-
-
-const char *netdev_kind_to_string(NetDevKind d) _const_;
-NetDevKind netdev_kind_from_string(const char *d) _pure_;
-
-const char *macvlan_mode_to_string(MacVlanMode d) _const_;
-MacVlanMode macvlan_mode_from_string(const char *d) _pure_;
-
-const char *bond_mode_to_string(BondMode d) _const_;
-BondMode bond_mode_from_string(const char *d) _pure_;
-
-int config_parse_netdev_kind(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-
-int config_parse_macvlan_mode(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-
-int config_parse_bond_mode(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-
-/* gperf */
-const struct ConfigPerfItem* network_netdev_gperf_lookup(const char *key, unsigned length);
-
 /* Network */
 
 int network_load(Manager *manager);
@@ -555,18 +406,6 @@ int address_pool_acquire(AddressPool *p, unsigned prefixlen, union in_addr_union
 
 #define log_struct_link(level, link, ...) log_struct(level, "INTERFACE=%s", link->ifname, __VA_ARGS__)
 
-/* More macros which append INTERFACE= to the message */
-
-#define log_full_netdev(level, netdev, fmt, ...) log_meta_object(level, __FILE__, __LINE__, __func__, "INTERFACE=", netdev->ifname, "%-*s: " fmt, IFNAMSIZ, netdev->ifname, ##__VA_ARGS__)
-#define log_debug_netdev(netdev, ...)       log_full_netdev(LOG_DEBUG, netdev, ##__VA_ARGS__)
-#define log_info_netdev(netdev, ...)        log_full_netdev(LOG_INFO, netdev, ##__VA_ARGS__)
-#define log_notice_netdev(netdev, ...)      log_full_netdev(LOG_NOTICE, netdev, ##__VA_ARGS__)
-#define log_warning_netdev(netdev, ...)     log_full_netdev(LOG_WARNING, netdev,## __VA_ARGS__)
-#define log_error_netdev(netdev, ...)       log_full_netdev(LOG_ERR, netdev, ##__VA_ARGS__)
-
-#define log_struct_netdev(level, netdev, ...) log_struct(level, "INTERFACE=%s", netdev->ifname, __VA_ARGS__)
-
-#define NETDEV(netdev) "INTERFACE=%s", netdev->ifname
 #define ADDRESS_FMT_VAL(address)            \
         (address).s_addr & 0xFF,            \
         ((address).s_addr >> 8) & 0xFF,     \

commit 2023dc8a9a7d59eab16e020bbcd38b9e377ea452
Author: Tom Gundersen <teg at jklm.no>
Date:   Fri Jul 4 17:03:37 2014 +0200

    networkd: netdev - rework load_one
    
    We now:
     - parse config
     - match on environment
     - verify and complement config
     - create netdev

diff --git a/src/network/networkd-netdev.c b/src/network/networkd-netdev.c
index 0a2e319..ac47c03 100644
--- a/src/network/networkd-netdev.c
+++ b/src/network/networkd-netdev.c
@@ -495,22 +495,33 @@ static int netdev_load_one(Manager *manager, const char *filename) {
                 return r;
         }
 
+        /* skip out early if configuration does not match the environment */
+        if (net_match_config(NULL, NULL, NULL, NULL, NULL,
+                             netdev->match_host, netdev->match_virt,
+                             netdev->match_kernel, netdev->match_arch,
+                             NULL, NULL, NULL, NULL, NULL, NULL) <= 0)
+                return 0;
+
+        /* verify configuration */
         switch (netdev->kind) {
         case _NETDEV_KIND_INVALID:
                 log_warning("NetDev without Kind configured in %s. Ignoring", filename);
                 return 0;
+
         case NETDEV_KIND_VLAN:
                 if (netdev->vlanid > VLANID_MAX) {
                         log_warning("VLAN without valid Id configured in %s. Ignoring", filename);
                         return 0;
                 }
                 break;
+
         case NETDEV_KIND_VXLAN:
                 if (netdev->vxlanid > VXLAN_VID_MAX) {
                         log_warning("VXLAN without valid Id configured in %s. Ignoring", filename);
                         return 0;
                 }
                 break;
+
         case NETDEV_KIND_IPIP:
         case NETDEV_KIND_GRE:
         case NETDEV_KIND_SIT:
@@ -528,6 +539,24 @@ static int netdev_load_one(Manager *manager, const char *filename) {
                         return 0;
                 }
                 break;
+
+        case NETDEV_KIND_VETH:
+                if (!netdev->ifname_peer) {
+                        log_warning("Veth NetDev without peer name configured "
+                                    "in %s. Ignoring", filename);
+                        return 0;
+                }
+
+                if (!netdev->mac_peer) {
+                        r = netdev_get_mac(netdev->ifname_peer, &netdev->mac_peer);
+                        if (r < 0) {
+                                log_error("Failed to generate predictable MAC address for %s",
+                                          netdev->ifname_peer);
+                                return r;
+                        }
+                }
+                break;
+
         default:
                 break;
         }
@@ -560,12 +589,6 @@ static int netdev_load_one(Manager *manager, const char *filename) {
         if (!netdev->filename)
                 return log_oom();
 
-        if (net_match_config(NULL, NULL, NULL, NULL, NULL,
-                             netdev->match_host, netdev->match_virt,
-                             netdev->match_kernel, netdev->match_arch,
-                             NULL, NULL, NULL, NULL, NULL, NULL) <= 0)
-                return 0;
-
         if (!netdev->mac) {
                 r = netdev_get_mac(netdev->ifname, &netdev->mac);
                 if (r < 0) {
@@ -581,23 +604,9 @@ static int netdev_load_one(Manager *manager, const char *filename) {
 
         LIST_HEAD_INIT(netdev->callbacks);
 
+        /* create netdev */
         switch (netdev->kind) {
         case NETDEV_KIND_VETH:
-                if (!netdev->ifname_peer) {
-                        log_warning("Veth NetDev without peer name configured "
-                                    "in %s. Ignoring", filename);
-                        return 0;
-                }
-
-                if (!netdev->mac) {
-                        r = netdev_get_mac(netdev->ifname_peer, &netdev->mac_peer);
-                        if (r < 0) {
-                                log_error("Failed to generate predictable MAC address for %s",
-                                          netdev->ifname_peer);
-                                return r;
-                        }
-                }
-
                 r = netdev_create_veth(netdev, netdev_create_handler);
                 if (r < 0)
                         return r;

commit 6235b3def8f58afe5777f1f5b4e7951f9396c32c
Author: Tom Gundersen <teg at jklm.no>
Date:   Sat Jul 5 15:00:59 2014 +0200

    networkd: netdev - split out bridge creation

diff --git a/Makefile.am b/Makefile.am
index 2b1484f..420d514 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -4600,6 +4600,7 @@ libsystemd_networkd_core_la_SOURCES = \
 	src/network/networkd-dummy.c \
 	src/network/networkd-tuntap.c \
 	src/network/networkd-bond.c \
+	src/network/networkd-bridge.c \
 	src/network/networkd-network.c \
 	src/network/networkd-address.c \
 	src/network/networkd-route.c \
diff --git a/src/network/networkd-bridge.c b/src/network/networkd-bridge.c
new file mode 100644
index 0000000..4c106ee
--- /dev/null
+++ b/src/network/networkd-bridge.c
@@ -0,0 +1,116 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+
+/***
+    This file is part of systemd.
+
+    Copyright 2014  Tom Gundersen <teg at jklm.no>
+    Copyright 2014  Susant Sahani
+
+    systemd is free software; you can redistribute it and/or modify it
+    under the terms of the GNU Lesser General Public License as published by
+    the Free Software Foundation; either version 2.1 of the License, or
+    (at your option) any later version.
+
+    systemd is distributed in the hope that it will be useful, but
+    WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public License
+    along with systemd; If not, see <http://www.gnu.org/licenses/>.
+***/
+
+#include <netinet/ether.h>
+#include <arpa/inet.h>
+#include <net/if.h>
+
+#include "sd-rtnl.h"
+#include "networkd.h"
+#include "missing.h"
+
+static int netdev_fill_bridge_rtnl_message(NetDev *netdev, sd_rtnl_message *m) {
+        int r;
+
+        assert(m);
+
+        r = sd_rtnl_message_append_string(m, IFLA_IFNAME, netdev->ifname);
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not append IFLA_IFNAME, attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        r = sd_rtnl_message_open_container(m, IFLA_LINKINFO);
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not append IFLA_LINKINFO attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        r = sd_rtnl_message_open_container_union(m, IFLA_INFO_DATA,
+                                                 netdev_kind_to_string(netdev->kind));
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not append IFLA_INFO_DATA attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        r = sd_rtnl_message_close_container(m);
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not append IFLA_LINKINFO attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        r = sd_rtnl_message_close_container(m);
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not append IFLA_LINKINFO attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        return r;
+}
+
+int netdev_create_bridge(NetDev *netdev, sd_rtnl_message_handler_t callback) {
+        _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
+        int r;
+
+        assert(netdev);
+        assert(netdev->kind == NETDEV_KIND_BRIDGE);
+        assert(netdev->ifname);
+        assert(netdev->manager);
+        assert(netdev->manager->rtnl);
+
+        r = sd_rtnl_message_new_link(netdev->manager->rtnl, &m, RTM_NEWLINK, 0);
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not allocate RTM_NEWLINK message: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        r = netdev_fill_bridge_rtnl_message(netdev, m);
+        if(r < 0)
+                return r;
+
+        r = sd_rtnl_call_async(netdev->manager->rtnl, m, callback, netdev, 0, NULL);
+        if (r < 0) {
+                log_error_netdev(netdev,
+                                 "Could not send rtnetlink message: %s", strerror(-r));
+                return r;
+        }
+
+        netdev_ref(netdev);
+
+        log_debug_netdev(netdev, "Creating bridge netdev.");
+
+        netdev->state = NETDEV_STATE_CREATING;
+
+        return 0;
+}
diff --git a/src/network/networkd-netdev.c b/src/network/networkd-netdev.c
index f695152..0a2e319 100644
--- a/src/network/networkd-netdev.c
+++ b/src/network/networkd-netdev.c
@@ -246,106 +246,6 @@ static int netdev_create_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userda
         return 1;
 }
 
-static int netdev_create(NetDev *netdev) {
-        _cleanup_rtnl_message_unref_ sd_rtnl_message *req = NULL;
-        const char *kind;
-        int r;
-
-        assert(netdev);
-        assert(netdev->ifname);
-        assert(netdev->manager);
-        assert(netdev->manager->rtnl);
-
-        r = sd_rtnl_message_new_link(netdev->manager->rtnl, &req, RTM_NEWLINK, 0);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not allocate RTM_NEWLINK message: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        r = sd_rtnl_message_append_string(req, IFLA_IFNAME, netdev->ifname);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not append IFLA_IFNAME attribute: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        if (netdev->mtu) {
-                r = sd_rtnl_message_append_u32(req, IFLA_MTU, netdev->mtu);
-                if (r < 0) {
-                        log_error_netdev(netdev,
-                                         "Could not append IFLA_MTU attribute: %s",
-                                         strerror(-r));
-                        return r;
-                }
-        }
-
-        if (netdev->mac) {
-                r = sd_rtnl_message_append_ether_addr(req, IFLA_ADDRESS, netdev->mac);
-                if (r < 0) {
-                        log_error_netdev(netdev,
-                                         "Colud not append IFLA_ADDRESS attribute: %s",
-                                         strerror(-r));
-                    return r;
-                }
-        }
-
-        r = sd_rtnl_message_open_container(req, IFLA_LINKINFO);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not open IFLA_LINKINFO container: %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        kind = netdev_kind_to_string(netdev->kind);
-        if (!kind) {
-                log_error_netdev(netdev, "Invalid kind");
-                return -EINVAL;
-        }
-
-        r = sd_rtnl_message_open_container_union(req, IFLA_INFO_DATA, kind);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not open IFLA_INFO_DATA container: %s",
-                                  strerror(-r));
-                return r;
-        }
-
-        r = sd_rtnl_message_close_container(req);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not close IFLA_INFO_DATA container %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        r = sd_rtnl_message_close_container(req);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not close IFLA_LINKINFO container %s",
-                                 strerror(-r));
-                return r;
-        }
-
-        r = sd_rtnl_call_async(netdev->manager->rtnl, req, &netdev_create_handler, netdev, 0, NULL);
-        if (r < 0) {
-                log_error_netdev(netdev,
-                                 "Could not send rtnetlink message: %s", strerror(-r));
-                return r;
-        }
-
-        netdev_ref(netdev);
-
-        log_debug_netdev(netdev, "creating netdev");
-
-        netdev->state = NETDEV_STATE_CREATING;
-
-        return 0;
-}
-
 static int netdev_enslave(NetDev *netdev, Link *link, sd_rtnl_message_handler_t callback) {
         int r;
 
@@ -710,7 +610,7 @@ static int netdev_load_one(Manager *manager, const char *filename) {
 
                 break;
         case NETDEV_KIND_BRIDGE:
-                r = netdev_create(netdev);
+                r = netdev_create_bridge(netdev, netdev_create_handler);
                 if (r < 0)
                         return r;
                 break;
diff --git a/src/network/networkd.h b/src/network/networkd.h
index d09ab61..d891177 100644
--- a/src/network/networkd.h
+++ b/src/network/networkd.h
@@ -387,6 +387,7 @@ int netdev_create_macvlan(NetDev *netdev, Link *link, sd_rtnl_message_handler_t
 int netdev_create_dummy(NetDev *netdev, sd_rtnl_message_handler_t callback);
 int netdev_create_tuntap(NetDev *netdev);
 int netdev_create_bond(NetDev *netdev, sd_rtnl_message_handler_t callback);
+int netdev_create_bridge(NetDev *netdev, sd_rtnl_message_handler_t callback);
 
 
 const char *netdev_kind_to_string(NetDevKind d) _const_;

commit 3f2650377631aed3bc26fdbc3a2eef6e33cdf7e7
Author: Tom Gundersen <teg at jklm.no>
Date:   Sat Jul 5 14:53:54 2014 +0200

    networkd: netdev - rename 'enslave' to 'join'
    
    Enslave only really makes sense when referring to bridges and bonds, so try to be
    a bit more neutral.

diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c
index 9e057ce..ccf8181 100644
--- a/src/network/networkd-link.c
+++ b/src/network/networkd-link.c
@@ -1732,14 +1732,14 @@ static int link_up(Link *link) {
         return 0;
 }
 
-static int link_enslaved(Link *link) {
+static int link_joined(Link *link) {
         int r;
 
         assert(link);
         assert(link->state == LINK_STATE_ENSLAVING);
         assert(link->network);
 
-        log_debug_link(link, "enslaved");
+        log_debug_link(link, "joined netdev");
 
         if (!(link->flags & IFF_UP)) {
                 r = link_up(link);
@@ -1752,7 +1752,7 @@ static int link_enslaved(Link *link) {
         return link_enter_set_addresses(link);
 }
 
-static int enslave_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
+static int netdev_join_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
         _cleanup_link_unref_ Link *link = userdata;
         int r;
 
@@ -1769,7 +1769,7 @@ static int enslave_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
         r = sd_rtnl_message_get_errno(m);
         if (r < 0 && r != -EEXIST) {
                 log_struct_link(LOG_ERR, link,
-                                "MESSAGE=%-*s: could not enslave: %s",
+                                "MESSAGE=%-*s: could not join netdev: %s",
                                 IFNAMSIZ,
                                 link->ifname, strerror(-r),
                                 "ERRNO=%d", -r,
@@ -1779,12 +1779,12 @@ static int enslave_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
         }
 
         if (link->enslaving <= 0)
-                link_enslaved(link);
+                link_joined(link);
 
         return 1;
 }
 
-static int link_enter_enslave(Link *link) {
+static int link_enter_join_netdev(Link *link) {
         NetDev *vlan, *macvlan, *vxlan;
         Iterator i;
         int r;
@@ -1803,7 +1803,7 @@ static int link_enter_enslave(Link *link) {
             hashmap_isempty(link->network->vlans) &&
             hashmap_isempty(link->network->macvlans) &&
             hashmap_isempty(link->network->vxlans))
-                return link_enslaved(link);
+                return link_joined(link);
 
         if (link->network->bond) {
                 log_struct_link(LOG_DEBUG, link,
@@ -1813,10 +1813,10 @@ static int link_enter_enslave(Link *link) {
                                 NETDEV(link->network->bond),
                                 NULL);
 
-                r = netdev_enslave(link->network->bond, link, &enslave_handler);
+                r = netdev_join(link->network->bond, link, &netdev_join_handler);
                 if (r < 0) {
                         log_struct_link(LOG_WARNING, link,
-                                        "MESSAGE=%-*s: could not enslave by '%s': %s",
+                                        "MESSAGE=%-*s: could not join netdev '%s': %s",
                                         IFNAMSIZ,
                                         link->ifname, link->network->bond->ifname, strerror(-r),
                                         NETDEV(link->network->bond),
@@ -1836,10 +1836,10 @@ static int link_enter_enslave(Link *link) {
                                 NETDEV(link->network->bridge),
                                 NULL);
 
-                r = netdev_enslave(link->network->bridge, link, &enslave_handler);
+                r = netdev_join(link->network->bridge, link, &netdev_join_handler);
                 if (r < 0) {
                         log_struct_link(LOG_WARNING, link,
-                                        "MESSAGE=%-*s: could not enslave by '%s': %s",
+                                        "MESSAGE=%-*s: could not join netdev '%s': %s",
                                         IFNAMSIZ,
                                         link->ifname, link->network->bridge->ifname, strerror(-r),
                                         NETDEV(link->network->bridge),
@@ -1859,10 +1859,10 @@ static int link_enter_enslave(Link *link) {
                                 NETDEV(link->network->tunnel),
                                 NULL);
 
-                r = netdev_enslave(link->network->tunnel, link, &enslave_handler);
+                r = netdev_join(link->network->tunnel, link, &netdev_join_handler);
                 if (r < 0) {
                         log_struct_link(LOG_WARNING, link,
-                                        "MESSAGE=%-*s: could not enslave by '%s': %s",
+                                        "MESSAGE=%-*s: could not join netdev '%s': %s",
                                         IFNAMSIZ,
                                         link->ifname, link->network->tunnel->ifname, strerror(-r),
                                         NETDEV(link->network->tunnel),
@@ -1880,10 +1880,10 @@ static int link_enter_enslave(Link *link) {
                                 IFNAMSIZ,
                                 link->ifname, vlan->ifname, NETDEV(vlan), NULL);
 
-                r = netdev_enslave(vlan, link, &enslave_handler);
+                r = netdev_join(vlan, link, &netdev_join_handler);
                 if (r < 0) {
                         log_struct_link(LOG_WARNING, link,
-                                        "MESSAGE=%-*s: could not enslave by '%s': %s",
+                                        "MESSAGE=%-*s: could not join netdev '%s': %s",
                                         IFNAMSIZ,
                                         link->ifname, vlan->ifname, strerror(-r),
                                         NETDEV(vlan), NULL);
@@ -1900,10 +1900,10 @@ static int link_enter_enslave(Link *link) {
                                 IFNAMSIZ,
                                 link->ifname, macvlan->ifname, NETDEV(macvlan), NULL);
 
-                r = netdev_enslave(macvlan, link, &enslave_handler);
+                r = netdev_join(macvlan, link, &netdev_join_handler);
                 if (r < 0) {
                         log_struct_link(LOG_WARNING, link,
-                                        "MESSAGE=%-*s: could not enslave by '%s': %s",
+                                        "MESSAGE=%-*s: could not join netdev '%s': %s",
                                         IFNAMSIZ,
                                         link->ifname, macvlan->ifname, strerror(-r),
                                         NETDEV(macvlan), NULL);
@@ -1920,10 +1920,10 @@ static int link_enter_enslave(Link *link) {
                                 IFNAMSIZ,
                                 link->ifname, vxlan->ifname, NETDEV(vxlan), NULL);
 
-                r = netdev_enslave(vxlan, link, &enslave_handler);
+                r = netdev_join(vxlan, link, &netdev_join_handler);
                 if (r < 0) {
                         log_struct_link(LOG_WARNING, link,
-                                        "MESSAGE=%*s: could not enslave by '%s': %s",
+                                        "MESSAGE=%*s: could not join netdev '%s': %s",
                                         IFNAMSIZ,
                                         link->ifname, vxlan->ifname, strerror(-r),
                                         NETDEV(vxlan), NULL);
@@ -2074,7 +2074,7 @@ static int link_configure(Link *link) {
                         return r;
         }
 
-        return link_enter_enslave(link);
+        return link_enter_join_netdev(link);
 }
 
 static int link_initialized_and_synced(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
diff --git a/src/network/networkd-netdev.c b/src/network/networkd-netdev.c
index 88b692f..f695152 100644
--- a/src/network/networkd-netdev.c
+++ b/src/network/networkd-netdev.c
@@ -51,7 +51,7 @@ DEFINE_CONFIG_PARSE_ENUM(config_parse_netdev_kind, netdev_kind, NetDevKind, "Fai
 
 static void netdev_cancel_callbacks(NetDev *netdev) {
         _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL;
-        netdev_enslave_callback *callback;
+        netdev_join_callback *callback;
 
         if (!netdev)
                 return;
@@ -161,6 +161,7 @@ static int netdev_enslave_ready(NetDev *netdev, Link* link, sd_rtnl_message_hand
         assert(netdev->state == NETDEV_STATE_READY);
         assert(netdev->manager);
         assert(netdev->manager->rtnl);
+        assert(IN_SET(netdev->kind, NETDEV_KIND_BRIDGE, NETDEV_KIND_BOND));
         assert(link);
         assert(callback);
 
@@ -197,7 +198,7 @@ static int netdev_enslave_ready(NetDev *netdev, Link* link, sd_rtnl_message_hand
 }
 
 static int netdev_enter_ready(NetDev *netdev) {
-        netdev_enslave_callback *callback, *callback_next;
+        netdev_join_callback *callback, *callback_next;
         int r;
 
         assert(netdev);
@@ -345,25 +346,11 @@ static int netdev_create(NetDev *netdev) {
         return 0;
 }
 
-/* the callback must be called, possibly after a timeout, as otherwise the Link will hang */
-int netdev_enslave(NetDev *netdev, Link *link, sd_rtnl_message_handler_t callback) {
+static int netdev_enslave(NetDev *netdev, Link *link, sd_rtnl_message_handler_t callback) {
         int r;
 
-        switch(netdev->kind) {
-        case NETDEV_KIND_VLAN:
-                return netdev_create_vlan(netdev, link, callback);
-        case NETDEV_KIND_MACVLAN:
-                return netdev_create_macvlan(netdev, link, callback);
-        case NETDEV_KIND_VXLAN:
-                return netdev_create_vxlan(netdev, link, callback);
-        case NETDEV_KIND_IPIP:
-        case NETDEV_KIND_GRE:
-        case NETDEV_KIND_SIT:
-        case NETDEV_KIND_VTI:
-                return netdev_create_tunnel(netdev, link, callback);
-        default:
-                break;
-        }
+        assert(netdev);
+        assert(IN_SET(netdev->kind, NETDEV_KIND_BRIDGE, NETDEV_KIND_BOND));
 
         if (netdev->state == NETDEV_STATE_READY) {
                 r = netdev_enslave_ready(netdev, link, callback);
@@ -371,9 +358,9 @@ int netdev_enslave(NetDev *netdev, Link *link, sd_rtnl_message_handler_t callbac
                         return r;
         } else {
                 /* the netdev is not yet read, save this request for when it is*/
-                netdev_enslave_callback *cb;
+                netdev_join_callback *cb;
 
-                cb = new0(netdev_enslave_callback, 1);
+                cb = new0(netdev_join_callback, 1);
                 if (!cb)
                         return log_oom();
 
@@ -387,6 +374,33 @@ int netdev_enslave(NetDev *netdev, Link *link, sd_rtnl_message_handler_t callbac
         return 0;
 }
 
+/* the callback must be called, possibly after a timeout, as otherwise the Link will hang */
+int netdev_join(NetDev *netdev, Link *link, sd_rtnl_message_handler_t callback) {
+
+        assert(netdev);
+
+        switch(netdev->kind) {
+        case NETDEV_KIND_VLAN:
+                return netdev_create_vlan(netdev, link, callback);
+        case NETDEV_KIND_MACVLAN:
+                return netdev_create_macvlan(netdev, link, callback);
+        case NETDEV_KIND_VXLAN:
+                return netdev_create_vxlan(netdev, link, callback);
+        case NETDEV_KIND_IPIP:
+        case NETDEV_KIND_GRE:
+        case NETDEV_KIND_SIT:
+        case NETDEV_KIND_VTI:
+                return netdev_create_tunnel(netdev, link, callback);
+        case NETDEV_KIND_BRIDGE:
+        case NETDEV_KIND_BOND:
+                return netdev_enslave(netdev, link, callback);
+        default:
+                assert_not_reached("Enslaving by invalid netdev kind");
+        }
+
+        return 0;
+}
+
 int netdev_set_ifindex(NetDev *netdev, sd_rtnl_message *message) {
         uint16_t type;
         const char *kind;
diff --git a/src/network/networkd.h b/src/network/networkd.h
index 0f0ecd5..d09ab61 100644
--- a/src/network/networkd.h
+++ b/src/network/networkd.h
@@ -53,13 +53,13 @@ typedef struct Route Route;
 typedef struct Manager Manager;
 typedef struct AddressPool AddressPool;
 
-typedef struct netdev_enslave_callback netdev_enslave_callback;
+typedef struct netdev_join_callback netdev_join_callback;
 
-struct netdev_enslave_callback {
+struct netdev_join_callback {
         sd_rtnl_message_handler_t callback;
         Link *link;
 
-        LIST_FIELDS(netdev_enslave_callback, callbacks);
+        LIST_FIELDS(netdev_join_callback, callbacks);
 };
 
 typedef enum MacVlanMode {
@@ -153,7 +153,7 @@ struct NetDev {
         union in_addr_union remote;
         union in_addr_union group;
 
-        LIST_HEAD(netdev_enslave_callback, callbacks);
+        LIST_HEAD(netdev_join_callback, callbacks);
 };
 
 typedef enum DHCPSupport {
@@ -378,7 +378,7 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(NetDev*, netdev_unref);
 
 int netdev_get(Manager *manager, const char *name, NetDev **ret);
 int netdev_set_ifindex(NetDev *netdev, sd_rtnl_message *newlink);
-int netdev_enslave(NetDev *netdev, Link *link, sd_rtnl_message_handler_t cb);
+int netdev_join(NetDev *netdev, Link *link, sd_rtnl_message_handler_t cb);
 int netdev_create_tunnel(NetDev *netdev, Link *link, sd_rtnl_message_handler_t callback);
 int netdev_create_veth(NetDev *netdev, sd_rtnl_message_handler_t callback);
 int netdev_create_vxlan(NetDev *netdev, Link *link, sd_rtnl_message_handler_t callback);



More information about the systemd-commits mailing list