Thread (5 messages) 5 messages, 3 authors, 2011-11-30

[PATCH 2/2] net/hyperv: Add support for promiscuous mode setting

From: Haiyang Zhang <haiyangz@microsoft.com>
Date: 2011-11-30 15:44:41
Also in: lkml
Subsystem: hyper-v/azure core and drivers, networking drivers, the rest · Maintainers: "K. Y. Srinivasan", Haiyang Zhang, Wei Liu, Dexuan Cui, Long Li, Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds

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>
---
 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.4.1
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help