mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	net: Introduce VRF related flags and helpers
Add a VRF_MASTER flag for interfaces and helper functions for determining if a device is a VRF_MASTER. Add link attribute for passing VRF_TABLE id. Add vrf_ptr to netdevice. Add various macros for determining if a device is a VRF device, the index of the master VRF device and table associated with VRF device. Signed-off-by: Shrijeet Mukherjee <shm@cumulusnetworks.com> Signed-off-by: David Ahern <dsa@cumulusnetworks.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									0344338bd8
								
							
						
					
					
						commit
						4e3c89920c
					
				
					 3 changed files with 168 additions and 0 deletions
				
			
		| 
						 | 
				
			
			@ -1289,6 +1289,7 @@ enum netdev_priv_flags {
 | 
			
		|||
	IFF_XMIT_DST_RELEASE_PERM	= 1<<22,
 | 
			
		||||
	IFF_IPVLAN_MASTER		= 1<<23,
 | 
			
		||||
	IFF_IPVLAN_SLAVE		= 1<<24,
 | 
			
		||||
	IFF_VRF_MASTER			= 1<<25,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define IFF_802_1Q_VLAN			IFF_802_1Q_VLAN
 | 
			
		||||
| 
						 | 
				
			
			@ -1316,6 +1317,7 @@ enum netdev_priv_flags {
 | 
			
		|||
#define IFF_XMIT_DST_RELEASE_PERM	IFF_XMIT_DST_RELEASE_PERM
 | 
			
		||||
#define IFF_IPVLAN_MASTER		IFF_IPVLAN_MASTER
 | 
			
		||||
#define IFF_IPVLAN_SLAVE		IFF_IPVLAN_SLAVE
 | 
			
		||||
#define IFF_VRF_MASTER			IFF_VRF_MASTER
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 *	struct net_device - The DEVICE structure.
 | 
			
		||||
| 
						 | 
				
			
			@ -1432,6 +1434,7 @@ enum netdev_priv_flags {
 | 
			
		|||
 *	@dn_ptr:	DECnet specific data
 | 
			
		||||
 *	@ip6_ptr:	IPv6 specific data
 | 
			
		||||
 *	@ax25_ptr:	AX.25 specific data
 | 
			
		||||
 *	@vrf_ptr:	VRF specific data
 | 
			
		||||
 *	@ieee80211_ptr:	IEEE 802.11 specific data, assign before registering
 | 
			
		||||
 *
 | 
			
		||||
 *	@last_rx:	Time of last Rx
 | 
			
		||||
| 
						 | 
				
			
			@ -1650,6 +1653,7 @@ struct net_device {
 | 
			
		|||
	struct dn_dev __rcu     *dn_ptr;
 | 
			
		||||
	struct inet6_dev __rcu	*ip6_ptr;
 | 
			
		||||
	void			*ax25_ptr;
 | 
			
		||||
	struct net_vrf_dev __rcu *vrf_ptr;
 | 
			
		||||
	struct wireless_dev	*ieee80211_ptr;
 | 
			
		||||
	struct wpan_dev		*ieee802154_ptr;
 | 
			
		||||
#if IS_ENABLED(CONFIG_MPLS_ROUTING)
 | 
			
		||||
| 
						 | 
				
			
			@ -3808,6 +3812,22 @@ static inline bool netif_supports_nofcs(struct net_device *dev)
 | 
			
		|||
	return dev->priv_flags & IFF_SUPP_NOFCS;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline bool netif_is_vrf(const struct net_device *dev)
 | 
			
		||||
{
 | 
			
		||||
	return dev->priv_flags & IFF_VRF_MASTER;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline bool netif_index_is_vrf(struct net *net, int ifindex)
 | 
			
		||||
{
 | 
			
		||||
	struct net_device *dev = dev_get_by_index_rcu(net, ifindex);
 | 
			
		||||
	bool rc = false;
 | 
			
		||||
 | 
			
		||||
	if (dev)
 | 
			
		||||
		rc = netif_is_vrf(dev);
 | 
			
		||||
 | 
			
		||||
	return rc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* This device needs to keep skb dst for qdisc enqueue or ndo_start_xmit() */
 | 
			
		||||
static inline void netif_keep_dst(struct net_device *dev)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										139
									
								
								include/net/vrf.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										139
									
								
								include/net/vrf.h
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,139 @@
 | 
			
		|||
/*
 | 
			
		||||
 * include/net/net_vrf.h - adds vrf dev structure definitions
 | 
			
		||||
 * Copyright (c) 2015 Cumulus Networks
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU General Public License as published by
 | 
			
		||||
 * the Free Software Foundation; either version 2 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __LINUX_NET_VRF_H
 | 
			
		||||
#define __LINUX_NET_VRF_H
 | 
			
		||||
 | 
			
		||||
struct net_vrf_dev {
 | 
			
		||||
	struct rcu_head		rcu;
 | 
			
		||||
	int                     ifindex; /* ifindex of master dev */
 | 
			
		||||
	u32                     tb_id;   /* table id for VRF */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct slave {
 | 
			
		||||
	struct list_head	list;
 | 
			
		||||
	struct net_device	*dev;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct slave_queue {
 | 
			
		||||
	struct list_head	all_slaves;
 | 
			
		||||
	int			num_slaves;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct net_vrf {
 | 
			
		||||
	struct slave_queue	queue;
 | 
			
		||||
	struct rtable           *rth;
 | 
			
		||||
	u32			tb_id;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#if IS_ENABLED(CONFIG_NET_VRF)
 | 
			
		||||
/* called with rcu_read_lock() */
 | 
			
		||||
static inline int vrf_master_ifindex_rcu(const struct net_device *dev)
 | 
			
		||||
{
 | 
			
		||||
	struct net_vrf_dev *vrf_ptr;
 | 
			
		||||
	int ifindex = 0;
 | 
			
		||||
 | 
			
		||||
	if (!dev)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	if (netif_is_vrf(dev))
 | 
			
		||||
		ifindex = dev->ifindex;
 | 
			
		||||
	else {
 | 
			
		||||
		vrf_ptr = rcu_dereference(dev->vrf_ptr);
 | 
			
		||||
		if (vrf_ptr)
 | 
			
		||||
			ifindex = vrf_ptr->ifindex;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return ifindex;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* called with rcu_read_lock */
 | 
			
		||||
static inline int vrf_dev_table_rcu(const struct net_device *dev)
 | 
			
		||||
{
 | 
			
		||||
	int tb_id = 0;
 | 
			
		||||
 | 
			
		||||
	if (dev) {
 | 
			
		||||
		struct net_vrf_dev *vrf_ptr;
 | 
			
		||||
 | 
			
		||||
		vrf_ptr = rcu_dereference(dev->vrf_ptr);
 | 
			
		||||
		if (vrf_ptr)
 | 
			
		||||
			tb_id = vrf_ptr->tb_id;
 | 
			
		||||
	}
 | 
			
		||||
	return tb_id;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline int vrf_dev_table(const struct net_device *dev)
 | 
			
		||||
{
 | 
			
		||||
	int tb_id;
 | 
			
		||||
 | 
			
		||||
	rcu_read_lock();
 | 
			
		||||
	tb_id = vrf_dev_table_rcu(dev);
 | 
			
		||||
	rcu_read_unlock();
 | 
			
		||||
 | 
			
		||||
	return tb_id;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* called with rtnl */
 | 
			
		||||
static inline int vrf_dev_table_rtnl(const struct net_device *dev)
 | 
			
		||||
{
 | 
			
		||||
	int tb_id = 0;
 | 
			
		||||
 | 
			
		||||
	if (dev) {
 | 
			
		||||
		struct net_vrf_dev *vrf_ptr;
 | 
			
		||||
 | 
			
		||||
		vrf_ptr = rtnl_dereference(dev->vrf_ptr);
 | 
			
		||||
		if (vrf_ptr)
 | 
			
		||||
			tb_id = vrf_ptr->tb_id;
 | 
			
		||||
	}
 | 
			
		||||
	return tb_id;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* caller has already checked netif_is_vrf(dev) */
 | 
			
		||||
static inline struct rtable *vrf_dev_get_rth(const struct net_device *dev)
 | 
			
		||||
{
 | 
			
		||||
	struct rtable *rth = ERR_PTR(-ENETUNREACH);
 | 
			
		||||
	struct net_vrf *vrf = netdev_priv(dev);
 | 
			
		||||
 | 
			
		||||
	if (vrf) {
 | 
			
		||||
		rth = vrf->rth;
 | 
			
		||||
		atomic_inc(&rth->dst.__refcnt);
 | 
			
		||||
	}
 | 
			
		||||
	return rth;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
static inline int vrf_master_ifindex_rcu(const struct net_device *dev)
 | 
			
		||||
{
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline int vrf_dev_table_rcu(const struct net_device *dev)
 | 
			
		||||
{
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline int vrf_dev_table(const struct net_device *dev)
 | 
			
		||||
{
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline int vrf_dev_table_rtnl(const struct net_device *dev)
 | 
			
		||||
{
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline struct rtable *vrf_dev_get_rth(const struct net_device *dev)
 | 
			
		||||
{
 | 
			
		||||
	return ERR_PTR(-ENETUNREACH);
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif /* __LINUX_NET_VRF_H */
 | 
			
		||||
| 
						 | 
				
			
			@ -341,6 +341,15 @@ enum macvlan_macaddr_mode {
 | 
			
		|||
 | 
			
		||||
#define MACVLAN_FLAG_NOPROMISC	1
 | 
			
		||||
 | 
			
		||||
/* VRF section */
 | 
			
		||||
enum {
 | 
			
		||||
	IFLA_VRF_UNSPEC,
 | 
			
		||||
	IFLA_VRF_TABLE,
 | 
			
		||||
	__IFLA_VRF_MAX
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define IFLA_VRF_MAX (__IFLA_VRF_MAX - 1)
 | 
			
		||||
 | 
			
		||||
/* IPVLAN section */
 | 
			
		||||
enum {
 | 
			
		||||
	IFLA_IPVLAN_UNSPEC,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue