ipv4: Use dscp_t in struct fib_alias
authorGuillaume Nault <gnault@redhat.com>
Fri, 4 Feb 2022 13:58:19 +0000 (14:58 +0100)
committerJakub Kicinski <kuba@kernel.org>
Tue, 8 Feb 2022 04:12:46 +0000 (20:12 -0800)
Use the new dscp_t type to replace the fa_tos field of fib_alias. This
ensures ECN bits are ignored and makes the field compatible with the
fc_dscp field of struct fib_config.

Converting old *tos variables and fields to dscp_t allows sparse to
flag incorrect uses of DSCP and ECN bits. This patch is entirely about
type annotation and shouldn't change any existing behaviour.

Signed-off-by: Guillaume Nault <gnault@redhat.com>
Acked-by: David Ahern <dsahern@kernel.org>
Reviewed-by: Toke Høiland-Jørgensen <toke@redhat.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
net/ipv4/fib_lookup.h
net/ipv4/fib_semantics.c
net/ipv4/fib_trie.c
net/ipv4/route.c

index e184bcb..a63014b 100644 (file)
@@ -4,13 +4,14 @@
 
 #include <linux/types.h>
 #include <linux/list.h>
+#include <net/inet_dscp.h>
 #include <net/ip_fib.h>
 #include <net/nexthop.h>
 
 struct fib_alias {
        struct hlist_node       fa_list;
        struct fib_info         *fa_info;
-       u8                      fa_tos;
+       dscp_t                  fa_dscp;
        u8                      fa_type;
        u8                      fa_state;
        u8                      fa_slen;
index 4c53994..c9c4f2f 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/hash.h>
 
 #include <net/arp.h>
+#include <net/inet_dscp.h>
 #include <net/ip.h>
 #include <net/protocol.h>
 #include <net/route.h>
@@ -523,7 +524,7 @@ void rtmsg_fib(int event, __be32 key, struct fib_alias *fa,
        fri.tb_id = tb_id;
        fri.dst = key;
        fri.dst_len = dst_len;
-       fri.tos = fa->fa_tos;
+       fri.tos = inet_dscp_to_dsfield(fa->fa_dscp);
        fri.type = fa->fa_type;
        fri.offload = fa->offload;
        fri.trap = fa->trap;
@@ -2039,7 +2040,7 @@ static void fib_select_default(const struct flowi4 *flp, struct fib_result *res)
        int order = -1, last_idx = -1;
        struct fib_alias *fa, *fa1 = NULL;
        u32 last_prio = res->fi->fib_priority;
-       u8 last_tos = 0;
+       dscp_t last_dscp = 0;
 
        hlist_for_each_entry_rcu(fa, fa_head, fa_list) {
                struct fib_info *next_fi = fa->fa_info;
@@ -2047,19 +2048,20 @@ static void fib_select_default(const struct flowi4 *flp, struct fib_result *res)
 
                if (fa->fa_slen != slen)
                        continue;
-               if (fa->fa_tos && fa->fa_tos != flp->flowi4_tos)
+               if (fa->fa_dscp &&
+                   fa->fa_dscp != inet_dsfield_to_dscp(flp->flowi4_tos))
                        continue;
                if (fa->tb_id != tb->tb_id)
                        continue;
                if (next_fi->fib_priority > last_prio &&
-                   fa->fa_tos == last_tos) {
-                       if (last_tos)
+                   fa->fa_dscp == last_dscp) {
+                       if (last_dscp)
                                continue;
                        break;
                }
                if (next_fi->fib_flags & RTNH_F_DEAD)
                        continue;
-               last_tos = fa->fa_tos;
+               last_dscp = fa->fa_dscp;
                last_prio = next_fi->fib_priority;
 
                if (next_fi->fib_scope != res->scope ||
index d937eee..c05cd10 100644 (file)
@@ -82,7 +82,7 @@ static int call_fib_entry_notifier(struct notifier_block *nb,
                .dst = dst,
                .dst_len = dst_len,
                .fi = fa->fa_info,
-               .tos = fa->fa_tos,
+               .tos = inet_dscp_to_dsfield(fa->fa_dscp),
                .type = fa->fa_type,
                .tb_id = fa->tb_id,
        };
@@ -99,7 +99,7 @@ static int call_fib_entry_notifiers(struct net *net,
                .dst = dst,
                .dst_len = dst_len,
                .fi = fa->fa_info,
-               .tos = fa->fa_tos,
+               .tos = inet_dscp_to_dsfield(fa->fa_dscp),
                .type = fa->fa_type,
                .tb_id = fa->tb_id,
        };
@@ -974,13 +974,13 @@ static struct key_vector *fib_find_node(struct trie *t,
        return n;
 }
 
-/* Return the first fib alias matching TOS with
+/* Return the first fib alias matching DSCP with
  * priority less than or equal to PRIO.
  * If 'find_first' is set, return the first matching
- * fib alias, regardless of TOS and priority.
+ * fib alias, regardless of DSCP and priority.
  */
 static struct fib_alias *fib_find_alias(struct hlist_head *fah, u8 slen,
-                                       u8 tos, u32 prio, u32 tb_id,
+                                       dscp_t dscp, u32 prio, u32 tb_id,
                                        bool find_first)
 {
        struct fib_alias *fa;
@@ -989,6 +989,10 @@ static struct fib_alias *fib_find_alias(struct hlist_head *fah, u8 slen,
                return NULL;
 
        hlist_for_each_entry(fa, fah, fa_list) {
+               /* Avoid Sparse warning when using dscp_t in inequalities */
+               u8 __fa_dscp = inet_dscp_to_dsfield(fa->fa_dscp);
+               u8 __dscp = inet_dscp_to_dsfield(dscp);
+
                if (fa->fa_slen < slen)
                        continue;
                if (fa->fa_slen != slen)
@@ -999,9 +1003,9 @@ static struct fib_alias *fib_find_alias(struct hlist_head *fah, u8 slen,
                        break;
                if (find_first)
                        return fa;
-               if (fa->fa_tos > tos)
+               if (__fa_dscp > __dscp)
                        continue;
-               if (fa->fa_info->fib_priority >= prio || fa->fa_tos < tos)
+               if (fa->fa_info->fib_priority >= prio || __fa_dscp < __dscp)
                        return fa;
        }
 
@@ -1028,8 +1032,8 @@ fib_find_matching_alias(struct net *net, const struct fib_rt_info *fri)
 
        hlist_for_each_entry_rcu(fa, &l->leaf, fa_list) {
                if (fa->fa_slen == slen && fa->tb_id == fri->tb_id &&
-                   fa->fa_tos == fri->tos && fa->fa_info == fri->fi &&
-                   fa->fa_type == fri->type)
+                   fa->fa_dscp == inet_dsfield_to_dscp(fri->tos) &&
+                   fa->fa_info == fri->fi && fa->fa_type == fri->type)
                        return fa;
        }
 
@@ -1211,9 +1215,9 @@ int fib_table_insert(struct net *net, struct fib_table *tb,
        struct fib_info *fi;
        u8 plen = cfg->fc_dst_len;
        u8 slen = KEYLENGTH - plen;
+       dscp_t dscp;
        u32 key;
        int err;
-       u8 tos;
 
        key = ntohl(cfg->fc_dst);
 
@@ -1228,13 +1232,13 @@ int fib_table_insert(struct net *net, struct fib_table *tb,
                goto err;
        }
 
-       tos = inet_dscp_to_dsfield(cfg->fc_dscp);
+       dscp = cfg->fc_dscp;
        l = fib_find_node(t, &tp, key);
-       fa = l ? fib_find_alias(&l->leaf, slen, tos, fi->fib_priority,
+       fa = l ? fib_find_alias(&l->leaf, slen, dscp, fi->fib_priority,
                                tb->tb_id, false) : NULL;
 
        /* Now fa, if non-NULL, points to the first fib alias
-        * with the same keys [prefix,tos,priority], if such key already
+        * with the same keys [prefix,dscp,priority], if such key already
         * exists or to the node before which we will insert new one.
         *
         * If fa is NULL, we will need to allocate a new one and
@@ -1242,7 +1246,7 @@ int fib_table_insert(struct net *net, struct fib_table *tb,
         * of the new alias.
         */
 
-       if (fa && fa->fa_tos == tos &&
+       if (fa && fa->fa_dscp == dscp &&
            fa->fa_info->fib_priority == fi->fib_priority) {
                struct fib_alias *fa_first, *fa_match;
 
@@ -1262,7 +1266,7 @@ int fib_table_insert(struct net *net, struct fib_table *tb,
                hlist_for_each_entry_from(fa, fa_list) {
                        if ((fa->fa_slen != slen) ||
                            (fa->tb_id != tb->tb_id) ||
-                           (fa->fa_tos != tos))
+                           (fa->fa_dscp != dscp))
                                break;
                        if (fa->fa_info->fib_priority != fi->fib_priority)
                                break;
@@ -1290,7 +1294,7 @@ int fib_table_insert(struct net *net, struct fib_table *tb,
                                goto out;
 
                        fi_drop = fa->fa_info;
-                       new_fa->fa_tos = fa->fa_tos;
+                       new_fa->fa_dscp = fa->fa_dscp;
                        new_fa->fa_info = fi;
                        new_fa->fa_type = cfg->fc_type;
                        state = fa->fa_state;
@@ -1353,7 +1357,7 @@ int fib_table_insert(struct net *net, struct fib_table *tb,
                goto out;
 
        new_fa->fa_info = fi;
-       new_fa->fa_tos = tos;
+       new_fa->fa_dscp = dscp;
        new_fa->fa_type = cfg->fc_type;
        new_fa->fa_state = 0;
        new_fa->fa_slen = slen;
@@ -1569,7 +1573,8 @@ found:
                        if (index >= (1ul << fa->fa_slen))
                                continue;
                }
-               if (fa->fa_tos && fa->fa_tos != flp->flowi4_tos)
+               if (fa->fa_dscp &&
+                   inet_dscp_to_dsfield(fa->fa_dscp) != flp->flowi4_tos)
                        continue;
                if (fi->fib_dead)
                        continue;
@@ -1705,8 +1710,8 @@ int fib_table_delete(struct net *net, struct fib_table *tb,
        struct key_vector *l, *tp;
        u8 plen = cfg->fc_dst_len;
        u8 slen = KEYLENGTH - plen;
+       dscp_t dscp;
        u32 key;
-       u8 tos;
 
        key = ntohl(cfg->fc_dst);
 
@@ -1717,12 +1722,13 @@ int fib_table_delete(struct net *net, struct fib_table *tb,
        if (!l)
                return -ESRCH;
 
-       tos = inet_dscp_to_dsfield(cfg->fc_dscp);
-       fa = fib_find_alias(&l->leaf, slen, tos, 0, tb->tb_id, false);
+       dscp = cfg->fc_dscp;
+       fa = fib_find_alias(&l->leaf, slen, dscp, 0, tb->tb_id, false);
        if (!fa)
                return -ESRCH;
 
-       pr_debug("Deleting %08x/%d tos=%d t=%p\n", key, plen, tos, t);
+       pr_debug("Deleting %08x/%d dsfield=0x%02x t=%p\n", key, plen,
+                inet_dscp_to_dsfield(dscp), t);
 
        fa_to_delete = NULL;
        hlist_for_each_entry_from(fa, fa_list) {
@@ -1730,7 +1736,7 @@ int fib_table_delete(struct net *net, struct fib_table *tb,
 
                if ((fa->fa_slen != slen) ||
                    (fa->tb_id != tb->tb_id) ||
-                   (fa->fa_tos != tos))
+                   (fa->fa_dscp != dscp))
                        break;
 
                if ((!cfg->fc_type || fa->fa_type == cfg->fc_type) &&
@@ -2298,7 +2304,7 @@ static int fn_trie_dump_leaf(struct key_vector *l, struct fib_table *tb,
                                fri.tb_id = tb->tb_id;
                                fri.dst = xkey;
                                fri.dst_len = KEYLENGTH - fa->fa_slen;
-                               fri.tos = fa->fa_tos;
+                               fri.tos = inet_dscp_to_dsfield(fa->fa_dscp);
                                fri.type = fa->fa_type;
                                fri.offload = fa->offload;
                                fri.trap = fa->trap;
@@ -2810,8 +2816,9 @@ static int fib_trie_seq_show(struct seq_file *seq, void *v)
                                             fa->fa_info->fib_scope),
                                   rtn_type(buf2, sizeof(buf2),
                                            fa->fa_type));
-                       if (fa->fa_tos)
-                               seq_printf(seq, " tos=%d", fa->fa_tos);
+                       if (fa->fa_dscp)
+                               seq_printf(seq, " tos=%d",
+                                          inet_dscp_to_dsfield(fa->fa_dscp));
                        seq_putc(seq, '\n');
                }
        }
index 8b35075..634766e 100644 (file)
@@ -84,6 +84,7 @@
 #include <linux/jhash.h>
 #include <net/dst.h>
 #include <net/dst_metadata.h>
+#include <net/inet_dscp.h>
 #include <net/net_namespace.h>
 #include <net/ip.h>
 #include <net/route.h>
@@ -3391,7 +3392,7 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh,
 
                                if (fa->fa_slen == slen &&
                                    fa->tb_id == fri.tb_id &&
-                                   fa->fa_tos == fri.tos &&
+                                   fa->fa_dscp == inet_dsfield_to_dscp(fri.tos) &&
                                    fa->fa_info == res.fi &&
                                    fa->fa_type == fri.type) {
                                        fri.offload = fa->offload;