Browse Source

[virtio] Use host-specified MTU when available

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 7 years ago
parent
commit
4e85b2708f
2 changed files with 37 additions and 13 deletions
  1. 27
    13
      src/drivers/net/virtio-net.c
  2. 10
    0
      src/drivers/net/virtio-net.h

+ 27
- 13
src/drivers/net/virtio-net.c View File

@@ -77,13 +77,8 @@ enum {
77 77
 	QUEUE_NB
78 78
 };
79 79
 
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
87 82
 
88 83
 struct virtnet_nic {
89 84
 	/** Base pio register address */
@@ -160,12 +155,13 @@ static void virtnet_enqueue_iob ( struct net_device *netdev,
160 155
  */
161 156
 static void virtnet_refill_rx_virtqueue ( struct net_device *netdev ) {
162 157
 	struct virtnet_nic *virtnet = netdev->priv;
158
+	size_t len = ( netdev->max_pkt_len + 4 /* VLAN */ );
163 159
 
164 160
 	while ( virtnet->rx_num_iobufs < NUM_RX_BUF ) {
165 161
 		struct io_buffer *iobuf;
166 162
 
167 163
 		/* Try to allocate a buffer, stop for now if out of memory */
168
-		iobuf = alloc_iob ( RX_BUF_SIZE );
164
+		iobuf = alloc_iob ( len );
169 165
 		if ( ! iobuf )
170 166
 			break;
171 167
 
@@ -173,7 +169,7 @@ static void virtnet_refill_rx_virtqueue ( struct net_device *netdev ) {
173 169
 		list_add ( &iobuf->list, &virtnet->rx_iobufs );
174 170
 
175 171
 		/* Mark packet length until we know the actual size */
176
-		iob_put ( iobuf, RX_BUF_SIZE );
172
+		iob_put ( iobuf, len );
177 173
 
178 174
 		virtnet_enqueue_iob ( netdev, RX_INDEX, iobuf );
179 175
 		virtnet->rx_num_iobufs++;
@@ -237,7 +233,8 @@ static int virtnet_open_legacy ( struct net_device *netdev ) {
237 233
 
238 234
 	/* Driver is ready */
239 235
 	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 ) ) );
241 238
 	vp_set_status ( ioaddr, VIRTIO_CONFIG_S_DRIVER | VIRTIO_CONFIG_S_DRIVER_OK );
242 239
 	return 0;
243 240
 }
@@ -260,6 +257,7 @@ static int virtnet_open_modern ( struct net_device *netdev ) {
260 257
 	}
261 258
 	vpm_set_features ( &virtnet->vdev, features & (
262 259
 		( 1ULL << VIRTIO_NET_F_MAC ) |
260
+		( 1ULL << VIRTIO_NET_F_MTU ) |
263 261
 		( 1ULL << VIRTIO_F_VERSION_1 ) |
264 262
 		( 1ULL << VIRTIO_F_ANY_LAYOUT ) ) );
265 263
 	vpm_add_status ( &virtnet->vdev, VIRTIO_CONFIG_S_FEATURES_OK );
@@ -389,7 +387,7 @@ static void virtnet_process_rx_packets ( struct net_device *netdev ) {
389 387
 		virtnet->rx_num_iobufs--;
390 388
 
391 389
 		/* Update iobuf length */
392
-		iob_unput ( iobuf, RX_BUF_SIZE );
390
+		iob_unput ( iobuf, iob_len ( iobuf ) );
393 391
 		iob_put ( iobuf, len - sizeof ( struct virtio_net_hdr ) );
394 392
 
395 393
 		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 ) {
461 459
 	struct net_device *netdev;
462 460
 	struct virtnet_nic *virtnet;
463 461
 	u32 features;
462
+	u16 mtu;
464 463
 	int rc;
465 464
 
466 465
 	/* Allocate and hook up net device */
@@ -480,7 +479,7 @@ static int virtnet_probe_legacy ( struct pci_device *pci ) {
480 479
 	adjust_pci_device ( pci );
481 480
 	vp_reset ( ioaddr );
482 481
 
483
-	/* Load MAC address */
482
+	/* Load MAC address and MTU */
484 483
 	features = vp_get_features ( ioaddr );
485 484
 	if ( features & ( 1 << VIRTIO_NET_F_MAC ) ) {
486 485
 		vp_get ( ioaddr, offsetof ( struct virtio_net_config, mac ),
@@ -488,6 +487,12 @@ static int virtnet_probe_legacy ( struct pci_device *pci ) {
488 487
 		DBGC ( virtnet, "VIRTIO-NET %p mac=%s\n", virtnet,
489 488
 		       eth_ntoa ( netdev->hw_addr ) );
490 489
 	}
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
+	}
491 496
 
492 497
 	/* Register network device */
493 498
 	if ( ( rc = register_netdev ( netdev ) ) != 0 )
@@ -517,6 +522,7 @@ static int virtnet_probe_modern ( struct pci_device *pci, int *found_dev ) {
517 522
 	struct net_device *netdev;
518 523
 	struct virtnet_nic *virtnet;
519 524
 	u64 features;
525
+	u16 mtu;
520 526
 	int rc, common, isr, notify, config, device;
521 527
 
522 528
 	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 ) {
583 589
 	vpm_add_status ( &virtnet->vdev, VIRTIO_CONFIG_S_ACKNOWLEDGE );
584 590
 	vpm_add_status ( &virtnet->vdev, VIRTIO_CONFIG_S_DRIVER );
585 591
 
586
-	/* Load MAC address */
592
+	/* Load MAC address and MTU */
587 593
 	if ( device ) {
588 594
 		features = vpm_get_features ( &virtnet->vdev );
589 595
 		if ( features & ( 1ULL << VIRTIO_NET_F_MAC ) ) {
@@ -593,6 +599,14 @@ static int virtnet_probe_modern ( struct pci_device *pci, int *found_dev ) {
593 599
 			DBGC ( virtnet, "VIRTIO-NET %p mac=%s\n", virtnet,
594 600
 			       eth_ntoa ( netdev->hw_addr ) );
595 601
 		}
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
+		}
596 610
 	}
597 611
 
598 612
 	/* We need a valid MAC address */

+ 10
- 0
src/drivers/net/virtio-net.h View File

@@ -4,6 +4,7 @@
4 4
 /* The feature bitmap for virtio net */
5 5
 #define VIRTIO_NET_F_CSUM       0       /* Host handles pkts w/ partial csum */
6 6
 #define VIRTIO_NET_F_GUEST_CSUM 1       /* Guest handles pkts w/ partial csum */
7
+#define VIRTIO_NET_F_MTU        3       /* Initial MTU advice */
7 8
 #define VIRTIO_NET_F_MAC        5       /* Host has given MAC address. */
8 9
 #define VIRTIO_NET_F_GSO        6       /* Host handles pkts w/ any GSO type */
9 10
 #define VIRTIO_NET_F_GUEST_TSO4 7       /* Guest can handle TSOv4 in. */
@@ -25,6 +26,15 @@ struct virtio_net_config
25 26
 {
26 27
    /* The config defining mac address (if VIRTIO_NET_F_MAC) */
27 28
    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;
28 38
 } __attribute__((packed));
29 39
 
30 40
 /* This is the first element of the scatter-gather list.  If you don't

Loading…
Cancel
Save