| @@ -2278,13 +2278,24 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, · 2277 unmodified lines |
| 2278 | 2278 | goto tx_error; |
| 2279 | 2279 | } |
| 2280 | 2280 | |
| 2281 | | − /* Bypass encapsulation if the destination is local */ |
| 2282 | 2281 | if (!info) { |
| 2282 | + /* Bypass encapsulation if the destination is local */ |
| 2283 | 2283 | err = encap_bypass_if_local(skb, dev, vxlan, dst, |
| 2284 | 2284 | dst_port, ifindex, vni, |
| 2285 | 2285 | &rt->dst, rt->rt_flags); |
| 2286 | 2286 | if (err) |
| 2287 | 2287 | 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 | + } |
| 2288 | 2299 | } else if (info->key.tun_flags & TUNNEL_DONT_FRAGMENT) { |
| 2289 | 2300 | df = htons(IP_DF); |
| 2290 | 2301 | } |
| @@ -2837,6 +2848,7 @@ static const struct nla_policy vxlan_policy[IFLA_VXLAN_MAX + 1] = { · 546 unmodified lines |
| 2837 | 2848 | [IFLA_VXLAN_GPE] = { .type = NLA_FLAG, }, |
| 2838 | 2849 | [IFLA_VXLAN_REMCSUM_NOPARTIAL] = { .type = NLA_FLAG }, |
| 2839 | 2850 | [IFLA_VXLAN_TTL_INHERIT] = { .type = NLA_FLAG }, |
| 2851 | + [IFLA_VXLAN_DF] = { .type = NLA_U8 }, |
| 2840 | 2852 | }; |
| 2841 | 2853 | |
| 2842 | 2854 | 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 |
| 2893 | 2905 | } |
| 2894 | 2906 | } |
| 2895 | 2907 | |
| 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 | + |
| 2896 | 2918 | return 0; |
| 2897 | 2919 | } |
| 2898 | 2920 | |
| @@ -3538,6 +3560,9 @@ static int vxlan_nl2conf(struct nlattr *tb[], struct nlattr *data[], · 639 unmodified lines |
| 3538 | 3560 | conf->mtu = nla_get_u32(tb[IFLA_MTU]); |
| 3539 | 3561 | } |
| 3540 | 3562 | |
| 3563 | + if (data[IFLA_VXLAN_DF]) |
| 3564 | + conf->df = nla_get_u8(data[IFLA_VXLAN_DF]); |
| 3565 | + |
| 3541 | 3566 | return 0; |
| 3542 | 3567 | } |
| 3543 | 3568 | |
| @@ -3630,6 +3655,7 @@ static size_t vxlan_get_size(const struct net_device *dev) · 86 unmodified lines |
| 3630 | 3655 | nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_TTL */ |
| 3631 | 3656 | nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_TTL_INHERIT */ |
| 3632 | 3657 | nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_TOS */ |
| 3658 | + nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_DF */ |
| 3633 | 3659 | nla_total_size(sizeof(__be32)) + /* IFLA_VXLAN_LABEL */ |
| 3634 | 3660 | nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_LEARNING */ |
| 3635 | 3661 | 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 |
| 3696 | 3722 | nla_put_u8(skb, IFLA_VXLAN_TTL_INHERIT, |
| 3697 | 3723 | !!(vxlan->cfg.flags & VXLAN_F_TTL_INHERIT)) || |
| 3698 | 3724 | nla_put_u8(skb, IFLA_VXLAN_TOS, vxlan->cfg.tos) || |
| 3725 | + nla_put_u8(skb, IFLA_VXLAN_DF, vxlan->cfg.df) || |
| 3699 | 3726 | nla_put_be32(skb, IFLA_VXLAN_LABEL, vxlan->cfg.label) || |
| 3700 | 3727 | nla_put_u8(skb, IFLA_VXLAN_LEARNING, |
| 3701 | 3728 | !!(vxlan->cfg.flags & VXLAN_F_LEARN)) || |