From patchwork Tue Jul 6 14:14:07 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Rybchenko X-Patchwork-Id: 95415 X-Patchwork-Delegate: maxime.coquelin@redhat.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 31FD6A0C47; Tue, 6 Jul 2021 16:15:12 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id B2882412C7; Tue, 6 Jul 2021 16:15:11 +0200 (CEST) Received: from shelob.oktetlabs.ru (shelob.oktetlabs.ru [91.220.146.113]) by mails.dpdk.org (Postfix) with ESMTP id 034084128B; Tue, 6 Jul 2021 16:15:09 +0200 (CEST) Received: by shelob.oktetlabs.ru (Postfix, from userid 122) id 958DD7F563; Tue, 6 Jul 2021 17:15:09 +0300 (MSK) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on shelob.oktetlabs.ru X-Spam-Level: X-Spam-Status: No, score=0.8 required=5.0 tests=ALL_TRUSTED, DKIM_ADSP_DISCARD, URIBL_BLOCKED autolearn=no autolearn_force=no version=3.4.2 Received: from aros.oktetlabs.ru (aros.oktetlabs.ru [192.168.38.17]) by shelob.oktetlabs.ru (Postfix) with ESMTP id B01A87F517; Tue, 6 Jul 2021 17:15:05 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 shelob.oktetlabs.ru B01A87F517 Authentication-Results: shelob.oktetlabs.ru/B01A87F517; dkim=none; dkim-atps=neutral From: Andrew Rybchenko To: Maxime Coquelin , Chenbo Xia , Konstantin Ananyev , Shahaf Shuler , Andrew Rybchenko Cc: dev@dpdk.org, Ivan Ilchenko , stable@dpdk.org Date: Tue, 6 Jul 2021 17:14:07 +0300 Message-Id: <20210706141407.2391177-1-andrew.rybchenko@oktetlabs.ru> X-Mailer: git-send-email 2.30.2 MIME-Version: 1.0 Subject: [dpdk-dev] [PATCH] net/virtio: fix Rx scatter offload X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" From: Ivan Ilchenko Report Rx scatter offload capability depending on VIRTIO_NET_F_MRG_RXBUF. If Rx scatter is not requested, ensure that provided Rx buffers on each Rx queue are big enough to fit Rx packets up to configured MTU. Fixes: ce17eddefc20 ("ethdev: introduce Rx queue offloads API") Cc: stable@dpdk.org Signed-off-by: Ivan Ilchenko Signed-off-by: Andrew Rybchenko Reviewed-by: Maxime Coquelin --- drivers/net/virtio/virtio.h | 2 + drivers/net/virtio/virtio_ethdev.c | 63 ++++++++++++++++++++++++++++++ drivers/net/virtio/virtio_ethdev.h | 5 +++ drivers/net/virtio/virtio_rxtx.c | 10 +++++ 4 files changed, 80 insertions(+) diff --git a/drivers/net/virtio/virtio.h b/drivers/net/virtio/virtio.h index 2c987d19ab..525e2dad4c 100644 --- a/drivers/net/virtio/virtio.h +++ b/drivers/net/virtio/virtio.h @@ -167,6 +167,7 @@ struct virtio_hw { uint8_t started; uint8_t weak_barriers; uint8_t vlan_strip; + bool rx_ol_scatter; uint8_t has_tx_offload; uint8_t has_rx_offload; uint8_t use_vec_rx; @@ -180,6 +181,7 @@ struct virtio_hw { uint8_t duplex; uint8_t intr_lsc; uint16_t max_mtu; + size_t max_rx_pkt_len; /* * App management thread and virtio interrupt handler thread * both can change device state, this lock is meant to avoid diff --git a/drivers/net/virtio/virtio_ethdev.c b/drivers/net/virtio/virtio_ethdev.c index 0568305667..6d6e105960 100644 --- a/drivers/net/virtio/virtio_ethdev.c +++ b/drivers/net/virtio/virtio_ethdev.c @@ -841,6 +841,54 @@ virtio_dev_allmulticast_disable(struct rte_eth_dev *dev) return 0; } +uint16_t +virtio_rx_mem_pool_buf_size(struct rte_mempool *mp) +{ + return rte_pktmbuf_data_room_size(mp) - RTE_PKTMBUF_HEADROOM; +} + +bool +virtio_rx_check_scatter(uint16_t max_rx_pkt_len, uint16_t rx_buf_size, + bool rx_scatter_enabled, const char **error) +{ + if (!rx_scatter_enabled && max_rx_pkt_len > rx_buf_size) { + *error = "Rx scatter is disabled and RxQ mbuf pool object size is too small"; + return false; + } + + return true; +} + +static bool +virtio_check_scatter_on_all_rx_queues(struct rte_eth_dev *dev, + uint16_t frame_size) +{ + struct virtio_hw *hw = dev->data->dev_private; + struct virtnet_rx *rxvq; + struct virtqueue *vq; + unsigned int qidx; + uint16_t buf_size; + const char *error; + + if (hw->vqs == NULL) + return true; + + for (qidx = 0; (vq = hw->vqs[2 * qidx + VTNET_SQ_RQ_QUEUE_IDX]) != NULL; + qidx++) { + rxvq = &vq->rxq; + buf_size = virtio_rx_mem_pool_buf_size(rxvq->mpool); + + if (!virtio_rx_check_scatter(frame_size, buf_size, + hw->rx_ol_scatter, &error)) { + PMD_INIT_LOG(ERR, "MTU check for RxQ %u failed: %s", + qidx, error); + return false; + } + } + + return true; +} + #define VLAN_TAG_LEN 4 /* 802.3ac tag (not DMA'd) */ static int virtio_mtu_set(struct rte_eth_dev *dev, uint16_t mtu) @@ -858,6 +906,15 @@ virtio_mtu_set(struct rte_eth_dev *dev, uint16_t mtu) RTE_ETHER_MIN_MTU, max_frame_size - ether_hdr_len); return -EINVAL; } + + if (!virtio_check_scatter_on_all_rx_queues(dev, frame_size)) { + PMD_INIT_LOG(ERR, "MTU vs Rx scatter and Rx buffers check failed"); + return -EINVAL; + } + + hw->max_rx_pkt_len = frame_size; + dev->data->dev_conf.rxmode.max_rx_pkt_len = hw->max_rx_pkt_len; + return 0; } @@ -2042,6 +2099,8 @@ virtio_dev_configure(struct rte_eth_dev *dev) if (rxmode->max_rx_pkt_len > hw->max_mtu + ether_hdr_len) req_features &= ~(1ULL << VIRTIO_NET_F_MTU); + hw->max_rx_pkt_len = rxmode->max_rx_pkt_len; + if (rx_offloads & (DEV_RX_OFFLOAD_UDP_CKSUM | DEV_RX_OFFLOAD_TCP_CKSUM)) req_features |= (1ULL << VIRTIO_NET_F_GUEST_CSUM); @@ -2090,6 +2149,8 @@ virtio_dev_configure(struct rte_eth_dev *dev) if (rx_offloads & DEV_RX_OFFLOAD_VLAN_STRIP) hw->vlan_strip = 1; + hw->rx_ol_scatter = (rx_offloads & DEV_RX_OFFLOAD_SCATTER); + if ((rx_offloads & DEV_RX_OFFLOAD_VLAN_FILTER) && !virtio_with_feature(hw, VIRTIO_NET_F_CTRL_VLAN)) { PMD_DRV_LOG(ERR, @@ -2445,6 +2506,8 @@ virtio_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info) host_features = VIRTIO_OPS(hw)->get_features(hw); dev_info->rx_offload_capa = DEV_RX_OFFLOAD_VLAN_STRIP; dev_info->rx_offload_capa |= DEV_RX_OFFLOAD_JUMBO_FRAME; + if (host_features & (1ULL << VIRTIO_NET_F_MRG_RXBUF)) + dev_info->rx_offload_capa = DEV_RX_OFFLOAD_SCATTER; if (host_features & (1ULL << VIRTIO_NET_F_GUEST_CSUM)) { dev_info->rx_offload_capa |= DEV_RX_OFFLOAD_TCP_CKSUM | diff --git a/drivers/net/virtio/virtio_ethdev.h b/drivers/net/virtio/virtio_ethdev.h index 5a501e7890..2f63ef2b2d 100644 --- a/drivers/net/virtio/virtio_ethdev.h +++ b/drivers/net/virtio/virtio_ethdev.h @@ -120,4 +120,9 @@ int virtio_dev_close(struct rte_eth_dev *dev); int virtio_inject_pkts(struct rte_eth_dev *dev, struct rte_mbuf **tx_pkts, int nb_pkts); +bool virtio_rx_check_scatter(uint16_t max_rx_pkt_len, uint16_t rx_buf_size, + bool rx_scatter_enabled, const char **error); + +uint16_t virtio_rx_mem_pool_buf_size(struct rte_mempool *mp); + #endif /* _VIRTIO_ETHDEV_H_ */ diff --git a/drivers/net/virtio/virtio_rxtx.c b/drivers/net/virtio/virtio_rxtx.c index 34108fb946..511b3d71b1 100644 --- a/drivers/net/virtio/virtio_rxtx.c +++ b/drivers/net/virtio/virtio_rxtx.c @@ -634,6 +634,8 @@ virtio_dev_rx_queue_setup(struct rte_eth_dev *dev, struct virtqueue *vq = hw->vqs[vq_idx]; struct virtnet_rx *rxvq; uint16_t rx_free_thresh; + uint16_t buf_size; + const char *error; PMD_INIT_FUNC_TRACE(); @@ -642,6 +644,14 @@ virtio_dev_rx_queue_setup(struct rte_eth_dev *dev, return -EINVAL; } + buf_size = virtio_rx_mem_pool_buf_size(mp); + if (!virtio_rx_check_scatter(hw->max_rx_pkt_len, buf_size, + hw->rx_ol_scatter, &error)) { + PMD_INIT_LOG(ERR, "RxQ %u Rx scatter check failed: %s", + queue_idx, error); + return -EINVAL; + } + rx_free_thresh = rx_conf->rx_free_thresh; if (rx_free_thresh == 0) rx_free_thresh =