[systemd-devel] [PATCH] networkd: Introduce tun/tap device
Lennart Poettering
lennart at poettering.net
Mon Jun 30 10:33:46 PDT 2014
On Mon, 30.06.14 22:23, Susant Sahani (susant at redhat.com) wrote:
> This patch introduces TUN/TAP device creation support
> to networkd.
Please always also include the updates to the respective man pages that
document these settings in these patches! THanks!
>
> Example conf to create a tap device:
>
> file: tap.netdev
> ------------------
> [NetDev]
> Name=tap-test
> Kind=tap
>
> [Tap]
> OneQueue=true
> MultiQueue=true
> PacketInfo=true
> ------------------
>
> Modifications:
>
> Added:
> 1. file networkd-tuntap.c
> 3. netdev kind NETDEV_KIND_TUN and NETDEV_KIND_TAP
> 2. Tun and Tap Sections and config params to parse
> conf and gperf conf parameters
>
> TODO:
> 1. Add user(uid) group(gid) parameters
> ---
> Makefile.am | 1 +
> src/network/networkd-netdev-gperf.gperf | 6 ++
> src/network/networkd-netdev.c | 34 ++++++++---
> src/network/networkd-tuntap.c | 101 ++++++++++++++++++++++++++++++++
> src/network/networkd.h | 7 +++
> 5 files changed, 142 insertions(+), 7 deletions(-)
> create mode 100644 src/network/networkd-tuntap.c
>
> diff --git a/Makefile.am b/Makefile.am
> index bb85b2c..c947731 100644
> --- a/Makefile.am
> +++ b/Makefile.am
> @@ -4514,6 +4514,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..38133c8 100644
> --- a/src/network/networkd-netdev-gperf.gperf
> +++ b/src/network/networkd-netdev-gperf.gperf
> @@ -38,3 +38,9 @@ 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)
> +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)
> +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)
> diff --git a/src/network/networkd-netdev.c b/src/network/networkd-netdev.c
> index dcf7596..a25cb84 100644
> --- a/src/network/networkd-netdev.c
> +++ b/src/network/networkd-netdev.c
> @@ -41,7 +41,9 @@ 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_TUN] = "tun",
> + [NETDEV_KIND_TAP] = "tap",
> };
>
> DEFINE_STRING_TABLE_LOOKUP(netdev_kind, NetDevKind);
> @@ -221,6 +223,7 @@ static int netdev_enter_ready(NetDev *netdev) {
>
> return 0;
> }
> +
> static int netdev_create_handler(sd_rtnl *rtnl, sd_rtnl_message *m, void *userdata) {
> NetDev *netdev = userdata;
> int r;
> @@ -521,11 +524,19 @@ 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;
> + switch(netdev->kind) {
> + case NETDEV_KIND_TUN:
> + case NETDEV_KIND_TAP:
> + break;
> + default:
> + 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;
> + }
> + break;
> }
>
> netdev->ifindex = ifindex;
> @@ -617,9 +628,10 @@ static int netdev_load_one(Manager *manager, const char *filename) {
> 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\0Tun\0Tap\0",
> config_item_perf_lookup, (void*) network_netdev_gperf_lookup,
> false, false, netdev);
> if (r < 0) {
> @@ -719,6 +731,14 @@ static int netdev_load_one(Manager *manager, const char *filename) {
> if (r < 0)
> return r;
> break;
> +
> + case NETDEV_KIND_TUN:
> + case NETDEV_KIND_TAP:
> + 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..69a77f2
> --- /dev/null
> +++ b/src/network/networkd-tuntap.c
> @@ -0,0 +1,101 @@
> +/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
> +
> +/***
> + This file is part of systemd.
> +
> + Copyright 2014 Susant Sahani <susant at redhat.com>
> +
> + systemd is free software; you can redistribute it and/or modify it
> + under the terms of the GNU Lesser General Public License as published by
> + the Free Software Foundation; either version 2.1 of the License, or
> + (at your option) any later version.
> +
> + systemd is distributed in the hope that it will be useful, but
> + WITHOUT ANY WARRANTY; without even the implied warranty of
> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + Lesser General Public License for more details.
> +
> + You should have received a copy of the GNU Lesser General Public License
> + along with systemd; If not, see <http://www.gnu.org/licenses/>.
> +***/
> +
> +#include <sys/ioctl.h>
> +#include <net/if.h>
> +#include <linux/if_tun.h>
> +
> +#include "networkd.h"
> +
> +#define TUN_DEV "/dev/net/tun"
> +
> +
> +static int netdev_fill_tuntap_message(NetDev *netdev, struct ifreq *ifr) {
> +
> + assert(netdev);
> + assert(ifr);
> +
> + memset(ifr, 0, sizeof(*ifr));
> +
> + if (netdev->kind != NETDEV_KIND_TAP)
> + ifr->ifr_flags |= IFF_TUN;
> + else
> + ifr->ifr_flags |= IFF_TAP;
> +
> + 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) {
> + _cleanup_close_ int fd;
> + int r = 0;
> +
> + fd = open(TUN_DEV, O_RDWR);
> + if (fd < 0)
> + return -errno;
> +
> + r = ioctl(fd, TUNSETIFF, ifr);
> + if (r < 0)
> + return -errno;
> +
> + r = ioctl(fd, TUNSETPERSIST, 1);
> + if (r < 0)
> + return -errno;
> +
> + return r;
> +}
> +
> +int netdev_create_tuntap(NetDev *netdev) {
> + struct ifreq ifr;
> + int r;
> +
> + assert(netdev);
> + assert(netdev->ifname);
> +
> + switch(netdev->kind) {
> + case NETDEV_KIND_TUN:
> + case NETDEV_KIND_TAP:
> + break;
> + default:
> + return -ENOTSUP;
> + }
> +
> + r = netdev_fill_tuntap_message(netdev, &ifr);
> + if(r < 0)
> + return r;
> +
> + log_debug_netdev(netdev, "Creating tuntap netdev: %s",
> + netdev_kind_to_string(netdev->kind));
> +
> + return netdev_tuntap_add(&ifr);
> +}
> diff --git a/src/network/networkd.h b/src/network/networkd.h
> index 11268de..f943a10 100644
> --- a/src/network/networkd.h
> +++ b/src/network/networkd.h
> @@ -81,6 +81,8 @@ typedef enum NetDevKind {
> NETDEV_KIND_SIT,
> NETDEV_KIND_VETH,
> NETDEV_KIND_VTI,
> + NETDEV_KIND_TUN,
> + NETDEV_KIND_TAP,
> _NETDEV_KIND_MAX,
> _NETDEV_KIND_INVALID = -1
> } NetDevKind;
> @@ -123,6 +125,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;
> @@ -352,6 +358,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_;
Lennart
--
Lennart Poettering, Red Hat
More information about the systemd-devel
mailing list