aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/hyperv
diff options
context:
space:
mode:
authorHaiyang Zhang <haiyangz@microsoft.com>2011-11-30 10:19:08 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2011-12-01 13:25:26 -0500
commitd426b2e3d91f8ec3203f8852e7ad0153b5dfdf71 (patch)
tree331e51d5ef01679b32ab28e2832eeedc8a9b23bc /drivers/net/hyperv
parentc18132005e711c07523d8c6602e5b2266ab9a0f2 (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')
-rw-r--r--drivers/net/hyperv/hyperv_net.h24
-rw-r--r--drivers/net/hyperv/netvsc_drv.c46
-rw-r--r--drivers/net/hyperv/rndis_filter.c23
3 files changed, 68 insertions, 25 deletions
diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
index ac1ec8405124..49b131f71d7a 100644
--- a/drivers/net/hyperv/hyperv_net.h
+++ b/drivers/net/hyperv/hyperv_net.h
@@ -87,6 +87,27 @@ struct netvsc_device_info {
87 int ring_size; 87 int ring_size;
88}; 88};
89 89
90enum rndis_device_state {
91 RNDIS_DEV_UNINITIALIZED = 0,
92 RNDIS_DEV_INITIALIZING,
93 RNDIS_DEV_INITIALIZED,
94 RNDIS_DEV_DATAINITIALIZED,
95};
96
97struct rndis_device {
98 struct netvsc_device *net_dev;
99
100 enum rndis_device_state state;
101 bool link_state;
102 atomic_t new_req_id;
103
104 spinlock_t request_lock;
105 struct list_head req_list;
106
107 unsigned char hw_mac_adr[ETH_ALEN];
108};
109
110
90/* Interface */ 111/* Interface */
91int netvsc_device_add(struct hv_device *device, void *additional_info); 112int netvsc_device_add(struct hv_device *device, void *additional_info);
92int netvsc_device_remove(struct hv_device *device); 113int netvsc_device_remove(struct hv_device *device);
@@ -109,6 +130,9 @@ int rndis_filter_receive(struct hv_device *dev,
109int rndis_filter_send(struct hv_device *dev, 130int rndis_filter_send(struct hv_device *dev,
110 struct hv_netvsc_packet *pkt); 131 struct hv_netvsc_packet *pkt);
111 132
133int rndis_filter_set_packet_filter(struct rndis_device *dev, u32 new_filter);
134
135
112#define NVSP_INVALID_PROTOCOL_VERSION ((u32)0xFFFFFFFF) 136#define NVSP_INVALID_PROTOCOL_VERSION ((u32)0xFFFFFFFF)
113 137
114#define NVSP_PROTOCOL_VERSION_1 2 138#define NVSP_PROTOCOL_VERSION_1 2
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;
56module_param(ring_size, int, S_IRUGO); 56module_param(ring_size, int, S_IRUGO);
57MODULE_PARM_DESC(ring_size, "Ring buffer size (# of pages)"); 57MODULE_PARM_DESC(ring_size, "Ring buffer size (# of pages)");
58 58
59/* no-op so the netdev core doesn't return -EINVAL when modifying the the 59struct set_multicast_work {
60 * multicast address list in SIOCADDMULTI. hv is setup to get all multicast 60 struct work_struct work;
61 * when it calls RndisFilterOnOpen() */ 61 struct net_device *net;
62};
63
64static void do_set_multicast(struct work_struct *w)
65{
66 struct set_multicast_work *swk =
67 container_of(w, struct set_multicast_work, work);
68 struct net_device *net = swk->net;
69
70 struct net_device_context *ndevctx = netdev_priv(net);
71 struct netvsc_device *nvdev;
72 struct rndis_device *rdev;
73
74 nvdev = hv_get_drvdata(ndevctx->device_ctx);
75 if (nvdev == NULL)
76 return;
77
78 rdev = nvdev->extension;
79 if (rdev == NULL)
80 return;
81
82 if (net->flags & IFF_PROMISC)
83 rndis_filter_set_packet_filter(rdev,
84 NDIS_PACKET_TYPE_PROMISCUOUS);
85 else
86 rndis_filter_set_packet_filter(rdev,
87 NDIS_PACKET_TYPE_BROADCAST |
88 NDIS_PACKET_TYPE_ALL_MULTICAST |
89 NDIS_PACKET_TYPE_DIRECTED);
90
91 kfree(w);
92}
93
62static void netvsc_set_multicast_list(struct net_device *net) 94static void netvsc_set_multicast_list(struct net_device *net)
63{ 95{
96 struct set_multicast_work *swk =
97 kmalloc(sizeof(struct set_multicast_work), GFP_ATOMIC);
98 if (swk == NULL)
99 return;
100
101 swk->net = net;
102 INIT_WORK(&swk->work, do_set_multicast);
103 schedule_work(&swk->work);
64} 104}
65 105
66static int netvsc_open(struct net_device *net) 106static int netvsc_open(struct net_device *net)
diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c
index bafccb360041..418e7aac229c 100644
--- a/drivers/net/hyperv/rndis_filter.c
+++ b/drivers/net/hyperv/rndis_filter.c
@@ -30,26 +30,6 @@
30#include "hyperv_net.h" 30#include "hyperv_net.h"
31 31
32 32
33enum rndis_device_state {
34 RNDIS_DEV_UNINITIALIZED = 0,
35 RNDIS_DEV_INITIALIZING,
36 RNDIS_DEV_INITIALIZED,
37 RNDIS_DEV_DATAINITIALIZED,
38};
39
40struct rndis_device {
41 struct netvsc_device *net_dev;
42
43 enum rndis_device_state state;
44 bool link_state;
45 atomic_t new_req_id;
46
47 spinlock_t request_lock;
48 struct list_head req_list;
49
50 unsigned char hw_mac_adr[ETH_ALEN];
51};
52
53struct rndis_request { 33struct rndis_request {
54 struct list_head list_ent; 34 struct list_head list_ent;
55 struct completion wait_event; 35 struct completion wait_event;
@@ -522,8 +502,7 @@ static int rndis_filter_query_device_link_status(struct rndis_device *dev)
522 return ret; 502 return ret;
523} 503}
524 504
525static int rndis_filter_set_packet_filter(struct rndis_device *dev, 505int rndis_filter_set_packet_filter(struct rndis_device *dev, u32 new_filter)
526 u32 new_filter)
527{ 506{
528 struct rndis_request *request; 507 struct rndis_request *request;
529 struct rndis_set_request *set; 508 struct rndis_set_request *set;