diff options
| author | Haiyang Zhang <haiyangz@microsoft.com> | 2011-11-30 10:19:08 -0500 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@suse.de> | 2011-12-01 13:25:26 -0500 |
| commit | d426b2e3d91f8ec3203f8852e7ad0153b5dfdf71 (patch) | |
| tree | 331e51d5ef01679b32ab28e2832eeedc8a9b23bc /drivers/net/hyperv | |
| 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')
| -rw-r--r-- | drivers/net/hyperv/hyperv_net.h | 24 | ||||
| -rw-r--r-- | drivers/net/hyperv/netvsc_drv.c | 46 | ||||
| -rw-r--r-- | 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 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 | ||
| 90 | enum rndis_device_state { | ||
| 91 | RNDIS_DEV_UNINITIALIZED = 0, | ||
| 92 | RNDIS_DEV_INITIALIZING, | ||
| 93 | RNDIS_DEV_INITIALIZED, | ||
| 94 | RNDIS_DEV_DATAINITIALIZED, | ||
| 95 | }; | ||
| 96 | |||
| 97 | struct 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 */ |
| 91 | int netvsc_device_add(struct hv_device *device, void *additional_info); | 112 | int netvsc_device_add(struct hv_device *device, void *additional_info); |
| 92 | int netvsc_device_remove(struct hv_device *device); | 113 | int netvsc_device_remove(struct hv_device *device); |
| @@ -109,6 +130,9 @@ int rndis_filter_receive(struct hv_device *dev, | |||
| 109 | int rndis_filter_send(struct hv_device *dev, | 130 | int rndis_filter_send(struct hv_device *dev, |
| 110 | struct hv_netvsc_packet *pkt); | 131 | struct hv_netvsc_packet *pkt); |
| 111 | 132 | ||
| 133 | int 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; | |||
| 56 | module_param(ring_size, int, S_IRUGO); | 56 | module_param(ring_size, int, S_IRUGO); |
| 57 | MODULE_PARM_DESC(ring_size, "Ring buffer size (# of pages)"); | 57 | MODULE_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 | 59 | struct 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 | |||
| 64 | static 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 | |||
| 62 | static void netvsc_set_multicast_list(struct net_device *net) | 94 | static 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 | ||
| 66 | static int netvsc_open(struct net_device *net) | 106 | 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 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 | ||
| 33 | enum rndis_device_state { | ||
| 34 | RNDIS_DEV_UNINITIALIZED = 0, | ||
| 35 | RNDIS_DEV_INITIALIZING, | ||
| 36 | RNDIS_DEV_INITIALIZED, | ||
| 37 | RNDIS_DEV_DATAINITIALIZED, | ||
| 38 | }; | ||
| 39 | |||
| 40 | struct 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 | |||
| 53 | struct rndis_request { | 33 | struct 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 | ||
| 525 | static int rndis_filter_set_packet_filter(struct rndis_device *dev, | 505 | int 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; |
