mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	rtnetlink: Add VF config code to rtnetlink
Add code to allow rtnetlink clients to query and set VF information through the PF driver. Signed-off-by: Mitch Williams <mitch.a.williams@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									95c26df829
								
							
						
					
					
						commit
						ebc08a6f47
					
				
					 1 changed files with 67 additions and 0 deletions
				
			
		| 
						 | 
				
			
			@ -35,6 +35,7 @@
 | 
			
		|||
#include <linux/security.h>
 | 
			
		||||
#include <linux/mutex.h>
 | 
			
		||||
#include <linux/if_addr.h>
 | 
			
		||||
#include <linux/pci.h>
 | 
			
		||||
 | 
			
		||||
#include <asm/uaccess.h>
 | 
			
		||||
#include <asm/system.h>
 | 
			
		||||
| 
						 | 
				
			
			@ -580,6 +581,15 @@ static void copy_rtnl_link_stats(struct rtnl_link_stats *a,
 | 
			
		|||
	a->tx_compressed = b->tx_compressed;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static inline int rtnl_vfinfo_size(const struct net_device *dev)
 | 
			
		||||
{
 | 
			
		||||
	if (dev->dev.parent && dev_is_pci(dev->dev.parent))
 | 
			
		||||
		return dev_num_vf(dev->dev.parent) *
 | 
			
		||||
			sizeof(struct ifla_vf_info);
 | 
			
		||||
	else
 | 
			
		||||
		return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline size_t if_nlmsg_size(const struct net_device *dev)
 | 
			
		||||
{
 | 
			
		||||
	return NLMSG_ALIGN(sizeof(struct ifinfomsg))
 | 
			
		||||
| 
						 | 
				
			
			@ -597,6 +607,8 @@ static inline size_t if_nlmsg_size(const struct net_device *dev)
 | 
			
		|||
	       + nla_total_size(4) /* IFLA_MASTER */
 | 
			
		||||
	       + nla_total_size(1) /* IFLA_OPERSTATE */
 | 
			
		||||
	       + nla_total_size(1) /* IFLA_LINKMODE */
 | 
			
		||||
	       + nla_total_size(4) /* IFLA_NUM_VF */
 | 
			
		||||
	       + nla_total_size(rtnl_vfinfo_size(dev)) /* IFLA_VFINFO */
 | 
			
		||||
	       + rtnl_link_get_size(dev); /* IFLA_LINKINFO */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -665,6 +677,17 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
 | 
			
		|||
	stats = dev_get_stats(dev);
 | 
			
		||||
	copy_rtnl_link_stats(nla_data(attr), stats);
 | 
			
		||||
 | 
			
		||||
	if (dev->netdev_ops->ndo_get_vf_config && dev->dev.parent) {
 | 
			
		||||
		int i;
 | 
			
		||||
		struct ifla_vf_info ivi;
 | 
			
		||||
 | 
			
		||||
		NLA_PUT_U32(skb, IFLA_NUM_VF, dev_num_vf(dev->dev.parent));
 | 
			
		||||
		for (i = 0; i < dev_num_vf(dev->dev.parent); i++) {
 | 
			
		||||
			if (dev->netdev_ops->ndo_get_vf_config(dev, i, &ivi))
 | 
			
		||||
				break;
 | 
			
		||||
			NLA_PUT(skb, IFLA_VFINFO, sizeof(ivi), &ivi);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if (dev->rtnl_link_ops) {
 | 
			
		||||
		if (rtnl_link_fill(skb, dev) < 0)
 | 
			
		||||
			goto nla_put_failure;
 | 
			
		||||
| 
						 | 
				
			
			@ -725,6 +748,12 @@ const struct nla_policy ifla_policy[IFLA_MAX+1] = {
 | 
			
		|||
	[IFLA_LINKINFO]		= { .type = NLA_NESTED },
 | 
			
		||||
	[IFLA_NET_NS_PID]	= { .type = NLA_U32 },
 | 
			
		||||
	[IFLA_IFALIAS]	        = { .type = NLA_STRING, .len = IFALIASZ-1 },
 | 
			
		||||
	[IFLA_VF_MAC]		= { .type = NLA_BINARY,
 | 
			
		||||
				    .len = sizeof(struct ifla_vf_mac) },
 | 
			
		||||
	[IFLA_VF_VLAN]		= { .type = NLA_BINARY,
 | 
			
		||||
				    .len = sizeof(struct ifla_vf_vlan) },
 | 
			
		||||
	[IFLA_VF_TX_RATE]	= { .type = NLA_BINARY,
 | 
			
		||||
				    .len = sizeof(struct ifla_vf_tx_rate) },
 | 
			
		||||
};
 | 
			
		||||
EXPORT_SYMBOL(ifla_policy);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -898,6 +927,44 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
 | 
			
		|||
		write_unlock_bh(&dev_base_lock);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (tb[IFLA_VF_MAC]) {
 | 
			
		||||
		struct ifla_vf_mac *ivm;
 | 
			
		||||
		ivm = nla_data(tb[IFLA_VF_MAC]);
 | 
			
		||||
		write_lock_bh(&dev_base_lock);
 | 
			
		||||
		if (ops->ndo_set_vf_mac)
 | 
			
		||||
			err = ops->ndo_set_vf_mac(dev, ivm->vf, ivm->mac);
 | 
			
		||||
		write_unlock_bh(&dev_base_lock);
 | 
			
		||||
		if (err < 0)
 | 
			
		||||
			goto errout;
 | 
			
		||||
		modified = 1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (tb[IFLA_VF_VLAN]) {
 | 
			
		||||
		struct ifla_vf_vlan *ivv;
 | 
			
		||||
		ivv = nla_data(tb[IFLA_VF_VLAN]);
 | 
			
		||||
		write_lock_bh(&dev_base_lock);
 | 
			
		||||
		if (ops->ndo_set_vf_vlan)
 | 
			
		||||
			err = ops->ndo_set_vf_vlan(dev, ivv->vf,
 | 
			
		||||
						   (u16)ivv->vlan,
 | 
			
		||||
						   (u8)ivv->qos);
 | 
			
		||||
		write_unlock_bh(&dev_base_lock);
 | 
			
		||||
		if (err < 0)
 | 
			
		||||
			goto errout;
 | 
			
		||||
		modified = 1;
 | 
			
		||||
	}
 | 
			
		||||
	err = 0;
 | 
			
		||||
 | 
			
		||||
	if (tb[IFLA_VF_TX_RATE]) {
 | 
			
		||||
		struct ifla_vf_tx_rate *ivt;
 | 
			
		||||
		ivt = nla_data(tb[IFLA_VF_TX_RATE]);
 | 
			
		||||
		write_lock_bh(&dev_base_lock);
 | 
			
		||||
		if (ops->ndo_set_vf_tx_rate)
 | 
			
		||||
			err = ops->ndo_set_vf_tx_rate(dev, ivt->vf, ivt->rate);
 | 
			
		||||
		write_unlock_bh(&dev_base_lock);
 | 
			
		||||
		if (err < 0)
 | 
			
		||||
			goto errout;
 | 
			
		||||
		modified = 1;
 | 
			
		||||
	}
 | 
			
		||||
	err = 0;
 | 
			
		||||
 | 
			
		||||
errout:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue