From nobody Thu Jun 25 09:39:12 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6265EC433EF for ; Mon, 28 Mar 2022 18:02:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S244967AbiC1SEP (ORCPT ); Mon, 28 Mar 2022 14:04:15 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:39352 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S245168AbiC1SDZ (ORCPT ); Mon, 28 Mar 2022 14:03:25 -0400 Received: from mail-lj1-x230.google.com (mail-lj1-x230.google.com [IPv6:2a00:1450:4864:20::230]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A9AE54839F for ; Mon, 28 Mar 2022 11:01:43 -0700 (PDT) Received: by mail-lj1-x230.google.com with SMTP id r22so20315655ljd.4 for ; Mon, 28 Mar 2022 11:01:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=daynix-com.20210112.gappssmtp.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=03PefwHsmItmTHhL6lJqxa9zDP27cAxap27LRrEspsw=; b=nfEeQvfRPoop5plFvifW8xUkvneLhLrM5cl1yZzcG3YIDt2bpnZh7Qb9BRBR1KMqmL kfO1vMpuGZgnfmUwktAGevzrihWEkV9fN4OOcZXIbkx0MTCNrzRZsnEGnalt+4oRAgTE m06MWgTGnRU1nxRZ7Lkhc+foCiS3XRX7xJrah10DtdHgJ5xYYz4c7gjJdZ3vNIfdmi0z lVqA8TavemfrvABP0O/yjV5G007U9UPNqy0mBinYHmnnpc1+vllkqfZojYw9uy/thFnS XN3ewSHXVb6Mkm52MJBdCvDzPa25xYyuiXDOAKL2JXf2hB/RxZ8Ez8I5pn+Q3HdNdJ7R jw9w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=03PefwHsmItmTHhL6lJqxa9zDP27cAxap27LRrEspsw=; b=j3vH6ulp87Tti/+fjdzwApOgPswOdm7iIDGSu7DzPtnAj67XXbXZ8WAHxEJ4Z/bok8 8tqJ8MDWXuP/a4v2/wdBUvMxsX3p0rFrn1zFKf3E2eaxWU+OjHqAQvLYZ33OFJdvY5ZI M/j1hn0Aammgs/B+tXlfkZmO+Wb55ISGTQWjIUUR1c5Wg3ySZkQfjICgHe7Mgfk4ujOS WiCExzX3AYggQJ6Q4J31fvNTeK9lRhOems5EeWkJwOP9ePSu38E2gEx3mkOog2HOzCDL YwCA1d0bpMxTBEikeblBdRGjOiWYn4JnrQblrlv3LKbjNaTAwpsYubmFa4N4y8D41UhN kdIg== X-Gm-Message-State: AOAM530vmfL0X8Gj/mR9Z9mSKpDBENu0tZvdtDQpi6OKesMHBOfr83lr x1UdkHHuZvbN4s54C6nFtK9jkFgZG2NO81wt X-Google-Smtp-Source: ABdhPJwxC1xj/F41v0H5XnVzziyNIhKmsc3QKEy+VvVawVWVILEfs+1ka8b4jxlkNvZDbalOWQBThQ== X-Received: by 2002:a2e:b054:0:b0:248:5819:b946 with SMTP id d20-20020a2eb054000000b002485819b946mr7119493ljl.389.1648490501549; Mon, 28 Mar 2022 11:01:41 -0700 (PDT) Received: from localhost.localdomain (host-188-190-49-235.la.net.ua. [188.190.49.235]) by smtp.gmail.com with ESMTPSA id a4-20020a2eb164000000b0024988e1cfb6sm1801559ljm.94.2022.03.28.11.01.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 28 Mar 2022 11:01:41 -0700 (PDT) From: Andrew Melnychenko To: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, virtualization@lists.linux-foundation.org Cc: kuba@kernel.org, davem@davemloft.net, jasowang@redhat.com, mst@redhat.com, yan@daynix.com, yuri.benditovich@daynix.com Subject: [PATCH v5 1/4] drivers/net/virtio_net: Fixed padded vheader to use v1 with hash. Date: Mon, 28 Mar 2022 20:53:33 +0300 Message-Id: <20220328175336.10802-2-andrew@daynix.com> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220328175336.10802-1-andrew@daynix.com> References: <20220328175336.10802-1-andrew@daynix.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" 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 | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index a801ea40908f..b9ed7c55d9a0 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -242,13 +242,13 @@ struct virtnet_info { }; =20 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]; }; =20 static bool is_xdp_frame(void *ptr) @@ -396,7 +396,7 @@ static struct sk_buff *page_to_skb(struct virtnet_info = *vi, =20 hdr_len =3D vi->hdr_len; if (vi->mergeable_rx_bufs) - hdr_padded_len =3D sizeof(*hdr); + hdr_padded_len =3D hdr_len; else hdr_padded_len =3D sizeof(struct padded_vnet_hdr); =20 @@ -1266,7 +1266,8 @@ static unsigned int get_mergeable_buf_len(struct rece= ive_queue *rq, struct ewma_pkt_len *avg_pkt_len, unsigned int room) { - const size_t hdr_len =3D sizeof(struct virtio_net_hdr_mrg_rxbuf); + struct virtnet_info *vi =3D rq->vq->vdev->priv; + const size_t hdr_len =3D vi->hdr_len; unsigned int len; =20 if (room) @@ -2851,7 +2852,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 =3D sizeof(struct virtio_net_hdr_mrg_rxbuf); + const unsigned int hdr_len =3D vi->hdr_len; unsigned int rq_size =3D virtqueue_get_vring_size(vq); unsigned int packet_len =3D vi->big_packets ? IP_MAX_MTU : vi->dev->max_m= tu; unsigned int buf_len =3D hdr_len + ETH_HLEN + VLAN_HLEN + packet_len; --=20 2.35.1 From nobody Thu Jun 25 09:39:12 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id F0010C433FE for ; Mon, 28 Mar 2022 18:02:30 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S244954AbiC1SEJ (ORCPT ); Mon, 28 Mar 2022 14:04:09 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:39354 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S245170AbiC1SD0 (ORCPT ); Mon, 28 Mar 2022 14:03:26 -0400 Received: from mail-lj1-x233.google.com (mail-lj1-x233.google.com [IPv6:2a00:1450:4864:20::233]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B41CE4B1E6 for ; Mon, 28 Mar 2022 11:01:44 -0700 (PDT) Received: by mail-lj1-x233.google.com with SMTP id g24so20300995lja.7 for ; Mon, 28 Mar 2022 11:01:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=daynix-com.20210112.gappssmtp.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=vpBON0TsJ9kCQgywxiFvAL7kx2glxEzhPvm1Ujx6csw=; b=h4Ql6Y4er3Wop84w1CW/1XxSCeqKBzR4R1kMSPSleJ9t4Zz9W3z8EUjfdJA+Uu8rRU X6zisfQ4gluF0BkAmxZ1cbonsKVGP+SXZa+9lsS8lP6wkGiCyz5nv0nSxVEJZEBDbYNA 21gHiyxtHD3VRbCf1iJQYrIt7DrUQ5K8y+RigyK7u2Ax9Px40F4vvo6Jfe20XJHX3wex B5SOL7CBBMCJOJZDwPFUrP7MyJXGFzaKVPfaN4aYsnilAO5pPiV6Sg9a/eOUbAaZQPk5 9X9M1pvsPj3fv8EypFJr5YW5LmyTNPq1yz1RBFapn3pVLyoDJ0llXfOe+aGHVkv4yAwZ xuSg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=vpBON0TsJ9kCQgywxiFvAL7kx2glxEzhPvm1Ujx6csw=; b=ePwWRuzC8ekAlW4PMxkmOoxTIUf02xpIhsZeUDXjiBCZE0A4qfz/LtbTosh5rSej8t lxBWkDTvP6QI/M8jn6vsJmH04ztW93StwpAJbwTiEH4/ue5FYhTCe9We17DLE8HfQHRw uCJGRV2HK4bnI0Iyu93FOg2Z2E5yT7Y2lqB9AnoYU3nHHW+Vk0zbVjgi6NR3hb9YXBbF wKGCyR34ATRS2Cq4XSUSoWaugXtQE1Gwz8LD000eKkY81EjSSlR582cJdHvkCu61zORV QLsk7t0Nh/kDrHGsIrAsdSXNOnRvyYpo6kiQx6qErzXdZNqd8FYnomGMqrSKv5bJ7/T6 6nVQ== X-Gm-Message-State: AOAM533U6esF+CiJwGD4n37wDqAaL6HaHF+GamgFhW/96wPKPNY1KsFD 6Lmac/snpDlGYwjERn3RXp3DsQ== X-Google-Smtp-Source: ABdhPJwo1FWpGqci9ApryQNZgzCcQt4CCr7r9u3V5z/XR2cke92sEJRhXJqbd2CsxW+SVcJ5RXx4zw== X-Received: by 2002:a2e:a907:0:b0:249:6747:d8ca with SMTP id j7-20020a2ea907000000b002496747d8camr21415025ljq.452.1648490502769; Mon, 28 Mar 2022 11:01:42 -0700 (PDT) Received: from localhost.localdomain (host-188-190-49-235.la.net.ua. [188.190.49.235]) by smtp.gmail.com with ESMTPSA id a4-20020a2eb164000000b0024988e1cfb6sm1801559ljm.94.2022.03.28.11.01.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 28 Mar 2022 11:01:42 -0700 (PDT) From: Andrew Melnychenko To: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, virtualization@lists.linux-foundation.org Cc: kuba@kernel.org, davem@davemloft.net, jasowang@redhat.com, mst@redhat.com, yan@daynix.com, yuri.benditovich@daynix.com Subject: [PATCH v5 2/4] drivers/net/virtio_net: Added basic RSS support. Date: Mon, 28 Mar 2022 20:53:34 +0300 Message-Id: <20220328175336.10802-3-andrew@daynix.com> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220328175336.10802-1-andrew@daynix.com> References: <20220328175336.10802-1-andrew@daynix.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Added features for RSS. Added initialization, RXHASH feature and ethtool ops. By default RSS/RXHASH is disabled. Virtio RSS "IPv6 extensions" hashes disabled. Added ethtools ops to set key and indirection table. Signed-off-by: Andrew Melnychenko --- drivers/net/virtio_net.c | 192 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 186 insertions(+), 6 deletions(-) diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index b9ed7c55d9a0..b5f2bb426a7b 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -169,6 +169,24 @@ struct receive_queue { struct xdp_rxq_info xdp_rxq; }; =20 +/* This structure can contain rss message with maximum settings for indire= ction table and keysize + * Note, that default structure that describes RSS configuration virtio_ne= t_rss_config + * contains same info but can't handle table values. + * In any case, structure would be passed to virtio hw through sg_buf spli= t by parts + * because table sizes may be differ according to the device configuration. + */ +#define VIRTIO_NET_RSS_MAX_KEY_SIZE 40 +#define VIRTIO_NET_RSS_MAX_TABLE_LEN 128 +struct virtio_net_ctrl_rss { + u32 hash_types; + u16 indirection_table_mask; + u16 unclassified_queue; + u16 indirection_table[VIRTIO_NET_RSS_MAX_TABLE_LEN]; + u16 max_tx_vq; + u8 hash_key_length; + 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; @@ -178,6 +196,7 @@ struct control_buf { u8 allmulti; __virtio16 vid; __virtio64 offloads; + struct virtio_net_ctrl_rss rss; }; =20 struct virtnet_info { @@ -206,6 +225,12 @@ struct virtnet_info { /* Host will merge rx buffers for big packets (shake it! shake it!) */ bool mergeable_rx_bufs; =20 + /* Host supports rss and/or hash report */ + bool has_rss; + u8 rss_key_size; + u16 rss_indir_table_size; + u32 rss_hash_types_supported; + /* Has control virtqueue */ bool has_cvq; =20 @@ -2184,6 +2209,57 @@ static void virtnet_get_ringparam(struct net_device = *dev, ring->tx_pending =3D ring->tx_max_pending; } =20 +static bool virtnet_commit_rss_command(struct virtnet_info *vi) +{ + struct net_device *dev =3D vi->dev; + struct scatterlist sgs[4]; + unsigned int sg_buf_size; + + /* prepare sgs */ + sg_init_table(sgs, 4); + + sg_buf_size =3D offsetof(struct virtio_net_ctrl_rss, indirection_table); + sg_set_buf(&sgs[0], &vi->ctrl->rss, sg_buf_size); + + sg_buf_size =3D sizeof(uint16_t) * (vi->ctrl->rss.indirection_table_mask = + 1); + sg_set_buf(&sgs[1], vi->ctrl->rss.indirection_table, sg_buf_size); + + sg_buf_size =3D offsetof(struct virtio_net_ctrl_rss, key) + - offsetof(struct virtio_net_ctrl_rss, max_tx_vq); + sg_set_buf(&sgs[2], &vi->ctrl->rss.max_tx_vq, sg_buf_size); + + sg_buf_size =3D 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, + VIRTIO_NET_CTRL_MQ_RSS_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 =3D 0; + int i =3D 0; + + vi->ctrl->rss.hash_types =3D vi->rss_hash_types_supported; + vi->ctrl->rss.indirection_table_mask =3D vi->rss_indir_table_size + ? vi->rss_indir_table_size - 1 : 0; + vi->ctrl->rss.unclassified_queue =3D 0; + + for (; i < vi->rss_indir_table_size; ++i) { + indir_val =3D ethtool_rxfh_indir_default(i, vi->curr_queue_pairs); + vi->ctrl->rss.indirection_table[i] =3D indir_val; + } + + vi->ctrl->rss.max_tx_vq =3D vi->curr_queue_pairs; + vi->ctrl->rss.hash_key_length =3D vi->rss_key_size; + + netdev_rss_key_fill(vi->ctrl->rss.key, vi->rss_key_size); +} + =20 static void virtnet_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) @@ -2412,6 +2488,71 @@ static void virtnet_update_settings(struct virtnet_i= nfo *vi) vi->duplex =3D duplex; } =20 +static u32 virtnet_get_rxfh_key_size(struct net_device *dev) +{ + return ((struct virtnet_info *)netdev_priv(dev))->rss_key_size; +} + +static u32 virtnet_get_rxfh_indir_size(struct net_device *dev) +{ + return ((struct virtnet_info *)netdev_priv(dev))->rss_indir_table_size; +} + +static int virtnet_get_rxfh(struct net_device *dev, u32 *indir, u8 *key, u= 8 *hfunc) +{ + struct virtnet_info *vi =3D netdev_priv(dev); + int i; + + if (indir) { + for (i =3D 0; i < vi->rss_indir_table_size; ++i) + indir[i] =3D vi->ctrl->rss.indirection_table[i]; + } + + if (key) + memcpy(key, vi->ctrl->rss.key, vi->rss_key_size); + + if (hfunc) + *hfunc =3D ETH_RSS_HASH_TOP; + + return 0; +} + +static int virtnet_set_rxfh(struct net_device *dev, const u32 *indir, cons= t u8 *key, const u8 hfunc) +{ + struct virtnet_info *vi =3D netdev_priv(dev); + int i; + + if (hfunc !=3D ETH_RSS_HASH_NO_CHANGE && hfunc !=3D ETH_RSS_HASH_TOP) + return -EOPNOTSUPP; + + if (indir) { + for (i =3D 0; i < vi->rss_indir_table_size; ++i) + vi->ctrl->rss.indirection_table[i] =3D indir[i]; + } + if (key) + memcpy(vi->ctrl->rss.key, key, vi->rss_key_size); + + virtnet_commit_rss_command(vi); + + return 0; +} + +static int virtnet_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc = *info, u32 *rule_locs) +{ + struct virtnet_info *vi =3D netdev_priv(dev); + int rc =3D 0; + + switch (info->cmd) { + case ETHTOOL_GRXRINGS: + info->data =3D vi->curr_queue_pairs; + break; + default: + rc =3D -EOPNOTSUPP; + } + + return rc; +} + static const struct ethtool_ops virtnet_ethtool_ops =3D { .supported_coalesce_params =3D ETHTOOL_COALESCE_MAX_FRAMES, .get_drvinfo =3D virtnet_get_drvinfo, @@ -2427,6 +2568,11 @@ static const struct ethtool_ops virtnet_ethtool_ops = =3D { .set_link_ksettings =3D virtnet_set_link_ksettings, .set_coalesce =3D virtnet_set_coalesce, .get_coalesce =3D virtnet_get_coalesce, + .get_rxfh_key_size =3D virtnet_get_rxfh_key_size, + .get_rxfh_indir_size =3D virtnet_get_rxfh_indir_size, + .get_rxfh =3D virtnet_get_rxfh, + .set_rxfh =3D virtnet_set_rxfh, + .get_rxnfc =3D virtnet_get_rxnfc, }; =20 static void virtnet_freeze_down(struct virtio_device *vdev) @@ -2679,6 +2825,16 @@ static int virtnet_set_features(struct net_device *d= ev, vi->guest_offloads =3D offloads; } =20 + if ((dev->features ^ features) & NETIF_F_RXHASH) { + if (features & NETIF_F_RXHASH) + vi->ctrl->rss.hash_types =3D vi->rss_hash_types_supported; + else + vi->ctrl->rss.hash_types =3D VIRTIO_NET_HASH_REPORT_NONE; + + if (!virtnet_commit_rss_command(vi)) + return -EINVAL; + } + return 0; } =20 @@ -3073,6 +3229,8 @@ static bool virtnet_validate_features(struct virtio_d= evice *vdev) "VIRTIO_NET_F_CTRL_VQ") || VIRTNET_FAIL_ON(vdev, VIRTIO_NET_F_MQ, "VIRTIO_NET_F_CTRL_VQ") || VIRTNET_FAIL_ON(vdev, VIRTIO_NET_F_CTRL_MAC_ADDR, + "VIRTIO_NET_F_CTRL_VQ") || + VIRTNET_FAIL_ON(vdev, VIRTIO_NET_F_RSS, "VIRTIO_NET_F_CTRL_VQ"))) { return false; } @@ -3113,13 +3271,14 @@ static int virtnet_probe(struct virtio_device *vdev) u16 max_queue_pairs; int mtu; =20 - /* Find if host supports multiqueue virtio_net device */ - err =3D 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 =3D 1; + if (virtio_has_feature(vdev, VIRTIO_NET_F_MQ) || virtio_has_feature(vdev,= VIRTIO_NET_F_RSS)) + max_queue_pairs =3D + virtio_cread16(vdev, offsetof(struct virtio_net_config, max_virtque= ue_pairs)); =20 /* 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 =3D 1; @@ -3207,6 +3366,23 @@ static int virtnet_probe(struct virtio_device *vdev) if (virtio_has_feature(vdev, VIRTIO_NET_F_MRG_RXBUF)) vi->mergeable_rx_bufs =3D true; =20 + if (virtio_has_feature(vdev, VIRTIO_NET_F_RSS)) { + vi->has_rss =3D true; + vi->rss_indir_table_size =3D + virtio_cread16(vdev, offsetof(struct virtio_net_config, + rss_max_indirection_table_length)); + vi->rss_key_size =3D + virtio_cread8(vdev, offsetof(struct virtio_net_config, rss_max_key_size= )); + + vi->rss_hash_types_supported =3D + virtio_cread32(vdev, offsetof(struct virtio_net_config, supported_ha= sh_types)); + vi->rss_hash_types_supported &=3D + ~(VIRTIO_NET_RSS_HASH_TYPE_IP_EX | + VIRTIO_NET_RSS_HASH_TYPE_TCP_EX | + VIRTIO_NET_RSS_HASH_TYPE_UDP_EX); + + dev->hw_features |=3D NETIF_F_RXHASH; + } if (virtio_has_feature(vdev, VIRTIO_NET_F_MRG_RXBUF) || virtio_has_feature(vdev, VIRTIO_F_VERSION_1)) vi->hdr_len =3D sizeof(struct virtio_net_hdr_mrg_rxbuf); @@ -3275,6 +3451,9 @@ static int virtnet_probe(struct virtio_device *vdev) } } =20 + if (vi->has_rss) + virtnet_init_default_rss(vi); + err =3D register_netdev(dev); if (err) { pr_debug("virtio_net: registering device failed\n"); @@ -3406,7 +3585,8 @@ static struct virtio_device_id id_table[] =3D { 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 =20 static unsigned int features[] =3D { VIRTNET_FEATURES, --=20 2.35.1 From nobody Thu Jun 25 09:39:12 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id E4753C433EF for ; Mon, 28 Mar 2022 18:02:40 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S244992AbiC1SET (ORCPT ); Mon, 28 Mar 2022 14:04:19 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:39384 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S245185AbiC1SD2 (ORCPT ); Mon, 28 Mar 2022 14:03:28 -0400 Received: from mail-lj1-x22b.google.com (mail-lj1-x22b.google.com [IPv6:2a00:1450:4864:20::22b]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4F8764CD59 for ; Mon, 28 Mar 2022 11:01:47 -0700 (PDT) Received: by mail-lj1-x22b.google.com with SMTP id bn33so20317254ljb.6 for ; Mon, 28 Mar 2022 11:01:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=daynix-com.20210112.gappssmtp.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=ebBwZz+tPMFcNWlsXOiLh/rBq0m4vokTaCikxzbWZ+I=; b=X5IbPxKrawXidzt0MnlIlNI+6UIZPt+h4/uLtZpoPcDRK3/mblcLBLtig7VDNFv0qW d1AWci999VtlSKMSQLLwwJPMAvmK9T4JEgkOv6Rs3uZCQwL6RHdHArZvM8LuJveaYnX8 XUeNnDbCi81y3FNC5HeeoJtIayhklwbXAUwtWbB/IA18+l/LQmDYqmh1REMnVeridmMw ZEM/vVUNoRlYR/XGP0JaB9AcwpoYqILQLe2TW6qAHlG8fplf4fjMlq1l/eMgJyz7KjYO 0lFhtW32UBhAZFXejxggIipsUsubUwWhBEOwL8UJ/mYR9nC0o0YqdZqUcR/NlirC9pAq uNmQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=ebBwZz+tPMFcNWlsXOiLh/rBq0m4vokTaCikxzbWZ+I=; b=Vuo1rBzzKk0ATWa0TRt5+rAJ/zA/4G/VJdWegdcvsxjAwxHYs4wvCip3B5Wu8kAPPB vYp8YuB4XTJDNWQbW7nV+lEKlrx8+I2tQW3+jb84ZMy85aBQzHu6lVwNl3KlODHf457u yIAsTa0vjzOUU2JXPjknb54onXdfg0DE1UZyyyxU/EOZDuKXr/SmOxAH3ZOjIaha305C bcfI0ahcN47GwwIUKyhvi5s4rIOqZB1GnRxvmhML/aINLi2NDTCpnbsavm/lkQEd1Bfl O4B2+1XxJvKgl2Sjr5wiZhUZlD5gB3RgC1vsMwyZ7GHHhWjRmYuWxwKQ8ck/7u8A/OUM 8bwg== X-Gm-Message-State: AOAM530aOXNFt8HXLuc/SpZw7yOGZmA3imk3uhJOovwqKNgW+/temFKB jodrBoez8yMwkhHBArfMGpb8v1SX+pTiAhWn X-Google-Smtp-Source: ABdhPJyANN2qk7qYtHOYQkQvlPtHqN9Y/L2X1B7fu4pz3Gp3gU0xyGflALuEDFEqbKW6LbQNUvTwUA== X-Received: by 2002:a2e:9045:0:b0:249:78ba:fbf8 with SMTP id n5-20020a2e9045000000b0024978bafbf8mr21358898ljg.218.1648490504041; Mon, 28 Mar 2022 11:01:44 -0700 (PDT) Received: from localhost.localdomain (host-188-190-49-235.la.net.ua. [188.190.49.235]) by smtp.gmail.com with ESMTPSA id a4-20020a2eb164000000b0024988e1cfb6sm1801559ljm.94.2022.03.28.11.01.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 28 Mar 2022 11:01:43 -0700 (PDT) From: Andrew Melnychenko To: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, virtualization@lists.linux-foundation.org Cc: kuba@kernel.org, davem@davemloft.net, jasowang@redhat.com, mst@redhat.com, yan@daynix.com, yuri.benditovich@daynix.com Subject: [PATCH v5 3/4] drivers/net/virtio_net: Added RSS hash report. Date: Mon, 28 Mar 2022 20:53:35 +0300 Message-Id: <20220328175336.10802-4-andrew@daynix.com> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220328175336.10802-1-andrew@daynix.com> References: <20220328175336.10802-1-andrew@daynix.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Added features for RSS hash report. If hash is provided - it sets to skb. Added checks if rss and/or hash are enabled together. Signed-off-by: Andrew Melnychenko --- drivers/net/virtio_net.c | 55 +++++++++++++++++++++++++++++++++++----- 1 file changed, 49 insertions(+), 6 deletions(-) diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index b5f2bb426a7b..c9472c30e8a2 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -227,6 +227,7 @@ struct virtnet_info { =20 /* 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; @@ -1148,6 +1149,35 @@ static struct sk_buff *receive_mergeable(struct net_= device *dev, return NULL; } =20 +static void virtio_skb_set_hash(const struct virtio_net_hdr_v1_hash *hdr_h= ash, + struct sk_buff *skb) +{ + enum pkt_hash_types rss_hash_type; + + if (!hdr_hash || !skb) + return; + + switch ((int)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 =3D 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 =3D PKT_HASH_TYPE_L3; + break; + case VIRTIO_NET_HASH_REPORT_NONE: + default: + rss_hash_type =3D PKT_HASH_TYPE_NONE; + } + skb_set_hash(skb, (unsigned int)hdr_hash->hash_value, rss_hash_type); +} + static void receive_buf(struct virtnet_info *vi, struct receive_queue *rq, void *buf, unsigned int len, void **ctx, unsigned int *xdp_xmit, @@ -1182,6 +1212,8 @@ static void receive_buf(struct virtnet_info *vi, stru= ct receive_queue *rq, return; =20 hdr =3D skb_vnet_hdr(skb); + if (dev->features & NETIF_F_RXHASH && vi->has_rss_hash_report) + virtio_skb_set_hash((const struct virtio_net_hdr_v1_hash *)hdr, skb); =20 if (hdr->hdr.flags & VIRTIO_NET_HDR_F_DATA_VALID) skb->ip_summed =3D CHECKSUM_UNNECESSARY; @@ -2232,7 +2264,8 @@ static bool virtnet_commit_rss_command(struct virtnet= _info *vi) sg_set_buf(&sgs[3], vi->ctrl->rss.key, sg_buf_size); =20 if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_MQ, - VIRTIO_NET_CTRL_MQ_RSS_CONFIG, sgs)) { + 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; } @@ -3231,6 +3264,8 @@ static bool virtnet_validate_features(struct virtio_d= evice *vdev) VIRTNET_FAIL_ON(vdev, VIRTIO_NET_F_CTRL_MAC_ADDR, "VIRTIO_NET_F_CTRL_VQ") || VIRTNET_FAIL_ON(vdev, VIRTIO_NET_F_RSS, + "VIRTIO_NET_F_CTRL_VQ") || + VIRTNET_FAIL_ON(vdev, VIRTIO_NET_F_HASH_REPORT, "VIRTIO_NET_F_CTRL_VQ"))) { return false; } @@ -3366,8 +3401,13 @@ static int virtnet_probe(struct virtio_device *vdev) if (virtio_has_feature(vdev, VIRTIO_NET_F_MRG_RXBUF)) vi->mergeable_rx_bufs =3D true; =20 - if (virtio_has_feature(vdev, VIRTIO_NET_F_RSS)) { + if (virtio_has_feature(vdev, VIRTIO_NET_F_HASH_REPORT)) + vi->has_rss_hash_report =3D true; + + if (virtio_has_feature(vdev, VIRTIO_NET_F_RSS)) vi->has_rss =3D true; + + if (vi->has_rss || vi->has_rss_hash_report) { vi->rss_indir_table_size =3D virtio_cread16(vdev, offsetof(struct virtio_net_config, rss_max_indirection_table_length)); @@ -3383,8 +3423,11 @@ static int virtnet_probe(struct virtio_device *vdev) =20 dev->hw_features |=3D NETIF_F_RXHASH; } - if (virtio_has_feature(vdev, VIRTIO_NET_F_MRG_RXBUF) || - virtio_has_feature(vdev, VIRTIO_F_VERSION_1)) + + if (vi->has_rss_hash_report) + vi->hdr_len =3D 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 =3D sizeof(struct virtio_net_hdr_mrg_rxbuf); else vi->hdr_len =3D sizeof(struct virtio_net_hdr); @@ -3451,7 +3494,7 @@ static int virtnet_probe(struct virtio_device *vdev) } } =20 - if (vi->has_rss) + if (vi->has_rss || vi->has_rss_hash_report) virtnet_init_default_rss(vi); =20 err =3D register_netdev(dev); @@ -3586,7 +3629,7 @@ static struct virtio_device_id id_table[] =3D { 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_RSS + VIRTIO_NET_F_RSS, VIRTIO_NET_F_HASH_REPORT =20 static unsigned int features[] =3D { VIRTNET_FEATURES, --=20 2.35.1 From nobody Thu Jun 25 09:39:12 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 23CBEC433EF for ; Mon, 28 Mar 2022 18:02:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S245005AbiC1SEZ (ORCPT ); Mon, 28 Mar 2022 14:04:25 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:39382 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S245186AbiC1SD2 (ORCPT ); Mon, 28 Mar 2022 14:03:28 -0400 Received: from mail-lf1-x12e.google.com (mail-lf1-x12e.google.com [IPv6:2a00:1450:4864:20::12e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 34DB34B1E6 for ; Mon, 28 Mar 2022 11:01:47 -0700 (PDT) Received: by mail-lf1-x12e.google.com with SMTP id k21so26159291lfe.4 for ; Mon, 28 Mar 2022 11:01:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=daynix-com.20210112.gappssmtp.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=XwrXFEA6ufe8dhxsMfcGXWPDSgo5Wl5hFQl5/q/s41A=; b=gHyv2qs2Yjq/ET7dkvz7OTcH8gpSmULP7P//kx11mu9/+xqOAQehRE51mGJ5/niBSX 0pVi8VNCBoiCZQbxtDiA2CchVULw9xHJglAV/fYsbDWm50j52Usq40j8ewNFccLZhlGo qoSq1PBxybT9st8xoOU0NMLqSk2uIg37bHY9L8SzZCyy2ASEhp9QVpvT2NnZFTCP/S7P G5kA9qUe+kNGWBybNNA2edLumDyI5l3BS0iGVGp8c/eNO+PsPe54aPyMUW01Dq2G3oic Mhc2dB4UWmkJ99/BOrRbrUHQjzycZs+exBjI8CGivRz2a5inPStD3soSHXV5Z9j6La7z y3Gg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=XwrXFEA6ufe8dhxsMfcGXWPDSgo5Wl5hFQl5/q/s41A=; b=nuVLDIyWFvMJL5v+YlvoCDSN2s5G+XtO7MSXmwHrbWFlfzMbERUUwKLS/UdoXmxrk4 0UGzh1otzzfQTIzXUHEK2Pk6LkHH+QNudgY1UenrCuJh6Ti3TaW8Kha8zCa7uKD5GnIE L6psbvqjh2P/asR8XsjW4pHaGApLZM3oYJGaSwriV2aXGjxp2+aQI1eq6ydwgjFIu8NE SJLvEAaEs0LujkyFuwSb2LBX8DY8ep/uq38bDUFO8UO276zDsVf957JYeQTG6FJf5+r9 U5MHD+eZjkKP+eVnpR+CHfr7wR0CVVsb2oTkdyGBSYuMcYQx9ajcOx5EPZzx261Mup9s Ysug== X-Gm-Message-State: AOAM532x1D52gXy+fK/UOpUY1bXjPTuxZfa0Elsl6sTyTb94iJiv7KG2 YG+qOM8uH4zZlEd0Cu5QcC03GA== X-Google-Smtp-Source: ABdhPJzqoqh0sgKnKs5HEqi6D3G6NXiCSBODvFvDqYTbViPzi7+Xk2QY1waFok8NORsCAwWNGH3rqQ== X-Received: by 2002:a05:6512:130c:b0:44a:2dd3:91d0 with SMTP id x12-20020a056512130c00b0044a2dd391d0mr21741491lfu.234.1648490505338; Mon, 28 Mar 2022 11:01:45 -0700 (PDT) Received: from localhost.localdomain (host-188-190-49-235.la.net.ua. [188.190.49.235]) by smtp.gmail.com with ESMTPSA id a4-20020a2eb164000000b0024988e1cfb6sm1801559ljm.94.2022.03.28.11.01.44 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 28 Mar 2022 11:01:44 -0700 (PDT) From: Andrew Melnychenko To: netdev@vger.kernel.org, linux-kernel@vger.kernel.org, virtualization@lists.linux-foundation.org Cc: kuba@kernel.org, davem@davemloft.net, jasowang@redhat.com, mst@redhat.com, yan@daynix.com, yuri.benditovich@daynix.com Subject: [PATCH v5 4/4] drivers/net/virtio_net: Added RSS hash report control. Date: Mon, 28 Mar 2022 20:53:36 +0300 Message-Id: <20220328175336.10802-5-andrew@daynix.com> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220328175336.10802-1-andrew@daynix.com> References: <20220328175336.10802-1-andrew@daynix.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Now it's possible to control supported hashflows. Added hashflow set/get callbacks. Also, disabling RXH_IP_SRC/DST for TCP would disable then 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 Disabling happens because VirtioNET hashtype for IP doesn't check L4 proto, it works for all IP packets(TCP, UDP, ICMP, etc.). For TCP and UDP, it's possible to set IP+PORT hashes. But disabling IP hashes will disable them for TCP and UDP simultaneously. It's possible to set IP+PORT for TCP/UDP and disable/enable IP for everything else(UDP, ICMP, etc.). Signed-off-by: Andrew Melnychenko --- drivers/net/virtio_net.c | 141 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 140 insertions(+), 1 deletion(-) diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index c9472c30e8a2..17eeb4f807e3 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -231,6 +231,7 @@ struct virtnet_info { u8 rss_key_size; u16 rss_indir_table_size; u32 rss_hash_types_supported; + u32 rss_hash_types_saved; =20 /* Has control virtqueue */ bool has_cvq; @@ -2278,6 +2279,7 @@ static void virtnet_init_default_rss(struct virtnet_i= nfo *vi) int i =3D 0; =20 vi->ctrl->rss.hash_types =3D vi->rss_hash_types_supported; + vi->rss_hash_types_saved =3D vi->rss_hash_types_supported; vi->ctrl->rss.indirection_table_mask =3D vi->rss_indir_table_size ? vi->rss_indir_table_size - 1 : 0; vi->ctrl->rss.unclassified_queue =3D 0; @@ -2293,6 +2295,121 @@ static void virtnet_init_default_rss(struct virtnet= _info *vi) netdev_rss_key_fill(vi->ctrl->rss.key, vi->rss_key_size); } =20 +static void virtnet_get_hashflow(const struct virtnet_info *vi, struct eth= tool_rxnfc *info) +{ + info->data =3D 0; + switch (info->flow_type) { + case TCP_V4_FLOW: + if (vi->rss_hash_types_saved & VIRTIO_NET_RSS_HASH_TYPE_TCPv4) { + info->data =3D 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 =3D 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 =3D 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 =3D 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 =3D 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 =3D 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 =3D 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 =3D RXH_IP_SRC | RXH_IP_DST; + } + break; + case IPV4_FLOW: + if (vi->rss_hash_types_saved & VIRTIO_NET_RSS_HASH_TYPE_IPv4) + info->data =3D RXH_IP_SRC | RXH_IP_DST; + + break; + case IPV6_FLOW: + if (vi->rss_hash_types_saved & VIRTIO_NET_RSS_HASH_TYPE_IPv6) + info->data =3D RXH_IP_SRC | RXH_IP_DST; + + break; + default: + info->data =3D 0; + break; + } +} + +static bool virtnet_set_hashflow(struct virtnet_info *vi, struct ethtool_r= xnfc *info) +{ + u32 new_hashtypes =3D vi->rss_hash_types_saved; + bool is_disable =3D info->data & RXH_DISCARD; + bool is_l4 =3D info->data =3D=3D (RXH_IP_SRC | RXH_IP_DST | RXH_L4_B_0_1 = | RXH_L4_B_2_3); + + /* supports only 'sd', 'sdfn' and 'r' */ + if (!((info->data =3D=3D (RXH_IP_SRC | RXH_IP_DST)) | is_l4 | is_disable)) + return false; + + switch (info->flow_type) { + case TCP_V4_FLOW: + new_hashtypes &=3D ~(VIRTIO_NET_RSS_HASH_TYPE_IPv4 | VIRTIO_NET_RSS_HASH= _TYPE_TCPv4); + if (!is_disable) + new_hashtypes |=3D VIRTIO_NET_RSS_HASH_TYPE_IPv4 + | (is_l4 ? VIRTIO_NET_RSS_HASH_TYPE_TCPv4 : 0); + break; + case UDP_V4_FLOW: + new_hashtypes &=3D ~(VIRTIO_NET_RSS_HASH_TYPE_IPv4 | VIRTIO_NET_RSS_HASH= _TYPE_UDPv4); + if (!is_disable) + new_hashtypes |=3D VIRTIO_NET_RSS_HASH_TYPE_IPv4 + | (is_l4 ? VIRTIO_NET_RSS_HASH_TYPE_UDPv4 : 0); + break; + case IPV4_FLOW: + new_hashtypes &=3D ~VIRTIO_NET_RSS_HASH_TYPE_IPv4; + if (!is_disable) + new_hashtypes =3D VIRTIO_NET_RSS_HASH_TYPE_IPv4; + break; + case TCP_V6_FLOW: + new_hashtypes &=3D ~(VIRTIO_NET_RSS_HASH_TYPE_IPv6 | VIRTIO_NET_RSS_HASH= _TYPE_TCPv6); + if (!is_disable) + new_hashtypes |=3D VIRTIO_NET_RSS_HASH_TYPE_IPv6 + | (is_l4 ? VIRTIO_NET_RSS_HASH_TYPE_TCPv6 : 0); + break; + case UDP_V6_FLOW: + new_hashtypes &=3D ~(VIRTIO_NET_RSS_HASH_TYPE_IPv6 | VIRTIO_NET_RSS_HASH= _TYPE_UDPv6); + if (!is_disable) + new_hashtypes |=3D VIRTIO_NET_RSS_HASH_TYPE_IPv6 + | (is_l4 ? VIRTIO_NET_RSS_HASH_TYPE_UDPv6 : 0); + break; + case IPV6_FLOW: + new_hashtypes &=3D ~VIRTIO_NET_RSS_HASH_TYPE_IPv6; + if (!is_disable) + new_hashtypes =3D VIRTIO_NET_RSS_HASH_TYPE_IPv6; + break; + default: + /* unsupported flow */ + return false; + } + + /* if unsupported hashtype was set */ + if (new_hashtypes !=3D (new_hashtypes & vi->rss_hash_types_supported)) + return false; + + if (new_hashtypes !=3D vi->rss_hash_types_saved) { + vi->rss_hash_types_saved =3D new_hashtypes; + vi->ctrl->rss.hash_types =3D vi->rss_hash_types_saved; + if (vi->dev->features & NETIF_F_RXHASH) + return virtnet_commit_rss_command(vi); + } + + return true; +} =20 static void virtnet_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) @@ -2578,6 +2695,27 @@ static int virtnet_get_rxnfc(struct net_device *dev,= struct ethtool_rxnfc *info, switch (info->cmd) { case ETHTOOL_GRXRINGS: info->data =3D vi->curr_queue_pairs; + break; + case ETHTOOL_GRXFH: + virtnet_get_hashflow(vi, info); + break; + default: + rc =3D -EOPNOTSUPP; + } + + return rc; +} + +static int virtnet_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc = *info) +{ + struct virtnet_info *vi =3D netdev_priv(dev); + int rc =3D 0; + + switch (info->cmd) { + case ETHTOOL_SRXFH: + if (!virtnet_set_hashflow(vi, info)) + rc =3D -EINVAL; + break; default: rc =3D -EOPNOTSUPP; @@ -2606,6 +2744,7 @@ static const struct ethtool_ops virtnet_ethtool_ops = =3D { .get_rxfh =3D virtnet_get_rxfh, .set_rxfh =3D virtnet_set_rxfh, .get_rxnfc =3D virtnet_get_rxnfc, + .set_rxnfc =3D virtnet_set_rxnfc, }; =20 static void virtnet_freeze_down(struct virtio_device *vdev) @@ -2860,7 +2999,7 @@ static int virtnet_set_features(struct net_device *de= v, =20 if ((dev->features ^ features) & NETIF_F_RXHASH) { if (features & NETIF_F_RXHASH) - vi->ctrl->rss.hash_types =3D vi->rss_hash_types_supported; + vi->ctrl->rss.hash_types =3D vi->rss_hash_types_saved; else vi->ctrl->rss.hash_types =3D VIRTIO_NET_HASH_REPORT_NONE; =20 --=20 2.35.1