hv_netvsc: fix network namespace issues with VF support
[ Upstream commit 7bf7bb37f16a80465ee3bd7c6c966f96f5a075a6 ] When finding the parent netvsc device, the search needs to be across all netvsc device instances (independent of network namespace). Find parent device of VF using upper_dev_get routine which searches only adjacent list. Fixes: e8ff40d4bff1 ("hv_netvsc: improve VF device matching") Signed-off-by: Stephen Hemminger <sthemmin@microsoft.com> netns aware byref Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Sasha Levin <alexander.levin@microsoft.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
51b6940707
commit
0a84c912f5
@ -724,6 +724,8 @@ struct net_device_context {
|
||||
struct hv_device *device_ctx;
|
||||
/* netvsc_device */
|
||||
struct netvsc_device __rcu *nvdev;
|
||||
/* list of netvsc net_devices */
|
||||
struct list_head list;
|
||||
/* reconfigure work */
|
||||
struct delayed_work dwork;
|
||||
/* last reconfig time */
|
||||
|
@ -66,6 +66,8 @@ static int debug = -1;
|
||||
module_param(debug, int, S_IRUGO);
|
||||
MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
|
||||
|
||||
static LIST_HEAD(netvsc_dev_list);
|
||||
|
||||
static void netvsc_change_rx_flags(struct net_device *net, int change)
|
||||
{
|
||||
struct net_device_context *ndev_ctx = netdev_priv(net);
|
||||
@ -1749,13 +1751,10 @@ out_unlock:
|
||||
|
||||
static struct net_device *get_netvsc_bymac(const u8 *mac)
|
||||
{
|
||||
struct net_device *dev;
|
||||
struct net_device_context *ndev_ctx;
|
||||
|
||||
ASSERT_RTNL();
|
||||
|
||||
for_each_netdev(&init_net, dev) {
|
||||
if (dev->netdev_ops != &device_ops)
|
||||
continue; /* not a netvsc device */
|
||||
list_for_each_entry(ndev_ctx, &netvsc_dev_list, list) {
|
||||
struct net_device *dev = hv_get_drvdata(ndev_ctx->device_ctx);
|
||||
|
||||
if (ether_addr_equal(mac, dev->perm_addr))
|
||||
return dev;
|
||||
@ -1766,25 +1765,18 @@ static struct net_device *get_netvsc_bymac(const u8 *mac)
|
||||
|
||||
static struct net_device *get_netvsc_byref(struct net_device *vf_netdev)
|
||||
{
|
||||
struct net_device_context *net_device_ctx;
|
||||
struct net_device *dev;
|
||||
|
||||
ASSERT_RTNL();
|
||||
dev = netdev_master_upper_dev_get(vf_netdev);
|
||||
if (!dev || dev->netdev_ops != &device_ops)
|
||||
return NULL; /* not a netvsc device */
|
||||
|
||||
for_each_netdev(&init_net, dev) {
|
||||
struct net_device_context *net_device_ctx;
|
||||
net_device_ctx = netdev_priv(dev);
|
||||
if (!rtnl_dereference(net_device_ctx->nvdev))
|
||||
return NULL; /* device is removed */
|
||||
|
||||
if (dev->netdev_ops != &device_ops)
|
||||
continue; /* not a netvsc device */
|
||||
|
||||
net_device_ctx = netdev_priv(dev);
|
||||
if (!rtnl_dereference(net_device_ctx->nvdev))
|
||||
continue; /* device is removed */
|
||||
|
||||
if (rtnl_dereference(net_device_ctx->vf_netdev) == vf_netdev)
|
||||
return dev; /* a match */
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return dev;
|
||||
}
|
||||
|
||||
/* Called when VF is injecting data into network stack.
|
||||
@ -2065,15 +2057,19 @@ static int netvsc_probe(struct hv_device *dev,
|
||||
else
|
||||
net->max_mtu = ETH_DATA_LEN;
|
||||
|
||||
ret = register_netdev(net);
|
||||
rtnl_lock();
|
||||
ret = register_netdevice(net);
|
||||
if (ret != 0) {
|
||||
pr_err("Unable to register netdev.\n");
|
||||
goto register_failed;
|
||||
}
|
||||
|
||||
return ret;
|
||||
list_add(&net_device_ctx->list, &netvsc_dev_list);
|
||||
rtnl_unlock();
|
||||
return 0;
|
||||
|
||||
register_failed:
|
||||
rtnl_unlock();
|
||||
rndis_filter_device_remove(dev, nvdev);
|
||||
rndis_failed:
|
||||
free_percpu(net_device_ctx->vf_stats);
|
||||
@ -2119,6 +2115,7 @@ static int netvsc_remove(struct hv_device *dev)
|
||||
rndis_filter_device_remove(dev, nvdev);
|
||||
|
||||
unregister_netdevice(net);
|
||||
list_del(&ndev_ctx->list);
|
||||
|
||||
rtnl_unlock();
|
||||
rcu_read_unlock();
|
||||
|
Loading…
x
Reference in New Issue
Block a user