Commit 32ccf110 authored by Guillaume Nault's avatar Guillaume Nault Committed by Jakub Kicinski
Browse files

ipv4: Use dscp_t in struct fib_alias



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: default avatarGuillaume Nault <gnault@redhat.com>
Acked-by: default avatarDavid Ahern <dsahern@kernel.org>
Reviewed-by: default avatarToke Høiland-Jørgensen <toke@redhat.com>
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent f55fbb6a
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -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;
+8 −6
Original line number Diff line number Diff line
@@ -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 ||
+33 −26
Original line number Diff line number Diff line
@@ -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 @@ int fib_table_lookup(struct fib_table *tb, const struct flowi4 *flp,
			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');
		}
	}
+2 −1
Original line number Diff line number Diff line
@@ -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;