Skip to content

Commit 4e85b27

Browse files
committed
[virtio] Use host-specified MTU when available
Signed-off-by: Michael Brown <mcb30@ipxe.org>
1 parent de85336 commit 4e85b27

File tree

2 files changed

+37
-13
lines changed

2 files changed

+37
-13
lines changed

src/drivers/net/virtio-net.c

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -77,13 +77,8 @@ enum {
7777
QUEUE_NB
7878
};
7979

80-
enum {
81-
/** Max number of pending rx packets */
82-
NUM_RX_BUF = 8,
83-
84-
/** Max Ethernet frame length, including FCS and VLAN tag */
85-
RX_BUF_SIZE = 1522,
86-
};
80+
/** Max number of pending rx packets */
81+
#define NUM_RX_BUF 8
8782

8883
struct virtnet_nic {
8984
/** Base pio register address */
@@ -160,20 +155,21 @@ static void virtnet_enqueue_iob ( struct net_device *netdev,
160155
*/
161156
static void virtnet_refill_rx_virtqueue ( struct net_device *netdev ) {
162157
struct virtnet_nic *virtnet = netdev->priv;
158+
size_t len = ( netdev->max_pkt_len + 4 /* VLAN */ );
163159

164160
while ( virtnet->rx_num_iobufs < NUM_RX_BUF ) {
165161
struct io_buffer *iobuf;
166162

167163
/* Try to allocate a buffer, stop for now if out of memory */
168-
iobuf = alloc_iob ( RX_BUF_SIZE );
164+
iobuf = alloc_iob ( len );
169165
if ( ! iobuf )
170166
break;
171167

172168
/* Keep track of iobuf so close() can free it */
173169
list_add ( &iobuf->list, &virtnet->rx_iobufs );
174170

175171
/* Mark packet length until we know the actual size */
176-
iob_put ( iobuf, RX_BUF_SIZE );
172+
iob_put ( iobuf, len );
177173

178174
virtnet_enqueue_iob ( netdev, RX_INDEX, iobuf );
179175
virtnet->rx_num_iobufs++;
@@ -237,7 +233,8 @@ static int virtnet_open_legacy ( struct net_device *netdev ) {
237233

238234
/* Driver is ready */
239235
features = vp_get_features ( ioaddr );
240-
vp_set_features ( ioaddr, features & ( 1 << VIRTIO_NET_F_MAC ) );
236+
vp_set_features ( ioaddr, features & ( ( 1 << VIRTIO_NET_F_MAC ) |
237+
( 1 << VIRTIO_NET_F_MTU ) ) );
241238
vp_set_status ( ioaddr, VIRTIO_CONFIG_S_DRIVER | VIRTIO_CONFIG_S_DRIVER_OK );
242239
return 0;
243240
}
@@ -260,6 +257,7 @@ static int virtnet_open_modern ( struct net_device *netdev ) {
260257
}
261258
vpm_set_features ( &virtnet->vdev, features & (
262259
( 1ULL << VIRTIO_NET_F_MAC ) |
260+
( 1ULL << VIRTIO_NET_F_MTU ) |
263261
( 1ULL << VIRTIO_F_VERSION_1 ) |
264262
( 1ULL << VIRTIO_F_ANY_LAYOUT ) ) );
265263
vpm_add_status ( &virtnet->vdev, VIRTIO_CONFIG_S_FEATURES_OK );
@@ -389,7 +387,7 @@ static void virtnet_process_rx_packets ( struct net_device *netdev ) {
389387
virtnet->rx_num_iobufs--;
390388

391389
/* Update iobuf length */
392-
iob_unput ( iobuf, RX_BUF_SIZE );
390+
iob_unput ( iobuf, iob_len ( iobuf ) );
393391
iob_put ( iobuf, len - sizeof ( struct virtio_net_hdr ) );
394392

395393
DBGC2 ( virtnet, "VIRTIO-NET %p rx complete iobuf %p len %zd\n",
@@ -461,6 +459,7 @@ static int virtnet_probe_legacy ( struct pci_device *pci ) {
461459
struct net_device *netdev;
462460
struct virtnet_nic *virtnet;
463461
u32 features;
462+
u16 mtu;
464463
int rc;
465464

466465
/* Allocate and hook up net device */
@@ -480,14 +479,20 @@ static int virtnet_probe_legacy ( struct pci_device *pci ) {
480479
adjust_pci_device ( pci );
481480
vp_reset ( ioaddr );
482481

483-
/* Load MAC address */
482+
/* Load MAC address and MTU */
484483
features = vp_get_features ( ioaddr );
485484
if ( features & ( 1 << VIRTIO_NET_F_MAC ) ) {
486485
vp_get ( ioaddr, offsetof ( struct virtio_net_config, mac ),
487486
netdev->hw_addr, ETH_ALEN );
488487
DBGC ( virtnet, "VIRTIO-NET %p mac=%s\n", virtnet,
489488
eth_ntoa ( netdev->hw_addr ) );
490489
}
490+
if ( features & ( 1ULL << VIRTIO_NET_F_MTU ) ) {
491+
vp_get ( ioaddr, offsetof ( struct virtio_net_config, mtu ),
492+
&mtu, sizeof ( mtu ) );
493+
DBGC ( virtnet, "VIRTIO-NET %p mtu=%d\n", virtnet, mtu );
494+
netdev->max_pkt_len = ( mtu + ETH_HLEN );
495+
}
491496

492497
/* Register network device */
493498
if ( ( rc = register_netdev ( netdev ) ) != 0 )
@@ -517,6 +522,7 @@ static int virtnet_probe_modern ( struct pci_device *pci, int *found_dev ) {
517522
struct net_device *netdev;
518523
struct virtnet_nic *virtnet;
519524
u64 features;
525+
u16 mtu;
520526
int rc, common, isr, notify, config, device;
521527

522528
common = virtio_pci_find_capability ( pci, VIRTIO_PCI_CAP_COMMON_CFG );
@@ -583,7 +589,7 @@ static int virtnet_probe_modern ( struct pci_device *pci, int *found_dev ) {
583589
vpm_add_status ( &virtnet->vdev, VIRTIO_CONFIG_S_ACKNOWLEDGE );
584590
vpm_add_status ( &virtnet->vdev, VIRTIO_CONFIG_S_DRIVER );
585591

586-
/* Load MAC address */
592+
/* Load MAC address and MTU */
587593
if ( device ) {
588594
features = vpm_get_features ( &virtnet->vdev );
589595
if ( features & ( 1ULL << VIRTIO_NET_F_MAC ) ) {
@@ -593,6 +599,14 @@ static int virtnet_probe_modern ( struct pci_device *pci, int *found_dev ) {
593599
DBGC ( virtnet, "VIRTIO-NET %p mac=%s\n", virtnet,
594600
eth_ntoa ( netdev->hw_addr ) );
595601
}
602+
if ( features & ( 1ULL << VIRTIO_NET_F_MTU ) ) {
603+
vpm_get ( &virtnet->vdev,
604+
offsetof ( struct virtio_net_config, mtu ),
605+
&mtu, sizeof ( mtu ) );
606+
DBGC ( virtnet, "VIRTIO-NET %p mtu=%d\n", virtnet,
607+
mtu );
608+
netdev->max_pkt_len = ( mtu + ETH_HLEN );
609+
}
596610
}
597611

598612
/* We need a valid MAC address */

src/drivers/net/virtio-net.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
/* The feature bitmap for virtio net */
55
#define VIRTIO_NET_F_CSUM 0 /* Host handles pkts w/ partial csum */
66
#define VIRTIO_NET_F_GUEST_CSUM 1 /* Guest handles pkts w/ partial csum */
7+
#define VIRTIO_NET_F_MTU 3 /* Initial MTU advice */
78
#define VIRTIO_NET_F_MAC 5 /* Host has given MAC address. */
89
#define VIRTIO_NET_F_GSO 6 /* Host handles pkts w/ any GSO type */
910
#define VIRTIO_NET_F_GUEST_TSO4 7 /* Guest can handle TSOv4 in. */
@@ -25,6 +26,15 @@ struct virtio_net_config
2526
{
2627
/* The config defining mac address (if VIRTIO_NET_F_MAC) */
2728
u8 mac[6];
29+
/* See VIRTIO_NET_F_STATUS and VIRTIO_NET_S_* above */
30+
u16 status;
31+
/* Maximum number of each of transmit and receive queues;
32+
* see VIRTIO_NET_F_MQ and VIRTIO_NET_CTRL_MQ.
33+
* Legal values are between 1 and 0x8000
34+
*/
35+
u16 max_virtqueue_pairs;
36+
/* Default maximum transmit unit advice */
37+
u16 mtu;
2838
} __attribute__((packed));
2939

3040
/* This is the first element of the scatter-gather list. If you don't

0 commit comments

Comments
 (0)