]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
networkd: ip6 tunnel add support for flowlabel
authorSusant Sahani <susant@redhat.com>
Tue, 21 Jul 2015 04:36:44 +0000 (10:06 +0530)
committerSusant Sahani <susant@redhat.com>
Tue, 21 Jul 2015 04:36:44 +0000 (10:06 +0530)
Add Pv6 Flow Label support. The 20-bit Flow Label field in the IPv6
header[RFC2460] is used by a  node to label packets of a flow.

src/network/networkd-netdev-gperf.gperf
src/network/networkd-netdev-tunnel.c
src/network/networkd-netdev-tunnel.h

index 010c106610f4ea581478f524b3771bca848dfb66..63258c03762eaf5a4aa46c3eeb3fd4e0bc23ef18 100644 (file)
@@ -36,6 +36,7 @@ Tunnel.TOS,                  config_parse_unsigned,              0,
 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)
+Tunnel.IPv6FlowLabel,        config_parse_ipv6_flowlabel,        0,                             offsetof(Tunnel, ipv6_flowlabel)
 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)
index 5533fb5c7bb8b65cfc5fe47f01e4b456a56d5a7d..a13edf693602106ad3eb4043731f338ebcbea7b2 100644 (file)
@@ -33,6 +33,7 @@
 #include "conf-parser.h"
 
 #define DEFAULT_TNL_HOP_LIMIT   64
+#define IP6_FLOWINFO_FLOWLABEL  htonl(0x000FFFFF)
 
 static const char* const ip6tnl_mode_table[_NETDEV_IP6_TNL_MODE_MAX] = {
         [NETDEV_IP6_TNL_MODE_IP6IP6] = "ip6ip6",
@@ -264,6 +265,16 @@ static int netdev_ip6tnl_fill_message_create(NetDev *netdev, Link *link, sd_netl
         if (r < 0)
                 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_TTL attribute: %m");
 
+        if (t->ipv6_flowlabel != _NETDEV_IPV6_FLOWLABEL_INVALID) {
+                r = sd_netlink_message_append_u32(m, IFLA_IPTUN_FLOWINFO, t->ipv6_flowlabel);
+                if (r < 0)
+                        return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_FLOWINFO attribute: %m");
+        }
+
+        r = sd_netlink_message_append_u32(m, IFLA_IPTUN_FLAGS, t->flags);
+        if (r < 0)
+                return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_FLAGS attribute: %m");
+
         switch (t->ip6tnl_mode) {
         case NETDEV_IP6_TNL_MODE_IP6IP6:
                 proto = IPPROTO_IPV6;
@@ -380,6 +391,52 @@ int config_parse_tunnel_address(const char *unit,
         return 0;
 }
 
+static const char* const ipv6_flowlabel_table[_NETDEV_IPV6_FLOWLABEL_MAX] = {
+        [NETDEV_IPV6_FLOWLABEL_INHERIT] = "inherit",
+};
+
+DEFINE_STRING_TABLE_LOOKUP(ipv6_flowlabel, IPv6FlowLabel);
+
+int config_parse_ipv6_flowlabel(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) {
+        IPv6FlowLabel *ipv6_flowlabel = data;
+        Tunnel *t = userdata;
+        IPv6FlowLabel s;
+        int k = 0;
+        int r;
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+        assert(ipv6_flowlabel);
+
+        s = ipv6_flowlabel_from_string(rvalue);
+        if (s != _NETDEV_IPV6_FLOWLABEL_INVALID) {
+                *ipv6_flowlabel = IP6_FLOWINFO_FLOWLABEL;
+                t->flags |= IP6_TNL_F_USE_ORIG_FLOWLABEL;
+        } else {
+                r = config_parse_unsigned(unit, filename, line, section, section_line, lvalue, ltype, rvalue, &k, userdata);
+                if (r >= 0) {
+                        if (k > 0xFFFFF)
+                                log_syntax(unit, LOG_ERR, filename, line, k, "Failed to parse IPv6 flowlabel option, ignoring: %s", rvalue);
+                        else {
+                                *ipv6_flowlabel = htonl(k) & IP6_FLOWINFO_FLOWLABEL;
+                                t->flags &= ~IP6_TNL_F_USE_ORIG_FLOWLABEL;
+                        }
+                }
+        }
+
+        return 0;
+}
+
 static void ipip_init(NetDev *n) {
         Tunnel *t = IPIP(n);
 
@@ -452,6 +509,7 @@ static void ip6tnl_init(NetDev *n) {
         t->ttl = DEFAULT_TNL_HOP_LIMIT;
         t->encap_limit = IPV6_DEFAULT_TNL_ENCAP_LIMIT;
         t->ip6tnl_mode = _NETDEV_IP6_TNL_MODE_INVALID;
+        t->ipv6_flowlabel = _NETDEV_IPV6_FLOWLABEL_INVALID;
 }
 
 const NetDevVTable ipip_vtable = {
index 546c9f08b9b1f2ad746098b3f1cb9bf05f106f1d..47981fbe32421b5381f4bfd3a1e42161dbec73a9 100644 (file)
@@ -33,6 +33,12 @@ typedef enum Ip6TnlMode {
         _NETDEV_IP6_TNL_MODE_INVALID = -1,
 } Ip6TnlMode;
 
+typedef enum IPv6FlowLabel {
+        NETDEV_IPV6_FLOWLABEL_INHERIT = 0xFFFFF + 1,
+        _NETDEV_IPV6_FLOWLABEL_MAX,
+        _NETDEV_IPV6_FLOWLABEL_INVALID = -1,
+} IPv6FlowLabel;
+
 struct Tunnel {
         NetDev meta;
 
@@ -48,6 +54,7 @@ struct Tunnel {
         union in_addr_union remote;
 
         Ip6TnlMode ip6tnl_mode;
+        IPv6FlowLabel ipv6_flowlabel;
 
         bool pmtudisc;
 };
@@ -81,3 +88,12 @@ int config_parse_tunnel_address(const char *unit,
                                 const char *rvalue,
                                 void *data,
                                 void *userdata);
+
+const char *ipv6_flowlabel_to_string(IPv6FlowLabel d) _const_;
+IPv6FlowLabel ipv6_flowlabel_from_string(const char *d) _pure_;
+
+int config_parse_ipv6_flowlabel(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);