Received: by 2002:a05:6358:1087:b0:cb:c9d3:cd90 with SMTP id j7csp2083418rwi; Tue, 11 Oct 2022 04:45:12 -0700 (PDT) X-Google-Smtp-Source: AMsMyM5MWexJUZjbvDztoZ6kQTQsFEKmaByhCdjy8N1Nyhl2MWrbK++LJ+3zh/oSIriWeGezF+kD X-Received: by 2002:a05:6a02:192:b0:43c:a0cb:44d3 with SMTP id bj18-20020a056a02019200b0043ca0cb44d3mr21193147pgb.139.1665488711811; Tue, 11 Oct 2022 04:45:11 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1665488711; cv=none; d=google.com; s=arc-20160816; b=D/OCef0u0poaFk9GkpJftaYez9LTVh5oVgAuwxyZIOtQO1KBz+37IcPjmi6IFYUezv oyFHwZFp8XD6fGEpgK/cWaVOTTQJDN3d/dJzOKZzMrrKcwkkxWPt6/HtIDFMzronscFq KnMA/vdTFP3mmk0xh3fa28VnGMC+Tm+EPhhvUmHVPCRgDA8WYsfxOKaNs07yZHXDr6P5 dUKge8D/6JAiOuS+EUImYoqeQ7lpLJ11IXgkW5a5/HxEbU/xtOZLpOpahSrIPtak7KcN zJ7Fu0v0VyGLDzECJPG/K1krvtVOV4o/IOwxT5KMjpvp8ZW8Jr2eooDF+HxQ68r0gMpM LSbA== 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 :user-agent:references:in-reply-to:date:cc:to:from:subject :message-id:dkim-signature; bh=u1hbqqzbWNT/5E/BpvJ3/Vjrk7gdxHvHj9BLV42QDiA=; b=q1z0iNxCdaoPfGFcsXb4BePJbnX3PyOWCZhGkm8c+ZepIhG42AT8NoXr9ocBsUDNnx Foc08NqPBmKgI/hdZWadkHw3p3Ph5Ac2/gOqs9TpYlLNoqQw80fNFS398cUsXDhu0WtJ L4bHk5rez8+ZtvZvbX46zmKLMxLxiaTRXyq9YVONRBbjmtcWQsYIs9mb7KiY2soV5+BF jEs6bp9P5L/isDf63ukS8PChrOhCclYl0Ums/9sYQNRse6v/oQ3rtR75iETN0u0x9Uhc Nlll3Rfpzl030Kh/bExMV65CXYX9dDcJr401e/H6DwWvdv6XTH+RRpI3ye83RAAbY0LH 0PCw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=glq83Z8d; 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=NONE dis=NONE) header.from=redhat.com Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id my10-20020a17090b4c8a00b00205d798ce68si15643860pjb.139.2022.10.11.04.45.00; Tue, 11 Oct 2022 04:45:11 -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=@redhat.com header.s=mimecast20190719 header.b=glq83Z8d; 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=NONE dis=NONE) header.from=redhat.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229607AbiJKLfL (ORCPT + 99 others); Tue, 11 Oct 2022 07:35:11 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45908 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229656AbiJKLfI (ORCPT ); Tue, 11 Oct 2022 07:35:08 -0400 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0F34B3CBC1 for ; Tue, 11 Oct 2022 04:35:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1665488102; 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: in-reply-to:in-reply-to:references:references; bh=u1hbqqzbWNT/5E/BpvJ3/Vjrk7gdxHvHj9BLV42QDiA=; b=glq83Z8dhP1uWS8sC4OoBctI+edz3r9r1hZKMukahVlOog5dnhNMH1kg8gnBlWUgf3wCix czR+b+UDIZGDQRNAslSL+TWcCoLHzm7DnARYnNpBg1qh6T3OWUOlFK7AfbyC2xYw3gXQiy mEP5VeGBYwkFE8y2kwwuUOxTS66peJY= Received: from mail-wm1-f72.google.com (mail-wm1-f72.google.com [209.85.128.72]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_128_GCM_SHA256) id us-mta-640-0G-1_3rjOwyLLH1yuixRnA-1; Tue, 11 Oct 2022 07:35:01 -0400 X-MC-Unique: 0G-1_3rjOwyLLH1yuixRnA-1 Received: by mail-wm1-f72.google.com with SMTP id d5-20020a05600c34c500b003b4fb42ccdeso10449835wmq.8 for ; Tue, 11 Oct 2022 04:35:01 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:user-agent:references :in-reply-to:date:cc:to:from:subject:message-id:x-gm-message-state :from:to:cc:subject:date:message-id:reply-to; bh=u1hbqqzbWNT/5E/BpvJ3/Vjrk7gdxHvHj9BLV42QDiA=; b=3MD4Jw/2lWvrkdphFyL7Z1Plpd8BmpPgqMqUnSfds1cRs3qSYaKDx5TvD72f8nBK/P VwJR+PGTSCV7l+Ve0qjLwXTvQWaqHax4UUAOcOCiYBpV1VEUEpVKUvZbvNT+6a1vszcB eDkXCAAiGMDZluVpBgtDIsF+nT2vXxJrcRBkLVZxnaDpukz7Asj7eCn2qYr8XvJYWCF3 4wI6DEq+LcBCF6cMcDVyTUpw/7o9r2x7DKkoxgZrwvj2AGjWGtczg3fVnhwvet+xGYpp 3y2ay8Ldt0xTpAU29j3k8SY35ebJvNWVGKWB/GQM4Ufdcr/9ReWZhKdVjhjAooa2uinI W+3Q== X-Gm-Message-State: ACrzQf2ptFGCuj/QARVdMwwXZwlqh+xo4P8/WKlHvJ8wkzmACLX1QhBh p14YQ5o4+G0pZLgkHps9GN3WiDRByAPKSk7rlS1ciUi89HPUfzgy3dQrRVuiOvVtSM7lNn87DOm 3tW56uwdTI87LX0FWj7CrJXz/ X-Received: by 2002:a05:600c:3d05:b0:3b4:9a42:10d0 with SMTP id bh5-20020a05600c3d0500b003b49a4210d0mr16370538wmb.135.1665488100048; Tue, 11 Oct 2022 04:35:00 -0700 (PDT) X-Received: by 2002:a05:600c:3d05:b0:3b4:9a42:10d0 with SMTP id bh5-20020a05600c3d0500b003b49a4210d0mr16370520wmb.135.1665488099770; Tue, 11 Oct 2022 04:34:59 -0700 (PDT) Received: from gerbillo.redhat.com (146-241-103-235.dyn.eolo.it. [146.241.103.235]) by smtp.gmail.com with ESMTPSA id a8-20020a1cf008000000b003a6a3595edasm12193963wmb.27.2022.10.11.04.34.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 11 Oct 2022 04:34:59 -0700 (PDT) Message-ID: Subject: Re: [PATCH v1 net 3/3] selftest: Add test for SO_INCOMING_CPU. From: Paolo Abeni To: Kuniyuki Iwashima , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Hideaki YOSHIFUJI , David Ahern , Martin KaFai Lau Cc: Craig Gallek , Willem de Bruijn , Kuniyuki Iwashima , netdev@vger.kernel.org, linux-kernel@vger.kernel.org Date: Tue, 11 Oct 2022 13:34:58 +0200 In-Reply-To: <20221010174351.11024-4-kuniyu@amazon.com> References: <20221010174351.11024-1-kuniyu@amazon.com> <20221010174351.11024-4-kuniyu@amazon.com> Content-Type: text/plain; charset="UTF-8" User-Agent: Evolution 3.42.4 (3.42.4-2.fc35) MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,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 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Mon, 2022-10-10 at 10:43 -0700, Kuniyuki Iwashima wrote: > Some highly optimised applications use SO_INCOMING_CPU to make them > efficient, but they didn't test if it's working correctly by getsockopt() > to avoid slowing down. As a result, no one noticed it had been broken > for years, so it's a good time to add a test to catch future regression. > > The test does > > 1) Create $(nproc) TCP listeners associated with each CPU. > > 2) Create 32 child sockets for each listener by calling > sched_setaffinity() for each CPU. > > 3) Check if accept()ed sockets' sk_incoming_cpu matches > listener's one. > > If we see -EAGAIN, SO_INCOMING_CPU is broken. However, we might not see > any error even if broken; the kernel could miraculously distribute all SYN > to correct listeners. Not to let that happen, we must increase the number > of clients and CPUs to some extent, so the test requires $(nproc) >= 2 and > creates 64 sockets at least. > > Test: > $ nproc > 96 > $ ./so_incoming_cpu > > Before the previous patch: > > # Starting 1 tests from 2 test cases. > # RUN so_incoming_cpu.test1 ... > # so_incoming_cpu.c:129:test1:Expected cpu (82) == i (0) > # test1: Test terminated by assertion > # FAIL so_incoming_cpu.test1 > not ok 1 so_incoming_cpu.test1 > # FAILED: 0 / 1 tests passed. > # Totals: pass:0 fail:1 xfail:0 xpass:0 skip:0 error:0 > > After: > > # Starting 1 tests from 2 test cases. > # RUN so_incoming_cpu.test1 ... > # so_incoming_cpu.c:137:test1:SO_INCOMING_CPU is very likely to be working correctly with 3072 sockets. > # OK so_incoming_cpu.test1 > ok 1 so_incoming_cpu.test1 > # PASSED: 1 / 1 tests passed. > # Totals: pass:1 fail:0 xfail:0 xpass:0 skip:0 error:0 > > Signed-off-by: Kuniyuki Iwashima > --- > tools/testing/selftests/net/.gitignore | 1 + > tools/testing/selftests/net/Makefile | 1 + > tools/testing/selftests/net/so_incoming_cpu.c | 148 ++++++++++++++++++ > 3 files changed, 150 insertions(+) > create mode 100644 tools/testing/selftests/net/so_incoming_cpu.c > > diff --git a/tools/testing/selftests/net/.gitignore b/tools/testing/selftests/net/.gitignore > index 3d7adee7a3e6..ff8807cc9c2e 100644 > --- a/tools/testing/selftests/net/.gitignore > +++ b/tools/testing/selftests/net/.gitignore > @@ -25,6 +25,7 @@ rxtimestamp > sk_bind_sendto_listen > sk_connect_zero_addr > socket > +so_incoming_cpu > so_netns_cookie > so_txtime > stress_reuseport_listen > diff --git a/tools/testing/selftests/net/Makefile b/tools/testing/selftests/net/Makefile > index 2a6b0bc648c4..ba57e7e7dc86 100644 > --- a/tools/testing/selftests/net/Makefile > +++ b/tools/testing/selftests/net/Makefile > @@ -70,6 +70,7 @@ TEST_PROGS += io_uring_zerocopy_tx.sh > TEST_GEN_FILES += bind_bhash > TEST_GEN_PROGS += sk_bind_sendto_listen > TEST_GEN_PROGS += sk_connect_zero_addr > +TEST_GEN_PROGS += so_incoming_cpu > > TEST_FILES := settings > > diff --git a/tools/testing/selftests/net/so_incoming_cpu.c b/tools/testing/selftests/net/so_incoming_cpu.c > new file mode 100644 > index 000000000000..0ee0f2e393eb > --- /dev/null > +++ b/tools/testing/selftests/net/so_incoming_cpu.c > @@ -0,0 +1,148 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* Copyright Amazon.com Inc. or its affiliates. */ > +#define _GNU_SOURCE > +#include > + > +#include > +#include > +#include > + > +#include "../kselftest_harness.h" > + > +#define CLIENT_PER_SERVER 32 /* More sockets, more reliable */ > +#define NR_SERVER self->nproc > +#define NR_CLIENT (CLIENT_PER_SERVER * NR_SERVER) > + > +FIXTURE(so_incoming_cpu) > +{ > + int nproc; > + int *servers; > + union { > + struct sockaddr addr; > + struct sockaddr_in in_addr; > + }; > + socklen_t addrlen; > +}; > + > +FIXTURE_SETUP(so_incoming_cpu) > +{ > + self->nproc = get_nprocs(); > + ASSERT_LE(2, self->nproc); > + > + self->servers = malloc(sizeof(int) * NR_SERVER); > + ASSERT_NE(self->servers, NULL); > + > + self->in_addr.sin_family = AF_INET; > + self->in_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); > + self->in_addr.sin_port = htons(0); > + self->addrlen = sizeof(struct sockaddr_in); > +} > + > +FIXTURE_TEARDOWN(so_incoming_cpu) > +{ > + int i; > + > + for (i = 0; i < NR_SERVER; i++) > + close(self->servers[i]); > + > + free(self->servers); > +} > + > +void create_servers(struct __test_metadata *_metadata, > + FIXTURE_DATA(so_incoming_cpu) *self) > +{ > + int i, fd, ret; > + > + for (i = 0; i < NR_SERVER; i++) { > + fd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0); > + ASSERT_NE(fd, -1); > + > + ret = setsockopt(fd, SOL_SOCKET, SO_INCOMING_CPU, &i, sizeof(int)); > + ASSERT_EQ(ret, 0); > + > + ret = setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &(int){1}, sizeof(int)); > + ASSERT_EQ(ret, 0); > + > + ret = bind(fd, &self->addr, self->addrlen); > + ASSERT_EQ(ret, 0); > + > + if (i == 0) { > + ret = getsockname(fd, &self->addr, &self->addrlen); > + ASSERT_EQ(ret, 0); > + } > + > + /* We don't use CLIENT_PER_SERVER here not to block > + * this test at connect() if SO_INCOMING_CPU is broken. > + */ > + ret = listen(fd, NR_CLIENT); > + ASSERT_EQ(ret, 0); > + > + self->servers[i] = fd; > + } > +} > + > +void create_clients(struct __test_metadata *_metadata, > + FIXTURE_DATA(so_incoming_cpu) *self) > +{ > + cpu_set_t cpu_set; > + int i, j, fd, ret; > + > + for (i = 0; i < NR_SERVER; i++) { > + CPU_ZERO(&cpu_set); > + > + CPU_SET(i, &cpu_set); > + ASSERT_EQ(CPU_COUNT(&cpu_set), 1); > + ASSERT_NE(CPU_ISSET(i, &cpu_set), 0); > + > + /* Make sure SYN will be processed on the i-th CPU > + * and finally distributed to the i-th listener. > + */ > + sched_setaffinity(0, sizeof(cpu_set), &cpu_set); > + ASSERT_EQ(ret, 0); > + > + for (j = 0; j < CLIENT_PER_SERVER; j++) { > + fd = socket(AF_INET, SOCK_STREAM, 0); > + ASSERT_NE(fd, -1); > + > + ret = connect(fd, &self->addr, self->addrlen); > + ASSERT_EQ(ret, 0); > + > + close(fd); > + } > + } > +} > + > +void verify_incoming_cpu(struct __test_metadata *_metadata, > + FIXTURE_DATA(so_incoming_cpu) *self) > +{ > + int i, j, fd, cpu, ret, total = 0; > + socklen_t len = sizeof(int); > + > + for (i = 0; i < NR_SERVER; i++) { > + for (j = 0; j < CLIENT_PER_SERVER; j++) { > + /* If we see -EAGAIN here, SO_INCOMING_CPU is broken */ > + fd = accept(self->servers[i], &self->addr, &self->addrlen); > + ASSERT_NE(fd, -1); > + > + ret = getsockopt(fd, SOL_SOCKET, SO_INCOMING_CPU, &cpu, &len); > + ASSERT_EQ(ret, 0); > + ASSERT_EQ(cpu, i); > + > + close(fd); > + total++; > + } > + } > + > + ASSERT_EQ(total, NR_CLIENT); > + TH_LOG("SO_INCOMING_CPU is very likely to be " > + "working correctly with %d sockets.", total); > +} > + > +TEST_F(so_incoming_cpu, test1) > +{ > + create_servers(_metadata, self); > + create_clients(_metadata, self); > + verify_incoming_cpu(_metadata, self); > +} I think it would be nicer if you could add more test-cases, covering e.g.: - set SO_INCOMING_CPU after SO_REUSE_PORT, - initially including a socket without SO_INCOMING_CPU and the removing it from the soreuseport set Thanks, Paolo