Skip to content

Commit a025fb5

Browse files
sbrivio-rhdavem330
authored andcommitted
geneve: Allow configuration of DF behaviour
draft-ietf-nvo3-geneve-08 says: It is strongly RECOMMENDED that Path MTU Discovery ([RFC1191], [RFC1981]) be used by setting the DF bit in the IP header when Geneve packets are transmitted over IPv4 (this is the default with IPv6). Now that ICMP error handling is working for GENEVE, we can comply with this recommendation. Make this configurable, though, to avoid breaking existing setups. By default, DF won't be set. It can be set or inherited from inner IPv4 packets. If it's configured to be inherited and we are encapsulating IPv6, it will be set. This only applies to non-lwt tunnels: if an external control plane is used, tunnel key will still control the DF flag. v2: - DF behaviour configuration only applies for non-lwt tunnels, apply DF setting only if (!geneve->collect_md) in geneve_xmit_skb() (Stephen Hemminger) Signed-off-by: Stefano Brivio <sbrivio@redhat.com> Reviewed-by: Sabrina Dubroca <sd@queasysnail.net> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent a079664 commit a025fb5

File tree

2 files changed

+56
-8
lines changed

2 files changed

+56
-8
lines changed

drivers/net/geneve.c

Lines changed: 47 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ struct geneve_dev {
7070
bool collect_md;
7171
bool use_udp6_rx_checksums;
7272
bool ttl_inherit;
73+
enum ifla_geneve_df df;
7374
};
7475

7576
struct geneve_sock {
@@ -875,8 +876,8 @@ static int geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev,
875876
struct rtable *rt;
876877
struct flowi4 fl4;
877878
__u8 tos, ttl;
879+
__be16 df = 0;
878880
__be16 sport;
879-
__be16 df;
880881
int err;
881882

882883
rt = geneve_get_v4_rt(skb, dev, gs4, &fl4, info);
@@ -890,15 +891,31 @@ static int geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev,
890891
if (geneve->collect_md) {
891892
tos = ip_tunnel_ecn_encap(key->tos, ip_hdr(skb), skb);
892893
ttl = key->ttl;
894+
895+
df = key->tun_flags & TUNNEL_DONT_FRAGMENT ? htons(IP_DF) : 0;
893896
} else {
894897
tos = ip_tunnel_ecn_encap(fl4.flowi4_tos, ip_hdr(skb), skb);
895898
if (geneve->ttl_inherit)
896899
ttl = ip_tunnel_get_ttl(ip_hdr(skb), skb);
897900
else
898901
ttl = key->ttl;
899902
ttl = ttl ? : ip4_dst_hoplimit(&rt->dst);
903+
904+
if (geneve->df == GENEVE_DF_SET) {
905+
df = htons(IP_DF);
906+
} else if (geneve->df == GENEVE_DF_INHERIT) {
907+
struct ethhdr *eth = eth_hdr(skb);
908+
909+
if (ntohs(eth->h_proto) == ETH_P_IPV6) {
910+
df = htons(IP_DF);
911+
} else if (ntohs(eth->h_proto) == ETH_P_IP) {
912+
struct iphdr *iph = ip_hdr(skb);
913+
914+
if (iph->frag_off & htons(IP_DF))
915+
df = htons(IP_DF);
916+
}
917+
}
900918
}
901-
df = key->tun_flags & TUNNEL_DONT_FRAGMENT ? htons(IP_DF) : 0;
902919

903920
err = geneve_build_skb(&rt->dst, skb, info, xnet, sizeof(struct iphdr));
904921
if (unlikely(err))
@@ -1145,6 +1162,7 @@ static const struct nla_policy geneve_policy[IFLA_GENEVE_MAX + 1] = {
11451162
[IFLA_GENEVE_UDP_ZERO_CSUM6_TX] = { .type = NLA_U8 },
11461163
[IFLA_GENEVE_UDP_ZERO_CSUM6_RX] = { .type = NLA_U8 },
11471164
[IFLA_GENEVE_TTL_INHERIT] = { .type = NLA_U8 },
1165+
[IFLA_GENEVE_DF] = { .type = NLA_U8 },
11481166
};
11491167

11501168
static int geneve_validate(struct nlattr *tb[], struct nlattr *data[],
@@ -1180,6 +1198,16 @@ static int geneve_validate(struct nlattr *tb[], struct nlattr *data[],
11801198
}
11811199
}
11821200

1201+
if (data[IFLA_GENEVE_DF]) {
1202+
enum ifla_geneve_df df = nla_get_u8(data[IFLA_GENEVE_DF]);
1203+
1204+
if (df < 0 || df > GENEVE_DF_MAX) {
1205+
NL_SET_ERR_MSG_ATTR(extack, tb[IFLA_GENEVE_DF],
1206+
"Invalid DF attribute");
1207+
return -EINVAL;
1208+
}
1209+
}
1210+
11831211
return 0;
11841212
}
11851213

