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

ipv4: nexthop version of fib_info_nh_uses_dev



Similar to the last path, need to fix fib_info_nh_uses_dev for
external nexthops to avoid referencing multiple nh_grp structs.
Move the device check in fib_info_nh_uses_dev to a helper and
create a nexthop version that is called if the fib_info uses an
external nexthop.

Fixes: 430a0491 ("nexthop: Add support for nexthop groups")
Signed-off-by: default avatarDavid Ahern <dsahern@gmail.com>
Acked-by: default avatarNikolay Aleksandrov <nikolay@cumulusnetworks.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent af7888ad
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -447,6 +447,16 @@ static inline int fib_num_tclassid_users(struct net *net)
#endif
int fib_unmerge(struct net *net);

static inline bool nhc_l3mdev_matches_dev(const struct fib_nh_common *nhc,
const struct net_device *dev)
{
	if (nhc->nhc_dev == dev ||
	    l3mdev_master_ifindex_rcu(nhc->nhc_dev) == dev->ifindex)
		return true;

	return false;
}

/* Exported by fib_semantics.c */
int ip_fib_check_default(__be32 gw, struct net_device *dev);
int fib_sync_down_dev(struct net_device *dev, unsigned long event, bool force);
+25 −0
Original line number Diff line number Diff line
@@ -266,6 +266,31 @@ struct fib_nh_common *nexthop_get_nhc_lookup(const struct nexthop *nh,
	return NULL;
}

static inline bool nexthop_uses_dev(const struct nexthop *nh,
				    const struct net_device *dev)
{
	struct nh_info *nhi;

	if (nh->is_group) {
		struct nh_group *nhg = rcu_dereference(nh->nh_grp);
		int i;

		for (i = 0; i < nhg->num_nh; i++) {
			struct nexthop *nhe = nhg->nh_entries[i].nh;

			nhi = rcu_dereference(nhe->nh_info);
			if (nhc_l3mdev_matches_dev(&nhi->fib_nhc, dev))
				return true;
		}
	} else {
		nhi = rcu_dereference(nh->nh_info);
		if (nhc_l3mdev_matches_dev(&nhi->fib_nhc, dev))
			return true;
	}

	return false;
}

static inline unsigned int fib_info_num_path(const struct fib_info *fi)
{
	if (unlikely(fi->nh))
+10 −9
Original line number Diff line number Diff line
@@ -309,19 +309,20 @@ bool fib_info_nh_uses_dev(struct fib_info *fi, const struct net_device *dev)
{
	bool dev_match = false;
#ifdef CONFIG_IP_ROUTE_MULTIPATH
	if (unlikely(fi->nh)) {
		dev_match = nexthop_uses_dev(fi->nh, dev);
	} else {
		int ret;

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

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