History

vxlan: Allow configuration of DF behaviour

Allow users to set the IPv4 DF bit in outgoing packets, or to inherit its value from the IPv4 inner header. If the encapsulated protocol is IPv6 and DF is configured to be inherited, always set it. For IPv4, inheriting DF from the inner header was probably intended from the very beginning judging by the comment to vxlan_xmit(), but it wasn't actually implemented -- also because it would have done more harm than good, without handling for ICMP Fragmentation Needed messages. According to RFC 7348, "Path MTU discovery MAY be used". An expired RFC draft, draft-saum-nvo3-pmtud-over-vxlan-05, whose purpose was to describe PMTUD implementation, says that "is a MUST that Vxlan gateways [...] SHOULD set the DF-bit [...]", whatever that means. Given this background, the only sane option is probably to let the user decide, and keep the current behaviour as default. 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, move DF setting to if (!info) block in vxlan_xmit_one() (Stephen Hemminger)

Stefano Brivio committed 8 years ago

Commit b4d30691 parent c3a43b93 files · +38 −1Browse files

Unified · Split

3 files
  1. drivers/net/vxlan.c +28 −1
  2. include/net/vxlan.h +1 −0
  3. include/uapi/linux/if_link.h +9 −0
drivers/net/vxlan.c+28−1
@@ -2278,13 +2278,24 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, · 2277 unmodified lines
22782278 goto tx_error;
22792279 }
22802280
2281− /* Bypass encapsulation if the destination is local */
22822281 if (!info) {
2282+ /* Bypass encapsulation if the destination is local */
22832283 err = encap_bypass_if_local(skb, dev, vxlan, dst,
22842284 dst_port, ifindex, vni,
22852285 &rt->dst, rt->rt_flags);
22862286 if (err)
22872287 goto out_unlock;
2288+
2289+ if (vxlan->cfg.df == VXLAN_DF_SET) {
2290+ df = htons(IP_DF);
2291+ } else if (vxlan->cfg.df == VXLAN_DF_INHERIT) {
2292+ struct ethhdr *eth = eth_hdr(skb);
2293+
2294+ if (ntohs(eth->h_proto) == ETH_P_IPV6 ||
2295+ (ntohs(eth->h_proto) == ETH_P_IP &&
2296+ old_iph->frag_off & htons(IP_DF)))
2297+ df = htons(IP_DF);
2298+ }
22882299 } else if (info->key.tun_flags & TUNNEL_DONT_FRAGMENT) {
22892300 df = htons(IP_DF);
22902301 }
@@ -2837,6 +2848,7 @@ static const struct nla_policy vxlan_policy[IFLA_VXLAN_MAX + 1] = { · 546 unmodified lines
28372848 [IFLA_VXLAN_GPE] = { .type = NLA_FLAG, },
28382849 [IFLA_VXLAN_REMCSUM_NOPARTIAL] = { .type = NLA_FLAG },
28392850 [IFLA_VXLAN_TTL_INHERIT] = { .type = NLA_FLAG },
2851+ [IFLA_VXLAN_DF] = { .type = NLA_U8 },
28402852 };
28412853
28422854 static int vxlan_validate(struct nlattr *tb[], struct nlattr *data[],
@@ -2893,6 +2905,16 @@ static int vxlan_validate(struct nlattr *tb[], struct nlattr *data[], · 50 unmodified lines
28932905 }
28942906 }
28952907
2908+ if (data[IFLA_VXLAN_DF]) {
2909+ enum ifla_vxlan_df df = nla_get_u8(data[IFLA_VXLAN_DF]);
2910+
2911+ if (df < 0 || df > VXLAN_DF_MAX) {
2912+ NL_SET_ERR_MSG_ATTR(extack, tb[IFLA_VXLAN_DF],
2913+ "Invalid DF attribute");
2914+ return -EINVAL;
2915+ }
2916+ }
2917+
28962918 return 0;
28972919 }
28982920
@@ -3538,6 +3560,9 @@ static int vxlan_nl2conf(struct nlattr *tb[], struct nlattr *data[], · 639 unmodified lines
35383560 conf->mtu = nla_get_u32(tb[IFLA_MTU]);
35393561 }
35403562
3563+ if (data[IFLA_VXLAN_DF])
3564+ conf->df = nla_get_u8(data[IFLA_VXLAN_DF]);
3565+
35413566 return 0;
35423567 }
35433568
@@ -3630,6 +3655,7 @@ static size_t vxlan_get_size(const struct net_device *dev) · 86 unmodified lines
36303655 nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_TTL */
36313656 nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_TTL_INHERIT */
36323657 nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_TOS */
3658+ nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_DF */
36333659 nla_total_size(sizeof(__be32)) + /* IFLA_VXLAN_LABEL */
36343660 nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_LEARNING */
36353661 nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_PROXY */
@@ -3696,6 +3722,7 @@ static int vxlan_fill_info(struct sk_buff *skb, const struct net_device *dev) · 60 unmodified lines
36963722 nla_put_u8(skb, IFLA_VXLAN_TTL_INHERIT,
36973723 !!(vxlan->cfg.flags & VXLAN_F_TTL_INHERIT)) ||
36983724 nla_put_u8(skb, IFLA_VXLAN_TOS, vxlan->cfg.tos) ||
3725+ nla_put_u8(skb, IFLA_VXLAN_DF, vxlan->cfg.df) ||
36993726 nla_put_be32(skb, IFLA_VXLAN_LABEL, vxlan->cfg.label) ||
37003727 nla_put_u8(skb, IFLA_VXLAN_LEARNING,
37013728 !!(vxlan->cfg.flags & VXLAN_F_LEARN)) ||
include/net/vxlan.h+1−0
@@ -216,6 +216,7 @@ struct vxlan_config { · 215 unmodified lines
216216 unsigned long age_interval;
217217 unsigned int addrmax;
218218 bool no_share;
219+ enum ifla_vxlan_df df;
219220 };
220221
221222 struct vxlan_dev_node {
include/uapi/linux/if_link.h+9−0
@@ -533,6 +533,7 @@ enum { · 532 unmodified lines
533533 IFLA_VXLAN_LABEL,
534534 IFLA_VXLAN_GPE,
535535 IFLA_VXLAN_TTL_INHERIT,
536+ IFLA_VXLAN_DF,
536537 __IFLA_VXLAN_MAX
537538 };
538539 #define IFLA_VXLAN_MAX (__IFLA_VXLAN_MAX - 1)
@@ -542,6 +543,14 @@ struct ifla_vxlan_port_range { · 3 unmodified lines
542543 __be16 high;
543544 };
544545
546+enum ifla_vxlan_df {
547+ VXLAN_DF_UNSET = 0,
548+ VXLAN_DF_SET,
549+ VXLAN_DF_INHERIT,
550+ __VXLAN_DF_END,
551+ VXLAN_DF_MAX = __VXLAN_DF_END - 1,
552+};
553+
545554 /* GENEVE section */
546555 enum {
547556 IFLA_GENEVE_UNSPEC,

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t