From patchwork Sun Oct 8 05:20:45 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Akihiko Odaki X-Patchwork-Id: 13412555 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9B1B41FD5 for ; Sun, 8 Oct 2023 05:22:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=daynix-com.20230601.gappssmtp.com header.i=@daynix-com.20230601.gappssmtp.com header.b="oS7RsZl2" Received: from mail-oa1-x2f.google.com (mail-oa1-x2f.google.com [IPv6:2001:4860:4864:20::2f]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id BC1BBBD for ; Sat, 7 Oct 2023 22:22:08 -0700 (PDT) Received: by mail-oa1-x2f.google.com with SMTP id 586e51a60fabf-1dd54aca17cso2590368fac.3 for ; Sat, 07 Oct 2023 22:22:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=daynix-com.20230601.gappssmtp.com; s=20230601; t=1696742526; x=1697347326; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=wYCQ+fW716tmGuChYsDFVDZG3YnuxKzHlfuupc0GLGY=; b=oS7RsZl2BBnB13+koV64IOlKKa8vg2ZwAA/borqfKqPEZa/1e3+is7Ylvf4yRH48En iM74iFDL+D8j1YB2iuDwT+xMVEjhq9iCvCBkQDHUBJRYBSUzIYozVUFbecU1eeGizeuh 42mLyVZFsb2cOdH1sZL8DOtxPsWZHEjLkGytWmOuBeV4J69kynpFTd36Qln9bm8HWp7j baPvIi9taQCh5Q3QH+VpAMRj+fGuByknwJ+yXcf3pavrBIp5mAzJvoKN3ppi6sVXkps+ +xw5aIYmJQkfJI9U+7+JsLX7XaIx8l2xevaZ+LmPeUXYUmvNpsR1RI3R6i4hCXusxdA4 QQxw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1696742526; x=1697347326; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=wYCQ+fW716tmGuChYsDFVDZG3YnuxKzHlfuupc0GLGY=; b=qDYPPYhp4S52WTwnq/mBkHXUYmo5U1btvMeqjzi8/s9Rm7Stql7ow3fz3jZtcYzdDw vR/DUNa692WrkpTT5cXuPAtHAx9atNQl8EBT2UKnp2DYjJTPN+8+G4xcTDxRuKF++SPW 4WeBNp6gLoib4dYEWP1DmO97GRu/nkmBcLhtxOpNl1uFSda0lvLOgdLZZSWO84/i0RSO vB4wYVrDKfrwdOKmbbAUOT9wozDnYF9vSBWelwFNi468UDyyaz9jL+BXg3tqDsIXkABj 10SY4zi0abXAht84RjTQFg5FpvPdDQxuZB68pz8jFrVEaXiCz7dNFj+kvHG5zvNaw1yv uXTw== X-Gm-Message-State: AOJu0YxRAR8CVBeUCJcrWjytZVvohIpdlLViqaTcoEQol3HEdNWMp4OC bWL0Q8gLE/h1DxqVELQFz5CyDQ== X-Google-Smtp-Source: AGHT+IEBBXm6m/WtSPUhh5oF+VJBXDbr96mbF1KkK7r1eDIobYG0/oD0fn8R1wf3qYfKO3KIRt7bgg== X-Received: by 2002:a05:6870:ab83:b0:1e2:665:49e4 with SMTP id gs3-20020a056870ab8300b001e2066549e4mr10360254oab.23.1696742526036; Sat, 07 Oct 2023 22:22:06 -0700 (PDT) Received: from localhost ([2400:4050:a840:1e00:78d2:b862:10a7:d486]) by smtp.gmail.com with UTF8SMTPSA id g22-20020a1709029f9600b001c61e628e9dsm6783558plq.77.2023.10.07.22.21.59 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Sat, 07 Oct 2023 22:22:05 -0700 (PDT) From: Akihiko Odaki To: Cc: Willem de Bruijn , Jason Wang , "Michael S. Tsirkin" , Xuan Zhuo Shuah Khan , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, virtualization@lists.linux-foundation.org, linux-kselftest@vger.kernel.org, bpf@vger.kernel.org, davem@davemloft.net, kuba@kernel.org, ast@kernel.org, daniel@iogearbox.net, andrii@kernel.org, kafai@fb.com, songliubraving@fb.com, yhs@fb.com, john.fastabend@gmail.com, kpsingh@kernel.org, rdunlap@infradead.org, willemb@google.com, gustavoars@kernel.org, herbert@gondor.apana.org.au, steffen.klassert@secunet.com, nogikh@google.com, pablo@netfilter.org, decui@microsoft.com, cai@lca.pw, jakub@cloudflare.com, elver@google.com, pabeni@redhat.com, Yuri Benditovich , Akihiko Odaki Subject: [RFC PATCH 1/7] net: skbuff: Add tun_vnet_hash flag Date: Sun, 8 Oct 2023 14:20:45 +0900 Message-ID: <20231008052101.144422-2-akihiko.odaki@daynix.com> X-Mailer: git-send-email 2.42.0 In-Reply-To: <20231008052101.144422-1-akihiko.odaki@daynix.com> References: <20231008052101.144422-1-akihiko.odaki@daynix.com> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_NONE autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net X-Patchwork-State: RFC tun_vnet_hash can use this flag to indicate it stored virtio-net hash cache to cb. Signed-off-by: Akihiko Odaki --- include/linux/skbuff.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 4174c4b82d13..e638f157c13c 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -837,6 +837,7 @@ typedef unsigned char *sk_buff_data_t; * @truesize: Buffer size * @users: User count - see {datagram,tcp}.c * @extensions: allocated extensions, valid if active_extensions is nonzero + * @tun_vnet_hash: tun stored virtio-net hash cache to cb */ struct sk_buff { @@ -989,6 +990,7 @@ struct sk_buff { #if IS_ENABLED(CONFIG_IP_SCTP) __u8 csum_not_inet:1; #endif + __u8 tun_vnet_hash:1; #if defined(CONFIG_NET_SCHED) || defined(CONFIG_NET_XGRESS) __u16 tc_index; /* traffic control index */ From patchwork Sun Oct 8 05:20:46 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Akihiko Odaki X-Patchwork-Id: 13412556 X-Patchwork-Delegate: kuba@kernel.org Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C6AFE9CA6F for ; Sun, 8 Oct 2023 05:22:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=daynix-com.20230601.gappssmtp.com header.i=@daynix-com.20230601.gappssmtp.com header.b="pDAjb8r1" Received: from mail-pg1-x530.google.com (mail-pg1-x530.google.com [IPv6:2607:f8b0:4864:20::530]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id CCC37D8 for ; Sat, 7 Oct 2023 22:22:15 -0700 (PDT) Received: by mail-pg1-x530.google.com with SMTP id 41be03b00d2f7-5827f6d60aaso2131228a12.3 for ; Sat, 07 Oct 2023 22:22:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=daynix-com.20230601.gappssmtp.com; s=20230601; t=1696742535; x=1697347335; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=k5mxF0OX9xOXmYEMR+WWj7I9pRqOisNzgsEMTbX9Fcw=; b=pDAjb8r1pyoOoIgkbxYqZiqols5A9mnuszTRbedtgUp3glqaEpXhshft/kpn1fYZf8 63HnfxHvVoGFIxk75z/mnIa0QQ71xh6FvDZpx+FrAqj2lVlPZSXzfabwpUXJ3HNh8hsK VIJXWv3CRbQ31VBWx6LjmhYZ5eCvu5OADYUtRRP4ghrbuTwrADrBvQ+uy2u5kjIdcugg FV1bD7mueXYtjBMWKzN+kKdYeXRzbHOKDalr7cUVQb/jw/5zHhCbs8mJzrKtweu7qvVq 0GV/6vQRsSdMk5qNsbAAv1R5shF+vflFG86pHYBmNnAQsEFECIVuUdNqO1WJwb5qW3cd CWXQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1696742535; x=1697347335; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=k5mxF0OX9xOXmYEMR+WWj7I9pRqOisNzgsEMTbX9Fcw=; b=pVe/SKhoHJ6/Wn7zbKWdHDsVUwmGq34tjuguoptU0MqSgfM5KrDYFJGoLWmm7o7wYU DMGAFoHsYw9u60nlOeaArrOkseexC2k5+PwCZ9yHn1tsqL5SubhMdDa+ykwj5XfOiB/t mhtBejRfSPXkOVzkCUuvD6anDBUzOeFWPIrHUVPG1Atv4lTBxqryAqI4/ViHxDsiHetT lKW0gS8YZyV8K+bek8unWVAZqp20ukYHyLO/81X830dtnVCZyd+LYvav8amJ38Ztdh9o Pws0Xc9vu0yh2WkFSe/NQilsIn3drvFEzX3EMNQNuux9XDtwJWtoqp9hcdHVPhh8vYbM S7HA== X-Gm-Message-State: AOJu0Yz4juWjjxiXq63DVLobeQmGtdK6jz+XoxAuZ3VugmMMfID74//t MzvvDxHyyIRmbOMvrpea7+9wtQ== X-Google-Smtp-Source: AGHT+IG9O4pTvHffkcpbfSSY2BqjAJCrJuGtiCOgDSHXbFaxRlalyaGem1e7MjUKpdr/veWyOVwJJw== X-Received: by 2002:a05:6a00:807:b0:68f:b7f6:f1df with SMTP id m7-20020a056a00080700b0068fb7f6f1dfmr12856183pfk.5.1696742535241; Sat, 07 Oct 2023 22:22:15 -0700 (PDT) Received: from localhost ([2400:4050:a840:1e00:78d2:b862:10a7:d486]) by smtp.gmail.com with UTF8SMTPSA id ff13-20020a056a002f4d00b00693390caf39sm3945943pfb.113.2023.10.07.22.22.08 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Sat, 07 Oct 2023 22:22:14 -0700 (PDT) From: Akihiko Odaki To: Cc: Willem de Bruijn , Jason Wang , "Michael S. Tsirkin" , Xuan Zhuo Shuah Khan , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, virtualization@lists.linux-foundation.org, linux-kselftest@vger.kernel.org, bpf@vger.kernel.org, davem@davemloft.net, kuba@kernel.org, ast@kernel.org, daniel@iogearbox.net, andrii@kernel.org, kafai@fb.com, songliubraving@fb.com, yhs@fb.com, john.fastabend@gmail.com, kpsingh@kernel.org, rdunlap@infradead.org, willemb@google.com, gustavoars@kernel.org, herbert@gondor.apana.org.au, steffen.klassert@secunet.com, nogikh@google.com, pablo@netfilter.org, decui@microsoft.com, cai@lca.pw, jakub@cloudflare.com, elver@google.com, pabeni@redhat.com, Yuri Benditovich , Akihiko Odaki Subject: [RFC PATCH 2/7] net/core: Ensure qdisc_skb_cb will not be overwritten Date: Sun, 8 Oct 2023 14:20:46 +0900 Message-ID: <20231008052101.144422-3-akihiko.odaki@daynix.com> X-Mailer: git-send-email 2.42.0 In-Reply-To: <20231008052101.144422-1-akihiko.odaki@daynix.com> References: <20231008052101.144422-1-akihiko.odaki@daynix.com> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_NONE autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC Later qdisc_skb_cb will be used to deliver virtio-net hash information for tun. Signed-off-by: Akihiko Odaki --- net/core/dev.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/core/dev.c b/net/core/dev.c index 85df22f05c38..305fb465cc1e 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -3622,6 +3622,7 @@ static struct sk_buff *validate_xmit_skb(struct sk_buff *skb, struct net_device if (netif_needs_gso(skb, features)) { struct sk_buff *segs; + BUILD_BUG_ON(sizeof(struct qdisc_skb_cb) > SKB_GSO_CB_OFFSET); segs = skb_gso_segment(skb, features); if (IS_ERR(segs)) { goto out_kfree_skb; From patchwork Sun Oct 8 05:20:47 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Akihiko Odaki X-Patchwork-Id: 13412557 X-Patchwork-Delegate: kuba@kernel.org Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CA06C1FC8 for ; Sun, 8 Oct 2023 05:22:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=daynix-com.20230601.gappssmtp.com header.i=@daynix-com.20230601.gappssmtp.com header.b="V4mTdqPk" Received: from mail-oa1-x36.google.com (mail-oa1-x36.google.com [IPv6:2001:4860:4864:20::36]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id AF2EDCE for ; Sat, 7 Oct 2023 22:22:24 -0700 (PDT) Received: by mail-oa1-x36.google.com with SMTP id 586e51a60fabf-1e5602c12e5so2065622fac.3 for ; Sat, 07 Oct 2023 22:22:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=daynix-com.20230601.gappssmtp.com; s=20230601; t=1696742544; x=1697347344; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=qPY8LcetYpbUlVlPFegVlbCc6qfJazG7CQ0SWRfz3jQ=; b=V4mTdqPkPMPDZBYohbxCoqITKGbl1WAPtQHeJ05bPnuQXpUPydkT6bIx19SKcgCRDu cs/570qHa3wo8pwZw9HAGKRPm+Kc++7ODlWpRu8t+yvI3qB+gvu2H/MAQ6FbtYdNWa9z hBrcLE+OLvEYVHJSbpj433I2AKf1gWcLDffjEUr+1DDQJlKVgzGC2sAjnlrL2TEPuX6F GqDgRB8z2OjGLx4frZYvIfTc+DPMs4/8zhsHRoG3OV5JPrcLSTVX7vP9pdkGvokVqSsq Joc6EISZeZa4Hn/mRa+h9MHSp8c2WcFP80sOLhAIhIbfAPuJkQqX40C6La9bv62DJkfx EURQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1696742544; x=1697347344; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=qPY8LcetYpbUlVlPFegVlbCc6qfJazG7CQ0SWRfz3jQ=; b=lh7Gt91RjGRytOPimaOEoQ7btLfzgcUEd6UFQ/imQxjZTFkw2nJy4zWORyvSk3Gm6V Esv21mN2zn4ZtFqr7QiptuVSg4OxONROKSE4/toVQG8swZEYInyjIKtS8ayLvjCAsvRf NRw1cfec3gcccytCWsSFt/BEOBTsRCTOrUUUGYrtNtLMomsk4XgY3mv3Cy9a6vTM5p+i cwadBk+A5KqUcGx+LWUwFRyg9+CcqZrJvX0qHFZA9G2WhbgJsr6jegu3ApIwPwA0VfKk hJy8bUmgquCuwlFyn5alXIHg0mqo1XAInaoUlY63dre+GwDgJFt5dF12Ye9ozURV7PHs HTbQ== X-Gm-Message-State: AOJu0YzN3DWW0aj5iiOTg1EBv1GGC3r0E0E6081t62I8qLfv2SxAX0jE IHnlLcHYxgZ8xyGUNm0JcTaybg== X-Google-Smtp-Source: AGHT+IHTSzRT9n0IpDWOr/8WZ3/TNnoy4ql0yHPxeP449Qn02WJ+7/ihPVg6XYJwBN2eH2IMyO52BQ== X-Received: by 2002:a05:6870:6390:b0:1d6:5892:d279 with SMTP id t16-20020a056870639000b001d65892d279mr14600345oap.3.1696742544024; Sat, 07 Oct 2023 22:22:24 -0700 (PDT) Received: from localhost ([2400:4050:a840:1e00:78d2:b862:10a7:d486]) by smtp.gmail.com with UTF8SMTPSA id z15-20020a170903018f00b001c7276398f1sm6787489plg.164.2023.10.07.22.22.17 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Sat, 07 Oct 2023 22:22:23 -0700 (PDT) From: Akihiko Odaki To: Cc: Willem de Bruijn , Jason Wang , "Michael S. Tsirkin" , Xuan Zhuo Shuah Khan , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, virtualization@lists.linux-foundation.org, linux-kselftest@vger.kernel.org, bpf@vger.kernel.org, davem@davemloft.net, kuba@kernel.org, ast@kernel.org, daniel@iogearbox.net, andrii@kernel.org, kafai@fb.com, songliubraving@fb.com, yhs@fb.com, john.fastabend@gmail.com, kpsingh@kernel.org, rdunlap@infradead.org, willemb@google.com, gustavoars@kernel.org, herbert@gondor.apana.org.au, steffen.klassert@secunet.com, nogikh@google.com, pablo@netfilter.org, decui@microsoft.com, cai@lca.pw, jakub@cloudflare.com, elver@google.com, pabeni@redhat.com, Yuri Benditovich , Akihiko Odaki Subject: [RFC PATCH 3/7] net: sched: Add members to qdisc_skb_cb Date: Sun, 8 Oct 2023 14:20:47 +0900 Message-ID: <20231008052101.144422-4-akihiko.odaki@daynix.com> X-Mailer: git-send-email 2.42.0 In-Reply-To: <20231008052101.144422-1-akihiko.odaki@daynix.com> References: <20231008052101.144422-1-akihiko.odaki@daynix.com> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_NONE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC The new members will be used to deliver virtio-net hash information by tun. The other members are also reordered so that the overall size will not change. Signed-off-by: Akihiko Odaki --- include/net/sch_generic.h | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h index f232512505f8..9dfdc63859c7 100644 --- a/include/net/sch_generic.h +++ b/include/net/sch_generic.h @@ -430,13 +430,15 @@ struct tcf_proto { }; struct qdisc_skb_cb { - struct { - unsigned int pkt_len; - u16 slave_dev_queue_mapping; - u16 tc_classid; - }; #define QDISC_CB_PRIV_LEN 20 unsigned char data[QDISC_CB_PRIV_LEN]; + unsigned int pkt_len; + u16 slave_dev_queue_mapping; + union { + u16 tc_classid; + u16 tun_vnet_hash_report; + }; + u32 tun_vnet_hash_value; }; typedef void tcf_chain_head_change_t(struct tcf_proto *tp_head, void *priv); From patchwork Sun Oct 8 05:20:48 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Akihiko Odaki X-Patchwork-Id: 13412558 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A55324404 for ; Sun, 8 Oct 2023 05:22:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=daynix-com.20230601.gappssmtp.com header.i=@daynix-com.20230601.gappssmtp.com header.b="ICOmV4uF" Received: from mail-ot1-x335.google.com (mail-ot1-x335.google.com [IPv6:2607:f8b0:4864:20::335]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 863EFCA for ; Sat, 7 Oct 2023 22:22:33 -0700 (PDT) Received: by mail-ot1-x335.google.com with SMTP id 46e09a7af769-6c67060fdfbso2526204a34.2 for ; Sat, 07 Oct 2023 22:22:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=daynix-com.20230601.gappssmtp.com; s=20230601; t=1696742553; x=1697347353; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=WXV1DoyjPp87oCp4GdEnt0NdQQSYrGAY7Po/ZL34Lp4=; b=ICOmV4uFzFgRoMojgZRrOjVo8ihVN+OsyeC2HpGHwhZhTv+S8pS5zv3E3EvwRfWK6c nlrLF4V5PzUsvWf0BGN8ri0n+NhVsZER9ZJrByrLKYqAL2fpupRS3aqSONte+GM6UbSZ DJ4AsQlyvf6/U4EJbLAU3mu0HAS/VTNuTYn3SjSKSSBKcG9BYHjVMAFTOjMqNSVVwlzF fkOQmg64wFEX33Wgc/U4OEz8L+e80ulBU8Oox9UD8bYILWIeZ0iEEllRrs5n6b+KIu6U nRHPgrBH1PFJ5wFUL5GEaWeu63FU0sSB7sEZxXAoQ1Vl0g7hJYsMi+KLKQF2AYoAwD0H A/Pw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1696742553; x=1697347353; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=WXV1DoyjPp87oCp4GdEnt0NdQQSYrGAY7Po/ZL34Lp4=; b=hv+dISgVxd9+EfJ3bsZQMRzKguuWmejyskUO0JRZpZ4znwajerUQ04pihIlnbTfKrM XxEnLfsDzZSq+M7eJ96qMZI3V9DV9cmasrXgDmvNoTjKLjUXjUge8VFczxjLc5ZFxk9e /bKtDOrnPrRilgSbpONEmTN4jWHJc3ogWq7IF03q9ejKNGUKznX6Wem4LD9x3CLKz+Q4 l1tASwIPV2UC4N2SpKt9LOZhBZLBtDhVnTpECUSatvMRqb56VxXwQuXrLU9xjjb44Lz3 vnUegdQYLWrVuqLfUyJi7dkhR4KA7tql4dnDEhNWI3IOTsgqCh5dbIUcF92bhHjLKgi7 yLvw== X-Gm-Message-State: AOJu0YwuHZEFJ8jSSxZPdGCSPd9alGXZ3DGUfySne8bwMuOPs/oOxCZT HcPJ+jxVVCKTohUeNfvhLBzm2A== X-Google-Smtp-Source: AGHT+IEnM/w6bYhuIff7nAc+N4szl0w92GRiQtiPkGnHsbTVEUpZD8V3VNSUvSGiEbmYvN35F3h12A== X-Received: by 2002:a05:6870:9602:b0:1dd:443c:57a8 with SMTP id d2-20020a056870960200b001dd443c57a8mr16038022oaq.26.1696742552670; Sat, 07 Oct 2023 22:22:32 -0700 (PDT) Received: from localhost ([2400:4050:a840:1e00:78d2:b862:10a7:d486]) by smtp.gmail.com with UTF8SMTPSA id e4-20020a170902d38400b001bb9bc8d232sm6796924pld.61.2023.10.07.22.22.26 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Sat, 07 Oct 2023 22:22:32 -0700 (PDT) From: Akihiko Odaki To: Cc: Willem de Bruijn , Jason Wang , "Michael S. Tsirkin" , Xuan Zhuo Shuah Khan , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, virtualization@lists.linux-foundation.org, linux-kselftest@vger.kernel.org, bpf@vger.kernel.org, davem@davemloft.net, kuba@kernel.org, ast@kernel.org, daniel@iogearbox.net, andrii@kernel.org, kafai@fb.com, songliubraving@fb.com, yhs@fb.com, john.fastabend@gmail.com, kpsingh@kernel.org, rdunlap@infradead.org, willemb@google.com, gustavoars@kernel.org, herbert@gondor.apana.org.au, steffen.klassert@secunet.com, nogikh@google.com, pablo@netfilter.org, decui@microsoft.com, cai@lca.pw, jakub@cloudflare.com, elver@google.com, pabeni@redhat.com, Yuri Benditovich , Akihiko Odaki Subject: [RFC PATCH 4/7] virtio_net: Add functions for hashing Date: Sun, 8 Oct 2023 14:20:48 +0900 Message-ID: <20231008052101.144422-5-akihiko.odaki@daynix.com> X-Mailer: git-send-email 2.42.0 In-Reply-To: <20231008052101.144422-1-akihiko.odaki@daynix.com> References: <20231008052101.144422-1-akihiko.odaki@daynix.com> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_NONE autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net X-Patchwork-State: RFC They are useful to implement VIRTIO_NET_F_RSS and VIRTIO_NET_F_HASH_REPORT. Signed-off-by: Akihiko Odaki --- include/linux/virtio_net.h | 157 +++++++++++++++++++++++++++++++++++++ 1 file changed, 157 insertions(+) diff --git a/include/linux/virtio_net.h b/include/linux/virtio_net.h index 7b4dd69555e4..f05781ddc261 100644 --- a/include/linux/virtio_net.h +++ b/include/linux/virtio_net.h @@ -7,6 +7,143 @@ #include #include +struct virtio_net_hash { + u32 value; + u16 report; +}; + +struct virtio_net_toeplitz_state { + u32 hash; + u32 key_buffer; + const u32 *key; +}; + +#define VIRTIO_NET_SUPPORTED_HASH_TYPES (VIRTIO_NET_RSS_HASH_TYPE_IPv4 | \ + VIRTIO_NET_RSS_HASH_TYPE_TCPv4 | \ + VIRTIO_NET_RSS_HASH_TYPE_UDPv4 | \ + VIRTIO_NET_RSS_HASH_TYPE_IPv6 | \ + VIRTIO_NET_RSS_HASH_TYPE_TCPv6 | \ + VIRTIO_NET_RSS_HASH_TYPE_UDPv6) + +static inline void virtio_net_toeplitz(struct virtio_net_toeplitz_state *state, + const u32 *input, size_t len) +{ + u32 key; + + while (len) { + state->key++; + key = ntohl(*state->key); + + for (u32 bit = BIT(31); bit; bit >>= 1) { + if (*input & bit) + state->hash ^= state->key_buffer; + + state->key_buffer = + (state->key_buffer << 1) | !!(key & bit); + } + + input++; + len--; + } +} + +static inline u8 virtio_net_hash_key_length(u32 types) +{ + size_t len = 0; + + if (types & VIRTIO_NET_HASH_REPORT_IPv4) + len = max(len, + sizeof(struct flow_dissector_key_ipv4_addrs)); + + if (types & + (VIRTIO_NET_HASH_REPORT_TCPv4 | VIRTIO_NET_HASH_REPORT_UDPv4)) + len = max(len, + sizeof(struct flow_dissector_key_ipv4_addrs) + + sizeof(struct flow_dissector_key_ports)); + + if (types & VIRTIO_NET_HASH_REPORT_IPv6) + len = max(len, + sizeof(struct flow_dissector_key_ipv6_addrs)); + + if (types & + (VIRTIO_NET_HASH_REPORT_TCPv6 | VIRTIO_NET_HASH_REPORT_UDPv6)) + len = max(len, + sizeof(struct flow_dissector_key_ipv6_addrs) + + sizeof(struct flow_dissector_key_ports)); + + return 4 + len; +} + +static inline void virtio_net_hash(const struct sk_buff *skb, + u32 types, const u32 *key, + struct virtio_net_hash *hash) +{ + u16 report = VIRTIO_NET_HASH_REPORT_NONE; + struct virtio_net_toeplitz_state toeplitz_state = { + .key_buffer = ntohl(*key), + .key = key + }; + struct flow_keys flow; + + if (!skb_flow_dissect_flow_keys(skb, &flow, 0)) + return; + + switch (flow.basic.n_proto) { + case htons(ETH_P_IP): + if (flow.basic.ip_proto == IPPROTO_TCP && + (types & VIRTIO_NET_RSS_HASH_TYPE_TCPv4)) { + report = VIRTIO_NET_HASH_REPORT_TCPv4; + virtio_net_toeplitz(&toeplitz_state, + (u32 *)&flow.addrs.v4addrs, + sizeof(flow.addrs.v4addrs) / 4); + virtio_net_toeplitz(&toeplitz_state, &flow.ports.ports, + 1); + } else if (flow.basic.ip_proto == IPPROTO_UDP && + (types & VIRTIO_NET_RSS_HASH_TYPE_UDPv4)) { + report = VIRTIO_NET_HASH_REPORT_UDPv4; + virtio_net_toeplitz(&toeplitz_state, + (u32 *)&flow.addrs.v4addrs, + sizeof(flow.addrs.v4addrs) / 4); + virtio_net_toeplitz(&toeplitz_state, &flow.ports.ports, + 1); + } else if (types & VIRTIO_NET_RSS_HASH_TYPE_IPv4) { + report = VIRTIO_NET_HASH_REPORT_IPv4; + virtio_net_toeplitz(&toeplitz_state, + (u32 *)&flow.addrs.v4addrs, + sizeof(flow.addrs.v4addrs) / 4); + } + break; + + case htons(ETH_P_IPV6): + if (flow.basic.ip_proto == IPPROTO_TCP && + (types & VIRTIO_NET_RSS_HASH_TYPE_TCPv6)) { + report = VIRTIO_NET_HASH_REPORT_TCPv6; + virtio_net_toeplitz(&toeplitz_state, + (u32 *)&flow.addrs.v6addrs, + sizeof(flow.addrs.v6addrs) / 4); + virtio_net_toeplitz(&toeplitz_state, &flow.ports.ports, + 1); + } else if (flow.basic.ip_proto == IPPROTO_UDP && + (types & VIRTIO_NET_RSS_HASH_TYPE_UDPv6)) { + report = VIRTIO_NET_HASH_REPORT_UDPv6; + virtio_net_toeplitz(&toeplitz_state, + (u32 *)&flow.addrs.v6addrs, + sizeof(flow.addrs.v6addrs) / 4); + virtio_net_toeplitz(&toeplitz_state, &flow.ports.ports, + 1); + } else if (types & VIRTIO_NET_RSS_HASH_TYPE_IPv6) { + report = VIRTIO_NET_HASH_REPORT_IPv6; + virtio_net_toeplitz(&toeplitz_state, + (u32 *)&flow.addrs.v6addrs, + sizeof(flow.addrs.v6addrs) / 4); + } + break; + } + + hash->value = toeplitz_state.hash; + hash->report = report; +} + static inline bool virtio_net_hdr_match_proto(__be16 protocol, __u8 gso_type) { switch (gso_type & ~VIRTIO_NET_HDR_GSO_ECN) { @@ -216,4 +353,24 @@ static inline int virtio_net_hdr_from_skb(const struct sk_buff *skb, return 0; } +static inline int virtio_net_hdr_v1_hash_from_skb(const struct sk_buff *skb, + struct virtio_net_hdr_v1_hash *hdr, + bool has_data_valid, + int vlan_hlen, + const struct virtio_net_hash *hash) +{ + int ret; + + memset(hdr, 0, sizeof(*hdr)); + + ret = virtio_net_hdr_from_skb(skb, (struct virtio_net_hdr *)hdr, + true, has_data_valid, vlan_hlen); + if (!ret) { + hdr->hash_value = cpu_to_le32(hash->value); + hdr->hash_report = cpu_to_le16(hash->report); + } + + return ret; +} + #endif /* _LINUX_VIRTIO_NET_H */ From patchwork Sun Oct 8 05:20:49 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Akihiko Odaki X-Patchwork-Id: 13412559 X-Patchwork-Delegate: kuba@kernel.org Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 26CEF3D67 for ; Sun, 8 Oct 2023 05:22:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=daynix-com.20230601.gappssmtp.com header.i=@daynix-com.20230601.gappssmtp.com header.b="beWt45x9" Received: from mail-pf1-x42d.google.com (mail-pf1-x42d.google.com [IPv6:2607:f8b0:4864:20::42d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id F3193D8 for ; Sat, 7 Oct 2023 22:22:41 -0700 (PDT) Received: by mail-pf1-x42d.google.com with SMTP id d2e1a72fcca58-690b7cb71aeso2601035b3a.0 for ; Sat, 07 Oct 2023 22:22:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=daynix-com.20230601.gappssmtp.com; s=20230601; t=1696742561; x=1697347361; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=VNEYNcUIQ02Z47r7DMDdtClBgN2jorlreZmQMyrQ9r0=; b=beWt45x9XHhiZftn0IA9xjbSV2VX0nxSvGuDTo5NHegCwVpmWmV4boT3C6I3sfTYFx IwGg4740mYSy5vGofP6VuuA+25nr/rWU9BOALEwX/40ZnzTZqnT8Axg0XlhT9In9Xclz ZNyEGuJcnOuqnhdatsIviQlbwtLpTQVzwz/9cMV1dnvroh9TvlBCRvQ/HNcaLvP20dRj Sy53YEFoJXy0h+a9QRWNct32qmlkekzMC3YUN/jdUK/MQwap+t//40cYz6ywLrn8JfIi l8XcZ7dd+neDl4lIpfaMkUHpV6REbx73VBW+j03gbnpEDpW6PcSLUsdJkM3WKBmAgEu+ 2IYw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1696742561; x=1697347361; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=VNEYNcUIQ02Z47r7DMDdtClBgN2jorlreZmQMyrQ9r0=; b=kng+lRNRMcBKuZLXnpEXKPvEKVpFtFkBuoh+JxMSS1EYzlmY8tGxHJT/90KWkX/jFw bcI978hiZ7Qocj1dhAbNYZv5FYg9DvkD2C/xsHYR5C5y8pCOL6TN7uHe1IpdChyGug48 2IFs4X20MqihSoymcy8RYuNJM9S+tQpfT82j5eW89kVjjs8xO2WXw4jB7FtaYJ+0OTFW 0kRYPhrbc5w1mnQsfJOTB55zK/hc6s23lw0Ch0aSH5h7fqERvt5NW+BKBd+GFvF1nZmo PKtOUGgX3G1/e3Z/vPKQLtxzJX1pKNDXnlAJgbGZYi0E99+XvFy1yoHnz+Jkv4gTUamw V6+g== X-Gm-Message-State: AOJu0YzuPtQAdOXN4vYJsFtSt/s/PEUgYEKrH9ptishOBPhNUhleNKBO LfJj4/vwdGSOspWDxLBr+0gRSA== X-Google-Smtp-Source: AGHT+IGY5tnRnPz8E+W9dEDOenN+gDxxh23v4PsChY6hQrk8ypyfQ6NhuytLuwAbjEnGq6UL78YBoQ== X-Received: by 2002:a05:6a00:1ad1:b0:68f:d44c:22f8 with SMTP id f17-20020a056a001ad100b0068fd44c22f8mr12614847pfv.1.1696742561319; Sat, 07 Oct 2023 22:22:41 -0700 (PDT) Received: from localhost ([2400:4050:a840:1e00:78d2:b862:10a7:d486]) by smtp.gmail.com with UTF8SMTPSA id j20-20020a62b614000000b0068fe5a5a566sm4054525pff.142.2023.10.07.22.22.35 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Sat, 07 Oct 2023 22:22:41 -0700 (PDT) From: Akihiko Odaki To: Cc: Willem de Bruijn , Jason Wang , "Michael S. Tsirkin" , Xuan Zhuo Shuah Khan , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, virtualization@lists.linux-foundation.org, linux-kselftest@vger.kernel.org, bpf@vger.kernel.org, davem@davemloft.net, kuba@kernel.org, ast@kernel.org, daniel@iogearbox.net, andrii@kernel.org, kafai@fb.com, songliubraving@fb.com, yhs@fb.com, john.fastabend@gmail.com, kpsingh@kernel.org, rdunlap@infradead.org, willemb@google.com, gustavoars@kernel.org, herbert@gondor.apana.org.au, steffen.klassert@secunet.com, nogikh@google.com, pablo@netfilter.org, decui@microsoft.com, cai@lca.pw, jakub@cloudflare.com, elver@google.com, pabeni@redhat.com, Yuri Benditovich , Akihiko Odaki Subject: [RFC PATCH 5/7] tun: Introduce virtio-net hashing feature Date: Sun, 8 Oct 2023 14:20:49 +0900 Message-ID: <20231008052101.144422-6-akihiko.odaki@daynix.com> X-Mailer: git-send-email 2.42.0 In-Reply-To: <20231008052101.144422-1-akihiko.odaki@daynix.com> References: <20231008052101.144422-1-akihiko.odaki@daynix.com> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_NONE autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC virtio-net have two usage of hashes: one is RSS and another is hash reporting. Conventionally the hash calculation was done by the VMM. However, computing the hash after the queue was chosen defeats the purpose of RSS. Another approach is to use eBPF steering program. This approach has another downside: it cannot report the calculated hash due to the restrictive nature of eBPF. Introduce the code to compute hashes to the kernel in order to overcome thse challenges. An alternative solution is to extend the eBPF steering program so that it will be able to report to the userspace, but it makes little sense to allow to implement different hashing algorithms with eBPF since the hash value reported by virtio-net is strictly defined by the specification. The hash value already stored in sk_buff is not used and computed independently since it may have been computed in a way not conformant with the specification. Signed-off-by: Akihiko Odaki --- drivers/net/tun.c | 187 ++++++++++++++++++++++++++++++++---- include/uapi/linux/if_tun.h | 16 +++ 2 files changed, 182 insertions(+), 21 deletions(-) diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 89ab9efe522c..561a573cd008 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -171,6 +171,9 @@ struct tun_prog { struct bpf_prog *prog; }; +#define TUN_VNET_HASH_MAX_KEY_SIZE 40 +#define TUN_VNET_HASH_MAX_INDIRECTION_TABLE_LENGTH 128 + /* Since the socket were moved to tun_file, to preserve the behavior of persist * device, socket filter, sndbuf and vnet header size were restore when the * file were attached to a persist device. @@ -209,6 +212,9 @@ struct tun_struct { struct tun_prog __rcu *steering_prog; struct tun_prog __rcu *filter_prog; struct ethtool_link_ksettings link_ksettings; + struct tun_vnet_hash vnet_hash; + u16 vnet_hash_indirection_table[TUN_VNET_HASH_MAX_INDIRECTION_TABLE_LENGTH]; + u32 vnet_hash_key[TUN_VNET_HASH_MAX_KEY_SIZE / 4]; /* init args */ struct file *file; struct ifreq *ifr; @@ -219,6 +225,13 @@ struct veth { __be16 h_vlan_TCI; }; +static const struct tun_vnet_hash_cap tun_vnet_hash_cap = { + .max_indirection_table_length = + TUN_VNET_HASH_MAX_INDIRECTION_TABLE_LENGTH, + + .types = VIRTIO_NET_SUPPORTED_HASH_TYPES +}; + static void tun_flow_init(struct tun_struct *tun); static void tun_flow_uninit(struct tun_struct *tun); @@ -320,10 +333,16 @@ static long tun_set_vnet_be(struct tun_struct *tun, int __user *argp) if (get_user(be, argp)) return -EFAULT; - if (be) + if (be) { + if (!(tun->flags & TUN_VNET_LE) && + (tun->vnet_hash.flags & TUN_VNET_HASH_REPORT)) { + return -EINVAL; + } + tun->flags |= TUN_VNET_BE; - else + } else { tun->flags &= ~TUN_VNET_BE; + } return 0; } @@ -558,15 +577,47 @@ static u16 tun_ebpf_select_queue(struct tun_struct *tun, struct sk_buff *skb) return ret % numqueues; } +static u16 tun_vnet_select_queue(struct tun_struct *tun, struct sk_buff *skb) +{ + u32 value = qdisc_skb_cb(skb)->tun_vnet_hash_value; + u32 numqueues; + u32 index; + u16 queue; + + numqueues = READ_ONCE(tun->numqueues); + if (!numqueues) + return 0; + + index = value & READ_ONCE(tun->vnet_hash.indirection_table_mask); + queue = READ_ONCE(tun->vnet_hash_indirection_table[index]); + if (!queue) + queue = READ_ONCE(tun->vnet_hash.unclassified_queue); + + return queue % numqueues; +} + static u16 tun_select_queue(struct net_device *dev, struct sk_buff *skb, struct net_device *sb_dev) { struct tun_struct *tun = netdev_priv(dev); + u8 vnet_hash_flags = READ_ONCE(tun->vnet_hash.flags); + struct virtio_net_hash hash; u16 ret; + if (vnet_hash_flags & (TUN_VNET_HASH_RSS | TUN_VNET_HASH_REPORT)) { + virtio_net_hash(skb, READ_ONCE(tun->vnet_hash.types), + tun->vnet_hash_key, &hash); + + skb->tun_vnet_hash = true; + qdisc_skb_cb(skb)->tun_vnet_hash_value = hash.value; + qdisc_skb_cb(skb)->tun_vnet_hash_report = hash.report; + } + rcu_read_lock(); if (rcu_dereference(tun->steering_prog)) ret = tun_ebpf_select_queue(tun, skb); + else if (vnet_hash_flags & TUN_VNET_HASH_RSS) + ret = tun_vnet_select_queue(tun, skb); else ret = tun_automq_select_queue(tun, skb); rcu_read_unlock(); @@ -2088,10 +2139,15 @@ static ssize_t tun_put_user(struct tun_struct *tun, struct iov_iter *iter) { struct tun_pi pi = { 0, skb->protocol }; + struct virtio_net_hash vnet_hash = { + .value = qdisc_skb_cb(skb)->tun_vnet_hash_value, + .report = qdisc_skb_cb(skb)->tun_vnet_hash_report + }; ssize_t total; int vlan_offset = 0; int vlan_hlen = 0; int vnet_hdr_sz = 0; + size_t vnet_hdr_content_sz; if (skb_vlan_tag_present(skb)) vlan_hlen = VLAN_HLEN; @@ -2116,31 +2172,49 @@ static ssize_t tun_put_user(struct tun_struct *tun, } if (vnet_hdr_sz) { - struct virtio_net_hdr gso; + union { + struct virtio_net_hdr hdr; + struct virtio_net_hdr_v1_hash v1_hash_hdr; + } hdr; + int ret; if (iov_iter_count(iter) < vnet_hdr_sz) return -EINVAL; - if (virtio_net_hdr_from_skb(skb, &gso, - tun_is_little_endian(tun), true, - vlan_hlen)) { + if ((READ_ONCE(tun->vnet_hash.flags) & TUN_VNET_HASH_REPORT) && + vnet_hdr_sz >= sizeof(hdr.v1_hash_hdr) && + skb->tun_vnet_hash) { + vnet_hdr_content_sz = sizeof(hdr.v1_hash_hdr); + ret = virtio_net_hdr_v1_hash_from_skb(skb, + &hdr.v1_hash_hdr, + true, + vlan_hlen, + &vnet_hash); + } else { + vnet_hdr_content_sz = sizeof(hdr.hdr); + ret = virtio_net_hdr_from_skb(skb, &hdr.hdr, + tun_is_little_endian(tun), + true, vlan_hlen); + } + + if (ret) { struct skb_shared_info *sinfo = skb_shinfo(skb); pr_err("unexpected GSO type: " "0x%x, gso_size %d, hdr_len %d\n", - sinfo->gso_type, tun16_to_cpu(tun, gso.gso_size), - tun16_to_cpu(tun, gso.hdr_len)); + sinfo->gso_type, tun16_to_cpu(tun, hdr.hdr.gso_size), + tun16_to_cpu(tun, hdr.hdr.hdr_len)); print_hex_dump(KERN_ERR, "tun: ", DUMP_PREFIX_NONE, 16, 1, skb->head, - min((int)tun16_to_cpu(tun, gso.hdr_len), 64), true); + min((int)tun16_to_cpu(tun, hdr.hdr.hdr_len), 64), true); WARN_ON_ONCE(1); return -EINVAL; } - if (copy_to_iter(&gso, sizeof(gso), iter) != sizeof(gso)) + if (copy_to_iter(&hdr, vnet_hdr_content_sz, iter) != vnet_hdr_content_sz) return -EFAULT; - iov_iter_advance(iter, vnet_hdr_sz - sizeof(gso)); + iov_iter_advance(iter, vnet_hdr_sz - vnet_hdr_content_sz); } if (vlan_hlen) { @@ -3007,24 +3081,27 @@ static int tun_set_queue(struct file *file, struct ifreq *ifr) return ret; } -static int tun_set_ebpf(struct tun_struct *tun, struct tun_prog __rcu **prog_p, - void __user *data) +static struct bpf_prog *tun_set_ebpf(struct tun_struct *tun, + struct tun_prog __rcu **prog_p, + void __user *data) { struct bpf_prog *prog; int fd; + int ret; if (copy_from_user(&fd, data, sizeof(fd))) - return -EFAULT; + return ERR_PTR(-EFAULT); if (fd == -1) { prog = NULL; } else { prog = bpf_prog_get_type(fd, BPF_PROG_TYPE_SOCKET_FILTER); if (IS_ERR(prog)) - return PTR_ERR(prog); + return prog; } - return __tun_set_ebpf(tun, prog_p, prog); + ret = __tun_set_ebpf(tun, prog_p, prog); + return ret ? ERR_PTR(ret) : prog; } /* Return correct value for tun->dev->addr_len based on tun->dev->type. */ @@ -3082,6 +3159,11 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd, int le; int ret; bool do_notify = false; + struct bpf_prog *bpf_ret; + struct tun_vnet_hash vnet_hash; + u16 vnet_hash_indirection_table[TUN_VNET_HASH_MAX_INDIRECTION_TABLE_LENGTH]; + u8 vnet_hash_key[TUN_VNET_HASH_MAX_KEY_SIZE]; + size_t len; if (cmd == TUNSETIFF || cmd == TUNSETQUEUE || (_IOC_TYPE(cmd) == SOCK_IOC_TYPE && cmd != SIOCGSKNS)) { @@ -3295,7 +3377,10 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd, ret = -EFAULT; break; } - if (vnet_hdr_sz < (int)sizeof(struct virtio_net_hdr)) { + if (vnet_hdr_sz < + (int)((tun->vnet_hash.flags & TUN_VNET_HASH_REPORT) ? + sizeof(struct virtio_net_hdr_v1_hash) : + sizeof(struct virtio_net_hdr))) { ret = -EINVAL; break; } @@ -3314,10 +3399,16 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd, ret = -EFAULT; break; } - if (le) + if (le) { tun->flags |= TUN_VNET_LE; - else + } else { + if (!tun_legacy_is_little_endian(tun)) { + ret = -EINVAL; + break; + } + tun->flags &= ~TUN_VNET_LE; + } break; case TUNGETVNETBE: @@ -3360,11 +3451,17 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd, break; case TUNSETSTEERINGEBPF: - ret = tun_set_ebpf(tun, &tun->steering_prog, argp); + bpf_ret = tun_set_ebpf(tun, &tun->steering_prog, argp); + if (IS_ERR(bpf_ret)) + ret = PTR_ERR(bpf_ret); + else if (bpf_ret) + tun->vnet_hash.flags &= ~TUN_VNET_HASH_RSS; break; case TUNSETFILTEREBPF: - ret = tun_set_ebpf(tun, &tun->filter_prog, argp); + bpf_ret = tun_set_ebpf(tun, &tun->filter_prog, argp); + if (IS_ERR(bpf_ret)) + ret = PTR_ERR(bpf_ret); break; case TUNSETCARRIER: @@ -3382,6 +3479,54 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd, ret = open_related_ns(&net->ns, get_net_ns); break; + case TUNGETVNETHASHCAP: + if (copy_to_user(argp, &tun_vnet_hash_cap, + sizeof(tun_vnet_hash_cap))) + ret = -EFAULT; + break; + + case TUNSETVNETHASH: + len = sizeof(vnet_hash); + if (copy_from_user(&vnet_hash, argp, len)) { + ret = -EFAULT; + break; + } + + if (((vnet_hash.flags & TUN_VNET_HASH_REPORT) && + (tun->vnet_hdr_sz < sizeof(struct virtio_net_hdr_v1_hash) || + !tun_is_little_endian(tun))) || + vnet_hash.indirection_table_mask >= + TUN_VNET_HASH_MAX_INDIRECTION_TABLE_LENGTH) { + ret = -EINVAL; + break; + } + + argp = (u8 __user *)argp + len; + len = (vnet_hash.indirection_table_mask + 1) * 2; + if (copy_from_user(vnet_hash_indirection_table, argp, len)) { + ret = -EFAULT; + break; + } + + argp = (u8 __user *)argp + len; + len = virtio_net_hash_key_length(vnet_hash.types); + + if (copy_from_user(vnet_hash_key, argp, len)) { + ret = -EFAULT; + break; + } + + tun->vnet_hash = vnet_hash; + memcpy(tun->vnet_hash_indirection_table, + vnet_hash_indirection_table, + (vnet_hash.indirection_table_mask + 1) * 2); + memcpy(tun->vnet_hash_key, vnet_hash_key, len); + + if (vnet_hash.flags & TUN_VNET_HASH_RSS) + __tun_set_ebpf(tun, &tun->steering_prog, NULL); + + break; + default: ret = -EINVAL; break; diff --git a/include/uapi/linux/if_tun.h b/include/uapi/linux/if_tun.h index 287cdc81c939..dc591cd897c8 100644 --- a/include/uapi/linux/if_tun.h +++ b/include/uapi/linux/if_tun.h @@ -61,6 +61,8 @@ #define TUNSETFILTEREBPF _IOR('T', 225, int) #define TUNSETCARRIER _IOW('T', 226, int) #define TUNGETDEVNETNS _IO('T', 227) +#define TUNGETVNETHASHCAP _IO('T', 228) +#define TUNSETVNETHASH _IOW('T', 229, unsigned int) /* TUNSETIFF ifr flags */ #define IFF_TUN 0x0001 @@ -115,4 +117,18 @@ struct tun_filter { __u8 addr[][ETH_ALEN]; }; +struct tun_vnet_hash_cap { + __u16 max_indirection_table_length; + __u32 types; +}; + +#define TUN_VNET_HASH_RSS 0x01 +#define TUN_VNET_HASH_REPORT 0x02 +struct tun_vnet_hash { + __u8 flags; + __u32 types; + __u16 indirection_table_mask; + __u16 unclassified_queue; +}; + #endif /* _UAPI__IF_TUN_H */ From patchwork Sun Oct 8 05:20:50 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Akihiko Odaki X-Patchwork-Id: 13412560 X-Patchwork-Delegate: kuba@kernel.org Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DAA031FC8 for ; Sun, 8 Oct 2023 05:22:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=daynix-com.20230601.gappssmtp.com header.i=@daynix-com.20230601.gappssmtp.com header.b="vvSK8kZQ" Received: from mail-pf1-x42a.google.com (mail-pf1-x42a.google.com [IPv6:2607:f8b0:4864:20::42a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 10717C6 for ; Sat, 7 Oct 2023 22:22:51 -0700 (PDT) Received: by mail-pf1-x42a.google.com with SMTP id d2e1a72fcca58-69101022969so3128780b3a.3 for ; Sat, 07 Oct 2023 22:22:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=daynix-com.20230601.gappssmtp.com; s=20230601; t=1696742570; x=1697347370; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=oKBP9OidVZtRjyPI+dL7f0Ou7EZ8mYm7HxjxyAavXjY=; b=vvSK8kZQtk0o++AJ/wQ3H9cIiAUNeDlPvKenKS9pxFGBkUgi2Lqi3FZJVjC3GqYzW5 sB3XpCizq93t/e9Fd6ibctWLD7zPrds7GpT4Kz4/ZIIu27iMiFwUAw6G+erAiv3rcHbk bKR+Th74BWLc7GIVszisIpI1aTO5O8r433Ki7Vk/OuAl6GUMpvmqoT8yaFFiF5C1nNXz Vy45AQZsleY+8UUee1vhMBvxgpAI1Mth4IbrUzdud70Rp7pKR7bXx5CKfo2aDdUzD2aw Ec3tU1JuvTZtXp0tpLS9HpjNaP8qC5v2Lj5UUGwn4dpuLNPHook9A2S9WDRmJN/0UWv+ 3o0g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1696742570; x=1697347370; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=oKBP9OidVZtRjyPI+dL7f0Ou7EZ8mYm7HxjxyAavXjY=; b=h0fSJuUgd5+l8MWtk4Fmkgwe8Wlmu+dUZupEv2KRUhUJgfHLAN+R5ebn+lvA5UT0uO OB1vee1D/fpGOWFHWpfkdpeXv/U5wUE99LLgUNNVwJnLmR6zd+2tguH07F3qFWIAf2Pb t6Tyl9o3mSHNRT3OE2053vlYwkq3FLdCeY7bmUW4g8mdBQWYpLgWkGkFsDBuhPih/Soe TBL7586IyECdohfO1537qWvOzVwq31xSVKAmmg5rwnZ0nmngZdRIUELAg0T5L4esK9O/ +mtnt0zv7dumjr415Oe0zrKDVwP4pdAWsvDNrbLgUbTNpU98+MDp5d7IJ6bsK8K5C2L0 cbgg== X-Gm-Message-State: AOJu0YzS58+s2j3BtwALDY1kYEyXo3uYKBwBJ1rvRJ6mNArjFzRiFult R4lBhAG4oJK2UaUK7eR5+Y/9SQ== X-Google-Smtp-Source: AGHT+IG36H9U5TphBvXsn5jJ+RFrSEAA6EIqoSwejagR/ikRbdmjuiGs25vIJjx3PZ2OM+wTCNw+Mw== X-Received: by 2002:a05:6a00:348f:b0:696:8874:c12b with SMTP id cp15-20020a056a00348f00b006968874c12bmr12867686pfb.13.1696742570518; Sat, 07 Oct 2023 22:22:50 -0700 (PDT) Received: from localhost ([2400:4050:a840:1e00:78d2:b862:10a7:d486]) by smtp.gmail.com with UTF8SMTPSA id k14-20020aa792ce000000b006933f85bc29sm3958551pfa.111.2023.10.07.22.22.43 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Sat, 07 Oct 2023 22:22:50 -0700 (PDT) From: Akihiko Odaki To: Cc: Willem de Bruijn , Jason Wang , "Michael S. Tsirkin" , Xuan Zhuo Shuah Khan , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, virtualization@lists.linux-foundation.org, linux-kselftest@vger.kernel.org, bpf@vger.kernel.org, davem@davemloft.net, kuba@kernel.org, ast@kernel.org, daniel@iogearbox.net, andrii@kernel.org, kafai@fb.com, songliubraving@fb.com, yhs@fb.com, john.fastabend@gmail.com, kpsingh@kernel.org, rdunlap@infradead.org, willemb@google.com, gustavoars@kernel.org, herbert@gondor.apana.org.au, steffen.klassert@secunet.com, nogikh@google.com, pablo@netfilter.org, decui@microsoft.com, cai@lca.pw, jakub@cloudflare.com, elver@google.com, pabeni@redhat.com, Yuri Benditovich , Akihiko Odaki Subject: [RFC PATCH 6/7] selftest: tun: Add tests for virtio-net hashing Date: Sun, 8 Oct 2023 14:20:50 +0900 Message-ID: <20231008052101.144422-7-akihiko.odaki@daynix.com> X-Mailer: git-send-email 2.42.0 In-Reply-To: <20231008052101.144422-1-akihiko.odaki@daynix.com> References: <20231008052101.144422-1-akihiko.odaki@daynix.com> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_NONE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC The added tests confirm tun can perform RSS and hash reporting, and reject invalid configurations for them. Signed-off-by: Akihiko Odaki --- tools/testing/selftests/net/Makefile | 2 +- tools/testing/selftests/net/tun.c | 578 ++++++++++++++++++++++++++- 2 files changed, 572 insertions(+), 8 deletions(-) diff --git a/tools/testing/selftests/net/Makefile b/tools/testing/selftests/net/Makefile index 8b017070960d..253a683073d9 100644 --- a/tools/testing/selftests/net/Makefile +++ b/tools/testing/selftests/net/Makefile @@ -2,7 +2,7 @@ # Makefile for net selftests CFLAGS = -Wall -Wl,--no-as-needed -O2 -g -CFLAGS += -I../../../../usr/include/ $(KHDR_INCLUDES) +CFLAGS += -I../../../../usr/include/ -I../../../include/ $(KHDR_INCLUDES) # Additional include paths needed by kselftest.h CFLAGS += -I../ diff --git a/tools/testing/selftests/net/tun.c b/tools/testing/selftests/net/tun.c index fa83918b62d1..862652fb4ed4 100644 --- a/tools/testing/selftests/net/tun.c +++ b/tools/testing/selftests/net/tun.c @@ -2,21 +2,39 @@ #define _GNU_SOURCE +#include #include #include +#include #include #include #include #include -#include +#include +#include +#include +#include +#include +#include +#include #include +#include #include #include -#include -#include +#include +#include +#include +#include #include "../kselftest_harness.h" +#define TUN_HWADDR_SOURCE { 0x02, 0x00, 0x00, 0x00, 0x00, 0x00 } + +#define TUN_HWADDR_DEST { 0x02, 0x00, 0x00, 0x00, 0x00, 0x01 } + +#define TUN_IPADDR_SOURCE htonl((172 << 24) | (17 << 16) | 0) +#define TUN_IPADDR_DEST htonl((172 << 24) | (17 << 16) | 1) + static int tun_attach(int fd, char *dev) { struct ifreq ifr; @@ -39,7 +57,7 @@ static int tun_detach(int fd, char *dev) return ioctl(fd, TUNSETQUEUE, (void *) &ifr); } -static int tun_alloc(char *dev) +static int tun_alloc(char *dev, short flags) { struct ifreq ifr; int fd, err; @@ -52,7 +70,8 @@ static int tun_alloc(char *dev) memset(&ifr, 0, sizeof(ifr)); strcpy(ifr.ifr_name, dev); - ifr.ifr_flags = IFF_TAP | IFF_NAPI | IFF_MULTI_QUEUE; + ifr.ifr_flags = flags | IFF_TAP | IFF_NAPI | IFF_NO_PI | + IFF_MULTI_QUEUE; err = ioctl(fd, TUNSETIFF, (void *) &ifr); if (err < 0) { @@ -64,6 +83,40 @@ static int tun_alloc(char *dev) return fd; } +static bool tun_add_to_bridge(int local_fd, const char *name) +{ + struct ifreq ifreq = { + .ifr_name = "xbridge", + .ifr_ifindex = if_nametoindex(name) + }; + + if (!ifreq.ifr_ifindex) { + perror("if_nametoindex"); + return false; + } + + if (ioctl(local_fd, SIOCBRADDIF, &ifreq)) { + perror("SIOCBRADDIF"); + return false; + } + + return true; +} + +static bool tun_set_flags(int local_fd, const char *name, short flags) +{ + struct ifreq ifreq = { .ifr_flags = flags }; + + strcpy(ifreq.ifr_name, name); + + if (ioctl(local_fd, SIOCSIFFLAGS, &ifreq)) { + perror("SIOCSIFFLAGS"); + return false; + } + + return true; +} + static int tun_delete(char *dev) { struct { @@ -102,6 +155,153 @@ static int tun_delete(char *dev) return ret; } +static uint32_t tun_sum(const void *buf, size_t len) +{ + const uint16_t *sbuf = buf; + uint32_t sum = 0; + + while (len > 1) { + sum += *sbuf++; + len -= 2; + } + + if (len) + sum += *(uint8_t *)sbuf; + + return sum; +} + +static uint16_t tun_build_ip_check(uint32_t sum) +{ + return ~((sum & 0xffff) + (sum >> 16)); +} + +static uint32_t tun_build_ip_pseudo_sum(const void *iphdr) +{ + uint16_t tot_len = ntohs(((struct iphdr *)iphdr)->tot_len); + + return tun_sum((char *)iphdr + offsetof(struct iphdr, saddr), 8) + + htons(((struct iphdr *)iphdr)->protocol) + + htons(tot_len - sizeof(struct iphdr)); +} + +static uint32_t tun_build_ipv6_pseudo_sum(const void *ipv6hdr) +{ + return tun_sum((char *)ipv6hdr + offsetof(struct ipv6hdr, saddr), 32) + + ((struct ipv6hdr *)ipv6hdr)->payload_len + + htons(((struct ipv6hdr *)ipv6hdr)->nexthdr); +} + +static void tun_build_ethhdr(struct ethhdr *ethhdr, uint16_t proto) +{ + *ethhdr = (struct ethhdr) { + .h_dest = TUN_HWADDR_DEST, + .h_source = TUN_HWADDR_SOURCE, + .h_proto = htons(proto) + }; +} + +static void tun_build_iphdr(void *dest, uint16_t len, uint8_t protocol) +{ + struct iphdr iphdr = { + .ihl = sizeof(iphdr) / 4, + .version = 4, + .tot_len = htons(sizeof(iphdr) + len), + .ttl = 255, + .protocol = protocol, + .saddr = TUN_IPADDR_SOURCE, + .daddr = TUN_IPADDR_DEST + }; + + iphdr.check = tun_build_ip_check(tun_sum(&iphdr, sizeof(iphdr))); + memcpy(dest, &iphdr, sizeof(iphdr)); +} + +static void tun_build_ipv6hdr(void *dest, uint16_t len, uint8_t protocol) +{ + struct ipv6hdr ipv6hdr = { + .version = 6, + .payload_len = htons(len), + .nexthdr = protocol, + .saddr = { + .s6_addr32 = { + htonl(0xffff0000), 0, 0, TUN_IPADDR_SOURCE + } + }, + .daddr = { + .s6_addr32 = { + htonl(0xffff0000), 0, 0, TUN_IPADDR_DEST + } + }, + }; + + memcpy(dest, &ipv6hdr, sizeof(ipv6hdr)); +} + +static void tun_build_tcphdr(void *dest, uint32_t sum) +{ + struct tcphdr tcphdr = { + .source = htons(9), + .dest = htons(9), + .fin = 1, + .doff = sizeof(tcphdr) / 4, + }; + uint32_t tcp_sum = tun_sum(&tcphdr, sizeof(tcphdr)); + + tcphdr.check = tun_build_ip_check(sum + tcp_sum); + memcpy(dest, &tcphdr, sizeof(tcphdr)); +} + +static void tun_build_udphdr(void *dest, uint32_t sum) +{ + struct udphdr udphdr = { + .source = htons(9), + .dest = htons(9), + .len = htons(sizeof(udphdr)), + }; + uint32_t udp_sum = tun_sum(&udphdr, sizeof(udphdr)); + + udphdr.check = tun_build_ip_check(sum + udp_sum); + memcpy(dest, &udphdr, sizeof(udphdr)); +} + +static bool tun_vnet_hash_check(int source_fd, const int *dest_fds, + const void *buffer, size_t len, + uint16_t report, uint32_t value) +{ + size_t read_len = sizeof(struct virtio_net_hdr_v1_hash) + len; + struct virtio_net_hdr_v1_hash *read_buffer; + int ret; + + if (write(source_fd, buffer, len) != len) { + perror("write"); + return false; + } + + read_buffer = malloc(read_len); + if (!read_buffer) { + perror("malloc"); + return false; + } + + ret = read(dest_fds[value & 1], read_buffer, read_len); + if (ret != read_len) { + perror("read"); + free(read_buffer); + return false; + } + + if (read_buffer->hash_value != htole32(value) || + read_buffer->hash_report != htole16(report) || + memcmp(read_buffer + 1, buffer, len)) { + free(read_buffer); + return false; + } + + free(read_buffer); + return true; +} + FIXTURE(tun) { char ifname[IFNAMSIZ]; @@ -112,10 +312,10 @@ FIXTURE_SETUP(tun) { memset(self->ifname, 0, sizeof(self->ifname)); - self->fd = tun_alloc(self->ifname); + self->fd = tun_alloc(self->ifname, 0); ASSERT_GE(self->fd, 0); - self->fd2 = tun_alloc(self->ifname); + self->fd2 = tun_alloc(self->ifname, 0); ASSERT_GE(self->fd2, 0); } @@ -159,4 +359,368 @@ TEST_F(tun, reattach_close_delete) { EXPECT_EQ(tun_delete(self->ifname), 0); } +FIXTURE(tun_vnet_hash) +{ + int local_fd; + int source_fd; + int dest_fds[2]; +}; + +FIXTURE_SETUP(tun_vnet_hash) +{ + static const struct { + struct tun_vnet_hash hdr; + uint16_t indirection_table[ARRAY_SIZE(self->dest_fds)]; + uint8_t key[40]; + } vnet_hash = { + .hdr = { + .flags = TUN_VNET_HASH_REPORT | TUN_VNET_HASH_RSS, + .types = VIRTIO_NET_RSS_HASH_TYPE_IPv4 | + VIRTIO_NET_RSS_HASH_TYPE_TCPv4 | + VIRTIO_NET_RSS_HASH_TYPE_UDPv4 | + VIRTIO_NET_RSS_HASH_TYPE_IPv6 | + VIRTIO_NET_RSS_HASH_TYPE_TCPv6 | + VIRTIO_NET_RSS_HASH_TYPE_UDPv6, + .indirection_table_mask = 1 + }, + .indirection_table = { 0, 1 }, + .key = { + 0x6d, 0x5a, 0x56, 0xda, 0x25, 0x5b, 0x0e, 0xc2, + 0x41, 0x67, 0x25, 0x3d, 0x43, 0xa3, 0x8f, 0xb0, + 0xd0, 0xca, 0x2b, 0xcb, 0xae, 0x7b, 0x30, 0xb4, + 0x77, 0xcb, 0x2d, 0xa3, 0x80, 0x30, 0xf2, 0x0c, + 0x6a, 0x42, 0xb7, 0x3b, 0xbe, 0xac, 0x01, 0xfa + } + }; + + struct { + struct virtio_net_hdr_v1_hash vnet_hdr; + struct ethhdr ethhdr; + struct arphdr arphdr; + unsigned char sender_hwaddr[6]; + uint32_t sender_ipaddr; + unsigned char target_hwaddr[6]; + uint32_t target_ipaddr; + } __packed packet = { + .ethhdr = { + .h_source = TUN_HWADDR_SOURCE, + .h_dest = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, + .h_proto = htons(ETH_P_ARP) + }, + .arphdr = { + .ar_hrd = htons(ARPHRD_ETHER), + .ar_pro = htons(ETH_P_IP), + .ar_hln = ETH_ALEN, + .ar_pln = 4, + .ar_op = htons(ARPOP_REQUEST) + }, + .sender_hwaddr = TUN_HWADDR_DEST, + .sender_ipaddr = TUN_IPADDR_DEST, + .target_ipaddr = TUN_IPADDR_DEST + }; + + char ifname[IFNAMSIZ]; + int i; + + self->local_fd = socket(AF_LOCAL, SOCK_STREAM, 0); + ASSERT_GE(self->local_fd, 0); + + ASSERT_EQ(ioctl(self->local_fd, SIOCBRADDBR, "xbridge"), 0); + ASSERT_TRUE(tun_set_flags(self->local_fd, "xbridge", IFF_UP)); + + ifname[0] = 0; + self->source_fd = tun_alloc(ifname, 0); + ASSERT_GE(self->source_fd, 0); + ASSERT_TRUE(tun_add_to_bridge(self->local_fd, ifname)); + ASSERT_TRUE(tun_set_flags(self->local_fd, ifname, IFF_UP)); + + ifname[0] = 0; + for (size_t i = 0; i < ARRAY_SIZE(self->dest_fds); i++) { + self->dest_fds[i] = tun_alloc(ifname, IFF_VNET_HDR); + ASSERT_GE(self->dest_fds[i], 0); + } + + ASSERT_TRUE(tun_add_to_bridge(self->local_fd, ifname)); + i = sizeof(struct virtio_net_hdr_v1_hash); + ASSERT_EQ(ioctl(self->dest_fds[0], TUNSETVNETHDRSZ, &i), 0); + i = 1; + ASSERT_EQ(ioctl(self->dest_fds[0], TUNSETVNETLE, &i), 0); + ASSERT_TRUE(tun_set_flags(self->local_fd, ifname, IFF_UP)); + ASSERT_EQ(write(self->dest_fds[0], &packet, sizeof(packet)), + sizeof(packet)); + ASSERT_EQ(ioctl(self->dest_fds[0], TUNSETVNETHASH, &vnet_hash), 0); +} + +FIXTURE_TEARDOWN(tun_vnet_hash) +{ + ASSERT_TRUE(tun_set_flags(self->local_fd, "xbridge", 0)); + EXPECT_EQ(ioctl(self->local_fd, SIOCBRDELBR, "xbridge"), 0); + EXPECT_EQ(close(self->source_fd), 0); + + for (size_t i = 0; i < ARRAY_SIZE(self->dest_fds); i++) + EXPECT_EQ(close(self->dest_fds[i]), 0); + + EXPECT_EQ(close(self->local_fd), 0); +} + +TEST_F(tun_vnet_hash, ipv4) +{ + struct { + struct ethhdr ethhdr; + struct iphdr iphdr; + } __packed packet; + + tun_build_ethhdr(&packet.ethhdr, ETH_P_IP); + tun_build_iphdr(&packet.iphdr, 0, 253); + + EXPECT_TRUE(tun_vnet_hash_check(self->source_fd, self->dest_fds, + &packet, sizeof(packet), + VIRTIO_NET_HASH_REPORT_IPv4, + 0x9246d590)); +} + +TEST_F(tun_vnet_hash, tcpv4) +{ + struct { + struct ethhdr ethhdr; + struct iphdr iphdr; + struct tcphdr tcphdr; + } __packed packet; + + tun_build_ethhdr(&packet.ethhdr, ETH_P_IP); + tun_build_iphdr(&packet.iphdr, sizeof(struct tcphdr), IPPROTO_TCP); + + tun_build_tcphdr(&packet.tcphdr, + tun_build_ip_pseudo_sum(&packet.iphdr)); + + EXPECT_TRUE(tun_vnet_hash_check(self->source_fd, self->dest_fds, + &packet, sizeof(packet), + VIRTIO_NET_HASH_REPORT_TCPv4, + 0xfad3f31a)); +} + +TEST_F(tun_vnet_hash, udpv4) +{ + struct { + struct ethhdr ethhdr; + struct iphdr iphdr; + struct udphdr udphdr; + } __packed packet; + + tun_build_ethhdr(&packet.ethhdr, ETH_P_IP); + tun_build_iphdr(&packet.iphdr, sizeof(struct udphdr), IPPROTO_UDP); + + tun_build_udphdr(&packet.udphdr, + tun_build_ip_pseudo_sum(&packet.iphdr)); + + EXPECT_TRUE(tun_vnet_hash_check(self->source_fd, self->dest_fds, + &packet, sizeof(packet), + VIRTIO_NET_HASH_REPORT_UDPv4, + 0xfad3f31a)); +} + +TEST_F(tun_vnet_hash, ipv6) +{ + struct { + struct ethhdr ethhdr; + struct ipv6hdr ipv6hdr; + } __packed packet; + + tun_build_ethhdr(&packet.ethhdr, ETH_P_IPV6); + tun_build_ipv6hdr(&packet.ipv6hdr, 0, 253); + + EXPECT_TRUE(tun_vnet_hash_check(self->source_fd, self->dest_fds, + &packet, sizeof(packet), + VIRTIO_NET_HASH_REPORT_IPv6, + 0x6b7835b3)); +} + +TEST_F(tun_vnet_hash, tcpv6) +{ + struct { + struct ethhdr ethhdr; + struct ipv6hdr ipv6hdr; + struct tcphdr tcphdr; + } __packed packet; + + tun_build_ethhdr(&packet.ethhdr, ETH_P_IPV6); + tun_build_ipv6hdr(&packet.ipv6hdr, sizeof(struct tcphdr), IPPROTO_TCP); + + tun_build_tcphdr(&packet.tcphdr, + tun_build_ipv6_pseudo_sum(&packet.ipv6hdr)); + + EXPECT_TRUE(tun_vnet_hash_check(self->source_fd, self->dest_fds, + &packet, sizeof(packet), + VIRTIO_NET_HASH_REPORT_TCPv6, + 0x6c6717)); +} + +TEST_F(tun_vnet_hash, udpv6) +{ + struct { + struct ethhdr ethhdr; + struct ipv6hdr ipv6hdr; + struct udphdr udphdr; + } __packed packet; + + tun_build_ethhdr(&packet.ethhdr, ETH_P_IPV6); + tun_build_ipv6hdr(&packet.ipv6hdr, sizeof(struct udphdr), IPPROTO_UDP); + + tun_build_udphdr(&packet.udphdr, + tun_build_ipv6_pseudo_sum(&packet.ipv6hdr)); + + EXPECT_TRUE(tun_vnet_hash_check(self->source_fd, self->dest_fds, + &packet, sizeof(packet), + VIRTIO_NET_HASH_REPORT_UDPv6, + 0x6c6717)); +} + +FIXTURE(tun_vnet_hash_config) +{ + int fd; +}; + +FIXTURE_SETUP(tun_vnet_hash_config) +{ + char ifname[IFNAMSIZ]; + + ifname[0] = 0; + self->fd = tun_alloc(ifname, 0); + ASSERT_GE(self->fd, 0); +} + +FIXTURE_TEARDOWN(tun_vnet_hash_config) +{ + EXPECT_EQ(close(self->fd), 0); +} + +TEST_F(tun_vnet_hash_config, cap) +{ + struct tun_vnet_hash_cap cap; + + ASSERT_EQ(ioctl(self->fd, TUNGETVNETHASHCAP, &cap), 0); + EXPECT_EQ(cap.max_indirection_table_length, 128); + EXPECT_EQ(cap.types, + VIRTIO_NET_RSS_HASH_TYPE_IPv4 | + VIRTIO_NET_RSS_HASH_TYPE_TCPv4 | + VIRTIO_NET_RSS_HASH_TYPE_UDPv4 | + VIRTIO_NET_RSS_HASH_TYPE_IPv6 | + VIRTIO_NET_RSS_HASH_TYPE_TCPv6 | + VIRTIO_NET_RSS_HASH_TYPE_UDPv6); +} + +TEST_F(tun_vnet_hash_config, insufficient_hdr_sz) +{ + static const struct tun_vnet_hash vnet_hash = { + .flags = TUN_VNET_HASH_REPORT + }; + int i; + + i = 1; + ASSERT_EQ(ioctl(self->fd, TUNSETVNETLE, &i), 0); + + ASSERT_EQ(ioctl(self->fd, TUNSETVNETHASH, &vnet_hash), -1); + EXPECT_EQ(errno, EINVAL); +} + +TEST_F(tun_vnet_hash_config, shrink_hdr_sz) +{ + static const struct tun_vnet_hash vnet_hash = { + .flags = TUN_VNET_HASH_REPORT + }; + int i; + + i = sizeof(struct virtio_net_hdr_v1_hash); + ASSERT_EQ(ioctl(self->fd, TUNSETVNETHDRSZ, &i), 0); + + i = 1; + ASSERT_EQ(ioctl(self->fd, TUNSETVNETLE, &i), 0); + + ASSERT_EQ(ioctl(self->fd, TUNSETVNETHASH, &vnet_hash), 0); + + i = sizeof(struct virtio_net_hdr); + ASSERT_EQ(ioctl(self->fd, TUNSETVNETHDRSZ, &i), -1); + EXPECT_EQ(errno, EINVAL); +} + +TEST_F(tun_vnet_hash_config, too_big_indirection_table) +{ + static const struct tun_vnet_hash vnet_hash = { + .flags = TUN_VNET_HASH_REPORT, + .indirection_table_mask = 255 + }; + int i; + + i = sizeof(struct virtio_net_hdr_v1_hash); + ASSERT_EQ(ioctl(self->fd, TUNSETVNETHDRSZ, &i), 0); + + i = 1; + ASSERT_EQ(ioctl(self->fd, TUNSETVNETLE, &i), 0); + + ASSERT_EQ(ioctl(self->fd, TUNSETVNETHASH, &vnet_hash), -1); + EXPECT_EQ(errno, EINVAL); +} + +TEST_F(tun_vnet_hash_config, set_be_early) +{ + static const struct tun_vnet_hash vnet_hash = { + .flags = TUN_VNET_HASH_REPORT + }; + int i; + + i = 1; + if (ioctl(self->fd, TUNSETVNETBE, &i)) + return; + + i = sizeof(struct virtio_net_hdr_v1_hash); + ASSERT_EQ(ioctl(self->fd, TUNSETVNETHDRSZ, &i), 0); + + ASSERT_EQ(ioctl(self->fd, TUNSETVNETHASH, &vnet_hash), -1); + EXPECT_EQ(errno, EINVAL); +} + +TEST_F(tun_vnet_hash_config, set_be_later) +{ + static const struct tun_vnet_hash vnet_hash = { + .flags = TUN_VNET_HASH_REPORT + }; + int i; + + i = sizeof(struct virtio_net_hdr_v1_hash); + ASSERT_EQ(ioctl(self->fd, TUNSETVNETHDRSZ, &i), 0); + + if (ioctl(self->fd, TUNSETVNETHASH, &vnet_hash)) + return; + + i = 1; + ASSERT_EQ(ioctl(self->fd, TUNSETVNETBE, &i), -1); + EXPECT_EQ(errno, EINVAL); +} + +TEST_F(tun_vnet_hash_config, unset_le_later) +{ + static const struct tun_vnet_hash vnet_hash = { + .flags = TUN_VNET_HASH_REPORT + }; + int i; + + i = sizeof(struct virtio_net_hdr_v1_hash); + ASSERT_EQ(ioctl(self->fd, TUNSETVNETHDRSZ, &i), 0); + + i = 1; + ioctl(self->fd, TUNSETVNETBE, &i); + + if (!ioctl(self->fd, TUNSETVNETHASH, &vnet_hash)) + return; + + i = 1; + ASSERT_EQ(ioctl(self->fd, TUNSETVNETLE, &i), 0); + + ASSERT_EQ(ioctl(self->fd, TUNSETVNETHASH, &vnet_hash), 0); + + i = 0; + ASSERT_EQ(ioctl(self->fd, TUNSETVNETLE, &i), -1); + EXPECT_EQ(errno, EINVAL); +} + TEST_HARNESS_MAIN From patchwork Sun Oct 8 05:20:51 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Akihiko Odaki X-Patchwork-Id: 13412561 Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net [23.128.96.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 16F621FD5 for ; Sun, 8 Oct 2023 05:23:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=daynix-com.20230601.gappssmtp.com header.i=@daynix-com.20230601.gappssmtp.com header.b="vwi2J1cY" Received: from mail-ot1-x331.google.com (mail-ot1-x331.google.com [IPv6:2607:f8b0:4864:20::331]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2510ED8 for ; Sat, 7 Oct 2023 22:22:59 -0700 (PDT) Received: by mail-ot1-x331.google.com with SMTP id 46e09a7af769-6c7b3adbeb6so2546481a34.0 for ; Sat, 07 Oct 2023 22:22:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=daynix-com.20230601.gappssmtp.com; s=20230601; t=1696742578; x=1697347378; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=kdDWVt4lpIJYL5Xl2mxJffHYtHkpJSxptvcjLCGS28w=; b=vwi2J1cYT7UODUfB1N5XD/TP+QyK/UcEqkxxo9199A/yEs724R1p2bibfEUUF6GpqX 5XRzBuZ3UNoxs/0zafYT7bDF2KZTGqqWlivxcvc2KWaMLEmAt6v4rBj3b7C+EBdsDX+R wIvNZx8i3tbz6+ZOjp7mLlmXytOB2QhWJes9WAWvjLJhfDV3uYK7lk7c4haA1WYoht2r eVpYwAnKnIfEbnBb8yn1IM2EQN3b/XVK+pNGfFoFtZmHTIs6jwJkkMkEiMkh4RPPHA4j GFtzn0+zrWE7Q5VuZI5C6x8by1YCKKrFRTFwOjVvjtLfQNDdaor70GaZDNBC1hTGOfgK 47iA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1696742578; x=1697347378; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=kdDWVt4lpIJYL5Xl2mxJffHYtHkpJSxptvcjLCGS28w=; b=cw2MZC5DbgkUz0srPySIxlPG3R2y/fcT+CdK9fSxIAQx2nPR+LnqJUY+T+sGHurWMK 47vxY4O0LVt9/gsJvgDPXdyeX+oOsHNY51USc3hnK9aYv5QV+j8JxDNBKZBUhcOY8eRb sz+0ZBlvDD9vQv4BFl/huFORqmr/thkPCida2CGpLmvSJAQBdWS4hirriHz4n7cihcgH HGbaP+dbp02QuUCf8Tm9DnSafQ8CUbNOBS6p7g4Go9A4VvyjwOJGMc0DzT+NECVveC+9 69RRx0xcqUq2CsD6Birx8G+nXOD2Antg7yHOIGYON4GADqpJvo8e8LwM8Z6X0KVy2hsZ zEfQ== X-Gm-Message-State: AOJu0YwggW5yqEXIJKh1rKsFv0905NN1tNxkCJ4306FByq00P9GqHEpx S3f7yQm3wDonuRn97UryLx6EhQ== X-Google-Smtp-Source: AGHT+IFmz0Csm/McUo7epY/hvuuEc7olif/dP1uLse9ltuNTbzOKdI+TI+qxxYbYUL4vOkxFlEeQWA== X-Received: by 2002:a05:6870:40d0:b0:1d6:96f9:66fa with SMTP id l16-20020a05687040d000b001d696f966famr15377523oal.54.1696742578366; Sat, 07 Oct 2023 22:22:58 -0700 (PDT) Received: from localhost ([2400:4050:a840:1e00:78d2:b862:10a7:d486]) by smtp.gmail.com with UTF8SMTPSA id h18-20020a170902eed200b001c627413e87sm6772511plb.290.2023.10.07.22.22.52 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Sat, 07 Oct 2023 22:22:57 -0700 (PDT) From: Akihiko Odaki To: Cc: Willem de Bruijn , Jason Wang , "Michael S. Tsirkin" , Xuan Zhuo Shuah Khan , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, kvm@vger.kernel.org, virtualization@lists.linux-foundation.org, linux-kselftest@vger.kernel.org, bpf@vger.kernel.org, davem@davemloft.net, kuba@kernel.org, ast@kernel.org, daniel@iogearbox.net, andrii@kernel.org, kafai@fb.com, songliubraving@fb.com, yhs@fb.com, john.fastabend@gmail.com, kpsingh@kernel.org, rdunlap@infradead.org, willemb@google.com, gustavoars@kernel.org, herbert@gondor.apana.org.au, steffen.klassert@secunet.com, nogikh@google.com, pablo@netfilter.org, decui@microsoft.com, cai@lca.pw, jakub@cloudflare.com, elver@google.com, pabeni@redhat.com, Yuri Benditovich , Akihiko Odaki Subject: [RFC PATCH 7/7] vhost_net: Support VIRTIO_NET_F_HASH_REPORT Date: Sun, 8 Oct 2023 14:20:51 +0900 Message-ID: <20231008052101.144422-8-akihiko.odaki@daynix.com> X-Mailer: git-send-email 2.42.0 In-Reply-To: <20231008052101.144422-1-akihiko.odaki@daynix.com> References: <20231008052101.144422-1-akihiko.odaki@daynix.com> Precedence: bulk X-Mailing-List: bpf@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_NONE autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net X-Patchwork-State: RFC VIRTIO_NET_F_HASH_REPORT allows to report hash values calculated on the host. When VHOST_NET_F_VIRTIO_NET_HDR is employed, it will report no hash values (i.e., the hash_report member is always set to VIRTIO_NET_HASH_REPORT_NONE). Otherwise, the values reported by the underlying socket will be reported. VIRTIO_NET_F_HASH_REPORT requires VIRTIO_F_VERSION_1. Signed-off-by: Akihiko Odaki --- drivers/vhost/net.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c index f2ed7167c848..6a31d450fae2 100644 --- a/drivers/vhost/net.c +++ b/drivers/vhost/net.c @@ -73,6 +73,7 @@ enum { VHOST_NET_FEATURES = VHOST_FEATURES | (1ULL << VHOST_NET_F_VIRTIO_NET_HDR) | (1ULL << VIRTIO_NET_F_MRG_RXBUF) | + (1ULL << VIRTIO_NET_F_HASH_REPORT) | (1ULL << VIRTIO_F_ACCESS_PLATFORM) | (1ULL << VIRTIO_F_RING_RESET) }; @@ -1634,10 +1635,13 @@ static int vhost_net_set_features(struct vhost_net *n, u64 features) size_t vhost_hlen, sock_hlen, hdr_len; int i; - hdr_len = (features & ((1ULL << VIRTIO_NET_F_MRG_RXBUF) | - (1ULL << VIRTIO_F_VERSION_1))) ? - sizeof(struct virtio_net_hdr_mrg_rxbuf) : - sizeof(struct virtio_net_hdr); + if (features & (1ULL << VIRTIO_NET_F_HASH_REPORT)) + hdr_len = sizeof(struct virtio_net_hdr_v1_hash); + else if (features & ((1ULL << VIRTIO_NET_F_MRG_RXBUF) | + (1ULL << VIRTIO_F_VERSION_1))) + hdr_len = sizeof(struct virtio_net_hdr_mrg_rxbuf); + else + hdr_len = sizeof(struct virtio_net_hdr); if (features & (1 << VHOST_NET_F_VIRTIO_NET_HDR)) { /* vhost provides vnet_hdr */ vhost_hlen = hdr_len; @@ -1718,6 +1722,10 @@ static long vhost_net_ioctl(struct file *f, unsigned int ioctl, return -EFAULT; if (features & ~VHOST_NET_FEATURES) return -EOPNOTSUPP; + if ((features & ((1ULL << VIRTIO_F_VERSION_1) | + (1ULL << VIRTIO_NET_F_HASH_REPORT))) == + (1ULL << VIRTIO_NET_F_HASH_REPORT)) + return -EINVAL; return vhost_net_set_features(n, features); case VHOST_GET_BACKEND_FEATURES: features = VHOST_NET_BACKEND_FEATURES;