From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.0 required=3.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_PASS,URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 54679C4360F for ; Sun, 17 Mar 2019 23:48:20 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 3148320854 for ; Sun, 17 Mar 2019 23:48:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727576AbfCQXpT (ORCPT ); Sun, 17 Mar 2019 19:45:19 -0400 Received: from 87-237-14-1.powered-by.benesol.be ([87.237.14.1]:40849 "EHLO wizbit.localdomain" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1727171AbfCQXpS (ORCPT ); Sun, 17 Mar 2019 19:45:18 -0400 Received: from mx.wizbit.be (localhost [127.0.0.1]) by wizbit.localdomain (Postfix) with ESMTP id 45EC96004; Mon, 18 Mar 2019 00:37:57 +0100 (CET) From: Bram Yvahk To: steffen.klassert@secunet.com, herbert@gondor.apana.org.au, davem@davemloft.net Cc: netdev@vger.kernel.org Subject: [PATCH ipsec/vti 1/2] vti: fragment IPv4 packets when DF bit is not set Date: Sun, 17 Mar 2019 23:37:56 +0000 Message-Id: <1552865877-13401-2-git-send-email-bram-yvahk@mail.wizbit.be> X-Mailer: git-send-email 1.8.4 In-Reply-To: <1552865877-13401-1-git-send-email-bram-yvahk@mail.wizbit.be> References: <1552865877-13401-1-git-send-email-bram-yvahk@mail.wizbit.be> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Only send a 'need to frag' ICMP message when the "Don't Fragment" bit is set. If it's not set then the packet can/will be fragmented. This fixes sending an 'need to frag' message on a client that did not set the DF bit, i.e.: $ ping -s 1300 -M dont -c5 192.168.235.2 PING 192.168.235.3 (192.168.235.3) 1300(1328) bytes of data. From 192.168.236.254 icmp_seq=1 Frag needed and DF set (mtu = 1214) Signed-off-by: Bram Yvahk --- net/ipv4/ip_vti.c | 43 +++++++++++++++++++++++++++-------------- net/ipv6/ip6_vti.c | 56 +++++++++++++++++++++++++++++++++++++++--------------- 2 files changed, 70 insertions(+), 29 deletions(-) diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c index 68a21bf..5738e44 100644 --- a/net/ipv4/ip_vti.c +++ b/net/ipv4/ip_vti.c @@ -196,6 +196,34 @@ static bool vti_state_check(const struct xfrm_state *x, __be32 dst, __be32 src) return true; } +static bool vti_tunnel_check_size(struct sk_buff *skb) +{ + int mtu; + + if (skb->protocol == htons(ETH_P_IP)) { + if (!(ip_hdr(skb)->frag_off & htons(IP_DF)) || skb->ignore_df) + return true; + } + + mtu = dst_mtu(skb_dst(skb)); + if (skb->len > mtu) { + skb_dst_update_pmtu(skb, mtu); + if (skb->protocol == htons(ETH_P_IP)) { + icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, + htonl(mtu)); + } else { + if (mtu < IPV6_MIN_MTU) + mtu = IPV6_MIN_MTU; + + icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); + } + + return false; + } + + return true; +} + static netdev_tx_t vti_xmit(struct sk_buff *skb, struct net_device *dev, struct flowi *fl) { @@ -205,7 +233,6 @@ static netdev_tx_t vti_xmit(struct sk_buff *skb, struct net_device *dev, struct net_device *tdev; /* Device to other host */ int pkt_len = skb->len; int err; - int mtu; if (!dst) { dev->stats.tx_carrier_errors++; @@ -233,19 +260,7 @@ static netdev_tx_t vti_xmit(struct sk_buff *skb, struct net_device *dev, goto tx_error; } - mtu = dst_mtu(dst); - if (skb->len > mtu) { - skb_dst_update_pmtu(skb, mtu); - if (skb->protocol == htons(ETH_P_IP)) { - icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, - htonl(mtu)); - } else { - if (mtu < IPV6_MIN_MTU) - mtu = IPV6_MIN_MTU; - - icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); - } - + if (!vti_tunnel_check_size(skb)) { dst_release(dst); goto tx_error; } diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c index 8b6eeff..47f178c 100644 --- a/net/ipv6/ip6_vti.c +++ b/net/ipv6/ip6_vti.c @@ -436,6 +436,46 @@ static bool vti6_state_check(const struct xfrm_state *x, } /** + * vti6_tunnel_check_size - check size of packet + * @skb: the outgoing socket buffer + * + * Description: + * Check if packet is too large (> pmtu) + * + * Return: + * true if size of packet is ok + * false if packet is too large + **/ +static bool vti6_tunnel_check_size(struct sk_buff *skb) +{ + int mtu; + + if (skb->protocol == htons(ETH_P_IP)) { + if (!(ip_hdr(skb)->frag_off & htons(IP_DF)) || skb->ignore_df) + return true; + } + + mtu = dst_mtu(skb_dst(skb)); + if (skb->len > mtu) { + skb_dst_update_pmtu(skb, mtu); + + if (skb->protocol == htons(ETH_P_IPV6)) { + if (mtu < IPV6_MIN_MTU) + mtu = IPV6_MIN_MTU; + + icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); + } else { + icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, + htonl(mtu)); + } + + return false; + } + + return true; +} + +/** * vti6_xmit - send a packet * @skb: the outgoing socket buffer * @dev: the outgoing tunnel device @@ -451,7 +491,6 @@ vti6_xmit(struct sk_buff *skb, struct net_device *dev, struct flowi *fl) struct xfrm_state *x; int pkt_len = skb->len; int err = -1; - int mtu; if (!dst) goto tx_err_link_failure; @@ -481,20 +520,7 @@ vti6_xmit(struct sk_buff *skb, struct net_device *dev, struct flowi *fl) goto tx_err_dst_release; } - mtu = dst_mtu(dst); - if (skb->len > mtu) { - skb_dst_update_pmtu(skb, mtu); - - if (skb->protocol == htons(ETH_P_IPV6)) { - if (mtu < IPV6_MIN_MTU) - mtu = IPV6_MIN_MTU; - - icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); - } else { - icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, - htonl(mtu)); - } - + if (!vti6_tunnel_check_size(skb)) { err = -EMSGSIZE; goto tx_err_dst_release; } -- 2.7.0