Browse Source

[virtio] Use host-specified MTU when available

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

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

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

Loading…
Cancel
Save