Commit 52d0d404 authored by Hangbin Liu's avatar Hangbin Liu Committed by David S. Miller

geneve: add ttl inherit support

Similar with commit 72f6d71e ("vxlan: add ttl inherit support"),
currently ttl == 0 means "use whatever default value" on geneve instead
of inherit inner ttl. To respect compatibility with old behavior, let's
add a new IFLA_GENEVE_TTL_INHERIT for geneve ttl inherit support.
Reported-by: default avatarJianlin Shi <jishi@redhat.com>
Suggested-by: default avatarJiri Benc <jbenc@redhat.com>
Signed-off-by: default avatarHangbin Liu <liuhangbin@gmail.com>
Reviewed-by: default avatarJiri Benc <jbenc@redhat.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent d700ec41
...@@ -69,6 +69,7 @@ struct geneve_dev { ...@@ -69,6 +69,7 @@ struct geneve_dev {
struct gro_cells gro_cells; struct gro_cells gro_cells;
bool collect_md; bool collect_md;
bool use_udp6_rx_checksums; bool use_udp6_rx_checksums;
bool ttl_inherit;
}; };
struct geneve_sock { struct geneve_sock {
...@@ -843,7 +844,11 @@ static int geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev, ...@@ -843,7 +844,11 @@ static int geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev,
ttl = key->ttl; ttl = key->ttl;
} else { } else {
tos = ip_tunnel_ecn_encap(fl4.flowi4_tos, ip_hdr(skb), skb); 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; df = key->tun_flags & TUNNEL_DONT_FRAGMENT ? htons(IP_DF) : 0;
...@@ -889,7 +894,11 @@ static int geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev, ...@@ -889,7 +894,11 @@ static int geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev,
} else { } else {
prio = ip_tunnel_ecn_encap(ip6_tclass(fl6.flowlabel), prio = ip_tunnel_ecn_encap(ip6_tclass(fl6.flowlabel),
ip_hdr(skb), skb); 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)); err = geneve_build_skb(dst, skb, info, xnet, sizeof(struct ipv6hdr));
if (unlikely(err)) if (unlikely(err))
...@@ -1091,6 +1100,7 @@ static const struct nla_policy geneve_policy[IFLA_GENEVE_MAX + 1] = { ...@@ -1091,6 +1100,7 @@ static const struct nla_policy geneve_policy[IFLA_GENEVE_MAX + 1] = {
[IFLA_GENEVE_UDP_CSUM] = { .type = NLA_U8 }, [IFLA_GENEVE_UDP_CSUM] = { .type = NLA_U8 },
[IFLA_GENEVE_UDP_ZERO_CSUM6_TX] = { .type = NLA_U8 }, [IFLA_GENEVE_UDP_ZERO_CSUM6_TX] = { .type = NLA_U8 },
[IFLA_GENEVE_UDP_ZERO_CSUM6_RX] = { .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[], static int geneve_validate(struct nlattr *tb[], struct nlattr *data[],
...@@ -1170,7 +1180,8 @@ static bool geneve_dst_addr_equal(struct ip_tunnel_info *a, ...@@ -1170,7 +1180,8 @@ static bool geneve_dst_addr_equal(struct ip_tunnel_info *a,
static int geneve_configure(struct net *net, struct net_device *dev, static int geneve_configure(struct net *net, struct net_device *dev,
struct netlink_ext_ack *extack, struct netlink_ext_ack *extack,
const struct ip_tunnel_info *info, 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_net *gn = net_generic(net, geneve_net_id);
struct geneve_dev *t, *geneve = netdev_priv(dev); struct geneve_dev *t, *geneve = netdev_priv(dev);
...@@ -1219,6 +1230,7 @@ static int geneve_configure(struct net *net, struct net_device *dev, ...@@ -1219,6 +1230,7 @@ static int geneve_configure(struct net *net, struct net_device *dev,
geneve->info = *info; geneve->info = *info;
geneve->collect_md = metadata; geneve->collect_md = metadata;
geneve->use_udp6_rx_checksums = ipv6_rx_csum; geneve->use_udp6_rx_checksums = ipv6_rx_csum;
geneve->ttl_inherit = ttl_inherit;
err = register_netdevice(dev); err = register_netdevice(dev);
if (err) if (err)
...@@ -1237,7 +1249,8 @@ static void init_tnl_info(struct ip_tunnel_info *info, __u16 dst_port) ...@@ -1237,7 +1249,8 @@ static void init_tnl_info(struct ip_tunnel_info *info, __u16 dst_port)
static int geneve_nl2info(struct nlattr *tb[], struct nlattr *data[], static int geneve_nl2info(struct nlattr *tb[], struct nlattr *data[],
struct netlink_ext_ack *extack, struct netlink_ext_ack *extack,
struct ip_tunnel_info *info, bool *metadata, 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; int attrtype;
...@@ -1315,6 +1328,9 @@ static int geneve_nl2info(struct nlattr *tb[], struct nlattr *data[], ...@@ -1315,6 +1328,9 @@ static int geneve_nl2info(struct nlattr *tb[], struct nlattr *data[],
if (data[IFLA_GENEVE_TTL]) if (data[IFLA_GENEVE_TTL])
info->key.ttl = nla_get_u8(data[IFLA_GENEVE_TTL]); info->key.ttl = nla_get_u8(data[IFLA_GENEVE_TTL]);
if (data[IFLA_GENEVE_TTL_INHERIT])
*ttl_inherit = true;
if (data[IFLA_GENEVE_TOS]) if (data[IFLA_GENEVE_TOS])
info->key.tos = nla_get_u8(data[IFLA_GENEVE_TOS]); info->key.tos = nla_get_u8(data[IFLA_GENEVE_TOS]);
...@@ -1438,17 +1454,18 @@ static int geneve_newlink(struct net *net, struct net_device *dev, ...@@ -1438,17 +1454,18 @@ static int geneve_newlink(struct net *net, struct net_device *dev,
{ {
bool use_udp6_rx_checksums = false; bool use_udp6_rx_checksums = false;
struct ip_tunnel_info info; struct ip_tunnel_info info;
bool ttl_inherit = false;
bool metadata = false; bool metadata = false;
int err; int err;
init_tnl_info(&info, GENEVE_UDP_PORT); init_tnl_info(&info, GENEVE_UDP_PORT);
err = geneve_nl2info(tb, data, extack, &info, &metadata, err = geneve_nl2info(tb, data, extack, &info, &metadata,
&use_udp6_rx_checksums, false); &use_udp6_rx_checksums, &ttl_inherit, false);
if (err) if (err)
return err; return err;
err = geneve_configure(net, dev, extack, &info, metadata, err = geneve_configure(net, dev, extack, &info, metadata,
use_udp6_rx_checksums); use_udp6_rx_checksums, ttl_inherit);
if (err) if (err)
return err; return err;
...@@ -1511,6 +1528,7 @@ static int geneve_changelink(struct net_device *dev, struct nlattr *tb[], ...@@ -1511,6 +1528,7 @@ static int geneve_changelink(struct net_device *dev, struct nlattr *tb[],
struct ip_tunnel_info info; struct ip_tunnel_info info;
bool metadata; bool metadata;
bool use_udp6_rx_checksums; bool use_udp6_rx_checksums;
bool ttl_inherit;
int err; int err;
/* If the geneve device is configured for metadata (or externally /* If the geneve device is configured for metadata (or externally
...@@ -1523,8 +1541,9 @@ static int geneve_changelink(struct net_device *dev, struct nlattr *tb[], ...@@ -1523,8 +1541,9 @@ static int geneve_changelink(struct net_device *dev, struct nlattr *tb[],
memcpy(&info, &geneve->info, sizeof(info)); memcpy(&info, &geneve->info, sizeof(info));
metadata = geneve->collect_md; metadata = geneve->collect_md;
use_udp6_rx_checksums = geneve->use_udp6_rx_checksums; use_udp6_rx_checksums = geneve->use_udp6_rx_checksums;
ttl_inherit = geneve->ttl_inherit;
err = geneve_nl2info(tb, data, extack, &info, &metadata, err = geneve_nl2info(tb, data, extack, &info, &metadata,
&use_udp6_rx_checksums, true); &use_udp6_rx_checksums, &ttl_inherit, true);
if (err) if (err)
return err; return err;
...@@ -1537,6 +1556,7 @@ static int geneve_changelink(struct net_device *dev, struct nlattr *tb[], ...@@ -1537,6 +1556,7 @@ static int geneve_changelink(struct net_device *dev, struct nlattr *tb[],
geneve->info = info; geneve->info = info;
geneve->collect_md = metadata; geneve->collect_md = metadata;
geneve->use_udp6_rx_checksums = use_udp6_rx_checksums; geneve->use_udp6_rx_checksums = use_udp6_rx_checksums;
geneve->ttl_inherit = ttl_inherit;
geneve_unquiesce(geneve, gs4, gs6); geneve_unquiesce(geneve, gs4, gs6);
return 0; return 0;
...@@ -1562,6 +1582,7 @@ static size_t geneve_get_size(const struct net_device *dev) ...@@ -1562,6 +1582,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_CSUM */
nla_total_size(sizeof(__u8)) + /* IFLA_GENEVE_UDP_ZERO_CSUM6_TX */ 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_UDP_ZERO_CSUM6_RX */
nla_total_size(sizeof(__u8)) + /* IFLA_GENEVE_TTL_INHERIT */
0; 0;
} }
...@@ -1569,6 +1590,7 @@ static int geneve_fill_info(struct sk_buff *skb, const struct net_device *dev) ...@@ -1569,6 +1590,7 @@ static int geneve_fill_info(struct sk_buff *skb, const struct net_device *dev)
{ {
struct geneve_dev *geneve = netdev_priv(dev); struct geneve_dev *geneve = netdev_priv(dev);
struct ip_tunnel_info *info = &geneve->info; struct ip_tunnel_info *info = &geneve->info;
bool ttl_inherit = geneve->ttl_inherit;
bool metadata = geneve->collect_md; bool metadata = geneve->collect_md;
__u8 tmp_vni[3]; __u8 tmp_vni[3];
__u32 vni; __u32 vni;
...@@ -1614,6 +1636,9 @@ static int geneve_fill_info(struct sk_buff *skb, const struct net_device *dev) ...@@ -1614,6 +1636,9 @@ static int geneve_fill_info(struct sk_buff *skb, const struct net_device *dev)
goto nla_put_failure; goto nla_put_failure;
#endif #endif
if (nla_put_u8(skb, IFLA_GENEVE_TTL_INHERIT, ttl_inherit))
goto nla_put_failure;
return 0; return 0;
nla_put_failure: nla_put_failure:
...@@ -1650,7 +1675,7 @@ struct net_device *geneve_dev_create_fb(struct net *net, const char *name, ...@@ -1650,7 +1675,7 @@ struct net_device *geneve_dev_create_fb(struct net *net, const char *name,
return dev; return dev;
init_tnl_info(&info, dst_port); 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) { if (err) {
free_netdev(dev); free_netdev(dev);
return ERR_PTR(err); return ERR_PTR(err);
......
...@@ -555,6 +555,7 @@ enum { ...@@ -555,6 +555,7 @@ enum {
IFLA_GENEVE_UDP_ZERO_CSUM6_TX, IFLA_GENEVE_UDP_ZERO_CSUM6_TX,
IFLA_GENEVE_UDP_ZERO_CSUM6_RX, IFLA_GENEVE_UDP_ZERO_CSUM6_RX,
IFLA_GENEVE_LABEL, IFLA_GENEVE_LABEL,
IFLA_GENEVE_TTL_INHERIT,
__IFLA_GENEVE_MAX __IFLA_GENEVE_MAX
}; };
#define IFLA_GENEVE_MAX (__IFLA_GENEVE_MAX - 1) #define IFLA_GENEVE_MAX (__IFLA_GENEVE_MAX - 1)
......
...@@ -542,6 +542,7 @@ enum { ...@@ -542,6 +542,7 @@ enum {
IFLA_GENEVE_UDP_ZERO_CSUM6_TX, IFLA_GENEVE_UDP_ZERO_CSUM6_TX,
IFLA_GENEVE_UDP_ZERO_CSUM6_RX, IFLA_GENEVE_UDP_ZERO_CSUM6_RX,
IFLA_GENEVE_LABEL, IFLA_GENEVE_LABEL,
IFLA_GENEVE_TTL_INHERIT,
__IFLA_GENEVE_MAX __IFLA_GENEVE_MAX
}; };
#define IFLA_GENEVE_MAX (__IFLA_GENEVE_MAX - 1) #define IFLA_GENEVE_MAX (__IFLA_GENEVE_MAX - 1)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment