]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - drivers/net/geneve.c
Merge tag 'jfs-for-4.20' of git://github.com/kleikamp/linux-shaggy
[linux.git] / drivers / net / geneve.c
index 61c4bfbeb41c043ef0a0f24ce242c960eaa03db1..a0cd1c41cf5f07255283be656f1ecf074417532a 100644 (file)
@@ -69,6 +69,7 @@ struct geneve_dev {
        struct gro_cells   gro_cells;
        bool               collect_md;
        bool               use_udp6_rx_checksums;
+       bool               ttl_inherit;
 };
 
 struct geneve_sock {
@@ -830,8 +831,8 @@ static int geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev,
        if (IS_ERR(rt))
                return PTR_ERR(rt);
 
-       skb_dst_update_pmtu(skb, dst_mtu(&rt->dst) -
-                                GENEVE_IPV4_HLEN - info->options_len);
+       skb_tunnel_check_pmtu(skb, &rt->dst,
+                             GENEVE_IPV4_HLEN + info->options_len);
 
        sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true);
        if (geneve->collect_md) {
@@ -839,7 +840,11 @@ static int geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev,
                ttl = key->ttl;
        } else {
                tos = ip_tunnel_ecn_encap(fl4.flowi4_tos, ip_hdr(skb), skb);
-               ttl = key->ttl ? : ip4_dst_hoplimit(&rt->dst);
+               if (geneve->ttl_inherit)
+                       ttl = ip_tunnel_get_ttl(ip_hdr(skb), skb);
+               else
+                       ttl = key->ttl;
+               ttl = ttl ? : ip4_dst_hoplimit(&rt->dst);
        }
        df = key->tun_flags & TUNNEL_DONT_FRAGMENT ? htons(IP_DF) : 0;
 
@@ -872,8 +877,7 @@ static int geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev,
        if (IS_ERR(dst))
                return PTR_ERR(dst);
 
-       skb_dst_update_pmtu(skb, dst_mtu(dst) -
-                                GENEVE_IPV6_HLEN - info->options_len);
+       skb_tunnel_check_pmtu(skb, dst, GENEVE_IPV6_HLEN + info->options_len);
 
        sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true);
        if (geneve->collect_md) {
@@ -882,7 +886,11 @@ static int geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev,
        } else {
                prio = ip_tunnel_ecn_encap(ip6_tclass(fl6.flowlabel),
                                           ip_hdr(skb), skb);
-               ttl = key->ttl ? : ip6_dst_hoplimit(dst);
+               if (geneve->ttl_inherit)
+                       ttl = ip_tunnel_get_ttl(ip_hdr(skb), skb);
+               else
+                       ttl = key->ttl;
+               ttl = ttl ? : ip6_dst_hoplimit(dst);
        }
        err = geneve_build_skb(dst, skb, info, xnet, sizeof(struct ipv6hdr));
        if (unlikely(err))
