From patchwork Wed Aug 18 17:54:38 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Melnychenko X-Patchwork-Id: 499523 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 80AA8C4338F for ; Wed, 18 Aug 2021 17:55:15 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 6485E61100 for ; Wed, 18 Aug 2021 17:55:15 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231422AbhHRRzs (ORCPT ); Wed, 18 Aug 2021 13:55:48 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:42146 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229533AbhHRRzl (ORCPT ); Wed, 18 Aug 2021 13:55:41 -0400 Received: from mail-lj1-x235.google.com (mail-lj1-x235.google.com [IPv6:2a00:1450:4864:20::235]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 75561C061796 for ; Wed, 18 Aug 2021 10:55:05 -0700 (PDT) Received: by mail-lj1-x235.google.com with SMTP id t25so801322ljc.12 for ; Wed, 18 Aug 2021 10:55:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=daynix-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=FDZPSj82vJSIqNRbjRn5ddf373T0TpM4lEOoyZlVBZQ=; b=gmyLLI7JXpGj/OVBAN+uSzWOdMfP5YgfaXsgxzkz64Wd+OYKX0wQXGC4jGag2WE7uY E8hA6Bemu37meaMUVtI6ps1/8pzZlwoGMjjoQ1HwzZPKh4p+YRSTqKhC2JWXFtYN2pZ/ 3tT5kqRRQdkRabE9aLIDVQ0njaXIiaSuvtBwo830lK9kZf0ZXWJGMYK3WgOS0A6NisxV AoDISwFNEovUT4P+kNpxPKbcunxMTHOUq/oo+R28Cyp2kIBycmoQ+/kyP6+ujRCMp9z2 HWZrecThca/8NfhVX5ktgC+IyuNH20vloG9nP/IkJlW/COuF1n9z4/OeZare6qDrIWR2 xVXQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=FDZPSj82vJSIqNRbjRn5ddf373T0TpM4lEOoyZlVBZQ=; b=Kgkpe021rJTT3TdhVih0c1kRjDuRrmu/zBOElthAaP/ALP5rnlXpJlFrr0euqwE/Qc EqvZ0H0tyVXuuZzyy7iwhiI5IgOxkQiIsTtRDxn4n2M2+1zqyvEg2NJLyftF1J7cU865 3GYOQDGt+ZmuzrwbjkmOZ5f4bOeuXxYgly/9/VifRIQMePNK0wRN6uzAk2b9oJ2cDzl1 qPsUx13AdchbBtkST6FtCJfuexBzsmPW2XGlZxVYJEOJN3et0ogQcu4yAn42cdUnzI6Q qWWRml5hodThC6gmQTlar1NXZ+Ef1MTLIenIyTjb0JiI5Xvnae7GeK3Fg/ybU9mTOlyO 4GLA== X-Gm-Message-State: AOAM532RJyFWMBuMciq0q84AdoOUNhmxgAS3+69rKkMmWCAUxmKTqRgv YGNaS7kz4+1e7nHYt56l5qL/UA== X-Google-Smtp-Source: ABdhPJzgju0iGClDUhJIg1bfxppQKWWT8UaYgKfcmAPRfVZg8FN3K6bHCLVQKa9pnbW8D41Y9+GRVw== X-Received: by 2002:a2e:a606:: with SMTP id v6mr8840863ljp.366.1629309303836; Wed, 18 Aug 2021 10:55:03 -0700 (PDT) Received: from navi.cosmonova.net.ua ([95.67.24.131]) by smtp.gmail.com with ESMTPSA id c5sm55820lji.67.2021.08.18.10.55.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 18 Aug 2021 10:55:03 -0700 (PDT) From: Andrew Melnychenko To: mst@redhat.com, jasowang@redhat.com, davem@davemloft.net, kuba@kernel.org Cc: virtualization@lists.linux-foundation.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [RFC PATCH 1/3] drivers/net/virtio_net: Fixed vheader to use v1. Date: Wed, 18 Aug 2021 20:54:38 +0300 Message-Id: <20210818175440.128691-2-andrew@daynix.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210818175440.128691-1-andrew@daynix.com> References: <20210818175440.128691-1-andrew@daynix.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org The header v1 provides additional info about RSS. Added changes to computing proper header length. In the next patches, the header may contain RSS hash info for the hash population. Signed-off-by: Andrew Melnychenko --- drivers/net/virtio_net.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 56c3f8519093..85427b4f51bc 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -240,13 +240,13 @@ struct virtnet_info { }; struct padded_vnet_hdr { - struct virtio_net_hdr_mrg_rxbuf hdr; + struct virtio_net_hdr_v1_hash hdr; /* * hdr is in a separate sg buffer, and data sg buffer shares same page * with this header sg. This padding makes next sg 16 byte aligned * after the header. */ - char padding[4]; + char padding[12]; }; static bool is_xdp_frame(void *ptr) @@ -1258,7 +1258,7 @@ static unsigned int get_mergeable_buf_len(struct receive_queue *rq, struct ewma_pkt_len *avg_pkt_len, unsigned int room) { - const size_t hdr_len = sizeof(struct virtio_net_hdr_mrg_rxbuf); + const size_t hdr_len = ((struct virtnet_info *)(rq->vq->vdev->priv))->hdr_len; unsigned int len; if (room) @@ -1642,7 +1642,7 @@ static int xmit_skb(struct send_queue *sq, struct sk_buff *skb) const unsigned char *dest = ((struct ethhdr *)skb->data)->h_dest; struct virtnet_info *vi = sq->vq->vdev->priv; int num_sg; - unsigned hdr_len = vi->hdr_len; + unsigned int hdr_len = vi->hdr_len; bool can_push; pr_debug("%s: xmit %p %pM\n", vi->dev->name, skb, dest); @@ -2819,7 +2819,7 @@ static void virtnet_del_vqs(struct virtnet_info *vi) */ static unsigned int mergeable_min_buf_len(struct virtnet_info *vi, struct virtqueue *vq) { - const unsigned int hdr_len = sizeof(struct virtio_net_hdr_mrg_rxbuf); + const unsigned int hdr_len = vi->hdr_len; unsigned int rq_size = virtqueue_get_vring_size(vq); unsigned int packet_len = vi->big_packets ? IP_MAX_MTU : vi->dev->max_mtu; unsigned int buf_len = hdr_len + ETH_HLEN + VLAN_HLEN + packet_len; From patchwork Wed Aug 18 17:54:39 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Melnychenko X-Patchwork-Id: 500256 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0726FC4338F for ; Wed, 18 Aug 2021 17:55:18 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id E058761100 for ; Wed, 18 Aug 2021 17:55:17 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231800AbhHRRzu (ORCPT ); Wed, 18 Aug 2021 13:55:50 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:42156 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229535AbhHRRzn (ORCPT ); Wed, 18 Aug 2021 13:55:43 -0400 Received: from mail-lf1-x136.google.com (mail-lf1-x136.google.com [IPv6:2a00:1450:4864:20::136]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 71670C06179A for ; Wed, 18 Aug 2021 10:55:06 -0700 (PDT) Received: by mail-lf1-x136.google.com with SMTP id x27so6386342lfu.5 for ; Wed, 18 Aug 2021 10:55:06 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=daynix-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=kYASjoaquUkTJwE6Il+qyUZOijKb6JIMjRhyJiXoHTM=; b=IrJ3bq8D3pzAvAqGGsvlw++mZ7Ap5ozefbuPauE+qyMUH1Xi6NbuFdHRcPK70G89xB RCG22Cw7MFj8SXhVNYtqKGqvAoTIKFRRy+JDj77QbGjOLABTCoJx71GPHkhApfHiL2ke 3MoEoe3hbwN4fxDtnsH8pqBznUo7KKdRhAcOEwyBxIvamSSUE95ieWTA8yACkjYoR+zI 1Xjl/8GOWO0totYTFy/5K2nIJHDOWz68o3GhVduIIm0DZg5/x0Og9JC6CgzsjRJ6o+bo To1PSVS2BodSsWp2uPe/vtbqrrdEtJQOwwpBRo6NJFnXxWmHe7q/M4aX05uQTtZjBOSO IJCQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=kYASjoaquUkTJwE6Il+qyUZOijKb6JIMjRhyJiXoHTM=; b=uQ77ZqcScnQRRYiQxSnfn3dwBJUCXv9IcojjlJ2imerCB2BoZWjgSj+CMoDKAXH+mO LDmXooKG+4X22HVtsAHAlIBRhwzVaSSQVR8FpYxznliBTKLbH0oCFP2kdaWpGk5k3/Zq RYiIr+DtG0E2q1aybarI8zSztiHisXN7ahW8dIl9sAYy0q4xF6pmMCZUZgc27L8iaNOj bWYUwFQabzYBonoBMwHa64Ze1onhIVfDZWCSFutZQgVKw2UuOhKbx9L6zuaOM1c1DqXc MIbNbYe84UlelKv+BNYhkP0PPQ16I/PgT9LJLJndKamg6ZVRKmSlFEGgr521UrplNSzF 54xg== X-Gm-Message-State: AOAM5302/KZcbccsb3EDtrTON4TLx79aNK+5GUpgGQZ4Y6OAJFuSjfJ3 rUO9AkWqGtB4EjpX9NtaTm6ITvnYA+qA3g== X-Google-Smtp-Source: ABdhPJxsSKv+OdOYXouEhjN0F9zaxYh+6/lkbpUYiKOLXZQsHySjEDTSfy/gLVdFeA1F8os0wMyEzQ== X-Received: by 2002:a19:f819:: with SMTP id a25mr7193558lff.203.1629309304779; Wed, 18 Aug 2021 10:55:04 -0700 (PDT) Received: from navi.cosmonova.net.ua ([95.67.24.131]) by smtp.gmail.com with ESMTPSA id c5sm55820lji.67.2021.08.18.10.55.03 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 18 Aug 2021 10:55:04 -0700 (PDT) From: Andrew Melnychenko To: mst@redhat.com, jasowang@redhat.com, davem@davemloft.net, kuba@kernel.org Cc: virtualization@lists.linux-foundation.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [RFC PATCH 2/3] drivers/net/virtio_net: Added basic RSS support. Date: Wed, 18 Aug 2021 20:54:39 +0300 Message-Id: <20210818175440.128691-3-andrew@daynix.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210818175440.128691-1-andrew@daynix.com> References: <20210818175440.128691-1-andrew@daynix.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Added features for RSS and RSS hash report. Added initialization, RXHASH feature and ethtool ops. By default RSS/RXHASH is disabled. Added ethtools ops to set key and indirection table. Signed-off-by: Andrew Melnychenko --- drivers/net/virtio_net.c | 215 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 203 insertions(+), 12 deletions(-) diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 85427b4f51bc..d87bde246305 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -167,6 +167,23 @@ struct receive_queue { struct xdp_rxq_info xdp_rxq; }; +/* This structure can contain rss message with maximum settings for indirection table and keysize */ +#define VIRTIO_NET_RSS_MAX_KEY_SIZE 40 +#define VIRTIO_NET_RSS_MAX_TABLE_LEN 128 +struct virtio_net_ctrl_rss { + struct { + __le32 hash_types; + __le16 indirection_table_mask; + __le16 unclassified_queue; + } __packed table_info; + u16 indirection_table[VIRTIO_NET_RSS_MAX_TABLE_LEN]; + struct { + u16 max_tx_vq; /* queues */ + u8 hash_key_length; + } __packed key_info; + u8 key[VIRTIO_NET_RSS_MAX_KEY_SIZE]; +}; + /* Control VQ buffers: protected by the rtnl lock */ struct control_buf { struct virtio_net_ctrl_hdr hdr; @@ -176,6 +193,7 @@ struct control_buf { u8 allmulti; __virtio16 vid; __virtio64 offloads; + struct virtio_net_ctrl_rss rss; }; struct virtnet_info { @@ -204,6 +222,14 @@ struct virtnet_info { /* Host will merge rx buffers for big packets (shake it! shake it!) */ bool mergeable_rx_bufs; + /* Host supports rss and/or hash report */ + bool has_rss; + bool has_rss_hash_report; + u8 rss_key_size; + u16 rss_indir_table_size; + u32 rss_hash_types_supported; + u32 rss_hash_types_saved; + /* Has control virtqueue */ bool has_cvq; @@ -393,7 +419,9 @@ static struct sk_buff *page_to_skb(struct virtnet_info *vi, hdr_p = p; hdr_len = vi->hdr_len; - if (vi->mergeable_rx_bufs) + if (vi->has_rss_hash_report) + hdr_padded_len = sizeof(struct virtio_net_hdr_v1_hash); + else if (vi->mergeable_rx_bufs) hdr_padded_len = sizeof(*hdr); else hdr_padded_len = sizeof(struct padded_vnet_hdr); @@ -2171,6 +2199,56 @@ static void virtnet_get_ringparam(struct net_device *dev, ring->tx_pending = ring->tx_max_pending; } +static bool virtnet_commit_rss_command(struct virtnet_info *vi) +{ + struct net_device *dev = vi->dev; + struct scatterlist sgs[4]; + unsigned int sg_buf_size; + + /* prepare sgs */ + sg_init_table(sgs, 4); + + sg_buf_size = sizeof(vi->ctrl->rss.table_info); + sg_set_buf(&sgs[0], &vi->ctrl->rss.table_info, sg_buf_size); + + sg_buf_size = sizeof(uint16_t) * vi->rss_indir_table_size; + sg_set_buf(&sgs[1], vi->ctrl->rss.indirection_table, sg_buf_size); + + sg_buf_size = sizeof(vi->ctrl->rss.key_info); + sg_set_buf(&sgs[2], &vi->ctrl->rss.key_info, sg_buf_size); + + sg_buf_size = vi->rss_key_size; + sg_set_buf(&sgs[3], vi->ctrl->rss.key, sg_buf_size); + + if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_MQ, + vi->has_rss ? VIRTIO_NET_CTRL_MQ_RSS_CONFIG + : VIRTIO_NET_CTRL_MQ_HASH_CONFIG, sgs)) { + dev_warn(&dev->dev, "VIRTIONET issue with committing RSS sgs\n"); + return false; + } + return true; +} + +static void virtnet_init_default_rss(struct virtnet_info *vi) +{ + u32 indir_val = 0; + int i = 0; + + vi->ctrl->rss.table_info.hash_types = vi->rss_hash_types_supported; + vi->rss_hash_types_saved = vi->rss_hash_types_supported; + vi->ctrl->rss.table_info.indirection_table_mask = vi->rss_indir_table_size - 1; + vi->ctrl->rss.table_info.unclassified_queue = 0; + + for (; i < vi->rss_indir_table_size; ++i) { + indir_val = ethtool_rxfh_indir_default(i, vi->max_queue_pairs); + vi->ctrl->rss.indirection_table[i] = indir_val; + } + + vi->ctrl->rss.key_info.max_tx_vq = vi->curr_queue_pairs; + vi->ctrl->rss.key_info.hash_key_length = vi->rss_key_size; + + netdev_rss_key_fill(vi->ctrl->rss.key, vi->rss_key_size); +} static void virtnet_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) @@ -2395,6 +2473,72 @@ static void virtnet_update_settings(struct virtnet_info *vi) vi->duplex = duplex; } +u32 virtnet_get_rxfh_key_size(struct net_device *dev) +{ + return ((struct virtnet_info *)netdev_priv(dev))->rss_key_size; +} + +u32 virtnet_get_rxfh_indir_size(struct net_device *dev) +{ + return ((struct virtnet_info *)netdev_priv(dev))->rss_indir_table_size; +} + +int virtnet_get_rxfh(struct net_device *dev, u32 *indir, u8 *key, u8 *hfunc) +{ + struct virtnet_info *vi = netdev_priv(dev); + int i; + + if (indir) { + for (i = 0; i < vi->rss_indir_table_size; ++i) + indir[i] = vi->ctrl->rss.indirection_table[i]; + } + + if (key) + memcpy(key, vi->ctrl->rss.key, vi->rss_key_size); + + if (hfunc) + *hfunc = ETH_RSS_HASH_TOP; + + return 0; +} + +int virtnet_set_rxfh(struct net_device *dev, const u32 *indir, const u8 *key, const u8 hfunc) +{ + struct virtnet_info *vi = netdev_priv(dev); + int i; + + if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP) + return -EOPNOTSUPP; + + if (indir) { + for (i = 0; i < vi->rss_indir_table_size; ++i) + vi->ctrl->rss.indirection_table[i] = indir[i]; + } + if (key) + memcpy(vi->ctrl->rss.key, key, vi->rss_key_size); + + virtnet_commit_rss_command(vi); + + return 0; +} + +int virtnet_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info, u32 *rule_locs) +{ + struct virtnet_info *vi = netdev_priv(dev); + int rc = 0; + + switch (info->cmd) { + case ETHTOOL_GRXRINGS: + info->data = vi->curr_queue_pairs; + rc = -EOPNOTSUPP; + } + default: + rc = -EOPNOTSUPP; + } + + return rc; +} + static const struct ethtool_ops virtnet_ethtool_ops = { .supported_coalesce_params = ETHTOOL_COALESCE_MAX_FRAMES, .get_drvinfo = virtnet_get_drvinfo, @@ -2410,6 +2554,11 @@ static const struct ethtool_ops virtnet_ethtool_ops = { .set_link_ksettings = virtnet_set_link_ksettings, .set_coalesce = virtnet_set_coalesce, .get_coalesce = virtnet_get_coalesce, + .get_rxfh_key_size = virtnet_get_rxfh_key_size, + .get_rxfh_indir_size = virtnet_get_rxfh_indir_size, + .get_rxfh = virtnet_get_rxfh, + .set_rxfh = virtnet_set_rxfh, + .get_rxnfc = virtnet_get_rxnfc, }; static void virtnet_freeze_down(struct virtio_device *vdev) @@ -2662,6 +2811,16 @@ static int virtnet_set_features(struct net_device *dev, vi->guest_offloads = offloads; } + if ((dev->features ^ features) & NETIF_F_RXHASH) { + if (features & NETIF_F_RXHASH) + vi->ctrl->rss.table_info.hash_types = vi->rss_hash_types_saved; + else + vi->ctrl->rss.table_info.hash_types = 0; + + if (!virtnet_commit_rss_command(vi)) + return -EINVAL; + } + return 0; } @@ -3080,13 +3239,14 @@ static int virtnet_probe(struct virtio_device *vdev) u16 max_queue_pairs; int mtu; - /* 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); + /* Find if host supports multiqueue/rss virtio_net device */ + max_queue_pairs = 0; + if (virtio_has_feature(vdev, VIRTIO_NET_F_MQ) || virtio_has_feature(vdev, VIRTIO_NET_F_RSS)) + max_queue_pairs = + virtio_cread16(vdev, offsetof(struct virtio_net_config, max_virtqueue_pairs)); /* We need at least 2 queue's */ - if (err || max_queue_pairs < VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MIN || + if (max_queue_pairs < VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MIN || max_queue_pairs > VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX || !virtio_has_feature(vdev, VIRTIO_NET_F_CTRL_VQ)) max_queue_pairs = 1; @@ -3160,6 +3320,9 @@ static int virtnet_probe(struct virtio_device *vdev) INIT_WORK(&vi->config_work, virtnet_config_changed_work); + if (virtio_has_feature(vdev, VIRTIO_NET_F_CTRL_VQ)) + vi->has_cvq = true; + /* If we can receive ANY GSO packets, we must allocate large ones. */ if (virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO4) || virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO6) || @@ -3170,8 +3333,32 @@ static int virtnet_probe(struct virtio_device *vdev) if (virtio_has_feature(vdev, VIRTIO_NET_F_MRG_RXBUF)) vi->mergeable_rx_bufs = true; - if (virtio_has_feature(vdev, VIRTIO_NET_F_MRG_RXBUF) || - virtio_has_feature(vdev, VIRTIO_F_VERSION_1)) + if (vi->has_cvq && virtio_has_feature(vdev, VIRTIO_NET_F_HASH_REPORT)) { + vi->has_rss_hash_report = true; + vi->rss_indir_table_size = 1; + vi->rss_key_size = VIRTIO_NET_RSS_MAX_KEY_SIZE; + } + + if (vi->has_cvq && virtio_has_feature(vdev, VIRTIO_NET_F_RSS)) { + vi->has_rss = true; + vi->rss_indir_table_size = + virtio_cread16(vdev, offsetof(struct virtio_net_config, + rss_max_indirection_table_length)); + vi->rss_key_size = + virtio_cread8(vdev, offsetof(struct virtio_net_config, rss_max_key_size)); + } + + if (vi->has_rss || vi->has_rss_hash_report) { + vi->rss_hash_types_supported = + virtio_cread32(vdev, offsetof(struct virtio_net_config, supported_hash_types)); + + dev->hw_features |= NETIF_F_RXHASH; + } + + if (vi->has_cvq && vi->has_rss_hash_report) + vi->hdr_len = sizeof(struct virtio_net_hdr_v1_hash); + else if (virtio_has_feature(vdev, VIRTIO_NET_F_MRG_RXBUF) || + virtio_has_feature(vdev, VIRTIO_F_VERSION_1)) vi->hdr_len = sizeof(struct virtio_net_hdr_mrg_rxbuf); else vi->hdr_len = sizeof(struct virtio_net_hdr); @@ -3180,9 +3367,6 @@ static int virtnet_probe(struct virtio_device *vdev) virtio_has_feature(vdev, VIRTIO_F_VERSION_1)) vi->any_header_sg = true; - if (virtio_has_feature(vdev, VIRTIO_NET_F_CTRL_VQ)) - vi->has_cvq = true; - if (virtio_has_feature(vdev, VIRTIO_NET_F_MTU)) { mtu = virtio_cread16(vdev, offsetof(struct virtio_net_config, @@ -3254,6 +3438,12 @@ static int virtnet_probe(struct virtio_device *vdev) virtnet_set_queues(vi, vi->curr_queue_pairs); + if (vi->has_rss || vi->has_rss_hash_report) { + rtnl_lock(); + virtnet_init_default_rss(vi); + rtnl_unlock(); + } + /* Assume link up if device can't report link status, otherwise get link status from config. */ netif_carrier_off(dev); @@ -3369,7 +3559,8 @@ static struct virtio_device_id id_table[] = { VIRTIO_NET_F_GUEST_ANNOUNCE, VIRTIO_NET_F_MQ, \ VIRTIO_NET_F_CTRL_MAC_ADDR, \ VIRTIO_NET_F_MTU, VIRTIO_NET_F_CTRL_GUEST_OFFLOADS, \ - VIRTIO_NET_F_SPEED_DUPLEX, VIRTIO_NET_F_STANDBY + VIRTIO_NET_F_SPEED_DUPLEX, VIRTIO_NET_F_STANDBY, \ + VIRTIO_NET_F_RSS, VIRTIO_NET_F_HASH_REPORT static unsigned int features[] = { VIRTNET_FEATURES, From patchwork Wed Aug 18 17:54:40 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Melnychenko X-Patchwork-Id: 499522 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id EFBA8C4338F for ; Wed, 18 Aug 2021 17:55:20 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id D13736113B for ; Wed, 18 Aug 2021 17:55:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232885AbhHRRzy (ORCPT ); Wed, 18 Aug 2021 13:55:54 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:42160 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229667AbhHRRzn (ORCPT ); Wed, 18 Aug 2021 13:55:43 -0400 Received: from mail-lj1-x22d.google.com (mail-lj1-x22d.google.com [IPv6:2a00:1450:4864:20::22d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5B356C0617AD for ; Wed, 18 Aug 2021 10:55:07 -0700 (PDT) Received: by mail-lj1-x22d.google.com with SMTP id h9so6585558ljq.8 for ; Wed, 18 Aug 2021 10:55:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=daynix-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=FaxHlGthirATxFhjaA6+LodZEweSNS8npuY55w+kwqI=; b=ueRgO9rsDH8h9Dl0VwHX2lFZDbo6wJ/hp2dx513bA7Vjy8ckwys5RknhabUcbciaUz njaAo6cj1gI6O24fDdfYNL4oTe+iiEvj+AJIfeYmaWltf2ww9jhHMtHmtO6yTOU9TjqJ zWTozWykUKnVLhAak+OuFdw9Qpk7lIsh/VmNLNg8JoBWoPjBYpD7/3lBRD5ry9gjxkYL 2SeZ2ASJ98Y1WHG0cxVmLntEe1GzRtzgwfuiu/w0yW1mAp2j0zbKj9OhChvBysi3Vj4l 0KWzwY3PGzXCXr55XUL5321t8iGPT6btF6a0hCsFNWeTn/AXPK3CVHLaCBIS8kgreTb3 D64Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=FaxHlGthirATxFhjaA6+LodZEweSNS8npuY55w+kwqI=; b=igBF3oitbCY/4k5uxyEPa+jmvlkAKxpzl5dUVVTwc/LAKH7qKs5rYSQ1VOtrj5BTo9 MyONtM6fYhYoEA8lJIAJca2iKWHsz1dZAM/2T5RMEAZpVWITb3rnuQevprdDVBL9Lzy1 W+MdEJWLC9quoB5hyPN2ZkK4KBmAkYMSiLbx7JPk5tXAykCEzSxs8VTw9kZmEzsV2gq3 3bfHzuUtkeEO11Cino9eKxZeJ15khtF5aNVOXxDKL8KaV9eFb5LGFrcRwD1IO2o1LLY0 SGPHiFkhIMIoa6kvL38Aum/uqZLQHlPj6bbNA+d3npWfc7tOAL+p8xYfmESXfBiJ4fmv yFnw== X-Gm-Message-State: AOAM532gwJZNOZn0Z9B/ALL0dWmvRJ4qGomPTc96fDH2+skFw+rb+Bcw KJ3SV68E7auo55/dbWlyz30h8w== X-Google-Smtp-Source: ABdhPJy5ThR5uwyZiMpJBsOcvGSZdjgDAXV+IUj3zSolVN+xfllaNSK4wygdy5FFjijVKRaCYS++bA== X-Received: by 2002:a2e:a549:: with SMTP id e9mr8906892ljn.500.1629309305717; Wed, 18 Aug 2021 10:55:05 -0700 (PDT) Received: from navi.cosmonova.net.ua ([95.67.24.131]) by smtp.gmail.com with ESMTPSA id c5sm55820lji.67.2021.08.18.10.55.04 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 18 Aug 2021 10:55:05 -0700 (PDT) From: Andrew Melnychenko To: mst@redhat.com, jasowang@redhat.com, davem@davemloft.net, kuba@kernel.org Cc: virtualization@lists.linux-foundation.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [RFC PATCH 3/3] drivers/net/virtio_net: Added RSS hash report. Date: Wed, 18 Aug 2021 20:54:40 +0300 Message-Id: <20210818175440.128691-4-andrew@daynix.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210818175440.128691-1-andrew@daynix.com> References: <20210818175440.128691-1-andrew@daynix.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Added set_hash for skb. Also added hashflow set/get callbacks. Virtio RSS "IPv6 extensions" hashes disabled. Also, disabling RXH_IP_SRC/DST for TCP would disable them for UDP. TCP and UDP supports only: ethtool -U eth0 rx-flow-hash tcp4 sd RXH_IP_SRC + RXH_IP_DST ethtool -U eth0 rx-flow-hash tcp4 sdfn RXH_IP_SRC + RXH_IP_DST + RXH_L4_B_0_1 + RXH_L4_B_2_3 Signed-off-by: Andrew Melnychenko --- drivers/net/virtio_net.c | 177 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 177 insertions(+) diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index d87bde246305..6a52eeaf9292 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -1151,6 +1151,8 @@ static void receive_buf(struct virtnet_info *vi, struct receive_queue *rq, struct net_device *dev = vi->dev; struct sk_buff *skb; struct virtio_net_hdr_mrg_rxbuf *hdr; + struct virtio_net_hdr_v1_hash *hdr_hash; + enum pkt_hash_types rss_hash_type; if (unlikely(len < vi->hdr_len + ETH_HLEN)) { pr_debug("%s: short packet %i\n", dev->name, len); @@ -1177,6 +1179,29 @@ static void receive_buf(struct virtnet_info *vi, struct receive_queue *rq, return; hdr = skb_vnet_hdr(skb); + if (vi->has_rss_hash_report && (dev->features & NETIF_F_RXHASH)) { + hdr_hash = (struct virtio_net_hdr_v1_hash *)(hdr); + + switch (hdr_hash->hash_report) { + case VIRTIO_NET_HASH_REPORT_TCPv4: + case VIRTIO_NET_HASH_REPORT_UDPv4: + case VIRTIO_NET_HASH_REPORT_TCPv6: + case VIRTIO_NET_HASH_REPORT_UDPv6: + case VIRTIO_NET_HASH_REPORT_TCPv6_EX: + case VIRTIO_NET_HASH_REPORT_UDPv6_EX: + rss_hash_type = PKT_HASH_TYPE_L4; + break; + case VIRTIO_NET_HASH_REPORT_IPv4: + case VIRTIO_NET_HASH_REPORT_IPv6: + case VIRTIO_NET_HASH_REPORT_IPv6_EX: + rss_hash_type = PKT_HASH_TYPE_L3; + break; + case VIRTIO_NET_HASH_REPORT_NONE: + default: + rss_hash_type = PKT_HASH_TYPE_NONE; + } + skb_set_hash(skb, hdr_hash->hash_value, rss_hash_type); + } if (hdr->hdr.flags & VIRTIO_NET_HDR_F_DATA_VALID) skb->ip_summed = CHECKSUM_UNNECESSARY; @@ -2250,6 +2275,132 @@ static void virtnet_init_default_rss(struct virtnet_info *vi) netdev_rss_key_fill(vi->ctrl->rss.key, vi->rss_key_size); } +void virtnet_get_hashflow(const struct virtnet_info *vi, struct ethtool_rxnfc *info) +{ + info->data = 0; + switch (info->flow_type) { + case TCP_V4_FLOW: + if (vi->rss_hash_types_saved & VIRTIO_NET_RSS_HASH_TYPE_TCPv4) { + info->data = RXH_IP_SRC | RXH_IP_DST | + RXH_L4_B_0_1 | RXH_L4_B_2_3; + } else if (vi->rss_hash_types_saved & VIRTIO_NET_RSS_HASH_TYPE_IPv4) { + info->data = RXH_IP_SRC | RXH_IP_DST; + } + break; + case TCP_V6_FLOW: + if (vi->rss_hash_types_saved & VIRTIO_NET_RSS_HASH_TYPE_TCPv6) { + info->data = RXH_IP_SRC | RXH_IP_DST | + RXH_L4_B_0_1 | RXH_L4_B_2_3; + } else if (vi->rss_hash_types_saved & VIRTIO_NET_RSS_HASH_TYPE_IPv6) { + info->data = RXH_IP_SRC | RXH_IP_DST; + } + break; + case UDP_V4_FLOW: + if (vi->rss_hash_types_saved & VIRTIO_NET_RSS_HASH_TYPE_UDPv4) { + info->data = RXH_IP_SRC | RXH_IP_DST | + RXH_L4_B_0_1 | RXH_L4_B_2_3; + } else if (vi->rss_hash_types_saved & VIRTIO_NET_RSS_HASH_TYPE_IPv4) { + info->data = RXH_IP_SRC | RXH_IP_DST; + } + break; + case UDP_V6_FLOW: + if (vi->rss_hash_types_saved & VIRTIO_NET_RSS_HASH_TYPE_UDPv6) { + info->data = RXH_IP_SRC | RXH_IP_DST | + RXH_L4_B_0_1 | RXH_L4_B_2_3; + } else if (vi->rss_hash_types_saved & VIRTIO_NET_RSS_HASH_TYPE_IPv6) { + info->data = RXH_IP_SRC | RXH_IP_DST; + } + break; + case IPV4_FLOW: + if (vi->rss_hash_types_saved & VIRTIO_NET_RSS_HASH_TYPE_IPv4) + info->data = RXH_IP_SRC | RXH_IP_DST; + + break; + case IPV6_FLOW: + if (vi->rss_hash_types_saved & VIRTIO_NET_RSS_HASH_TYPE_IPv4) + info->data = RXH_IP_SRC | RXH_IP_DST; + + break; + default: + info->data = 0; + break; + } +} + +bool virtnet_set_hashflow(struct virtnet_info *vi, struct ethtool_rxnfc *info) +{ + u64 is_iphash = info->data & (RXH_IP_SRC | RXH_IP_DST); + u64 is_porthash = info->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3); + u32 new_hashtypes = vi->rss_hash_types_saved; + + if ((is_iphash && (is_iphash != (RXH_IP_SRC | RXH_IP_DST))) || + (is_porthash && (is_porthash != (RXH_L4_B_0_1 | RXH_L4_B_2_3)))) { + return false; + } + + if (!is_iphash && is_porthash) + return false; + + switch (info->flow_type) { + case TCP_V4_FLOW: + case UDP_V4_FLOW: + case IPV4_FLOW: + new_hashtypes &= ~VIRTIO_NET_RSS_HASH_TYPE_IPv4; + if (is_iphash) + new_hashtypes |= VIRTIO_NET_RSS_HASH_TYPE_IPv4; + + break; + case TCP_V6_FLOW: + case UDP_V6_FLOW: + case IPV6_FLOW: + new_hashtypes &= ~VIRTIO_NET_RSS_HASH_TYPE_IPv6; + if (is_iphash) + new_hashtypes |= VIRTIO_NET_RSS_HASH_TYPE_IPv6; + + break; + default: + break; + } + + switch (info->flow_type) { + case TCP_V4_FLOW: + new_hashtypes &= ~VIRTIO_NET_RSS_HASH_TYPE_TCPv4; + if (is_porthash) + new_hashtypes |= VIRTIO_NET_RSS_HASH_TYPE_TCPv4; + + break; + case UDP_V4_FLOW: + new_hashtypes &= ~VIRTIO_NET_RSS_HASH_TYPE_UDPv4; + if (is_porthash) + new_hashtypes |= VIRTIO_NET_RSS_HASH_TYPE_UDPv4; + + break; + case TCP_V6_FLOW: + new_hashtypes &= ~VIRTIO_NET_RSS_HASH_TYPE_TCPv6; + if (is_porthash) + new_hashtypes |= VIRTIO_NET_RSS_HASH_TYPE_TCPv6; + + break; + case UDP_V6_FLOW: + new_hashtypes &= ~VIRTIO_NET_RSS_HASH_TYPE_UDPv6; + if (is_porthash) + new_hashtypes |= VIRTIO_NET_RSS_HASH_TYPE_UDPv6; + + break; + default: + break; + } + + if (new_hashtypes != vi->rss_hash_types_saved) { + vi->rss_hash_types_saved = new_hashtypes; + vi->ctrl->rss.table_info.hash_types = vi->rss_hash_types_saved; + if (vi->dev->features & NETIF_F_RXHASH) + return virtnet_commit_rss_command(vi); + } + + return true; +} + static void virtnet_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { @@ -2530,8 +2681,28 @@ int virtnet_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info, u32 *r switch (info->cmd) { case ETHTOOL_GRXRINGS: info->data = vi->curr_queue_pairs; + break; + case ETHTOOL_GRXFH: + virtnet_get_hashflow(vi, info); + break; + default: rc = -EOPNOTSUPP; } + + return rc; +} + +static int virtnet_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info) +{ + struct virtnet_info *vi = netdev_priv(dev); + int rc = 0; + + switch (info->cmd) { + case ETHTOOL_SRXFH: + if (!virtnet_set_hashflow(vi, info)) + rc = -EINVAL; + + break; default: rc = -EOPNOTSUPP; } @@ -2559,6 +2730,7 @@ static const struct ethtool_ops virtnet_ethtool_ops = { .get_rxfh = virtnet_get_rxfh, .set_rxfh = virtnet_set_rxfh, .get_rxnfc = virtnet_get_rxnfc, + .set_rxnfc = virtnet_set_rxnfc, }; static void virtnet_freeze_down(struct virtio_device *vdev) @@ -3351,8 +3523,13 @@ static int virtnet_probe(struct virtio_device *vdev) if (vi->has_rss || vi->has_rss_hash_report) { vi->rss_hash_types_supported = virtio_cread32(vdev, offsetof(struct virtio_net_config, supported_hash_types)); + vi->rss_hash_types_supported &= + ~(VIRTIO_NET_RSS_HASH_TYPE_IP_EX | + VIRTIO_NET_RSS_HASH_TYPE_TCP_EX | + VIRTIO_NET_RSS_HASH_TYPE_UDP_EX); dev->hw_features |= NETIF_F_RXHASH; + dev->features |= NETIF_F_NTUPLE; } if (vi->has_cvq && vi->has_rss_hash_report)