From nobody Fri Apr 3 12:26:37 2026 Received: from mail-pj1-f47.google.com (mail-pj1-f47.google.com [209.85.216.47]) (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 2105B26E165 for ; Mon, 30 Mar 2026 19:16:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.47 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774898217; cv=none; b=fkULNS1pLCWT2K5+C7WON3htFylcrbJ0dhPab7R31pneCcQVY2q6bv2bnpRGCn+z73ecf6xuQJrVg44IR45C2sPzJreo5uEzRkvrdLSUfHXtUAtFN6xyvddNatX9c9Hkvc3z9M9tivlurojTDvkii2Gjxls+1VX06kANI/5Eg8U= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774898217; c=relaxed/simple; bh=/s+EgbT4cwqyAVP8otaVBOlL/dCCRmkYjYM+V8pat60=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=C3lvVTQFChXgD7QiTDKk/N6u9vzvvhrGKOw6uIFiQH0U5QbCVZ1h0kn7R2NwzRGv3Sa0u54Hs+2zL4Ys0sM5A31SFhXWFWIU4VSUHHaJw/28l1nDsG7chfobppFK+KMVNtxkUezlW8Val+ZFRxcuQOJZvuHonC4eKZwUu3m72Do= 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=W4z5YJbU; arc=none smtp.client-ip=209.85.216.47 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="W4z5YJbU" Received: by mail-pj1-f47.google.com with SMTP id 98e67ed59e1d1-35691a231a7so2947000a91.3 for ; Mon, 30 Mar 2026 12:16:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1774898215; x=1775503015; 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=5WISAf0QjUXrCjlDt5u3fdpEKEmBPI+ZNLLd/DIJAm8=; b=W4z5YJbUeGIvrIt7mUCfKAMbBSjHW8Jzu9d89cyue6et/DAqLmNIB1nP3MMctHUpwc 3ivEr19Oq5qbgFomy+6YipxT9PE4GV2A3y3DXlONhpNptd/u+A7LnxMntTP0u8N2F2FD kOmAAdeO2HzQwhaXC08VcqVOkLHtkWxvYstUOtVGLFr/eMTKtT91qjw1uoASLQHf/7CA aO4chdyV+Ar+wXdoezpgj1axZBNrIRnSjdbn9KM8jpXF/0fKlOrm2Ixstz7EyeXSxKkX 1tSlLITWRKt6bHnlYSEZOLJ8q6zSGrNTv3EZ99ju1yrzXxhswwZqFHgN+SjjMtpWK957 Dblw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1774898215; x=1775503015; 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=5WISAf0QjUXrCjlDt5u3fdpEKEmBPI+ZNLLd/DIJAm8=; b=bgQ/aK0LJuZlXEK0qw5vGSECtZvb2J7ULQlYogHuy1D7YmTcOkEhzoyMLUraNlQdNA R+j8N0D0/cou6xeq9I4aiaRGZ+aVje434moTTxjPiugpdkHXI0DBR0onyPOn0DC56N/p +5BPIVC+RWl5Egu46yNCr3yNHIrPbXHw935oA+9vN5KR2srEZHrpZ731LigWUlqQRAlm Sgntv6eDmvz06gSiYoDAdAkhpS7LEfGvgqq92ZQ/HiKFLM2dExki2ad6QebRrxV1MINW nwzoThMiNXBqgGHvey1G1WA9tSahK/vz/TFufa8NPYeSKomjX03nT1TSzd6njNDoLt77 r8qA== X-Forwarded-Encrypted: i=1; AJvYcCUrYaKT2KOAvrgj/Es3ikdCqunJQH1C35GehLb2tQoHYs4skMeKj+UdN6vj13ziMq9cj5/mkfJ58vqIwkE=@vger.kernel.org X-Gm-Message-State: AOJu0YxzV3KWRaGzrOPhPYSKVMOGA/xRlBghv10ZZr7d35iXlM+Wtv6w GBkNSfVtsNV1sd2IfoiG+BfP2Ui9q2psTc6ifEr2sMcujx4REndHRXlR X-Gm-Gg: ATEYQzwW7qHCuSLYUp1OEl3KrAJbMkkec9gTY8ZipZPvJHNVkcmbFA9LePWu0+wChL2 JmReEFJQQtnO49dcwVolFTmTU32M+BKM+vHs/S4jk4LDQS2v/SqT5hS498QwF1Ag6xq5tQbHBWo Ma6Cz5Y62NcBuA7/wJgE17GGq6AIICuEWJIXsH46vBEOQq0YY9t/xfzD0m8XN2xkMdtqKrzo6gS 3w9wrTQBE6YIzDR04ckMztXQENw1ncOduj1U+fYW/6li8TQpUYKGOCkmcQPDosvQZrld9U8utkm ZlNC7ry9zVrBTxvxHJ0tuBQOCy/0Cg1PRKRK854WiNzlLukb8EXNj8MzW71MngIZeSBWFwnjk0t YWxt2qVzZnJfQ+GNe7H3LGVjCLn2aOEnkoqmyD/nCmDYyX4shCUExHNl4zpkIbIpdCnT/BEfKUP EiQUUqirOvlThovDTXeH8bXUdXThz15OeMZiSIIKyb X-Received: by 2002:a17:90a:e7c1:b0:35d:a276:a87d with SMTP id 98e67ed59e1d1-35da276afa0mr6030327a91.27.1774898215457; Mon, 30 Mar 2026 12:16:55 -0700 (PDT) Received: from DESKTOP-82PPU4A.localdomain ([202.8.116.192]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-35d950d9b12sm9627178a91.17.2026.03.30.12.16.48 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 30 Mar 2026 12:16:54 -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 v2 4/5] ipv6: mld: encode multicast exponential fields Date: Mon, 30 Mar 2026 19:16:10 +0000 Message-ID: <20260330191611.16929-5-royujjal@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260330191611.16929-1-royujjal@gmail.com> References: <20260330191611.16929-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" In MLD, QQIC and MRC fields are not currently encoded when generating query packets. Since the receiver of the query interprets these fields using the MLDv2 floating-point decoding logic, any raw interval value that exceeds the linear threshold is currently parsed incorrectly as an exponential value, leading to an incorrect interval calculation. Encode and assign the corresponding protocol fields during query generation. Introduce the logic to dynamically calculate the exponent and mantissa using bit-scan (fls). This ensures QQIC (8-bit) and MRC (16-bit) fields are properly encoded when transmitting query packets with intervals that exceed their respective linear thresholds (128 for QQI; 32768 for MRD). RFC3810: If QQIC >=3D 128, the QQIC field represents a floating-point value as follows: 0 1 2 3 4 5 6 7 +-+-+-+-+-+-+-+-+ |1| exp | mant | +-+-+-+-+-+-+-+-+ RFC3810: If Maximum Response Code >=3D 32768, the Maximum Response Code field represents a floating-point value as follows: 0 1 2 3 4 5 6 7 8 9 A B C D E F +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |1| exp | mant | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Signed-off-by: Ujjal Roy --- include/net/mld.h | 117 ++++++++++++++++++++++++++++++++++++++ net/bridge/br_multicast.c | 4 +- 2 files changed, 119 insertions(+), 2 deletions(-) diff --git a/include/net/mld.h b/include/net/mld.h index 5e093f9c75d9..1ee7d3f68a33 100644 --- a/include/net/mld.h +++ b/include/net/mld.h @@ -90,12 +90,129 @@ struct mld2_query { #define MLDV2_QQIC_MAN(value) ((value) & 0x0f) =20 #define MLD_QQIC_MIN_THRESHOLD 128 +/* Max representable (mant =3D 0xF, exp =3D 7) -> 31744 */ +#define MLD_QQIC_MAX_THRESHOLD 31744 #define MLD_MRC_MIN_THRESHOLD 32768UL +/* Max representable (mant =3D 0xFFF, exp =3D 7) -> 8387584 */ +#define MLD_MRC_MAX_THRESHOLD 8387584 #define MLDV1_MRD_MAX_COMPAT (MLD_MRC_MIN_THRESHOLD - 1) =20 #define MLD_MAX_QUEUE 8 #define MLD_MAX_SKBS 32 =20 +/* V2 exponential field encoding */ + +/* + * Calculate Maximum Response Code from Maximum Response Delay + * + * MLDv2 Maximum Response Code 16-bit encoding (RFC3810). + * + * RFC3810 defines only the decoding formula: + * Maximum Response Delay =3D (mant | 0x1000) << (exp + 3) + * + * but does NOT define the encoding procedure. To derive exponent: + * + * For the 16-bit MRC, the "hidden bit" (0x1000) is left shifted by 12 + * to sit above the 12-bit mantissa. The RFC then shifts this entire + * block left by (exp + 3) to reconstruct the value. + * So, 'hidden bit' is the MSB which is shifted by (12 + exp + 3). + * + * - Total left shift of the hidden bit =3D 12 + (exp + 3) =3D exp + 15. + * - This is the MSB at the 0-based bit position: (exp + 15). + * - Since fls() is 1-based, fls(value) - 1 =3D exp + 15. + * + * Therefore: + * exp =3D fls(value) - 16 + * mant =3D (value >> (exp + 3)) & 0x0FFF + * + * Final encoding formula: + * 0x8000 | (exp << 12) | mant + * + * Example (value =3D 1311744): + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0| 13117= 44 + * | ^-^--------mant---------^ ^...(exp+3)...^| exp= =3D5 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * Encoded: + * 0x8000 | (5 << 12) | 0x404 =3D 0xD404 + */ +static inline u16 mldv2_mrc(unsigned long mrd) +{ + u16 mc_man, mc_exp; + + /* RFC3810: MRC < 32768 is literal */ + if (mrd < MLD_MRC_MIN_THRESHOLD) + return (u16)mrd; + + /* Saturate at max representable (mant =3D 0xFFF, exp =3D 7) -> 8387584 */ + if (mrd >=3D MLD_MRC_MAX_THRESHOLD) + return 0xFFFF; + + mc_exp =3D (u16)(fls(mrd) - 16); + mc_man =3D (u16)((mrd >> (mc_exp + 3)) & 0x0FFF); + + return (0x8000 | (mc_exp << 12) | mc_man); +} + +/* + * Calculate Querier's Query Interval Code from Query Interval + * + * MLDv2 QQIC 8-bit floating-point encoding (RFC3810). + * + * RFC3810 defines only the decoding formula: + * QQI =3D (mant | 0x10) << (exp + 3) + * + * but does NOT define the encoding procedure. To derive exponent: + * + * For any value of mantissa and exponent, the decoding formula + * indicates that the "hidden bit" (0x10) is shifted 4 bits left + * to sit above the 4-bit mantissa. The RFC again shifts this + * entire block left by (exp + 3) to reconstruct the value. + * So, 'hidden bit' is the MSB which is shifted by (4 + exp + 3). + * + * Total left shift of the 'hidden bit' =3D 4 + (exp + 3) =3D exp + 7. + * This is the MSB at the 0-based bit position: (exp + 7). + * Since fls() is 1-based, fls(value) - 1 =3D exp + 7. + * + * Therefore: + * exp =3D fls(value) - 8 + * mant =3D (value >> (exp + 3)) & 0x0F + * + * Final encoding formula: + * 0x80 | (exp << 4) | mant + * + * Example (value =3D 3200): + * 0 1 + * 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |0 0 0 0 1 1 0 0 1 0 0 0 0 0 0 0| (value =3D 3200) + * | ^-^-mant^ ^..(exp+3)..^| exp =3D 4, mant =3D 9 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * Encoded: + * 0x80 | (4 << 4) | 9 =3D 0xC9 + */ +static inline u8 mldv2_qqic(unsigned long value) +{ + u8 mc_man, mc_exp; + + /* RFC3810: QQIC < 128 is literal */ + if (value < MLD_QQIC_MIN_THRESHOLD) + return (u8)value; + + /* Saturate at max representable (mant =3D 0xF, exp =3D 7) -> 31744 */ + if (value >=3D MLD_QQIC_MAX_THRESHOLD) + return 0xFF; + + mc_exp =3D (u8)(fls(value) - 8); + mc_man =3D (u8)((value >> (mc_exp + 3)) & 0x0F); + + return (0x80 | (mc_exp << 4) | mc_man); +} + /* V2 exponential field decoding */ =20 /* Calculate Maximum Response Delay from Maximum Response Code diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 27010744d7ae..c2d144f6a86e 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -1181,7 +1181,7 @@ static struct sk_buff *br_ip6_multicast_alloc_query(s= truct net_bridge_mcast *brm break; case 2: mld2q =3D (struct mld2_query *)icmp6_hdr(skb); - mld2q->mld2q_mrc =3D htons((u16)jiffies_to_msecs(interval)); + mld2q->mld2q_mrc =3D htons((u16)jiffies_to_msecs(mldv2_mrc(interval))); mld2q->mld2q_type =3D ICMPV6_MGM_QUERY; mld2q->mld2q_code =3D 0; mld2q->mld2q_cksum =3D 0; @@ -1190,7 +1190,7 @@ static struct sk_buff *br_ip6_multicast_alloc_query(s= truct net_bridge_mcast *brm mld2q->mld2q_suppress =3D sflag; mld2q->mld2q_qrv =3D 2; mld2q->mld2q_nsrcs =3D htons(llqt_srcs); - mld2q->mld2q_qqic =3D brmctx->multicast_query_interval / HZ; + mld2q->mld2q_qqic =3D mldv2_qqic(brmctx->multicast_query_interval / HZ); mld2q->mld2q_mca =3D *group; csum =3D &mld2q->mld2q_cksum; csum_start =3D (void *)mld2q; --=20 2.43.0