Skip to content

Commit 7f7f626

Browse files
committed
Merge branch 'hv_netvsc-fix-multicast-flags-and-sync'
Stephen Hemminger says: ==================== hv_netvsc: fix multicast flags and sync This set of patches deals with the handling of multicast flags and addresses in transparent VF mode. The recent set of patches (in linux-net) had a couple of bugs. ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents 652dfb2 + b0dee79 commit 7f7f626

File tree

3 files changed

+21
-7
lines changed

3 files changed

+21
-7
lines changed

drivers/net/hyperv/hyperv_net.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,7 @@ struct rndis_device {
173173
struct list_head req_list;
174174

175175
struct work_struct mcast_work;
176+
u32 filter;
176177

177178
bool link_state; /* 0 - link up, 1 - link down */
178179

drivers/net/hyperv/netvsc_drv.c

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,15 +89,20 @@ static void netvsc_change_rx_flags(struct net_device *net, int change)
8989
static void netvsc_set_rx_mode(struct net_device *net)
9090
{
9191
struct net_device_context *ndev_ctx = netdev_priv(net);
92-
struct net_device *vf_netdev = rtnl_dereference(ndev_ctx->vf_netdev);
93-
struct netvsc_device *nvdev = rtnl_dereference(ndev_ctx->nvdev);
92+
struct net_device *vf_netdev;
93+
struct netvsc_device *nvdev;
9494

95+
rcu_read_lock();
96+
vf_netdev = rcu_dereference(ndev_ctx->vf_netdev);
9597
if (vf_netdev) {
9698
dev_uc_sync(vf_netdev, net);
9799
dev_mc_sync(vf_netdev, net);
98100
}
99101

100-
rndis_filter_update(nvdev);
102+
nvdev = rcu_dereference(ndev_ctx->nvdev);
103+
if (nvdev)
104+
rndis_filter_update(nvdev);
105+
rcu_read_unlock();
101106
}
102107

103108
static int netvsc_open(struct net_device *net)
@@ -1846,8 +1851,12 @@ static void __netvsc_vf_setup(struct net_device *ndev,
18461851

18471852
/* set multicast etc flags on VF */
18481853
dev_change_flags(vf_netdev, ndev->flags | IFF_SLAVE);
1854+
1855+
/* sync address list from ndev to VF */
1856+
netif_addr_lock_bh(ndev);
18491857
dev_uc_sync(vf_netdev, ndev);
18501858
dev_mc_sync(vf_netdev, ndev);
1859+
netif_addr_unlock_bh(ndev);
18511860

18521861
if (netif_running(ndev)) {
18531862
ret = dev_open(vf_netdev);

drivers/net/hyperv/rndis_filter.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -825,13 +825,15 @@ static int rndis_filter_set_packet_filter(struct rndis_device *dev,
825825
struct rndis_set_request *set;
826826
int ret;
827827

828+
if (dev->filter == new_filter)
829+
return 0;
830+
828831
request = get_rndis_request(dev, RNDIS_MSG_SET,
829832
RNDIS_MESSAGE_SIZE(struct rndis_set_request) +
830833
sizeof(u32));
831834
if (!request)
832835
return -ENOMEM;
833836

834-
835837
/* Setup the rndis set */
836838
set = &request->request_msg.msg.set_req;
837839
set->oid = RNDIS_OID_GEN_CURRENT_PACKET_FILTER;
@@ -842,8 +844,10 @@ static int rndis_filter_set_packet_filter(struct rndis_device *dev,
842844
&new_filter, sizeof(u32));
843845

844846
ret = rndis_filter_send_request(dev, request);
845-
if (ret == 0)
847+
if (ret == 0) {
846848
wait_for_completion(&request->wait_event);
849+
dev->filter = new_filter;
850+
}
847851

848852
put_rndis_request(dev, request);
849853

@@ -861,9 +865,9 @@ static void rndis_set_multicast(struct work_struct *w)
861865
filter = NDIS_PACKET_TYPE_PROMISCUOUS;
862866
} else {
863867
if (flags & IFF_ALLMULTI)
864-
flags |= NDIS_PACKET_TYPE_ALL_MULTICAST;
868+
filter |= NDIS_PACKET_TYPE_ALL_MULTICAST;
865869
if (flags & IFF_BROADCAST)
866-
flags |= NDIS_PACKET_TYPE_BROADCAST;
870+
filter |= NDIS_PACKET_TYPE_BROADCAST;
867871
}
868872

869873
rndis_filter_set_packet_filter(rdev, filter);

0 commit comments

Comments
 (0)