Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit dcb1ecb5 authored by David Ahern's avatar David Ahern Committed by David S. Miller
Browse files

ipv4: Prepare for fib6_nh from a nexthop object



Convert more IPv4 code to use fib_nh_common over fib_nh to enable routes
to use a fib6_nh based nexthop. In the end, only code not using a
nexthop object in a fib_info should directly access fib_nh in a fib_info
without checking the famiy and going through fib_nh_common. Those
functions will be marked when it is not directly evident.

Signed-off-by: default avatarDavid Ahern <dsahern@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 5481d73f
Loading
Loading
Loading
Loading
+11 −4
Original line number Diff line number Diff line
@@ -195,7 +195,7 @@ struct fib_result_nl {
#define FIB_TABLE_HASHSZ 2
#endif

__be32 fib_info_update_nh_saddr(struct net *net, struct fib_nh *nh,
__be32 fib_info_update_nhc_saddr(struct net *net, struct fib_nh_common *nhc,
				 unsigned char scope);
__be32 fib_result_prefsrc(struct net *net, struct fib_result *res);

@@ -455,11 +455,18 @@ static inline void fib_combine_itag(u32 *itag, const struct fib_result *res)
{
#ifdef CONFIG_IP_ROUTE_CLASSID
	struct fib_nh_common *nhc = res->nhc;
	struct fib_nh *nh = container_of(nhc, struct fib_nh, nh_common);
#ifdef CONFIG_IP_MULTIPLE_TABLES
	u32 rtag;
#endif
	if (nhc->nhc_family == AF_INET) {
		struct fib_nh *nh;

		nh = container_of(nhc, struct fib_nh, nh_common);
		*itag = nh->nh_tclassid << 16;
	} else {
		*itag = 0;
	}

#ifdef CONFIG_IP_MULTIPLE_TABLES
	rtag = res->tclassid;
	if (*itag == 0)
+6 −6
Original line number Diff line number Diff line
@@ -235,9 +235,9 @@ static inline unsigned int __inet_dev_addr_type(struct net *net,
	if (table) {
		ret = RTN_UNICAST;
		if (!fib_table_lookup(table, &fl4, &res, FIB_LOOKUP_NOREF)) {
			struct fib_nh *nh = fib_info_nh(res.fi, 0);
			struct fib_nh_common *nhc = fib_info_nhc(res.fi, 0);

			if (!dev || dev == nh->fib_nh_dev)
			if (!dev || dev == nhc->nhc_dev)
				ret = res.type;
		}
	}
@@ -325,18 +325,18 @@ bool fib_info_nh_uses_dev(struct fib_info *fi, const struct net_device *dev)
	int ret;

	for (ret = 0; ret < fib_info_num_path(fi); ret++) {
		const struct fib_nh *nh = fib_info_nh(fi, ret);
		const struct fib_nh_common *nhc = fib_info_nhc(fi, ret);

		if (nh->fib_nh_dev == dev) {
		if (nhc->nhc_dev == dev) {
			dev_match = true;
			break;
		} else if (l3mdev_master_ifindex_rcu(nh->fib_nh_dev) == dev->ifindex) {
		} else if (l3mdev_master_ifindex_rcu(nhc->nhc_dev) == dev->ifindex) {
			dev_match = true;
			break;
		}
	}
#else
	if (fib_info_nh(fi, 0)->fib_nh_dev == dev)
	if (fib_info_nhc(fi, 0)->nhc_dev == dev)
		dev_match = true;
#endif

+2 −2
Original line number Diff line number Diff line
@@ -147,9 +147,9 @@ static bool fib4_rule_suppress(struct fib_rule *rule, struct fib_lookup_arg *arg
	struct net_device *dev = NULL;

	if (result->fi) {
		struct fib_nh *nh = fib_info_nh(result->fi, 0);
		struct fib_nh_common *nhc = fib_info_nhc(result->fi, 0);

		dev = nh->fib_nh_dev;
		dev = nhc->nhc_dev;
	}

	/* do not accept result if the route does
+38 −17
Original line number Diff line number Diff line
@@ -61,6 +61,9 @@ static unsigned int fib_info_cnt;
#define DEVINDEX_HASHSIZE (1U << DEVINDEX_HASHBITS)
static struct hlist_head fib_info_devhash[DEVINDEX_HASHSIZE];

/* for_nexthops and change_nexthops only used when nexthop object
 * is not set in a fib_info. The logic within can reference fib_nh.
 */
#ifdef CONFIG_IP_ROUTE_MULTIPATH

#define for_nexthops(fi) {						\
@@ -402,20 +405,23 @@ static inline size_t fib_nlmsg_size(struct fib_info *fi)

		/* each nexthop is packed in an attribute */
		size_t nhsize = nla_total_size(sizeof(struct rtnexthop));
		unsigned int i;

		/* may contain flow and gateway attribute */
		nhsize += 2 * nla_total_size(4);

		/* grab encap info */
		for_nexthops(fi) {
			if (nh->fib_nh_lws) {
		for (i = 0; i < fib_info_num_path(fi); i++) {
			struct fib_nh_common *nhc = fib_info_nhc(fi, i);

			if (nhc->nhc_lwtstate) {
				/* RTA_ENCAP_TYPE */
				nh_encapsize += lwtunnel_get_encap_size(
						nh->fib_nh_lws);
						nhc->nhc_lwtstate);
				/* RTA_ENCAP */
				nh_encapsize +=  nla_total_size(2);
			}
		} endfor_nexthops(fi);
		}

		/* all nexthops are packed in a nested attribute */
		payload += nla_total_size((nhs * nhsize) + nh_encapsize);
@@ -1194,9 +1200,15 @@ static void fib_info_hash_move(struct hlist_head *new_info_hash,
	fib_info_hash_free(old_laddrhash, bytes);
}

__be32 fib_info_update_nh_saddr(struct net *net, struct fib_nh *nh,
__be32 fib_info_update_nhc_saddr(struct net *net, struct fib_nh_common *nhc,
				 unsigned char scope)
{
	struct fib_nh *nh;

	if (nhc->nhc_family != AF_INET)
		return inet_select_addr(nhc->nhc_dev, 0, scope);

	nh = container_of(nhc, struct fib_nh, nh_common);
	nh->nh_saddr = inet_select_addr(nh->fib_nh_dev, nh->fib_nh_gw4, scope);
	nh->nh_saddr_genid = atomic_read(&net->ipv4.dev_addr_genid);

@@ -1206,16 +1218,19 @@ __be32 fib_info_update_nh_saddr(struct net *net, struct fib_nh *nh,
__be32 fib_result_prefsrc(struct net *net, struct fib_result *res)
{
	struct fib_nh_common *nhc = res->nhc;
	struct fib_nh *nh;

	if (res->fi->fib_prefsrc)
		return res->fi->fib_prefsrc;

	if (nhc->nhc_family == AF_INET) {
		struct fib_nh *nh;

		nh = container_of(nhc, struct fib_nh, nh_common);
		if (nh->nh_saddr_genid == atomic_read(&net->ipv4.dev_addr_genid))
			return nh->nh_saddr;
	}

	return fib_info_update_nh_saddr(net, nh, res->fi->fib_scope);
	return fib_info_update_nhc_saddr(net, nhc, res->fi->fib_scope);
}

static bool fib_valid_prefsrc(struct fib_config *cfg, __be32 fib_prefsrc)
@@ -1397,7 +1412,8 @@ struct fib_info *fib_create_info(struct fib_config *cfg,
	}

	change_nexthops(fi) {
		fib_info_update_nh_saddr(net, nexthop_nh, fi->fib_scope);
		fib_info_update_nhc_saddr(net, &nexthop_nh->nh_common,
					  fi->fib_scope);
		if (nexthop_nh->fib_nh_gw_family == AF_INET6)
			fi->fib_nh_is_v6 = true;
	} endfor_nexthops(fi)
@@ -1625,17 +1641,22 @@ int fib_dump_info(struct sk_buff *skb, u32 portid, u32 seq, int event,
	    nla_put_in_addr(skb, RTA_PREFSRC, fi->fib_prefsrc))
		goto nla_put_failure;
	if (nhs == 1) {
		const struct fib_nh *nh = fib_info_nh(fi, 0);
		const struct fib_nh_common *nhc = fib_info_nhc(fi, 0);
		unsigned char flags = 0;

		if (fib_nexthop_info(skb, &nh->nh_common, &flags, false) < 0)
		if (fib_nexthop_info(skb, nhc, &flags, false) < 0)
			goto nla_put_failure;

		rtm->rtm_flags = flags;
#ifdef CONFIG_IP_ROUTE_CLASSID
		if (nhc->nhc_family == AF_INET) {
			struct fib_nh *nh;

			nh = container_of(nhc, struct fib_nh, nh_common);
			if (nh->nh_tclassid &&
			    nla_put_u32(skb, RTA_FLOW, nh->nh_tclassid))
				goto nla_put_failure;
		}
#endif
	} else {
		if (fib_add_multipath(skb, fi) < 0)
+9 −6
Original line number Diff line number Diff line
@@ -2724,9 +2724,9 @@ static unsigned int fib_flag_trans(int type, __be32 mask, struct fib_info *fi)
	if (type == RTN_UNREACHABLE || type == RTN_PROHIBIT)
		flags = RTF_REJECT;
	if (fi) {
		const struct fib_nh *nh = fib_info_nh(fi, 0);
		const struct fib_nh_common *nhc = fib_info_nhc(fi, 0);

		if (nh->fib_nh_gw4)
		if (nhc->nhc_gw.ipv4)
			flags |= RTF_GATEWAY;
	}
	if (mask == htonl(0xFFFFFFFF))
@@ -2773,14 +2773,17 @@ static int fib_route_seq_show(struct seq_file *seq, void *v)
		seq_setwidth(seq, 127);

		if (fi) {
			struct fib_nh *nh = fib_info_nh(fi, 0);
			struct fib_nh_common *nhc = fib_info_nhc(fi, 0);
			__be32 gw = 0;

			if (nhc->nhc_gw_family == AF_INET)
				gw = nhc->nhc_gw.ipv4;

			seq_printf(seq,
				   "%s\t%08X\t%08X\t%04X\t%d\t%u\t"
				   "%d\t%08X\t%d\t%u\t%u",
				   nh->fib_nh_dev ? nh->fib_nh_dev->name : "*",
				   prefix,
				   nh->fib_nh_gw4, flags, 0, 0,
				   nhc->nhc_dev ? nhc->nhc_dev->name : "*",
				   prefix, gw, flags, 0, 0,
				   fi->fib_priority,
				   mask,
				   (fi->fib_advmss ?
Loading