Message ID | 20230630120306.8534-1-florian.kauer@linutronix.de |
---|---|
State | New |
Headers |
Return-Path: <linux-kernel-owner@vger.kernel.org> Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:994d:0:b0:3d9:f83d:47d9 with SMTP id k13csp10323568vqr; Fri, 30 Jun 2023 05:31:52 -0700 (PDT) X-Google-Smtp-Source: APBJJlFUXrdBz90IERim3NlJUOvXFNPChlZkIInw3tqbIiyeCeBjEULCCYtShyo1Ih8hGIN37Bjk X-Received: by 2002:a17:903:1c5:b0:1b8:6a09:9cf9 with SMTP id e5-20020a17090301c500b001b86a099cf9mr2621441plh.26.1688128311855; Fri, 30 Jun 2023 05:31:51 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1688128311; cv=none; d=google.com; s=arc-20160816; b=hVLTnq6irNA7wfGQx/XgqbfYYUEaTKYOWzEyueuJYkuwVvduF912wQZGES/eY/duaN laHauNrdNK6k2/bO/f02RcB0DmVdw3tCzcx1zjCholZW08iGQkV2W84w/fUS7q0L+t59 lqNZN6ZSREfKT/EfAdgCUQFeXj8nvy3MOt/jjnYybXUD/waOiTJwHIusI01Hl2X4rmGv 0mL+KNIgHgJ4aMbS9qPUqJ9/3DnmDjSjNBQX7nYy0oiIQyp782d7q1ImoC7pdv+jqwhT Mx1Feii//5U01FGES8ZCAqBQ6OLI7OoGigmXpY6yfbNIGp26vXY5EEeVt87MToYE9B74 58dQ== 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 :message-id:date:subject:cc:to:dkim-signature:dkim-signature:from; bh=XZbPTleH8tvt6ILWOyc607090QYMkQzPFfKhUGy2cko=; fh=vkNG5A84ue9FDdCMhBbz4BCTvT23Vy4yVb6k7s6+7Yo=; b=ik1zeMkSu8q4O+yyWmAlJ5HI9wDQzJbuLCe5zmZFojKaAsF/BghrtNIuoAyFPJHYdA PN0h9gsiQzoRJpultJizMoGVFR9e7i82OLTFeSYxwB79VV8GUQkIP50SIaXuqIKVdENH 4Uh+m4NehDNaruBw5W/rL72HD87THOi7aziLg5NyggK8Eu8lNhfZ7ylnB0SM0kCXWx5f 5OupzXxOReKtGLAMNyj4yTi9AfF9NdHdOQSLf5thMDqFK7aKDnMn9xn5GvqKIumIcRhj NHPDKO0eSUZnFyGmwE5kMSAxWelMisJcg22MdylnXFKUgiI/yWhBeusbrlVZJSiFmwEy UHZA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linutronix.de header.s=2020 header.b=uRmnxtDn; dkim=neutral (no key) header.i=@linutronix.de; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=linutronix.de Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id m1-20020a170902db0100b001b875fea746si558209plx.416.2023.06.30.05.31.22; Fri, 30 Jun 2023 05:31:51 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@linutronix.de header.s=2020 header.b=uRmnxtDn; dkim=neutral (no key) header.i=@linutronix.de; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=linutronix.de Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232989AbjF3MDd (ORCPT <rfc822;nicolai.engesland@gmail.com> + 99 others); Fri, 30 Jun 2023 08:03:33 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48732 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232957AbjF3MDS (ORCPT <rfc822;linux-kernel@vger.kernel.org>); Fri, 30 Jun 2023 08:03:18 -0400 Received: from galois.linutronix.de (Galois.linutronix.de [IPv6:2a0a:51c0:0:12e:550::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5C8C73AB1; Fri, 30 Jun 2023 05:03:13 -0700 (PDT) From: Florian Kauer <florian.kauer@linutronix.de> DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1688126591; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=XZbPTleH8tvt6ILWOyc607090QYMkQzPFfKhUGy2cko=; b=uRmnxtDn3mLSSk1VRWVUabR3L6Cb6skeKPeVT8tsuZlMtQ0m9othNXwcY+wxZk2osYh2zu dtZTwk+Y8lLzDTe3O1qRy72VcVaZVWLwQoMocvOjyGsmQstf22NxkcJu15BIOkEZYulvNp vlbZv6/FdZvx1fi/EXz4XtwwbuBclM6BKA7okoxJTej9DWqlLsm+0j3eS3vIk40Grjx4xD VoHycBNcC9hfbdgImTYcTfxF3HWVQd62uWpZfy4yZc/WJgwDtbFasFjJVGu08bnRzHkfob bcxEpXz4Y8V63upjEwaaJ86rdOWm4oxqlHvmU27bD/vXqS8GU25IPhU92n/inQ== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1688126591; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=XZbPTleH8tvt6ILWOyc607090QYMkQzPFfKhUGy2cko=; b=7upiJJkMkWVEEcvMAtbhIM5502wHHDPKdKUndgk2PG6bRQmzDUchv9yucRd8kCUPjWBTiC otEXzvc7s7aDk4Cw== To: Jesse Brandeburg <jesse.brandeburg@intel.com>, Tony Nguyen <anthony.l.nguyen@intel.com>, "David S . Miller" <davem@davemloft.net>, Eric Dumazet <edumazet@google.com>, Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>, Vedang Patel <vedang.patel@intel.com>, Maciej Fijalkowski <maciej.fijalkowski@intel.com>, Jithu Joseph <jithu.joseph@intel.com>, Andre Guedes <andre.guedes@intel.com>, Simon Horman <simon.horman@corigine.com> Cc: intel-wired-lan@lists.osuosl.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, kurt@linutronix.de, florian.kauer@linutronix.de, Vinicius Costa Gomes <vinicius.gomes@intel.com> Subject: [PATCH net v3] igc: Prevent garbled TX queue with XDP ZEROCOPY Date: Fri, 30 Jun 2023 14:03:06 +0200 Message-Id: <20230630120306.8534-1-florian.kauer@linutronix.de> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-4.4 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_MED,SPF_HELO_NONE, SPF_PASS,T_SCC_BODY_TEXT_LINE,URIBL_BLOCKED autolearn=ham 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: <linux-kernel.vger.kernel.org> X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1770130833176174002?= X-GMAIL-MSGID: =?utf-8?q?1770130833176174002?= |
Series |
[net,v3] igc: Prevent garbled TX queue with XDP ZEROCOPY
|
|
Commit Message
Florian Kauer
June 30, 2023, 12:03 p.m. UTC
In normal operation, each populated queue item has next_to_watch pointing to the last TX desc of the packet, while each cleaned item has it set to 0. In particular, next_to_use that points to the next (necessarily clean) item to use has next_to_watch set to 0. When the TX queue is used both by an application using AF_XDP with ZEROCOPY as well as a second non-XDP application generating high traffic, the queue pointers can get in an invalid state where next_to_use points to an item where next_to_watch is NOT set to 0. However, the implementation assumes at several places that this is never the case, so if it does hold, bad things happen. In particular, within the loop inside of igc_clean_tx_irq(), next_to_clean can overtake next_to_use. Finally, this prevents any further transmission via this queue and it never gets unblocked or signaled. Secondly, if the queue is in this garbled state, the inner loop of igc_clean_tx_ring() will never terminate, completely hogging a CPU core. The reason is that igc_xdp_xmit_zc() reads next_to_use before acquiring the lock, and writing it back (potentially unmodified) later. If it got modified before locking, the outdated next_to_use is written pointing to an item that was already used elsewhere (and thus next_to_watch got written). Fixes: 9acf59a752d4 ("igc: Enable TX via AF_XDP zero-copy") Signed-off-by: Florian Kauer <florian.kauer@linutronix.de> Reviewed-by: Kurt Kanzenbach <kurt@linutronix.de> Tested-by: Kurt Kanzenbach <kurt@linutronix.de> Acked-by: Vinicius Costa Gomes <vinicius.gomes@intel.com> --- v2 -> v3: Resolve merge conflict v1 -> v2: I added some more context for further clarification, but it is also just how I interpret the code. Also the typo is fixed and it is reverse christmas again 😉 --- drivers/net/ethernet/intel/igc/igc_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
Comments
On Fri, Jun 30, 2023 at 02:03:06PM +0200, Florian Kauer wrote: > In normal operation, each populated queue item has > next_to_watch pointing to the last TX desc of the packet, > while each cleaned item has it set to 0. In particular, > next_to_use that points to the next (necessarily clean) > item to use has next_to_watch set to 0. > > When the TX queue is used both by an application using > AF_XDP with ZEROCOPY as well as a second non-XDP application > generating high traffic, the queue pointers can get in > an invalid state where next_to_use points to an item > where next_to_watch is NOT set to 0. > > However, the implementation assumes at several places > that this is never the case, so if it does hold, > bad things happen. In particular, within the loop inside > of igc_clean_tx_irq(), next_to_clean can overtake next_to_use. > Finally, this prevents any further transmission via > this queue and it never gets unblocked or signaled. > Secondly, if the queue is in this garbled state, > the inner loop of igc_clean_tx_ring() will never terminate, > completely hogging a CPU core. > > The reason is that igc_xdp_xmit_zc() reads next_to_use > before acquiring the lock, and writing it back > (potentially unmodified) later. If it got modified > before locking, the outdated next_to_use is written > pointing to an item that was already used elsewhere > (and thus next_to_watch got written). > > Fixes: 9acf59a752d4 ("igc: Enable TX via AF_XDP zero-copy") > Signed-off-by: Florian Kauer <florian.kauer@linutronix.de> > Reviewed-by: Kurt Kanzenbach <kurt@linutronix.de> > Tested-by: Kurt Kanzenbach <kurt@linutronix.de> > Acked-by: Vinicius Costa Gomes <vinicius.gomes@intel.com> Reviewed-by: Simon Horman <simon.horman@corigine.com>
On 6/30/2023 15:03, Florian Kauer wrote: > In normal operation, each populated queue item has > next_to_watch pointing to the last TX desc of the packet, > while each cleaned item has it set to 0. In particular, > next_to_use that points to the next (necessarily clean) > item to use has next_to_watch set to 0. > > When the TX queue is used both by an application using > AF_XDP with ZEROCOPY as well as a second non-XDP application > generating high traffic, the queue pointers can get in > an invalid state where next_to_use points to an item > where next_to_watch is NOT set to 0. > > However, the implementation assumes at several places > that this is never the case, so if it does hold, > bad things happen. In particular, within the loop inside > of igc_clean_tx_irq(), next_to_clean can overtake next_to_use. > Finally, this prevents any further transmission via > this queue and it never gets unblocked or signaled. > Secondly, if the queue is in this garbled state, > the inner loop of igc_clean_tx_ring() will never terminate, > completely hogging a CPU core. > > The reason is that igc_xdp_xmit_zc() reads next_to_use > before acquiring the lock, and writing it back > (potentially unmodified) later. If it got modified > before locking, the outdated next_to_use is written > pointing to an item that was already used elsewhere > (and thus next_to_watch got written). > > Fixes: 9acf59a752d4 ("igc: Enable TX via AF_XDP zero-copy") > Signed-off-by: Florian Kauer <florian.kauer@linutronix.de> > Reviewed-by: Kurt Kanzenbach <kurt@linutronix.de> > Tested-by: Kurt Kanzenbach <kurt@linutronix.de> > Acked-by: Vinicius Costa Gomes <vinicius.gomes@intel.com> > --- > > v2 -> v3: > Resolve merge conflict > > v1 -> v2: > I added some more context for further clarification, > but it is also just how I interpret the code. > Also the typo is fixed and it is reverse christmas again 😉 > > --- > drivers/net/ethernet/intel/igc/igc_main.c | 4 ++-- > 1 file changed, 2 insertions(+), 2 deletions(-) Tested-by: Naama Meir <naamax.meir@linux.intel.com>
diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c index 019ce91c45aa..722ffcc319f0 100644 --- a/drivers/net/ethernet/intel/igc/igc_main.c +++ b/drivers/net/ethernet/intel/igc/igc_main.c @@ -2833,9 +2833,8 @@ static void igc_xdp_xmit_zc(struct igc_ring *ring) struct netdev_queue *nq = txring_txq(ring); union igc_adv_tx_desc *tx_desc = NULL; int cpu = smp_processor_id(); - u16 ntu = ring->next_to_use; struct xdp_desc xdp_desc; - u16 budget; + u16 budget, ntu; if (!netif_carrier_ok(ring->netdev)) return; @@ -2845,6 +2844,7 @@ static void igc_xdp_xmit_zc(struct igc_ring *ring) /* Avoid transmit queue timeout since we share it with the slow path */ txq_trans_cond_update(nq); + ntu = ring->next_to_use; budget = igc_desc_unused(ring); while (xsk_tx_peek_desc(pool, &xdp_desc) && budget--) {