The netvsc device should propagate filters to the SR-IOV VF
device (if present). The flags also need to be propagated to the
VF device as well. This only really matters on local Hyper-V
since Azure does not support multiple addresses.

Signed-off-by: Stephen Hemminger <sthem...@microsoft.com>
---
 drivers/net/hyperv/netvsc_drv.c | 40 ++++++++++++++++++++++++++++++++++++----
 1 file changed, 36 insertions(+), 4 deletions(-)

diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index 5299cfb16ce2..cdb78eefab67 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -66,10 +66,36 @@ static int debug = -1;
 module_param(debug, int, S_IRUGO);
 MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
 
-static void netvsc_set_multicast_list(struct net_device *net)
+static void netvsc_change_rx_flags(struct net_device *net, int change)
 {
-       struct net_device_context *net_device_ctx = netdev_priv(net);
-       struct netvsc_device *nvdev = rtnl_dereference(net_device_ctx->nvdev);
+       struct net_device_context *ndev_ctx = netdev_priv(net);
+       struct net_device *vf_netdev = rtnl_dereference(ndev_ctx->vf_netdev);
+       int inc;
+
+       if (!vf_netdev)
+               return;
+
+       if (change & IFF_PROMISC) {
+               inc = (net->flags & IFF_PROMISC) ? 1 : -1;
+               dev_set_promiscuity(vf_netdev, inc);
+       }
+
+       if (change & IFF_ALLMULTI) {
+               inc = (net->flags & IFF_ALLMULTI) ? 1 : -1;
+               dev_set_allmulti(vf_netdev, inc);
+       }
+}
+
+static void netvsc_set_rx_mode(struct net_device *net)
+{
+       struct net_device_context *ndev_ctx = netdev_priv(net);
+       struct net_device *vf_netdev = rtnl_dereference(ndev_ctx->vf_netdev);
+       struct netvsc_device *nvdev = rtnl_dereference(ndev_ctx->nvdev);
+
+       if (vf_netdev) {
+               dev_uc_sync(vf_netdev, net);
+               dev_mc_sync(vf_netdev, net);
+       }
 
        rndis_filter_update(nvdev);
 }
@@ -1586,7 +1612,8 @@ static const struct net_device_ops device_ops = {
        .ndo_open =                     netvsc_open,
        .ndo_stop =                     netvsc_close,
        .ndo_start_xmit =               netvsc_start_xmit,
-       .ndo_set_rx_mode =              netvsc_set_multicast_list,
+       .ndo_change_rx_flags =          netvsc_change_rx_flags,
+       .ndo_set_rx_mode =              netvsc_set_rx_mode,
        .ndo_change_mtu =               netvsc_change_mtu,
        .ndo_validate_addr =            eth_validate_addr,
        .ndo_set_mac_address =          netvsc_set_mac_addr,
@@ -1817,6 +1844,11 @@ static void __netvsc_vf_setup(struct net_device *ndev,
                netdev_warn(vf_netdev,
                            "unable to change mtu to %u\n", ndev->mtu);
 
+       /* set multicast etc flags on VF */
+       dev_change_flags(vf_netdev, ndev->flags | IFF_SLAVE);
+       dev_uc_sync(vf_netdev, ndev);
+       dev_mc_sync(vf_netdev, ndev);
+
        if (netif_running(ndev)) {
                ret = dev_open(vf_netdev);
                if (ret)
-- 
2.16.1

_______________________________________________
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

Reply via email to