Skip to content

Commit e8ff40d

Browse files
shemmingerdavem330
authored andcommitted
hv_netvsc: improve VF device matching
The code to associate netvsc and VF devices can be made less error prone by using a better matching algorithms. On registration, use the permanent address which avoids any possible issues caused by device MAC address being changed. For all other callbacks, search by the netdevice pointer value to ensure getting the correct network device. Signed-off-by: Stephen Hemminger <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent ee837a1 commit e8ff40d

File tree

1 file changed

+39
-21
lines changed

1 file changed

+39
-21
lines changed

drivers/net/hyperv/netvsc_drv.c

Lines changed: 39 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1215,22 +1215,44 @@ static void netvsc_free_netdev(struct net_device *netdev)
12151215
free_netdev(netdev);
12161216
}
12171217

1218-
static struct net_device *get_netvsc_net_device(char *mac)
1218+
static struct net_device *get_netvsc_bymac(const u8 *mac)
12191219
{
1220-
struct net_device *dev, *found = NULL;
1220+
struct net_device *dev;
12211221

12221222
ASSERT_RTNL();
12231223

12241224
for_each_netdev(&init_net, dev) {
1225-
if (memcmp(dev->dev_addr, mac, ETH_ALEN) == 0) {
1226-
if (dev->netdev_ops != &device_ops)
1227-
continue;
1228-
found = dev;
1229-
break;
1230-
}
1225+
if (dev->netdev_ops != &device_ops)
1226+
continue; /* not a netvsc device */
1227+
1228+
if (ether_addr_equal(mac, dev->perm_addr))
1229+
return dev;
1230+
}
1231+
1232+
return NULL;
1233+
}
1234+
1235+
static struct net_device *get_netvsc_byref(const struct net_device *vf_netdev)
1236+
{
1237+
struct net_device *dev;
1238+
1239+
ASSERT_RTNL();
1240+
1241+
for_each_netdev(&init_net, dev) {
1242+
struct net_device_context *net_device_ctx;
1243+
1244+
if (dev->netdev_ops != &device_ops)
1245+
continue; /* not a netvsc device */
1246+
1247+
net_device_ctx = netdev_priv(dev);
1248+
if (net_device_ctx->nvdev == NULL)
1249+
continue; /* device is removed */
1250+
1251+
if (net_device_ctx->vf_netdev == vf_netdev)
1252+
return dev; /* a match */
12311253
}
12321254

1233-
return found;
1255+
return NULL;
12341256
}
12351257

12361258
static int netvsc_register_vf(struct net_device *vf_netdev)
@@ -1239,12 +1261,15 @@ static int netvsc_register_vf(struct net_device *vf_netdev)
12391261
struct net_device_context *net_device_ctx;
12401262
struct netvsc_device *netvsc_dev;
12411263

1264+
if (vf_netdev->addr_len != ETH_ALEN)
1265+
return NOTIFY_DONE;
1266+
12421267
/*
12431268
* We will use the MAC address to locate the synthetic interface to
12441269
* associate with the VF interface. If we don't find a matching
12451270
* synthetic interface, move on.
12461271
*/
1247-
ndev = get_netvsc_net_device(vf_netdev->dev_addr);
1272+
ndev = get_netvsc_bymac(vf_netdev->perm_addr);
12481273
if (!ndev)
12491274
return NOTIFY_DONE;
12501275

@@ -1284,16 +1309,13 @@ static int netvsc_vf_up(struct net_device *vf_netdev)
12841309
struct netvsc_device *netvsc_dev;
12851310
struct net_device_context *net_device_ctx;
12861311

1287-
ndev = get_netvsc_net_device(vf_netdev->dev_addr);
1312+
ndev = get_netvsc_byref(vf_netdev);
12881313
if (!ndev)
12891314
return NOTIFY_DONE;
12901315

12911316
net_device_ctx = netdev_priv(ndev);
12921317
netvsc_dev = net_device_ctx->nvdev;
12931318

1294-
if (!netvsc_dev || !net_device_ctx->vf_netdev)
1295-
return NOTIFY_DONE;
1296-
12971319
netdev_info(ndev, "VF up: %s\n", vf_netdev->name);
12981320
netvsc_inject_enable(net_device_ctx);
12991321

@@ -1322,16 +1344,13 @@ static int netvsc_vf_down(struct net_device *vf_netdev)
13221344
struct netvsc_device *netvsc_dev;
13231345
struct net_device_context *net_device_ctx;
13241346

1325-
ndev = get_netvsc_net_device(vf_netdev->dev_addr);
1347+
ndev = get_netvsc_byref(vf_netdev);
13261348
if (!ndev)
13271349
return NOTIFY_DONE;
13281350

13291351
net_device_ctx = netdev_priv(ndev);
13301352
netvsc_dev = net_device_ctx->nvdev;
13311353

1332-
if (!netvsc_dev || !net_device_ctx->vf_netdev)
1333-
return NOTIFY_DONE;
1334-
13351354
netdev_info(ndev, "VF down: %s\n", vf_netdev->name);
13361355
netvsc_inject_disable(net_device_ctx);
13371356
netvsc_switch_datapath(ndev, false);
@@ -1351,14 +1370,13 @@ static int netvsc_unregister_vf(struct net_device *vf_netdev)
13511370
struct netvsc_device *netvsc_dev;
13521371
struct net_device_context *net_device_ctx;
13531372

1354-
ndev = get_netvsc_net_device(vf_netdev->dev_addr);
1373+
ndev = get_netvsc_byref(vf_netdev);
13551374
if (!ndev)
13561375
return NOTIFY_DONE;
13571376

13581377
net_device_ctx = netdev_priv(ndev);
13591378
netvsc_dev = net_device_ctx->nvdev;
1360-
if (!netvsc_dev || !net_device_ctx->vf_netdev)
1361-
return NOTIFY_DONE;
1379+
13621380
netdev_info(ndev, "VF unregistering: %s\n", vf_netdev->name);
13631381
netvsc_inject_disable(net_device_ctx);
13641382
net_device_ctx->vf_netdev = NULL;

0 commit comments

Comments
 (0)