From nobody Fri Oct 2 07:45:29 2026 Received: from mail-pg1-f178.google.com (mail-pg1-f178.google.com [209.85.215.178]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2D52B3F4DD6 for ; Tue, 4 Aug 2026 02:59:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.178 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785812378; cv=none; b=VGVR3vGbO0/myLK6zGoHm2g/OcwK+5dfczIKC4CRKevR7VVz7aH9YpatifaSB8VicoEdIpBVgp9CRpWax6kXNKS/UMlqcyNyso05u0Tt82AsTaCAPG6FCbNew4YFRVDjGIRNhCayXY10YVnmuoQyZWkRS3Cb0md6sJIxlKushi0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785812378; c=relaxed/simple; bh=kGHg5dJxMvflgLmIQwKaqqixfYXyjBoPcjsJhN7I9ys=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=uK7ZP4pJKHbXipL2gihQzx3dL3tkeqGPKWlm/WpdAy+AsCBBPJz0FTBwA5TD8H8eu7gymjoiJQeaUKQtO9ibWHC45dthCcSXfZi7bftpqA312lLQEgFQgffHdqnkppGcbTJ5EQzumx896ENvnmLAuHosxiJ57b1PpwUnjEARUnI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=DyXTQkr/; arc=none smtp.client-ip=209.85.215.178 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="DyXTQkr/" Received: by mail-pg1-f178.google.com with SMTP id 41be03b00d2f7-caf45fc5202so2794453a12.1 for ; Mon, 03 Aug 2026 19:59:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1785812376; x=1786417176; 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:content-type; bh=QkQ333WBrChtciSILIhBH7Fyg9DmGWGZdjGTMAJJv4M=; b=DyXTQkr/8xC0usDA55oPDLTk+SbM0KXdIyo0Eh10qwsLOBND6x5lWiY9cxhgdMKVw7 bkLsjl5QlK/xDVaBUKqiwU2u9d/dhK7mmpmtrIc7UGSsr1IuCsg0N/5T+ama6OOPMXkZ Xjy8UI2YHKQZ6iRqE1imkBnk38aHKV7c5kskoTVyUleAgBy67WNw8TX4ZON4Gv6OiXkd xWL7di0sFDMRJYNaNOxRJc5rQCWRr+rapGONzwxvMOWv0nzUd25TcV6wRbYe0qzmdBVs aKE4VxrcKq7f250754maIlAgtHvpo1J7v20Z13DRA9we1YoTo1tuCM91r+cA4iZda7V1 w+0Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1785812376; x=1786417176; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=QkQ333WBrChtciSILIhBH7Fyg9DmGWGZdjGTMAJJv4M=; b=W5ebAV241fjE1C3ALcwXmL3ce5hT87ze/jq69zvQ5iHhOiO2wcRccvARlpfE8GIMRq BdAY2ZMpEyPFlAg5fGAMJ/wVyrQDdqLBU9AcerKiW7omeKazVVQ3aiUmSmZBbn0qHsKx cRu4zzaHBdV0ovKGTU+iuFvw9Q25i2K3SJLLOcfCmuI2ss+RdX0pBV5cF5N631QqF5Mz NudFp5l2e7yPR0DWYifhqINRSEZNhXBQxc0TTtQaLZ48a9BJZLhlI1VsHW88+Hw3xZe0 /0G7USId1/emAP8j//N3ivSS3LNwdo03TpUnbjo8yERBdAnMKh/kHv7oehIxDlzcyezq mC2A== X-Forwarded-Encrypted: i=1; AHgh+Ro+J6SIWmcql0/JOZIsOG3fpUqQU2280wur7P1Uc0CQTbOX7EJz6eMQ6t2djCFfNhLEKLjWy8rhTBSalhM=@vger.kernel.org X-Gm-Message-State: AOJu0YzScbBqJegIAVjHia8BfYzPBpcXVWyjJSEBQ/dIIzrj99O5vcod FPJDLrGhNzRwANvhE2dl/EJNTQI2bZtdBL5Iuvs+eotE0IyMJMNYEwAo X-Gm-Gg: AR+sD11/4ooqZK9Lms81FBPDnhP7iBgNFWTDGzXcngHlS8AO59Tr46fM7Vql0nO4ktn w/M1sBc3u8c+PWFcVA1zG9rtrxkMgvqHAE/2+d53Pf/BhHgMnGiR10EhMYo+OiUz55k4+kByyD2 IfqXH4NdyWVwYSvCasYE4TNUC4Yqccg2S0YpVrsnyu6Hkpa/i5IVC9d5R8PCHD3mrJdjN6yJSM/ Wvi5VaYo2Lqr/F8P4vLQmnpRFQ0xtE7dD0IEBsyg5x3bFXq9gACbHEZoT9eAvAArGUPhqIkZKor MhX8GLUJWf4zJo2DOR/OXYWRmnvxuB+s6dxRdq5WmC/q/ZK4joTlgEKnFbvFuCCc/95SpQfyry3 1PIFm1B+AmKuRzzic+6R1+bFv10hooKkbNifRquS67OYiNrUubMdetvnwaNBlCr3hA2CAW3KuRC QUD2rAfpOVZ/TOUDiu6i0ny7qKIPYoaLa+1JB0TWk76WqMMTcthwnOgNX1GonERlx42g== X-Received: by 2002:a05:6a21:9206:b0:3c0:9c18:d5a6 with SMTP id adf61e73a8af0-3c92a8cc15bmr12885686637.67.1785812376564; Mon, 03 Aug 2026 19:59:36 -0700 (PDT) Received: from fedora ([2804:1b3:a8c3:8ee5:1c39:64d9:e257:73dc]) by smtp.gmail.com with ESMTPSA id a92af1059eb24-13fab2530c0sm35974758c88.8.2026.08.03.19.59.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 03 Aug 2026 19:59:36 -0700 (PDT) From: Marcelo Mendes Spessoto Junior To: netdev@vger.kernel.org Cc: davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, horms@kernel.org, shuah@kernel.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org, Marcelo Mendes Spessoto Junior Subject: [PATCH net-next v2 1/4] selftests: net: test IPV6_FL_A_RENEW Date: Mon, 3 Aug 2026 23:59:07 -0300 Message-ID: <20260804025910.50145-2-marcelomspessoto@gmail.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260804025910.50145-1-marcelomspessoto@gmail.com> References: <20260804025910.50145-1-marcelomspessoto@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" RENEW was the only flow label action without selftests coverage. Assert renew returns no error on correct usage and fails for labels that do not exist. Based on the previously implemented EXCL share test, that demonstrates that a new flow label with same label can be created after the linger period, use renew to show that the flow label can last longer and block a new flow label creation after the previous linger time. This test, however, demands sleep during execution, and should be placed as a conditional test under the -l option. The addition of expect_fail_errno helper is necessary to assert the corresponding error when a function can fail on multiple ways. Signed-off-by: Marcelo Mendes Spessoto Junior --- .../selftests/net/ipv6_flowlabel_mgr.c | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/tools/testing/selftests/net/ipv6_flowlabel_mgr.c b/tools/testi= ng/selftests/net/ipv6_flowlabel_mgr.c index af95b48acea9..01fab414895c 100644 --- a/tools/testing/selftests/net/ipv6_flowlabel_mgr.c +++ b/tools/testing/selftests/net/ipv6_flowlabel_mgr.c @@ -27,6 +27,7 @@ =20 /* from net/ipv6/ip6_flowlabel.c */ #define FL_MIN_LINGER 6 +#define FL_MAX_LINGER 150 =20 #define explain(x) \ do { if (cfg_verbose) fprintf(stderr, " " x "\n"); } while (0) @@ -42,6 +43,18 @@ #define expect_pass(x) __expect(x) #define expect_fail(x) __expect(!(x)) =20 +#define expect_fail_errno(x, e) \ + do { \ + int __exp =3D (e); \ + int __ret =3D (x); \ + int __err =3D errno; \ + if (__ret && __err =3D=3D __exp) \ + fprintf(stderr, "[OK] " #x "\n"); \ + else \ + error(1, 0, "[ERR] " #x " (line %d): expected errno %d, got %d", \ + __LINE__, __exp, __err); \ + } while (0) + static bool cfg_long_running; static bool cfg_verbose; =20 @@ -71,6 +84,17 @@ static int flowlabel_put(int fd, uint32_t label) return setsockopt(fd, SOL_IPV6, IPV6_FLOWLABEL_MGR, &req, sizeof(req)); } =20 +static int flowlabel_renew(int fd, uint32_t label, uint16_t linger) +{ + struct in6_flowlabel_req req =3D { + .flr_action =3D IPV6_FL_A_RENEW, + .flr_label =3D htonl(label), + .flr_linger =3D linger, + }; + + return setsockopt(fd, SOL_IPV6, IPV6_FLOWLABEL_MGR, &req, sizeof(req)); +} + static void run_tests(int fd) { int wstatus; @@ -160,6 +184,26 @@ static void run_tests(int fd) error(1, errno, "wait"); if (!WIFEXITED(wstatus) || WEXITSTATUS(wstatus) !=3D 0) error(1, errno, "wait: unexpected child result"); + + explain("It is not possible to renew a label that does not exist"); + expect_fail_errno(flowlabel_renew(fd, 5, 2 * (FL_MIN_LINGER * 2 + 1)), ES= RCH); + + explain("Create a label for basic renew validation"); + expect_pass(flowlabel_get(fd, 5, IPV6_FL_S_EXCL, IPV6_FL_F_CREATE)); + explain("Check if renew does not return errors for existing and valid lab= el"); + expect_pass(flowlabel_renew(fd, 5, 2 * (FL_MIN_LINGER * 2 + 1))); + + if (cfg_long_running) { + explain("create a new label with FL_MIN_LINGER linger time"); + expect_pass(flowlabel_get(fd, 6, IPV6_FL_S_EXCL, IPV6_FL_F_CREATE)); + explain("renew the label to increase its linger time and put it"); + expect_pass(flowlabel_renew(fd, 6, 2 * (FL_MIN_LINGER * 2 + 1))); + expect_pass(flowlabel_put(fd, 6)); + sleep(FL_MIN_LINGER * 2 + 1); + explain("The label cannot be created because the new linger time is not = over yet"); + expect_fail_errno(flowlabel_get(fd, 6, IPV6_FL_S_ANY, IPV6_FL_F_CREATE),= EPERM); + } + } =20 static void parse_opts(int argc, char **argv) --=20 2.55.0 From nobody Fri Oct 2 07:45:29 2026 Received: from mail-pg1-f179.google.com (mail-pg1-f179.google.com [209.85.215.179]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8F67240B114 for ; Tue, 4 Aug 2026 02:59:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.179 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785812382; cv=none; b=k3aG6agccIK77joEE+HwGXrVzRWSB6crkLCB5yQrPRhOhmO9x0wUH1+n+5m9qEPmx2v6XugQg9SR/L3WbxncT7SHtaOEbT4MnnuGFzJpxrG+xsDuW0oVjuTucCnghW74y7UFJsVi1/DgO8zuEmTrmJ0ynkrmMO5XI7Y3JExlCOs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785812382; c=relaxed/simple; bh=H0UkMIe4CsIcpxmyZN1Ww99+u120SPTOqvKQ5GFRMAc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=G48MY2bhDu0V4rd3O9kBbrQ+cNepKhxra9dSTkyFMy8W10PE6pPjldbPp8ZMT3jZ5kyx6Mm/sPprKC0dxON+/SvkkmFz4EZLGqDV8jdaGkzG5kfD4Pz6BNniPqf2uLUOABfoiU4/v5dAdjDIbAS206TNGlVdTqRRRA4KIyxu7ZY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=SLVNK0jc; arc=none smtp.client-ip=209.85.215.179 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="SLVNK0jc" Received: by mail-pg1-f179.google.com with SMTP id 41be03b00d2f7-c9fe3c9bd5fso383255a12.0 for ; Mon, 03 Aug 2026 19:59:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1785812381; x=1786417181; 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:content-type; bh=jmT/3flv0l5fERcYAXy6zGT7XeDtm3nxWHOeoNo8+6g=; b=SLVNK0jcCd9rz4z1O9bVlrwxWuIGHtT7Ov3Wia8WcOx7cah/lrc1t9r+jplPbJ5x91 mp3DQW4EKBiWZX9ZUVw3DVnr/Pkvaw+wU2syXou1ul2+5qY/b6fj9hVAHWJD4VYYr9hx n8WVjRiask9+XzHyE4d9stsKEwbJ7Ye8jI+xEsE1fTWfxbCuDxyvNEswriY4n0WU3yLN gXUFF/JwWIklI1NqQHo8pszitiX5cC5KfnEaRZJ2+1QSOd1Cod3maTW7KG3yZrEaAX/k r5DDD0iBZiOJvrvH7+vxIMC0vEV9xGRwOfh1TBdHCgcKKU/A90Oo1uKMuLIJz9s0FCuz pS6w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1785812381; x=1786417181; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=jmT/3flv0l5fERcYAXy6zGT7XeDtm3nxWHOeoNo8+6g=; b=j1rhKnTmw12H0hDVGFC2StLbNgeG27KMqzVt1Y/6UWiAE/ToEfXWxGIdrVl8bH3f25 VLyAXBGhoxjba23DDDY7Ug9MIorDW18+1mTtdAiYsRZc/avCU7N0lcbvgA6pQRvcPgl7 O3w0uXzgiEf14aRDM5uZiQfQMUS0YSPRWeQQyso9dWEZcWkXm0i9nKQ30ijvoV6IDn1q /+Ri2ytvg5HNVDrPilUcd7RtqnVMwUE/BtnfZ/Z0bPDIK18O3+8mI+Y/vhYJyB+GTRo5 hmEj6o2AKdVXHkD1svd7FfhVG0vd86i/79xomS8k5tj6/M/NyKuhRq41f7bkwOBKNmxA NrIg== X-Forwarded-Encrypted: i=1; AHgh+Rq03bDFZzzTJi9peArTT+QxmPQC0GO0oeMAdmOHk/mbB6yutSs/mErtj6hFfE2xa5LeKUbKuG0bUWAByg0=@vger.kernel.org X-Gm-Message-State: AOJu0Yz8KgmUBWLUQNXGKvIHQT6G1wPYJ7SrrvWPkr2l30B+kij/pjUC Qd/bgqDU2OyC6lAsYtLsmfveKmAffKcksPQpCwTNzcI6Ij080Y1hrgXk7CmfQDiF X-Gm-Gg: AR+sD11fU/6ITF1x3Y3CL1SF5i3mZS4uQHDvI3x0q+8JQoDDP6zsvq8d06B11v9E4hf v2DSumUqIZ8i7aACb06OM6gLeHe/v5Jebs4GdxFXANhAScXvrF4Fay/gLCF1GXX632SSrpufOVl e5BvwmnYcJsOM9HKwhejThXJIfeE4bP963zkvOl4Ldmr7HR1sDyN0vTr4BrgAeXWddIwqzxBJzj KkpmY4WVBHRfemChS8yPOCYwmek12aAlBYjRL63FRaApFkgAjsi38nzAsn22enc0OcqDaKUR9qx up0HokzvumyccCw6UpuMgu4qz9eo/fkQNEIlPULMiqU1WnwrAB4ymupZKB0hGEMCblAfbRkmNHP pWTQQA+I95dubv5dFEg/NXcoSirvlvky4MZ+aVfzyTus/WV9qjzM+tAjTw4A3vHOqseMwsSO5gl 8d6tl/ksoNNyM+B11bNZ53kC9qq8y9tTrTsFBCM3qsQbm6MDY1Fe4We7Fz6NJbI0FRfw== X-Received: by 2002:a05:6a20:9e47:b0:3c0:b598:4983 with SMTP id adf61e73a8af0-3cb6ca54d23mr2124033637.30.1785812380841; Mon, 03 Aug 2026 19:59:40 -0700 (PDT) Received: from fedora ([2804:1b3:a8c3:8ee5:1c39:64d9:e257:73dc]) by smtp.gmail.com with ESMTPSA id a92af1059eb24-13fab2530c0sm35974758c88.8.2026.08.03.19.59.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 03 Aug 2026 19:59:40 -0700 (PDT) From: Marcelo Mendes Spessoto Junior To: netdev@vger.kernel.org Cc: davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, horms@kernel.org, shuah@kernel.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org, Marcelo Mendes Spessoto Junior Subject: [PATCH net-next v2 2/4] selftests: net: test IPV6_FL_F_REMOTE Date: Mon, 3 Aug 2026 23:59:08 -0300 Message-ID: <20260804025910.50145-3-marcelomspessoto@gmail.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260804025910.50145-1-marcelomspessoto@gmail.com> References: <20260804025910.50145-1-marcelomspessoto@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" This flag retrieves the flow label seen by the socket at connection setup via a getsockopt query. Therefore, the validation of this flag requires a brief connection setup (source code for flow label shows it must be TCP). The simple TCP connection logic was wrapped inside two simple helpers, because there are other uncovered features of flow label mgr that could benefit from it (such as IPV6_FL_F_REFLECT). Signed-off-by: Marcelo Mendes Spessoto Junior --- .../selftests/net/ipv6_flowlabel_mgr.c | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/tools/testing/selftests/net/ipv6_flowlabel_mgr.c b/tools/testi= ng/selftests/net/ipv6_flowlabel_mgr.c index 01fab414895c..d482be2e9f9f 100644 --- a/tools/testing/selftests/net/ipv6_flowlabel_mgr.c +++ b/tools/testing/selftests/net/ipv6_flowlabel_mgr.c @@ -24,6 +24,9 @@ #ifndef IPV6_FLOWLABEL_MGR #define IPV6_FLOWLABEL_MGR 32 #endif +#ifndef IPV6_FLOWINFO_SEND +#define IPV6_FLOWINFO_SEND 33 +#endif =20 /* from net/ipv6/ip6_flowlabel.c */ #define FL_MIN_LINGER 6 @@ -95,6 +98,66 @@ static int flowlabel_renew(int fd, uint32_t label, uint1= 6_t linger) return setsockopt(fd, SOL_IPV6, IPV6_FLOWLABEL_MGR, &req, sizeof(req)); } =20 +static struct sockaddr_in6 loopback_addr(void) +{ + struct sockaddr_in6 addr =3D { + .sin6_family =3D AF_INET6, + .sin6_addr =3D IN6ADDR_LOOPBACK_INIT, + .sin6_port =3D htons(8888), + }; + + return addr; +} + +static int tcp_listen(void) +{ + struct sockaddr_in6 addr =3D loopback_addr(); + const int one =3D 1; + int fd; + + fd =3D socket(PF_INET6, SOCK_STREAM, 0); + if (fd =3D=3D -1) + error(1, errno, "socket listener"); + if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one))) + error(1, errno, "setsockopt SO_REUSEADDR"); + if (bind(fd, (void *)&addr, sizeof(addr))) + error(1, errno, "bind"); + if (listen(fd, 1)) + error(1, errno, "listen"); + + return fd; +} + +static void tcp_connect(int listener, uint32_t flowlabel, int *client, int= *accepted) +{ + struct sockaddr_in6 addr =3D loopback_addr(); + const int one =3D 1; + int cfd, afd; + + cfd =3D socket(PF_INET6, SOCK_STREAM, 0); + if (cfd =3D=3D -1) + error(1, errno, "socket client"); + + if (flowlabel_get(cfd, flowlabel, IPV6_FL_S_EXCL, IPV6_FL_F_CREATE)) + error(1, errno, "flowlabel_get"); + if (setsockopt(cfd, SOL_IPV6, IPV6_FLOWINFO_SEND, &one, sizeof(one))) + error(1, errno, "setsockopt flowinfo_send"); + addr.sin6_flowinfo =3D htonl(flowlabel); + + if (connect(cfd, (void *)&addr, sizeof(addr))) + error(1, errno, "connect"); + + afd =3D accept(listener, NULL, NULL); + if (afd =3D=3D -1) + error(1, errno, "accept"); + + if (flowlabel_put(cfd, flowlabel)) + error(1, errno, "flowlabel_put"); + + *client =3D cfd; + *accepted =3D afd; +} + static void run_tests(int fd) { int wstatus; @@ -204,6 +267,27 @@ static void run_tests(int fd) expect_fail_errno(flowlabel_get(fd, 6, IPV6_FL_S_ANY, IPV6_FL_F_CREATE),= EPERM); } =20 + { + struct in6_flowlabel_req freq =3D { + .flr_action =3D IPV6_FL_A_GET, + .flr_flags =3D IPV6_FL_F_REMOTE, + }; + socklen_t freq_len =3D sizeof(freq); + int remote_listener =3D tcp_listen(); + int remote_cfd, remote_afd; + + explain("Prepare TCP SYN for REMOTE flag validation"); + tcp_connect(remote_listener, 7, &remote_cfd, &remote_afd); + + explain("Query for label sent by client with IPV6_FL_F_REMOTE"); + expect_pass(getsockopt(remote_afd, SOL_IPV6, IPV6_FLOWLABEL_MGR, &freq, = &freq_len)); + if (ntohl(freq.flr_label) !=3D 7) + error(1, 0, "unexpected remote flowlabel %u", ntohl(freq.flr_label)); + + close(remote_afd); + close(remote_cfd); + close(remote_listener); + } } =20 static void parse_opts(int argc, char **argv) --=20 2.55.0 From nobody Fri Oct 2 07:45:29 2026 Received: from mail-pj1-f48.google.com (mail-pj1-f48.google.com [209.85.216.48]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CDD3841A4E4 for ; Tue, 4 Aug 2026 02:59:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.48 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785812386; cv=none; b=cDZcwcTFVkuqFlyYfCrRSEPZv3IcIY+DZ8006oWpEge5I+e/TI1qtrUZiip8x9UbKUsJP8AH1fH3EJd0g4fFVee6dD2iIi/ME2LIP4EhQUwIEVJRyXejKNDxWYJfeM9mzIdwSnTb1JNVNpxDmppbbYFlQtWGq+diER+8xe0ZiHU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785812386; c=relaxed/simple; bh=JmhELRI2ithkLQv4rBVDAJOIi3ocRRvtV26qJNG/l5o=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=cyHRPfjUMShvktcbKP8Yn+NEKN48tJc50AVx1qmgGxKqKBdJgQ5gFEKojZtafpb9EjW0DXcTvIELOFuC8r6X0sOXLCnEmZMpW48v+xvyvUfHICENkAFjbQroAt0Lsxf+jNM4NHMR31sQTvXU3jFei+vz2lhZbDVau5PgG72B67k= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=Umm9D5CG; arc=none smtp.client-ip=209.85.216.48 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Umm9D5CG" Received: by mail-pj1-f48.google.com with SMTP id 98e67ed59e1d1-38e07ebd263so2491225a91.1 for ; Mon, 03 Aug 2026 19:59:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1785812384; x=1786417184; 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:content-type; bh=fEwXBy8GqBmJpL/bfLNE70Yj9p6IegQd47Zgr1mcc8U=; b=Umm9D5CGiqD9wJ5b0bLDhXBjpvJfP1pOA1l9iPfkjuCp0zxa170eMMbJP6pO/CSnmJ FKdIq87leBBX2yk08b7BSJccAt4nJClHzldU24pgnJ+WOycec2R+egrdfsOQTsr6AqgX Sf1R9pxT1fFyil+tBucAvqDoQc6bcc2epWxq4lpDnUV0A99ucSVHl1QiVgkKROPC4w8W Upl6/C9oiFY4A1SW29qlBNRflYbmYV4+H/DeyMApPwY+YWSNFYOXEuherz0i92OzzWbp HUWk0vxFD7Op7urQUfZH0gi4l+92WrCkLnf/zLYs2cw63oQsUHysERy1AyO6Y6QBzl/1 H/4A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1785812384; x=1786417184; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=fEwXBy8GqBmJpL/bfLNE70Yj9p6IegQd47Zgr1mcc8U=; b=UN8PCsfcFeTeOlfffas77EGnH/V9LR4V9egaGl6LbKiSJECnk7uTiqXYefLy7eza8k vxqtDgxzm5eoJIrbebm1K9LHA/+jSc3VO+RyakHEidGbSjxrg+aZye3YqJ79QMVBwO/d ZFQqK04bTcMkOsOCKhYHe40ubGo2KlIkpb7a32IlwzYct/Z2XNVnzMvydpog9FkbO8iE wIGE/4yOwWvlhhnKAch1/N5nX5iwPJC1Zejkbzm2U6md/zNlg4e3dllN26hY+tl6zPyN gocwmaSJFtSPaw1MHrLZjkwIHlbBUut9fSlw0MBm0Pvp1rnAX0LTfFzg5V78JMKQPRkh g9hA== X-Forwarded-Encrypted: i=1; AHgh+Rq9FQ0qn2FtDi2SyTOcDFKVtDRPiP/oCRgqCs9GCihrwcc7slK4Ni6iw1ahelh+QNrA4P1cmAdT+l0UOW8=@vger.kernel.org X-Gm-Message-State: AOJu0Yx68AmUNwId8S2j6IxlnYlzthHghEAn5yY3E4ilP7XGJhWOGqJ/ erpGVUT1d/koeWyplRqMZIm2OiWWK5Tgimw6jy+Z4UxVnaS7Ce10pro8 X-Gm-Gg: AR+sD11L+bdwv/7RVZQvWPebwh/z6KDncbpx+4CMq7mY/T2K9LxEKb8yqC4+F1mWY6i uHG3sYu2SHrlVHCxCvbl1m75B5Q0fob2rJFuVAGOcaQTHKbJIyZ1DnLHLqC9pq1GwmXsQGuT9BM aJW8ZiW5anadm1Su4tl08DETVGgys0ehaUiHIE/sIjEGBd+f0wHlYwoLjOuInacveXT0uqYDPbF agx5IhHw0p1NKNj9oi1cZeiSw0GAZuyKr2SqB2rgLN7wYS+p9nf2aM3+cxPnD48jTqBSDkvdXXe NGp5pNVxli1gEmVv/tzqolgeHO2MuQoC1t3QZwL3Klq/CaNWBa7dbvo2oQblQOqZu7aONkcPlZc RfGGMXYamhBZONZFW+TQS1P2AEkPsLdDy+MlTql7ybzoVfwxM0MhJLJgpT88C8YB/7p72uvYa41 stk8riwbJM7P+lBaiAHYodaeeDU8IDJFHJI6i06wkkwLaXHL4Hj2gZ6Z9Je7TkW7tyIdU83Kzhl djz X-Received: by 2002:a17:90b:57e6:b0:38f:23d6:b4ad with SMTP id 98e67ed59e1d1-38fbc3f7e43mr11073937a91.8.1785812384145; Mon, 03 Aug 2026 19:59:44 -0700 (PDT) Received: from fedora ([2804:1b3:a8c3:8ee5:1c39:64d9:e257:73dc]) by smtp.gmail.com with ESMTPSA id a92af1059eb24-13fab2530c0sm35974758c88.8.2026.08.03.19.59.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 03 Aug 2026 19:59:43 -0700 (PDT) From: Marcelo Mendes Spessoto Junior To: netdev@vger.kernel.org Cc: davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, horms@kernel.org, shuah@kernel.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org, Marcelo Mendes Spessoto Junior Subject: [PATCH net-next v2 3/4] selftests: net: test IPV6_FL_F_REFLECT Date: Mon, 3 Aug 2026 23:59:09 -0300 Message-ID: <20260804025910.50145-4-marcelomspessoto@gmail.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260804025910.50145-1-marcelomspessoto@gmail.com> References: <20260804025910.50145-1-marcelomspessoto@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" According to source code, flowlabel_consistency must be deactivated for the IPV6_FL_F_REFLECT flag to work. Therefore, take the following measures: deactivate it on the wrapper .sh script, and skip this test if it is run on an environment that does not correspond. The previously defined tcp_listen and tcp_connect helpers were reused, since the connection flow required for REFLECT validation is very similar to REMOTE. Signed-off-by: Marcelo Mendes Spessoto Junior --- tools/testing/selftests/net/ipv6_flowlabel.sh | 3 +- .../selftests/net/ipv6_flowlabel_mgr.c | 61 +++++++++++++++++++ 2 files changed, 63 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/net/ipv6_flowlabel.sh b/tools/testing/= selftests/net/ipv6_flowlabel.sh index cee95e252bee..4c3de3a27807 100755 --- a/tools/testing/selftests/net/ipv6_flowlabel.sh +++ b/tools/testing/selftests/net/ipv6_flowlabel.sh @@ -8,7 +8,8 @@ set -e =20 echo "TEST management" -./in_netns.sh ./ipv6_flowlabel_mgr +./in_netns.sh \ + sh -c 'sysctl -q -w net.ipv6.flowlabel_consistency=3D0 && ./ipv6_flowlab= el_mgr' =20 echo "TEST datapath" ./in_netns.sh \ diff --git a/tools/testing/selftests/net/ipv6_flowlabel_mgr.c b/tools/testi= ng/selftests/net/ipv6_flowlabel_mgr.c index d482be2e9f9f..af87eec799c8 100644 --- a/tools/testing/selftests/net/ipv6_flowlabel_mgr.c +++ b/tools/testing/selftests/net/ipv6_flowlabel_mgr.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -158,6 +159,22 @@ static void tcp_connect(int listener, uint32_t flowlab= el, int *client, int *acce *accepted =3D afd; } =20 +static bool flowlabel_consistency_enabled(void) +{ + char buf[2] =3D {}; + int fd; + + fd =3D open("/proc/sys/net/ipv6/flowlabel_consistency", O_RDONLY); + if (fd =3D=3D -1) + return true; + + if (read(fd, buf, sizeof(buf) - 1) < 0) + buf[0] =3D '1'; + close(fd); + + return buf[0] !=3D '0'; +} + static void run_tests(int fd) { int wstatus; @@ -288,6 +305,50 @@ static void run_tests(int fd) close(remote_cfd); close(remote_listener); } + + if (flowlabel_consistency_enabled()) { + fprintf(stderr, + "[INFO] skip REFLECT flag validation (net.ipv6.flowlabel_consistency mu= st be 0)\n"); + } else { + struct in6_flowlabel_req reflect_query =3D { + .flr_action =3D IPV6_FL_A_GET, + }; + struct in6_flowlabel_req reflect_off =3D { + .flr_action =3D IPV6_FL_A_PUT, + .flr_flags =3D IPV6_FL_F_REFLECT, + }; + struct in6_flowlabel_req reflect_on =3D { + .flr_action =3D IPV6_FL_A_GET, + .flr_flags =3D IPV6_FL_F_REFLECT, + }; + socklen_t reflect_query_len =3D sizeof(reflect_query); + int reflect_listener =3D tcp_listen(); + int reflect_cfd, reflect_afd; + + explain("Enable REFLECT on the listener before the client connects"); + expect_pass(setsockopt(reflect_listener, SOL_IPV6, IPV6_FLOWLABEL_MGR, + &reflect_on, sizeof(reflect_on))); + + tcp_connect(reflect_listener, 8, &reflect_cfd, &reflect_afd); + + explain("Query the accepted socket's outgoing label, should be reflected= "); + expect_pass(getsockopt(reflect_afd, SOL_IPV6, IPV6_FLOWLABEL_MGR, + &reflect_query, &reflect_query_len)); + if (ntohl(reflect_query.flr_label) !=3D 8) + error(1, 0, "unexpected reflected flowlabel %u", + ntohl(reflect_query.flr_label)); + + explain("PUT+REFLECT disables reflection on the accepted socket"); + expect_pass(setsockopt(reflect_afd, SOL_IPV6, IPV6_FLOWLABEL_MGR, + &reflect_off, sizeof(reflect_off))); + explain("cannot disable reflection twice"); + expect_fail(setsockopt(reflect_afd, SOL_IPV6, IPV6_FLOWLABEL_MGR, + &reflect_off, sizeof(reflect_off))); + + close(reflect_afd); + close(reflect_cfd); + close(reflect_listener); + } } =20 static void parse_opts(int argc, char **argv) --=20 2.55.0 From nobody Fri Oct 2 07:45:29 2026 Received: from mail-pj1-f52.google.com (mail-pj1-f52.google.com [209.85.216.52]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4539D415F1A for ; Tue, 4 Aug 2026 02:59:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.52 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785812391; cv=none; b=dGvCHfB9hfE9Xt6UewfEWjJoubuVf2qaeVf8gWGdYqnOGyEEWbIObYkl8cdvrBwEAnxtLUlT3kV0q0Xrxl9GbSoDmQ9J7e2ZhXOhG/et9G1JpDsZRTdm257/NDQNlycQeInZvGsIBkulnG8TXYLOyApBBl/nhm9xyvSRkkMqwqE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785812391; c=relaxed/simple; bh=FpK+PjjhCN3h8Em234HUUSWkZ7XkOYTLlXHlmQ8TqeQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=NeXojjtUIkiCWKi/hCj0tpO0sm1/EJgrR7uLAbN37R0Lrm8zJN3q7B+9b+9n3CTRPFe+GhGhDQUOEWsV9VrM0ifkxGkpdz0ClhQO+q5VuSujz85jiEEpBJxAayvpDdkDUVltbaVB9UEp/S0TPKEQeHjEDesdi1l9DbaEVbDl8mU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=AdmgjJA6; arc=none smtp.client-ip=209.85.216.52 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="AdmgjJA6" Received: by mail-pj1-f52.google.com with SMTP id 98e67ed59e1d1-38e347638adso4692103a91.0 for ; Mon, 03 Aug 2026 19:59:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1785812388; x=1786417188; 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:content-type; bh=wQo8OcjOTMXh9X3kaJrhqxoi/2bzY3rrnHALBkkL6gk=; b=AdmgjJA6SChaUVOrLRrWjVjcF7nBFg5P7vhAiaVZf3/Z9KEOoXhzYNWn/qGvcWdIO9 6DflZYywJbrRPLe/gLc/3W1eFEzSh7SOhxBnQMBxLLGN/9OJEMzL47hxmTsOWCIocKvw YlkNXexHELXKZf0J9QxnsQEHhR3X0Jry2RR0Y29d0wQ6HKNscXaqQIm1PCc79EVJ1iz6 7EHZhl1kykClWrUgYMZi/qd2nPUzn83e+zi8N4EHmQPohhAvMMNOTtjgKAv12Cb2fFZi ie+0IGvOki2raPhlqy8E+u97P+sLcEa5lj8tIUr12+8Gb+z4azJP9d4qxiSiMuEM7vaG P0JQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1785812388; x=1786417188; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=wQo8OcjOTMXh9X3kaJrhqxoi/2bzY3rrnHALBkkL6gk=; b=jNF6xxieb7nqbRM2F3qjWAXX0S+MhElHVfz0XuzDPIc5hHlPCHr4zXlE55zuthTHif ShGw5CwHEYoWNNnOK4Qto7aOq8zVpNa2bc5OUOf6syBUSDs8R4Igl9w4bEWK8e+ToRly HKqbtfc2Mu82GsFs/o5YE8lZ1irMI5ncZBVDIK+qrF3pUCFfCu/Kq2kmdo6L3qrLQ+TJ XCkuKlQkGotjsx/lTfm1fqs2E0xGEQRAqmOztBMfd0ZiSB0fkAAF/IM5u04h2PYDgYkr DKY3S/s1lumHs6rqzPOJ1e6Oj0wnBFlvJ+iG4xKSUF4I8IGnLgR2czbpB3bo4R6/nOdG cdbA== X-Forwarded-Encrypted: i=1; AHgh+RpULfvSTy2rTQpIhoF9uTPg5cZN5fk6Lzg9SDGRqTy455+JAj9+wZU1ndfJsUJ2vl5TycAEu/wI4enpVGM=@vger.kernel.org X-Gm-Message-State: AOJu0YzzJfukNXuR9YfXwCxf0FxOkmIoN8X/jjYBklmN4NTkFrlIY45N rj3NncvadEKfgJkaIJir6K7h47CVdrZxl7NUSBPu/t3UO/KPJrrS53wt X-Gm-Gg: AR+sD11eQy4q8Fiyh0nd2pAz/gpCvYLZlRNKh+VMohnOIZJdg1YxQjWDoL+Kfk/E0L3 xR6wL+u3Qhcofv9Qizyfqb39covjyBui1l4ApAuMaZqFD0a3SQ/yzL4aMkdTsePt1SB6VieG2nq 2DdKJKgn5E9VJq4FHocZRxEClTpKOpbAHsevqgBCkYqzTE7yZhEQ5kCRU3vOlX0JruQmQ5qRJdl K3atF15apyQ4yz+AWv2OBdk8ApQgX0ydS+6MwhhRkI46TzSP2V3zEXUtCWE9UNiryDKookUZy4T hOtfiTZoThCxy7PUf8f1xGVlUy2TgkdFgqU/e+Mth4o0IW0yR5dF/EjySmoojcx9dzrnP9/aMng cW6nRUTjoekB2qVK9b+/fNY0i9gFzo0B9eunmS8lv8TFF2LbDFWDDh6DXTUbKikJPaYYIptvWC1 7stQ37o/QHo9vzll+Hb2SxUFF8wSzGAdXTJ68d/3Rh0RszghgFGU0IjQmsam+Fln8GgA== X-Received: by 2002:a17:90b:54c3:b0:38e:659b:f366 with SMTP id 98e67ed59e1d1-38fbc0b4324mr10179461a91.0.1785812387519; Mon, 03 Aug 2026 19:59:47 -0700 (PDT) Received: from fedora ([2804:1b3:a8c3:8ee5:1c39:64d9:e257:73dc]) by smtp.gmail.com with ESMTPSA id a92af1059eb24-13fab2530c0sm35974758c88.8.2026.08.03.19.59.44 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 03 Aug 2026 19:59:47 -0700 (PDT) From: Marcelo Mendes Spessoto Junior To: netdev@vger.kernel.org Cc: davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, horms@kernel.org, shuah@kernel.org, linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org, Marcelo Mendes Spessoto Junior Subject: [PATCH net-next v2 4/4] selftests: net: adopt harness for flow label mgr Date: Mon, 3 Aug 2026 23:59:10 -0300 Message-ID: <20260804025910.50145-5-marcelomspessoto@gmail.com> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260804025910.50145-1-marcelomspessoto@gmail.com> References: <20260804025910.50145-1-marcelomspessoto@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The kselftest_harness.h file contains modern helpers to build tests for kselftest. Dropping current test helpers for ipv6_flowlabel_mgr to use harness helps tests to be more legible and conform to the structure of the latest tests. It also enforces TAP standard. Another change made to the structure of ipv6_flowlabel_mgr test file was the removal of parse_opts. The supported opts were already unused: the binary is listed in TEST_GEN_FILES, and is driven solely by ipv6_flowlabel.sh via "./in_netns.sh ./ipv6_flowlabel_mgr", which never passed -l or -v. Dropping the -l gate means the two checks it previously guarded (each with a 13-second sleep, ~26 seconds total) are now unconditionally enabled on every run instead of never running at all. The TH_LOG and code comments cover the information obtainable from (-v). Signed-off-by: Marcelo Mendes Spessoto Junior --- .../selftests/net/ipv6_flowlabel_mgr.c | 521 ++++++++++-------- 1 file changed, 299 insertions(+), 222 deletions(-) diff --git a/tools/testing/selftests/net/ipv6_flowlabel_mgr.c b/tools/testi= ng/selftests/net/ipv6_flowlabel_mgr.c index af87eec799c8..482921f7ee11 100644 --- a/tools/testing/selftests/net/ipv6_flowlabel_mgr.c +++ b/tools/testing/selftests/net/ipv6_flowlabel_mgr.c @@ -20,6 +20,7 @@ #include #include #include +#include "kselftest_harness.h" =20 /* uapi/glibc weirdness may leave this undefined */ #ifndef IPV6_FLOWLABEL_MGR @@ -33,35 +34,6 @@ #define FL_MIN_LINGER 6 #define FL_MAX_LINGER 150 =20 -#define explain(x) \ - do { if (cfg_verbose) fprintf(stderr, " " x "\n"); } while (0) - -#define __expect(x) \ - do { \ - if (!(x)) \ - fprintf(stderr, "[OK] " #x "\n"); \ - else \ - error(1, 0, "[ERR] " #x " (line %d)", __LINE__); \ - } while (0) - -#define expect_pass(x) __expect(x) -#define expect_fail(x) __expect(!(x)) - -#define expect_fail_errno(x, e) \ - do { \ - int __exp =3D (e); \ - int __ret =3D (x); \ - int __err =3D errno; \ - if (__ret && __err =3D=3D __exp) \ - fprintf(stderr, "[OK] " #x "\n"); \ - else \ - error(1, 0, "[ERR] " #x " (line %d): expected errno %d, got %d", \ - __LINE__, __exp, __err); \ - } while (0) - -static bool cfg_long_running; -static bool cfg_verbose; - static int flowlabel_get(int fd, uint32_t label, uint8_t share, uint16_t f= lags) { struct in6_flowlabel_req req =3D { @@ -159,230 +131,335 @@ static void tcp_connect(int listener, uint32_t flow= label, int *client, int *acce *accepted =3D afd; } =20 -static bool flowlabel_consistency_enabled(void) +TEST(cannot_get_non_existent_label) { - char buf[2] =3D {}; - int fd; + int fd, err; =20 - fd =3D open("/proc/sys/net/ipv6/flowlabel_consistency", O_RDONLY); - if (fd =3D=3D -1) - return true; + fd =3D socket(PF_INET6, SOCK_DGRAM, 0); + ASSERT_GE(fd, 0) TH_LOG("socket failed"); =20 - if (read(fd, buf, sizeof(buf) - 1) < 0) - buf[0] =3D '1'; - close(fd); + err =3D flowlabel_get(fd, 9, IPV6_FL_S_ANY, 0); + ASSERT_TRUE(err) TH_LOG("expected get of a non-existent label to fail"); + ASSERT_EQ(ENOENT, errno) TH_LOG("expected ENOENT, got %d", errno); =20 - return buf[0] !=3D '0'; + ASSERT_EQ(0, close(fd)); +} + +TEST(cannot_put_non_existent_label) +{ + int fd, err; + + fd =3D socket(PF_INET6, SOCK_DGRAM, 0); + ASSERT_GE(fd, 0) TH_LOG("socket failed"); + + err =3D flowlabel_put(fd, 10); + ASSERT_TRUE(err) TH_LOG("expected put of a non-existent label to fail"); + ASSERT_EQ(ESRCH, errno) TH_LOG("expected ESRCH, got %d", errno); + + ASSERT_EQ(0, close(fd)); +} + +TEST(cannot_create_label_greater_than_20_bits) +{ + int fd, err; + + fd =3D socket(PF_INET6, SOCK_DGRAM, 0); + ASSERT_GE(fd, 0) TH_LOG("socket failed"); + + err =3D flowlabel_get(fd, 0x1FFFFF, IPV6_FL_S_ANY, IPV6_FL_F_CREATE); + ASSERT_TRUE(err) TH_LOG("expected label > 20 bits to be rejected"); + ASSERT_EQ(EINVAL, errno) TH_LOG("expected EINVAL, got %d", errno); + + ASSERT_EQ(0, close(fd)); +} + +TEST(can_create_and_get_and_put_labels) +{ + int fd, err; + + fd =3D socket(PF_INET6, SOCK_DGRAM, 0); + ASSERT_GE(fd, 0) TH_LOG("socket failed"); + + err =3D flowlabel_get(fd, 1, IPV6_FL_S_ANY, IPV6_FL_F_CREATE); + ASSERT_TRUE(!err) TH_LOG("failed to create label (FL_F_CREATE)"); + + err =3D flowlabel_get(fd, 1, IPV6_FL_S_ANY, 0); + ASSERT_TRUE(!err) TH_LOG("failed to get the label without FL_F_CREATE"); + + err =3D flowlabel_get(fd, 1, IPV6_FL_S_ANY, IPV6_FL_F_CREATE); + ASSERT_TRUE(!err) TH_LOG("failed to get it again with create flag set, to= o"); + + err =3D flowlabel_get(fd, 1, IPV6_FL_S_ANY, IPV6_FL_F_CREATE | IPV6_FL_F_= EXCL); + ASSERT_TRUE(err) TH_LOG("expected FL_F_EXCL to reject an already-existing= label"); + ASSERT_EQ(EEXIST, errno) TH_LOG("expected EEXIST, got %d", errno); + + err =3D flowlabel_put(fd, 1); + ASSERT_TRUE(!err) TH_LOG("failed to put first reference"); + err =3D flowlabel_put(fd, 1); + ASSERT_TRUE(!err) TH_LOG("failed to put second reference"); + err =3D flowlabel_put(fd, 1); + ASSERT_TRUE(!err) TH_LOG("failed to put third reference"); + err =3D flowlabel_put(fd, 1); + ASSERT_TRUE(err) TH_LOG("expected fourth put to fail, no references left"= ); + ASSERT_EQ(ESRCH, errno) TH_LOG("expected ESRCH, got %d", errno); + + ASSERT_EQ(0, close(fd)); +} + +TEST(exclusive_label_share) +{ + int fd, err; + + fd =3D socket(PF_INET6, SOCK_DGRAM, 0); + ASSERT_GE(fd, 0) TH_LOG("socket failed"); + + err =3D flowlabel_get(fd, 2, IPV6_FL_S_EXCL, IPV6_FL_F_CREATE); + ASSERT_TRUE(!err) TH_LOG("failed to create a new exclusive label (FL_S_EX= CL)"); + + err =3D flowlabel_get(fd, 2, IPV6_FL_S_ANY, IPV6_FL_F_CREATE); + ASSERT_TRUE(err) TH_LOG("expected reuse in non-exclusive mode to fail"); + ASSERT_EQ(EPERM, errno) TH_LOG("expected EPERM, got %d", errno); + + err =3D flowlabel_get(fd, 2, IPV6_FL_S_EXCL, IPV6_FL_F_CREATE); + ASSERT_TRUE(err) TH_LOG("expected reuse in exclusive mode to fail too"); + ASSERT_EQ(EPERM, errno) TH_LOG("expected EPERM, got %d", errno); + + err =3D flowlabel_put(fd, 2); + ASSERT_TRUE(!err) TH_LOG("failed to put the exclusive label"); + + err =3D flowlabel_get(fd, 2, IPV6_FL_S_ANY, IPV6_FL_F_CREATE); + ASSERT_TRUE(err) TH_LOG("expected reuse to fail, due to linger"); + ASSERT_EQ(EPERM, errno) TH_LOG("expected EPERM, got %d", errno); + + sleep(FL_MIN_LINGER * 2 + 1); + + err =3D flowlabel_get(fd, 2, IPV6_FL_S_ANY, IPV6_FL_F_CREATE); + ASSERT_TRUE(!err) TH_LOG("expected reuse to succeed after linger"); + + ASSERT_EQ(0, close(fd)); } =20 -static void run_tests(int fd) +TEST(user_private_label_share) { - int wstatus; + int fd, err, wstatus; pid_t pid; =20 - explain("cannot get non-existent label"); - expect_fail(flowlabel_get(fd, 1, IPV6_FL_S_ANY, 0)); - - explain("cannot put non-existent label"); - expect_fail(flowlabel_put(fd, 1)); - - explain("cannot create label greater than 20 bits"); - expect_fail(flowlabel_get(fd, 0x1FFFFF, IPV6_FL_S_ANY, - IPV6_FL_F_CREATE)); - - explain("create a new label (FL_F_CREATE)"); - expect_pass(flowlabel_get(fd, 1, IPV6_FL_S_ANY, IPV6_FL_F_CREATE)); - explain("can get the label (without FL_F_CREATE)"); - expect_pass(flowlabel_get(fd, 1, IPV6_FL_S_ANY, 0)); - explain("can get it again with create flag set, too"); - expect_pass(flowlabel_get(fd, 1, IPV6_FL_S_ANY, IPV6_FL_F_CREATE)); - explain("cannot get it again with the exclusive (FL_FL_EXCL) flag"); - expect_fail(flowlabel_get(fd, 1, IPV6_FL_S_ANY, - IPV6_FL_F_CREATE | IPV6_FL_F_EXCL)); - explain("can now put exactly three references"); - expect_pass(flowlabel_put(fd, 1)); - expect_pass(flowlabel_put(fd, 1)); - expect_pass(flowlabel_put(fd, 1)); - expect_fail(flowlabel_put(fd, 1)); - - explain("create a new exclusive label (FL_S_EXCL)"); - expect_pass(flowlabel_get(fd, 2, IPV6_FL_S_EXCL, IPV6_FL_F_CREATE)); - explain("cannot get it again in non-exclusive mode"); - expect_fail(flowlabel_get(fd, 2, IPV6_FL_S_ANY, IPV6_FL_F_CREATE)); - explain("cannot get it again in exclusive mode either"); - expect_fail(flowlabel_get(fd, 2, IPV6_FL_S_EXCL, IPV6_FL_F_CREATE)); - expect_pass(flowlabel_put(fd, 2)); - - if (cfg_long_running) { - explain("cannot reuse the label, due to linger"); - expect_fail(flowlabel_get(fd, 2, IPV6_FL_S_ANY, - IPV6_FL_F_CREATE)); - explain("after sleep, can reuse"); - sleep(FL_MIN_LINGER * 2 + 1); - expect_pass(flowlabel_get(fd, 2, IPV6_FL_S_ANY, - IPV6_FL_F_CREATE)); - } + fd =3D socket(PF_INET6, SOCK_DGRAM, 0); + ASSERT_GE(fd, 0) TH_LOG("socket failed"); + + err =3D flowlabel_get(fd, 3, IPV6_FL_S_USER, IPV6_FL_F_CREATE); + ASSERT_TRUE(!err) TH_LOG("failed to create a new user-private label (FL_S= _USER)"); + + err =3D flowlabel_get(fd, 3, IPV6_FL_S_ANY, 0); + ASSERT_TRUE(err) TH_LOG("expected get in non-exclusive mode to fail"); + ASSERT_EQ(EPERM, errno) TH_LOG("expected EPERM, got %d", errno); + + err =3D flowlabel_get(fd, 3, IPV6_FL_S_EXCL, 0); + ASSERT_TRUE(err) TH_LOG("expected get in exclusive mode to fail"); + ASSERT_EQ(EPERM, errno) TH_LOG("expected EPERM, got %d", errno); + + err =3D flowlabel_get(fd, 3, IPV6_FL_S_USER, 0); + ASSERT_TRUE(!err) TH_LOG("failed to get it again in user mode"); =20 - explain("create a new user-private label (FL_S_USER)"); - expect_pass(flowlabel_get(fd, 3, IPV6_FL_S_USER, IPV6_FL_F_CREATE)); - explain("cannot get it again in non-exclusive mode"); - expect_fail(flowlabel_get(fd, 3, IPV6_FL_S_ANY, 0)); - explain("cannot get it again in exclusive mode"); - expect_fail(flowlabel_get(fd, 3, IPV6_FL_S_EXCL, 0)); - explain("can get it again in user mode"); - expect_pass(flowlabel_get(fd, 3, IPV6_FL_S_USER, 0)); - explain("child process can get it too, but not after setuid(nobody)"); pid =3D fork(); - if (pid =3D=3D -1) - error(1, errno, "fork"); + ASSERT_NE(-1, pid) TH_LOG("fork failed"); if (!pid) { - expect_pass(flowlabel_get(fd, 3, IPV6_FL_S_USER, 0)); - if (setuid(USHRT_MAX)) + err =3D flowlabel_get(fd, 3, IPV6_FL_S_USER, 0); + ASSERT_TRUE(!err) TH_LOG("child failed to get the user-private label"); + + if (setuid(USHRT_MAX)) { fprintf(stderr, "[INFO] skip setuid child test\n"); - else - expect_fail(flowlabel_get(fd, 3, IPV6_FL_S_USER, 0)); + exit(0); + } + + err =3D flowlabel_get(fd, 3, IPV6_FL_S_USER, 0); + ASSERT_TRUE(err) TH_LOG("child unexpectedly got the label after setuid(n= obody)"); + ASSERT_EQ(EPERM, errno) TH_LOG("expected EPERM, got %d", errno); exit(0); } - if (wait(&wstatus) =3D=3D -1) - error(1, errno, "wait"); - if (!WIFEXITED(wstatus) || WEXITSTATUS(wstatus) !=3D 0) - error(1, errno, "wait: unexpected child result"); - - explain("create a new process-private label (FL_S_PROCESS)"); - expect_pass(flowlabel_get(fd, 4, IPV6_FL_S_PROCESS, IPV6_FL_F_CREATE)); - explain("can get it again"); - expect_pass(flowlabel_get(fd, 4, IPV6_FL_S_PROCESS, 0)); - explain("child process cannot can get it"); + ASSERT_EQ(pid, wait(&wstatus)) TH_LOG("wait failed"); + ASSERT_TRUE(WIFEXITED(wstatus)) TH_LOG("child did not exit normally"); + ASSERT_EQ(0, WEXITSTATUS(wstatus)) TH_LOG("child reported unexpected resu= lt"); + + ASSERT_EQ(0, close(fd)); +} + +TEST(process_private_label_share) +{ + int fd, err, wstatus; + pid_t pid; + + fd =3D socket(PF_INET6, SOCK_DGRAM, 0); + ASSERT_GE(fd, 0) TH_LOG("socket failed"); + + err =3D flowlabel_get(fd, 4, IPV6_FL_S_PROCESS, IPV6_FL_F_CREATE); + ASSERT_TRUE(!err) TH_LOG("failed to create a new process-private label (F= L_S_PROCESS)"); + + err =3D flowlabel_get(fd, 4, IPV6_FL_S_PROCESS, 0); + ASSERT_TRUE(!err) TH_LOG("failed to get it again"); + pid =3D fork(); - if (pid =3D=3D -1) - error(1, errno, "fork"); + ASSERT_NE(-1, pid) TH_LOG("fork failed"); if (!pid) { - expect_fail(flowlabel_get(fd, 4, IPV6_FL_S_PROCESS, 0)); + err =3D flowlabel_get(fd, 4, IPV6_FL_S_PROCESS, 0); + ASSERT_TRUE(err) TH_LOG("child unexpectedly got the process-private labe= l"); + ASSERT_EQ(EPERM, errno) TH_LOG("expected EPERM, got %d", errno); exit(0); } - if (wait(&wstatus) =3D=3D -1) - error(1, errno, "wait"); - if (!WIFEXITED(wstatus) || WEXITSTATUS(wstatus) !=3D 0) - error(1, errno, "wait: unexpected child result"); - - explain("It is not possible to renew a label that does not exist"); - expect_fail_errno(flowlabel_renew(fd, 5, 2 * (FL_MIN_LINGER * 2 + 1)), ES= RCH); - - explain("Create a label for basic renew validation"); - expect_pass(flowlabel_get(fd, 5, IPV6_FL_S_EXCL, IPV6_FL_F_CREATE)); - explain("Check if renew does not return errors for existing and valid lab= el"); - expect_pass(flowlabel_renew(fd, 5, 2 * (FL_MIN_LINGER * 2 + 1))); - - if (cfg_long_running) { - explain("create a new label with FL_MIN_LINGER linger time"); - expect_pass(flowlabel_get(fd, 6, IPV6_FL_S_EXCL, IPV6_FL_F_CREATE)); - explain("renew the label to increase its linger time and put it"); - expect_pass(flowlabel_renew(fd, 6, 2 * (FL_MIN_LINGER * 2 + 1))); - expect_pass(flowlabel_put(fd, 6)); - sleep(FL_MIN_LINGER * 2 + 1); - explain("The label cannot be created because the new linger time is not = over yet"); - expect_fail_errno(flowlabel_get(fd, 6, IPV6_FL_S_ANY, IPV6_FL_F_CREATE),= EPERM); - } + ASSERT_EQ(pid, wait(&wstatus)) TH_LOG("wait failed"); + ASSERT_TRUE(WIFEXITED(wstatus)) TH_LOG("child did not exit normally"); + ASSERT_EQ(0, WEXITSTATUS(wstatus)) TH_LOG("child reported unexpected resu= lt"); =20 - { - struct in6_flowlabel_req freq =3D { - .flr_action =3D IPV6_FL_A_GET, - .flr_flags =3D IPV6_FL_F_REMOTE, - }; - socklen_t freq_len =3D sizeof(freq); - int remote_listener =3D tcp_listen(); - int remote_cfd, remote_afd; - - explain("Prepare TCP SYN for REMOTE flag validation"); - tcp_connect(remote_listener, 7, &remote_cfd, &remote_afd); - - explain("Query for label sent by client with IPV6_FL_F_REMOTE"); - expect_pass(getsockopt(remote_afd, SOL_IPV6, IPV6_FLOWLABEL_MGR, &freq, = &freq_len)); - if (ntohl(freq.flr_label) !=3D 7) - error(1, 0, "unexpected remote flowlabel %u", ntohl(freq.flr_label)); - - close(remote_afd); - close(remote_cfd); - close(remote_listener); - } - - if (flowlabel_consistency_enabled()) { - fprintf(stderr, - "[INFO] skip REFLECT flag validation (net.ipv6.flowlabel_consistency mu= st be 0)\n"); - } else { - struct in6_flowlabel_req reflect_query =3D { - .flr_action =3D IPV6_FL_A_GET, - }; - struct in6_flowlabel_req reflect_off =3D { - .flr_action =3D IPV6_FL_A_PUT, - .flr_flags =3D IPV6_FL_F_REFLECT, - }; - struct in6_flowlabel_req reflect_on =3D { - .flr_action =3D IPV6_FL_A_GET, - .flr_flags =3D IPV6_FL_F_REFLECT, - }; - socklen_t reflect_query_len =3D sizeof(reflect_query); - int reflect_listener =3D tcp_listen(); - int reflect_cfd, reflect_afd; - - explain("Enable REFLECT on the listener before the client connects"); - expect_pass(setsockopt(reflect_listener, SOL_IPV6, IPV6_FLOWLABEL_MGR, - &reflect_on, sizeof(reflect_on))); - - tcp_connect(reflect_listener, 8, &reflect_cfd, &reflect_afd); - - explain("Query the accepted socket's outgoing label, should be reflected= "); - expect_pass(getsockopt(reflect_afd, SOL_IPV6, IPV6_FLOWLABEL_MGR, - &reflect_query, &reflect_query_len)); - if (ntohl(reflect_query.flr_label) !=3D 8) - error(1, 0, "unexpected reflected flowlabel %u", - ntohl(reflect_query.flr_label)); - - explain("PUT+REFLECT disables reflection on the accepted socket"); - expect_pass(setsockopt(reflect_afd, SOL_IPV6, IPV6_FLOWLABEL_MGR, - &reflect_off, sizeof(reflect_off))); - explain("cannot disable reflection twice"); - expect_fail(setsockopt(reflect_afd, SOL_IPV6, IPV6_FLOWLABEL_MGR, - &reflect_off, sizeof(reflect_off))); - - close(reflect_afd); - close(reflect_cfd); - close(reflect_listener); - } + ASSERT_EQ(0, close(fd)); } =20 -static void parse_opts(int argc, char **argv) +TEST(cannot_renew_non_existent_label) { - int c; - - while ((c =3D getopt(argc, argv, "lv")) !=3D -1) { - switch (c) { - case 'l': - cfg_long_running =3D true; - break; - case 'v': - cfg_verbose =3D true; - break; - default: - error(1, 0, "%s: parse error", argv[0]); - } - } + int fd, err; + + fd =3D socket(PF_INET6, SOCK_DGRAM, 0); + ASSERT_GE(fd, 0) TH_LOG("socket failed"); + + err =3D flowlabel_renew(fd, 5, 2 * (FL_MIN_LINGER * 2 + 1)); + ASSERT_TRUE(err) TH_LOG("expected renew of a non-existent label to fail"); + ASSERT_EQ(ESRCH, errno) TH_LOG("expected ESRCH, got %d", errno); + + ASSERT_EQ(0, close(fd)); } =20 -int main(int argc, char **argv) +TEST(can_renew_existing_label) { - int fd; + int fd, err; + + fd =3D socket(PF_INET6, SOCK_DGRAM, 0); + ASSERT_GE(fd, 0) TH_LOG("socket failed"); + + err =3D flowlabel_get(fd, 5, IPV6_FL_S_EXCL, IPV6_FL_F_CREATE); + ASSERT_TRUE(!err) TH_LOG("failed to create a new label for renew validati= on"); =20 - parse_opts(argc, argv); + err =3D flowlabel_renew(fd, 5, 2 * (FL_MIN_LINGER * 2 + 1)); + ASSERT_TRUE(!err) TH_LOG("failed to renew an existing valid label"); + + err =3D flowlabel_put(fd, 5); + ASSERT_TRUE(!err) TH_LOG("failed to put the label"); + + ASSERT_EQ(0, close(fd)); +} + +TEST(renew_label_linger) +{ + /* RENEW must extend a label's linger period: putting a renewed + * label and waiting out its original linger time must not be + * enough to allow the label to be recreated. + */ + int fd, err; =20 fd =3D socket(PF_INET6, SOCK_DGRAM, 0); + ASSERT_GE(fd, 0) TH_LOG("socket failed"); + + err =3D flowlabel_get(fd, 6, IPV6_FL_S_EXCL, IPV6_FL_F_CREATE); + ASSERT_TRUE(!err) TH_LOG("failed to create a new label with FL_MIN_LINGER= linger time"); + + err =3D flowlabel_renew(fd, 6, 2 * (FL_MIN_LINGER * 2 + 1)); + ASSERT_TRUE(!err) TH_LOG("failed to renew the label to increase its linge= r time"); + + err =3D flowlabel_put(fd, 6); + ASSERT_TRUE(!err) TH_LOG("failed to put the label"); + + sleep(FL_MIN_LINGER * 2 + 1); + + err =3D flowlabel_get(fd, 6, IPV6_FL_S_ANY, IPV6_FL_F_CREATE); + ASSERT_TRUE(err) TH_LOG("expected reuse to fail, new linger time not over= yet"); + ASSERT_EQ(EPERM, errno) TH_LOG("expected EPERM, got %d", errno); + + ASSERT_EQ(0, close(fd)); +} + +TEST(remote_flag) +{ + /* The REMOTE flag, used for getsockopt, is expected to retrieve the + * label from the latest received header. + */ + struct in6_flowlabel_req freq =3D { + .flr_action =3D IPV6_FL_A_GET, + .flr_flags =3D IPV6_FL_F_REMOTE, + }; + socklen_t freq_len =3D sizeof(freq); + int listener, cfd, afd, err; + + listener =3D tcp_listen(); + tcp_connect(listener, 7, &cfd, &afd); + + err =3D getsockopt(afd, SOL_IPV6, IPV6_FLOWLABEL_MGR, &freq, &freq_len); + ASSERT_TRUE(!err) TH_LOG("getsockopt with IPV6_FL_F_REMOTE failed"); + ASSERT_EQ(7, ntohl(freq.flr_label)) TH_LOG("unexpected remote flow label"= ); + + ASSERT_EQ(0, close(afd)); + ASSERT_EQ(0, close(cfd)); + ASSERT_EQ(0, close(listener)); +} + +static bool flowlabel_consistency_enabled(void) +{ + char buf[2] =3D {}; + int fd; + + fd =3D open("/proc/sys/net/ipv6/flowlabel_consistency", O_RDONLY); if (fd =3D=3D -1) - error(1, errno, "socket"); + return true; + + if (read(fd, buf, sizeof(buf) - 1) < 0) + buf[0] =3D '1'; + close(fd); =20 - run_tests(fd); + return buf[0] !=3D '0'; +} + +TEST(reflect_flag) +{ + /* The REFLECT flag acts as a trigger to the REPFLOW bit. When REPFLOW + * is triggered for a socket, it adopts the label received from the + * connected socket. + */ + struct in6_flowlabel_req reflect_on =3D { + .flr_action =3D IPV6_FL_A_GET, + .flr_flags =3D IPV6_FL_F_REFLECT, + }; + struct in6_flowlabel_req reflect_query =3D { + .flr_action =3D IPV6_FL_A_GET, + }; + struct in6_flowlabel_req reflect_off =3D { + .flr_action =3D IPV6_FL_A_PUT, + .flr_flags =3D IPV6_FL_F_REFLECT, + }; + socklen_t reflect_query_len =3D sizeof(reflect_query); + int listener, cfd, afd, err; + + if (flowlabel_consistency_enabled()) + SKIP(return, + "net.ipv6.flowlabel_consistency must be 0 (run via ipv6_flowlabel.s= h)"); + + listener =3D tcp_listen(); + err =3D setsockopt(listener, SOL_IPV6, IPV6_FLOWLABEL_MGR, &reflect_on, s= izeof(reflect_on)); + ASSERT_TRUE(!err) TH_LOG("failed to enable REFLECT on the listener"); =20 - if (close(fd)) - error(1, errno, "close"); + tcp_connect(listener, 8, &cfd, &afd); =20 - return 0; + err =3D getsockopt(afd, SOL_IPV6, IPV6_FLOWLABEL_MGR, &reflect_query, &re= flect_query_len); + ASSERT_TRUE(!err) TH_LOG("failed to query the accepted socket's outgoing = label"); + ASSERT_EQ(8, ntohl(reflect_query.flr_label)) + TH_LOG("accepted socket did not reflect client's label"); + + err =3D setsockopt(afd, SOL_IPV6, IPV6_FLOWLABEL_MGR, &reflect_off, sizeo= f(reflect_off)); + ASSERT_TRUE(!err) TH_LOG("failed to disable REFLECT on the accepted socke= t"); + + err =3D setsockopt(afd, SOL_IPV6, IPV6_FLOWLABEL_MGR, &reflect_off, sizeo= f(reflect_off)); + ASSERT_TRUE(err) TH_LOG("expected disabling REFLECT twice to fail"); + ASSERT_EQ(ESRCH, errno) TH_LOG("expected ESRCH, got %d", errno); + + ASSERT_EQ(0, close(afd)); + ASSERT_EQ(0, close(cfd)); + ASSERT_EQ(0, close(listener)); } + +TEST_HARNESS_MAIN --=20 2.55.0