@@ -1225,7 +1253,7 @@ static int geneve_configure(struct net *net, struct net_device *dev,
12251253
struct netlink_ext_ack *extack,
12261254
const struct ip_tunnel_info *info,
12271255
bool metadata, bool ipv6_rx_csum,
1228-
bool ttl_inherit)
1256+
bool ttl_inherit, enum ifla_geneve_df df)
12291257
{
12301258
struct geneve_net *gn = net_generic(net, geneve_net_id);
12311259
struct geneve_dev *t, *geneve = netdev_priv(dev);
@@ -1275,6 +1303,7 @@ static int geneve_configure(struct net *net, struct net_device *dev,
12751303
geneve->collect_md = metadata;
12761304
geneve->use_udp6_rx_checksums = ipv6_rx_csum;
12771305
geneve->ttl_inherit = ttl_inherit;
1306+
geneve->df = df;
12781307

12791308
err = register_netdevice(dev);
12801309
if (err)
@@ -1294,7 +1323,7 @@ static int geneve_nl2info(struct nlattr *tb[], struct nlattr *data[],
12941323
struct netlink_ext_ack *extack,
12951324
struct ip_tunnel_info *info, bool *metadata,
12961325
bool *use_udp6_rx_checksums, bool *ttl_inherit,
1297-
bool changelink)
1326+
enum ifla_geneve_df *df, bool changelink)
12981327
{
12991328
int attrtype;
13001329

@@ -1382,6 +1411,9 @@ static int geneve_nl2info(struct nlattr *tb[], struct nlattr *data[],
13821411
if (data[IFLA_GENEVE_TOS])
13831412
info->key.tos = nla_get_u8(data[IFLA_GENEVE_TOS]);
13841413

1414+
if (data[IFLA_GENEVE_DF])
1415+
*df = nla_get_u8(data[IFLA_GENEVE_DF]);
1416+
13851417
if (data[IFLA_GENEVE_LABEL]) {
13861418
info->key.label = nla_get_be32(data[IFLA_GENEVE_LABEL]) &
13871419
IPV6_FLOWLABEL_MASK;
@@ -1500,6 +1532,7 @@ static int geneve_newlink(struct net *net, struct net_device *dev,
15001532
struct nlattr *tb[], struct nlattr *data[],
15011533
struct netlink_ext_ack *extack)
15021534
{
1535+
enum ifla_geneve_df df = GENEVE_DF_UNSET;
15031536
bool use_udp6_rx_checksums = false;
15041537
struct ip_tunnel_info info;
15051538
bool ttl_inherit = false;
@@ -1508,12 +1541,12 @@ static int geneve_newlink(struct net *net, struct net_device *dev,
15081541

15091542
init_tnl_info(&info, GENEVE_UDP_PORT);
15101543
err = geneve_nl2info(tb, data, extack, &info, &metadata,
1511-
&use_udp6_rx_checksums, &ttl_inherit, false);
1544+
&use_udp6_rx_checksums, &ttl_inherit, &df, false);
15121545
if (err)
15131546
return err;
15141547

15151548
err = geneve_configure(net, dev, extack, &info, metadata,
1516-
use_udp6_rx_checksums, ttl_inherit);
1549+
use_udp6_rx_checksums, ttl_inherit, df);
15171550
if (err)
15181551
return err;
15191552

@@ -1576,6 +1609,7 @@ static int geneve_changelink(struct net_device *dev, struct nlattr *tb[],
15761609
struct ip_tunnel_info info;
15771610
bool metadata;
15781611
bool use_udp6_rx_checksums;
1612+
enum ifla_geneve_df df;
15791613
bool ttl_inherit;
15801614
int err;
15811615

@@ -1591,7 +1625,7 @@ static int geneve_changelink(struct net_device *dev, struct nlattr *tb[],
15911625
use_udp6_rx_checksums = geneve->use_udp6_rx_checksums;
15921626
ttl_inherit = geneve->ttl_inherit;
15931627
err = geneve_nl2info(tb, data, extack, &info, &metadata,
1594-
&use_udp6_rx_checksums, &ttl_inherit, true);
1628+
&use_udp6_rx_checksums, &ttl_inherit, &df, true);
15951629
if (err)
15961630
return err;
15971631

@@ -1624,6 +1658,7 @@ static size_t geneve_get_size(const struct net_device *dev)
16241658
nla_total_size(sizeof(struct in6_addr)) + /* IFLA_GENEVE_REMOTE{6} */
16251659
nla_total_size(sizeof(__u8)) + /* IFLA_GENEVE_TTL */
16261660
nla_total_size(sizeof(__u8)) + /* IFLA_GENEVE_TOS */
1661+
nla_total_size(sizeof(__u8)) + /* IFLA_GENEVE_DF */
16271662
nla_total_size(sizeof(__be32)) + /* IFLA_GENEVE_LABEL */
16281663
nla_total_size(sizeof(__be16)) + /* IFLA_GENEVE_PORT */
16291664
nla_total_size(0) + /* IFLA_GENEVE_COLLECT_METADATA */
@@ -1672,6 +1707,9 @@ static int geneve_fill_info(struct sk_buff *skb, const struct net_device *dev)
16721707
nla_put_be32(skb, IFLA_GENEVE_LABEL, info->key.label))
16731708
goto nla_put_failure;
16741709

1710+
if (nla_put_u8(skb, IFLA_GENEVE_DF, geneve->df))
1711+
goto nla_put_failure;
1712+
16751713
if (nla_put_be16(skb, IFLA_GENEVE_PORT, info->key.tp_dst))
16761714
goto nla_put_failure;
16771715

@@ -1723,7 +1761,8 @@ struct net_device *geneve_dev_create_fb(struct net *net, const char *name,
17231761
return dev;
17241762

17251763
init_tnl_info(&info, dst_port);
1726-
err = geneve_configure(net, dev, NULL, &info, true, true, false);
1764+
err = geneve_configure(net, dev, NULL, &info,
1765+
true, true, false, GENEVE_DF_UNSET);
17271766
if (err) {
17281767
free_netdev(dev);
17291768
return ERR_PTR(err);

include/uapi/linux/if_link.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -566,10 +566,19 @@ enum {
566566
IFLA_GENEVE_UDP_ZERO_CSUM6_RX,
567567
IFLA_GENEVE_LABEL,
568568
IFLA_GENEVE_TTL_INHERIT,
569+
IFLA_GENEVE_DF,
569570
__IFLA_GENEVE_MAX
570571
};
571572
#define IFLA_GENEVE_MAX (__IFLA_GENEVE_MAX - 1)
572573

574+
enum ifla_geneve_df {
575+
GENEVE_DF_UNSET = 0,
576+
GENEVE_DF_SET,
577+
GENEVE_DF_INHERIT,
578+
__GENEVE_DF_END,
579+
GENEVE_DF_MAX = __GENEVE_DF_END - 1,
580+
};
581+
573582
/* PPP section */
574583
enum {
575584
IFLA_PPP_UNSPEC,

0 commit comments

Comments
 (0)