This patch introduces tuntap support to networkd. Example conf
file : tuntap.netdev [NetDev] Name=tuntap-test Kind=tuntap [TUNTAP] Mode=tap OneQueue=true MultiQueue=true PacketInfo=true Added: 1. file networkd-tuntap.c 2. enum TunTapKind 3. NETDEV_KIND_TUNTAP 4. TUNTAP Section to parse conf and gperf conf parameters TODO: 1. Add user(uid) group(gid) parameters --- Makefile.am | 1 + src/network/networkd-netdev-gperf.gperf | 4 ++ src/network/networkd-netdev.c | 40 +++++++++--- src/network/networkd-tuntap.c | 106 ++++++++++++++++++++++++++++++++ src/network/networkd.h | 19 ++++++ 5 files changed, 163 insertions(+), 7 deletions(-) create mode 100644 src/network/networkd-tuntap.c diff --git a/Makefile.am b/Makefile.am index 37a164e..d9cba3b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -4479,6 +4479,7 @@ libsystemd_networkd_core_la_SOURCES = \ src/network/networkd-tunnel.c \ src/network/networkd-veth.c \ src/network/networkd-vxlan.c \ + src/network/networkd-tuntap.c \ src/network/networkd-network.c \ src/network/networkd-address.c \ src/network/networkd-route.c \ diff --git a/src/network/networkd-netdev-gperf.gperf b/src/network/networkd-netdev-gperf.gperf index 9125e1d..d29e41d 100644 --- a/src/network/networkd-netdev-gperf.gperf +++ b/src/network/networkd-netdev-gperf.gperf @@ -38,3 +38,7 @@ VXLAN.Group, config_parse_tunnel_address, 0, 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) +TUNTAP.Mode, config_parse_tuntap_kind, 0, offsetof(NetDev, tuntap_kind) +TUNTAP.OneQueue, config_parse_bool, 0, offsetof(NetDev, one_queue) +TUNTAP.MultiQueue, config_parse_bool, 0, offsetof(NetDev, multi_queue) +TUNTAP.PacketInfo, config_parse_bool, 0, offsetof(NetDev, packet_info) diff --git a/src/network/networkd-netdev.c b/src/network/networkd-netdev.c index dcf7596..41db707 100644 --- a/src/network/networkd-netdev.c +++ b/src/network/networkd-netdev.c @@ -41,7 +41,8 @@ static const char* const netdev_kind_table[_NETDEV_KIND_MAX] = { [NETDEV_KIND_GRE] = "gre", [NETDEV_KIND_SIT] = "sit", [NETDEV_KIND_VETH] = "veth", - [NETDEV_KIND_VTI] = "vti" + [NETDEV_KIND_VTI] = "vti", + [NETDEV_KIND_TUNTAP] = "tuntap" }; DEFINE_STRING_TABLE_LOOKUP(netdev_kind, NetDevKind); @@ -57,6 +58,14 @@ 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"); +static const char* const tuntap_kind_table[_TUNTAP_KIND_MAX] = { + [TUNTAP_KIND_TAP] = "tap", + [TUNTAP_KIND_TUNNEL] = "tunnel", +}; + +DEFINE_STRING_TABLE_LOOKUP(tuntap_kind, TunTapKind); +DEFINE_CONFIG_PARSE_ENUM(config_parse_tuntap_kind, tuntap_kind, TunTapKind, "Failed to parse tuntap kind"); + static void netdev_cancel_callbacks(NetDev *netdev) { _cleanup_rtnl_message_unref_ sd_rtnl_message *m = NULL; netdev_enslave_callback *callback; @@ -521,11 +530,13 @@ int netdev_set_ifindex(NetDev *netdev, sd_rtnl_message *message) { return -EINVAL; } - if (!streq(kind, received_kind)) { - log_error_netdev(netdev, "Received newlink with wrong KIND %s, " - "expected %s", received_kind, kind); - netdev_enter_failed(netdev); - return r; + if (netdev->kind != NETDEV_KIND_TUNTAP) { + if (!streq(kind, received_kind)) { + log_error_netdev(netdev, "Received newlink with wrong KIND %s, " + "expected %s", received_kind, kind); + netdev_enter_failed(netdev); + return r; + } } netdev->ifindex = ifindex; @@ -612,14 +623,16 @@ static int netdev_load_one(Manager *manager, const char *filename) { netdev->manager = manager; netdev->state = _NETDEV_STATE_INVALID; netdev->kind = _NETDEV_KIND_INVALID; + netdev->tuntap_kind = _TUNTAP_KIND_INVALID; netdev->macvlan_mode = _NETDEV_MACVLAN_MODE_INVALID; netdev->vlanid = VLANID_MAX + 1; netdev->vxlanid = VXLAN_VID_MAX + 1; netdev->tunnel_pmtudisc = true; netdev->learning = true; + netdev->packet_info = true; r = config_parse(NULL, filename, file, - "Match\0NetDev\0VLAN\0MACVLAN\0VXLAN\0Tunnel\0Peer\0", + "Match\0NetDev\0VLAN\0MACVLAN\0VXLAN\0Tunnel\0Peer\0TUNTAP\0", config_item_perf_lookup, (void*) network_netdev_gperf_lookup, false, false, netdev); if (r < 0) { @@ -666,6 +679,12 @@ static int netdev_load_one(Manager *manager, const char *filename) { return 0; } + if (netdev->kind == NETDEV_KIND_TUNTAP && + netdev->tuntap_kind == _TUNTAP_KIND_INVALID) { + log_warning("TunTap without Mode configured in %s. Ignoring", filename); + return 0; + } + netdev->filename = strdup(filename); if (!netdev->filename) return log_oom(); @@ -719,6 +738,13 @@ static int netdev_load_one(Manager *manager, const char *filename) { if (r < 0) return r; break; + + case NETDEV_KIND_TUNTAP: + r = netdev_create_tuntap(netdev); + if (r < 0) + return r; + break; + default: break; } diff --git a/src/network/networkd-tuntap.c b/src/network/networkd-tuntap.c new file mode 100644 index 0000000..f138b8a --- /dev/null +++ b/src/network/networkd-tuntap.c @@ -0,0 +1,106 @@ +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ + +/*** + This file is part of systemd. + + Copyright 2014 Susant Sahani <sus...@redhat.com> + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +#include <sys/ioctl.h> +#include <net/if.h> +#include <linux/if_tun.h> + +#include "networkd.h" + +#define TUN_DEV "/dev/net/tun" + + +static int netdev_fill_tuntap_message(NetDev *netdev, struct ifreq *ifr) { + + assert(netdev); + assert(ifr); + + memset(ifr, 0, sizeof(*ifr)); + + if(netdev->tuntap_kind == TUNTAP_KIND_TAP) + ifr->ifr_flags |= IFF_TAP; + else + ifr->ifr_flags |= IFF_TUN; + + if(!netdev->packet_info) + ifr->ifr_flags &= ~IFF_NO_PI; + else + ifr->ifr_flags |= IFF_NO_PI; + + if(netdev->one_queue) + ifr->ifr_flags |= IFF_ONE_QUEUE; + + if(netdev->multi_queue) + ifr->ifr_flags |= IFF_MULTI_QUEUE; + + strncpy(ifr->ifr_name, netdev->ifname, IFNAMSIZ-1); + + return 0; +} + +static int netdev_tuntap_add(struct ifreq *ifr) +{ + int fd; + int r = 0; + + fd = open(TUN_DEV, O_RDWR); + if (fd < 0) { + r = -errno; + goto fail; + } + + r = ioctl(fd, TUNSETIFF, ifr); + if (r < 0) { + r = -errno; + goto fail; + } + + r = ioctl(fd, TUNSETPERSIST, 1); + if (r < 0) { + r = -errno; + goto fail; + } + + fail: + close(fd); + + return r; +} + +int netdev_create_tuntap(NetDev *netdev) { + int r; + struct ifreq ifr; + + assert(netdev); + assert(netdev->ifname); + + if(netdev->kind != NETDEV_KIND_TUNTAP) + 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(&ifr); +} diff --git a/src/network/networkd.h b/src/network/networkd.h index b7b1d90..ab1ca4e 100644 --- a/src/network/networkd.h +++ b/src/network/networkd.h @@ -80,6 +80,7 @@ typedef enum NetDevKind { NETDEV_KIND_SIT, NETDEV_KIND_VETH, NETDEV_KIND_VTI, + NETDEV_KIND_TUNTAP, _NETDEV_KIND_MAX, _NETDEV_KIND_INVALID = -1 } NetDevKind; @@ -93,6 +94,13 @@ typedef enum NetDevState { _NETDEV_STATE_INVALID = -1, } NetDevState; +typedef enum TunTapKind { + TUNTAP_KIND_TAP, + TUNTAP_KIND_TUNNEL, + _TUNTAP_KIND_MAX, + _TUNTAP_KIND_INVALID = -1 +} TunTapKind; + struct NetDev { Manager *manager; @@ -112,6 +120,7 @@ struct NetDev { struct ether_addr *mac; struct ether_addr *mac_peer; NetDevKind kind; + TunTapKind tuntap_kind; uint64_t vlanid; uint64_t vxlanid; @@ -122,6 +131,10 @@ struct NetDev { bool tunnel_pmtudisc; bool learning; + bool one_queue; + bool multi_queue; + bool packet_info; + unsigned ttl; unsigned tos; struct in_addr local; @@ -342,6 +355,7 @@ int netdev_enslave(NetDev *netdev, Link *link, sd_rtnl_message_handler_t cb); int netdev_create_tunnel(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_tuntap(NetDev *netdev); const char *netdev_kind_to_string(NetDevKind d) _const_; NetDevKind netdev_kind_from_string(const char *d) _pure_; @@ -349,10 +363,15 @@ 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 *tuntap_kind_to_string(TunTapKind d) _const_; +TunTapKind tuntap_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); 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_tuntap_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); -- 1.9.3 _______________________________________________ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel