src/dpdk/drivers/net/virtio/virtio_ethdev.c
static int
virtio_dev_configure(struct rte_eth_dev *dev)
{
	const struct rte_eth_rxmode *rxmode = &dev->data->dev_conf.rxmode;
	const struct rte_eth_txmode *txmode = &dev->data->dev_conf.txmode;
	struct virtio_hw *hw = dev->data->dev_private;
	uint32_t ether_hdr_len = RTE_ETHER_HDR_LEN + VLAN_TAG_LEN +
		hw->vtnet_hdr_size;
	uint64_t rx_offloads = rxmode->offloads;
	uint64_t tx_offloads = txmode->offloads;
	uint64_t req_features;
	int ret;

	PMD_INIT_LOG(DEBUG, "configure");
	req_features = VIRTIO_PMD_DEFAULT_GUEST_FEATURES;

	if (rxmode->mq_mode != ETH_MQ_RX_NONE) {
		PMD_DRV_LOG(ERR,
			"Unsupported Rx multi queue mode %d",
			rxmode->mq_mode);
		return -EINVAL;
	}

	if (txmode->mq_mode != ETH_MQ_TX_NONE) {
		PMD_DRV_LOG(ERR,
			"Unsupported Tx multi queue mode %d",
			txmode->mq_mode);
		return -EINVAL;
	}

	if (dev->data->dev_conf.intr_conf.rxq) {
		ret = virtio_init_device(dev, hw->req_guest_features);
		if (ret < 0)
			return ret;
	}

	if (rxmode->max_rx_pkt_len > hw->max_mtu + ether_hdr_len)
		req_features &= ~(1ULL << VIRTIO_NET_F_MTU);

	if (rx_offloads & (DEV_RX_OFFLOAD_UDP_CKSUM |
			   DEV_RX_OFFLOAD_TCP_CKSUM))
		req_features |= (1ULL << VIRTIO_NET_F_GUEST_CSUM);

	if (rx_offloads & DEV_RX_OFFLOAD_TCP_LRO)
		req_features |=
			(1ULL << VIRTIO_NET_F_GUEST_TSO4) |
			(1ULL << VIRTIO_NET_F_GUEST_TSO6);

	if (tx_offloads & (DEV_TX_OFFLOAD_UDP_CKSUM |
			   DEV_TX_OFFLOAD_TCP_CKSUM))
		req_features |= (1ULL << VIRTIO_NET_F_CSUM);

	if (tx_offloads & DEV_TX_OFFLOAD_TCP_TSO)
		req_features |=
			(1ULL << VIRTIO_NET_F_HOST_TSO4) |
			(1ULL << VIRTIO_NET_F_HOST_TSO6);

	/* if request features changed, reinit the device */
	if (req_features != hw->req_guest_features) {
		ret = virtio_init_device(dev, req_features);
		if (ret < 0)
			return ret;
	}

	if ((rx_offloads & (DEV_RX_OFFLOAD_UDP_CKSUM |
			    DEV_RX_OFFLOAD_TCP_CKSUM)) &&
		!virtio_with_feature(hw, VIRTIO_NET_F_GUEST_CSUM)) {
		PMD_DRV_LOG(ERR,
			"rx checksum not available on this host");
		return -ENOTSUP;
	}

	if ((rx_offloads & DEV_RX_OFFLOAD_TCP_LRO) &&
		(!virtio_with_feature(hw, VIRTIO_NET_F_GUEST_TSO4) ||
		 !virtio_with_feature(hw, VIRTIO_NET_F_GUEST_TSO6))) {
		PMD_DRV_LOG(ERR,
			"Large Receive Offload not available on this host");
		return -ENOTSUP;
	}

	/* start control queue */
	if (virtio_with_feature(hw, VIRTIO_NET_F_CTRL_VQ))
		virtio_dev_cq_start(dev);

	if (rx_offloads & DEV_RX_OFFLOAD_VLAN_STRIP)
		hw->vlan_strip = 1;

	if ((rx_offloads & DEV_RX_OFFLOAD_VLAN_FILTER) &&
			!virtio_with_feature(hw, VIRTIO_NET_F_CTRL_VLAN)) {
		PMD_DRV_LOG(ERR,
			    "vlan filtering not available on this host");
		return -ENOTSUP;
	}

	hw->has_tx_offload = tx_offload_enabled(hw);
	hw->has_rx_offload = rx_offload_enabled(hw);

	if (dev->data->dev_flags & RTE_ETH_DEV_INTR_LSC)
		/* Enable vector (0) for Link State Intrerrupt */
		if (VIRTIO_OPS(hw)->set_config_irq(hw, 0) ==
				VIRTIO_MSI_NO_VECTOR) {
			PMD_DRV_LOG(ERR, "failed to set config vector");
			return -EBUSY;
		}

	if (virtio_with_packed_queue(hw)) {
#if defined(RTE_ARCH_X86_64) && defined(CC_AVX512_SUPPORT)
		if ((hw->use_vec_rx || hw->use_vec_tx) &&
		    (!rte_cpu_get_flag_enabled(RTE_CPUFLAG_AVX512F) ||
		     !virtio_with_feature(hw, VIRTIO_F_IN_ORDER) ||
		     !virtio_with_feature(hw, VIRTIO_F_VERSION_1) ||
		     rte_vect_get_max_simd_bitwidth() < RTE_VECT_SIMD_512)) {
			PMD_DRV_LOG(INFO,
				"disabled packed ring vectorized path for requirements not met");
			hw->use_vec_rx = 0;
			hw->use_vec_tx = 0;
		}
#elif defined(RTE_ARCH_ARM)
		if ((hw->use_vec_rx || hw->use_vec_tx) &&
		    (!rte_cpu_get_flag_enabled(RTE_CPUFLAG_NEON) ||
		     !virtio_with_feature(hw, VIRTIO_F_IN_ORDER) ||
		     !virtio_with_feature(hw, VIRTIO_F_VERSION_1) ||
		     rte_vect_get_max_simd_bitwidth() < RTE_VECT_SIMD_128)) {
			PMD_DRV_LOG(INFO,
				"disabled packed ring vectorized path for requirements not met");
			hw->use_vec_rx = 0;
			hw->use_vec_tx = 0;
		}
#else
		hw->use_vec_rx = 0;
		hw->use_vec_tx = 0;
#endif

		if (hw->use_vec_rx) {
			if (virtio_with_feature(hw, VIRTIO_NET_F_MRG_RXBUF)) {
				PMD_DRV_LOG(INFO,
					"disabled packed ring vectorized rx for mrg_rxbuf enabled");
				hw->use_vec_rx = 0;
			}

			if (rx_offloads & DEV_RX_OFFLOAD_TCP_LRO) {
				PMD_DRV_LOG(INFO,
					"disabled packed ring vectorized rx for TCP_LRO enabled");
				hw->use_vec_rx = 0;
			}
		}
	} else {
		if (virtio_with_feature(hw, VIRTIO_F_IN_ORDER)) {
			hw->use_inorder_tx = 1;
			hw->use_inorder_rx = 1;
			hw->use_vec_rx = 0;
		}

		if (hw->use_vec_rx) {
#if defined RTE_ARCH_ARM
			if (!rte_cpu_get_flag_enabled(RTE_CPUFLAG_NEON)) {
				PMD_DRV_LOG(INFO,
					"disabled split ring vectorized path for requirement not met");
				hw->use_vec_rx = 0;
			}
#endif
			if (virtio_with_feature(hw, VIRTIO_NET_F_MRG_RXBUF)) {
				PMD_DRV_LOG(INFO,
					"disabled split ring vectorized rx for mrg_rxbuf enabled");
				hw->use_vec_rx = 0;
			}

			if (rx_offloads & (DEV_RX_OFFLOAD_UDP_CKSUM |
					   DEV_RX_OFFLOAD_TCP_CKSUM |
					   DEV_RX_OFFLOAD_TCP_LRO |
					   DEV_RX_OFFLOAD_VLAN_STRIP)) {
				PMD_DRV_LOG(INFO,
					"disabled split ring vectorized rx for offloading enabled");
				hw->use_vec_rx = 0;
			}

			if (rte_vect_get_max_simd_bitwidth() < RTE_VECT_SIMD_128) {
				PMD_DRV_LOG(INFO,
					"disabled split ring vectorized rx, max SIMD bitwidth too low");
				hw->use_vec_rx = 0;
			}
		}
	}

	return 0;
}
/*
 * Configure virtio device
 * It returns 0 on success.
 */
