mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-04 02:06:43 +07:00
net: lwtunnel: handle MTU calculation in forwading
[ Upstream commit fade56410c22cacafb1be9f911a0afd3701d8366 ] Commit14972cbd34
("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:14972cbd34
("net: lwtunnel: Handle fragmentation") Suggested-by: David Ahern <dsahern@gmail.com> Signed-off-by: Vadim Fedorenko <vfedorenko@novek.ru> Reviewed-by: David Ahern <dsahern@kernel.org> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
parent
6939c39a41
commit
4476568069
@ -31,6 +31,7 @@
|
|||||||
#include <net/flow.h>
|
#include <net/flow.h>
|
||||||
#include <net/flow_dissector.h>
|
#include <net/flow_dissector.h>
|
||||||
#include <net/netns/hash.h>
|
#include <net/netns/hash.h>
|
||||||
|
#include <net/lwtunnel.h>
|
||||||
|
|
||||||
#define IPV4_MAX_PMTU 65535U /* RFC 2675, Section 5.1 */
|
#define IPV4_MAX_PMTU 65535U /* RFC 2675, Section 5.1 */
|
||||||
#define IPV4_MIN_MTU 68 /* RFC 791 */
|
#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,
|
|||||||
|
|
||||||
/* 'forwarding = true' case should always honour route mtu */
|
/* 'forwarding = true' case should always honour route mtu */
|
||||||
mtu = dst_metric_raw(dst, RTAX_MTU);
|
mtu = dst_metric_raw(dst, RTAX_MTU);
|
||||||
if (mtu)
|
if (!mtu)
|
||||||
return mtu;
|
mtu = min(READ_ONCE(dst->dev->mtu), IP_MAX_MTU);
|
||||||
|
|
||||||
return min(READ_ONCE(dst->dev->mtu), IP_MAX_MTU);
|
return mtu - lwtunnel_headroom(dst->lwtstate, mtu);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline unsigned int ip_skb_dst_mtu(struct sock *sk,
|
static inline unsigned int ip_skb_dst_mtu(struct sock *sk,
|
||||||
const struct sk_buff *skb)
|
const struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
|
unsigned int mtu;
|
||||||
|
|
||||||
if (!sk || !sk_fullsock(sk) || ip_sk_use_pmtu(sk)) {
|
if (!sk || !sk_fullsock(sk) || ip_sk_use_pmtu(sk)) {
|
||||||
bool forwarding = IPCB(skb)->flags & IPSKB_FORWARDED;
|
bool forwarding = IPCB(skb)->flags & IPSKB_FORWARDED;
|
||||||
|
|
||||||
return ip_dst_mtu_maybe_forward(skb_dst(skb), forwarding);
|
return ip_dst_mtu_maybe_forward(skb_dst(skb), forwarding);
|
||||||
}
|
}
|
||||||
|
|
||||||
return min(READ_ONCE(skb_dst(skb)->dev->mtu), IP_MAX_MTU);
|
mtu = min(READ_ONCE(skb_dst(skb)->dev->mtu), IP_MAX_MTU);
|
||||||
|
return mtu - lwtunnel_headroom(skb_dst(skb)->lwtstate, mtu);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct dst_metrics *ip_fib_metrics_init(struct net *net, struct nlattr *fc_mx,
|
struct dst_metrics *ip_fib_metrics_init(struct net *net, struct nlattr *fc_mx,
|
||||||
|
@ -264,11 +264,18 @@ int ip6_fragment(struct net *net, struct sock *sk, struct sk_buff *skb,
|
|||||||
|
|
||||||
static inline int ip6_skb_dst_mtu(struct sk_buff *skb)
|
static inline int ip6_skb_dst_mtu(struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
|
int mtu;
|
||||||
|
|
||||||
struct ipv6_pinfo *np = skb->sk && !dev_recursion_level() ?
|
struct ipv6_pinfo *np = skb->sk && !dev_recursion_level() ?
|
||||||
inet6_sk(skb->sk) : NULL;
|
inet6_sk(skb->sk) : NULL;
|
||||||
|
|
||||||
return (np && np->pmtudisc >= IPV6_PMTUDISC_PROBE) ?
|
if (np && np->pmtudisc >= IPV6_PMTUDISC_PROBE) {
|
||||||
skb_dst(skb)->dev->mtu : dst_mtu(skb_dst(skb));
|
mtu = READ_ONCE(skb_dst(skb)->dev->mtu);
|
||||||
|
mtu -= lwtunnel_headroom(skb_dst(skb)->lwtstate, mtu);
|
||||||
|
} else
|
||||||
|
mtu = dst_mtu(skb_dst(skb));
|
||||||
|
|
||||||
|
return mtu;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool ip6_sk_accept_pmtu(const struct sock *sk)
|
static inline bool ip6_sk_accept_pmtu(const struct sock *sk)
|
||||||
@ -316,7 +323,7 @@ static inline unsigned int ip6_dst_mtu_forward(const struct dst_entry *dst)
|
|||||||
if (dst_metric_locked(dst, RTAX_MTU)) {
|
if (dst_metric_locked(dst, RTAX_MTU)) {
|
||||||
mtu = dst_metric_raw(dst, RTAX_MTU);
|
mtu = dst_metric_raw(dst, RTAX_MTU);
|
||||||
if (mtu)
|
if (mtu)
|
||||||
return mtu;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
mtu = IPV6_MIN_MTU;
|
mtu = IPV6_MIN_MTU;
|
||||||
@ -326,7 +333,8 @@ static inline unsigned int ip6_dst_mtu_forward(const struct dst_entry *dst)
|
|||||||
mtu = idev->cnf.mtu6;
|
mtu = idev->cnf.mtu6;
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
|
|
||||||
return mtu;
|
out:
|
||||||
|
return mtu - lwtunnel_headroom(dst->lwtstate, mtu);
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 ip6_mtu_from_fib6(const struct fib6_result *res,
|
u32 ip6_mtu_from_fib6(const struct fib6_result *res,
|
||||||
|
@ -1327,7 +1327,7 @@ static unsigned int ipv4_mtu(const struct dst_entry *dst)
|
|||||||
mtu = dst_metric_raw(dst, RTAX_MTU);
|
mtu = dst_metric_raw(dst, RTAX_MTU);
|
||||||
|
|
||||||
if (mtu)
|
if (mtu)
|
||||||
return mtu;
|
goto out;
|
||||||
|
|
||||||
mtu = READ_ONCE(dst->dev->mtu);
|
mtu = READ_ONCE(dst->dev->mtu);
|
||||||
|
|
||||||
@ -1336,6 +1336,7 @@ static unsigned int ipv4_mtu(const struct dst_entry *dst)
|
|||||||
mtu = 576;
|
mtu = 576;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
mtu = min_t(unsigned int, mtu, IP_MAX_MTU);
|
mtu = min_t(unsigned int, mtu, IP_MAX_MTU);
|
||||||
|
|
||||||
return mtu - lwtunnel_headroom(dst->lwtstate, mtu);
|
return mtu - lwtunnel_headroom(dst->lwtstate, mtu);
|
||||||
|
Loading…
Reference in New Issue
Block a user