From nobody Tue Jun 30 20:10:38 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 A62F4C433FE for ; Sun, 9 Jan 2022 21:07:37 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237057AbiAIVHX (ORCPT ); Sun, 9 Jan 2022 16:07:23 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54020 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232768AbiAIVHS (ORCPT ); Sun, 9 Jan 2022 16:07:18 -0500 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 F029DC06173F for ; Sun, 9 Jan 2022 13:07:17 -0800 (PST) Received: by mail-lf1-x136.google.com with SMTP id s30so9674041lfo.7 for ; Sun, 09 Jan 2022 13:07:17 -0800 (PST) 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=uG1TFygcuHO7vcN1VeccDOe78rhsfnpTNXRs/s5AciY=; b=IB0QPQ0bTMVO7PZtDHKhx20evVfLgpnfnA6QKEYRn+WQLPF6DWJ2RxtA2/0/eb3atB 3ZCsAEtXrRNOU9p4RBDkWzzPlwhabrXhSU9/ofxE/zKFTl1q0pw3rvY5eDx3gsvkRlnS mrPcDaRcxKCigvj0Cz8nKdMmW0SlFiMSvn4euaGhaW1Y0r4zogX9OLDMZGasx1DG+wuw sGFtWFrdqndEP+ONlh0ouUUVHXtynScLstgUiZqvqgMgVy5D+oA23pOS8hlm/FoCpvgd WJl3oA4yTmQWld1uQhZc9Pck/ww1xQiCKKoXBY+Gn+248cyLM7D97JwEuaznaY4MuAKj tLAg== 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=uG1TFygcuHO7vcN1VeccDOe78rhsfnpTNXRs/s5AciY=; b=dcGzJGAezXYWk1Vxv30tkB5qg/J1EXX5KAYXSjPC3vlWbXEBmIwu5AEl2tQICX1BIo vWLoOyLtg0P6nlPkvJZ9QpbLDdp+Vnae2r9bd5bSnWeooAPiqPWzWoGQlKAe1Zg5773f gTVwbkxP/pcSn7f8NhFzHuf+MIox7bXXb+INOC6gTFCv6Mv+9XhslzDgzVbT6xrqFAfG s0al2S0tUNaqN0Bh6YbL4NlN+Feq+wkGLl8SkDY2KvPG7I+ADwUs+rE1aJuhOOKFmDud iTDInID02rRwrN6vkEqBewiVIF3honCPCsmJDmfSBnyn0Oe/na4cWee172yF3AJAX73Z EmyQ== X-Gm-Message-State: AOAM531qt/Sg4tNOKR+PuHXIf8zNVHuDS0ZBMyRn5rl7oBqwa38WxOhZ tgPvWy34idS/qUbtXh+uNSAYMhl98PnVWzAi X-Google-Smtp-Source: ABdhPJxeRI+9T37ZGNuxNPDVJXBNo2d8k6wTSUFr4KBufW5inOMyrUHtS3fD/r5SHOBxdL/rymmUkQ== X-Received: by 2002:a2e:8802:: with SMTP id x2mr57534346ljh.382.1641762436228; Sun, 09 Jan 2022 13:07:16 -0800 (PST) Received: from navi.cosmonova.net.ua ([95.67.24.131]) by smtp.gmail.com with ESMTPSA id p17sm766129lfu.233.2022.01.09.13.07.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 09 Jan 2022 13:07:15 -0800 (PST) From: Andrew Melnychenko To: netdev@vger.kernel.org, virtualization@lists.linux-foundation.org, linux-kernel@vger.kernel.org, davem@davemloft.net, kuba@kernel.org, jasowang@redhat.com, mst@redhat.com Cc: yan@daynix.com, yuri.benditovich@daynix.com Subject: [PATCH 1/4] drivers/net/virtio_net: Fixed padded vheader to use v1 with hash. Date: Sun, 9 Jan 2022 23:06:56 +0200 Message-Id: <20220109210659.2866740-2-andrew@daynix.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220109210659.2866740-1-andrew@daynix.com> References: <20220109210659.2866740-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 | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index b107835242ad..66439ca488f4 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) @@ -395,7 +395,9 @@ static struct sk_buff *page_to_skb(struct virtnet_info = *vi, hdr_p =3D p; =20 hdr_len =3D vi->hdr_len; - if (vi->mergeable_rx_bufs) + if (vi->has_rss_hash_report) + hdr_padded_len =3D sizeof(struct virtio_net_hdr_v1_hash); + else if (vi->mergeable_rx_bufs) hdr_padded_len =3D sizeof(*hdr); else hdr_padded_len =3D sizeof(struct padded_vnet_hdr); @@ -1266,7 +1268,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) @@ -2849,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.34.1 From nobody Tue Jun 30 20:10:38 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 B88F7C433F5 for ; Sun, 9 Jan 2022 21:07:37 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237072AbiAIVH0 (ORCPT ); Sun, 9 Jan 2022 16:07:26 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54030 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237038AbiAIVHU (ORCPT ); Sun, 9 Jan 2022 16:07:20 -0500 Received: from mail-lf1-x132.google.com (mail-lf1-x132.google.com [IPv6:2a00:1450:4864:20::132]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2E40AC06173F for ; Sun, 9 Jan 2022 13:07:19 -0800 (PST) Received: by mail-lf1-x132.google.com with SMTP id u13so37386663lff.12 for ; Sun, 09 Jan 2022 13:07:19 -0800 (PST) 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=uAmtBE5XTkwhwH0nRAkkE7dKv+jBT+3UHOOWIsORAMY=; b=OxWA02gRFOFB3TGiUmLwcaE1xEqmyH8nRxC8sUHGIkic5Fb5K0eIumfMDUMgz4hFSC CvXYdT/VAyWR2KGs9td6eGoPpSwPeYaVJcEujuswUIobuPn8cCaVisvbOmgL0sqi8STK JFHtq2xPVi6LraZApmTJK7G+OLMf96StZXDYoRkrpebo89yH7nZ6kUHfgl5saSp1EsYb ICW64Z4N66Hkb2pOxKwWGVc2YkX/gcvpHrnOrX/H+dayKj7Smv23utFuVbbjeJstqlvI Cf0VpCd/3VYv72/3vwWItAAhuTqL5w5y2bxaDJsyvoK2YwqCmCaKG40k0J/xRLusywlO zipw== 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=uAmtBE5XTkwhwH0nRAkkE7dKv+jBT+3UHOOWIsORAMY=; b=6ehW5gGwI9G5lyjcsye0zHdrXb7tMQ3SdND7luVBuqdqqPXitzB+FAyrQRHJTzUUFH G9gtT/P6REJskUWwmcRzSK6d+Lf86GgpTRECijT1NnzdMF+hWsDFR0Eq95DrxIqybFIw n3R3/7udnb18KJL0R0LudghaxEua65yZNL+xr0X7w28mdE8jTsJOwhudqwsN1PldpNJN j4Qt1GPVhLwlpxj9coJ/Vb6c7yKlLRkl4bz1ojNGDVgeytoBOuCauM4FPxLfkK0ioZl6 IGdQ3DgiN6quSrabixyKR8XCQnScMtkrjEnnjoKhTgoaN45JSrmVlLBMLZ7MucVTkUvR 333g== X-Gm-Message-State: AOAM53028U5pTe49MgKqtgHKpBe/gaNsXmlf2BzRscu7Nmo2nG1vKG65 EFtEEKWPB9SeUOUlP9ilzFBkbQ== X-Google-Smtp-Source: ABdhPJxMkf0xv6fF90sKVT6rqo5utLKX7sTrqC/lrxCYbV2BGiftTekRjltY8WztGMAbOKK94JThBg== X-Received: by 2002:a2e:8543:: with SMTP id u3mr52946847ljj.307.1641762437311; Sun, 09 Jan 2022 13:07:17 -0800 (PST) Received: from navi.cosmonova.net.ua ([95.67.24.131]) by smtp.gmail.com with ESMTPSA id p17sm766129lfu.233.2022.01.09.13.07.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 09 Jan 2022 13:07:16 -0800 (PST) From: Andrew Melnychenko To: netdev@vger.kernel.org, virtualization@lists.linux-foundation.org, linux-kernel@vger.kernel.org, davem@davemloft.net, kuba@kernel.org, jasowang@redhat.com, mst@redhat.com Cc: yan@daynix.com, yuri.benditovich@daynix.com Subject: [PATCH 2/4] drivers/net/virtio_net: Added basic RSS support. Date: Sun, 9 Jan 2022 23:06:57 +0200 Message-Id: <20220109210659.2866740-3-andrew@daynix.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220109210659.2866740-1-andrew@daynix.com> References: <20220109210659.2866740-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 | 194 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 184 insertions(+), 10 deletions(-) diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 66439ca488f4..21794731fc75 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -169,6 +169,28 @@ 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 { + 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; @@ -178,6 +200,7 @@ struct control_buf { u8 allmulti; __virtio16 vid; __virtio64 offloads; + struct virtio_net_ctrl_rss rss; }; =20 struct virtnet_info { @@ -206,6 +229,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 @@ -395,9 +424,7 @@ static struct sk_buff *page_to_skb(struct virtnet_info = *vi, hdr_p =3D p; =20 hdr_len =3D vi->hdr_len; - if (vi->has_rss_hash_report) - hdr_padded_len =3D sizeof(struct virtio_net_hdr_v1_hash); - else if (vi->mergeable_rx_bufs) + if (vi->mergeable_rx_bufs) hdr_padded_len =3D sizeof(*hdr); else hdr_padded_len =3D sizeof(struct padded_vnet_hdr); @@ -2184,6 +2211,55 @@ 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 sizeof(vi->ctrl->rss.table_info); + sg_set_buf(&sgs[0], &vi->ctrl->rss.table_info, sg_buf_size); + + sg_buf_size =3D sizeof(uint16_t) * vi->rss_indir_table_size; + sg_set_buf(&sgs[1], vi->ctrl->rss.indirection_table, sg_buf_size); + + sg_buf_size =3D sizeof(vi->ctrl->rss.key_info); + sg_set_buf(&sgs[2], &vi->ctrl->rss.key_info, 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.table_info.hash_types =3D vi->rss_hash_types_supported; + vi->ctrl->rss.table_info.indirection_table_mask =3D vi->rss_indir_table_s= ize - 1; + vi->ctrl->rss.table_info.unclassified_queue =3D 0; + + for (; i < vi->rss_indir_table_size; ++i) { + indir_val =3D ethtool_rxfh_indir_default(i, vi->max_queue_pairs); + vi->ctrl->rss.indirection_table[i] =3D indir_val; + } + + vi->ctrl->rss.key_info.max_tx_vq =3D vi->curr_queue_pairs; + vi->ctrl->rss.key_info.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) @@ -3073,7 +3219,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"))) { + "VIRTIO_NET_F_CTRL_VQ") || + VIRTNET_FAIL_ON(vdev, VIRTIO_NET_F_RSS, "VIRTIO_NET_F_RSS"))) { return false; } =20 @@ -3113,13 +3260,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 0; + 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 +3355,25 @@ 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= )); + } + + if (vi->has_rss) { + 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 +3442,12 @@ static int virtnet_probe(struct virtio_device *vdev) } } =20 + if (vi->has_rss) { + rtnl_lock(); + virtnet_init_default_rss(vi); + rtnl_unlock(); + } + err =3D register_netdev(dev); if (err) { pr_debug("virtio_net: registering device failed\n"); @@ -3406,7 +3579,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.34.1 From nobody Tue Jun 30 20:10:38 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 18F8FC4321E for ; Sun, 9 Jan 2022 21:07:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237112AbiAIVHc (ORCPT ); Sun, 9 Jan 2022 16:07:32 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54036 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237040AbiAIVHU (ORCPT ); Sun, 9 Jan 2022 16:07:20 -0500 Received: from mail-lf1-x12b.google.com (mail-lf1-x12b.google.com [IPv6:2a00:1450:4864:20::12b]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 426A4C061751 for ; Sun, 9 Jan 2022 13:07:20 -0800 (PST) Received: by mail-lf1-x12b.google.com with SMTP id u13so37386749lff.12 for ; Sun, 09 Jan 2022 13:07:20 -0800 (PST) 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=gPMwCL078ECJkrlQTrRDDMNXwBo1Y+lA8nTpGMji1Wg=; b=jxWccFhpO5rk3jHyiLzmvF/kyhq/XU78LlunysVItkpbWP+nNSO2rgRGekjjqsuWpv 9BEcOCD0MdXnHrglMH+zDrU9LTjpcTvYCYhg3LBhRZgZxpgQE1/oRgkdjzXwFYXCyqRS fdsAKd59ou0LUqZNzK1+7hdpgbZmuOADY6Xziy7yWtdtcBKsiME4F3f6NdyEmjznmOIB jELoyra4mxTsQk69kfLiEUI0hpxImfazWWTWQugLqLoXHlLhQ6DFqe7OMjvUmwU+Zs35 FKHTmf7sGZigM73fDkyzukEeGaGndMscOyP7Vrhyc0+Y20+Wt7+tIkpbCtm08dFz4S1V yleg== 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=gPMwCL078ECJkrlQTrRDDMNXwBo1Y+lA8nTpGMji1Wg=; b=6zaLWsWe768NGL3huTRcXt3KBYyD0DhRvbCm9wmv4SR/6ZElWgTy5o0xBUCL9tjzNC 70qo6cE1gq3TIvZD7blA7axneJGiGxUo/fH6X5rD6aOQg/Qww0ybVCEyb88POHMYJQB+ 5T5QUO78iEVtRg0plVOgjOEVEmsbun5qIdavHWPJ4vkdhotPHyWO30FXFJd96qaoJHY5 ASbp5KP20xLCtNZBLENQTo+FnjJ6VV8P5cYWr82XCFPr6K9+eL2rnhDgXSYijjw0uTju oHXrS+xzIS3LxYWb4g3qbZfutSqdNa5XBS2JXuMk+uttztSijlSC3lrD+O0PRuFjLhT8 8zGA== X-Gm-Message-State: AOAM530WemdQXRlaTvZbKT2dWxtI4bifIUQeCehm3g9vcg9CB/DUYdgf 4+L7uP35cYgG8Evmd0WH9rKnRA== X-Google-Smtp-Source: ABdhPJzkLZ3kLE4tJ7kFEzPFPXa4NfnIE1rfj++1VSELHsF9723jYLQDF2/21JeeE3d2RoZJNYR1yQ== X-Received: by 2002:a2e:5d1:: with SMTP id 200mr56438738ljf.272.1641762438526; Sun, 09 Jan 2022 13:07:18 -0800 (PST) Received: from navi.cosmonova.net.ua ([95.67.24.131]) by smtp.gmail.com with ESMTPSA id p17sm766129lfu.233.2022.01.09.13.07.17 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 09 Jan 2022 13:07:17 -0800 (PST) From: Andrew Melnychenko To: netdev@vger.kernel.org, virtualization@lists.linux-foundation.org, linux-kernel@vger.kernel.org, davem@davemloft.net, kuba@kernel.org, jasowang@redhat.com, mst@redhat.com Cc: yan@daynix.com, yuri.benditovich@daynix.com Subject: [PATCH 3/4] drivers/net/virtio_net: Added RSS hash report. Date: Sun, 9 Jan 2022 23:06:58 +0200 Message-Id: <20220109210659.2866740-4-andrew@daynix.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220109210659.2866740-1-andrew@daynix.com> References: <20220109210659.2866740-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 | 56 ++++++++++++++++++++++++++++++++++------ 1 file changed, 48 insertions(+), 8 deletions(-) diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 21794731fc75..6e7461b01f87 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -231,6 +231,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; @@ -424,7 +425,9 @@ static struct sk_buff *page_to_skb(struct virtnet_info = *vi, hdr_p =3D p; =20 hdr_len =3D vi->hdr_len; - if (vi->mergeable_rx_bufs) + if (vi->has_rss_hash_report) + hdr_padded_len =3D sizeof(struct virtio_net_hdr_v1_hash); + else if (vi->mergeable_rx_bufs) hdr_padded_len =3D sizeof(*hdr); else hdr_padded_len =3D sizeof(struct padded_vnet_hdr); @@ -1160,6 +1163,8 @@ static void receive_buf(struct virtnet_info *vi, stru= ct receive_queue *rq, struct net_device *dev =3D 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; =20 if (unlikely(len < vi->hdr_len + ETH_HLEN)) { pr_debug("%s: short packet %i\n", dev->name, len); @@ -1186,6 +1191,29 @@ static void receive_buf(struct virtnet_info *vi, str= uct receive_queue *rq, return; =20 hdr =3D skb_vnet_hdr(skb); + if (dev->features & NETIF_F_RXHASH) { + hdr_hash =3D (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 =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, hdr_hash->hash_value, rss_hash_type); + } =20 if (hdr->hdr.flags & VIRTIO_NET_HDR_F_DATA_VALID) skb->ip_summed =3D CHECKSUM_UNNECESSARY; @@ -2233,7 +2261,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; } @@ -3220,7 +3249,9 @@ static bool virtnet_validate_features(struct virtio_d= evice *vdev) 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_RSS"))) { + VIRTNET_FAIL_ON(vdev, VIRTIO_NET_F_RSS, "VIRTIO_NET_F_RSS") || + VIRTNET_FAIL_ON(vdev, VIRTIO_NET_F_HASH_REPORT, + "VIRTIO_NET_F_HASH_REPORT"))) { return false; } =20 @@ -3355,6 +3386,12 @@ 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_HASH_REPORT)) { + vi->has_rss_hash_report =3D true; + vi->rss_indir_table_size =3D 1; + vi->rss_key_size =3D VIRTIO_NET_RSS_MAX_KEY_SIZE; + } + if (virtio_has_feature(vdev, VIRTIO_NET_F_RSS)) { vi->has_rss =3D true; vi->rss_indir_table_size =3D @@ -3364,7 +3401,7 @@ static int virtnet_probe(struct virtio_device *vdev) virtio_cread8(vdev, offsetof(struct virtio_net_config, rss_max_key_size= )); } =20 - if (vi->has_rss) { + if (vi->has_rss || vi->has_rss_hash_report) { vi->rss_hash_types_supported =3D virtio_cread32(vdev, offsetof(struct virtio_net_config, supported_ha= sh_types)); vi->rss_hash_types_supported &=3D @@ -3374,8 +3411,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); @@ -3442,7 +3482,7 @@ static int virtnet_probe(struct virtio_device *vdev) } } =20 - if (vi->has_rss) { + if (vi->has_rss || vi->has_rss_hash_report) { rtnl_lock(); virtnet_init_default_rss(vi); rtnl_unlock(); @@ -3580,7 +3620,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.34.1 From nobody Tue Jun 30 20:10:38 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 3EA17C4167B for ; Sun, 9 Jan 2022 21:07:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237124AbiAIVHe (ORCPT ); Sun, 9 Jan 2022 16:07:34 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54046 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237041AbiAIVHV (ORCPT ); Sun, 9 Jan 2022 16:07:21 -0500 Received: from mail-lf1-x12c.google.com (mail-lf1-x12c.google.com [IPv6:2a00:1450:4864:20::12c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 411BAC06173F for ; Sun, 9 Jan 2022 13:07:21 -0800 (PST) Received: by mail-lf1-x12c.google.com with SMTP id j11so37488848lfg.3 for ; Sun, 09 Jan 2022 13:07:21 -0800 (PST) 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=FP2HV+KB9S2snMgVXESVBDFeX2fn1V4rp/jz+fcXOVc=; b=dLABM+LnIWptARKU4HIg3R4viKD91mq4dzwmMwGvXrbqA3OmUjU7Mbd4GhxPS7Akq4 T0NblkNwn0poZnnDQ1wGZA5+dWq/KUs89JMpvrn1FvsV23FTZUyC2GILxp9dicG2tPz0 LcAIp53ZTj1kSmuDqrJ6lwci7XPaOoEOOY6mqT7hxdvPiigh7O5c6zrQfn3PQE8hrUGj o76LrrofZxhlVe5+F7MJbqmYO9zpKDKn+/YjSKvjzMJkG0WbF/+HZSG6xygfkQWcKWhY 7XxTbmdzbH461TYvKjrY5qAo+/B85Mc2GmlHZbL0OiSm2nCRWNdiA8k7X88JnobcuTyi 3+Qw== 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=FP2HV+KB9S2snMgVXESVBDFeX2fn1V4rp/jz+fcXOVc=; b=K7A5dorlZvpdslZXqo/MCAAKE7zsYDDPbSxRJRFBq3VM6Dkvzugn7bLYq6Pa7IfLm8 PEoeyIQf8uB78hZSX7kbEpWHt189YEEOU4xp200W7SPA7HqjKOo7UPBc5W0Snreo4FT3 L1Y8pqKTf3NzGcThoEFzC9x9rD4QpAOusw2WOwyRxw87SYRqRvmt7OOo38QvoPA5yrU3 QI6QdCMGIvhtXYLJ6ZVy/TUqi0NFoWgmdtdYLm9LykIpuzx+khaXvOkivM512x3r5v2T 4znKCIzTjblh/XOy3N/kn29LN62kDRsjiTcaQZUwzaaiIKT8TKjRRLePoLs36MRA+zWI Sbhg== X-Gm-Message-State: AOAM5320NUDbv768riQ0C/EW5W49TQp2Hv0/0gyEU/97dfixCYgtRJq1 uW2/gYFDoIbQfufko9gw+u/Fgg== X-Google-Smtp-Source: ABdhPJxFZAP8N5kCFdbxXfhRLVT0qaqLJZf7SKzRTUkgwUUByj41Xjj78polbwvu1TkMIH49DWPtvw== X-Received: by 2002:a2e:a230:: with SMTP id i16mr49431274ljm.494.1641762439527; Sun, 09 Jan 2022 13:07:19 -0800 (PST) Received: from navi.cosmonova.net.ua ([95.67.24.131]) by smtp.gmail.com with ESMTPSA id p17sm766129lfu.233.2022.01.09.13.07.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 09 Jan 2022 13:07:19 -0800 (PST) From: Andrew Melnychenko To: netdev@vger.kernel.org, virtualization@lists.linux-foundation.org, linux-kernel@vger.kernel.org, davem@davemloft.net, kuba@kernel.org, jasowang@redhat.com, mst@redhat.com Cc: yan@daynix.com, yuri.benditovich@daynix.com Subject: [PATCH 4/4] drivers/net/virtio_net: Added RSS hash report control. Date: Sun, 9 Jan 2022 23:06:59 +0200 Message-Id: <20220109210659.2866740-5-andrew@daynix.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220109210659.2866740-1-andrew@daynix.com> References: <20220109210659.2866740-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. Also 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 Signed-off-by: Andrew Melnychenko --- drivers/net/virtio_net.c | 159 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 159 insertions(+) diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 6e7461b01f87..1b8dd384483c 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -235,6 +235,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; @@ -2275,6 +2276,7 @@ static void virtnet_init_default_rss(struct virtnet_i= nfo *vi) int i =3D 0; =20 vi->ctrl->rss.table_info.hash_types =3D vi->rss_hash_types_supported; + vi->rss_hash_types_saved =3D vi->rss_hash_types_supported; vi->ctrl->rss.table_info.indirection_table_mask =3D vi->rss_indir_table_s= ize - 1; vi->ctrl->rss.table_info.unclassified_queue =3D 0; =20 @@ -2289,6 +2291,131 @@ 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_IPv4) + 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) +{ + u64 is_iphash =3D info->data & (RXH_IP_SRC | RXH_IP_DST); + u64 is_porthash =3D info->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3); + u32 new_hashtypes =3D vi->rss_hash_types_saved; + + if ((is_iphash && (is_iphash !=3D (RXH_IP_SRC | RXH_IP_DST))) || + (is_porthash && (is_porthash !=3D (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 &=3D ~VIRTIO_NET_RSS_HASH_TYPE_IPv4; + if (is_iphash) + new_hashtypes |=3D VIRTIO_NET_RSS_HASH_TYPE_IPv4; + + break; + case TCP_V6_FLOW: + case UDP_V6_FLOW: + case IPV6_FLOW: + new_hashtypes &=3D ~VIRTIO_NET_RSS_HASH_TYPE_IPv6; + if (is_iphash) + new_hashtypes |=3D VIRTIO_NET_RSS_HASH_TYPE_IPv6; + + break; + default: + break; + } + + switch (info->flow_type) { + case TCP_V4_FLOW: + new_hashtypes &=3D ~VIRTIO_NET_RSS_HASH_TYPE_TCPv4; + if (is_porthash) + new_hashtypes |=3D VIRTIO_NET_RSS_HASH_TYPE_TCPv4; + + break; + case UDP_V4_FLOW: + new_hashtypes &=3D ~VIRTIO_NET_RSS_HASH_TYPE_UDPv4; + if (is_porthash) + new_hashtypes |=3D VIRTIO_NET_RSS_HASH_TYPE_UDPv4; + + break; + case TCP_V6_FLOW: + new_hashtypes &=3D ~VIRTIO_NET_RSS_HASH_TYPE_TCPv6; + if (is_porthash) + new_hashtypes |=3D VIRTIO_NET_RSS_HASH_TYPE_TCPv6; + + break; + case UDP_V6_FLOW: + new_hashtypes &=3D ~VIRTIO_NET_RSS_HASH_TYPE_UDPv6; + if (is_porthash) + new_hashtypes |=3D VIRTIO_NET_RSS_HASH_TYPE_UDPv6; + + break; + default: + break; + } + + if (new_hashtypes !=3D vi->rss_hash_types_saved) { + vi->rss_hash_types_saved =3D new_hashtypes; + vi->ctrl->rss.table_info.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) @@ -2574,6 +2701,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; @@ -2602,6 +2750,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) @@ -2854,6 +3003,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.table_info.hash_types =3D vi->rss_hash_types_saved; + else + vi->ctrl->rss.table_info.hash_types =3D 0; + + if (!virtnet_commit_rss_command(vi)) + return -EINVAL; + } + return 0; } =20 --=20 2.34.1