[virtio] Use host-specified MTU when available
Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
parent
de85336abb
commit
4e85b2708f
|
@ -77,13 +77,8 @@ enum {
|
||||||
QUEUE_NB
|
QUEUE_NB
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
/** Max number of pending rx packets */
|
||||||
/** Max number of pending rx packets */
|
#define NUM_RX_BUF 8
|
||||||
NUM_RX_BUF = 8,
|
|
||||||
|
|
||||||
/** Max Ethernet frame length, including FCS and VLAN tag */
|
|
||||||
RX_BUF_SIZE = 1522,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct virtnet_nic {
|
struct virtnet_nic {
|
||||||
/** Base pio register address */
|
/** Base pio register address */
|
||||||
|
@ -160,12 +155,13 @@ static void virtnet_enqueue_iob ( struct net_device *netdev,
|
||||||
*/
|
*/
|
||||||
static void virtnet_refill_rx_virtqueue ( struct net_device *netdev ) {
|
static void virtnet_refill_rx_virtqueue ( struct net_device *netdev ) {
|
||||||
struct virtnet_nic *virtnet = netdev->priv;
|
struct virtnet_nic *virtnet = netdev->priv;
|
||||||
|
size_t len = ( netdev->max_pkt_len + 4 /* VLAN */ );
|
||||||
|
|
||||||
while ( virtnet->rx_num_iobufs < NUM_RX_BUF ) {
|
while ( virtnet->rx_num_iobufs < NUM_RX_BUF ) {
|
||||||
struct io_buffer *iobuf;
|
struct io_buffer *iobuf;
|
||||||
|
|
||||||
/* Try to allocate a buffer, stop for now if out of memory */
|
/* Try to allocate a buffer, stop for now if out of memory */
|
||||||
iobuf = alloc_iob ( RX_BUF_SIZE );
|
iobuf = alloc_iob ( len );
|
||||||
if ( ! iobuf )
|
if ( ! iobuf )
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -173,7 +169,7 @@ static void virtnet_refill_rx_virtqueue ( struct net_device *netdev ) {
|
||||||
list_add ( &iobuf->list, &virtnet->rx_iobufs );
|
list_add ( &iobuf->list, &virtnet->rx_iobufs );
|
||||||
|
|
||||||
/* Mark packet length until we know the actual size */
|
/* Mark packet length until we know the actual size */
|
||||||
iob_put ( iobuf, RX_BUF_SIZE );
|
iob_put ( iobuf, len );
|
||||||
|
|
||||||
virtnet_enqueue_iob ( netdev, RX_INDEX, iobuf );
|
virtnet_enqueue_iob ( netdev, RX_INDEX, iobuf );
|
||||||
virtnet->rx_num_iobufs++;
|
virtnet->rx_num_iobufs++;
|
||||||
|
@ -237,7 +233,8 @@ static int virtnet_open_legacy ( struct net_device *netdev ) {
|
||||||
|
|
||||||
/* Driver is ready */
|
/* Driver is ready */
|
||||||
features = vp_get_features ( ioaddr );
|
features = vp_get_features ( ioaddr );
|
||||||
vp_set_features ( ioaddr, features & ( 1 << VIRTIO_NET_F_MAC ) );
|
vp_set_features ( ioaddr, features & ( ( 1 << VIRTIO_NET_F_MAC ) |
|
||||||
|
( 1 << VIRTIO_NET_F_MTU ) ) );
|
||||||
vp_set_status ( ioaddr, VIRTIO_CONFIG_S_DRIVER | VIRTIO_CONFIG_S_DRIVER_OK );
|
vp_set_status ( ioaddr, VIRTIO_CONFIG_S_DRIVER | VIRTIO_CONFIG_S_DRIVER_OK );
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -260,6 +257,7 @@ static int virtnet_open_modern ( struct net_device *netdev ) {
|
||||||
}
|
}
|
||||||
vpm_set_features ( &virtnet->vdev, features & (
|
vpm_set_features ( &virtnet->vdev, features & (
|
||||||
( 1ULL << VIRTIO_NET_F_MAC ) |
|
( 1ULL << VIRTIO_NET_F_MAC ) |
|
||||||
|
( 1ULL << VIRTIO_NET_F_MTU ) |
|
||||||
( 1ULL << VIRTIO_F_VERSION_1 ) |
|
( 1ULL << VIRTIO_F_VERSION_1 ) |
|
||||||
( 1ULL << VIRTIO_F_ANY_LAYOUT ) ) );
|
( 1ULL << VIRTIO_F_ANY_LAYOUT ) ) );
|
||||||
vpm_add_status ( &virtnet->vdev, VIRTIO_CONFIG_S_FEATURES_OK );
|
vpm_add_status ( &virtnet->vdev, VIRTIO_CONFIG_S_FEATURES_OK );
|
||||||
|
@ -389,7 +387,7 @@ static void virtnet_process_rx_packets ( struct net_device *netdev ) {
|
||||||
virtnet->rx_num_iobufs--;
|
virtnet->rx_num_iobufs--;
|
||||||
|
|
||||||
/* Update iobuf length */
|
/* Update iobuf length */
|
||||||
iob_unput ( iobuf, RX_BUF_SIZE );
|
iob_unput ( iobuf, iob_len ( iobuf ) );
|
||||||
iob_put ( iobuf, len - sizeof ( struct virtio_net_hdr ) );
|
iob_put ( iobuf, len - sizeof ( struct virtio_net_hdr ) );
|
||||||
|
|
||||||
DBGC2 ( virtnet, "VIRTIO-NET %p rx complete iobuf %p len %zd\n",
|
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 ) {
|
||||||
struct net_device *netdev;
|
struct net_device *netdev;
|
||||||
struct virtnet_nic *virtnet;
|
struct virtnet_nic *virtnet;
|
||||||
u32 features;
|
u32 features;
|
||||||
|
u16 mtu;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
/* Allocate and hook up net device */
|
/* Allocate and hook up net device */
|
||||||
|
@ -480,7 +479,7 @@ static int virtnet_probe_legacy ( struct pci_device *pci ) {
|
||||||
adjust_pci_device ( pci );
|
adjust_pci_device ( pci );
|
||||||
vp_reset ( ioaddr );
|
vp_reset ( ioaddr );
|
||||||
|
|
||||||
/* Load MAC address */
|
/* Load MAC address and MTU */
|
||||||
features = vp_get_features ( ioaddr );
|
features = vp_get_features ( ioaddr );
|
||||||
if ( features & ( 1 << VIRTIO_NET_F_MAC ) ) {
|
if ( features & ( 1 << VIRTIO_NET_F_MAC ) ) {
|
||||||
vp_get ( ioaddr, offsetof ( struct virtio_net_config, mac ),
|
vp_get ( ioaddr, offsetof ( struct virtio_net_config, mac ),
|
||||||
|
@ -488,6 +487,12 @@ static int virtnet_probe_legacy ( struct pci_device *pci ) {
|
||||||
DBGC ( virtnet, "VIRTIO-NET %p mac=%s\n", virtnet,
|
DBGC ( virtnet, "VIRTIO-NET %p mac=%s\n", virtnet,
|
||||||
eth_ntoa ( netdev->hw_addr ) );
|
eth_ntoa ( netdev->hw_addr ) );
|
||||||
}
|
}
|
||||||
|
if ( features & ( 1ULL << VIRTIO_NET_F_MTU ) ) {
|
||||||
|
vp_get ( ioaddr, offsetof ( struct virtio_net_config, mtu ),
|
||||||
|
&mtu, sizeof ( mtu ) );
|
||||||
|
DBGC ( virtnet, "VIRTIO-NET %p mtu=%d\n", virtnet, mtu );
|
||||||
|
netdev->max_pkt_len = ( mtu + ETH_HLEN );
|
||||||
|
}
|
||||||
|
|
||||||
/* Register network device */
|
/* Register network device */
|
||||||
if ( ( rc = register_netdev ( netdev ) ) != 0 )
|
if ( ( rc = register_netdev ( netdev ) ) != 0 )
|
||||||
|
@ -517,6 +522,7 @@ static int virtnet_probe_modern ( struct pci_device *pci, int *found_dev ) {
|
||||||
struct net_device *netdev;
|
struct net_device *netdev;
|
||||||
struct virtnet_nic *virtnet;
|
struct virtnet_nic *virtnet;
|
||||||
u64 features;
|
u64 features;
|
||||||
|
u16 mtu;
|
||||||
int rc, common, isr, notify, config, device;
|
int rc, common, isr, notify, config, device;
|
||||||
|
|
||||||
common = virtio_pci_find_capability ( pci, VIRTIO_PCI_CAP_COMMON_CFG );
|
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 ) {
|
||||||
vpm_add_status ( &virtnet->vdev, VIRTIO_CONFIG_S_ACKNOWLEDGE );
|
vpm_add_status ( &virtnet->vdev, VIRTIO_CONFIG_S_ACKNOWLEDGE );
|
||||||
vpm_add_status ( &virtnet->vdev, VIRTIO_CONFIG_S_DRIVER );
|
vpm_add_status ( &virtnet->vdev, VIRTIO_CONFIG_S_DRIVER );
|
||||||
|
|
||||||
/* Load MAC address */
|
/* Load MAC address and MTU */
|
||||||
if ( device ) {
|
if ( device ) {
|
||||||
features = vpm_get_features ( &virtnet->vdev );
|
features = vpm_get_features ( &virtnet->vdev );
|
||||||
if ( features & ( 1ULL << VIRTIO_NET_F_MAC ) ) {
|
if ( features & ( 1ULL << VIRTIO_NET_F_MAC ) ) {
|
||||||
|
@ -593,6 +599,14 @@ static int virtnet_probe_modern ( struct pci_device *pci, int *found_dev ) {
|
||||||
DBGC ( virtnet, "VIRTIO-NET %p mac=%s\n", virtnet,
|
DBGC ( virtnet, "VIRTIO-NET %p mac=%s\n", virtnet,
|
||||||
eth_ntoa ( netdev->hw_addr ) );
|
eth_ntoa ( netdev->hw_addr ) );
|
||||||
}
|
}
|
||||||
|
if ( features & ( 1ULL << VIRTIO_NET_F_MTU ) ) {
|
||||||
|
vpm_get ( &virtnet->vdev,
|
||||||
|
offsetof ( struct virtio_net_config, mtu ),
|
||||||
|
&mtu, sizeof ( mtu ) );
|
||||||
|
DBGC ( virtnet, "VIRTIO-NET %p mtu=%d\n", virtnet,
|
||||||
|
mtu );
|
||||||
|
netdev->max_pkt_len = ( mtu + ETH_HLEN );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We need a valid MAC address */
|
/* We need a valid MAC address */
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
/* The feature bitmap for virtio net */
|
/* The feature bitmap for virtio net */
|
||||||
#define VIRTIO_NET_F_CSUM 0 /* Host handles pkts w/ partial csum */
|
#define VIRTIO_NET_F_CSUM 0 /* Host handles pkts w/ partial csum */
|
||||||
#define VIRTIO_NET_F_GUEST_CSUM 1 /* Guest handles pkts w/ partial csum */
|
#define VIRTIO_NET_F_GUEST_CSUM 1 /* Guest handles pkts w/ partial csum */
|
||||||
|
#define VIRTIO_NET_F_MTU 3 /* Initial MTU advice */
|
||||||
#define VIRTIO_NET_F_MAC 5 /* Host has given MAC address. */
|
#define VIRTIO_NET_F_MAC 5 /* Host has given MAC address. */
|
||||||
#define VIRTIO_NET_F_GSO 6 /* Host handles pkts w/ any GSO type */
|
#define VIRTIO_NET_F_GSO 6 /* Host handles pkts w/ any GSO type */
|
||||||
#define VIRTIO_NET_F_GUEST_TSO4 7 /* Guest can handle TSOv4 in. */
|
#define VIRTIO_NET_F_GUEST_TSO4 7 /* Guest can handle TSOv4 in. */
|
||||||
|
@ -25,6 +26,15 @@ struct virtio_net_config
|
||||||
{
|
{
|
||||||
/* The config defining mac address (if VIRTIO_NET_F_MAC) */
|
/* The config defining mac address (if VIRTIO_NET_F_MAC) */
|
||||||
u8 mac[6];
|
u8 mac[6];
|
||||||
|
/* See VIRTIO_NET_F_STATUS and VIRTIO_NET_S_* above */
|
||||||
|
u16 status;
|
||||||
|
/* Maximum number of each of transmit and receive queues;
|
||||||
|
* see VIRTIO_NET_F_MQ and VIRTIO_NET_CTRL_MQ.
|
||||||
|
* Legal values are between 1 and 0x8000
|
||||||
|
*/
|
||||||
|
u16 max_virtqueue_pairs;
|
||||||
|
/* Default maximum transmit unit advice */
|
||||||
|
u16 mtu;
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
/* This is the first element of the scatter-gather list. If you don't
|
/* This is the first element of the scatter-gather list. If you don't
|
||||||
|
|
Reference in New Issue