[systemd-commits] 5 commits - man/systemd.netdev.xml src/libsystemd src/libsystemd-network src/network

Tom Gundersen tomegun at kemper.freedesktop.org
Thu Jan 22 12:41:33 PST 2015


 man/systemd.netdev.xml                    |   29 +++
 src/libsystemd-network/dhcp-identifier.c  |   13 -
 src/libsystemd-network/sd-dhcp-client.c   |   91 ++++++-----
 src/libsystemd-network/test-dhcp-client.c |   44 ++---
 src/libsystemd/sd-rtnl/rtnl-types.c       |   24 +++
 src/libsystemd/sd-rtnl/rtnl-types.h       |    4 
 src/network/networkd-netdev-gperf.gperf   |    1 
 src/network/networkd-netdev-tunnel.c      |  235 +++++++++++++++++++++++++++++-
 src/network/networkd-netdev-tunnel.h      |   28 +++
 src/network/networkd-netdev.c             |    8 +
 src/network/networkd-netdev.h             |    8 +
 src/network/networkd-network.c            |    7 
 12 files changed, 412 insertions(+), 80 deletions(-)

New commits:
commit 5bac5235934fabe5a3e6a9d47f4812f81034c427
Author: Tom Gundersen <teg at jklm.no>
Date:   Thu Jan 22 00:53:16 2015 +0100

    sd-dhcp-client: use RFC4361-complient ClientID by default
    
    In addition to the benefits listed in the RFC, this allows DHCP to work also in
    case several interfaces share the same MAC address on the same link (IPVLAN).
    
    Note that this will make the ClientID (so probably the assigned IP address)
    change on upgrades. If it is desired to avoid that we would have to remember and
    write back the ID (which the library supports, but networkd currently does not).

diff --git a/src/libsystemd-network/sd-dhcp-client.c b/src/libsystemd-network/sd-dhcp-client.c
index 65e888a..5f90617 100644
--- a/src/libsystemd-network/sd-dhcp-client.c
+++ b/src/libsystemd-network/sd-dhcp-client.c
@@ -36,9 +36,10 @@
 #include "dhcp-protocol.h"
 #include "dhcp-internal.h"
 #include "dhcp-lease-internal.h"
+#include "dhcp-identifier.h"
 #include "sd-dhcp-client.h"
 
