From nobody Wed Mar 16 23:29:34 2022 X-Original-To: dev-commits-src-main@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id B60561A37474; Wed, 16 Mar 2022 23:29:34 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4KJmhG4mVHz4gpq; Wed, 16 Mar 2022 23:29:34 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1647473374; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=OEIs+fqFH1oXyQ9LYfh61q28vfVJLfrZRj2mDO+ovxI=; b=q68gZDZFDut6+qXhAVDejHQzXT9V3dUGLgCJZhsSATsZNJNGJaLXmnFdOINSfjjIOxqk+O RS840mdUwQv1BItJCJz6Oy95OlmTDVkBIC4kSFZGeB59TbnK6xOYm1tdY2XqW5HSBYsj9e JkSIIExLCfMMssPIjCtnO8wkBgt90CidB9Fwj2rQOCGaI+07HC/Q4Ouy9Oz4PEs9tn4lzM rSGVkt6nmM0tu4LKzvfqV3tvSw2IEMVo9RdrnFJrrIMxERRLVSrRYXkdkNQcRPFV8qR2sT IHz1lgknGlBuiB+NMaBdS1JOndgopD8BEdVDqXUZC7/Xhsr6cWSmcPEEde/aGw== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 7FC9A1F816; Wed, 16 Mar 2022 23:29:34 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 22GNTY7h034297; Wed, 16 Mar 2022 23:29:34 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 22GNTYak034296; Wed, 16 Mar 2022 23:29:34 GMT (envelope-from git) Date: Wed, 16 Mar 2022 23:29:34 GMT Message-Id: <202203162329.22GNTYak034296@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Kristof Provost Subject: git: 66acf7685bcd - main - if_epair: fix race condition on multi-core systems List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-main@freebsd.org X-BeenThere: dev-commits-src-main@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: kp X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 66acf7685bcd8cf23b6c658a991637238a01859e Auto-Submitted: auto-generated ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1647473374; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=OEIs+fqFH1oXyQ9LYfh61q28vfVJLfrZRj2mDO+ovxI=; b=a5unIWNIOoMCHGl838gHD0x4CsJpOQAsg/zNKWy5Yf5XAf8yVKCnWzMFjlxJOx3DLUeag7 Bw7D2wCnBZhgOBsPCsbisHZmpPC433b/rBRGfvFAAf1xU1jU5XE3mAF+vKXXB0/Bs0b3Ez xjGDTzQvnH0eErBpjTlGOHTRAFBYEOlK8VwGFDTr0H4peLn/JbqkMHTQhSmv4cmGP8mLSZ lVzn3r8INtM0BIwPzOH5NDOQtvvx2JcE3cXliEezb2Bo3mqnc5wYNS2EFisMcc1ZikSPG7 +/SB3jWftDFQwtCwq5Sw3TBqWSek8w/8wY+tQteZ+cR780sPIawZ6EUbEm5YUQ== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1647473374; a=rsa-sha256; cv=none; b=rl/Z47nuWobCJQySAUmKZfuErm5d/XFgAelihuEXoo3AdrtsGBoqZn4er/F0MXnjIYEjKn /yW2C5TTaMdTxvhPjI+wnmA+gN5gBQOiGOR7KJ3AlDr3kZzHKT1sZLBUNvdeuFT0Ln+oWa VnITsxMZwi74o2LpeP8pQ2IoPmPmKgebhy4kjAx5/GThU1ylZ3hOwNZ6/DuQLW3/9Uz16f hXkMNcM0gThe5u9M0v/F0CKGePOuJiSF7GyPRKyv1KqkRBsVEHmz8q6X+rKQITQlr9YLk+ EYltwcYkjJap9FuL+SEgZguBEeujxHkfr07Nrh9mEPl3avjYGtgI0++HU9nf2w== ARC-Authentication-Results: i=1; mx1.freebsd.org; none X-ThisMailContainsUnwantedMimeParts: N The branch main has been updated by kp: URL: https://cgit.FreeBSD.org/src/commit/?id=66acf7685bcd8cf23b6c658a991637238a01859e commit 66acf7685bcd8cf23b6c658a991637238a01859e Author: Michael Gmelin AuthorDate: 2022-03-16 22:08:55 +0000 Commit: Kristof Provost CommitDate: 2022-03-16 22:08:55 +0000 if_epair: fix race condition on multi-core systems As an unwanted side effect of the performance improvements in 24f0bfbad57b9, epair interfaces stop forwarding traffic on higher load levels when running on multi-core systems. This happens due to a race condition in the logic that decides when to place work in the task queue(s) responsible for processing the content of ring buffers. In order to fix this, a field named state is added to the epair_queue structure. This field is used by the affected functions to signal each other that something happened in the underlying ring buffers that might require work to be scheduled in task queue(s), replacing the existing logic, which relied on checking if ring buffers are empty or not. epair_menq() does: - set BIT_MBUF_QUEUED - queue mbuf - if testandset BIT_QUEUE_TASK: enqueue task epair_tx_start_deferred() does: - swap ring buffers - process mbufs - clear BIT_QUEUE_TASK - if testandclear BIT_MBUF_QUEUED enqueue task PR: 262571 Reported by: Johan Hendriks MFC after: 3 days Differential Revision: https://reviews.freebsd.org/D34569 --- sys/net/if_epair.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/sys/net/if_epair.c b/sys/net/if_epair.c index c39434b31b9f..fbf48c7793ea 100644 --- a/sys/net/if_epair.c +++ b/sys/net/if_epair.c @@ -104,11 +104,15 @@ static unsigned int next_index = 0; #define EPAIR_LOCK() mtx_lock(&epair_n_index_mtx) #define EPAIR_UNLOCK() mtx_unlock(&epair_n_index_mtx) +#define BIT_QUEUE_TASK 0 +#define BIT_MBUF_QUEUED 1 + struct epair_softc; struct epair_queue { int id; struct buf_ring *rxring[2]; volatile int ridx; /* 0 || 1 */ + volatile int state; /* taskqueue coordination */ struct task tx_task; struct epair_softc *sc; }; @@ -177,7 +181,8 @@ epair_tx_start_deferred(void *arg, int pending) } while (!atomic_fcmpset_int(&q->ridx, &ridx, nidx)); epair_if_input(sc, q, ridx); - if (! buf_ring_empty(q->rxring[nidx])) + atomic_clear_int(&q->state, (1 << BIT_QUEUE_TASK)); + if (atomic_testandclear_int(&q->state, BIT_MBUF_QUEUED)) taskqueue_enqueue(epair_tasks.tq[q->id], &q->tx_task); if_rele(sc->ifp); @@ -192,7 +197,6 @@ epair_menq(struct mbuf *m, struct epair_softc *osc) short mflags; struct epair_queue *q = NULL; uint32_t bucket; - bool was_empty; #ifdef RSS struct ether_header *eh; #endif @@ -244,14 +248,14 @@ epair_menq(struct mbuf *m, struct epair_softc *osc) #endif q = &osc->queues[bucket]; + atomic_set_int(&q->state, (1 << BIT_MBUF_QUEUED)); ridx = atomic_load_int(&q->ridx); - was_empty = buf_ring_empty(q->rxring[ridx]); ret = buf_ring_enqueue(q->rxring[ridx], m); if (ret != 0) { /* Ring is full. */ if_inc_counter(ifp, IFCOUNTER_OQDROPS, 1); m_freem(m); - goto done; + return (0); } if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); @@ -266,8 +270,7 @@ epair_menq(struct mbuf *m, struct epair_softc *osc) /* Someone else received the packet. */ if_inc_counter(oifp, IFCOUNTER_IPACKETS, 1); -done: - if (was_empty) + if (!atomic_testandset_int(&q->state, BIT_QUEUE_TASK)) taskqueue_enqueue(epair_tasks.tq[bucket], &q->tx_task); return (0); @@ -552,6 +555,7 @@ epair_clone_create(struct if_clone *ifc, char *name, size_t len, caddr_t params) q->rxring[0] = buf_ring_alloc(RXRSIZE, M_EPAIR, M_WAITOK, NULL); q->rxring[1] = buf_ring_alloc(RXRSIZE, M_EPAIR, M_WAITOK, NULL); q->ridx = 0; + q->state = 0; q->sc = sca; NET_TASK_INIT(&q->tx_task, 0, epair_tx_start_deferred, q); } @@ -574,6 +578,7 @@ epair_clone_create(struct if_clone *ifc, char *name, size_t len, caddr_t params) q->rxring[0] = buf_ring_alloc(RXRSIZE, M_EPAIR, M_WAITOK, NULL); q->rxring[1] = buf_ring_alloc(RXRSIZE, M_EPAIR, M_WAITOK, NULL); q->ridx = 0; + q->state = 0; q->sc = scb; NET_TASK_INIT(&q->tx_task, 0, epair_tx_start_deferred, q); }