[Openvpn-devel,ovpn-net-next] ovpn: set skb->ignore_df = 1 before sending IPv6 packets out

Message ID 20250506210853.10585-1-a@unstable.cc
State New
Headers show
Series [Openvpn-devel,ovpn-net-next] ovpn: set skb->ignore_df = 1 before sending IPv6 packets out | expand

Commit Message

Antonio Quartulli May 6, 2025, 9:08 p.m. UTC
From: Antonio Quartulli <antonio@openvpn.net>

IPv6 user packets (sent over the tunnel) may be larger than
the outgoing interface MTU after encapsulation.
When this happens ovpn should allow the kernel to fragment
them because they are "locally generated".

To achieve the above, we must set skb->ignore_df = 1
so that ip6_fragment() can be made aware of this decision.

Failing to do so will result in ip6_fragment() dropping
the packet thinking it was "routed".

Reported-by: Gert Doering <gert@greenie.muc.de>
Signed-off-by: Antonio Quartulli <antonio@openvpn.net>
---
 drivers/net/ovpn/udp.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

Comments

Gert Doering May 7, 2025, 6:44 a.m. UTC | #1
Hi,

On Tue, May 06, 2025 at 11:08:53PM +0200, Antonio Quartulli wrote:
> From: Antonio Quartulli <antonio@openvpn.net>
> 
> IPv6 user packets (sent over the tunnel) may be larger than
> the outgoing interface MTU after encapsulation.
> When this happens ovpn should allow the kernel to fragment
> them because they are "locally generated".
> 
> To achieve the above, we must set skb->ignore_df = 1
> so that ip6_fragment() can be made aware of this decision.
> 
> Failing to do so will result in ip6_fragment() dropping
> the packet thinking it was "routed".
> 
> Reported-by: Gert Doering <gert@greenie.muc.de>
> Signed-off-by: Antonio Quartulli <antonio@openvpn.net>

Not sure what the protocol is on this - but I can confirm that this
fixes the problems I've observed (t_client, IPv6 UDP transport,
tun mtu 1500, ping with 3000 byte packets = inside *and* outside
fragmentation needed).

Details are in https://github.com/OpenVPN/ovpn-net-next/issues/3.

so:

Tested-By: Gert Doering <gert@greenie.muc.de>
Acked-By: Gert Doering <gert@greenie.muc.de>

gert
Gert Doering May 7, 2025, 6:45 a.m. UTC | #2
Hi,

On Tue, May 06, 2025 at 11:08:53PM +0200, Antonio Quartulli wrote:
> From: Antonio Quartulli <antonio@openvpn.net>
> 
> IPv6 user packets (sent over the tunnel) may be larger than
> the outgoing interface MTU after encapsulation.
> When this happens ovpn should allow the kernel to fragment
> them because they are "locally generated".
> 
> To achieve the above, we must set skb->ignore_df = 1
> so that ip6_fragment() can be made aware of this decision.
> 
> Failing to do so will result in ip6_fragment() dropping
> the packet thinking it was "routed".
> 
> Reported-by: Gert Doering <gert@greenie.muc.de>
> Signed-off-by: Antonio Quartulli <antonio@openvpn.net>

Not sure what the protocol is on this - but I can confirm that this
fixes the problems I've observed (t_client, IPv6 UDP transport,
tun mtu 1500, ping with 3000 byte packets = inside *and* outside
fragmentation needed).

Details are in https://github.com/OpenVPN/ovpn-net-next/issues/3.

so:

Tested-By: Gert Doering <gert@greenie.muc.de>
Acked-By: Gert Doering <gert@greenie.muc.de>

gert
Antonio Quartulli May 7, 2025, 6:49 a.m. UTC | #3
Hi,

On 07/05/2025 08:45, Gert Doering wrote:
> so:
> 
> Tested-By: Gert Doering <gert@greenie.muc.de>
> Acked-By: Gert Doering <gert@greenie.muc.de>

Sending your tags this way is definitely the way to go.
I'll add them when pushing the patch to my tree.

Thanks!
Antonio Quartulli May 7, 2025, 7:38 p.m. UTC | #4
On 07/05/2025 08:49, Antonio Quartulli wrote:
> Hi,
> 
> On 07/05/2025 08:45, Gert Doering wrote:
>> so:
>>
>> Tested-By: Gert Doering <gert@greenie.muc.de>
>> Acked-By: Gert Doering <gert@greenie.muc.de>
> 
> Sending your tags this way is definitely the way to go.
> I'll add them when pushing the patch to my tree.

Merged to main branch, commit id e2fb21d856f8

Thanks!

Patch

diff --git a/drivers/net/ovpn/udp.c b/drivers/net/ovpn/udp.c
index c9e189056f33..aef8c0406ec9 100644
--- a/drivers/net/ovpn/udp.c
+++ b/drivers/net/ovpn/udp.c
@@ -262,6 +262,16 @@  static int ovpn_udp6_output(struct ovpn_peer *peer, struct ovpn_bind *bind,
 	dst_cache_set_ip6(cache, dst, &fl.saddr);
 
 transmit:
+	/* user IPv6 packets may be larger than the transport interface
+	 * MTU (after encapsulation), however, since they are locally
+	 * generated we should ensure they get fragmented.
+	 * Setting the ignore_df flag to 1 will instruct ip6_fragment() to
+	 * fragment packets if needed.
+	 *
+	 * NOTE: this is not needed for IPv4 because we pass df=0 to
+	 * udp_tunnel_xmit_skb()
+	 */
+	skb->ignore_df = 1;
 	udp_tunnel6_xmit_skb(dst, sk, skb, skb->dev, &fl.saddr, &fl.daddr, 0,
 			     ip6_dst_hoplimit(dst), 0, fl.fl6_sport,
 			     fl.fl6_dport, udp_get_no_check6_tx(sk));