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

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

net: l3mdev: Allow the l3mdev to be a loopback



Allow an L3 master device to act as the loopback for that L3 domain.
For IPv4 the device can also have the address 127.0.0.1.

Signed-off-by: default avatarDavid Ahern <dsa@cumulusnetworks.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent a8e3e1a9
Loading
Loading
Loading
Loading
+3 −3
Original line number Original line Diff line number Diff line
@@ -90,7 +90,7 @@ static inline int l3mdev_master_ifindex_by_index(struct net *net, int ifindex)
}
}


static inline
static inline
const struct net_device *l3mdev_master_dev_rcu(const struct net_device *_dev)
struct net_device *l3mdev_master_dev_rcu(const struct net_device *_dev)
{
{
	/* netdev_master_upper_dev_get_rcu calls
	/* netdev_master_upper_dev_get_rcu calls
	 * list_first_or_null_rcu to walk the upper dev list.
	 * list_first_or_null_rcu to walk the upper dev list.
@@ -99,7 +99,7 @@ const struct net_device *l3mdev_master_dev_rcu(const struct net_device *_dev)
	 * typecast to remove the const
	 * typecast to remove the const
	 */
	 */
	struct net_device *dev = (struct net_device *)_dev;
	struct net_device *dev = (struct net_device *)_dev;
	const struct net_device *master;
	struct net_device *master;


	if (!dev)
	if (!dev)
		return NULL;
		return NULL;
@@ -254,7 +254,7 @@ static inline int l3mdev_master_ifindex_by_index(struct net *net, int ifindex)
}
}


static inline
static inline
const struct net_device *l3mdev_master_dev_rcu(const struct net_device *dev)
struct net_device *l3mdev_master_dev_rcu(const struct net_device *dev)
{
{
	return NULL;
	return NULL;
}
}
+6 −2
Original line number Original line Diff line number Diff line
@@ -2018,7 +2018,9 @@ static struct rtable *__mkroute_output(const struct fib_result *res,
		return ERR_PTR(-EINVAL);
		return ERR_PTR(-EINVAL);


	if (likely(!IN_DEV_ROUTE_LOCALNET(in_dev)))
	if (likely(!IN_DEV_ROUTE_LOCALNET(in_dev)))
		if (ipv4_is_loopback(fl4->saddr) && !(dev_out->flags & IFF_LOOPBACK))
		if (ipv4_is_loopback(fl4->saddr) &&
		    !(dev_out->flags & IFF_LOOPBACK) &&
		    !netif_is_l3_master(dev_out))
			return ERR_PTR(-EINVAL);
			return ERR_PTR(-EINVAL);


	if (ipv4_is_lbcast(fl4->daddr))
	if (ipv4_is_lbcast(fl4->daddr))
@@ -2302,7 +2304,9 @@ struct rtable *__ip_route_output_key_hash(struct net *net, struct flowi4 *fl4,
			else
			else
				fl4->saddr = fl4->daddr;
				fl4->saddr = fl4->daddr;
		}
		}
		dev_out = net->loopback_dev;

		/* L3 master device is the loopback for that domain */
		dev_out = l3mdev_master_dev_rcu(dev_out) ? : net->loopback_dev;
		fl4->flowi4_oif = dev_out->ifindex;
		fl4->flowi4_oif = dev_out->ifindex;
		flags |= RTCF_LOCAL;
		flags |= RTCF_LOCAL;
		goto make_route;
		goto make_route;
+10 −2
Original line number Original line Diff line number Diff line
@@ -2558,8 +2558,16 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
{
{
	u32 tb_id;
	u32 tb_id;
	struct net *net = dev_net(idev->dev);
	struct net *net = dev_net(idev->dev);
	struct rt6_info *rt = ip6_dst_alloc(net, net->loopback_dev,
	struct net_device *dev = net->loopback_dev;
					    DST_NOCOUNT);
	struct rt6_info *rt;

	/* use L3 Master device as loopback for host routes if device
	 * is enslaved and address is not link local or multicast
	 */
	if (!rt6_need_strict(addr))
		dev = l3mdev_master_dev_rcu(idev->dev) ? : dev;

	rt = ip6_dst_alloc(net, dev, DST_NOCOUNT);
	if (!rt)
	if (!rt)
		return ERR_PTR(-ENOMEM);
		return ERR_PTR(-ENOMEM);