Configure virtio device
It returns 0 on success.
Configure virtio device It returns 0 on success .
static int
virtio_dev_configure(struct rte_eth_dev *dev)
{
	const struct rte_eth_rxmode *rxmode = &dev->data->dev_conf.rxmode;
	const struct rte_eth_txmode *txmode = &dev->data->dev_conf.txmode;
	struct virtio_hw *hw = dev->data->dev_private;
	uint32_t ether_hdr_len = RTE_ETHER_HDR_LEN + VLAN_TAG_LEN +
		hw->vtnet_hdr_size;
	uint64_t rx_offloads = rxmode->offloads;
	uint64_t tx_offloads = txmode->offloads;
	uint64_t req_features;
	int ret;
	PMD_INIT_LOG(DEBUG, "configure");
	req_features = VIRTIO_PMD_DEFAULT_GUEST_FEATURES;
	if (rxmode->mq_mode != ETH_MQ_RX_NONE) {
		PMD_DRV_LOG(ERR,
			"Unsupported Rx multi queue mode %d",
			rxmode->mq_mode);
		return -EINVAL;
	}
	if (txmode->mq_mode != ETH_MQ_TX_NONE) {
		PMD_DRV_LOG(ERR,
			"Unsupported Tx multi queue mode %d",
			txmode->mq_mode);
		return -EINVAL;
	}
	if (dev->data->dev_conf.intr_conf.rxq) {
		ret = virtio_init_device(dev, hw->req_guest_features);
		if (ret < 0)
			return ret;
	}
	if (rxmode->max_rx_pkt_len > hw->max_mtu + ether_hdr_len)
		req_features &= ~(1ULL << VIRTIO_NET_F_MTU);
	if (rx_offloads & (DEV_RX_OFFLOAD_UDP_CKSUM |
			   DEV_RX_OFFLOAD_TCP_CKSUM))
		req_features |= (1ULL << VIRTIO_NET_F_GUEST_CSUM);
	if (rx_offloads & DEV_RX_OFFLOAD_TCP_LRO)
		req_features |=
			(1ULL << VIRTIO_NET_F_GUEST_TSO4) |
			(1ULL << VIRTIO_NET_F_GUEST_TSO6);
	if (tx_offloads & (DEV_TX_OFFLOAD_UDP_CKSUM |
			   DEV_TX_OFFLOAD_TCP_CKSUM))
		req_features |= (1ULL << VIRTIO_NET_F_CSUM);
	if (tx_offloads & DEV_TX_OFFLOAD_TCP_TSO)
		req_features |=
			(1ULL << VIRTIO_NET_F_HOST_TSO4) |
			(1ULL << VIRTIO_NET_F_HOST_TSO6);
	if (req_features != hw->req_guest_features) {
		ret = virtio_init_device(dev, req_features);
		if (ret < 0)
			return ret;
	}
	if ((rx_offloads & (DEV_RX_OFFLOAD_UDP_CKSUM |
			    DEV_RX_OFFLOAD_TCP_CKSUM)) &&
		!virtio_with_feature(hw, VIRTIO_NET_F_GUEST_CSUM)) {
		PMD_DRV_LOG(ERR,
			"rx checksum not available on this host");
		return -ENOTSUP;
	}
	if ((rx_offloads & DEV_RX_OFFLOAD_TCP_LRO) &&
		(!virtio_with_feature(hw, VIRTIO_NET_F_GUEST_TSO4) ||
		 !virtio_with_feature(hw, VIRTIO_NET_F_GUEST_TSO6))) {
		PMD_DRV_LOG(ERR,
			"Large Receive Offload not available on this host");
		return -ENOTSUP;
	}
	if (virtio_with_feature(hw, VIRTIO_NET_F_CTRL_VQ))
		virtio_dev_cq_start(dev);
	if (rx_offloads & DEV_RX_OFFLOAD_VLAN_STRIP)
		hw->vlan_strip = 1;
	if ((rx_offloads & DEV_RX_OFFLOAD_VLAN_FILTER) &&
			!virtio_with_feature(hw, VIRTIO_NET_F_CTRL_VLAN)) {
		PMD_DRV_LOG(ERR,
			    "vlan filtering not available on this host");
		return -ENOTSUP;
	}
	hw->has_tx_offload = tx_offload_enabled(hw);
	hw->has_rx_offload = rx_offload_enabled(hw);
	if (dev->data->dev_flags & RTE_ETH_DEV_INTR_LSC)
		if (VIRTIO_OPS(hw)->set_config_irq(hw, 0) ==
				VIRTIO_MSI_NO_VECTOR) {
			PMD_DRV_LOG(ERR, "failed to set config vector");
			return -EBUSY;
		}
	if (virtio_with_packed_queue(hw)) {
#if defined(RTE_ARCH_X86_64) && defined(CC_AVX512_SUPPORT)
		if ((hw->use_vec_rx || hw->use_vec_tx) &&
		    (!rte_cpu_get_flag_enabled(RTE_CPUFLAG_AVX512F) ||
		     !virtio_with_feature(hw, VIRTIO_F_IN_ORDER) ||
		     !virtio_with_feature(hw, VIRTIO_F_VERSION_1) ||
		     rte_vect_get_max_simd_bitwidth() < RTE_VECT_SIMD_512)) {
			PMD_DRV_LOG(INFO,
				"disabled packed ring vectorized path for requirements not met");
			hw->use_vec_rx = 0;
			hw->use_vec_tx = 0;
		}
#elif defined(RTE_ARCH_ARM)
		if ((hw->use_vec_rx || hw->use_vec_tx) &&
		    (!rte_cpu_get_flag_enabled(RTE_CPUFLAG_NEON) ||
		     !virtio_with_feature(hw, VIRTIO_F_IN_ORDER) ||
		     !virtio_with_feature(hw, VIRTIO_F_VERSION_1) ||
		     rte_vect_get_max_simd_bitwidth() < RTE_VECT_SIMD_128)) {
			PMD_DRV_LOG(INFO,
				"disabled packed ring vectorized path for requirements not met");
			hw->use_vec_rx = 0;
			hw->use_vec_tx = 0;
		}
#else
		hw->use_vec_rx = 0;
		hw->use_vec_tx = 0;
#endif
		if (hw->use_vec_rx) {
			if (virtio_with_feature(hw, VIRTIO_NET_F_MRG_RXBUF)) {
				PMD_DRV_LOG(INFO,
					"disabled packed ring vectorized rx for mrg_rxbuf enabled");
				hw->use_vec_rx = 0;
			}
			if (rx_offloads & DEV_RX_OFFLOAD_TCP_LRO) {
				PMD_DRV_LOG(INFO,
					"disabled packed ring vectorized rx for TCP_LRO enabled");
				hw->use_vec_rx = 0;
			}
		}
	} else {
		if (virtio_with_feature(hw, VIRTIO_F_IN_ORDER)) {
			hw->use_inorder_tx = 1;
			hw->use_inorder_rx = 1;
			hw->use_vec_rx = 0;
		}
		if (hw->use_vec_rx) {
#if defined RTE_ARCH_ARM
			if (!rte_cpu_get_flag_enabled(RTE_CPUFLAG_NEON)) {
				PMD_DRV_LOG(INFO,
					"disabled split ring vectorized path for requirement not met");
				hw->use_vec_rx = 0;
			}
#endif
			if (virtio_with_feature(hw, VIRTIO_NET_F_MRG_RXBUF)) {
				PMD_DRV_LOG(INFO,
					"disabled split ring vectorized rx for mrg_rxbuf enabled");
				hw->use_vec_rx = 0;
			}
			if (rx_offloads & (DEV_RX_OFFLOAD_UDP_CKSUM |
					   DEV_RX_OFFLOAD_TCP_CKSUM |
					   DEV_RX_OFFLOAD_TCP_LRO |
					   DEV_RX_OFFLOAD_VLAN_STRIP)) {
				PMD_DRV_LOG(INFO,
					"disabled split ring vectorized rx for offloading enabled");
				hw->use_vec_rx = 0;
			}
			if (rte_vect_get_max_simd_bitwidth() < RTE_VECT_SIMD_128) {
				PMD_DRV_LOG(INFO,
					"disabled split ring vectorized rx, max SIMD bitwidth too low");
				hw->use_vec_rx = 0;
			}
		}
	}
	return 0;
}
static int virtio_dev_configure ( struct rte_eth_dev * dev ) { const struct rte_eth_rxmode * rxmode = & dev -> data -> dev_conf . rxmode ; const struct rte_eth_txmode * txmode = & dev -> data -> dev_conf . txmode ; struct virtio_hw * hw = dev -> data -> dev_private ; uint32_t ether_hdr_len = RTE_ETHER_HDR_LEN + VLAN_TAG_LEN + hw -> vtnet_hdr_size ; uint64_t rx_offloads = rxmode -> offloads ; uint64_t tx_offloads = txmode -> offloads ; uint64_t req_features ; int ret ; PMD_INIT_LOG ( DEBUG , " " ) ; req_features = VIRTIO_PMD_DEFAULT_GUEST_FEATURES ; if ( rxmode -> mq_mode != ETH_MQ_RX_NONE ) { PMD_DRV_LOG ( ERR , " " , rxmode -> mq_mode ) ; return - EINVAL ; } if ( txmode -> mq_mode != ETH_MQ_TX_NONE ) { PMD_DRV_LOG ( ERR , " " , txmode -> mq_mode ) ; return - EINVAL ; } if ( dev -> data -> dev_conf . intr_conf . rxq ) { ret = virtio_init_device ( dev , hw -> req_guest_features ) ; if ( ret < 0 ) return ret ; } if ( rxmode -> max_rx_pkt_len > hw -> max_mtu + ether_hdr_len ) req_features &= ~ ( 1ULL << VIRTIO_NET_F_MTU ) ; if ( rx_offloads & ( DEV_RX_OFFLOAD_UDP_CKSUM | DEV_RX_OFFLOAD_TCP_CKSUM ) ) req_features |= ( 1ULL << VIRTIO_NET_F_GUEST_CSUM ) ; if ( rx_offloads & DEV_RX_OFFLOAD_TCP_LRO ) req_features |= ( 1ULL << VIRTIO_NET_F_GUEST_TSO4 ) | ( 1ULL << VIRTIO_NET_F_GUEST_TSO6 ) ; if ( tx_offloads & ( DEV_TX_OFFLOAD_UDP_CKSUM | DEV_TX_OFFLOAD_TCP_CKSUM ) ) req_features |= ( 1ULL << VIRTIO_NET_F_CSUM ) ; if ( tx_offloads & DEV_TX_OFFLOAD_TCP_TSO ) req_features |= ( 1ULL << VIRTIO_NET_F_HOST_TSO4 ) | ( 1ULL << VIRTIO_NET_F_HOST_TSO6 ) ; if ( req_features != hw -> req_guest_features ) { ret = virtio_init_device ( dev , req_features ) ; if ( ret < 0 ) return ret ; } if ( ( rx_offloads & ( DEV_RX_OFFLOAD_UDP_CKSUM | DEV_RX_OFFLOAD_TCP_CKSUM ) ) && ! virtio_with_feature ( hw , VIRTIO_NET_F_GUEST_CSUM ) ) { PMD_DRV_LOG ( ERR , " " ) ; return - ENOTSUP ; } if ( ( rx_offloads & DEV_RX_OFFLOAD_TCP_LRO ) && ( ! virtio_with_feature ( hw , VIRTIO_NET_F_GUEST_TSO4 ) || ! virtio_with_feature ( hw , VIRTIO_NET_F_GUEST_TSO6 ) ) ) { PMD_DRV_LOG ( ERR , " " ) ; return - ENOTSUP ; } if ( virtio_with_feature ( hw , VIRTIO_NET_F_CTRL_VQ ) ) virtio_dev_cq_start ( dev ) ; if ( rx_offloads & DEV_RX_OFFLOAD_VLAN_STRIP ) hw -> vlan_strip = 1 ; if ( ( rx_offloads & DEV_RX_OFFLOAD_VLAN_FILTER ) && ! virtio_with_feature ( hw , VIRTIO_NET_F_CTRL_VLAN ) ) { PMD_DRV_LOG ( ERR , " " ) ; return - ENOTSUP ; } hw -> has_tx_offload = tx_offload_enabled ( hw ) ; hw -> has_rx_offload = rx_offload_enabled ( hw ) ; if ( dev -> data -> dev_flags & RTE_ETH_DEV_INTR_LSC ) if ( VIRTIO_OPS ( hw ) -> set_config_irq ( hw , 0 ) == VIRTIO_MSI_NO_VECTOR ) { PMD_DRV_LOG ( ERR , " " ) ; return - EBUSY ; } if ( virtio_with_packed_queue ( hw ) ) { #if defined ( RTE_ARCH_X86_64 ) && defined ( CC_AVX512_SUPPORT ) if ( ( hw -> use_vec_rx || hw -> use_vec_tx ) && ( ! rte_cpu_get_flag_enabled ( RTE_CPUFLAG_AVX512F ) || ! virtio_with_feature ( hw , VIRTIO_F_IN_ORDER ) || ! virtio_with_feature ( hw , VIRTIO_F_VERSION_1 ) || rte_vect_get_max_simd_bitwidth ( ) < RTE_VECT_SIMD_512 ) ) { PMD_DRV_LOG ( INFO , " " ) ; hw -> use_vec_rx = 0 ; hw -> use_vec_tx = 0 ; } #elif defined ( RTE_ARCH_ARM ) if ( ( hw -> use_vec_rx || hw -> use_vec_tx ) && ( ! rte_cpu_get_flag_enabled ( RTE_CPUFLAG_NEON ) || ! virtio_with_feature ( hw , VIRTIO_F_IN_ORDER ) || ! virtio_with_feature ( hw , VIRTIO_F_VERSION_1 ) || rte_vect_get_max_simd_bitwidth ( ) < RTE_VECT_SIMD_128 ) ) { PMD_DRV_LOG ( INFO , " " ) ; hw -> use_vec_rx = 0 ; hw -> use_vec_tx = 0 ; } #else hw -> use_vec_rx = 0 ; hw -> use_vec_tx = 0 ; #endif if ( hw -> use_vec_rx ) { if ( virtio_with_feature ( hw , VIRTIO_NET_F_MRG_RXBUF ) ) { PMD_DRV_LOG ( INFO , " " ) ; hw -> use_vec_rx = 0 ; } if ( rx_offloads & DEV_RX_OFFLOAD_TCP_LRO ) { PMD_DRV_LOG ( INFO , " " ) ; hw -> use_vec_rx = 0 ; } } } else { if ( virtio_with_feature ( hw , VIRTIO_F_IN_ORDER ) ) { hw -> use_inorder_tx = 1 ; hw -> use_inorder_rx = 1 ; hw -> use_vec_rx = 0 ; } if ( hw -> use_vec_rx ) { #if defined RTE_ARCH_ARM if ( ! rte_cpu_get_flag_enabled ( RTE_CPUFLAG_NEON ) ) { PMD_DRV_LOG ( INFO , " " ) ; hw -> use_vec_rx = 0 ; } #endif if ( virtio_with_feature ( hw , VIRTIO_NET_F_MRG_RXBUF ) ) { PMD_DRV_LOG ( INFO , " " ) ; hw -> use_vec_rx = 0 ; } if ( rx_offloads & ( DEV_RX_OFFLOAD_UDP_CKSUM | DEV_RX_OFFLOAD_TCP_CKSUM | DEV_RX_OFFLOAD_TCP_LRO | DEV_RX_OFFLOAD_VLAN_STRIP ) ) { PMD_DRV_LOG ( INFO , " " ) ; hw -> use_vec_rx = 0 ; } if ( rte_vect_get_max_simd_bitwidth ( ) < RTE_VECT_SIMD_128 ) { PMD_DRV_LOG ( INFO , " " ) ; hw -> use_vec_rx = 0 ; } } } return 0 ; }
Configure virtio device
 It returns 0 on success.
Configure virtio device It returns 0 on success .
/* if request features changed, reinit the device */ /* start control queue */ /* Enable vector (0) for Link State Intrerrupt */