forked from mirrors/linux
		
	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: David Ahern <dsa@cumulusnetworks.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									a8e3e1a9f0
								
							
						
					
					
						commit
						5f02ce24c2
					
				
					 3 changed files with 19 additions and 7 deletions
				
			
		| 
						 | 
					@ -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;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue