From nobody Tue Apr 7 13:46:29 2026 Received: from mail-pf1-f178.google.com (mail-pf1-f178.google.com [209.85.210.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 CFF003CAE9D for ; Fri, 3 Apr 2026 15:01:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.178 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775228491; cv=none; b=gfPU9myRd0M7wcnlfLq8naZbUV1Fb5QYXOwlS8J764w/Kz8HspvjotJwe/DV4Fz2AND8M/BU517DKtutDXZzRIKl0v1kBdqcRdsnMZCndYZsFddrfGC1NW1iSQmOpPzGi33CC9PErNHekQAOwJ6GJHfE86Zcnp9d0R5aoRzBqcE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775228491; c=relaxed/simple; bh=EKpTwE4ZfpPM1Z81RyM2aK+iglf5OV67iJmGTsG62ls=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=dLFdE57mVBbGi/LXrBo8/x4lNAWn4zwcPRkpPxdfi/8oMYQ8ampaS1yzZs0bvrxZ+DuzhBHKaF2zZmTZFCHjEmKy2s2NPqd+4bDM1YonEXcXLudR+QCADJTLea1W2amtHUoMP1Fws+IgRM9YGZytAo9VzhkTf4kbaaLZAarW25E= 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=VljK/N1H; arc=none smtp.client-ip=209.85.210.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="VljK/N1H" Received: by mail-pf1-f178.google.com with SMTP id d2e1a72fcca58-82ce2e2880cso1448678b3a.0 for ; Fri, 03 Apr 2026 08:01:29 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1775228489; x=1775833289; 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=kA8wWqgtt+a655+1MvtrE0v6BL6IMopBXGlXnFLxq48=; b=VljK/N1HcWQHhTT/EUp+8siMDgazeIjpCh96QGkXbusS7fb407O0fsxbCS0xaIpV1v 9zwu9xR9jQX/5Hj2aOUMygDMEKt6JSqr+IrmqFxMRjD1pUAwUwgW7csA1HbXPx8uoojJ RMrHqD2iZK9thANcjv63/RtzVuC4+Y6kuzCkpSQderI4137PGU86bUtgxR5oHP5qwTEp Af1f+saZZqGDB89qwpkWrxc9Rr+ygF87dCLJAiYFK4DbOjBm+yGqExEZwMDDMuvii3ug g1FPIEctUTSPvUv15AYGQFfeBzkyv7S5RKnKyaML1Gz5A4sc1WS9LFl2/mF2hIc5+/pZ 20ig== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1775228489; x=1775833289; 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=kA8wWqgtt+a655+1MvtrE0v6BL6IMopBXGlXnFLxq48=; b=ZveoG9elevxrMrY8Glk+jMR6+91rCAXOw29It36vhJmMSEamyvVy7ZGJ/OXPRnIv3+ X1CDSRKZsIbvqbOEiEX4MjQ0vDhPpICuGX4y1PQDaWWp730RQKnrIJioxgZLgKV/BNpL lu9y8RynKWakgw9yrdwjxCkMUYiST1PqQ9CziM1K0XsYWL/AFLXx35uMS6Qq7HyY6nUT G3E4oxeuc3CdGcxXYmpRCWqsW0g9kzxtpru0wXrqVholb4iACw/4+rNJv/+gVDZ3XA8g qgXqd4fzlvKu7nbCf6B0dTgGSNEkWf9PEoolgQYUTbC+3lT2Aleu4eSOJ+eExuN+Qehi 2eHA== X-Forwarded-Encrypted: i=1; AJvYcCVUK5ce4mzSBexu2uyh1r71IbX+uARzKEz4E2JQoFOY5bxOhgbn4thnnQAICsMLj5dpbGZNekqUN7FoBD0=@vger.kernel.org X-Gm-Message-State: AOJu0YxZB1KVsmze1y+fd++t9pR7BX8tS4lhoR8KpBnstB8sWwhaAhVq z3k7Vo/5WB+6vCQilqhqrFb88OGzf8GawckI4s816ri02pHotUCNblymN14ATt0kiRg= X-Gm-Gg: AeBDievJ9dA/+/cqAQUeyMf1LErLh2bal7s6Z0SSBe41FWC2hj0OCat06arigLqdurP 00/V4Zqo/V0Y8f4BJmAcbLv6ocrpZu4Dfwu0pD4+cGMZN1ZziwNxHiI71qofzCnKMUxSzzvlhPg vdo2HWHPMusKDxIJNBuAIhkdNHkJa8cOqvC/gVNPvqUKS9pTq3TCJQVvE+Cj3iG0NL+y6u9E0el sUvOsVH/3q8JF8/RU7cCHzsKdAdu6AqqEzG4v0U0t/p9nKcpfxBfz6KOm+FREoM1ixbPnm4KGFj tWaMahMPoBIQP+l01WhfVM9ygMjKQUO99qENTewhSWSmCDpQsPfGQqcFY9KAHco0AxWDV8VTNZ1 5jelqrm8uYxjrRGKNuiApSNi2RWT3+LNJMuhlPo+UxdUbxXkOjNoT3tEwFdMt5rq3eVC3ZvkkqV hUO85S/lgr78UskjsMiy09XPySdy4+m6G7lFpQnpbHoRBOSBygSkQ= X-Received: by 2002:a05:6a00:1d9e:b0:82c:68f6:a18 with SMTP id d2e1a72fcca58-82d0db5b47amr3435171b3a.34.1775228489031; Fri, 03 Apr 2026 08:01:29 -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.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 03 Apr 2026 08:01:28 -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 4/5] ipv6: mld: encode multicast exponential fields Date: Fri, 3 Apr 2026 15:00:49 +0000 Message-ID: <20260403150050.1235-5-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" In MLD, QQIC and MRC fields are not correctly encoded when generating query packets. Since the receiver of the query interprets these fields using the MLDv2 floating-point decoding logic, any value that exceeds the linear threshold is incorrectly parsed 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 | 122 ++++++++++++++++++++++++++++++++++++++ net/bridge/br_multicast.c | 4 +- 2 files changed, 124 insertions(+), 2 deletions(-) diff --git a/include/net/mld.h b/include/net/mld.h index da3299545ebd..147e8c44eb28 100644 --- a/include/net/mld.h +++ b/include/net/mld.h @@ -90,12 +90,134 @@ 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 + * + * MRC represents the 16-bit encoded form of Maximum Response + * Delay (MRD); once decoded, the resulting value is in + * milliseconds. + * + * 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 mrd; + + /* Saturate at max representable (mant =3D 0xFFF, exp =3D 7) -> 8387584 */ + if (mrd >=3D MLD_MRC_MAX_THRESHOLD) + return 0xFFFF; + + mc_exp =3D fls(mrd) - 16; + mc_man =3D (mrd >> (mc_exp + 3)) & 0x0FFF; + + return 0x8000 | (mc_exp << 12) | mc_man; +} + +/* + * Calculate Querier's Query Interval Code from Query Interval + * + * QQIC represents the 8-bit encoded form of Query Interval (QQI); + * once decoded, the resulting value is in seconds. + * + * 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 value; + + /* Saturate at max representable (mant =3D 0xF, exp =3D 7) -> 31744 */ + if (value >=3D MLD_QQIC_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; +} + /* 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..a22e44c4fa48 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)mldv2_mrc(jiffies_to_msecs(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