From nobody Tue Apr 7 13:46:29 2026 Received: from mail-pf1-f173.google.com (mail-pf1-f173.google.com [209.85.210.173]) (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 DAAAC3CE4BB for ; Fri, 3 Apr 2026 15:01:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.173 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775228500; cv=none; b=ho4F4yO36EebtgvBtlK6zZBAvpjiro+J9b+ifv8egaiMJlNAo/f1y4cJzTfsuGF6seJvWK8x7Gy5pOrX6C4QKWyA+nXFWLoWmdINppmbWfc7eZmi23hUi7fAZb5Du6jvf4r33jUe29XxIrPmdnT8GZHIK5+SV7JbAL8/nASpn4U= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775228500; c=relaxed/simple; bh=4LeT1cJ+asqbP8EaYg7MOJK/G//aZNU+VpLMKTbgT3Y=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=sldJZuV7Giu0zptTqEhSh7WSKChKf4XZgY0SQASF0iK/8Xbig8XBPi6Tt+7Y15d55rjrFzlWKlNL8V7ExTloRjt9I1vhHOY9E+tyFDRkeO/R3lAPo8Ukw9tYw1rGsuC6e0O62AwMsRhUTEQJcaTTxA0nA7DGd1CUkVldEr2mvqM= 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=BubxWlLq; arc=none smtp.client-ip=209.85.210.173 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="BubxWlLq" Received: by mail-pf1-f173.google.com with SMTP id d2e1a72fcca58-82418b0178cso971495b3a.1 for ; Fri, 03 Apr 2026 08:01:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1775228497; x=1775833297; 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=VjltsPsyl0fA4bSmkbZpBvZZ8hQ+nYEUswOg9yantuE=; b=BubxWlLqoybWJMSpG7OovPTbP0xjrORg17brdwAOkgNeqsS5e0p1cHawflsxUxcVAt DjLWridLfo0gsKU8en6jwyQwp/glaju5aP5OkvcGXuR7zPKIfB4nXl9RyQu9ZguRpxp2 9OWKtoia+2s4SSahWnqodulNSr/MrC30n1VRUtdQY96d3fB9TEhmHZ84Dtir+W9Hzp1I qFdpC1ssU6uRCPNHF3H6nSobta4lY18u8x8Jevp5CLeWKpKu6meg3Z+85Lrn8i/xS09e 1gfsmm9sYW6pWSApq+t7Es7EqkPJE8AdR8BJBOGJIuORSNshSzGXmsbZ0GSD+3DQ4+Ca geAw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1775228497; x=1775833297; 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; bh=VjltsPsyl0fA4bSmkbZpBvZZ8hQ+nYEUswOg9yantuE=; b=YAqomEajTuSxie5ZTgSOLxeOlveWgFgjIAYuDAtLe31lTaDcogHbf5TP8C+KalH/v4 TZ6KIGpIHqDEB8gin0b9vdjOYWMh6GQRsoIKNUztWitJX28F4RW8GNrMFR6KZzrAFT6P uoO1pD4qGhfQ5fmzcMhx/Pq55TIR/LnjVgZm8DgVuBp4eAOvfBQiaCl/M7g/hX4YHg7v 1J1hc7DJuqCvN9KuxptRy/MOPGIvdiLWeQPgmbxuqZQnaB8jhMekoYf07dfG7+mYUhH1 t2fYxBAPGHEv2aIco0LzUzz3zJYU1R7x+WBQtqB8F6EpKYfCiPTJAS2bXx4h/z3kXaMd s0jg== X-Forwarded-Encrypted: i=1; AJvYcCWs1gFKWu5Hh9rphtpteWhPds/N2rEiHJ7qtxCq7aowEfvIbk9uOWpEZrd1VxDyYd6ADq+TZv/hJ8ZvQVY=@vger.kernel.org X-Gm-Message-State: AOJu0YxBPz100nUFK7HnySRjEKO7FNnd5fZAjt9EFgSlnWIbqwDHiX/3 xQUk20a2o245z9eTDdCWBGf3zu6WMpVzsHkjTuX7JDEJ2BpSJ+1wzimR X-Gm-Gg: AeBDiet3h/LWCnX6ObRiQiN4Y8bLIeB8KpH5ez0Axk5YLi3kOF5ALWN8lPWC9eIHlon KL6/cHv0ytetdYoJiKC9sMmCgWVQAzx3w2wWAwstLuQi0FabzB7Q3zT1ITAFQejNyxDht9Jk3mE 4pIzaex14g5lwGNBkEJHEdb1gMN0a9ZRTqRi5F6Js/pR1iJ7jQr3AXjRLBmXfZKVtu9LGpLWuaH fwUYUyuwFpy54jJft5di/d7eG8wh+I5FbcEXzm3rgKJyHT1uWjXq4890jAw1ofAFmKmB7K4/hNo rSDqkgKdI2jkbOuiDddZlQwnwjzB50Iqz1H/aj7b1/s7NGN6zVPxKNPGsaFaaDQm40TU1VzPzwN aKjdj0dxWpR0XaAsSi2fHDezX2roZ/xhxNSCnYUpR8n/rZ1o2TG1HGTI7xwOHm8HQGRxOnZOtsz +d1HOoHyjZvjcOKRvJkVpExHL0IUYEW1XUEKzGIN05 X-Received: by 2002:a05:6a00:2d10:b0:82c:66f2:1226 with SMTP id d2e1a72fcca58-82d0db84a62mr3307715b3a.38.1775228496765; Fri, 03 Apr 2026 08:01:36 -0700 (PDT) Received: from DESKTOP-82PPU4A.localdomain ([202.8.116.192]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-82cf9ca79basm7789483b3a.58.2026.04.03.08.01.29 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 03 Apr 2026 08:01:34 -0700 (PDT) From: Ujjal Roy To: "David S . Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Nikolay Aleksandrov , Ido Schimmel , David Ahern , Shuah Khan , Andy Roulin , Yong Wang , Petr Machata Cc: Ujjal Roy , bridge@lists.linux.dev, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org Subject: [PATCH net-next v3 5/5] selftests: net: bridge: add tests for MRC and QQIC validation Date: Fri, 3 Apr 2026 15:00:50 +0000 Message-ID: <20260403150050.1235-6-royujjal@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260403150050.1235-1-royujjal@gmail.com> References: <20260403150050.1235-1-royujjal@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" Update bridge selftests that configure Max Resp Time (MRT) and Querier Query Interval (QQI) parameters and validate the resulting Query packet fields for Max Resp Code (MRC) and Querier Query Interval Code (QQIC). These tests cover the IGMPv3 and MLDv2 for below cases: * MRC and QQIC in linear range. * MRC and QQIC in non-linear range. TEST: Vlan multicast snooping enable [ OK ] TEST: Vlan mcast_query_interval global option default value [ OK ] Vlan 10 mcast_query_interval (QQIC) test cases: TEST: Number of tagged IGMPv2 general query [ OK ] TEST: IGMPv3 QQIC linear value 60 [ OK ] TEST: MLDv2 QQIC linear value 60 [ OK ] TEST: IGMPv3 QQIC non linear value 160 [ OK ] TEST: MLDv2 QQIC non linear value 160 [ OK ] TEST: Vlan mcast_query_response_interval global option default value [ OK= ] Vlan 10 mcast_query_response_interval (MRC) test cases: TEST: IGMPv3 MRC linear value 60 [ OK ] TEST: IGMPv3 MRC non linear value 160 [ OK ] TEST: MLDv2 MRC linear value 30000 [ OK ] TEST: MLDv2 MRC non linear value 60000 [ OK ] Signed-off-by: Ujjal Roy --- .../selftests/net/forwarding/.gitignore | 2 + .../testing/selftests/net/forwarding/Makefile | 10 ++ .../net/forwarding/bridge_vlan_mcast.sh | 157 +++++++++++++++++- .../selftests/net/forwarding/mc_decode.c | 73 ++++++++ .../selftests/net/forwarding/mc_encode.c | 78 +++++++++ 5 files changed, 315 insertions(+), 5 deletions(-) create mode 100644 tools/testing/selftests/net/forwarding/mc_decode.c create mode 100644 tools/testing/selftests/net/forwarding/mc_encode.c diff --git a/tools/testing/selftests/net/forwarding/.gitignore b/tools/test= ing/selftests/net/forwarding/.gitignore index 418ff96c52ef..aa0c7f1afb4b 100644 --- a/tools/testing/selftests/net/forwarding/.gitignore +++ b/tools/testing/selftests/net/forwarding/.gitignore @@ -1,3 +1,5 @@ # SPDX-License-Identifier: GPL-2.0-only forwarding.config ipmr +mc_encode +mc_decode diff --git a/tools/testing/selftests/net/forwarding/Makefile b/tools/testin= g/selftests/net/forwarding/Makefile index bbaf4d937dd8..a26da846632d 100644 --- a/tools/testing/selftests/net/forwarding/Makefile +++ b/tools/testing/selftests/net/forwarding/Makefile @@ -1,5 +1,15 @@ # SPDX-License-Identifier: GPL-2.0+ OR MIT =20 +top_srcdir =3D ../../../../.. + +CFLAGS +=3D -Wall -Wl,--no-as-needed -O2 -g -I$(top_srcdir)/usr/include $(= KHDR_INCLUDES) +CFLAGS +=3D -I$(top_srcdir)/tools/include + +TEST_GEN_FILES :=3D \ + mc_encode \ + mc_decode \ +# end of TEST_GEN_FILES + TEST_PROGS :=3D \ bridge_activity_notify.sh \ bridge_fdb_learning_limit.sh \ diff --git a/tools/testing/selftests/net/forwarding/bridge_vlan_mcast.sh b/= tools/testing/selftests/net/forwarding/bridge_vlan_mcast.sh index 72dfbeaf56b9..89598712f869 100755 --- a/tools/testing/selftests/net/forwarding/bridge_vlan_mcast.sh +++ b/tools/testing/selftests/net/forwarding/bridge_vlan_mcast.sh @@ -5,6 +5,7 @@ ALL_TESTS=3D"vlmc_control_test vlmc_querier_test vlmc_igmp_= mld_version_test \ vlmc_last_member_test vlmc_startup_query_test vlmc_membership_test \ vlmc_querier_intvl_test vlmc_query_intvl_test vlmc_query_response_intv= l_test \ vlmc_router_port_test vlmc_filtering_test" +TEST_NAME=3D"" NUM_NETIFS=3D4 CHECK_TC=3D"yes" TEST_GROUP=3D"239.10.10.10" @@ -96,6 +97,17 @@ cleanup() vrf_cleanup } =20 +check_binary() +{ + local cmd=3D$1; shift + local args=3D$@ + + if [[ ! -x "$(command -v "$cmd")" ]]; then + log_test_skip "$args $cmd not found" + return $EXIT_STATUS + fi +} + vlmc_v2join_test() { local expect=3D$1 @@ -162,14 +174,27 @@ vlmc_query_cnt_setup() { local type=3D$1 local dev=3D$2 + local intvl_match=3D"$3" =20 if [[ $type =3D=3D "igmp" ]]; then + # This matches: IP Protocol 2 (IGMP) tc filter add dev $dev egress pref 10 prot 802.1Q \ flower vlan_id 10 vlan_ethtype ipv4 dst_ip 224.0.0.1 ip_proto 2 \ + action continue + # AND Type 0x11 (Query) at offset 24 after IP + # IP (20 byte IP + 4 bytes Option) + tc filter add dev $dev egress pref 20 prot 802.1Q u32 \ + match u8 0x11 0xff at 24 $intvl_match \ action pass else + # This matches: ICMPv6 tc filter add dev $dev egress pref 10 prot 802.1Q \ flower vlan_id 10 vlan_ethtype ipv6 dst_ip ff02::1 ip_proto icmpv6 \ + action continue + # AND Type 0x82 (Query) at offset 48 after IPv6 + # IPv6 (40 bytes IPv6 + 2 bytes next HDR + 4 bytes Option + 2 byte pad) + tc filter add dev $dev egress pref 20 prot 802.1Q u32 \ + match u8 0x82 0xff at 48 $intvl_match \ action pass fi =20 @@ -181,9 +206,46 @@ vlmc_query_cnt_cleanup() local dev=3D$1 =20 ip link set dev br0 type bridge mcast_stats_enabled 0 + tc filter del dev $dev egress pref 20 tc filter del dev $dev egress pref 10 } =20 +vlmc_query_get_intvl_match() +{ + local type=3D$1 + local version=3D$2 + local interval=3D$3 + local encode=3D"" + + if [ "$interval" =3D "" ]; then + return + fi + + if [ "$TEST_NAME" =3D "vlmc_query_intvl_test" ]; then + # QQIC is 8-bit floating point encoding for IGMPv3 and MLDv2 + encode=3D"$(./mc_encode 8 $interval)" + if [ "${type}v${version}" =3D "igmpv3" ]; then + # IP 20 bytes + 4 bytes Option + IGMPv3[9] + echo "match u8 $encode 0xff at 33" + elif [ "${type}v${version}" =3D "mldv2" ]; then + # IPv6 40 + 2 next HDR + 4 Option + 2 pad + MLDv2[25] + echo "match u8 $encode 0xff at 73" + fi + elif [ "$TEST_NAME" =3D "vlmc_query_response_intvl_test" ]; then + if [ "${type}v${version}" =3D "igmpv3" ]; then + # MRC is 8-bit floating point encoding for MLDv2 + encode=3D"$(./mc_encode 8 $interval)" + # IP 20 bytes + 4 bytes Option + IGMPv3[1] + echo "match u8 $encode 0xff at 25" + elif [ "${type}v${version}" =3D "mldv2" ]; then + # MRC is 16-bit floating point encoding for MLDv2 + encode=3D"$(./mc_encode 16 $interval)" + # IPv6 40 + 2 next HDR + 4 Option + 2 pad + MLDv2[4] + echo "match u16 $encode 0xffff at 52" + fi + fi +} + vlmc_check_query() { local type=3D$1 @@ -191,9 +253,12 @@ vlmc_check_query() local dev=3D$3 local expect=3D$4 local time=3D$5 + local interval=3D$6 + local intvl_match=3D"" local ret=3D0 =20 - vlmc_query_cnt_setup $type $dev + intvl_match=3D"$(vlmc_query_get_intvl_match $type $version $interval)" + vlmc_query_cnt_setup $type $dev "$intvl_match" =20 local pre_tx_xstats=3D$(vlmc_query_cnt_xstats $type $version $dev) bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_querier 1 @@ -201,7 +266,7 @@ vlmc_check_query() if [[ $ret -eq 0 ]]; then sleep $time =20 - local tcstats=3D$(tc_rule_stats_get $dev 10 egress) + local tcstats=3D$(tc_rule_stats_get $dev 20 egress) local post_tx_xstats=3D$(vlmc_query_cnt_xstats $type $version $dev) =20 if [[ $tcstats !=3D $expect || \ @@ -428,6 +493,10 @@ vlmc_querier_intvl_test() =20 vlmc_query_intvl_test() { + TEST_NAME=3D"vlmc_query_intvl_test" + + check_binary "./mc_encode" "$TEST_NAME: verify" || return 1 + RET=3D0 local goutput=3D`bridge -j vlan global show` echo -n $goutput | @@ -440,6 +509,7 @@ vlmc_query_intvl_test() check_err $? "Wrong default mcast_query_interval global vlan option value" log_test "Vlan mcast_query_interval global option default value" =20 + echo "Vlan 10 mcast_query_interval (QQIC) test cases:" RET=3D0 bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_startup_quer= y_count 0 bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_query_interv= al 200 @@ -447,14 +517,52 @@ vlmc_query_intvl_test() # 1 is sent immediately, then 2 more in the next 5 seconds vlmc_check_query igmp 2 $swp1 3 5 check_err $? "Wrong number of tagged IGMPv2 general queries sent" - log_test "Vlan 10 mcast_query_interval option changed to 200" + log_test "Number of tagged IGMPv2 general query" + + RET=3D0 + bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_igmp_version= 3 + check_err $? "Could not set mcast_igmp_version in vlan 10" + bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_mld_version 2 + check_err $? "Could not set mcast_mld_version in vlan 10" + + RET=3D0 + bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_query_interv= al 6000 + check_err $? "Could not set mcast_query_interval in vlan 10" + # 1 is sent immediately, IGMPv3 QQIC should match with linear value 60s + vlmc_check_query igmp 3 $swp1 1 1 60 + check_err $? "Wrong QQIC in sent tagged IGMPv3 general queries" + log_test "IGMPv3 QQIC linear value 60" + RET=3D0 + # 1 is sent immediately, MLDv2 QQIC should match with linear value 60s + vlmc_check_query mld 2 $swp1 1 1 60 + check_err $? "Wrong QQIC in sent tagged MLDv2 general queries" + log_test "MLDv2 QQIC linear value 60" =20 + RET=3D0 + bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_query_interv= al 16000 + check_err $? "Could not set mcast_query_interval in vlan 10" + # 1 is sent immediately, IGMPv3 QQIC should match with non linear value 1= 60s + vlmc_check_query igmp 3 $swp1 1 1 160 + check_err $? "Wrong QQIC in sent tagged IGMPv3 general queries" + log_test "IGMPv3 QQIC non linear value 160" + RET=3D0 + # 1 is sent immediately, MLDv2 QQIC should match with non linear value 16= 0s + vlmc_check_query mld 2 $swp1 1 1 160 + check_err $? "Wrong QQIC in sent tagged MLDv2 general queries" + log_test "MLDv2 QQIC non linear value 160" + + bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_igmp_version= 2 + bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_mld_version 1 bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_startup_quer= y_count 2 bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_query_interv= al 12500 } =20 vlmc_query_response_intvl_test() { + TEST_NAME=3D"vlmc_query_response_intvl_test" + + check_binary "./mc_encode" "$TEST_NAME: verify" || return 1 + RET=3D0 local goutput=3D`bridge -j vlan global show` echo -n $goutput | @@ -468,10 +576,49 @@ vlmc_query_response_intvl_test() log_test "Vlan mcast_query_response_interval global option default value" =20 RET=3D0 - bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_query_respon= se_interval 200 + bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_startup_quer= y_count 0 + bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_igmp_version= 3 + check_err $? "Could not set mcast_igmp_version in vlan 10" + + echo "Vlan 10 mcast_query_response_interval (MRC) test cases:" + RET=3D0 + bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_query_respon= se_interval 600 + check_err $? "Could not set mcast_query_response_interval in vlan 10" + # 1 is sent immediately, IGMPv3 MRC should match with linear value 60 uni= ts of 1/10s + vlmc_check_query igmp 3 $swp1 1 1 60 + check_err $? "Wrong MRC in sent tagged IGMPv3 general queries" + log_test "IGMPv3 MRC linear value 60" + + RET=3D0 + bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_query_respon= se_interval 1600 + check_err $? "Could not set mcast_query_response_interval in vlan 10" + # 1 is sent immediately, IGMPv3 MRC should match with non linear value 16= 0 unit of 1/10s + vlmc_check_query igmp 3 $swp1 1 1 160 + check_err $? "Wrong MRC in sent tagged IGMPv3 general queries" + log_test "IGMPv3 MRC non linear value 160" + + bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_mld_version 2 + check_err $? "Could not set mcast_mld_version in vlan 10" + + RET=3D0 + bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_query_respon= se_interval 3000 + check_err $? "Could not set mcast_query_response_interval in vlan 10" + # 1 is sent immediately, MLDv2 MRC should match with linear value 30000(m= s) + vlmc_check_query mld 2 $swp1 1 1 30000 + check_err $? "Wrong MRC in sent tagged MLDv2 general queries" + log_test "MLDv2 MRC linear value 30000" + + RET=3D0 + bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_query_respon= se_interval 6000 check_err $? "Could not set mcast_query_response_interval in vlan 10" - log_test "Vlan 10 mcast_query_response_interval option changed to 200" + # 1 is sent immediately, MLDv2 MRC should match with non linear value 600= 00(ms) + vlmc_check_query mld 2 $swp1 1 1 60000 + check_err $? "Wrong MRC in sent tagged MLDv2 general queries" + log_test "MLDv2 MRC non linear value 60000" =20 + bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_igmp_version= 2 + bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_mld_version 1 + bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_startup_quer= y_count 2 bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_query_respon= se_interval 1000 } =20 diff --git a/tools/testing/selftests/net/forwarding/mc_decode.c b/tools/tes= ting/selftests/net/forwarding/mc_decode.c new file mode 100644 index 000000000000..2c5e784226e4 --- /dev/null +++ b/tools/testing/selftests/net/forwarding/mc_decode.c @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include + +/* 8-bit floating-point exponential field decode */ +#define FP_8BIT_EXP(value) (((value) >> 4) & 0x07) +#define FP_8BIT_MAN(value) ((value) & 0x0f) + +/* 16-bit floating-point exponential field decode */ +#define FP_16BIT_EXP(value) (((value) >> 12) & 0x0007) +#define FP_16BIT_MAN(value) ((value) & 0x0fff) + +/* 8-bit floating-point exponential field linear threshold */ +#define FP_8BIT_MIN_THRESHOLD 128 +/* 8-bit non linear max representable (mant =3D 0xF, exp =3D 7) -> 31744 */ +#define FP_8BIT_MAX_THRESHOLD 31744 + +/* 16-bit floating-point exponential field linear threshold */ +#define FP_16BIT_MIN_THRESHOLD 32768UL +/* 16-bit non linear max representable (mant =3D 0xFFF, exp =3D 7) -> 8387= 584 */ +#define FP_16BIT_MAX_THRESHOLD 8387584 + +/* This decodes 8-bit floating-point exponential values */ +static inline uint32_t decode_8bit_field(const u8 code) +{ + if (code < FP_8BIT_MIN_THRESHOLD) { + return code; + } else { + uint32_t mc_man, mc_exp; + + mc_exp =3D FP_8BIT_EXP(code); + mc_man =3D FP_8BIT_MAN(code); + return (mc_man | 0x10) << (mc_exp + 3); + } +} + +/* This decodes 16-bit floating-point exponential values */ +static inline uint32_t decode_16bit_field(const uint16_t code) +{ + if (code < FP_16BIT_MIN_THRESHOLD) { + return code; + } else { + uint32_t mc_man, mc_exp; + + mc_exp =3D FP_16BIT_EXP(code); + mc_man =3D FP_16BIT_MAN(code); + + return (mc_man | 0x1000) << (mc_exp + 3); + } +} + +int main(int argc, char *argv[]) +{ + uint32_t bits =3D 8, code =3D 0, decode =3D 0; + + if (argc !=3D 3) + return 1; + + if (bits !=3D 8 && bits !=3D 16) + return 1; + + bits =3D atoi(argv[1]); + code =3D atoi(argv[2]); + + if (bits =3D=3D 8) + decode =3D decode_8bit_field(code); + else + decode =3D decode_16bit_field(code); + printf("%u\n", decode); + + return 0; +} diff --git a/tools/testing/selftests/net/forwarding/mc_encode.c b/tools/tes= ting/selftests/net/forwarding/mc_encode.c new file mode 100644 index 000000000000..24d9bd9299cc --- /dev/null +++ b/tools/testing/selftests/net/forwarding/mc_encode.c @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include + +/* 8-bit floating-point exponential field linear threshold */ +#define FP_8BIT_MIN_THRESHOLD 128 +/* 8-bit non linear max representable (mant =3D 0xF, exp =3D 7) -> 31744 */ +#define FP_8BIT_MAX_THRESHOLD 31744 + +/* 16-bit floating-point exponential field linear threshold */ +#define FP_16BIT_MIN_THRESHOLD 32768UL +/* 16-bit non linear max representable (mant =3D 0xFFF, exp =3D 7) -> 8387= 584 */ +#define FP_16BIT_MAX_THRESHOLD 8387584 + +/* This encodes value to 8-bit floating-point exponential format */ +static inline uint8_t encode_8bit_field(unsigned int value) +{ + uint8_t mc_exp, mc_man; + + /* Value < 128 is literal */ + if (value < FP_8BIT_MIN_THRESHOLD) + return value; + + /* Saturate at max representable (mant =3D 0xF, exp =3D 7) -> 31744 */ + if (value >=3D FP_8BIT_MAX_THRESHOLD) + return 0xFF; + + mc_exp =3D fls(value) - 8; + mc_man =3D (value >> (mc_exp + 3)) & 0x0F; + + return 0x80 | (mc_exp << 4) | mc_man; +} + +/* This encodes value to 16-bit floating-point exponential format */ +static inline uint16_t encode_16bit_field(unsigned int value) +{ + uint16_t mc_man, mc_exp; + + /* Value < 32768 is literal */ + if (value < FP_16BIT_MIN_THRESHOLD) + return value; + + /* Saturate at max representable (mant =3D 0xFFF, exp =3D 7) -> 8387584 */ + if (value >=3D FP_16BIT_MAX_THRESHOLD) + return 0xFFFF; + + mc_exp =3D fls(value) - 16; + mc_man =3D (value >> (mc_exp + 3)) & 0x0FFF; + + return 0x8000 | (mc_exp << 12) | mc_man; +} + +int main(int argc, char *argv[]) +{ + unsigned int bits =3D 8, value =3D 0; + uint8_t encoded8 =3D 0; + uint16_t encoded16 =3D 0; + + if (argc !=3D 3) + return 1; + + bits =3D atoi(argv[1]); + value =3D atoi(argv[2]); + + if (bits !=3D 8 && bits !=3D 16) + return 1; + + if (bits =3D=3D 8) { + encoded8 =3D encode_8bit_field(value); + printf("%hhu\n", encoded8); + } else { + encoded16 =3D encode_16bit_field(value); + printf("%hu\n", encoded16); + } + + return 0; +} --=20 2.43.0