aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefano Brivio <sbrivio@redhat.com>2018-11-08 06:19:19 -0500
committerDavid S. Miller <davem@davemloft.net>2018-11-08 20:13:08 -0500
commita025fb5f49ad38cf749753b16fcd031d0d678f2b (patch)
treed6abb23ae528b57c7faeac6c3bb699c0a019a931
parenta07966447f39fe43e37d05c9bfc92b1493267a59 (diff)
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>
-rw-r--r--drivers/net/geneve.c55
-rw-r--r--include/uapi/linux/if_link.h9
2 files changed, 56 insertions, 8 deletions
diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c
index 4dc457489770..7c53e06b31c3 100644
--- a/drivers/net/geneve.c
+++ b/drivers/net/geneve.c
@@ -70,6 +70,7 @@ struct geneve_dev {
70 bool collect_md; 70 bool collect_md;
71 bool use_udp6_rx_checksums; 71 bool use_udp6_rx_checksums;
72 bool ttl_inherit; 72 bool ttl_inherit;
73 enum ifla_geneve_df df;
73}; 74};
74 75
75struct geneve_sock { 76struct geneve_sock {
@@ -875,8 +876,8 @@ static int geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev,
875 struct rtable *rt; 876 struct rtable *rt;
876 struct flowi4 fl4; 877 struct flowi4 fl4;
877 __u8 tos, ttl; 878 __u8 tos, ttl;
879 __be16 df = 0;
878 __be16 sport; 880 __be16 sport;
879 __be16 df;
880 int err; 881 int err;
881 882
882 rt = geneve_get_v4_rt(skb, dev, gs4, &fl4, info); 883 rt = geneve_get_v4_rt(skb, dev, gs4, &fl4, info);
@@ -890,6 +891,8 @@ static int geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev,
890 if (geneve->collect_md) { 891 if (geneve->collect_md) {
891 tos = ip_tunnel_ecn_encap(key->tos, ip_hdr(skb), skb); 892 tos = ip_tunnel_ecn_encap(key->tos, ip_hdr(skb), skb);
892 ttl = key->ttl; 893 ttl = key->ttl;
894
895 df = key->tun_flags & TUNNEL_DONT_FRAGMENT ? htons(IP_DF) : 0;
893 } else { 896 } else {
894 tos = ip_tunnel_ecn_encap(fl4.flowi4_tos, ip_hdr(skb), skb); 897 tos = ip_tunnel_ecn_encap(fl4.flowi4_tos, ip_hdr(skb), skb);
895 if (geneve->ttl_inherit) 898 if (geneve->ttl_inherit)
@@ -897,8 +900,22 @@ static int geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev,
897 else 900 else
898 ttl = key->ttl; 901 ttl = key->ttl;
899 ttl = ttl ? : ip4_dst_hoplimit(&rt->dst); 902 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 }
900 } 918 }
901 df = key->tun_flags & TUNNEL_DONT_FRAGMENT ? htons(IP_DF) : 0;
902 919
903 err = geneve_build_skb(&rt->dst, skb, info, xnet, sizeof(struct iphdr)); 920 err = geneve_build_skb(&rt->dst, skb, info, xnet, sizeof(struct iphdr));
904 if (unlikely(err)) 921 if (unlikely(err))
@@ -1145,6 +1162,7 @@ static const struct nla_policy geneve_policy[IFLA_GENEVE_MAX + 1] = {
1145 [IFLA_GENEVE_UDP_ZERO_CSUM6_TX] = { .type = NLA_U8 }, 1162 [IFLA_GENEVE_UDP_ZERO_CSUM6_TX] = { .type = NLA_U8 },
1146 [IFLA_GENEVE_UDP_ZERO_CSUM6_RX] = { .type = NLA_U8 }, 1163 [IFLA_GENEVE_UDP_ZERO_CSUM6_RX] = { .type = NLA_U8 },
1147 [IFLA_GENEVE_TTL_INHERIT] = { .type = NLA_U8 }, 1164 [IFLA_GENEVE_TTL_INHERIT] = { .type = NLA_U8 },
1165 [IFLA_GENEVE_DF] = { .type = NLA_U8 },
1148}; 1166};
1149 1167
1150static int geneve_validate(struct nlattr *tb[], struct nlattr *data[], 1168static int geneve_validate(struct nlattr *tb[], struct nlattr *data[],
@@ -1180,6 +1198,16 @@ static int geneve_validate(struct nlattr *tb[], struct nlattr *data[],
1180 } 1198 }
1181 } 1199 }
1182 1200
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
1183 return 0; 1211 return 0;
1184} 1212}
1185 1213
@@ -1225,7 +1253,7 @@ static int geneve_configure(struct net *net, struct net_device *dev,
1225 struct netlink_ext_ack *extack, 1253 struct netlink_ext_ack *extack,
1226 const struct ip_tunnel_info *info, 1254 const struct ip_tunnel_info *info,
1227 bool metadata, bool ipv6_rx_csum, 1255 bool metadata, bool ipv6_rx_csum,
1228 bool ttl_inherit) 1256 bool ttl_inherit, enum ifla_geneve_df df)
1229{ 1257{
1230 struct geneve_net *gn = net_generic(net, geneve_net_id); 1258 struct geneve_net *gn = net_generic(net, geneve_net_id);
1231 struct geneve_dev *t, *geneve = netdev_priv(dev); 1259 struct geneve_dev *t, *geneve = netdev_priv(dev);
@@ -1275,6 +1303,7 @@ static int geneve_configure(struct net *net, struct net_device *dev,
1275 geneve->collect_md = metadata; 1303 geneve->collect_md = metadata;
1276 geneve->use_udp6_rx_checksums = ipv6_rx_csum; 1304 geneve->use_udp6_rx_checksums = ipv6_rx_csum;
1277 geneve->ttl_inherit = ttl_inherit; 1305 geneve->ttl_inherit = ttl_inherit;
1306 geneve->df = df;
1278 1307
1279 err = register_netdevice(dev); 1308 err = register_netdevice(dev);
1280 if (err) 1309 if (err)
@@ -1294,7 +1323,7 @@ static int geneve_nl2info(struct nlattr *tb[], struct nlattr *data[],
1294 struct netlink_ext_ack *extack, 1323 struct netlink_ext_ack *extack,
1295 struct ip_tunnel_info *info, bool *metadata, 1324 struct ip_tunnel_info *info, bool *metadata,
1296 bool *use_udp6_rx_checksums, bool *ttl_inherit, 1325 bool *use_udp6_rx_checksums, bool *ttl_inherit,
1297 bool changelink) 1326 enum ifla_geneve_df *df, bool changelink)
1298{ 1327{
1299 int attrtype; 1328 int attrtype;
1300 1329
@@ -1382,6 +1411,9 @@ static int geneve_nl2info(struct nlattr *tb[], struct nlattr *data[],
1382 if (data[IFLA_GENEVE_TOS]) 1411 if (data[IFLA_GENEVE_TOS])
1383 info->key.tos = nla_get_u8(data[IFLA_GENEVE_TOS]); 1412 info->key.tos = nla_get_u8(data[IFLA_GENEVE_TOS]);
1384 1413
1414 if (data[IFLA_GENEVE_DF])
1415 *df = nla_get_u8(data[IFLA_GENEVE_DF]);
1416
1385 if (data[IFLA_GENEVE_LABEL]) { 1417 if (data[IFLA_GENEVE_LABEL]) {
1386 info->key.label = nla_get_be32(data[IFLA_GENEVE_LABEL]) & 1418 info->key.label = nla_get_be32(data[IFLA_GENEVE_LABEL]) &
1387 IPV6_FLOWLABEL_MASK; 1419 IPV6_FLOWLABEL_MASK;
@@ -1500,6 +1532,7 @@ static int geneve_newlink(struct net *net, struct net_device *dev,
1500 struct nlattr *tb[], struct nlattr *data[], 1532 struct nlattr *tb[], struct nlattr *data[],
1501 struct netlink_ext_ack *extack) 1533 struct netlink_ext_ack *extack)
1502{ 1534{
1535 enum ifla_geneve_df df = GENEVE_DF_UNSET;
1503 bool use_udp6_rx_checksums = false; 1536 bool use_udp6_rx_checksums = false;
1504 struct ip_tunnel_info info; 1537 struct ip_tunnel_info info;
1505 bool ttl_inherit = false; 1538 bool ttl_inherit = false;
@@ -1508,12 +1541,12 @@ static int geneve_newlink(struct net *net, struct net_device *dev,
1508 1541
1509 init_tnl_info(&info, GENEVE_UDP_PORT); 1542 init_tnl_info(&info, GENEVE_UDP_PORT);
1510 err = geneve_nl2info(tb, data, extack, &info, &metadata, 1543 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);
1512 if (err) 1545 if (err)
1513 return err; 1546 return err;
1514 1547
1515 err = geneve_configure(net, dev, extack, &info, metadata, 1548 err = geneve_configure(net, dev, extack, &info, metadata,
1516 use_udp6_rx_checksums, ttl_inherit); 1549 use_udp6_rx_checksums, ttl_inherit, df);
1517 if (err) 1550 if (err)
1518 return err; 1551 return err;
1519 1552
@@ -1576,6 +1609,7 @@ static int geneve_changelink(struct net_device *dev, struct nlattr *tb[],
1576 struct ip_tunnel_info info; 1609 struct ip_tunnel_info info;
1577 bool metadata; 1610 bool metadata;
1578 bool use_udp6_rx_checksums; 1611 bool use_udp6_rx_checksums;
1612 enum ifla_geneve_df df;
1579 bool ttl_inherit; 1613 bool ttl_inherit;
1580 int err; 1614 int err;
1581 1615
@@ -1591,7 +1625,7 @@ static int geneve_changelink(struct net_device *dev, struct nlattr *tb[],
1591 use_udp6_rx_checksums = geneve->use_udp6_rx_checksums; 1625 use_udp6_rx_checksums = geneve->use_udp6_rx_checksums;
1592 ttl_inherit = geneve->ttl_inherit; 1626 ttl_inherit = geneve->ttl_inherit;
1593 err = geneve_nl2info(tb, data, extack, &info, &metadata, 1627 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);
1595 if (err) 1629 if (err)
1596 return err; 1630 return err;
1597 1631
@@ -1624,6 +1658,7 @@ static size_t geneve_get_size(const struct net_device *dev)
1624 nla_total_size(sizeof(struct in6_addr)) + /* IFLA_GENEVE_REMOTE{6} */ 1658 nla_total_size(sizeof(struct in6_addr)) + /* IFLA_GENEVE_REMOTE{6} */
1625 nla_total_size(sizeof(__u8)) + /* IFLA_GENEVE_TTL */ 1659 nla_total_size(sizeof(__u8)) + /* IFLA_GENEVE_TTL */
1626 nla_total_size(sizeof(__u8)) + /* IFLA_GENEVE_TOS */ 1660 nla_total_size(sizeof(__u8)) + /* IFLA_GENEVE_TOS */
1661 nla_total_size(sizeof(__u8)) + /* IFLA_GENEVE_DF */
1627 nla_total_size(sizeof(__be32)) + /* IFLA_GENEVE_LABEL */ 1662 nla_total_size(sizeof(__be32)) + /* IFLA_GENEVE_LABEL */
1628 nla_total_size(sizeof(__be16)) + /* IFLA_GENEVE_PORT */ 1663 nla_total_size(sizeof(__be16)) + /* IFLA_GENEVE_PORT */
1629 nla_total_size(0) + /* IFLA_GENEVE_COLLECT_METADATA */ 1664 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)
1672 nla_put_be32(skb, IFLA_GENEVE_LABEL, info->key.label)) 1707 nla_put_be32(skb, IFLA_GENEVE_LABEL, info->key.label))
1673 goto nla_put_failure; 1708 goto nla_put_failure;
1674 1709
1710 if (nla_put_u8(skb, IFLA_GENEVE_DF, geneve->df))
1711 goto nla_put_failure;
1712
1675 if (nla_put_be16(skb, IFLA_GENEVE_PORT, info->key.tp_dst)) 1713 if (nla_put_be16(skb, IFLA_GENEVE_PORT, info->key.tp_dst))
1676 goto nla_put_failure; 1714 goto nla_put_failure;
1677 1715
@@ -1723,7 +1761,8 @@ struct net_device *geneve_dev_create_fb(struct net *net, const char *name,
1723 return dev; 1761 return dev;
1724 1762
1725 init_tnl_info(&info, dst_port); 1763 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);
1727 if (err) { 1766 if (err) {
1728 free_netdev(dev); 1767 free_netdev(dev);
1729 return ERR_PTR(err); 1768 return ERR_PTR(err);
diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h
index efc588949431..f42c069d81db 100644
--- a/include/uapi/linux/if_link.h
+++ b/include/uapi/linux/if_link.h
@@ -566,10 +566,19 @@ enum {
566 IFLA_GENEVE_UDP_ZERO_CSUM6_RX, 566 IFLA_GENEVE_UDP_ZERO_CSUM6_RX,
567 IFLA_GENEVE_LABEL, 567 IFLA_GENEVE_LABEL,
568 IFLA_GENEVE_TTL_INHERIT, 568 IFLA_GENEVE_TTL_INHERIT,
569 IFLA_GENEVE_DF,
569 __IFLA_GENEVE_MAX 570 __IFLA_GENEVE_MAX
570}; 571};
571#define IFLA_GENEVE_MAX (__IFLA_GENEVE_MAX - 1) 572#define IFLA_GENEVE_MAX (__IFLA_GENEVE_MAX - 1)
572 573
574enum 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
573/* PPP section */ 582/* PPP section */
574enum { 583enum {
575 IFLA_PPP_UNSPEC, 584 IFLA_PPP_UNSPEC,