lkml.org 
[lkml]   [2018]   [Aug]   [1]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.14 022/246] hv_netvsc: fix network namespace issues with VF support
    Date
    4.14-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Stephen Hemminger <stephen@networkplumber.org>

    [ 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>
    ---
    drivers/net/hyperv/hyperv_net.h | 2 +
    drivers/net/hyperv/netvsc_drv.c | 45 ++++++++++++++++++----------------------
    2 files changed, 23 insertions(+), 24 deletions(-)

    --- a/drivers/net/hyperv/hyperv_net.h
    +++ b/drivers/net/hyperv/hyperv_net.h
    @@ -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 */
    --- a/drivers/net/hyperv/netvsc_drv.c
    +++ b/drivers/net/hyperv/netvsc_drv.c
    @@ -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;
    -
    - ASSERT_RTNL();
    + struct net_device_context *ndev_ctx;

    - 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_bym

    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();
    -
    - for_each_netdev(&init_net, dev) {
    - struct net_device_context *net_device_ctx;
    -
    - 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 */
    + dev = netdev_master_upper_dev_get(vf_netdev);
    + if (!dev || dev->netdev_ops != &device_ops)
    + return NULL; /* not a netvsc device */
    +
    + net_device_ctx = netdev_priv(dev);
    + if (!rtnl_dereference(net_device_ctx->nvdev))
    + return NULL; /* 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
    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_devic
    rndis_filter_device_remove(dev, nvdev);

    unregister_netdevice(net);
    + list_del(&ndev_ctx->list);

    rtnl_unlock();
    rcu_read_unlock();

    \
     
     \ /
      Last update: 2018-08-01 20:09    [W:2.762 / U:0.568 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site