geneve: fix TOS inheriting for ipv4
authorMatthias May <matthias.may@westermo.com>
Fri, 5 Aug 2022 19:00:06 +0000 (21:00 +0200)
committerJakub Kicinski <kuba@kernel.org>
Wed, 10 Aug 2022 05:17:15 +0000 (22:17 -0700)
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>
drivers/net/geneve.c

index 018d365..fafe7de 100644 (file)
@@ -797,7 +797,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);
@@ -823,6 +824,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) {
@@ -911,6 +914,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;
@@ -921,7 +925,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);
 
@@ -965,7 +969,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
@@ -1149,7 +1153,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);