From aa9f11405829fd4755fef28602a7167dba3ddc89 Mon Sep 17 00:00:00 2001 From: Tom Gundersen Date: Wed, 16 Jul 2014 13:17:10 +0200 Subject: [PATCH] networkd: netdev - split NetDev struct into per-kind structs Similarly to how unit types work. --- src/network/networkd-link.c | 24 +- src/network/networkd-netdev-bond.c | 73 ++--- src/network/networkd-netdev-bond.h | 12 +- src/network/networkd-netdev-bridge.c | 65 +--- src/network/networkd-netdev-bridge.h | 6 + src/network/networkd-netdev-dummy.c | 56 +--- src/network/networkd-netdev-dummy.h | 6 + src/network/networkd-netdev-gperf.gperf | 50 +-- src/network/networkd-netdev-macvlan.c | 88 ++---- src/network/networkd-netdev-macvlan.h | 12 +- src/network/networkd-netdev-tunnel.c | 391 +++++++----------------- src/network/networkd-netdev-tunnel.h | 14 + src/network/networkd-netdev-tuntap.c | 83 +++-- src/network/networkd-netdev-tuntap.h | 12 + src/network/networkd-netdev-veth.c | 80 ++--- src/network/networkd-netdev-veth.h | 9 + src/network/networkd-netdev-vlan.c | 98 ++---- src/network/networkd-netdev-vlan.h | 8 + src/network/networkd-netdev-vxlan.c | 71 ++--- src/network/networkd-netdev-vxlan.h | 14 + src/network/networkd-netdev.c | 321 +++++++++++-------- src/network/networkd-netdev.h | 101 ++++-- src/network/networkd-network.c | 15 +- 23 files changed, 686 insertions(+), 923 deletions(-) diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 7a0f30bdf..0a6f52408 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -1808,7 +1808,7 @@ static int link_enter_join_netdev(Link *link) { "MESSAGE=%-*s: enslaving by '%s'", IFNAMSIZ, link->ifname, link->network->bond->ifname, - NETDEV(link->network->bond), + NETDEVIF(link->network->bond), NULL); r = netdev_join(link->network->bond, link, &netdev_join_handler); @@ -1817,7 +1817,7 @@ static int link_enter_join_netdev(Link *link) { "MESSAGE=%-*s: could not join netdev '%s': %s", IFNAMSIZ, link->ifname, link->network->bond->ifname, strerror(-r), - NETDEV(link->network->bond), + NETDEVIF(link->network->bond), NULL); link_enter_failed(link); return r; @@ -1831,7 +1831,7 @@ static int link_enter_join_netdev(Link *link) { "MESSAGE=%-*s: enslaving by '%s'", IFNAMSIZ, link->ifname, link->network->bridge->ifname, - NETDEV(link->network->bridge), + NETDEVIF(link->network->bridge), NULL); r = netdev_join(link->network->bridge, link, &netdev_join_handler); @@ -1840,7 +1840,7 @@ static int link_enter_join_netdev(Link *link) { "MESSAGE=%-*s: could not join netdev '%s': %s", IFNAMSIZ, link->ifname, link->network->bridge->ifname, strerror(-r), - NETDEV(link->network->bridge), + NETDEVIF(link->network->bridge), NULL); link_enter_failed(link); return r; @@ -1854,7 +1854,7 @@ static int link_enter_join_netdev(Link *link) { "MESSAGE=%-*s: enslaving by '%s'", IFNAMSIZ, link->ifname, link->network->tunnel->ifname, - NETDEV(link->network->tunnel), + NETDEVIF(link->network->tunnel), NULL); r = netdev_join(link->network->tunnel, link, &netdev_join_handler); @@ -1863,7 +1863,7 @@ static int link_enter_join_netdev(Link *link) { "MESSAGE=%-*s: could not join netdev '%s': %s", IFNAMSIZ, link->ifname, link->network->tunnel->ifname, strerror(-r), - NETDEV(link->network->tunnel), + NETDEVIF(link->network->tunnel), NULL); link_enter_failed(link); return r; @@ -1876,7 +1876,7 @@ static int link_enter_join_netdev(Link *link) { log_struct_link(LOG_DEBUG, link, "MESSAGE=%-*s: enslaving by '%s'", IFNAMSIZ, - link->ifname, vlan->ifname, NETDEV(vlan), NULL); + link->ifname, vlan->ifname, NETDEVIF(vlan), NULL); r = netdev_join(vlan, link, &netdev_join_handler); if (r < 0) { @@ -1884,7 +1884,7 @@ static int link_enter_join_netdev(Link *link) { "MESSAGE=%-*s: could not join netdev '%s': %s", IFNAMSIZ, link->ifname, vlan->ifname, strerror(-r), - NETDEV(vlan), NULL); + NETDEVIF(vlan), NULL); link_enter_failed(link); return r; } @@ -1896,7 +1896,7 @@ static int link_enter_join_netdev(Link *link) { log_struct_link(LOG_DEBUG, link, "MESSAGE=%-*s: enslaving by '%s'", IFNAMSIZ, - link->ifname, macvlan->ifname, NETDEV(macvlan), NULL); + link->ifname, macvlan->ifname, NETDEVIF(macvlan), NULL); r = netdev_join(macvlan, link, &netdev_join_handler); if (r < 0) { @@ -1904,7 +1904,7 @@ static int link_enter_join_netdev(Link *link) { "MESSAGE=%-*s: could not join netdev '%s': %s", IFNAMSIZ, link->ifname, macvlan->ifname, strerror(-r), - NETDEV(macvlan), NULL); + NETDEVIF(macvlan), NULL); link_enter_failed(link); return r; } @@ -1916,7 +1916,7 @@ static int link_enter_join_netdev(Link *link) { log_struct_link(LOG_DEBUG, link, "MESSAGE=%*s: enslaving by '%s'", IFNAMSIZ, - link->ifname, vxlan->ifname, NETDEV(vxlan), NULL); + link->ifname, vxlan->ifname, NETDEVIF(vxlan), NULL); r = netdev_join(vxlan, link, &netdev_join_handler); if (r < 0) { @@ -1924,7 +1924,7 @@ static int link_enter_join_netdev(Link *link) { "MESSAGE=%*s: could not join netdev '%s': %s", IFNAMSIZ, link->ifname, vxlan->ifname, strerror(-r), - NETDEV(vxlan), NULL); + NETDEVIF(vxlan), NULL); link_enter_failed(link); return r; } diff --git a/src/network/networkd-netdev-bond.c b/src/network/networkd-netdev-bond.c index 561ca2a14..562f9eb9d 100644 --- a/src/network/networkd-netdev-bond.c +++ b/src/network/networkd-netdev-bond.c @@ -63,49 +63,18 @@ static uint8_t bond_mode_to_kernel(BondMode mode) { } } -static int netdev_bond_fill_message_create(NetDev *netdev, sd_rtnl_message *m) { +static int netdev_bond_fill_message_create(NetDev *netdev, Link *link, sd_rtnl_message *m) { + Bond *b = BOND(netdev); int r; + assert(netdev); + assert(!link); + assert(b); 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, - "Could 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; - } - - if (netdev->bond_mode != _NETDEV_BOND_MODE_INVALID) { + if (b->mode != _NETDEV_BOND_MODE_INVALID) { r = sd_rtnl_message_append_u8(m, IFLA_BOND_MODE, - bond_mode_to_kernel(netdev->bond_mode)); + bond_mode_to_kernel(b->mode)); if (r < 0) { log_error_netdev(netdev, "Could not append IFLA_BOND_MODE attribute: %s", @@ -114,26 +83,22 @@ static int netdev_bond_fill_message_create(NetDev *netdev, sd_rtnl_message *m) { } } - 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 0; +} - 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; - } +static void bond_init(NetDev *netdev) { + Bond *b = BOND(netdev); + + assert(netdev); + assert(b); - return r; + b->mode = _NETDEV_BOND_MODE_INVALID; } const NetDevVTable bond_vtable = { + .object_size = sizeof(Bond), + .init = bond_init, + .sections = "Match\0NetDev\0Bond\0", .fill_message_create = netdev_bond_fill_message_create, - .enslave = netdev_enslave, + .create_type = NETDEV_CREATE_MASTER, }; diff --git a/src/network/networkd-netdev-bond.h b/src/network/networkd-netdev-bond.h index 03ef08167..09731b73e 100644 --- a/src/network/networkd-netdev-bond.h +++ b/src/network/networkd-netdev-bond.h @@ -21,9 +21,9 @@ #pragma once -#include "networkd-netdev.h" +typedef struct Bond Bond; -extern const NetDevVTable bond_vtable; +#include "networkd-netdev.h" typedef enum BondMode { NETDEV_BOND_MODE_BALANCE_RR, @@ -37,6 +37,14 @@ typedef enum BondMode { _NETDEV_BOND_MODE_INVALID = -1 } BondMode; +struct Bond { + NetDev meta; + + BondMode mode; +}; + +extern const NetDevVTable bond_vtable; + const char *bond_mode_to_string(BondMode d) _const_; BondMode bond_mode_from_string(const char *d) _pure_; diff --git a/src/network/networkd-netdev-bridge.c b/src/network/networkd-netdev-bridge.c index 7ae304e96..91b7051a0 100644 --- a/src/network/networkd-netdev-bridge.c +++ b/src/network/networkd-netdev-bridge.c @@ -28,67 +28,8 @@ #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; - } - - if (netdev->mac) { - r = sd_rtnl_message_append_ether_addr(m, IFLA_ADDRESS, netdev->mac); - if (r < 0) { - log_error_netdev(netdev, - "Could 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, "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, + .object_size = sizeof(Bridge), + .sections = "Match\0NetDev\0", + .create_type = NETDEV_CREATE_MASTER, }; diff --git a/src/network/networkd-netdev-bridge.h b/src/network/networkd-netdev-bridge.h index 4d971c62e..a7d02b1c9 100644 --- a/src/network/networkd-netdev-bridge.h +++ b/src/network/networkd-netdev-bridge.h @@ -21,6 +21,12 @@ #pragma once +typedef struct Bridge Bridge; + #include "networkd-netdev.h" +struct Bridge { + NetDev meta; +}; + extern const NetDevVTable bridge_vtable; diff --git a/src/network/networkd-netdev-dummy.c b/src/network/networkd-netdev-dummy.c index 2f861a73e..01c10a2d7 100644 --- a/src/network/networkd-netdev-dummy.c +++ b/src/network/networkd-netdev-dummy.c @@ -28,58 +28,8 @@ #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, - "Could 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, + .object_size = sizeof(Dummy), + .sections = "Match\0NetDev\0", + .create_type = NETDEV_CREATE_INDEPENDENT, }; diff --git a/src/network/networkd-netdev-dummy.h b/src/network/networkd-netdev-dummy.h index dcbd3cc02..0d321e5ae 100644 --- a/src/network/networkd-netdev-dummy.h +++ b/src/network/networkd-netdev-dummy.h @@ -21,6 +21,12 @@ #pragma once +typedef struct Dummy Dummy; + #include "networkd-netdev.h" +struct Dummy { + NetDev meta; +}; + extern const NetDevVTable dummy_vtable; diff --git a/src/network/networkd-netdev-gperf.gperf b/src/network/networkd-netdev-gperf.gperf index 090dfb35e..b46b8dbfc 100644 --- a/src/network/networkd-netdev-gperf.gperf +++ b/src/network/networkd-netdev-gperf.gperf @@ -27,28 +27,28 @@ NetDev.Name, config_parse_ifname, 0, NetDev.Kind, config_parse_netdev_kind, 0, offsetof(NetDev, kind) NetDev.MTUBytes, config_parse_iec_size, 0, offsetof(NetDev, mtu) NetDev.MACAddress, config_parse_hwaddr, 0, offsetof(NetDev, mac) -VLAN.Id, config_parse_uint64, 0, offsetof(NetDev, vlanid) -MACVLAN.Mode, config_parse_macvlan_mode, 0, offsetof(NetDev, macvlan_mode) -Tunnel.Local, config_parse_tunnel_address, 0, offsetof(NetDev, local) -Tunnel.Remote, config_parse_tunnel_address, 0, offsetof(NetDev, remote) -Tunnel.TOS, config_parse_unsigned, 0, offsetof(NetDev, tos) -Tunnel.TTL, config_parse_unsigned, 0, offsetof(NetDev, ttl) -Tunnel.DiscoverPathMTU, config_parse_bool, 0, offsetof(NetDev, tunnel_pmtudisc) -Peer.Name, config_parse_ifname, 0, offsetof(NetDev, ifname_peer) -Peer.MACAddress, config_parse_hwaddr, 0, offsetof(NetDev, mac_peer) -VXLAN.Id, config_parse_uint64, 0, offsetof(NetDev, vxlanid) -VXLAN.Group, config_parse_tunnel_address, 0, offsetof(NetDev, group) -VXLAN.TOS, config_parse_unsigned, 0, offsetof(NetDev, tos) -VXLAN.TTL, config_parse_unsigned, 0, offsetof(NetDev, ttl) -VXLAN.MacLearning, config_parse_bool, 0, offsetof(NetDev, learning) -Tun.OneQueue, config_parse_bool, 0, offsetof(NetDev, one_queue) -Tun.MultiQueue, config_parse_bool, 0, offsetof(NetDev, multi_queue) -Tun.PacketInfo, config_parse_bool, 0, offsetof(NetDev, packet_info) -Tun.User, config_parse_string, 0, offsetof(NetDev, user_name) -Tun.Group, config_parse_string, 0, offsetof(NetDev, group_name) -Tap.OneQueue, config_parse_bool, 0, offsetof(NetDev, one_queue) -Tap.MultiQueue, config_parse_bool, 0, offsetof(NetDev, multi_queue) -Tap.PacketInfo, config_parse_bool, 0, offsetof(NetDev, packet_info) -Tap.User, config_parse_string, 0, offsetof(NetDev, user_name) -Tap.Group, config_parse_string, 0, offsetof(NetDev, group_name) -Bond.Mode, config_parse_bond_mode, 0, offsetof(NetDev, bond_mode) +VLAN.Id, config_parse_uint64, 0, offsetof(VLan, id) +MACVLAN.Mode, config_parse_macvlan_mode, 0, offsetof(MacVlan, mode) +Tunnel.Local, config_parse_tunnel_address, 0, offsetof(Tunnel, local) +Tunnel.Remote, config_parse_tunnel_address, 0, offsetof(Tunnel, remote) +Tunnel.TOS, config_parse_unsigned, 0, offsetof(Tunnel, tos) +Tunnel.TTL, config_parse_unsigned, 0, offsetof(Tunnel, ttl) +Tunnel.DiscoverPathMTU, config_parse_bool, 0, offsetof(Tunnel, pmtudisc) +Peer.Name, config_parse_ifname, 0, offsetof(Veth, ifname_peer) +Peer.MACAddress, config_parse_hwaddr, 0, offsetof(Veth, mac_peer) +VXLAN.Id, config_parse_uint64, 0, offsetof(VxLan, id) +VXLAN.Group, config_parse_tunnel_address, 0, offsetof(VxLan, group) +VXLAN.TOS, config_parse_unsigned, 0, offsetof(VxLan, tos) +VXLAN.TTL, config_parse_unsigned, 0, offsetof(VxLan, ttl) +VXLAN.MacLearning, config_parse_bool, 0, offsetof(VxLan, learning) +Tun.OneQueue, config_parse_bool, 0, offsetof(TunTap, one_queue) +Tun.MultiQueue, config_parse_bool, 0, offsetof(TunTap, multi_queue) +Tun.PacketInfo, config_parse_bool, 0, offsetof(TunTap, packet_info) +Tun.User, config_parse_string, 0, offsetof(TunTap, user_name) +Tun.Group, config_parse_string, 0, offsetof(TunTap, group_name) +Tap.OneQueue, config_parse_bool, 0, offsetof(TunTap, one_queue) +Tap.MultiQueue, config_parse_bool, 0, offsetof(TunTap, multi_queue) +Tap.PacketInfo, config_parse_bool, 0, offsetof(TunTap, packet_info) +Tap.User, config_parse_string, 0, offsetof(TunTap, user_name) +Tap.Group, config_parse_string, 0, offsetof(TunTap, group_name) +Bond.Mode, config_parse_bond_mode, 0, offsetof(Bond, mode) diff --git a/src/network/networkd-netdev-macvlan.c b/src/network/networkd-netdev-macvlan.c index bfa1ff1ac..2e5554a17 100644 --- a/src/network/networkd-netdev-macvlan.c +++ b/src/network/networkd-netdev-macvlan.c @@ -37,67 +37,16 @@ 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) { + MacVlan *m = MACVLAN(netdev); int r; assert(netdev); - assert(netdev->kind == NETDEV_KIND_MACVLAN); + assert(m); 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, - "Could 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 (m->mode != _NETDEV_MACVLAN_MODE_INVALID) { + r = sd_rtnl_message_append_u32(req, IFLA_MACVLAN_MODE, m->mode); if (r < 0) { log_error_netdev(netdev, "Could not append IFLA_MACVLAN_MODE attribute: %s", @@ -106,25 +55,22 @@ static int netdev_macvlan_fill_message_create(NetDev *netdev, Link *link, sd_rtn } } - 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; - } + return 0; +} - 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; - } +static void macvlan_init(NetDev *n) { + MacVlan *m = MACVLAN(n); - return 0; + assert(n); + assert(m); + + m->mode = _NETDEV_MACVLAN_MODE_INVALID; } const NetDevVTable macvlan_vtable = { - .fill_message_create_on_link = netdev_macvlan_fill_message_create, + .object_size = sizeof(MacVlan), + .init = macvlan_init, + .sections = "Match\0NetDev\0MACVLAN\0", + .fill_message_create = netdev_macvlan_fill_message_create, + .create_type = NETDEV_CREATE_STACKED, }; diff --git a/src/network/networkd-netdev-macvlan.h b/src/network/networkd-netdev-macvlan.h index ea268cc27..d61efc16d 100644 --- a/src/network/networkd-netdev-macvlan.h +++ b/src/network/networkd-netdev-macvlan.h @@ -21,9 +21,9 @@ #pragma once -#include "networkd-netdev.h" +typedef struct MacVlan MacVlan; -extern const NetDevVTable macvlan_vtable; +#include "networkd-netdev.h" typedef enum MacVlanMode { NETDEV_MACVLAN_MODE_PRIVATE = MACVLAN_MODE_PRIVATE, @@ -34,6 +34,14 @@ typedef enum MacVlanMode { _NETDEV_MACVLAN_MODE_INVALID = -1 } MacVlanMode; +struct MacVlan { + NetDev meta; + + MacVlanMode mode; +}; + +extern const NetDevVTable macvlan_vtable; + const char *macvlan_mode_to_string(MacVlanMode d) _const_; MacVlanMode macvlan_mode_from_string(const char *d) _pure_; diff --git a/src/network/networkd-netdev-tunnel.c b/src/network/networkd-netdev-tunnel.c index 2ecfef8e5..4561f8d0a 100644 --- a/src/network/networkd-netdev-tunnel.c +++ b/src/network/networkd-netdev-tunnel.c @@ -33,61 +33,14 @@ #include "conf-parser.h" static int netdev_ipip_fill_message_create(NetDev *netdev, Link *link, sd_rtnl_message *m) { + Tunnel *t = IPIP(netdev); 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, - "Could 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; - } + assert(t); + assert(t->family == AF_INET); r = sd_rtnl_message_append_u32(m, IFLA_IPTUN_LINK, link->ifindex); if (r < 0) { @@ -97,7 +50,7 @@ static int netdev_ipip_fill_message_create(NetDev *netdev, Link *link, sd_rtnl_m return r; } - r = sd_rtnl_message_append_in_addr(m, IFLA_IPTUN_LOCAL, &netdev->local.in); + r = sd_rtnl_message_append_in_addr(m, IFLA_IPTUN_LOCAL, &t->local.in); if (r < 0) { log_error_netdev(netdev, "Could not append IFLA_IPTUN_LOCAL attribute: %s", @@ -105,7 +58,7 @@ static int netdev_ipip_fill_message_create(NetDev *netdev, Link *link, sd_rtnl_m return r; } - r = sd_rtnl_message_append_in_addr(m, IFLA_IPTUN_REMOTE, &netdev->remote.in); + r = sd_rtnl_message_append_in_addr(m, IFLA_IPTUN_REMOTE, &t->remote.in); if (r < 0) { log_error_netdev(netdev, "Could not append IFLA_IPTUN_REMOTE attribute: %s", @@ -113,7 +66,7 @@ static int netdev_ipip_fill_message_create(NetDev *netdev, Link *link, sd_rtnl_m return r; } - r = sd_rtnl_message_append_u8(m, IFLA_IPTUN_TTL, netdev->ttl); + r = sd_rtnl_message_append_u8(m, IFLA_IPTUN_TTL, t->ttl); if (r < 0) { log_error_netdev(netdev, "Could not append IFLA_IPTUN_TTL attribute: %s", @@ -121,81 +74,18 @@ static int netdev_ipip_fill_message_create(NetDev *netdev, Link *link, sd_rtnl_m 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) { + Tunnel *t = SIT(netdev); 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, - "Could 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; - } + assert(t); + assert(t->family == AF_INET); r = sd_rtnl_message_append_u32(m, IFLA_IPTUN_LINK, link->ifindex); if (r < 0) { @@ -205,7 +95,7 @@ static int netdev_sit_fill_message_create(NetDev *netdev, Link *link, sd_rtnl_me return r; } - r = sd_rtnl_message_append_in_addr(m, IFLA_IPTUN_LOCAL, &netdev->local.in); + r = sd_rtnl_message_append_in_addr(m, IFLA_IPTUN_LOCAL, &t->local.in); if (r < 0) { log_error_netdev(netdev, "Could not append IFLA_IPTUN_LOCAL attribute: %s", @@ -213,7 +103,7 @@ static int netdev_sit_fill_message_create(NetDev *netdev, Link *link, sd_rtnl_me return r; } - r = sd_rtnl_message_append_in_addr(m, IFLA_IPTUN_REMOTE, &netdev->remote.in); + r = sd_rtnl_message_append_in_addr(m, IFLA_IPTUN_REMOTE, &t->remote.in); if (r < 0) { log_error_netdev(netdev, "Could not append IFLA_IPTUN_REMOTE attribute: %s", @@ -221,7 +111,7 @@ static int netdev_sit_fill_message_create(NetDev *netdev, Link *link, sd_rtnl_me return r; } - r = sd_rtnl_message_append_u8(m, IFLA_IPTUN_TTL, netdev->ttl); + r = sd_rtnl_message_append_u8(m, IFLA_IPTUN_TTL, t->ttl); if (r < 0) { log_error_netdev(netdev, "Could not append IFLA_IPTUN_TTL attribute: %s", @@ -229,81 +119,18 @@ static int netdev_sit_fill_message_create(NetDev *netdev, Link *link, sd_rtnl_me 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) { + Tunnel *t = GRE(netdev); 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, - "Could 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; - } + assert(t); + assert(t->family == AF_INET); r = sd_rtnl_message_append_u32(m, IFLA_GRE_LINK, link->ifindex); if (r < 0) { @@ -313,7 +140,7 @@ static int netdev_gre_fill_message_create(NetDev *netdev, Link *link, sd_rtnl_me return r; } - r = sd_rtnl_message_append_in_addr(m, IFLA_GRE_LOCAL, &netdev->local.in); + r = sd_rtnl_message_append_in_addr(m, IFLA_GRE_LOCAL, &t->local.in); if (r < 0) { log_error_netdev(netdev, "Could not append IFLA_GRE_LOCAL attribute: %s", @@ -321,7 +148,7 @@ static int netdev_gre_fill_message_create(NetDev *netdev, Link *link, sd_rtnl_me return r; } - r = sd_rtnl_message_append_in_addr(m, IFLA_GRE_REMOTE, &netdev->remote.in); + r = sd_rtnl_message_append_in_addr(m, IFLA_GRE_REMOTE, &t->remote.in); if (r < 0) { log_error_netdev(netdev, "Could not append IFLA_GRE_REMOTE attribute: %s", @@ -329,7 +156,7 @@ static int netdev_gre_fill_message_create(NetDev *netdev, Link *link, sd_rtnl_me return r; } - r = sd_rtnl_message_append_u8(m, IFLA_GRE_TTL, netdev->ttl); + r = sd_rtnl_message_append_u8(m, IFLA_GRE_TTL, t->ttl); if (r < 0) { log_error_netdev(netdev, "Could not append IFLA_GRE_TTL attribute: %s", @@ -337,7 +164,7 @@ static int netdev_gre_fill_message_create(NetDev *netdev, Link *link, sd_rtnl_me return r; } - r = sd_rtnl_message_append_u8(m, IFLA_GRE_TOS, netdev->tos); + r = sd_rtnl_message_append_u8(m, IFLA_GRE_TOS, t->tos); if (r < 0) { log_error_netdev(netdev, "Could not append IFLA_GRE_TOS attribute: %s", @@ -345,81 +172,18 @@ static int netdev_gre_fill_message_create(NetDev *netdev, Link *link, sd_rtnl_me 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) { + Tunnel *t = VTI(netdev); 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, - "Could 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; - } + assert(t); + assert(t->family == AF_INET); r = sd_rtnl_message_append_u32(m, IFLA_VTI_LINK, link->ifindex); if (r < 0) { @@ -429,7 +193,7 @@ static int netdev_vti_fill_message_create(NetDev *netdev, Link *link, sd_rtnl_me return r; } - r = sd_rtnl_message_append_in_addr(m, IFLA_VTI_LOCAL, &netdev->local.in); + r = sd_rtnl_message_append_in_addr(m, IFLA_VTI_LOCAL, &t->local.in); if (r < 0) { log_error_netdev(netdev, "Could not append IFLA_IPTUN_LOCAL attribute: %s", @@ -437,7 +201,7 @@ static int netdev_vti_fill_message_create(NetDev *netdev, Link *link, sd_rtnl_me return r; } - r = sd_rtnl_message_append_in_addr(m, IFLA_VTI_REMOTE, &netdev->remote.in); + r = sd_rtnl_message_append_in_addr(m, IFLA_VTI_REMOTE, &t->remote.in); if (r < 0) { log_error_netdev(netdev, "Could not append IFLA_IPTUN_REMOTE attribute: %s", @@ -445,40 +209,45 @@ static int netdev_vti_fill_message_create(NetDev *netdev, Link *link, sd_rtnl_me 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) { + Tunnel *t = NULL; + assert(netdev); assert(filename); - if (netdev->local.in.s_addr == INADDR_ANY) { + switch (netdev->kind) { + case NETDEV_KIND_IPIP: + t = IPIP(netdev); + break; + case NETDEV_KIND_SIT: + t = SIT(netdev); + break; + case NETDEV_KIND_GRE: + t = GRE(netdev); + break; + case NETDEV_KIND_VTI: + t = VTI(netdev); + break; + default: + assert_not_reached("Invalid tunnel kind"); + } + + assert(t); + + if (t->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) { + if (t->remote.in.s_addr == INADDR_ANY) { log_warning("Tunnel without remote address configured in %s. Ignoring", filename); return -EINVAL; } - if (netdev->family != AF_INET) { + if (t->family != AF_INET) { log_warning("Tunnel with invalid address family configured in %s. Ignoring", filename); return -EINVAL; } @@ -496,7 +265,7 @@ int config_parse_tunnel_address(const char *unit, const char *rvalue, void *data, void *userdata) { - NetDev *n = userdata; + Tunnel *t = userdata; union in_addr_union *addr = data; int r; @@ -505,7 +274,7 @@ int config_parse_tunnel_address(const char *unit, assert(rvalue); assert(data); - r = net_parse_inaddr(rvalue, &n->family, addr); + r = net_parse_inaddr(rvalue, &t->family, addr); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Tunnel address is invalid, ignoring assignment: %s", rvalue); @@ -515,22 +284,74 @@ int config_parse_tunnel_address(const char *unit, return 0; } +static void ipip_init(NetDev *n) { + Tunnel *t = IPIP(n); + + assert(n); + assert(t); + + t->pmtudisc = true; +} + +static void sit_init(NetDev *n) { + Tunnel *t = SIT(n); + + assert(n); + assert(t); + + t->pmtudisc = true; +} + +static void vti_init(NetDev *n) { + Tunnel *t = VTI(n); + + assert(n); + assert(t); + + t->pmtudisc = true; +} + +static void gre_init(NetDev *n) { + Tunnel *t = GRE(n); + + assert(n); + assert(t); + + t->pmtudisc = true; +} + const NetDevVTable ipip_vtable = { - .fill_message_create_on_link = netdev_ipip_fill_message_create, + .object_size = sizeof(Tunnel), + .init = ipip_init, + .sections = "Match\0NetDev\0Tunnel\0", + .fill_message_create = netdev_ipip_fill_message_create, + .create_type = NETDEV_CREATE_STACKED, .config_verify = netdev_tunnel_verify, }; const NetDevVTable sit_vtable = { - .fill_message_create_on_link = netdev_sit_fill_message_create, + .object_size = sizeof(Tunnel), + .init = sit_init, + .sections = "Match\0NetDev\0Tunnel\0", + .fill_message_create = netdev_sit_fill_message_create, + .create_type = NETDEV_CREATE_STACKED, .config_verify = netdev_tunnel_verify, }; const NetDevVTable vti_vtable = { - .fill_message_create_on_link = netdev_vti_fill_message_create, + .object_size = sizeof(Tunnel), + .init = vti_init, + .sections = "Match\0NetDev\0Tunnel\0", + .fill_message_create = netdev_vti_fill_message_create, + .create_type = NETDEV_CREATE_STACKED, .config_verify = netdev_tunnel_verify, }; const NetDevVTable gre_vtable = { - .fill_message_create_on_link = netdev_gre_fill_message_create, + .object_size = sizeof(Tunnel), + .init = gre_init, + .sections = "Match\0NetDev\0Tunnel\0", + .fill_message_create = netdev_gre_fill_message_create, + .create_type = NETDEV_CREATE_STACKED, .config_verify = netdev_tunnel_verify, }; diff --git a/src/network/networkd-netdev-tunnel.h b/src/network/networkd-netdev-tunnel.h index b30204b76..000a6460e 100644 --- a/src/network/networkd-netdev-tunnel.h +++ b/src/network/networkd-netdev-tunnel.h @@ -21,8 +21,22 @@ #pragma once +typedef struct Tunnel Tunnel; + #include "networkd-netdev.h" +struct Tunnel { + NetDev meta; + + int family; + + unsigned ttl; + unsigned tos; + union in_addr_union local; + union in_addr_union remote; + bool pmtudisc; +}; + extern const NetDevVTable ipip_vtable; extern const NetDevVTable sit_vtable; extern const NetDevVTable vti_vtable; diff --git a/src/network/networkd-netdev-tuntap.c b/src/network/networkd-netdev-tuntap.c index 8f6046174..dd3bd96db 100644 --- a/src/network/networkd-netdev-tuntap.c +++ b/src/network/networkd-netdev-tuntap.c @@ -28,24 +28,27 @@ #define TUN_DEV "/dev/net/tun" static int netdev_fill_tuntap_message(NetDev *netdev, struct ifreq *ifr) { + TunTap *t; assert(netdev); + assert(netdev->ifname); assert(ifr); - memset(ifr, 0, sizeof(*ifr)); - - if (netdev->kind == NETDEV_KIND_TAP) + if (netdev->kind == NETDEV_KIND_TAP) { + t = TAP(netdev); ifr->ifr_flags |= IFF_TAP; - else + } else { + t = TUN(netdev); ifr->ifr_flags |= IFF_TUN; + } - if (!netdev->packet_info) + if (!t->packet_info) ifr->ifr_flags |= IFF_NO_PI; - if (netdev->one_queue) + if (t->one_queue) ifr->ifr_flags |= IFF_ONE_QUEUE; - if (netdev->multi_queue) + if (t->multi_queue) ifr->ifr_flags |= IFF_MULTI_QUEUE; strncpy(ifr->ifr_name, netdev->ifname, IFNAMSIZ-1); @@ -55,12 +58,16 @@ static int netdev_fill_tuntap_message(NetDev *netdev, struct ifreq *ifr) { static int netdev_tuntap_add(NetDev *netdev, struct ifreq *ifr) { _cleanup_close_ int fd; + TunTap *t = NULL; const char *user; const char *group; uid_t uid; gid_t gid; int r = 0; + assert(netdev); + assert(ifr); + fd = open(TUN_DEV, O_RDWR); if (fd < 0) { log_error_netdev(netdev, @@ -77,14 +84,21 @@ static int netdev_tuntap_add(NetDev *netdev, struct ifreq *ifr) { return r; } - if(netdev->user_name) { + if (netdev->kind == NETDEV_KIND_TAP) + t = TAP(netdev); + else + t = TUN(netdev); + + assert(t); - user = netdev->user_name; + if(t->user_name) { + + user = t->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)); + t->user_name, strerror(-r)); return 0; } @@ -96,14 +110,14 @@ static int netdev_tuntap_add(NetDev *netdev, struct ifreq *ifr) { } } - if(netdev->group_name) { + if(t->group_name) { - group = netdev->group_name; + group = t->group_name; r = get_group_creds(&group, &gid); if (r < 0) { log_error("Cannot resolve group name %s: %s", - netdev->group_name, strerror(-r)); + t->group_name, strerror(-r)); return 0; } @@ -129,34 +143,47 @@ static int netdev_tuntap_add(NetDev *netdev, struct ifreq *ifr) { } static int netdev_create_tuntap(NetDev *netdev) { - struct ifreq ifr; + 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); } +static void tuntap_done(NetDev *netdev) { + TunTap *t = NULL; + + assert(netdev); + + if (netdev->kind == NETDEV_KIND_TUN) + t = TUN(netdev); + else + t = TAP(netdev); + + assert(t); + + free(t->user_name); + t->user_name = NULL; + + free(t->group_name); + t->group_name = NULL; +} + const NetDevVTable tun_vtable = { + .object_size = sizeof(TunTap), + .sections = "Match\0NetDev\0Tun\0", + .done = tuntap_done, .create = netdev_create_tuntap, + .create_type = NETDEV_CREATE_INDEPENDENT, }; const NetDevVTable tap_vtable = { + .object_size = sizeof(TunTap), + .sections = "Match\0NetDev\0Tap\0", + .done = tuntap_done, .create = netdev_create_tuntap, + .create_type = NETDEV_CREATE_INDEPENDENT, }; diff --git a/src/network/networkd-netdev-tuntap.h b/src/network/networkd-netdev-tuntap.h index 2b6e48f79..b804875bb 100644 --- a/src/network/networkd-netdev-tuntap.h +++ b/src/network/networkd-netdev-tuntap.h @@ -21,7 +21,19 @@ #pragma once +typedef struct TunTap TunTap; + #include "networkd-netdev.h" +struct TunTap { + NetDev meta; + + char *user_name; + char *group_name; + bool one_queue; + bool multi_queue; + bool packet_info; +}; + 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 index c995bbb70..da09ef908 100644 --- a/src/network/networkd-netdev-veth.c +++ b/src/network/networkd-netdev-veth.c @@ -27,47 +27,15 @@ #include "sd-rtnl.h" #include "networkd-netdev-veth.h" -static int netdev_veth_fill_message_create(NetDev *netdev, sd_rtnl_message *m) { +static int netdev_veth_fill_message_create(NetDev *netdev, Link *link, sd_rtnl_message *m) { + Veth *v = VETH(netdev); int r; assert(netdev); - assert(netdev->ifname); + assert(!link); + assert(v); 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, - "Could 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, @@ -76,16 +44,16 @@ static int netdev_veth_fill_message_create(NetDev *netdev, sd_rtnl_message *m) { return r; } - if (netdev->ifname_peer) { - r = sd_rtnl_message_append_string(m, IFLA_IFNAME, netdev->ifname_peer); + if (v->ifname_peer) { + r = sd_rtnl_message_append_string(m, IFLA_IFNAME, v->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 (v->mac_peer) { + r = sd_rtnl_message_append_ether_addr(m, IFLA_ADDRESS, v->mac_peer); if (r < 0) { log_error_netdev(netdev, "Could not append IFLA_ADDRESS attribute: %s", @@ -102,34 +70,28 @@ static int netdev_veth_fill_message_create(NetDev *netdev, sd_rtnl_message *m) { 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) { + Veth *v = VETH(netdev); int r; assert(netdev); + assert(v); assert(filename); - if (!netdev->ifname_peer) { + if (!v->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 (!v->mac_peer) { + r = netdev_get_mac(v->ifname_peer, &v->mac_peer); if (r < 0) { log_warning("Failed to generate predictable MAC address for %s. Ignoring", - netdev->ifname_peer); + v->ifname_peer); return -EINVAL; } } @@ -137,7 +99,21 @@ static int netdev_veth_verify(NetDev *netdev, const char *filename) { return 0; } +static void veth_done(NetDev *n) { + Veth *v = VETH(n); + + assert(n); + assert(v); + + free(v->ifname_peer); + free(v->mac_peer); +} + const NetDevVTable veth_vtable = { + .object_size = sizeof(Veth), + .sections = "Match\0NetDev\0Peer\0", + .done = veth_done, .fill_message_create = netdev_veth_fill_message_create, + .create_type = NETDEV_CREATE_INDEPENDENT, .config_verify = netdev_veth_verify, }; diff --git a/src/network/networkd-netdev-veth.h b/src/network/networkd-netdev-veth.h index 93dcdfa1a..85d8b49a7 100644 --- a/src/network/networkd-netdev-veth.h +++ b/src/network/networkd-netdev-veth.h @@ -21,6 +21,15 @@ #pragma once +typedef struct Veth Veth; + #include "networkd-netdev.h" +struct Veth { + NetDev meta; + + char *ifname_peer; + struct ether_addr *mac_peer; +}; + extern const NetDevVTable veth_vtable; diff --git a/src/network/networkd-netdev-vlan.c b/src/network/networkd-netdev-vlan.c index b625f4b07..13c445673 100644 --- a/src/network/networkd-netdev-vlan.c +++ b/src/network/networkd-netdev-vlan.c @@ -26,68 +26,16 @@ #include "list.h" static int netdev_vlan_fill_message_create(NetDev *netdev, Link *link, sd_rtnl_message *req) { + VLan *v = VLAN(netdev); int r; assert(netdev); - assert(netdev->ifname); - assert(netdev->kind == NETDEV_KIND_VLAN); + assert(v); 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, - "Could 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 (v->id <= VLANID_MAX) { + r = sd_rtnl_message_append_u16(req, IFLA_VLAN_ID, v->id); if (r < 0) { log_error_netdev(netdev, "Could not append IFLA_VLAN_ID attribute: %s", @@ -96,38 +44,38 @@ static int netdev_vlan_fill_message_create(NetDev *netdev, Link *link, sd_rtnl_m } } - 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) { + VLan *v = VLAN(netdev); + assert(netdev); + assert(v); assert(filename); - if (netdev->vlanid > VLANID_MAX) { - log_warning("VLAN without valid Id configured in %s. Ignoring", filename); + if (v->id > VLANID_MAX) { + log_warning("VLAN without valid Id (%"PRIu64") configured in %s. Ignoring", v->id, filename); return -EINVAL; } return 0; } +static void vlan_init(NetDev *netdev) { + VLan *v = VLAN(netdev); + + assert(netdev); + assert(v); + + v->id = VLANID_MAX + 1; +} + const NetDevVTable vlan_vtable = { - .fill_message_create_on_link = netdev_vlan_fill_message_create, + .object_size = sizeof(VLan), + .init = vlan_init, + .sections = "Match\0NetDev\0VLAN\0", + .fill_message_create = netdev_vlan_fill_message_create, + .create_type = NETDEV_CREATE_STACKED, .config_verify = netdev_vlan_verify, }; diff --git a/src/network/networkd-netdev-vlan.h b/src/network/networkd-netdev-vlan.h index 95f630f19..0c0fbbe09 100644 --- a/src/network/networkd-netdev-vlan.h +++ b/src/network/networkd-netdev-vlan.h @@ -21,8 +21,16 @@ #pragma once +typedef struct VLan VLan; + #include "networkd-netdev.h" #define VLANID_MAX 4094 +struct VLan { + NetDev meta; + + uint64_t id; +}; + extern const NetDevVTable vlan_vtable; diff --git a/src/network/networkd-netdev-vxlan.c b/src/network/networkd-netdev-vxlan.c index 38692c687..215c11729 100644 --- a/src/network/networkd-netdev-vxlan.c +++ b/src/network/networkd-netdev-vxlan.c @@ -28,39 +28,17 @@ #include "missing.h" static int netdev_vxlan_fill_message_create(NetDev *netdev, Link *link, sd_rtnl_message *m) { + VxLan *v = VXLAN(netdev); int r; assert(netdev); + assert(v); 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 (v->id <= VXLAN_VID_MAX) { + r = sd_rtnl_message_append_u32(m, IFLA_VXLAN_ID, v->id); if (r < 0) { log_error_netdev(netdev, "Could not append IFLA_VXLAN_ID attribute: %s", @@ -69,7 +47,7 @@ static int netdev_vxlan_fill_message_create(NetDev *netdev, Link *link, sd_rtnl_ } } - r = sd_rtnl_message_append_in_addr(m, IFLA_VXLAN_GROUP, &netdev->group.in); + r = sd_rtnl_message_append_in_addr(m, IFLA_VXLAN_GROUP, &v->group.in); if (r < 0) { log_error_netdev(netdev, "Could not append IFLA_VXLAN_GROUP attribute: %s", @@ -85,8 +63,8 @@ static int netdev_vxlan_fill_message_create(NetDev *netdev, Link *link, sd_rtnl_ return r; } - if(netdev->ttl) { - r = sd_rtnl_message_append_u8(m, IFLA_VXLAN_TTL, netdev->ttl); + if(v->ttl) { + r = sd_rtnl_message_append_u8(m, IFLA_VXLAN_TTL, v->ttl); if (r < 0) { log_error_netdev(netdev, "Could not append IFLA_VXLAN_TTL attribute: %s", @@ -95,8 +73,8 @@ static int netdev_vxlan_fill_message_create(NetDev *netdev, Link *link, sd_rtnl_ } } - if(netdev->tos) { - r = sd_rtnl_message_append_u8(m, IFLA_VXLAN_TOS, netdev->tos); + if(v->tos) { + r = sd_rtnl_message_append_u8(m, IFLA_VXLAN_TOS, v->tos); if (r < 0) { log_error_netdev(netdev, "Could not append IFLA_VXLAN_TOS attribute: %s", @@ -105,7 +83,7 @@ static int netdev_vxlan_fill_message_create(NetDev *netdev, Link *link, sd_rtnl_ } } - r = sd_rtnl_message_append_u8(m, IFLA_VXLAN_LEARNING, netdev->learning); + r = sd_rtnl_message_append_u8(m, IFLA_VXLAN_LEARNING, v->learning); if (r < 0) { log_error_netdev(netdev, "Could not append IFLA_VXLAN_LEARNING attribute: %s", @@ -113,22 +91,17 @@ static int netdev_vxlan_fill_message_create(NetDev *netdev, Link *link, sd_rtnl_ 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) { + VxLan *v = VXLAN(netdev); + assert(netdev); + assert(v); assert(filename); - if (netdev->vxlanid > VXLAN_VID_MAX) { + if (v->id > VXLAN_VID_MAX) { log_warning("VXLAN without valid Id configured in %s. Ignoring", filename); return -EINVAL; } @@ -136,7 +109,21 @@ static int netdev_vxlan_verify(NetDev *netdev, const char *filename) { return 0; } +static void vxlan_init(NetDev *netdev) { + VxLan *v = VXLAN(netdev); + + assert(netdev); + assert(v); + + v->id = VXLAN_VID_MAX + 1; + v->learning = true; +} + const NetDevVTable vxlan_vtable = { - .fill_message_create_on_link = netdev_vxlan_fill_message_create, + .object_size = sizeof(VxLan), + .init = vxlan_init, + .sections = "Match\0NetDev\0VXLAN\0", + .fill_message_create = netdev_vxlan_fill_message_create, + .create_type = NETDEV_CREATE_STACKED, .config_verify = netdev_vxlan_verify, }; diff --git a/src/network/networkd-netdev-vxlan.h b/src/network/networkd-netdev-vxlan.h index a2de2713c..8c906f107 100644 --- a/src/network/networkd-netdev-vxlan.h +++ b/src/network/networkd-netdev-vxlan.h @@ -21,8 +21,22 @@ #pragma once +typedef struct VxLan VxLan; + #include "networkd-netdev.h" +#include "in-addr-util.h" + #define VXLAN_VID_MAX (1u << 24) - 1 +struct VxLan { + NetDev meta; + + uint64_t id; + union in_addr_union group; + unsigned tos; + unsigned ttl; + bool learning; +}; + extern const NetDevVTable vxlan_vtable; diff --git a/src/network/networkd-netdev.c b/src/network/networkd-netdev.c index 86f2250c8..4a6f6e347 100644 --- a/src/network/networkd-netdev.c +++ b/src/network/networkd-netdev.c @@ -22,15 +22,6 @@ #include #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" @@ -111,17 +102,17 @@ static void netdev_free(NetDev *netdev) { free(netdev->description); free(netdev->ifname); - free(netdev->ifname_peer); free(netdev->mac); - free(netdev->mac_peer); - free(netdev->user_name); - free(netdev->group_name); condition_free_list(netdev->match_host); condition_free_list(netdev->match_virt); condition_free_list(netdev->match_kernel); condition_free_list(netdev->match_arch); + if (NETDEV_VTABLE(netdev) && + NETDEV_VTABLE(netdev)->done) + NETDEV_VTABLE(netdev)->done(netdev); + free(netdev); } @@ -268,6 +259,8 @@ static int netdev_create_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userda return 1; } + log_debug_netdev(netdev, "created"); + return 1; } @@ -294,46 +287,10 @@ int netdev_enslave(NetDev *netdev, Link *link, sd_rtnl_message_handler_t callbac link_ref(link); LIST_PREPEND(callbacks, netdev->callbacks, cb); - } - - 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) { - int r; - - assert(netdev); - assert(netdev->manager); - assert(netdev->manager->rtnl); - assert(NETDEV_VTABLE(netdev)); - - 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"); + log_debug_netdev(netdev, "will enslave '%s', when reday", + link->ifname); + } return 0; } @@ -487,8 +444,156 @@ int netdev_get_mac(const char *ifname, struct ether_addr **ret) { return 0; } +static int netdev_create(NetDev *netdev, Link *link) { + int r; + + assert(netdev); + + /* create netdev */ + if (NETDEV_VTABLE(netdev)->create) { + r = NETDEV_VTABLE(netdev)->create(netdev); + if (r < 0) + return r; + + log_debug_netdev(netdev, "created"); + } else { + _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; + } + + 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, + "Could not append IFLA_ADDRESS 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 (link) { + r = sd_rtnl_message_append_u32(m, IFLA_LINK, link->ifindex); + if (r < 0) { + log_error_netdev(netdev, + "Colud not append IFLA_LINK 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_VTABLE(netdev)->fill_message_create) { + r = NETDEV_VTABLE(netdev)->fill_message_create(netdev, link, m); + if (r < 0) + 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; + } + + + 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; + } + + netdev_ref(netdev); + + netdev->state = NETDEV_STATE_CREATING; + + log_debug_netdev(netdev, "creating"); + } + + 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) { + int r; + + assert(netdev); + assert(netdev->manager); + assert(netdev->manager->rtnl); + assert(NETDEV_VTABLE(netdev)); + + switch (NETDEV_VTABLE(netdev)->create_type) { + case NETDEV_CREATE_MASTER: + r = netdev_enslave(netdev, link, callback); + if (r < 0) + return r; + + break; + case NETDEV_CREATE_STACKED: + r = netdev_create(netdev, link); + if (r < 0) + return r; + + break; + default: + assert_not_reached("Can not join independent netdev"); + } + + return 0; +} + static int netdev_load_one(Manager *manager, const char *filename) { _cleanup_netdev_unref_ NetDev *netdev = NULL; + _cleanup_free_ NetDev *netdev_raw = NULL; _cleanup_fclose_ FILE *file = NULL; int r; @@ -508,69 +613,65 @@ static int netdev_load_one(Manager *manager, const char *filename) { return 0; } - netdev = new0(NetDev, 1); - if (!netdev) + netdev_raw = new0(NetDev, 1); + if (!netdev_raw) return log_oom(); - netdev->n_ref = 1; - netdev->manager = manager; - netdev->state = _NETDEV_STATE_INVALID; - netdev->kind = _NETDEV_KIND_INVALID; - netdev->macvlan_mode = _NETDEV_MACVLAN_MODE_INVALID; - netdev->bond_mode = _NETDEV_BOND_MODE_INVALID; - netdev->vlanid = VLANID_MAX + 1; - netdev->vxlanid = VXLAN_VID_MAX + 1; - netdev->tunnel_pmtudisc = true; - netdev->learning = true; + netdev_raw->kind = _NETDEV_KIND_INVALID; r = config_parse(NULL, filename, file, - "Match\0NetDev\0VLAN\0MACVLAN\0VXLAN\0Tunnel\0Peer\0Tun\0Tap\0Bond\0", + "Match\0NetDev\0", config_item_perf_lookup, network_netdev_gperf_lookup, - false, false, true, netdev); + true, false, true, netdev_raw); if (r < 0) return r; + r = fseek(file, 0, SEEK_SET); + if (r < 0) + return -errno; + /* 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, + netdev_raw->match_host, netdev_raw->match_virt, + netdev_raw->match_kernel, netdev_raw->match_arch, NULL, NULL, NULL, NULL, NULL, NULL) <= 0) return 0; - if (!NETDEV_VTABLE(netdev)) { + if (!NETDEV_VTABLE(netdev_raw)) { log_warning("NetDev with invalid Kind configured in %s. Ignoring", filename); return 0; } - /* verify configuration */ - if (NETDEV_VTABLE(netdev)->config_verify) { - r = NETDEV_VTABLE(netdev)->config_verify(netdev, filename); - if (r < 0) - return 0; - } - - if (!netdev->ifname) { + if (!netdev_raw->ifname) { log_warning("NetDev without Name configured in %s. Ignoring", filename); return 0; } - if (netdev->kind != NETDEV_KIND_VLAN && netdev->vlanid <= VLANID_MAX) { - log_warning("VLAN Id configured for a %s in %s. Ignoring", - netdev_kind_to_string(netdev->kind), filename); - return 0; - } + netdev = malloc0(NETDEV_VTABLE(netdev_raw)->object_size); + if (!netdev) + return log_oom(); - if (netdev->kind != NETDEV_KIND_VXLAN && netdev->vxlanid <= VXLAN_VID_MAX) { - log_warning("VXLAN Id configured for a %s in %s. Ignoring", - netdev_kind_to_string(netdev->kind), filename); - return 0; - } + netdev->n_ref = 1; + netdev->manager = manager; + netdev->state = _NETDEV_STATE_INVALID; + netdev->kind = netdev_raw->kind; + netdev->ifname = netdev_raw->ifname; - if (netdev->kind != NETDEV_KIND_MACVLAN && - netdev->macvlan_mode != _NETDEV_MACVLAN_MODE_INVALID) { - log_warning("MACVLAN Mode configured for a %s in %s. Ignoring", - netdev_kind_to_string(netdev->kind), filename); - return 0; + if (NETDEV_VTABLE(netdev)->init) + NETDEV_VTABLE(netdev)->init(netdev); + + r = config_parse(NULL, filename, file, + NETDEV_VTABLE(netdev)->sections, + config_item_perf_lookup, network_netdev_gperf_lookup, + false, false, false, netdev); + if (r < 0) + return r; + + /* verify configuration */ + if (NETDEV_VTABLE(netdev)->config_verify) { + r = NETDEV_VTABLE(netdev)->config_verify(netdev, filename); + if (r < 0) + return 0; } netdev->filename = strdup(filename); @@ -594,38 +695,16 @@ static int netdev_load_one(Manager *manager, const char *filename) { log_debug_netdev(netdev, "loaded %s", netdev_kind_to_string(netdev->kind)); - /* create netdev */ - 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; - } - - r = NETDEV_VTABLE(netdev)->fill_message_create(netdev, m); + switch (NETDEV_VTABLE(netdev)->create_type) { + case NETDEV_CREATE_MASTER: + case NETDEV_CREATE_INDEPENDENT: + r = netdev_create(netdev, NULL); if (r < 0) return r; - 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; - } - - 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; } netdev = NULL; diff --git a/src/network/networkd-netdev.h b/src/network/networkd-netdev.h index 042e1601c..e9a8a169d 100644 --- a/src/network/networkd-netdev.h +++ b/src/network/networkd-netdev.h @@ -66,6 +66,14 @@ typedef enum NetDevState { _NETDEV_STATE_INVALID = -1, } NetDevState; +typedef enum NetDevCreateType { + NETDEV_CREATE_INDEPENDENT, + NETDEV_CREATE_MASTER, + NETDEV_CREATE_STACKED, + _NETDEV_CREATE_MAX, + _NETDEV_CREATE_INVALID = -1, +} NetDevCreateType; + struct NetDev { Manager *manager; @@ -78,49 +86,50 @@ struct NetDev { Condition *match_kernel; Condition *match_arch; + NetDevState state; + NetDevKind kind; 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; - + size_t mtu; int ifindex; - NetDevState state; - - bool tunnel_pmtudisc; - bool learning; - bool one_queue; - bool multi_queue; - bool packet_info; - - unsigned ttl; - unsigned tos; - int family; - union in_addr_union local; - union in_addr_union remote; - union in_addr_union group; LIST_HEAD(netdev_join_callback, callbacks); }; +#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-veth.h" +#include "networkd-netdev-tunnel.h" +#include "networkd-netdev-dummy.h" +#include "networkd-netdev-tuntap.h" + struct NetDevVTable { - /* fill in message to create netdev */ - int (*fill_message_create)(NetDev *netdev, sd_rtnl_message *message); + /* How much memory does an object of this unit type need */ + size_t object_size; + + /* Config file sections this netdev kind understands, separated + * by NUL chars */ + const char *sections; - /* 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); + /* This should reset all type-specific variables. This should + * not allocate memory, and is called with zero-initialized + * data. It should hence only initialize variables that need + * to be set != 0. */ + void (*init)(NetDev *n); - /* fill in message to enslave link by netdev */ - int (*enslave)(NetDev *netdev, Link *link, sd_rtnl_message_handler_t callback); + /* This should free all kind-specific variables. It should be + * idempotent. */ + void (*done)(NetDev *n); + + /* fill in message to create netdev */ + int (*fill_message_create)(NetDev *netdev, Link *link, sd_rtnl_message *message); + + /* specifies if netdev is independent, or a master device or a stacked device */ + NetDevCreateType create_type; /* create netdev, if not done via rtnl */ int (*create)(NetDev *netdev); @@ -133,6 +142,32 @@ extern const NetDevVTable * const netdev_vtable[_NETDEV_KIND_MAX]; #define NETDEV_VTABLE(n) netdev_vtable[(n)->kind] +/* For casting a netdev into the various netdev kinds */ +#define DEFINE_CAST(UPPERCASE, MixedCase) \ + static inline MixedCase* UPPERCASE(NetDev *n) { \ + if (_unlikely_(!n || n->kind != NETDEV_KIND_##UPPERCASE)) \ + return NULL; \ + \ + return (MixedCase*) n; \ + } + +/* For casting the various netdev kinds into a netdev */ +#define NETDEV(n) (&(n)->meta) + +DEFINE_CAST(BRIDGE, Bridge); +DEFINE_CAST(BOND, Bond); +DEFINE_CAST(VLAN, VLan); +DEFINE_CAST(MACVLAN, MacVlan); +DEFINE_CAST(VXLAN, VxLan); +DEFINE_CAST(IPIP, Tunnel); +DEFINE_CAST(GRE, Tunnel); +DEFINE_CAST(SIT, Tunnel); +DEFINE_CAST(VTI, Tunnel); +DEFINE_CAST(VETH, Veth); +DEFINE_CAST(DUMMY, Dummy); +DEFINE_CAST(TUN, TunTap); +DEFINE_CAST(TAP, TunTap); + int netdev_load(Manager *manager); void netdev_drop(NetDev *netdev); @@ -167,4 +202,4 @@ const struct ConfigPerfItem* network_netdev_gperf_lookup(const char *key, unsign #define log_struct_netdev(level, netdev, ...) log_struct(level, "INTERFACE=%s", netdev->ifname, __VA_ARGS__) -#define NETDEV(netdev) "INTERFACE=%s", netdev->ifname +#define NETDEVIF(netdev) "INTERFACE=%s", netdev->ifname diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index 3e46a1a80..bc9304291 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -66,11 +66,11 @@ static int network_load_one(Manager *manager, const char *filename) { if (!network->vlans) return log_oom(); - network->macvlans = hashmap_new(uint64_hash_func, uint64_compare_func); + network->macvlans = hashmap_new(string_hash_func, string_compare_func); if (!network->macvlans) return log_oom(); - network->vxlans = hashmap_new(uint64_hash_func, uint64_compare_func); + network->vxlans = hashmap_new(string_hash_func, string_compare_func); if (!network->vxlans) return log_oom(); @@ -323,10 +323,11 @@ int config_parse_netdev(const char *unit, break; case NETDEV_KIND_VLAN: - r = hashmap_put(network->vlans, &netdev->vlanid, netdev); + r = hashmap_put(network->vlans, netdev->ifname, netdev); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, EINVAL, - "Can not add VLAN to network: %s", rvalue); + "Can not add VLAN '%s' to network: %s", + rvalue, strerror(-r)); return 0; } @@ -335,7 +336,8 @@ int config_parse_netdev(const char *unit, r = hashmap_put(network->macvlans, netdev->ifname, netdev); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, EINVAL, - "Can not add MACVLAN to network: %s", rvalue); + "Can not add MACVLAN '%s' to network: %s", + rvalue, strerror(-r)); return 0; } @@ -344,7 +346,8 @@ int config_parse_netdev(const char *unit, r = hashmap_put(network->vxlans, netdev->ifname, netdev); if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, EINVAL, - "Can not add VXLAN to network: %s", rvalue); + "Can not add VXLAN '%s' to network: %s", + rvalue, strerror(-r)); return 0; } -- 2.30.2