From: Tom Gundersen Date: Sun, 6 Jul 2014 12:07:34 +0000 (+0200) Subject: networkd: netdev - introduce vtable for netdev kinds X-Git-Tag: v216~630 X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=commitdiff_plain;h=3be1d7e0c5bf60658d34eb6311d4e77c6803578c 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 420d51455..fef6d242c 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-link.c b/src/network/networkd-link.c index ccf818115..0947b0c90 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -24,6 +24,7 @@ #include #include "networkd.h" +#include "networkd-netdev.h" #include "libudev-private.h" #include "udev-util.h" #include "util.h" diff --git a/src/network/networkd-manager.c b/src/network/networkd-manager.c index 46b803fee..4d105248f 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-bond.c b/src/network/networkd-netdev-bond.c similarity index 76% rename from src/network/networkd-bond.c rename to src/network/networkd-netdev-bond.c index 1e156775e..89e3965d1 100644 --- a/src/network/networkd-bond.c +++ b/src/network/networkd-netdev-bond.c @@ -26,7 +26,7 @@ #include "conf-parser.h" #include "sd-rtnl.h" -#include "networkd.h" +#include "networkd-netdev-bond.h" #include "missing.h" static const char* const bond_mode_table[_NETDEV_BOND_MODE_MAX] = { @@ -63,7 +63,7 @@ static uint8_t bond_mode_to_kernel(BondMode mode) { } } -static int netdev_fill_bond_rtnl_message(NetDev *netdev, sd_rtnl_message *m) { +static int netdev_bond_fill_message_create(NetDev *netdev, sd_rtnl_message *m) { int r; assert(m); @@ -123,41 +123,7 @@ static int netdev_fill_bond_rtnl_message(NetDev *netdev, sd_rtnl_message *m) { 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; -} +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 000000000..03ef08167 --- /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 + + 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 . +***/ + +#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-bridge.c b/src/network/networkd-netdev-bridge.c similarity index 65% rename from src/network/networkd-bridge.c rename to src/network/networkd-netdev-bridge.c index 4c106eed3..9a8bf57ee 100644 --- a/src/network/networkd-bridge.c +++ b/src/network/networkd-netdev-bridge.c @@ -25,12 +25,14 @@ #include #include "sd-rtnl.h" -#include "networkd.h" +#include "networkd-netdev-bridge.h" #include "missing.h" -static int netdev_fill_bridge_rtnl_message(NetDev *netdev, sd_rtnl_message *m) { +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); @@ -49,8 +51,7 @@ static int netdev_fill_bridge_rtnl_message(NetDev *netdev, sd_rtnl_message *m) { return r; } - r = sd_rtnl_message_open_container_union(m, IFLA_INFO_DATA, - netdev_kind_to_string(netdev->kind)); + 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", @@ -77,40 +78,7 @@ static int netdev_fill_bridge_rtnl_message(NetDev *netdev, sd_rtnl_message *m) { 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; -} +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 000000000..4d971c62e --- /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 + + 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 . +***/ + +#pragma once + +#include "networkd-netdev.h" + +extern const NetDevVTable bridge_vtable; diff --git a/src/network/networkd-dummy.c b/src/network/networkd-netdev-dummy.c similarity index 65% rename from src/network/networkd-dummy.c rename to src/network/networkd-netdev-dummy.c index 80fe41b0b..100dbbf78 100644 --- a/src/network/networkd-dummy.c +++ b/src/network/networkd-netdev-dummy.c @@ -26,13 +26,13 @@ #include #include "sd-rtnl.h" -#include "networkd.h" +#include "networkd-netdev-dummy.h" - -static int netdev_fill_dummy_rtnl_message(NetDev *netdev, sd_rtnl_message *m) { +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); @@ -61,8 +61,7 @@ static int netdev_fill_dummy_rtnl_message(NetDev *netdev, sd_rtnl_message *m) { return r; } - r = sd_rtnl_message_open_container_union(m, IFLA_INFO_DATA, - netdev_kind_to_string(netdev->kind)); + 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", @@ -81,42 +80,6 @@ static int netdev_fill_dummy_rtnl_message(NetDev *netdev, sd_rtnl_message *m) { 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; -} +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 000000000..dcbd3cc02 --- /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 + + 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 . +***/ + +#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 a698ea8c4..090dfb35e 100644 --- a/src/network/networkd-netdev-gperf.gperf +++ b/src/network/networkd-netdev-gperf.gperf @@ -1,7 +1,10 @@ %{ #include #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-macvlan.c b/src/network/networkd-netdev-macvlan.c similarity index 74% rename from src/network/networkd-macvlan.c rename to src/network/networkd-netdev-macvlan.c index 7c234264a..9eb66ffb7 100644 --- a/src/network/networkd-macvlan.c +++ b/src/network/networkd-netdev-macvlan.c @@ -21,7 +21,7 @@ #include -#include "networkd.h" +#include "networkd-netdev-macvlan.h" #include "network-internal.h" #include "conf-parser.h" #include "list.h" @@ -36,37 +36,22 @@ static const char* const macvlan_mode_table[_NETDEV_MACVLAN_MODE_MAX] = { 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; +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(callback); assert(netdev->ifname); - assert(netdev->manager); - assert(netdev->manager->rtnl); - r = sd_rtnl_message_new_link(netdev->manager->rtnl, &req, RTM_NEWLINK, 0); + r = sd_rtnl_message_append_u32(req, IFLA_LINK, link->ifindex); if (r < 0) { log_error_netdev(netdev, - "Could not allocate RTM_NEWLINK message: %s", + "Could not append IFLA_LINK attribute: %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, @@ -103,13 +88,7 @@ int netdev_create_macvlan(NetDev *netdev, Link *link, sd_rtnl_message_handler_t 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); + 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", @@ -143,18 +122,9 @@ int netdev_create_macvlan(NetDev *netdev, Link *link, sd_rtnl_message_handler_t 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; } + +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 000000000..ea268cc27 --- /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 + + 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 . +***/ + +#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-tunnel.c b/src/network/networkd-netdev-tunnel.c similarity index 84% rename from src/network/networkd-tunnel.c rename to src/network/networkd-netdev-tunnel.c index 5a244f61b..8acb74688 100644 --- a/src/network/networkd-tunnel.c +++ b/src/network/networkd-netdev-tunnel.c @@ -26,24 +26,22 @@ #include #include "sd-rtnl.h" -#include "networkd.h" +#include "networkd-netdev-tunnel.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; +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(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); @@ -142,17 +140,16 @@ static int netdev_fill_ipip_rtnl_message(Link *link, sd_rtnl_message *m) { return r; } -static int netdev_fill_sit_rtnl_message(Link *link, sd_rtnl_message *m) { - NetDev *netdev; +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(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); @@ -224,18 +221,10 @@ static int netdev_fill_sit_rtnl_message(Link *link, sd_rtnl_message *m) { 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); + r = sd_rtnl_message_append_u8(m, IFLA_IPTUN_TTL, netdev->ttl); if (r < 0) { log_error_netdev(netdev, - "Could not append IFLA_IPTUN_PMTUDISC attribute: %s", + "Could not append IFLA_IPTUN_TTL attribute: %s", strerror(-r)); return r; } @@ -259,17 +248,16 @@ static int netdev_fill_sit_rtnl_message(Link *link, sd_rtnl_message *m) { return r; } -static int netdev_fill_ipgre_rtnl_message(Link *link, sd_rtnl_message *m) { - NetDev *netdev; +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(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); @@ -376,17 +364,16 @@ static int netdev_fill_ipgre_rtnl_message(Link *link, sd_rtnl_message *m) { return r; } -static int netdev_fill_vti_rtnl_message(Link *link, sd_rtnl_message *m) { - NetDev *netdev; +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(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); @@ -477,65 +464,25 @@ static int netdev_fill_vti_rtnl_message(Link *link, sd_rtnl_message *m) { 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; - +static int netdev_tunnel_verify(NetDev *netdev, const char *filename) { assert(netdev); - assert(netdev->ifname); - assert(netdev->manager); - assert(netdev->manager->rtnl); - assert(link); - assert(link->network); - assert(link->network->tunnel == netdev); + assert(filename); - 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->local.in.s_addr == INADDR_ANY) { + log_warning("Tunnel without local address configured in %s. Ignoring", filename); + return -EINVAL; } - 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; + if (netdev->remote.in.s_addr == INADDR_ANY) { + log_warning("Tunnel without remote address configured in %s. Ignoring", filename); + return -EINVAL; } - 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; + if (netdev->family != AF_INET) { + log_warning("Tunnel with invalid address family configured in %s. Ignoring", filename); + return -EINVAL; } - link_ref(link); - - log_debug_netdev(netdev, "Creating tunnel netdev: %s", - netdev_kind_to_string(netdev->kind)); - - netdev->state = NETDEV_STATE_CREATING; - return 0; } @@ -567,3 +514,23 @@ int config_parse_tunnel_address(const char *unit, 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 000000000..b30204b76 --- /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 + + 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 . +***/ + +#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-tuntap.c b/src/network/networkd-netdev-tuntap.c similarity index 94% rename from src/network/networkd-tuntap.c rename to src/network/networkd-netdev-tuntap.c index ae2d5c1e3..8f6046174 100644 --- a/src/network/networkd-tuntap.c +++ b/src/network/networkd-netdev-tuntap.c @@ -23,11 +23,10 @@ #include #include -#include "networkd.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); @@ -129,7 +128,7 @@ static int netdev_tuntap_add(NetDev *netdev, struct ifreq *ifr) { return r; } -int netdev_create_tuntap(NetDev *netdev) { +static int netdev_create_tuntap(NetDev *netdev) { struct ifreq ifr; int r; @@ -153,3 +152,11 @@ int netdev_create_tuntap(NetDev *netdev) { 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 000000000..2b6e48f79 --- /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 + + 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 . +***/ + +#pragma once + +#include "networkd-netdev.h" + +extern const NetDevVTable tun_vtable; +extern const NetDevVTable tap_vtable; diff --git a/src/network/networkd-veth.c b/src/network/networkd-netdev-veth.c similarity index 75% rename from src/network/networkd-veth.c rename to src/network/networkd-netdev-veth.c index 50a5b676b..aca8022f0 100644 --- a/src/network/networkd-veth.c +++ b/src/network/networkd-netdev-veth.c @@ -25,13 +25,13 @@ #include #include "sd-rtnl.h" -#include "networkd.h" +#include "networkd-netdev-veth.h" - -static int netdev_fill_veth_rtnl_message(NetDev *netdev, sd_rtnl_message *m) { +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); @@ -60,8 +60,7 @@ static int netdev_fill_veth_rtnl_message(NetDev *netdev, sd_rtnl_message *m) { return r; } - r = sd_rtnl_message_open_container_union(m, IFLA_INFO_DATA, - netdev_kind_to_string(netdev->kind)); + 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", @@ -114,41 +113,31 @@ static int netdev_fill_veth_rtnl_message(NetDev *netdev, sd_rtnl_message *m) { return r; } -int netdev_create_veth(NetDev *netdev, sd_rtnl_message_handler_t callback) { - _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL; +static int netdev_veth_verify(NetDev *netdev, const char *filename) { int r; assert(netdev); - assert(netdev->ifname); - assert(netdev->manager); - assert(netdev->manager->rtnl); - assert(netdev->kind == NETDEV_KIND_VETH); + assert(filename); - 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->ifname_peer) { + log_warning("Veth NetDev without peer name configured in %s. Ignoring", + filename); + return -EINVAL; } - 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; + 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; + } } - netdev_ref(netdev); - - log_debug_netdev(netdev, "Creating veth netdev: %s", - netdev_kind_to_string(netdev->kind)); - - netdev->state = NETDEV_STATE_CREATING; - 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 000000000..93dcdfa1a --- /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 + + 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 . +***/ + +#pragma once + +#include "networkd-netdev.h" + +extern const NetDevVTable veth_vtable; diff --git a/src/network/networkd-vlan.c b/src/network/networkd-netdev-vlan.c similarity index 73% rename from src/network/networkd-vlan.c rename to src/network/networkd-netdev-vlan.c index 8727b9f10..20d0fd5e4 100644 --- a/src/network/networkd-vlan.c +++ b/src/network/networkd-netdev-vlan.c @@ -21,41 +21,27 @@ #include -#include "networkd.h" +#include "networkd-netdev-vlan.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; +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(callback); - assert(netdev->ifname); - assert(netdev->manager); - assert(netdev->manager->rtnl); + assert(req); - r = sd_rtnl_message_new_link(netdev->manager->rtnl, &req, RTM_NEWLINK, 0); + r = sd_rtnl_message_append_u32(req, IFLA_LINK, link->ifindex); if (r < 0) { log_error_netdev(netdev, - "Could not allocate RTM_NEWLINK message: %s", + "Could not append IFLA_LINK attribute: %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, @@ -92,13 +78,7 @@ int netdev_create_vlan(NetDev *netdev, Link *link, sd_rtnl_message_handler_t cal 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); + 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", @@ -132,18 +112,22 @@ int netdev_create_vlan(NetDev *netdev, Link *link, sd_rtnl_message_handler_t cal 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); + return 0; +} - log_debug_netdev(netdev, "creating netdev"); +static int netdev_vlan_verify(NetDev *netdev, const char *filename) { + assert(netdev); + assert(filename); - netdev->state = NETDEV_STATE_CREATING; + 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 000000000..95f630f19 --- /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 + + 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 . +***/ + +#pragma once + +#include "networkd-netdev.h" + +#define VLANID_MAX 4094 + +extern const NetDevVTable vlan_vtable; diff --git a/src/network/networkd-vxlan.c b/src/network/networkd-netdev-vxlan.c similarity index 74% rename from src/network/networkd-vxlan.c rename to src/network/networkd-netdev-vxlan.c index 160459450..38692c687 100644 --- a/src/network/networkd-vxlan.c +++ b/src/network/networkd-netdev-vxlan.c @@ -24,15 +24,15 @@ #include #include "sd-rtnl.h" -#include "networkd.h" +#include "networkd-netdev-vxlan.h" #include "missing.h" - -static int netdev_fill_vxlan_rtnl_message(NetDev *netdev, Link *link, sd_rtnl_message *m) { +static int netdev_vxlan_fill_message_create(NetDev *netdev, Link *link, sd_rtnl_message *m) { int r; + assert(netdev); assert(link); - assert(link->network); + assert(link->ifname); assert(m); r = sd_rtnl_message_append_string(m, IFLA_IFNAME, netdev->ifname); @@ -51,8 +51,7 @@ static int netdev_fill_vxlan_rtnl_message(NetDev *netdev, Link *link, sd_rtnl_me return r; } - r = sd_rtnl_message_open_container_union(m, IFLA_INFO_DATA, - netdev_kind_to_string(netdev->kind)); + 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", @@ -125,41 +124,19 @@ static int netdev_fill_vxlan_rtnl_message(NetDev *netdev, Link *link, sd_rtnl_me 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; - +static int netdev_vxlan_verify(NetDev *netdev, const char *filename) { assert(netdev); - assert(!(netdev->kind == NETDEV_KIND_VXLAN) || (link && callback)); - assert(netdev->ifname); - assert(netdev->manager); - assert(netdev->manager->rtnl); + assert(filename); - 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->vxlanid > VXLAN_VID_MAX) { + log_warning("VXLAN without valid Id configured in %s. Ignoring", filename); + return -EINVAL; } - 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; } + +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 000000000..a2de2713c --- /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 + + 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 . +***/ + +#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 ac47c03fe..a97831760 100644 --- a/src/network/networkd-netdev.c +++ b/src/network/networkd-netdev.c @@ -21,7 +21,16 @@ #include -#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 000000000..a52352288 --- /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 + + 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 . +***/ + +#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 c108ad235..0375194e4 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -23,6 +23,7 @@ #include #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.h b/src/network/networkd.h index d8911772b..3f0ef5d0e 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, \