Skip to content

Commit fade564

Browse files
vvfedorenkodavem330
authored andcommitted
net: lwtunnel: handle MTU calculation in forwading
Commit 14972cb ("net: lwtunnel: Handle fragmentation") moved fragmentation logic away from lwtunnel by carry encap headroom and use it in output MTU calculation. But the forwarding part was not covered and created difference in MTU for output and forwarding and further to silent drops on ipv4 forwarding path. Fix it by taking into account lwtunnel encap headroom. The same commit also introduced difference in how to treat RTAX_MTU in IPv4 and IPv6 where latter explicitly removes lwtunnel encap headroom from route MTU. Make IPv4 version do the same. Fixes: 14972cb ("net: lwtunnel: Handle fragmentation") Suggested-by: David Ahern <[email protected]> Signed-off-by: Vadim Fedorenko <[email protected]> Reviewed-by: David Ahern <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent d676598 commit fade564

File tree

3 files changed

+22
-9
lines changed

3 files changed

+22
-9
lines changed

include/net/ip.h

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include <net/flow.h>
3232
#include <net/flow_dissector.h>
3333
#include <net/netns/hash.h>
34+
#include <net/lwtunnel.h>
3435

3536
#define IPV4_MAX_PMTU 65535U /* RFC 2675, Section 5.1 */
3637
#define IPV4_MIN_MTU 68 /* RFC 791 */
@@ -445,22 +446,25 @@ static inline unsigned int ip_dst_mtu_maybe_forward(const struct dst_entry *dst,
445446

446447
/* 'forwarding = true' case should always honour route mtu */
447448
mtu = dst_metric_raw(dst, RTAX_MTU);
448-
if (mtu)
449-
return mtu;
449+
if (!mtu)
450+
mtu = min(READ_ONCE(dst->dev->mtu), IP_MAX_MTU);
450451

451-
return min(READ_ONCE(dst->dev->mtu), IP_MAX_MTU);
452+
return mtu - lwtunnel_headroom(dst->lwtstate, mtu);
452453
}
453454

454455
static inline unsigned int ip_skb_dst_mtu(struct sock *sk,
455456
const struct sk_buff *skb)
456457
{
458+
unsigned int mtu;
459+
457460
if (!sk || !sk_fullsock(sk) || ip_sk_use_pmtu(sk)) {
458461
bool forwarding = IPCB(skb)->flags & IPSKB_FORWARDED;
459462

460463
return ip_dst_mtu_maybe_forward(skb_dst(skb), forwarding);
461464
}
462465

463-
return min(READ_ONCE(skb_dst(skb)->dev->mtu), IP_MAX_MTU);
466+
mtu = min(READ_ONCE(skb_dst(skb)->dev->mtu), IP_MAX_MTU);
467+
return mtu - lwtunnel_headroom(skb_dst(skb)->lwtstate, mtu);
464468
}
465469

466470
struct dst_metrics *ip_fib_metrics_init(struct net *net, struct nlattr *fc_mx,

include/net/ip6_route.h

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -265,11 +265,18 @@ int ip6_fragment(struct net *net, struct sock *sk, struct sk_buff *skb,
265265

266266
static inline int ip6_skb_dst_mtu(struct sk_buff *skb)
267267
{
268+
int mtu;
269+
268270
struct ipv6_pinfo *np = skb->sk && !dev_recursion_level() ?
269271
inet6_sk(skb->sk) : NULL;
270272

271-
return (np && np->pmtudisc >= IPV6_PMTUDISC_PROBE) ?
272-
skb_dst(skb)->dev->mtu : dst_mtu(skb_dst(skb));
273+
if (np && np->pmtudisc >= IPV6_PMTUDISC_PROBE) {
274+
mtu = READ_ONCE(skb_dst(skb)->dev->mtu);
275+
mtu -= lwtunnel_headroom(skb_dst(skb)->lwtstate, mtu);
276+
} else
277+
mtu = dst_mtu(skb_dst(skb));
278+
279+
return mtu;
273280
}
274281

275282
static inline bool ip6_sk_accept_pmtu(const struct sock *sk)
@@ -317,7 +324,7 @@ static inline unsigned int ip6_dst_mtu_forward(const struct dst_entry *dst)
317324
if (dst_metric_locked(dst, RTAX_MTU)) {
318325
mtu = dst_metric_raw(dst, RTAX_MTU);
319326
if (mtu)
320-
return mtu;
327+
goto out;
321328
}
322329

323330
mtu = IPV6_MIN_MTU;
@@ -327,7 +334,8 @@ static inline unsigned int ip6_dst_mtu_forward(const struct dst_entry *dst)
327334
mtu = idev->cnf.mtu6;
328335
rcu_read_unlock();
329336

330-
return mtu;
337+
out:
338+
return mtu - lwtunnel_headroom(dst->lwtstate, mtu);
331339
}
332340

333341
u32 ip6_mtu_from_fib6(const struct fib6_result *res,

net/ipv4/route.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1306,7 +1306,7 @@ INDIRECT_CALLABLE_SCOPE unsigned int ipv4_mtu(const struct dst_entry *dst)
13061306
mtu = dst_metric_raw(dst, RTAX_MTU);
13071307

13081308
if (mtu)
1309-
return mtu;
1309+
goto out;
13101310

13111311
mtu = READ_ONCE(dst->dev->mtu);
13121312

@@ -1315,6 +1315,7 @@ INDIRECT_CALLABLE_SCOPE unsigned int ipv4_mtu(const struct dst_entry *dst)
13151315
mtu = 576;
13161316
}
13171317

1318+
out:
13181319
mtu = min_t(unsigned int, mtu, IP_MAX_MTU);
13191320

13201321
return mtu - lwtunnel_headroom(dst->lwtstate, mtu);

0 commit comments

Comments
 (0)