@@ -1084,6 +1092,7 @@ static const struct nla_policy geneve_policy[IFLA_GENEVE_MAX + 1] = {
        [IFLA_GENEVE_UDP_CSUM]          = { .type = NLA_U8 },
        [IFLA_GENEVE_UDP_ZERO_CSUM6_TX] = { .type = NLA_U8 },
        [IFLA_GENEVE_UDP_ZERO_CSUM6_RX] = { .type = NLA_U8 },
+       [IFLA_GENEVE_TTL_INHERIT]       = { .type = NLA_U8 },
 };
 
 static int geneve_validate(struct nlattr *tb[], struct nlattr *data[],
@@ -1163,7 +1172,8 @@ static bool geneve_dst_addr_equal(struct ip_tunnel_info *a,
 static int geneve_configure(struct net *net, struct net_device *dev,
                            struct netlink_ext_ack *extack,
                            const struct ip_tunnel_info *info,
-                           bool metadata, bool ipv6_rx_csum)
+                           bool metadata, bool ipv6_rx_csum,
+                           bool ttl_inherit)
 {
        struct geneve_net *gn = net_generic(net, geneve_net_id);
        struct geneve_dev *t, *geneve = netdev_priv(dev);
@@ -1212,6 +1222,7 @@ static int geneve_configure(struct net *net, struct net_device *dev,
        geneve->info = *info;
        geneve->collect_md = metadata;
        geneve->use_udp6_rx_checksums = ipv6_rx_csum;
+       geneve->ttl_inherit = ttl_inherit;
 
        err = register_netdevice(dev);
        if (err)
@@ -1230,7 +1241,8 @@ static void init_tnl_info(struct ip_tunnel_info *info, __u16 dst_port)
 static int geneve_nl2info(struct nlattr *tb[], struct nlattr *data[],
                          struct netlink_ext_ack *extack,
                          struct ip_tunnel_info *info, bool *metadata,
-                         bool *use_udp6_rx_checksums, bool changelink)
+                         bool *use_udp6_rx_checksums, bool *ttl_inherit,
+                         bool changelink)
 {
        int attrtype;
 
@@ -1305,8 +1317,15 @@ static int geneve_nl2info(struct nlattr *tb[], struct nlattr *data[],
                info->key.tun_id = tunid;
        }
 
-       if (data[IFLA_GENEVE_TTL])
+       if (data[IFLA_GENEVE_TTL_INHERIT]) {
+               if (nla_get_u8(data[IFLA_GENEVE_TTL_INHERIT]))
+                       *ttl_inherit = true;
+               else
+                       *ttl_inherit = false;
+       } else if (data[IFLA_GENEVE_TTL]) {
                info->key.ttl = nla_get_u8(data[IFLA_GENEVE_TTL]);
+               *ttl_inherit = false;
+       }
 
        if (data[IFLA_GENEVE_TOS])
                info->key.tos = nla_get_u8(data[IFLA_GENEVE_TOS]);
@@ -1431,17 +1450,18 @@ static int geneve_newlink(struct net *net, struct net_device *dev,
 {
        bool use_udp6_rx_checksums = false;
        struct ip_tunnel_info info;
+       bool ttl_inherit = false;
        bool metadata = false;
        int err;
 
        init_tnl_info(&info, GENEVE_UDP_PORT);
        err = geneve_nl2info(tb, data, extack, &info, &metadata,
-                            &use_udp6_rx_checksums, false);
+                            &use_udp6_rx_checksums, &ttl_inherit, false);
        if (err)
                return err;
 
        err = geneve_configure(net, dev, extack, &info, metadata,
-                              use_udp6_rx_checksums);
+                              use_udp6_rx_checksums, ttl_inherit);
        if (err)
                return err;
 
@@ -1504,6 +1524,7 @@ static int geneve_changelink(struct net_device *dev, struct nlattr *tb[],
        struct ip_tunnel_info info;
        bool metadata;
        bool use_udp6_rx_checksums;
+       bool ttl_inherit;
        int err;
 
        /* If the geneve device is configured for metadata (or externally
@@ -1516,8 +1537,9 @@ static int geneve_changelink(struct net_device *dev, struct nlattr *tb[],
        memcpy(&info, &geneve->info, sizeof(info));
        metadata = geneve->collect_md;
        use_udp6_rx_checksums = geneve->use_udp6_rx_checksums;
+       ttl_inherit = geneve->ttl_inherit;
        err = geneve_nl2info(tb, data, extack, &info, &metadata,
-                            &use_udp6_rx_checksums, true);
+                            &use_udp6_rx_checksums, &ttl_inherit, true);
        if (err)
                return err;
 
@@ -1530,6 +1552,7 @@ static int geneve_changelink(struct net_device *dev, struct nlattr *tb[],
        geneve->info = info;
        geneve->collect_md = metadata;
        geneve->use_udp6_rx_checksums = use_udp6_rx_checksums;
+       geneve->ttl_inherit = ttl_inherit;
        geneve_unquiesce(geneve, gs4, gs6);
 
        return 0;
@@ -1555,6 +1578,7 @@ static size_t geneve_get_size(const struct net_device *dev)
                nla_total_size(sizeof(__u8)) + /* IFLA_GENEVE_UDP_CSUM */
                nla_total_size(sizeof(__u8)) + /* IFLA_GENEVE_UDP_ZERO_CSUM6_TX */
                nla_total_size(sizeof(__u8)) + /* IFLA_GENEVE_UDP_ZERO_CSUM6_RX */
+               nla_total_size(sizeof(__u8)) + /* IFLA_GENEVE_TTL_INHERIT */
                0;
 }
 
@@ -1562,6 +1586,7 @@ static int geneve_fill_info(struct sk_buff *skb, const struct net_device *dev)
 {
        struct geneve_dev *geneve = netdev_priv(dev);
        struct ip_tunnel_info *info = &geneve->info;
+       bool ttl_inherit = geneve->ttl_inherit;
        bool metadata = geneve->collect_md;
        __u8 tmp_vni[3];
        __u32 vni;
@@ -1607,6 +1632,9 @@ static int geneve_fill_info(struct sk_buff *skb, const struct net_device *dev)
                goto nla_put_failure;
 #endif
 
+       if (nla_put_u8(skb, IFLA_GENEVE_TTL_INHERIT, ttl_inherit))
+               goto nla_put_failure;
+
        return 0;
 
 nla_put_failure:
@@ -1643,7 +1671,7 @@ struct net_device *geneve_dev_create_fb(struct net *net, const char *name,
                return dev;
 
        init_tnl_info(&info, dst_port);
-       err = geneve_configure(net, dev, NULL, &info, true, true);
+       err = geneve_configure(net, dev, NULL, &info, true, true, false);
        if (err) {
                free_netdev(dev);
                return ERR_PTR(err);