virtio-net: Support for setting MAC addresses of the virtio-net interfaces.

Refers to https://docs.oasis-open.org/virtio/virtio/v1.2/cs01/virtio-v1.2-cs01.html#x1-2230004
A driver SHOULD negotiate VIRTIO_NET_F_MAC if the device offers it.
If the driver negotiates the VIRTIO_NET_F_MAC feature, the driver MUST
set the physical address of the NIC to mac. Otherwise, it SHOULD use a
locally-administered MAC address.

Signed-off-by: liqinhui <liqinhui@xiaomi.com>
This commit is contained in:
liqinhui 2023-12-04 14:21:45 +08:00 committed by Xiang Xiao
parent 681b84b15d
commit 73ceb049af

View File

@ -39,6 +39,8 @@
* Pre-processor Definitions
****************************************************************************/
#define VIRTIO_NET_F_MAC 5
/* Virtio net header size and packet buffer size */
#define VIRTIO_NET_HDRSIZE (sizeof(struct virtio_net_hdr_s))
@ -74,6 +76,24 @@ begin_packed_struct struct virtio_net_hdr_s
uint16_t csum_offset;
} end_packed_struct;
/* The definition of the struct virtio_net_config refers to the link
* https://docs.oasis-open.org/virtio/virtio/v1.2/cs01/
* virtio-v1.2-cs01.html#x1-2230004.
*/
begin_packed_struct struct virtio_net_config_s
{
uint8_t mac[IFHWADDRLEN]; /* VIRTIO_NET_F_MAC */
uint16_t status; /* VIRTIO_NET_F_STATUS */
uint16_t max_virtqueue_pairs; /* VIRTIO_NET_F_MQ */
uint16_t mtu; /* VIRTIO_NET_F_MTU */
uint32_t speed; /* VIRTIO_NET_F_SPEED_DUPLEX */
uint8_t duplex;
uint8_t rss_max_key_size; /* VIRTIO_NET_F_RSS */
uint16_t rss_max_indirection_table_length;
uint32_t supported_hash_types;
} end_packed_struct;
struct virtio_net_priv_s
{
/* This holds the information visible to the NuttX network */
@ -487,7 +507,7 @@ static int virtio_net_init(FAR struct virtio_net_priv_s *priv,
/* Initialize the virtio device */
virtio_set_status(vdev, VIRTIO_CONFIG_STATUS_DRIVER);
virtio_set_features(vdev, 0);
virtio_negotiate_features(vdev, 1 << VIRTIO_NET_F_MAC);
virtio_set_status(vdev, VIRTIO_CONFIG_FEATURES_OK);
vqnames[VIRTIO_NET_RX] = "virtio_net_rx";
@ -520,6 +540,42 @@ static int virtio_net_init(FAR struct virtio_net_priv_s *priv,
return OK;
}
static void virtio_net_set_macaddr(FAR struct virtio_net_priv_s *priv)
{
FAR struct net_driver_s *dev = &priv->lower.netdev;
FAR struct virtio_device *vdev = priv->vdev;
FAR uint8_t *mac = dev->d_mac.ether.ether_addr_octet;
if (virtio_has_feature(vdev, VIRTIO_NET_F_MAC))
{
virtio_read_config(vdev, offsetof(struct virtio_net_config_s, mac),
mac, IFHWADDRLEN);
}
else
{
/* Assign a random locally-created MAC address.
*
* TODO: The generated MAC address should be checked to see if it
* conflicts with something else on the network.
*/
srand(time(NULL) +
#ifdef CONFIG_NETDEV_IFINDEX
dev->d_ifindex
#else
dev % 256
#endif
);
mac[0] = 0x42;
mac[1] = rand() % 256;
mac[2] = rand() % 256;
mac[3] = rand() % 256;
mac[4] = rand() % 256;
mac[5] = rand() % 256;
}
}
/****************************************************************************
* Name: virtio_net_probe
****************************************************************************/
@ -560,6 +616,8 @@ static int virtio_net_probe(FAR struct virtio_device *vdev)
goto err_with_virtqueues;
}
virtio_net_set_macaddr(priv);
return ret;
err_with_virtqueues: