diff options
author | Haiyang Zhang <haiyangz@microsoft.com> | 2011-11-30 07:19:08 -0800 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2011-12-01 10:25:26 -0800 |
commit | d426b2e3d91f8ec3203f8852e7ad0153b5dfdf71 (patch) | |
tree | 331e51d5ef01679b32ab28e2832eeedc8a9b23bc /drivers/net/hyperv/netvsc_drv.c | |
parent | c18132005e711c07523d8c6602e5b2266ab9a0f2 (diff) |
net/hyperv: Add support for promiscuous mode setting
Add code to accept promiscuous mode setting, and pass it to
RNDIS filter.
Signed-off-by: Haiyang Zhang <haiyangz@microsoft.com>
Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/net/hyperv/netvsc_drv.c')
-rw-r--r-- | drivers/net/hyperv/netvsc_drv.c | 46 |
1 files changed, 43 insertions, 3 deletions
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c index 93b0e91cbf98..b69c3a4d1e9e 100644 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c @@ -56,11 +56,51 @@ static int ring_size = 128; module_param(ring_size, int, S_IRUGO); MODULE_PARM_DESC(ring_size, "Ring buffer size (# of pages)"); -/* no-op so the netdev core doesn't return -EINVAL when modifying the the - * multicast address list in SIOCADDMULTI. hv is setup to get all multicast - * when it calls RndisFilterOnOpen() */ +struct set_multicast_work { + struct work_struct work; + struct net_device *net; +}; + +static void do_set_multicast(struct work_struct *w) +{ + struct set_multicast_work *swk = + container_of(w, struct set_multicast_work, work); + struct net_device *net = swk->net; + + struct net_device_context *ndevctx = netdev_priv(net); + struct netvsc_device *nvdev; + struct rndis_device *rdev; + + nvdev = hv_get_drvdata(ndevctx->device_ctx); + if (nvdev == NULL) + return; + + rdev = nvdev->extension; + if (rdev == NULL) + return; + + if (net->flags & IFF_PROMISC) + rndis_filter_set_packet_filter(rdev, + NDIS_PACKET_TYPE_PROMISCUOUS); + else + rndis_filter_set_packet_filter(rdev, + NDIS_PACKET_TYPE_BROADCAST | + NDIS_PACKET_TYPE_ALL_MULTICAST | + NDIS_PACKET_TYPE_DIRECTED); + + kfree(w); +} + static void netvsc_set_multicast_list(struct net_device *net) { + struct set_multicast_work *swk = + kmalloc(sizeof(struct set_multicast_work), GFP_ATOMIC); + if (swk == NULL) + return; + + swk->net = net; + INIT_WORK(&swk->work, do_set_multicast); + schedule_work(&swk->work); } static int netvsc_open(struct net_device *net) |