-#define MAX_CLIENT_ID_LEN 64  /* Arbitrary limit */
+#define MAX_CLIENT_ID_LEN (sizeof(uint32_t) + MAX_DUID_LEN)  /* Arbitrary limit */
 #define MAX_MAC_ADDR_LEN INFINIBAND_ALEN
 
 struct sd_dhcp_client {
@@ -60,29 +61,31 @@ struct sd_dhcp_client {
         uint8_t mac_addr[MAX_MAC_ADDR_LEN];
         size_t mac_addr_len;
         uint16_t arp_type;
-        union {
-                struct {
-                        uint8_t type; /* 0: Generic (non-LL) (RFC 2132) */
-                        uint8_t data[MAX_CLIENT_ID_LEN];
-                } _packed_ gen;
-                struct {
-                        uint8_t type; /* 1: Ethernet Link-Layer (RFC 2132) */
-                        uint8_t haddr[ETH_ALEN];
-                } _packed_ eth;
-                struct {
-                        uint8_t type; /* 2 - 254: ARP/Link-Layer (RFC 2132) */
-                        uint8_t haddr[0];
-                } _packed_ ll;
-                struct {
-                        uint8_t type; /* 255: Node-specific (RFC 4361) */
-                        uint8_t iaid[4];
-                        uint8_t duid[MAX_CLIENT_ID_LEN - 4];
-                } _packed_ ns;
-                struct {
-                        uint8_t type;
-                        uint8_t data[MAX_CLIENT_ID_LEN];
-                } _packed_ raw;
-        } client_id;
+        struct {
+                uint8_t type;
+                union {
+                        struct {
+                                /* 0: Generic (non-LL) (RFC 2132) */
+                                uint8_t data[MAX_CLIENT_ID_LEN];
+                        } _packed_ gen;
+                        struct {
+                                /* 1: Ethernet Link-Layer (RFC 2132) */
+                                uint8_t haddr[ETH_ALEN];
+                        } _packed_ eth;
+                        struct {
+                                /* 2 - 254: ARP/Link-Layer (RFC 2132) */
+                                uint8_t haddr[0];
+                        } _packed_ ll;
+                        struct {
+                                /* 255: Node-specific (RFC 4361) */
+                                uint32_t iaid;
+                                struct duid duid;
+                        } _packed_ ns;
+                        struct {
+                                uint8_t data[MAX_CLIENT_ID_LEN];
+                        } _packed_ raw;
+                };
+        } _packed_ client_id;
         size_t client_id_len;
         char *hostname;
         char *vendor_class_identifier;
@@ -239,10 +242,9 @@ int sd_dhcp_client_get_client_id(sd_dhcp_client *client, uint8_t *type,
         *data = NULL;
         *data_len = 0;
         if (client->client_id_len) {
-                *type = client->client_id.raw.type;
+                *type = client->client_id.type;
                 *data = client->client_id.raw.data;
-                *data_len = client->client_id_len -
-                        sizeof (client->client_id.raw.type);
+                *data_len = client->client_id_len - sizeof(client->client_id.type);
         }
 
         return 0;
@@ -270,8 +272,8 @@ int sd_dhcp_client_set_client_id(sd_dhcp_client *client, uint8_t type,
                 break;
         }
 
-        if (client->client_id_len == data_len + sizeof (client->client_id.raw.type) &&
-            client->client_id.raw.type == type &&
+        if (client->client_id_len == data_len + sizeof(client->client_id.type) &&
+            client->client_id.type == type &&
             memcmp(&client->client_id.raw.data, data, data_len) == 0)
                 return 0;
 
@@ -282,9 +284,9 @@ int sd_dhcp_client_set_client_id(sd_dhcp_client *client, uint8_t type,
                 client_stop(client, DHCP_EVENT_STOP);
         }
 
-        client->client_id.raw.type = type;
+        client->client_id.type = type;
         memcpy(&client->client_id.raw.data, data, data_len);
-        client->client_id_len = data_len + sizeof (client->client_id.raw.type);
+        client->client_id_len = data_len + sizeof (client->client_id.type);
 
         if (need_restart && client->state != DHCP_STATE_STOPPED)
                 sd_dhcp_client_start(client);
@@ -461,12 +463,21 @@ static int client_message_init(sd_dhcp_client *client, DHCPPacket **ret,
         if (client->arp_type == ARPHRD_ETHER)
                 memcpy(&packet->dhcp.chaddr, &client->mac_addr, ETH_ALEN);
 
-        /* If no client identifier exists, construct one from an ethernet
-           address if present */
-        if (client->client_id_len == 0 && client->arp_type == ARPHRD_ETHER) {
-                client->client_id.eth.type = ARPHRD_ETHER;
-                memcpy(&client->client_id.eth.haddr, &client->mac_addr, ETH_ALEN);
-                client->client_id_len = sizeof (client->client_id.eth);
+        /* If no client identifier exists, construct an RFC 4361-compliant one */
+        if (client->client_id_len == 0) {
+                size_t duid_len;
+
+                client->client_id.type = 255;
+
+                r = dhcp_identifier_set_iaid(client->index, client->mac_addr, client->mac_addr_len, &client->client_id.ns.iaid);
+                if (r < 0)
+                        return r;
+
+                r = dhcp_identifier_set_duid_en(&client->client_id.ns.duid, &duid_len);
+                if (r < 0)
+                        return r;
+
+                client->client_id_len = sizeof(client->client_id.type) + sizeof(client->client_id.ns.iaid) + duid_len;
         }
 
         /* Some DHCP servers will refuse to issue an DHCP lease if the Client
@@ -475,7 +486,7 @@ static int client_message_init(sd_dhcp_client *client, DHCPPacket **ret,
                 r = dhcp_option_append(&packet->dhcp, optlen, &optoffset, 0,
                                        DHCP_OPTION_CLIENT_IDENTIFIER,
                                        client->client_id_len,
-                                       &client->client_id.raw);
+                                       &client->client_id);
                 if (r < 0)
                         return r;
         }
@@ -1031,7 +1042,7 @@ static int client_handle_offer(sd_dhcp_client *client, DHCPMessage *offer,
 
         if (client->client_id_len) {
                 r = dhcp_lease_set_client_id(lease,
-                                             (uint8_t *) &client->client_id.raw,
+                                             (uint8_t *) &client->client_id,
                                              client->client_id_len);
                 if (r < 0)
                         return r;
@@ -1098,7 +1109,7 @@ static int client_handle_ack(sd_dhcp_client *client, DHCPMessage *ack,
 
         if (client->client_id_len) {
                 r = dhcp_lease_set_client_id(lease,
-                                             (uint8_t *) &client->client_id.raw,
+                                             (uint8_t *) &client->client_id,
                                              client->client_id_len);
                 if (r < 0)
                         return r;
diff --git a/src/libsystemd-network/test-dhcp-client.c b/src/libsystemd-network/test-dhcp-client.c
index 0515440..a3d69f3 100644
--- a/src/libsystemd-network/test-dhcp-client.c
+++ b/src/libsystemd-network/test-dhcp-client.c
@@ -32,17 +32,16 @@
 #include "sd-event.h"
 #include "event-util.h"
 
+#include "dhcp-identifier.h"
 #include "dhcp-protocol.h"
 #include "dhcp-internal.h"
 #include "sd-dhcp-client.h"
 
-static struct ether_addr mac_addr = {
-        .ether_addr_octet = {'A', 'B', 'C', '1', '2', '3'}
-};
+static uint8_t mac_addr[] = {'A', 'B', 'C', '1', '2', '3'};
 
 typedef int (*test_callback_recv_t)(size_t size, DHCPMessage *dhcp);
 
-static bool verbose = false;
+static bool verbose = true;
 static int test_fd[2];
 static test_callback_recv_t callback_recv;
 static be32_t xid;
@@ -136,10 +135,22 @@ static int check_options(uint8_t code, uint8_t len, const uint8_t *option,
 {
         switch(code) {
         case DHCP_OPTION_CLIENT_IDENTIFIER:
-                assert_se(len == 7);
-                assert_se(option[0] == 0x01);
-                assert_se(memcmp(&option[1], &mac_addr, ETH_ALEN) == 0);
+        {
+                uint32_t iaid;
+                struct duid duid;
+                size_t duid_len;
+
+                assert_se(dhcp_identifier_set_duid_en(&duid, &duid_len) >= 0);
+                assert_se(dhcp_identifier_set_iaid(42, mac_addr, ETH_ALEN, &iaid) >= 0);
+
+                assert_se(len == sizeof(uint8_t) + sizeof(uint32_t) + duid_len);
+                assert_se(len == 19);
+                assert_se(option[0] == 0xff);
+
+                assert_se(memcmp(&option[1], &iaid, sizeof(iaid)) == 0);
+                assert_se(memcmp(&option[5], &duid, duid_len) == 0);
                 break;
+        }
 
         default:
                 break;
@@ -185,8 +196,7 @@ int dhcp_network_send_raw_socket(int s, const union sockaddr_union *link,
         assert_se(ip_check == 0xffff);
 
         assert_se(discover->dhcp.xid);
-        assert_se(memcmp(discover->dhcp.chaddr,
-                      &mac_addr.ether_addr_octet, 6) == 0);
+        assert_se(memcmp(discover->dhcp.chaddr, &mac_addr, ETH_ALEN) == 0);
 
         size = len - sizeof(struct iphdr) - sizeof(struct udphdr);
 
@@ -246,10 +256,7 @@ static void test_discover_message(sd_event *e)
         assert_se(r >= 0);
 
         assert_se(sd_dhcp_client_set_index(client, 42) >= 0);
-        assert_se(sd_dhcp_client_set_mac(client,
-                                         (const uint8_t *) &mac_addr,
-                                         sizeof (mac_addr),
-                                         ARPHRD_ETHER) >= 0);
+        assert_se(sd_dhcp_client_set_mac(client, mac_addr, ETH_ALEN, ARPHRD_ETHER) >= 0);
 
         assert_se(sd_dhcp_client_set_request_option(client, 248) >= 0);
 
@@ -404,8 +411,7 @@ static int test_addr_acq_recv_request(size_t size, DHCPMessage *request) {
 
         memcpy(&test_addr_acq_ack[26], &udp_check, sizeof(udp_check));
         memcpy(&test_addr_acq_ack[32], &xid, sizeof(xid));
-        memcpy(&test_addr_acq_ack[56], &mac_addr.ether_addr_octet,
-               ETHER_ADDR_LEN);
+        memcpy(&test_addr_acq_ack[56], &mac_addr, ETHER_ADDR_LEN);
 
         callback_recv = NULL;
 
@@ -436,8 +442,7 @@ static int test_addr_acq_recv_discover(size_t size, DHCPMessage *discover) {
 
         memcpy(&test_addr_acq_offer[26], &udp_check, sizeof(udp_check));
         memcpy(&test_addr_acq_offer[32], &xid, sizeof(xid));
-        memcpy(&test_addr_acq_offer[56], &mac_addr.ether_addr_octet,
-               ETHER_ADDR_LEN);
+        memcpy(&test_addr_acq_offer[56], &mac_addr, ETHER_ADDR_LEN);
 
         callback_recv = test_addr_acq_recv_request;
 
@@ -467,10 +472,7 @@ static void test_addr_acq(sd_event *e) {
         assert_se(r >= 0);
 
         assert_se(sd_dhcp_client_set_index(client, 42) >= 0);
-        assert_se(sd_dhcp_client_set_mac(client,
-                                         (const uint8_t *) &mac_addr,
-                                         sizeof (mac_addr),
-                                         ARPHRD_ETHER) >= 0);
+        assert_se(sd_dhcp_client_set_mac(client, mac_addr, ETH_ALEN, ARPHRD_ETHER) >= 0);
 
         assert_se(sd_dhcp_client_set_callback(client, test_addr_acq_acquired, e)
                 >= 0);

commit 40862866417265ac8c20422cb44f14a8f141ce0d
Author: Tom Gundersen <teg at jklm.no>
Date:   Thu Jan 22 21:18:30 2015 +0100

    dhcp-identifier: create IAID even if no udev device can be found
    
    This is useful for testing.

diff --git a/src/libsystemd-network/dhcp-identifier.c b/src/libsystemd-network/dhcp-identifier.c
index 5386dca..e4b0ce6 100644
--- a/src/libsystemd-network/dhcp-identifier.c
+++ b/src/libsystemd-network/dhcp-identifier.c
@@ -78,14 +78,13 @@ int dhcp_identifier_set_iaid(int ifindex, uint8_t *mac, size_t mac_len, uint32_t
 
                 sprintf(ifindex_str, "n%d", ifindex);
                 device = udev_device_new_from_device_id(udev, ifindex_str);
-                if (!device)
-                        return -errno;
+                if (device) {
+                        if (udev_device_get_is_initialized(device) <= 0)
+                                /* not yet ready */
+                                return -EBUSY;
 
-                if (udev_device_get_is_initialized(device) <= 0)
-                        /* not yet ready */
-                        return -EBUSY;
-
-                name = net_get_name(device);
+                        name = net_get_name(device);
+                }
         }
 
         if (name)

commit b16492f86f13abd4a9447afd0910139af9656906
Author: Susant Sahani <susant at redhat.com>
Date:   Sun Jan 18 23:24:24 2015 +0530

    networkd: Introduce ip6gre and ip6gretap
    
    This patch introduces ipv6 gre and gretap.
    
    test:
    
    ip6gre.netdev:
    [NetDev]
    Name=ip6gretap
    Kind=ip6gretap
    
    [Tunnel]
    Local=2a00:ffde:4567:edde::4987
    Remote=2001:473:fece:cafe::5179
    
    ip6gre.network:
    [Match]
    Name=eno16777736
    
    [Network]
    Tunnel=ip6gretap
    
    ip link
    
    6: ip6gre at eno16777736: <POINTOPOINT,NOARP> mtu 1448 qdisc noop state
    DOWN mode DEFAULT group default
        link/gre6 2a:00:ff:de:45:67:ed:de:00:00:00:00:00:00:49:87 peer
    20:01:04:73:fe:ce:ca:fe:00:00:00:00:00:00:51:79

diff --git a/man/systemd.netdev.xml b/man/systemd.netdev.xml
index f6e385a..7edec36 100644
--- a/man/systemd.netdev.xml
+++ b/man/systemd.netdev.xml
@@ -331,7 +331,8 @@
 
                         <para>The <literal>[Tunnel]</literal> section only applies for netdevs of kind
                         <literal>ipip</literal>, <literal>sit</literal>, <literal>gre</literal>, <literal>gretap</literal>,
-                        <literal>vti</literal> and <literal>ip6tnl</literal> and accepts the following keys:</para>
+                        <literal>ip6gre</literal>, <literal>ip6gretap</literal>, <literal>vti</literal> and <literal>ip6tnl</literal>
+                        and accepts the following keys:</para>
 
                         <variablelist class='network-directives'>
                                 <varlistentry>
diff --git a/src/libsystemd/sd-rtnl/rtnl-types.c b/src/libsystemd/sd-rtnl/rtnl-types.c
index ef3aebf..d4abe4c 100644
--- a/src/libsystemd/sd-rtnl/rtnl-types.c
+++ b/src/libsystemd/sd-rtnl/rtnl-types.c
@@ -177,6 +177,8 @@ static const char* const nl_union_link_info_data_table[_NL_UNION_LINK_INFO_DATA_
         [NL_UNION_LINK_INFO_DATA_IPIP_TUNNEL] = "ipip",
         [NL_UNION_LINK_INFO_DATA_IPGRE_TUNNEL] = "gre",
         [NL_UNION_LINK_INFO_DATA_IPGRETAP_TUNNEL] = "gretap",
+        [NL_UNION_LINK_INFO_DATA_IP6GRE_TUNNEL] = "ip6gre",
+        [NL_UNION_LINK_INFO_DATA_IP6GRETAP_TUNNEL] = "ip6gretap",
         [NL_UNION_LINK_INFO_DATA_SIT_TUNNEL] = "sit",
         [NL_UNION_LINK_INFO_DATA_VTI_TUNNEL] = "vti",
         [NL_UNION_LINK_INFO_DATA_IP6TNL_TUNNEL] = "ip6tnl",
@@ -205,6 +207,10 @@ static const NLTypeSystem rtnl_link_info_data_type_systems[_NL_UNION_LINK_INFO_D
                                                     .types = rtnl_link_info_data_ipgre_types },
         [NL_UNION_LINK_INFO_DATA_IPGRETAP_TUNNEL] =  { .max = ELEMENTSOF(rtnl_link_info_data_ipgre_types) - 1,
                                                     .types = rtnl_link_info_data_ipgre_types },
+        [NL_UNION_LINK_INFO_DATA_IP6GRE_TUNNEL] =  { .max = ELEMENTSOF(rtnl_link_info_data_ipgre_types) - 1,
+                                                    .types = rtnl_link_info_data_ipgre_types },
+        [NL_UNION_LINK_INFO_DATA_IP6GRETAP_TUNNEL] =  { .max = ELEMENTSOF(rtnl_link_info_data_ipgre_types) - 1,
+                                                    .types = rtnl_link_info_data_ipgre_types },
         [NL_UNION_LINK_INFO_DATA_SIT_TUNNEL] =  { .max = ELEMENTSOF(rtnl_link_info_data_iptun_types) - 1,
                                                   .types = rtnl_link_info_data_iptun_types },
         [NL_UNION_LINK_INFO_DATA_VTI_TUNNEL] =  { .max = ELEMENTSOF(rtnl_link_info_data_ipvti_types) - 1,
diff --git a/src/libsystemd/sd-rtnl/rtnl-types.h b/src/libsystemd/sd-rtnl/rtnl-types.h
index 347a0ad..9c0dc30 100644
--- a/src/libsystemd/sd-rtnl/rtnl-types.h
+++ b/src/libsystemd/sd-rtnl/rtnl-types.h
@@ -76,6 +76,8 @@ typedef enum NLUnionLinkInfoData {
         NL_UNION_LINK_INFO_DATA_IPIP_TUNNEL,
         NL_UNION_LINK_INFO_DATA_IPGRE_TUNNEL,
         NL_UNION_LINK_INFO_DATA_IPGRETAP_TUNNEL,
+        NL_UNION_LINK_INFO_DATA_IP6GRE_TUNNEL,
+        NL_UNION_LINK_INFO_DATA_IP6GRETAP_TUNNEL,
         NL_UNION_LINK_INFO_DATA_SIT_TUNNEL,
         NL_UNION_LINK_INFO_DATA_VTI_TUNNEL,
         NL_UNION_LINK_INFO_DATA_IP6TNL_TUNNEL,
diff --git a/src/network/networkd-netdev-tunnel.c b/src/network/networkd-netdev-tunnel.c
index f439bf9..89a9096 100644
--- a/src/network/networkd-netdev-tunnel.c
+++ b/src/network/networkd-netdev-tunnel.c
@@ -218,6 +218,57 @@ static int netdev_gre_fill_message_create(NetDev *netdev, Link *link, sd_rtnl_me
         return r;
 }
 
+static int netdev_ip6gre_fill_message_create(NetDev *netdev, Link *link, sd_rtnl_message *m) {
+        Tunnel *t;
+        int r;
+
+        assert(netdev);
+
+        if (netdev->kind == NETDEV_KIND_IP6GRE)
+                 t = IP6GRE(netdev);
+        else
+                 t = IP6GRETAP(netdev);
+
+        assert(t);
+        assert(t->family == AF_INET6);
+        assert(link);
+        assert(m);
+
+        r = sd_rtnl_message_append_u32(m, IFLA_GRE_LINK, link->ifindex);
+        if (r < 0) {
+                log_netdev_error(netdev,
+                                 "Could not append IFLA_GRE_LINK attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        r = sd_rtnl_message_append_in6_addr(m, IFLA_GRE_LOCAL, &t->local.in6);
+        if (r < 0) {
+                log_netdev_error(netdev,
+                                 "Could not append IFLA_GRE_LOCAL attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        r = sd_rtnl_message_append_in6_addr(m, IFLA_GRE_REMOTE, &t->remote.in6);
+        if (r < 0) {
+                log_netdev_error(netdev,
+                                 "Could not append IFLA_GRE_REMOTE attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        r = sd_rtnl_message_append_u8(m, IFLA_GRE_TTL, t->ttl);
+        if (r < 0) {
+                log_netdev_error(netdev,
+                                 "Could not append IFLA_GRE_TTL 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;
@@ -341,6 +392,12 @@ static int netdev_tunnel_verify(NetDev *netdev, const char *filename) {
         case NETDEV_KIND_GRETAP:
                 t = GRETAP(netdev);
                 break;
+        case NETDEV_KIND_IP6GRE:
+                t = IP6GRE(netdev);
+                break;
+        case NETDEV_KIND_IP6GRETAP:
+                t = IP6GRETAP(netdev);
+                break;
         case NETDEV_KIND_VTI:
                 t = VTI(netdev);
                 break;
@@ -451,6 +508,21 @@ static void gre_init(NetDev *n) {
         t->pmtudisc = true;
 }
 
+static void ip6gre_init(NetDev *n) {
+        Tunnel *t;
+
+        assert(n);
+
+        if (n->kind == NETDEV_KIND_IP6GRE)
+                t = IP6GRE(n);
+        else
+                t = IP6GRETAP(n);
+
+        assert(t);
+
+        t->ttl = DEFAULT_TNL_HOP_LIMIT;
+}
+
 static void ip6tnl_init(NetDev *n) {
         Tunnel *t = IP6TNL(n);
 
@@ -507,6 +579,24 @@ const NetDevVTable gretap_vtable = {
         .config_verify = netdev_tunnel_verify,
 };
 
+const NetDevVTable ip6gre_vtable = {
+        .object_size = sizeof(Tunnel),
+        .init = ip6gre_init,
+        .sections = "Match\0NetDev\0Tunnel\0",
+        .fill_message_create = netdev_ip6gre_fill_message_create,
+        .create_type = NETDEV_CREATE_STACKED,
+        .config_verify = netdev_tunnel_verify,
+};
+
+const NetDevVTable ip6gretap_vtable = {
+        .object_size = sizeof(Tunnel),
+        .init = ip6gre_init,
+        .sections = "Match\0NetDev\0Tunnel\0",
+        .fill_message_create = netdev_ip6gre_fill_message_create,
+        .create_type = NETDEV_CREATE_STACKED,
+        .config_verify = netdev_tunnel_verify,
+};
+
 const NetDevVTable ip6tnl_vtable = {
         .object_size = sizeof(Tunnel),
         .init = ip6tnl_init,
diff --git a/src/network/networkd-netdev-tunnel.h b/src/network/networkd-netdev-tunnel.h
index 1687f9e..453d73c 100644
--- a/src/network/networkd-netdev-tunnel.h
+++ b/src/network/networkd-netdev-tunnel.h
@@ -57,6 +57,8 @@ extern const NetDevVTable sit_vtable;
 extern const NetDevVTable vti_vtable;
 extern const NetDevVTable gre_vtable;
 extern const NetDevVTable gretap_vtable;
+extern const NetDevVTable ip6gre_vtable;
+extern const NetDevVTable ip6gretap_vtable;
 extern const NetDevVTable ip6tnl_vtable;
 
 const char *ip6tnl_mode_to_string(Ip6TnlMode d) _const_;
diff --git a/src/network/networkd-netdev.c b/src/network/networkd-netdev.c
index ed85702..8119205 100644
--- a/src/network/networkd-netdev.c
+++ b/src/network/networkd-netdev.c
@@ -40,6 +40,8 @@ const NetDevVTable * const netdev_vtable[_NETDEV_KIND_MAX] = {
         [NETDEV_KIND_IPIP] = &ipip_vtable,
         [NETDEV_KIND_GRE] = &gre_vtable,
         [NETDEV_KIND_GRETAP] = &gretap_vtable,
+        [NETDEV_KIND_IP6GRE] = &ip6gre_vtable,
+        [NETDEV_KIND_IP6GRETAP] = &ip6gretap_vtable,
         [NETDEV_KIND_SIT] = &sit_vtable,
         [NETDEV_KIND_VTI] = &vti_vtable,
         [NETDEV_KIND_VETH] = &veth_vtable,
@@ -59,6 +61,8 @@ static const char* const netdev_kind_table[_NETDEV_KIND_MAX] = {
         [NETDEV_KIND_IPIP] = "ipip",
         [NETDEV_KIND_GRE] = "gre",
         [NETDEV_KIND_GRETAP] = "gretap",
+        [NETDEV_KIND_IP6GRE] = "ip6gre",
+        [NETDEV_KIND_IP6GRETAP] = "ip6gretap",
         [NETDEV_KIND_SIT] = "sit",
         [NETDEV_KIND_VETH] = "veth",
         [NETDEV_KIND_VTI] = "vti",
diff --git a/src/network/networkd-netdev.h b/src/network/networkd-netdev.h
index 77d00d4..3756b1e 100644
--- a/src/network/networkd-netdev.h
+++ b/src/network/networkd-netdev.h
@@ -48,6 +48,8 @@ typedef enum NetDevKind {
         NETDEV_KIND_IPIP,
         NETDEV_KIND_GRE,
         NETDEV_KIND_GRETAP,
+        NETDEV_KIND_IP6GRE,
+        NETDEV_KIND_IP6GRETAP,
         NETDEV_KIND_SIT,
         NETDEV_KIND_VETH,
         NETDEV_KIND_VTI,
@@ -166,6 +168,8 @@ DEFINE_CAST(VXLAN, VxLan);
 DEFINE_CAST(IPIP, Tunnel);
 DEFINE_CAST(GRE, Tunnel);
 DEFINE_CAST(GRETAP, Tunnel);
+DEFINE_CAST(IP6GRE, Tunnel);
+DEFINE_CAST(IP6GRETAP, Tunnel);
 DEFINE_CAST(SIT, Tunnel);
 DEFINE_CAST(VTI, Tunnel);
 DEFINE_CAST(IP6TNL, Tunnel);
diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c
index 0f474d9..4589162 100644
--- a/src/network/networkd-network.c
+++ b/src/network/networkd-network.c
@@ -453,6 +453,8 @@ int config_parse_tunnel(const char *unit,
             netdev->kind != NETDEV_KIND_SIT &&
             netdev->kind != NETDEV_KIND_GRE &&
             netdev->kind != NETDEV_KIND_GRETAP &&
+            netdev->kind != NETDEV_KIND_IP6GRE &&
+            netdev->kind != NETDEV_KIND_IP6GRETAP &&
             netdev->kind != NETDEV_KIND_VTI &&
             netdev->kind != NETDEV_KIND_IP6TNL
             ) {

commit 855ee1a1d272b599410212b40768a9c71f260e37
Author: Susant Sahani <susant at redhat.com>
Date:   Sat Jan 17 00:39:10 2015 +0530

    networkd: Introduce IP6 tunnel
    
    This patch enables networkd to create IP6 tunnels
    
    example conf:
    
    ipip6.netdev:
    [NetDev]
    Name=ipip6-tunnel
    Kind=ip6tnl
    
    [Tunnel]
    Mode=ip4ipv6
    Local=2a00:ffde:4567:edde::4987
    Remote=2001:473:fece:cafe::5179
    
    ipip6.network
    [Match]
    Name=wlan0
    
    [Network]
    Tunnel=ipip6-tunnel
    
    23: ipip6-tunnel at wlan0: <POINTOPOINT,NOARP> mtu 1452 qdisc noop state
    DOWN mode DEFAULT group default
        link/tunnel6 2a00:ffde:4567:edde::4987 peer 2001:473:fece:cafe::5179

diff --git a/man/systemd.netdev.xml b/man/systemd.netdev.xml
index ca50558..f6e385a 100644
--- a/man/systemd.netdev.xml
+++ b/man/systemd.netdev.xml
@@ -331,7 +331,7 @@
 
                         <para>The <literal>[Tunnel]</literal> section only applies for netdevs of kind
                         <literal>ipip</literal>, <literal>sit</literal>, <literal>gre</literal>, <literal>gretap</literal>,
-                        and <literal>vti</literal> and accepts the following keys:</para>
+                        <literal>vti</literal> and <literal>ip6tnl</literal> and accepts the following keys:</para>
 
                         <variablelist class='network-directives'>
                                 <varlistentry>
@@ -373,6 +373,23 @@
                                                 <para>A boolean. When true, enables Path MTU Discovery on the tunnel.</para>
                                         </listitem>
                                 </varlistentry>
+                                <varlistentry>
+                                  <term><varname>Mode=</varname></term>
+                                  <listitem>
+                                    <para>IPv6 tunnels can have three mode
+                                    <literal>ip6ip6</literal>
+                                    <literal>ip4ipv6</literal>,
+                                    <literal>any</literal>
+                                    </para>
+                                  </listitem>
+                                </varlistentry>
+
+                                   <varlistentry>
+                                        <term><varname>Mode=</varname></term>
+                                        <listitem>
+                                                <para>The mode specifies the ip6 tunnel protocol. Supported type are </para>
+                                        </listitem>
+                                </varlistentry>
                         </variablelist>
         </refsect1>
         <refsect1>
diff --git a/src/libsystemd/sd-rtnl/rtnl-types.c b/src/libsystemd/sd-rtnl/rtnl-types.c
index 97b3cee..ef3aebf 100644
--- a/src/libsystemd/sd-rtnl/rtnl-types.c
+++ b/src/libsystemd/sd-rtnl/rtnl-types.c
@@ -153,6 +153,17 @@ static const NLType rtnl_link_info_data_ipvti_types[IFLA_VTI_MAX + 1] = {
         [IFLA_VTI_REMOTE]       = { .type = NLA_IN_ADDR  },
 };
 
+static const NLType rtnl_link_info_data_ip6tnl_types[IFLA_IPTUN_MAX + 1] = {
+        [IFLA_IPTUN_LINK]                = { .type = NLA_U32 },
+        [IFLA_IPTUN_LOCAL]               = { .type = NLA_IN_ADDR },
+        [IFLA_IPTUN_REMOTE]              = { .type = NLA_IN_ADDR },
+        [IFLA_IPTUN_TTL]                 = { .type = NLA_U8 },
+        [IFLA_IPTUN_FLAGS]               = { .type = NLA_U32 },
+        [IFLA_IPTUN_PROTO]               = { .type = NLA_U8 },
+        [IFLA_IPTUN_ENCAP_LIMIT]         = { .type = NLA_U8 },
+        [IFLA_IPTUN_FLOWINFO]            = { .type = NLA_U32},
+};
+
 /* these strings must match the .kind entries in the kernel */
 static const char* const nl_union_link_info_data_table[_NL_UNION_LINK_INFO_DATA_MAX] = {
         [NL_UNION_LINK_INFO_DATA_BOND] = "bond",
@@ -168,6 +179,7 @@ static const char* const nl_union_link_info_data_table[_NL_UNION_LINK_INFO_DATA_
         [NL_UNION_LINK_INFO_DATA_IPGRETAP_TUNNEL] = "gretap",
         [NL_UNION_LINK_INFO_DATA_SIT_TUNNEL] = "sit",
         [NL_UNION_LINK_INFO_DATA_VTI_TUNNEL] = "vti",
+        [NL_UNION_LINK_INFO_DATA_IP6TNL_TUNNEL] = "ip6tnl",
 };
 
 DEFINE_STRING_TABLE_LOOKUP(nl_union_link_info_data, NLUnionLinkInfoData);
@@ -197,6 +209,9 @@ static const NLTypeSystem rtnl_link_info_data_type_systems[_NL_UNION_LINK_INFO_D
                                                   .types = rtnl_link_info_data_iptun_types },
         [NL_UNION_LINK_INFO_DATA_VTI_TUNNEL] =  { .max = ELEMENTSOF(rtnl_link_info_data_ipvti_types) - 1,
                                                   .types = rtnl_link_info_data_ipvti_types },
+        [NL_UNION_LINK_INFO_DATA_IP6TNL_TUNNEL] =  { .max = ELEMENTSOF(rtnl_link_info_data_ip6tnl_types) - 1,
+                                                     .types = rtnl_link_info_data_ip6tnl_types },
+
 };
 
 static const NLTypeSystemUnion rtnl_link_info_data_type_system_union = {
diff --git a/src/libsystemd/sd-rtnl/rtnl-types.h b/src/libsystemd/sd-rtnl/rtnl-types.h
index aacea19..347a0ad 100644
--- a/src/libsystemd/sd-rtnl/rtnl-types.h
+++ b/src/libsystemd/sd-rtnl/rtnl-types.h
@@ -78,6 +78,7 @@ typedef enum NLUnionLinkInfoData {
         NL_UNION_LINK_INFO_DATA_IPGRETAP_TUNNEL,
         NL_UNION_LINK_INFO_DATA_SIT_TUNNEL,
         NL_UNION_LINK_INFO_DATA_VTI_TUNNEL,
+        NL_UNION_LINK_INFO_DATA_IP6TNL_TUNNEL,
         _NL_UNION_LINK_INFO_DATA_MAX,
         _NL_UNION_LINK_INFO_DATA_INVALID = -1
 } NLUnionLinkInfoData;
diff --git a/src/network/networkd-netdev-gperf.gperf b/src/network/networkd-netdev-gperf.gperf
index cb741b4..963c47c 100644
--- a/src/network/networkd-netdev-gperf.gperf
+++ b/src/network/networkd-netdev-gperf.gperf
@@ -35,6 +35,7 @@ Tunnel.Remote,            config_parse_tunnel_address,        0,
 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)
+Tunnel.Mode,              config_parse_ip6tnl_mode,           0,                             offsetof(Tunnel, ip6tnl_mode)
 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)
diff --git a/src/network/networkd-netdev-tunnel.c b/src/network/networkd-netdev-tunnel.c
index fde08fb..f439bf9 100644
--- a/src/network/networkd-netdev-tunnel.c
+++ b/src/network/networkd-netdev-tunnel.c
@@ -3,7 +3,7 @@
 /***
     This file is part of systemd.
 
-    Copyright 2014 Susant Sahani <susant at redhat.com>
+    Copyright 2014 Susant Sahani
 
     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
@@ -24,6 +24,7 @@
 #include <net/if.h>
 #include <linux/ip.h>
 #include <linux/if_tunnel.h>
+#include <linux/ip6_tunnel.h>
 
 #include "sd-rtnl.h"
 #include "networkd-netdev-tunnel.h"
@@ -33,6 +34,17 @@
 #include "missing.h"
 #include "conf-parser.h"
 
+#define DEFAULT_TNL_HOP_LIMIT   64
+
+static const char* const ip6tnl_mode_table[_NETDEV_IP6_TNL_MODE_MAX] = {
+        [NETDEV_IP6_TNL_MODE_IP6IP6] = "ip6ip6",
+        [NETDEV_IP6_TNL_MODE_IPIP6] = "ip4ipv6",
+        [NETDEV_IP6_TNL_MODE_ANYIP6] = "any",
+};
+
+DEFINE_STRING_TABLE_LOOKUP(ip6tnl_mode, Ip6TnlMode);
+DEFINE_CONFIG_PARSE_ENUM(config_parse_ip6tnl_mode, ip6tnl_mode, Ip6TnlMode, "Failed to parse ip6 tunnel Mode");
+
 static int netdev_ipip_fill_message_create(NetDev *netdev, Link *link, sd_rtnl_message *m) {
         Tunnel *t = IPIP(netdev);
         int r;
@@ -243,6 +255,73 @@ static int netdev_vti_fill_message_create(NetDev *netdev, Link *link, sd_rtnl_me
         return r;
 }
 
+static int netdev_ip6tnl_fill_message_create(NetDev *netdev, Link *link, sd_rtnl_message *m) {
+        Tunnel *t = IP6TNL(netdev);
+        uint8_t proto;
+        int r;
+
+        assert(netdev);
+        assert(link);
+        assert(m);
+        assert(t);
+        assert(t->family == AF_INET6);
+
+        r = sd_rtnl_message_append_u32(m, IFLA_IPTUN_LINK, link->ifindex);
+        if (r < 0) {
+                log_netdev_error(netdev,
+                                 "Could not append IFLA_IPTUN_LINK attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        r = sd_rtnl_message_append_in6_addr(m, IFLA_IPTUN_LOCAL, &t->local.in6);
+        if (r < 0) {
+                log_netdev_error(netdev,
+                                 "Could not append IFLA_IPTUN_LOCAL attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        r = sd_rtnl_message_append_in6_addr(m, IFLA_IPTUN_REMOTE, &t->remote.in6);
+        if (r < 0) {
+                log_netdev_error(netdev,
+                                 "Could not append IFLA_IPTUN_REMOTE attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        r = sd_rtnl_message_append_u8(m, IFLA_IPTUN_TTL, t->ttl);
+        if (r < 0) {
+                log_netdev_error(netdev,
+                                 "Could not append IFLA_IPTUN_TTL attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        switch (t->ip6tnl_mode) {
+        case NETDEV_IP6_TNL_MODE_IP6IP6:
+                proto = IPPROTO_IPV6;
+                break;
+        case NETDEV_IP6_TNL_MODE_IPIP6:
+                proto = IPPROTO_IPIP;
+                break;
+        case NETDEV_IP6_TNL_MODE_ANYIP6:
+        default:
+                proto = 0;
+                break;
+        }
+
+        r = sd_rtnl_message_append_u8(m, IFLA_IPTUN_PROTO, proto);
+        if (r < 0) {
+                log_netdev_error(netdev,
+                                 "Could not append IFLA_IPTUN_MODE attribute: %s",
+                                 strerror(-r));
+                return r;
+        }
+
+        return r;
+}
+
 static int netdev_tunnel_verify(NetDev *netdev, const char *filename) {
         Tunnel *t = NULL;
 
@@ -265,6 +344,9 @@ static int netdev_tunnel_verify(NetDev *netdev, const char *filename) {
         case NETDEV_KIND_VTI:
                 t = VTI(netdev);
                 break;
+        case NETDEV_KIND_IP6TNL:
+                t = IP6TNL(netdev);
+                break;
         default:
                 assert_not_reached("Invalid tunnel kind");
         }
@@ -276,11 +358,18 @@ static int netdev_tunnel_verify(NetDev *netdev, const char *filename) {
                return -EINVAL;
         }
 
-        if (t->family != AF_INET) {
+        if (t->family != AF_INET && t->family != AF_INET6) {
               log_warning("Tunnel with invalid address family configured in %s. Ignoring", filename);
               return -EINVAL;
         }
 
+        if (netdev->kind == NETDEV_KIND_IP6TNL) {
+                if (t->ip6tnl_mode == _NETDEV_IP6_TNL_MODE_INVALID) {
+                        log_warning("IP6 Tunnel without mode configured in %s. Ignoring", filename);
+                        return -EINVAL;
+                }
+        }
+
         return 0;
 }
 
@@ -362,6 +451,17 @@ static void gre_init(NetDev *n) {
         t->pmtudisc = true;
 }
 
+static void ip6tnl_init(NetDev *n) {
+        Tunnel *t = IP6TNL(n);
+
+        assert(n);
+        assert(t);
+
+        t->ttl = DEFAULT_TNL_HOP_LIMIT;
+        t->encap_limit = IPV6_DEFAULT_TNL_ENCAP_LIMIT;
+        t->ip6tnl_mode = _NETDEV_IP6_TNL_MODE_INVALID;
+}
+
 const NetDevVTable ipip_vtable = {
         .object_size = sizeof(Tunnel),
         .init = ipip_init,
@@ -406,3 +506,12 @@ const NetDevVTable gretap_vtable = {
         .create_type = NETDEV_CREATE_STACKED,
         .config_verify = netdev_tunnel_verify,
 };
+
+const NetDevVTable ip6tnl_vtable = {
+        .object_size = sizeof(Tunnel),
+        .init = ip6tnl_init,
+        .sections = "Match\0NetDev\0Tunnel\0",
+        .fill_message_create = netdev_ip6tnl_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 b6f6c9d..1687f9e 100644
--- a/src/network/networkd-netdev-tunnel.h
+++ b/src/network/networkd-netdev-tunnel.h
@@ -25,15 +25,30 @@ typedef struct Tunnel Tunnel;
 
 #include "networkd-netdev.h"
 
+typedef enum Ip6TnlMode {
+        NETDEV_IP6_TNL_MODE_IP6IP6,
+        NETDEV_IP6_TNL_MODE_IPIP6,
+        NETDEV_IP6_TNL_MODE_ANYIP6,
+        _NETDEV_IP6_TNL_MODE_MAX,
+        _NETDEV_IP6_TNL_MODE_INVALID = -1,
+} Ip6TnlMode;
+
 struct Tunnel {
         NetDev meta;
 
+        uint8_t encap_limit;
+
         int family;
 
         unsigned ttl;
         unsigned tos;
+        unsigned flags;
+
         union in_addr_union local;
         union in_addr_union remote;
+
+        Ip6TnlMode ip6tnl_mode;
+
         bool pmtudisc;
 };
 
@@ -42,3 +57,13 @@ extern const NetDevVTable sit_vtable;
 extern const NetDevVTable vti_vtable;
 extern const NetDevVTable gre_vtable;
 extern const NetDevVTable gretap_vtable;
+extern const NetDevVTable ip6tnl_vtable;
+
+const char *ip6tnl_mode_to_string(Ip6TnlMode d) _const_;
+Ip6TnlMode ip6tnl_mode_from_string(const char *d) _pure_;
+
+int config_parse_ip6tnl_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);
diff --git a/src/network/networkd-netdev.c b/src/network/networkd-netdev.c
index 4e1fb43..ed85702 100644
--- a/src/network/networkd-netdev.c
+++ b/src/network/networkd-netdev.c
@@ -46,6 +46,7 @@ const NetDevVTable * const netdev_vtable[_NETDEV_KIND_MAX] = {
         [NETDEV_KIND_DUMMY] = &dummy_vtable,
         [NETDEV_KIND_TUN] = &tun_vtable,
         [NETDEV_KIND_TAP] = &tap_vtable,
+        [NETDEV_KIND_IP6TNL] = &ip6tnl_vtable,
 };
 
 static const char* const netdev_kind_table[_NETDEV_KIND_MAX] = {
@@ -64,6 +65,7 @@ static const char* const netdev_kind_table[_NETDEV_KIND_MAX] = {
         [NETDEV_KIND_DUMMY] = "dummy",
         [NETDEV_KIND_TUN] = "tun",
         [NETDEV_KIND_TAP] = "tap",
+        [NETDEV_KIND_IP6TNL] = "ip6tnl",
 };
 
 DEFINE_STRING_TABLE_LOOKUP(netdev_kind, NetDevKind);
diff --git a/src/network/networkd-netdev.h b/src/network/networkd-netdev.h
index 3c44795..77d00d4 100644
--- a/src/network/networkd-netdev.h
+++ b/src/network/networkd-netdev.h
@@ -51,6 +51,7 @@ typedef enum NetDevKind {
         NETDEV_KIND_SIT,
         NETDEV_KIND_VETH,
         NETDEV_KIND_VTI,
+        NETDEV_KIND_IP6TNL,
         NETDEV_KIND_DUMMY,
         NETDEV_KIND_TUN,
         NETDEV_KIND_TAP,
@@ -167,6 +168,7 @@ DEFINE_CAST(GRE, Tunnel);
 DEFINE_CAST(GRETAP, Tunnel);
 DEFINE_CAST(SIT, Tunnel);
 DEFINE_CAST(VTI, Tunnel);
+DEFINE_CAST(IP6TNL, Tunnel);
 DEFINE_CAST(VETH, Veth);
 DEFINE_CAST(DUMMY, Dummy);
 DEFINE_CAST(TUN, TunTap);
diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c
index 2b555ef..0f474d9 100644
--- a/src/network/networkd-network.c
+++ b/src/network/networkd-network.c
@@ -453,7 +453,9 @@ int config_parse_tunnel(const char *unit,
             netdev->kind != NETDEV_KIND_SIT &&
             netdev->kind != NETDEV_KIND_GRE &&
             netdev->kind != NETDEV_KIND_GRETAP &&
-            netdev->kind != NETDEV_KIND_VTI) {
+            netdev->kind != NETDEV_KIND_VTI &&
+            netdev->kind != NETDEV_KIND_IP6TNL
+            ) {
                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
                            "NetDev is not a tunnel, ignoring assignment: %s", rvalue);
                 return 0;

commit 1af2536acf8aecc3eb940d04268a419c956ee10a
Author: Susant Sahani <susant at redhat.com>
Date:   Sat Dec 20 13:35:06 2014 +0530

    networkd: introduce gretap
    
    This patch introdeces gretap to networkd

diff --git a/man/systemd.netdev.xml b/man/systemd.netdev.xml
index 03b0940..ca50558 100644
--- a/man/systemd.netdev.xml
+++ b/man/systemd.netdev.xml
@@ -166,9 +166,10 @@
                                                 <literal>macvlan</literal>,
                                                 <literal>ipvlan</literal>, <literal>vxlan</literal>,
                                                 <literal>ipip</literal>, <literal>gre</literal>,
-                                                <literal>sit</literal>, <literal>vti</literal>,
-                                                <literal>veth</literal>, <literal>tun</literal>,
-                                                <literal>tap</literal> and <literal>dummy</literal>
+                                                <literal>gretap</literal>, <literal>sit</literal>,
+                                                <literal>vti</literal>, <literal>veth</literal>,
+                                                <literal>tun</literal>, <literal>tap</literal> and
+                                                <literal>dummy</literal>
                                                 are supported. This option is compulsory.</para>
                                         </listitem>
                                 </varlistentry>
@@ -329,8 +330,8 @@
                 <title>[Tunnel] Section Options</title>
 
                         <para>The <literal>[Tunnel]</literal> section only applies for netdevs of kind
-                        <literal>ipip</literal>, <literal>sit</literal>, <literal>gre</literal> and
-                        <literal>vti</literal> and accepts the following keys:</para>
+                        <literal>ipip</literal>, <literal>sit</literal>, <literal>gre</literal>, <literal>gretap</literal>,
+                        and <literal>vti</literal> and accepts the following keys:</para>
 
                         <variablelist class='network-directives'>
                                 <varlistentry>
diff --git a/src/libsystemd/sd-rtnl/rtnl-types.c b/src/libsystemd/sd-rtnl/rtnl-types.c
index b0bd661..97b3cee 100644
--- a/src/libsystemd/sd-rtnl/rtnl-types.c
+++ b/src/libsystemd/sd-rtnl/rtnl-types.c
@@ -165,6 +165,7 @@ static const char* const nl_union_link_info_data_table[_NL_UNION_LINK_INFO_DATA_
         [NL_UNION_LINK_INFO_DATA_VXLAN] = "vxlan",
         [NL_UNION_LINK_INFO_DATA_IPIP_TUNNEL] = "ipip",
         [NL_UNION_LINK_INFO_DATA_IPGRE_TUNNEL] = "gre",
+        [NL_UNION_LINK_INFO_DATA_IPGRETAP_TUNNEL] = "gretap",
         [NL_UNION_LINK_INFO_DATA_SIT_TUNNEL] = "sit",
         [NL_UNION_LINK_INFO_DATA_VTI_TUNNEL] = "vti",
 };
@@ -190,6 +191,8 @@ static const NLTypeSystem rtnl_link_info_data_type_systems[_NL_UNION_LINK_INFO_D
                                                   .types = rtnl_link_info_data_iptun_types },
         [NL_UNION_LINK_INFO_DATA_IPGRE_TUNNEL] =  { .max = ELEMENTSOF(rtnl_link_info_data_ipgre_types) - 1,
                                                     .types = rtnl_link_info_data_ipgre_types },
+        [NL_UNION_LINK_INFO_DATA_IPGRETAP_TUNNEL] =  { .max = ELEMENTSOF(rtnl_link_info_data_ipgre_types) - 1,
+                                                    .types = rtnl_link_info_data_ipgre_types },
         [NL_UNION_LINK_INFO_DATA_SIT_TUNNEL] =  { .max = ELEMENTSOF(rtnl_link_info_data_iptun_types) - 1,
                                                   .types = rtnl_link_info_data_iptun_types },
         [NL_UNION_LINK_INFO_DATA_VTI_TUNNEL] =  { .max = ELEMENTSOF(rtnl_link_info_data_ipvti_types) - 1,
diff --git a/src/libsystemd/sd-rtnl/rtnl-types.h b/src/libsystemd/sd-rtnl/rtnl-types.h
index 1bb17a4..aacea19 100644
--- a/src/libsystemd/sd-rtnl/rtnl-types.h
+++ b/src/libsystemd/sd-rtnl/rtnl-types.h
@@ -75,6 +75,7 @@ typedef enum NLUnionLinkInfoData {
         NL_UNION_LINK_INFO_DATA_VXLAN,
         NL_UNION_LINK_INFO_DATA_IPIP_TUNNEL,
         NL_UNION_LINK_INFO_DATA_IPGRE_TUNNEL,
+        NL_UNION_LINK_INFO_DATA_IPGRETAP_TUNNEL,
         NL_UNION_LINK_INFO_DATA_SIT_TUNNEL,
         NL_UNION_LINK_INFO_DATA_VTI_TUNNEL,
         _NL_UNION_LINK_INFO_DATA_MAX,
diff --git a/src/network/networkd-netdev-tunnel.c b/src/network/networkd-netdev-tunnel.c
index 31d3464..fde08fb 100644
--- a/src/network/networkd-netdev-tunnel.c
+++ b/src/network/networkd-netdev-tunnel.c
@@ -140,14 +140,20 @@ static int netdev_sit_fill_message_create(NetDev *netdev, Link *link, sd_rtnl_me
 }
 
 static int netdev_gre_fill_message_create(NetDev *netdev, Link *link, sd_rtnl_message *m) {
-        Tunnel *t = GRE(netdev);
+        Tunnel *t;
         int r;
 
         assert(netdev);
-        assert(link);
-        assert(m);
+
+        if (netdev->kind == NETDEV_KIND_GRE)
+                 t = GRE(netdev);
+        else
+                 t = GRETAP(netdev);
+
         assert(t);
         assert(t->family == AF_INET);
+        assert(link);
+        assert(m);
 
         r = sd_rtnl_message_append_u32(m, IFLA_GRE_LINK, link->ifindex);
         if (r < 0) {
@@ -253,6 +259,9 @@ static int netdev_tunnel_verify(NetDev *netdev, const char *filename) {
         case NETDEV_KIND_GRE:
                 t = GRE(netdev);
                 break;
+        case NETDEV_KIND_GRETAP:
+                t = GRETAP(netdev);
+                break;
         case NETDEV_KIND_VTI:
                 t = VTI(netdev);
                 break;
@@ -339,9 +348,15 @@ static void vti_init(NetDev *n) {
 }
 
 static void gre_init(NetDev *n) {
-        Tunnel *t = GRE(n);
+        Tunnel *t;
 
         assert(n);
+
+        if (n->kind == NETDEV_KIND_GRE)
+                t = GRE(n);
+        else
+                t = GRETAP(n);
+
         assert(t);
 
         t->pmtudisc = true;
@@ -382,3 +397,12 @@ const NetDevVTable gre_vtable = {
         .create_type = NETDEV_CREATE_STACKED,
         .config_verify = netdev_tunnel_verify,
 };
+
+const NetDevVTable gretap_vtable = {
+        .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 000a646..b6f6c9d 100644
--- a/src/network/networkd-netdev-tunnel.h
+++ b/src/network/networkd-netdev-tunnel.h
@@ -41,3 +41,4 @@ extern const NetDevVTable ipip_vtable;
 extern const NetDevVTable sit_vtable;
 extern const NetDevVTable vti_vtable;
 extern const NetDevVTable gre_vtable;
+extern const NetDevVTable gretap_vtable;
diff --git a/src/network/networkd-netdev.c b/src/network/networkd-netdev.c
index 89efc88..4e1fb43 100644
--- a/src/network/networkd-netdev.c
+++ b/src/network/networkd-netdev.c
@@ -39,6 +39,7 @@ const NetDevVTable * const netdev_vtable[_NETDEV_KIND_MAX] = {
         [NETDEV_KIND_VXLAN] = &vxlan_vtable,
         [NETDEV_KIND_IPIP] = &ipip_vtable,
         [NETDEV_KIND_GRE] = &gre_vtable,
+        [NETDEV_KIND_GRETAP] = &gretap_vtable,
         [NETDEV_KIND_SIT] = &sit_vtable,
         [NETDEV_KIND_VTI] = &vti_vtable,
         [NETDEV_KIND_VETH] = &veth_vtable,
@@ -56,6 +57,7 @@ static const char* const netdev_kind_table[_NETDEV_KIND_MAX] = {
         [NETDEV_KIND_VXLAN] = "vxlan",
         [NETDEV_KIND_IPIP] = "ipip",
         [NETDEV_KIND_GRE] = "gre",
+        [NETDEV_KIND_GRETAP] = "gretap",
         [NETDEV_KIND_SIT] = "sit",
         [NETDEV_KIND_VETH] = "veth",
         [NETDEV_KIND_VTI] = "vti",
diff --git a/src/network/networkd-netdev.h b/src/network/networkd-netdev.h
index 1b311c6..3c44795 100644
--- a/src/network/networkd-netdev.h
+++ b/src/network/networkd-netdev.h
@@ -47,6 +47,7 @@ typedef enum NetDevKind {
         NETDEV_KIND_VXLAN,
         NETDEV_KIND_IPIP,
         NETDEV_KIND_GRE,
+        NETDEV_KIND_GRETAP,
         NETDEV_KIND_SIT,
         NETDEV_KIND_VETH,
         NETDEV_KIND_VTI,
@@ -163,6 +164,7 @@ DEFINE_CAST(IPVLAN, IPVlan);
 DEFINE_CAST(VXLAN, VxLan);
 DEFINE_CAST(IPIP, Tunnel);
 DEFINE_CAST(GRE, Tunnel);
+DEFINE_CAST(GRETAP, Tunnel);
 DEFINE_CAST(SIT, Tunnel);
 DEFINE_CAST(VTI, Tunnel);
 DEFINE_CAST(VETH, Veth);
diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c
index b824526..2b555ef 100644
--- a/src/network/networkd-network.c
+++ b/src/network/networkd-network.c
@@ -452,6 +452,7 @@ int config_parse_tunnel(const char *unit,
         if (netdev->kind != NETDEV_KIND_IPIP &&
             netdev->kind != NETDEV_KIND_SIT &&
             netdev->kind != NETDEV_KIND_GRE &&
+            netdev->kind != NETDEV_KIND_GRETAP &&
             netdev->kind != NETDEV_KIND_VTI) {
                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
                            "NetDev is not a tunnel, ignoring assignment: %s", rvalue);



More information about the systemd-commits mailing list