#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>
        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;
        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;
 
                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 ||
 
                .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,
        };
                .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,
        };
        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;
                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)
                        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;
        }
 
 
        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;
        }
 
        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);
 
                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
         * 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;
 
                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;
                                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;
                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;
                        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;
        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);
 
        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) {
 
                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) &&
                                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;
                                             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');
                }
        }