virtio_net 设备的队列数问题()

virtio_net设备的其他问题:见 https://www.cnblogs.com/10087622blog/p/15886345.html

一个virtio_net设备在 virtnet_probe 的时候,会 读取 VIRTIO_NET_F_MQ 特性

此时的max_queue_pairs 是取决于后端dev的特性。

/* Find if host supports multiqueue virtio_net device */ 	err = virtio_cread_feature(vdev, VIRTIO_NET_F_MQ, 				   struct virtio_net_config, 				   max_virtqueue_pairs, &max_queue_pairs);//caq:是否支持多队列,如果支持则获取到队列数

然后在sysfs中生效查看的队列数,是以 dev之后的队列总数和当前online的cpu核数的小值为current 生效值。

`
/* Enable multiqueue by default */
if (num_online_cpus() >= max_queue_pairs)//caq:cpu数大于队列数
vi->curr_queue_pairs = max_queue_pairs;//caq:则取小值
else
vi->curr_queue_pairs = num_online_cpus();//caq:否则取cpu数,也是小值
vi->max_queue_pairs = max_queue_pairs;//caq:max还是记录设备层的

/* Allocate/initialize the rx/tx queues, and invoke find_vqs */
err = init_vqs(vi);//caq:vq的获取和配置,回调 find_vqs
if (err)
	goto free;

ifdef CONFIG_SYSFS

if (vi->mergeable_rx_bufs)
	dev->sysfs_rx_queue_group = &virtio_net_mrg_rx_group;

endif//caq:真正在 sysfs中生效的队列个数是以 max_queue_pairs 和 num_online_cpus 的小值决定的

netif_set_real_num_tx_queues(dev, vi->curr_queue_pairs);//caq:实际使用的队列个数
netif_set_real_num_rx_queues(dev, vi->curr_queue_pairs);//caq:实际使用的队列个数设置为real 队列数

int netif_set_real_num_rx_queues(struct net_device *dev, unsigned int rxq)
{
int rc;

netif_set_real_num_rx_queues的实现如下:
if (rxq < 1 || rxq > dev->num_rx_queues)
	return -EINVAL;

if (dev->reg_state == NETREG_REGISTERED) {--------------//caq:如果注册过,则走更新流程
	ASSERT_RTNL();

	rc = net_rx_queue_update_kobjects(dev, dev->real_num_rx_queues,
					  rxq);
	if (rc)
		return rc;
}

dev->real_num_rx_queues = rxq;//caq:否则走设置流程
return 0;

}

//caq:申请queue的管理空间
static int virtnet_alloc_queues(struct virtnet_info *vi)
{
int i;

而针对virtio层,申请 virtio的queue的时候,却是使用的 max_queue_pairs。
vi->ctrl = kzalloc(sizeof(*vi->ctrl), GFP_KERNEL);
if (!vi->ctrl)//caq:control_buf 内存申请
	goto err_ctrl;
vi->sq = kcalloc(vi->max_queue_pairs, sizeof(*vi->sq), GFP_KERNEL);//caq:按照max_queue_pairs来申请queue资源
if (!vi->sq)//caq:sq管理数组
	goto err_sq;
vi->rq = kcalloc(vi->max_queue_pairs, sizeof(*vi->rq), GFP_KERNEL);
if (!vi->rq)//caq:rq管理数组
	goto err_rq;

`
所以会经常看到,申请中断的时候,如果是per vq per irq资源申请成功,则在 /proc/interrupts 中看到的该virtio设备的队列个数却有可能远远大于 真正生效的net的queue的个数。

————————

virtio_net设备的其他问题:见 https://www.cnblogs.com/10087622blog/p/15886345.html

一个virtio_net设备在 virtnet_probe 的时候,会 读取 VIRTIO_NET_F_MQ 特性

此时的max_queue_pairs 是取决于后端dev的特性。

/* Find if host supports multiqueue virtio_net device */ 	err = virtio_cread_feature(vdev, VIRTIO_NET_F_MQ, 				   struct virtio_net_config, 				   max_virtqueue_pairs, &max_queue_pairs);//caq:是否支持多队列,如果支持则获取到队列数

然后在sysfs中生效查看的队列数,是以 dev之后的队列总数和当前online的cpu核数的小值为current 生效值。

`
/* Enable multiqueue by default */
if (num_online_cpus() >= max_queue_pairs)//caq:cpu数大于队列数
vi->curr_queue_pairs = max_queue_pairs;//caq:则取小值
else
vi->curr_queue_pairs = num_online_cpus();//caq:否则取cpu数,也是小值
vi->max_queue_pairs = max_queue_pairs;//caq:max还是记录设备层的

/* Allocate/initialize the rx/tx queues, and invoke find_vqs */
err = init_vqs(vi);//caq:vq的获取和配置,回调 find_vqs
if (err)
	goto free;

ifdef CONFIG_SYSFS

if (vi->mergeable_rx_bufs)
	dev->sysfs_rx_queue_group = &virtio_net_mrg_rx_group;

endif//caq:真正在 sysfs中生效的队列个数是以 max_queue_pairs 和 num_online_cpus 的小值决定的

netif_set_real_num_tx_queues(dev, vi->curr_queue_pairs);//caq:实际使用的队列个数
netif_set_real_num_rx_queues(dev, vi->curr_queue_pairs);//caq:实际使用的队列个数设置为real 队列数

int netif_set_real_num_rx_queues(struct net_device *dev, unsigned int rxq)
{
int rc;

netif_set_real_num_rx_queues的实现如下:
if (rxq < 1 || rxq > dev->num_rx_queues)
	return -EINVAL;

if (dev->reg_state == NETREG_REGISTERED) {--------------//caq:如果注册过,则走更新流程
	ASSERT_RTNL();

	rc = net_rx_queue_update_kobjects(dev, dev->real_num_rx_queues,
					  rxq);
	if (rc)
		return rc;
}

dev->real_num_rx_queues = rxq;//caq:否则走设置流程
return 0;

}

//caq:申请queue的管理空间
static int virtnet_alloc_queues(struct virtnet_info *vi)
{
int i;

而针对virtio层,申请 virtio的queue的时候,却是使用的 max_queue_pairs。
vi->ctrl = kzalloc(sizeof(*vi->ctrl), GFP_KERNEL);
if (!vi->ctrl)//caq:control_buf 内存申请
	goto err_ctrl;
vi->sq = kcalloc(vi->max_queue_pairs, sizeof(*vi->sq), GFP_KERNEL);//caq:按照max_queue_pairs来申请queue资源
if (!vi->sq)//caq:sq管理数组
	goto err_sq;
vi->rq = kcalloc(vi->max_queue_pairs, sizeof(*vi->rq), GFP_KERNEL);
if (!vi->rq)//caq:rq管理数组
	goto err_rq;

`
所以会经常看到,申请中断的时候,如果是per vq per irq资源申请成功,则在 /proc/interrupts 中看到的该virtio设备的队列个数却有可能远远大于 真正生效的net的queue的个数。