Commit 18916818 authored by Benjamin Poirier's avatar Benjamin Poirier Committed by David S. Miller
Browse files

net: mpls: Remove rcu protection from nh_dev



Following the previous commit, nh_dev can no longer be accessed and
modified concurrently.

Signed-off-by: default avatarBenjamin Poirier <bpoirier@nvidia.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 7d4741ea
Loading
Loading
Loading
Loading
+15 −24
Original line number Original line Diff line number Diff line
@@ -409,7 +409,7 @@ static int mpls_forward(struct sk_buff *skb, struct net_device *dev,
		goto err;
		goto err;


	/* Find the output device */
	/* Find the output device */
	out_dev = rcu_dereference(nh->nh_dev);
	out_dev = nh->nh_dev;
	if (!mpls_output_possible(out_dev))
	if (!mpls_output_possible(out_dev))
		goto tx_err;
		goto tx_err;


@@ -698,7 +698,7 @@ static int mpls_nh_assign_dev(struct net *net, struct mpls_route *rt,
	    (dev->addr_len != nh->nh_via_alen))
	    (dev->addr_len != nh->nh_via_alen))
		goto errout;
		goto errout;


	RCU_INIT_POINTER(nh->nh_dev, dev);
	nh->nh_dev = dev;


	if (!(dev->flags & IFF_UP)) {
	if (!(dev->flags & IFF_UP)) {
		nh->nh_flags |= RTNH_F_DEAD;
		nh->nh_flags |= RTNH_F_DEAD;
@@ -1510,12 +1510,9 @@ static int mpls_ifdown(struct net_device *dev, int event)
			u8 deleted = 0;
			u8 deleted = 0;


			for_nexthops(rt) {
			for_nexthops(rt) {
				struct net_device *nh_dev =
				if (!nh->nh_dev || nh->nh_dev == dev)
					rtnl_dereference(nh->nh_dev);

				if (!nh_dev || nh_dev == dev)
					deleted++;
					deleted++;
				if (nh_dev == dev)
				if (nh->nh_dev == dev)
					nh_del = true;
					nh_del = true;
			} endfor_nexthops(rt);
			} endfor_nexthops(rt);


@@ -1540,7 +1537,7 @@ static int mpls_ifdown(struct net_device *dev, int event)
		change_nexthops(rt) {
		change_nexthops(rt) {
			unsigned int nh_flags = nh->nh_flags;
			unsigned int nh_flags = nh->nh_flags;


			if (rtnl_dereference(nh->nh_dev) != dev)
			if (nh->nh_dev != dev)
				goto next;
				goto next;


			switch (event) {
			switch (event) {
@@ -1553,7 +1550,7 @@ static int mpls_ifdown(struct net_device *dev, int event)
				break;
				break;
			}
			}
			if (event == NETDEV_UNREGISTER)
			if (event == NETDEV_UNREGISTER)
				RCU_INIT_POINTER(nh->nh_dev, NULL);
				nh->nh_dev = NULL;


			if (nh->nh_flags != nh_flags)
			if (nh->nh_flags != nh_flags)
				WRITE_ONCE(nh->nh_flags, nh_flags);
				WRITE_ONCE(nh->nh_flags, nh_flags);
@@ -1588,14 +1585,12 @@ static void mpls_ifup(struct net_device *dev, unsigned int flags)
		alive = 0;
		alive = 0;
		change_nexthops(rt) {
		change_nexthops(rt) {
			unsigned int nh_flags = nh->nh_flags;
			unsigned int nh_flags = nh->nh_flags;
			struct net_device *nh_dev =
				rtnl_dereference(nh->nh_dev);


			if (!(nh_flags & flags)) {
			if (!(nh_flags & flags)) {
				alive++;
				alive++;
				continue;
				continue;
			}
			}
			if (nh_dev != dev)
			if (nh->nh_dev != dev)
				continue;
				continue;
			alive++;
			alive++;
			nh_flags &= ~flags;
			nh_flags &= ~flags;
@@ -2030,7 +2025,7 @@ static int mpls_dump_route(struct sk_buff *skb, u32 portid, u32 seq, int event,
		    nla_put_via(skb, nh->nh_via_table, mpls_nh_via(rt, nh),
		    nla_put_via(skb, nh->nh_via_table, mpls_nh_via(rt, nh),
				nh->nh_via_alen))
				nh->nh_via_alen))
			goto nla_put_failure;
			goto nla_put_failure;
		dev = rtnl_dereference(nh->nh_dev);
		dev = nh->nh_dev;
		if (dev && nla_put_u32(skb, RTA_OIF, dev->ifindex))
		if (dev && nla_put_u32(skb, RTA_OIF, dev->ifindex))
			goto nla_put_failure;
			goto nla_put_failure;
		if (nh->nh_flags & RTNH_F_LINKDOWN)
		if (nh->nh_flags & RTNH_F_LINKDOWN)
@@ -2048,7 +2043,7 @@ static int mpls_dump_route(struct sk_buff *skb, u32 portid, u32 seq, int event,
			goto nla_put_failure;
			goto nla_put_failure;


		for_nexthops(rt) {
		for_nexthops(rt) {
			dev = rtnl_dereference(nh->nh_dev);
			dev = nh->nh_dev;
			if (!dev)
			if (!dev)
				continue;
				continue;


@@ -2159,18 +2154,14 @@ static int mpls_valid_fib_dump_req(struct net *net, const struct nlmsghdr *nlh,
static bool mpls_rt_uses_dev(struct mpls_route *rt,
static bool mpls_rt_uses_dev(struct mpls_route *rt,
			     const struct net_device *dev)
			     const struct net_device *dev)
{
{
	struct net_device *nh_dev;

	if (rt->rt_nhn == 1) {
	if (rt->rt_nhn == 1) {
		struct mpls_nh *nh = rt->rt_nh;
		struct mpls_nh *nh = rt->rt_nh;


		nh_dev = rtnl_dereference(nh->nh_dev);
		if (nh->nh_dev == dev)
		if (dev == nh_dev)
			return true;
			return true;
	} else {
	} else {
		for_nexthops(rt) {
		for_nexthops(rt) {
			nh_dev = rtnl_dereference(nh->nh_dev);
			if (nh->nh_dev == dev)
			if (nh_dev == dev)
				return true;
				return true;
		} endfor_nexthops(rt);
		} endfor_nexthops(rt);
	}
	}
@@ -2258,7 +2249,7 @@ static inline size_t lfib_nlmsg_size(struct mpls_route *rt)
		size_t nhsize = 0;
		size_t nhsize = 0;


		for_nexthops(rt) {
		for_nexthops(rt) {
			if (!rtnl_dereference(nh->nh_dev))
			if (!nh->nh_dev)
				continue;
				continue;
			nhsize += nla_total_size(sizeof(struct rtnexthop));
			nhsize += nla_total_size(sizeof(struct rtnexthop));
			/* RTA_VIA */
			/* RTA_VIA */
@@ -2504,7 +2495,7 @@ static int mpls_getroute(struct sk_buff *in_skb, struct nlmsghdr *in_nlh,
	    nla_put_via(skb, nh->nh_via_table, mpls_nh_via(rt, nh),
	    nla_put_via(skb, nh->nh_via_table, mpls_nh_via(rt, nh),
			nh->nh_via_alen))
			nh->nh_via_alen))
		goto nla_put_failure;
		goto nla_put_failure;
	dev = rtnl_dereference(nh->nh_dev);
	dev = nh->nh_dev;
	if (dev && nla_put_u32(skb, RTA_OIF, dev->ifindex))
	if (dev && nla_put_u32(skb, RTA_OIF, dev->ifindex))
		goto nla_put_failure;
		goto nla_put_failure;


@@ -2543,7 +2534,7 @@ static int resize_platform_label_table(struct net *net, size_t limit)
		rt0 = mpls_rt_alloc(1, lo->addr_len, 0);
		rt0 = mpls_rt_alloc(1, lo->addr_len, 0);
		if (IS_ERR(rt0))
		if (IS_ERR(rt0))
			goto nort0;
			goto nort0;
		RCU_INIT_POINTER(rt0->rt_nh->nh_dev, lo);
		rt0->rt_nh->nh_dev = lo;
		rt0->rt_protocol = RTPROT_KERNEL;
		rt0->rt_protocol = RTPROT_KERNEL;
		rt0->rt_payload_type = MPT_IPV4;
		rt0->rt_payload_type = MPT_IPV4;
		rt0->rt_ttl_propagate = MPLS_TTL_PROP_DEFAULT;
		rt0->rt_ttl_propagate = MPLS_TTL_PROP_DEFAULT;
@@ -2557,7 +2548,7 @@ static int resize_platform_label_table(struct net *net, size_t limit)
		rt2 = mpls_rt_alloc(1, lo->addr_len, 0);
		rt2 = mpls_rt_alloc(1, lo->addr_len, 0);
		if (IS_ERR(rt2))
		if (IS_ERR(rt2))
			goto nort2;
			goto nort2;
		RCU_INIT_POINTER(rt2->rt_nh->nh_dev, lo);
		rt2->rt_nh->nh_dev = lo;
		rt2->rt_protocol = RTPROT_KERNEL;
		rt2->rt_protocol = RTPROT_KERNEL;
		rt2->rt_payload_type = MPT_IPV6;
		rt2->rt_payload_type = MPT_IPV6;
		rt2->rt_ttl_propagate = MPLS_TTL_PROP_DEFAULT;
		rt2->rt_ttl_propagate = MPLS_TTL_PROP_DEFAULT;
+1 −1
Original line number Original line Diff line number Diff line
@@ -87,7 +87,7 @@ enum mpls_payload_type {
};
};


struct mpls_nh { /* next hop label forwarding entry */
struct mpls_nh { /* next hop label forwarding entry */
	struct net_device __rcu *nh_dev;
	struct net_device	*nh_dev;


	/* nh_flags is accessed under RCU in the packet path; it is
	/* nh_flags is accessed under RCU in the packet path; it is
	 * modified handling netdev events with rtnl lock held
	 * modified handling netdev events with rtnl lock held