Skip to content

Commit fe36cbe

Browse files
committed
virtio_net: clear MTU when out of range
virtio attempts to clear the MTU feature bit if the value is out of the supported range, but this has no real effect since FEATURES_OK has already been set. Fix this up by checking the MTU in the new validate callback. Fixes: 14de9d1 ("virtio-net: Add initial MTU advice feature") Signed-off-by: Michael S. Tsirkin <[email protected]>
1 parent 404123c commit fe36cbe

File tree

1 file changed

+30
-11
lines changed

1 file changed

+30
-11
lines changed

drivers/net/virtio_net.c

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2230,14 +2230,8 @@ static bool virtnet_validate_features(struct virtio_device *vdev)
22302230
#define MIN_MTU ETH_MIN_MTU
22312231
#define MAX_MTU ETH_MAX_MTU
22322232

2233-
static int virtnet_probe(struct virtio_device *vdev)
2233+
static int virtnet_validate(struct virtio_device *vdev)
22342234
{
2235-
int i, err;
2236-
struct net_device *dev;
2237-
struct virtnet_info *vi;
2238-
u16 max_queue_pairs;
2239-
int mtu;
2240-
22412235
if (!vdev->config->get) {
22422236
dev_err(&vdev->dev, "%s failure: config access disabled\n",
22432237
__func__);
@@ -2247,6 +2241,25 @@ static int virtnet_probe(struct virtio_device *vdev)
22472241
if (!virtnet_validate_features(vdev))
22482242
return -EINVAL;
22492243

2244+
if (virtio_has_feature(vdev, VIRTIO_NET_F_MTU)) {
2245+
int mtu = virtio_cread16(vdev,
2246+
offsetof(struct virtio_net_config,
2247+
mtu));
2248+
if (mtu < MIN_MTU)
2249+
__virtio_clear_bit(vdev, VIRTIO_NET_F_MTU);
2250+
}
2251+
2252+
return 0;
2253+
}
2254+
2255+
static int virtnet_probe(struct virtio_device *vdev)
2256+
{
2257+
int i, err;
2258+
struct net_device *dev;
2259+
struct virtnet_info *vi;
2260+
u16 max_queue_pairs;
2261+
int mtu;
2262+
22502263
/* Find if host supports multiqueue virtio_net device */
22512264
err = virtio_cread_feature(vdev, VIRTIO_NET_F_MQ,
22522265
struct virtio_net_config,
@@ -2362,12 +2375,17 @@ static int virtnet_probe(struct virtio_device *vdev)
23622375
offsetof(struct virtio_net_config,
23632376
mtu));
23642377
if (mtu < dev->min_mtu) {
2365-
__virtio_clear_bit(vdev, VIRTIO_NET_F_MTU);
2366-
} else {
2367-
dev->mtu = mtu;
2368-
dev->max_mtu = mtu;
2378+
/* Should never trigger: MTU was previously validated
2379+
* in virtnet_validate.
2380+
*/
2381+
dev_err(&vdev->dev, "device MTU appears to have changed "
2382+
"it is now %d < %d", mtu, dev->min_mtu);
2383+
goto free_stats;
23692384
}
23702385

2386+
dev->mtu = mtu;
2387+
dev->max_mtu = mtu;
2388+
23712389
/* TODO: size buffers correctly in this case. */
23722390
if (dev->mtu > ETH_DATA_LEN)
23732391
vi->big_packets = true;
@@ -2548,6 +2566,7 @@ static struct virtio_driver virtio_net_driver = {
25482566
.driver.name = KBUILD_MODNAME,
25492567
.driver.owner = THIS_MODULE,
25502568
.id_table = id_table,
2569+
.validate = virtnet_validate,
25512570
.probe = virtnet_probe,
25522571
.remove = virtnet_remove,
25532572
.config_changed = virtnet_config_changed,

0 commit comments

Comments
 (0)