Looks great, just minor comments below. On Tue, Jun 24, 2014 at 6:25 PM, Susant Sahani <sus...@redhat.com> wrote: > This patch introduces tuntap support to networkd. > > Example conf > > file : tuntap.netdev > > [NetDev] > Name=tuntap-test > Kind=tuntap > > [TUNTAP]
Hm, maybe call this TunTap instead? > 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 Yeah, this would be great to have as well. > --- > 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) { Probably better explain why tuntap needs special casing in a comment here. > + 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