vxlan: add ttl inherit support
authorHangbin Liu <liuhangbin@gmail.com>
Tue, 17 Apr 2018 06:11:28 +0000 (14:11 +0800)
committerDavid S. Miller <davem@davemloft.net>
Tue, 17 Apr 2018 17:53:13 +0000 (13:53 -0400)
Like tos inherit, ttl inherit should also means inherit the inner protocol's
ttl values, which actually not implemented in vxlan yet.

But we could not treat ttl == 0 as "use the inner TTL", because that would be
used also when the "ttl" option is not specified and that would be a behavior
change, and breaking real use cases.

So add a different attribute IFLA_VXLAN_TTL_INHERIT when "ttl inherit" is
specified with ip cmd.

Reported-by: Jianlin Shi <jishi@redhat.com>
Suggested-by: Jiri Benc <jbenc@redhat.com>
Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/vxlan.c
include/net/ip_tunnels.h
include/net/vxlan.h
include/uapi/linux/if_link.h

index fab7a4db249efa6921b35115e0662fff7d1b7695..aee0e60471f10d59c39ad39f8170eedea722455d 100644 (file)
@@ -2085,9 +2085,13 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
                local_ip = vxlan->cfg.saddr;
                dst_cache = &rdst->dst_cache;
                md->gbp = skb->mark;
-               ttl = vxlan->cfg.ttl;
-               if (!ttl && vxlan_addr_multicast(dst))
-                       ttl = 1;
+               if (flags & VXLAN_F_TTL_INHERIT) {
+                       ttl = ip_tunnel_get_ttl(old_iph, skb);
+               } else {
+                       ttl = vxlan->cfg.ttl;
+                       if (!ttl && vxlan_addr_multicast(dst))
+                               ttl = 1;
+               }
 
                tos = vxlan->cfg.tos;
                if (tos == 1)
@@ -2709,6 +2713,7 @@ static const struct nla_policy vxlan_policy[IFLA_VXLAN_MAX + 1] = {
        [IFLA_VXLAN_GBP]        = { .type = NLA_FLAG, },
        [IFLA_VXLAN_GPE]        = { .type = NLA_FLAG, },
        [IFLA_VXLAN_REMCSUM_NOPARTIAL]  = { .type = NLA_FLAG },
+       [IFLA_VXLAN_TTL_INHERIT]        = { .type = NLA_FLAG },
 };
 
 static int vxlan_validate(struct nlattr *tb[], struct nlattr *data[],
@@ -3254,6 +3259,12 @@ static int vxlan_nl2conf(struct nlattr *tb[], struct nlattr *data[],
        if (data[IFLA_VXLAN_TTL])
                conf->ttl = nla_get_u8(data[IFLA_VXLAN_TTL]);
 
+       if (data[IFLA_VXLAN_TTL_INHERIT]) {
+               if (changelink)
+                       return -EOPNOTSUPP;
+               conf->flags |= VXLAN_F_TTL_INHERIT;
+       }
+
        if (data[IFLA_VXLAN_LABEL])
                conf->label = nla_get_be32(data[IFLA_VXLAN_LABEL]) &
                             IPV6_FLOWLABEL_MASK;
index 540a4b4417bfbe4654a6da34ed2ee6d7543dbc62..751646adc7692d605727472775f0d2d6d6fa9f22 100644 (file)
@@ -379,6 +379,17 @@ static inline u8 ip_tunnel_get_dsfield(const struct iphdr *iph,
                return 0;
 }
 
+static inline u8 ip_tunnel_get_ttl(const struct iphdr *iph,
+                                      const struct sk_buff *skb)
+{
+       if (skb->protocol == htons(ETH_P_IP))
+               return iph->ttl;
+       else if (skb->protocol == htons(ETH_P_IPV6))
+               return ((const struct ipv6hdr *)iph)->hop_limit;
+       else
+               return 0;
+}
+
 /* Propogate ECN bits out */
 static inline u8 ip_tunnel_ecn_encap(u8 tos, const struct iphdr *iph,
                                     const struct sk_buff *skb)
index ad73d8b3fcc25856f9812e10a29abd074167758b..b99a02ae3934357747bcc46f4b2192ed492c194b 100644 (file)
@@ -262,6 +262,7 @@ struct vxlan_dev {
 #define VXLAN_F_COLLECT_METADATA       0x2000
 #define VXLAN_F_GPE                    0x4000
 #define VXLAN_F_IPV6_LINKLOCAL         0x8000
+#define VXLAN_F_TTL_INHERIT            0x10000
 
 /* Flags that are used in the receive path. These flags must match in
  * order for a socket to be shareable
index 68699f654118592527096dc26336f57da6a01cdc..b85266420bfb301568e29460d622415c58b2320c 100644 (file)
@@ -516,6 +516,7 @@ enum {
        IFLA_VXLAN_COLLECT_METADATA,
        IFLA_VXLAN_LABEL,
        IFLA_VXLAN_GPE,
+       IFLA_VXLAN_TTL_INHERIT,
        __IFLA_VXLAN_MAX
 };
 #define IFLA_VXLAN_MAX (__IFLA_VXLAN_MAX - 1)