[systemd-devel] [PATCH] networkd: Introduce tun/tap device

Zbigniew Jędrzejewski-Szmek zbyszek at in.waw.pl
Wed Jun 25 06:42:27 PDT 2014


On Wed, Jun 25, 2014 at 04:13:39PM +0530, Susant Sahani wrote:
> This patch introduces TUN/TAP device creation support
> to networkd.
> 
> 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                  |   9 +++
>  5 files changed, 144 insertions(+), 7 deletions(-)
>  create mode 100644 src/network/networkd-tuntap.c
> 
> diff --git a/Makefile.am b/Makefile.am
> index 4b292b2..165cfc3 100644
> --- a/Makefile.am
> +++ b/Makefile.am
> @@ -4494,6 +4494,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..644a1d0 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" <- Maybe add a comma here, to makes future patches simpler

>  };
>  
>  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..7c1840c
> --- /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;
Can the conditions in two if's above be reverted? It is easier to read
"true" conditions than "!false".

Also add space between "if" and "(".

> +
> +        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 b7b1d90..7f24635 100644
> --- a/src/network/networkd.h
> +++ b/src/network/networkd.h
> @@ -80,6 +80,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;
> @@ -122,6 +124,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 +348,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_;
> @@ -353,6 +360,8 @@ int config_parse_netdev_kind(const char *unit, const char *filename, unsigned li
>  
>  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);

Look good.

Zbyszek


More information about the systemd-devel mailing list