Received: by 2002:a05:6a10:2726:0:0:0:0 with SMTP id ib38csp5631615pxb; Mon, 28 Mar 2022 15:13:53 -0700 (PDT) X-Google-Smtp-Source: ABdhPJzc4oqOMncF145FlJKTYK929g6y7iN3jPsMrp8miDo/xj0uXyXw8IOt/lJhWrbNyBFr8Vpr X-Received: by 2002:a17:90b:1b01:b0:1c7:79d5:696 with SMTP id nu1-20020a17090b1b0100b001c779d50696mr1246415pjb.11.1648505633393; Mon, 28 Mar 2022 15:13:53 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1648505633; cv=none; d=google.com; s=arc-20160816; b=V0dQZOziz2rd2mmSXNoTwnKdJhZPpXbspcstJ5ekLY3jGwjw2AOOtodD71aoFt8XQ8 65D1+kRgBclwPGZpA40OBAzNrR8LJ9kbub8JMceQAV0KjDh+XGt/DhRs9Daho6cLg1RG /bw3QS2wuH5Ll0nZAlEKa95E0+ED16KBYZCqIqM4zTjsoEdTfpfUrz62Auj5UuIdu8lV qFQVatYyXsp+zawVRxDHEn7x7HjUNh5j+z5cwuZd7MQRY44GmZ2X5qxFm7Uh38fFa95S 4N1VghrJOMTURoFPMxmhz0j/daSLiFNzj6yQAwLQwV7tsydTqG2XQ6BcI1m999r/9FEm wlZw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=vpBON0TsJ9kCQgywxiFvAL7kx2glxEzhPvm1Ujx6csw=; b=JlprQFWMPG3eL7scp3/D0C8d2kW1tGYEVUkiN8evT3yLZy8qi4XyljEZiKptxVTuZr tmgl8PjakogwyFnOeAIY4IDScTF0W8GxpDUKQ08YLO5DitjYxeS6WP7StVc4Du2ht+/m vjVLOHfVJ78R8eD19XKJRW/MwG4e1LfuoIwXsbp//rJ4ahqf4aTvqVeub4PlmoOrebnB 5LnDBEENUS+xVgUamWSv/IDWdiyRSVkOC83yG0R2AclmwRWs+9R+w03/43r+6dZUcQwj +p5Fm1VpMkfZztvKes0t+YEszZw9RshhSyjrT+wh3lNUfSpSOc+FKCOxNnBpQtcLfEyM Q8hA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@daynix-com.20210112.gappssmtp.com header.s=20210112 header.b=h4Ql6Y4e; spf=softfail (google.com: domain of transitioning linux-kernel-owner@vger.kernel.org does not designate 23.128.96.19 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net. [23.128.96.19]) by mx.google.com with ESMTPS id h27-20020a63385b000000b003816043f0fcsi13732410pgn.753.2022.03.28.15.13.52 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 28 Mar 2022 15:13:53 -0700 (PDT) Received-SPF: softfail (google.com: domain of transitioning linux-kernel-owner@vger.kernel.org does not designate 23.128.96.19 as permitted sender) client-ip=23.128.96.19; Authentication-Results: mx.google.com; dkim=pass header.i=@daynix-com.20210112.gappssmtp.com header.s=20210112 header.b=h4Ql6Y4e; spf=softfail (google.com: domain of transitioning linux-kernel-owner@vger.kernel.org does not designate 23.128.96.19 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 4B223170DA7; Mon, 28 Mar 2022 14:33:08 -0700 (PDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S244952AbiC1SEH (ORCPT + 99 others); Mon, 28 Mar 2022 14:04:07 -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-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: 8bit X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI,RDNS_NONE, SPF_HELO_NONE,T_SCC_BODY_TEXT_LINE autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 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; }; +/* This structure can contain rss message with maximum settings for indirection table and keysize + * Note, that default structure that describes RSS configuration virtio_net_rss_config + * contains same info but can't handle table values. + * In any case, structure would be passed to virtio hw through sg_buf split 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; }; 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; + /* 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; @@ -2184,6 +2209,57 @@ 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 = offsetof(struct virtio_net_ctrl_rss, indirection_table); + sg_set_buf(&sgs[0], &vi->ctrl->rss, sg_buf_size); + + sg_buf_size = 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 = 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 = 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 = 0; + int i = 0; + + vi->ctrl->rss.hash_types = vi->rss_hash_types_supported; + vi->ctrl->rss.indirection_table_mask = vi->rss_indir_table_size + ? vi->rss_indir_table_size - 1 : 0; + vi->ctrl->rss.unclassified_queue = 0; + + for (; i < vi->rss_indir_table_size; ++i) { + indir_val = ethtool_rxfh_indir_default(i, vi->curr_queue_pairs); + vi->ctrl->rss.indirection_table[i] = indir_val; + } + + vi->ctrl->rss.max_tx_vq = vi->curr_queue_pairs; + vi->ctrl->rss.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) @@ -2412,6 +2488,71 @@ static void virtnet_update_settings(struct virtnet_info *vi) vi->duplex = duplex; } +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, 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; +} + +static 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; +} + +static 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; + break; + 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, @@ -2427,6 +2568,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) @@ -2679,6 +2825,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.hash_types = vi->rss_hash_types_supported; + else + vi->ctrl->rss.hash_types = VIRTIO_NET_HASH_REPORT_NONE; + + if (!virtnet_commit_rss_command(vi)) + return -EINVAL; + } + return 0; } @@ -3073,6 +3229,8 @@ static bool virtnet_validate_features(struct virtio_device *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; - /* 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 = 1; + 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; @@ -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 = true; + if (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)); + + 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; + } 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); @@ -3275,6 +3451,9 @@ static int virtnet_probe(struct virtio_device *vdev) } } + if (vi->has_rss) + virtnet_init_default_rss(vi); + err = register_netdev(dev); if (err) { pr_debug("virtio_net: registering device failed\n"); @@ -3406,7 +3585,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 static unsigned int features[] = { VIRTNET_FEATURES, -- 2.35.1