From: Matthias May matthias.may@westermo.com
stable inclusion from stable-v5.10.138 commit 2c746ec91de76e095e4f18367dbb5103a6ed09e1 category: bugfix bugzilla: 188217
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=...
-------------------------------------------------
commit b4ab94d6adaa5cf842b68bd28f4b50bc774496bd upstream.
The current code retrieves the TOS field after the lookup on the ipv4 routing table. The routing process currently only allows routing based on the original 3 TOS bits, and not on the full 6 DSCP bits. As a result the retrieved TOS is cut to the 3 bits. However for inheriting purposes the full 6 bits should be used.
Extract the full 6 bits before the route lookup and use that instead of the cut off 3 TOS bits.
Fixes: e305ac6cf5a1 ("geneve: Add support to collect tunnel metadata.") Signed-off-by: Matthias May matthias.may@westermo.com Acked-by: Guillaume Nault gnault@redhat.com Link: https://lore.kernel.org/r/20220805190006.8078-1-matthias.may@westermo.com Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org (cherry picked from commit 2c746ec91de76e095e4f18367dbb5103a6ed09e1) Signed-off-by: Wang Yufen wangyufen@huawei.com --- drivers/net/geneve.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c index ba9947d..081939c 100644 --- a/drivers/net/geneve.c +++ b/drivers/net/geneve.c @@ -772,7 +772,8 @@ static struct rtable *geneve_get_v4_rt(struct sk_buff *skb, struct geneve_sock *gs4, struct flowi4 *fl4, const struct ip_tunnel_info *info, - __be16 dport, __be16 sport) + __be16 dport, __be16 sport, + __u8 *full_tos) { bool use_cache = ip_tunnel_dst_cache_usable(skb, info); struct geneve_dev *geneve = netdev_priv(dev); @@ -797,6 +798,8 @@ static struct rtable *geneve_get_v4_rt(struct sk_buff *skb, use_cache = false; } fl4->flowi4_tos = RT_TOS(tos); + if (full_tos) + *full_tos = tos;
dst_cache = (struct dst_cache *)&info->dst_cache; if (use_cache) { @@ -884,6 +887,7 @@ static int geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev, const struct ip_tunnel_key *key = &info->key; struct rtable *rt; struct flowi4 fl4; + __u8 full_tos; __u8 tos, ttl; __be16 df = 0; __be16 sport; @@ -894,7 +898,7 @@ static int geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev,
sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true); rt = geneve_get_v4_rt(skb, dev, gs4, &fl4, info, - geneve->cfg.info.key.tp_dst, sport); + geneve->cfg.info.key.tp_dst, sport, &full_tos); if (IS_ERR(rt)) return PTR_ERR(rt);
@@ -938,7 +942,7 @@ static int geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev,
df = key->tun_flags & TUNNEL_DONT_FRAGMENT ? htons(IP_DF) : 0; } else { - tos = ip_tunnel_ecn_encap(fl4.flowi4_tos, ip_hdr(skb), skb); + tos = ip_tunnel_ecn_encap(full_tos, ip_hdr(skb), skb); if (geneve->cfg.ttl_inherit) ttl = ip_tunnel_get_ttl(ip_hdr(skb), skb); else @@ -1120,7 +1124,7 @@ static int geneve_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb) 1, USHRT_MAX, true);
rt = geneve_get_v4_rt(skb, dev, gs4, &fl4, info, - geneve->cfg.info.key.tp_dst, sport); + geneve->cfg.info.key.tp_dst, sport, NULL); if (IS_ERR(rt)) return PTR_ERR(rt);