164 lines
4.5 KiB
Diff
164 lines
4.5 KiB
Diff
From: Haiyang Zhang <haiyangz@microsoft.com>
|
|
Date: Wed, 30 Nov 2011 07:19:08 -0800
|
|
Subject: [PATCH 20/77] net/hyperv: Add support for promiscuous mode setting
|
|
|
|
commit d426b2e3d91f8ec3203f8852e7ad0153b5dfdf71 upstream.
|
|
|
|
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>
|
|
---
|
|
drivers/net/hyperv/hyperv_net.h | 24 +++++++++++++++++++
|
|
drivers/net/hyperv/netvsc_drv.c | 46 ++++++++++++++++++++++++++++++++++---
|
|
drivers/net/hyperv/rndis_filter.c | 23 +------------------
|
|
3 files changed, 68 insertions(+), 25 deletions(-)
|
|
|
|
diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
|
|
index ac1ec84..49b131f 100644
|
|
--- a/drivers/net/hyperv/hyperv_net.h
|
|
+++ b/drivers/net/hyperv/hyperv_net.h
|
|
@@ -87,6 +87,27 @@ struct netvsc_device_info {
|
|
int ring_size;
|
|
};
|
|
|
|
+enum rndis_device_state {
|
|
+ RNDIS_DEV_UNINITIALIZED = 0,
|
|
+ RNDIS_DEV_INITIALIZING,
|
|
+ RNDIS_DEV_INITIALIZED,
|
|
+ RNDIS_DEV_DATAINITIALIZED,
|
|
+};
|
|
+
|
|
+struct rndis_device {
|
|
+ struct netvsc_device *net_dev;
|
|
+
|
|
+ enum rndis_device_state state;
|
|
+ bool link_state;
|
|
+ atomic_t new_req_id;
|
|
+
|
|
+ spinlock_t request_lock;
|
|
+ struct list_head req_list;
|
|
+
|
|
+ unsigned char hw_mac_adr[ETH_ALEN];
|
|
+};
|
|
+
|
|
+
|
|
/* Interface */
|
|
int netvsc_device_add(struct hv_device *device, void *additional_info);
|
|
int netvsc_device_remove(struct hv_device *device);
|
|
@@ -109,6 +130,9 @@ int rndis_filter_receive(struct hv_device *dev,
|
|
int rndis_filter_send(struct hv_device *dev,
|
|
struct hv_netvsc_packet *pkt);
|
|
|
|
+int rndis_filter_set_packet_filter(struct rndis_device *dev, u32 new_filter);
|
|
+
|
|
+
|
|
#define NVSP_INVALID_PROTOCOL_VERSION ((u32)0xFFFFFFFF)
|
|
|
|
#define NVSP_PROTOCOL_VERSION_1 2
|
|
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
|
|
index 93b0e91..b69c3a4 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)
|
|
diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c
|
|
index bafccb3..418e7aa 100644
|
|
--- a/drivers/net/hyperv/rndis_filter.c
|
|
+++ b/drivers/net/hyperv/rndis_filter.c
|
|
@@ -30,26 +30,6 @@
|
|
#include "hyperv_net.h"
|
|
|
|
|
|
-enum rndis_device_state {
|
|
- RNDIS_DEV_UNINITIALIZED = 0,
|
|
- RNDIS_DEV_INITIALIZING,
|
|
- RNDIS_DEV_INITIALIZED,
|
|
- RNDIS_DEV_DATAINITIALIZED,
|
|
-};
|
|
-
|
|
-struct rndis_device {
|
|
- struct netvsc_device *net_dev;
|
|
-
|
|
- enum rndis_device_state state;
|
|
- bool link_state;
|
|
- atomic_t new_req_id;
|
|
-
|
|
- spinlock_t request_lock;
|
|
- struct list_head req_list;
|
|
-
|
|
- unsigned char hw_mac_adr[ETH_ALEN];
|
|
-};
|
|
-
|
|
struct rndis_request {
|
|
struct list_head list_ent;
|
|
struct completion wait_event;
|
|
@@ -522,8 +502,7 @@ static int rndis_filter_query_device_link_status(struct rndis_device *dev)
|
|
return ret;
|
|
}
|
|
|
|
-static int rndis_filter_set_packet_filter(struct rndis_device *dev,
|
|
- u32 new_filter)
|
|
+int rndis_filter_set_packet_filter(struct rndis_device *dev, u32 new_filter)
|
|
{
|
|
struct rndis_request *request;
|
|
struct rndis_set_request *set;
|
|
--
|
|
1.7.9.5
|
|
|