From nobody Sun Jun 14 07:34:43 2026 Received: from mail-pj1-f54.google.com (mail-pj1-f54.google.com [209.85.216.54]) (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 3462B309EEB for ; Fri, 1 May 2026 17:31:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.54 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777656711; cv=none; b=tCRvHEESOkyu6FsEDAHBoI/v5hUUUQqocxhiJh6l+OYC+V7mhd0OGlPbaQArM+a8SGrN+RODkdZCKLAS2FcOFysIEiZkxW+QEsjM0cYMqNlTn9krmPf+nmM7kikSNCfrn7iAVBEV5K5ac0z+D0AQ0jKgruNbjjvR6XdM6KknLdk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777656711; c=relaxed/simple; bh=OIVGLHkE0+zv8tPvOlRxlxnAchQfUFIaCtRMGLN9J8Q=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=r3NZMr7izAoU1YJFdomq1tfL2IwDHCtXaH/sA+0F1tDHoNXzMh4SMwRenshfYpvn4U2MdF/Tc0ApvfOTH8m6XLn4MJgZBKKQUJ4hJsKRUPniDqBB7omBFKN47RW+Xhf4yadVvX2h0WwiKqMZM0RFmJ5hNQ4F9fzvVVmiCZ/5rgc= 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=h43qFyYc; arc=none smtp.client-ip=209.85.216.54 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="h43qFyYc" Received: by mail-pj1-f54.google.com with SMTP id 98e67ed59e1d1-35e576110adso1570352a91.0 for ; Fri, 01 May 2026 10:31:50 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1777656709; x=1778261509; 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=YWCZJ9utsVn2aH4mDSbQniFeJPJsfUBS8uLBgw2m2To=; b=h43qFyYcKZwo1MSgMOkH/3ISiYG2BTyPOYOgSmNLinPpNpZOOV+Fzc0UMd1bMyA/RW jO53Vd7sQADeyi+JI9runBIN38BhU315ljAFiNtrUkW9DBydqFIoapW5ehLahLttJo/7 cqAr8WioNnP4Nc06CuDzilel7Vpi4ZQVHNV/rXtt7s+d09Bn9JopNwxv+DKECN8KTeZC sxw9cSoozlTNQRqCQTAjNllQnFS+tKxMxcaxs3t80Yq1WdBE+pDzJ9Y9k3Cz5TXQiYVx xpW+v47dEF8a4XS+cXDcEw7SzUb3qnfejkadFNqT1XzL/7ooyiS5v16nwxUs1usdORdE Amag== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1777656709; x=1778261509; 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=YWCZJ9utsVn2aH4mDSbQniFeJPJsfUBS8uLBgw2m2To=; b=PqCjrJ38yONuGUEa5fPSzsmSPeS6STOCaqiAcKUoZV0o1Fr4MG0gm4GXkNDj5hMzgj kEuF1bb3c40G4jMQweGsoSc37NT2okzP0G8NF8J4ZIcA9gVo6/M10XCItfe/v3aXdyg0 3idwLFo8u0o40KB/FjdLz8ViUIy63GMRhwCvA6DCwBhliXovLwQfQiVko7ytUTnfrXCZ z8jVS3yZW/KwgHh61P9b2WJOMJiR1Gvys/OZkDFqY3V87UPTKCKBv2sWRBt/VZUiKROX EL4ANWfwtVkG7gRSVdZpogYQVl6KTyUqWrbeJoXszPAxseZLwL3kltzGzxYEfAhn9fdc 4+XQ== X-Forwarded-Encrypted: i=1; AFNElJ/ZXBP0oHBbHT90erLAHfuNAUP6tLfkESKaOctrliGX3k4TkpFdz/KpjGMIwgSG2l1n2eCvmWFWmnsrFqQ=@vger.kernel.org X-Gm-Message-State: AOJu0YxlR/453/1FVXt5UF9Y56job5ZD5fsWCxRJDEsBedWMiDKIGXPK 5BbDYrWPi6GzjcX53d/F5i8uG7LmxDePKyfWUxcQ/MWHdkZJfX/vymz0 X-Gm-Gg: AeBDiet0z++1yT/1G3aEyCVAj2Tll3xtj+gnsTml65qe1ZQNj7xWv8Nu8GAr87wIIe0 ckNtXqWzcbYULOCr2AAcHAoOVHiRhw0gm+PpnQ+vLKe8xxau6prUk+DEgT1363DuLeAwRpnn422 0xXZftsh8bb1q+yxzP7r9VSj+WObbrbTvaTW4zknnO68B3XmOyKLkSGoHvP1AgkTHIxWzTDStJl 8vnlXxri8Qvzrs0VKD5YpKJmSqyzpEsqBbdXB+E+T5YaUTiQBC2E0m/8isH/tRLvYnHiQqhyD/M vgTMHyZPu0ZaIZETIVYuy0mnCI9lWXMA4mR/p8lBW3ueNHYcAL3l4zUS59tKaT8L0jm6bxKZxZY NIFMhI73aaMuaQWdIKNUU7qrV2zrTNbxTMcrAE3FjFNhv4RMXwIGXD6GVKIWosa8ZMRm87um4Jm j9Ga4WuAZIRRlYmnKJvmHKb+qcX1OHPccj5q/9xs/uDIOyEHsEgw== X-Received: by 2002:a17:90b:498c:b0:35f:b9f1:fded with SMTP id 98e67ed59e1d1-3650c4f44f4mr293791a91.12.1777656709241; Fri, 01 May 2026 10:31:49 -0700 (PDT) Received: from DESKTOP-82PPU4A.localdomain ([202.8.116.84]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-364ebec73aasm2908906a91.2.2026.05.01.10.31.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 May 2026 10:31:48 -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 v5 1/5] ipv4: igmp: get rid of IGMPV3_{QQIC,MRC} and simplify calculation Date: Fri, 1 May 2026 17:31:25 +0000 Message-ID: <20260501173130.3486-2-royujjal@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260501173130.3486-1-royujjal@gmail.com> References: <20260501173130.3486-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" Get rid of the IGMPV3_MRC macro and use the igmpv3_mrt() API to calculate the Max Resp Time from the Maximum Response Code. Similarly, for IGMPV3_QQIC, use the igmpv3_qqi() API to calculate the Querier's Query Interval from the QQIC field. Reviewed-by: Ido Schimmel Signed-off-by: Ujjal Roy Reviewed-by: Nikolay Aleksandrov --- include/linux/igmp.h | 80 +++++++++++++++++++++++++++++++++++---- net/bridge/br_multicast.c | 2 +- net/ipv4/igmp.c | 6 +-- 3 files changed, 76 insertions(+), 12 deletions(-) diff --git a/include/linux/igmp.h b/include/linux/igmp.h index 073b30a9b850..0e095c9f234e 100644 --- a/include/linux/igmp.h +++ b/include/linux/igmp.h @@ -92,15 +92,79 @@ struct ip_mc_list { struct rcu_head rcu; }; =20 +/* RFC3376, relevant sections: + * - 4.1.1. Maximum Response Code + * - 4.1.7. QQIC (Querier's Query Interval Code) + * + * For both MRC and QQIC, values >=3D 128 use the same floating-point + * encoding as follows: + * + * 0 1 2 3 4 5 6 7 + * +-+-+-+-+-+-+-+-+ + * |1| exp | mant | + * +-+-+-+-+-+-+-+-+ + */ +#define IGMPV3_FP_EXP(value) (((value) >> 4) & 0x07) +#define IGMPV3_FP_MAN(value) ((value) & 0x0f) + +/* IGMPv3 floating-point exponential field min threshold */ +#define IGMPV3_EXP_MIN_THRESHOLD 128 + /* V3 exponential field decoding */ -#define IGMPV3_MASK(value, nb) ((nb)>=3D32 ? (value) : ((1<<(nb))-1) & (va= lue)) -#define IGMPV3_EXP(thresh, nbmant, nbexp, value) \ - ((value) < (thresh) ? (value) : \ - ((IGMPV3_MASK(value, nbmant) | (1<<(nbmant))) << \ - (IGMPV3_MASK((value) >> (nbmant), nbexp) + (nbexp)))) - -#define IGMPV3_QQIC(value) IGMPV3_EXP(0x80, 4, 3, value) -#define IGMPV3_MRC(value) IGMPV3_EXP(0x80, 4, 3, value) + +/* IGMPv3 MRC/QQIC 8-bit exponential field decode + * + * RFC3376, 4.1.1 & 4.1.7. defines the decoding formula: + * 0 1 2 3 4 5 6 7 + * +-+-+-+-+-+-+-+-+ + * |1| exp | mant | + * +-+-+-+-+-+-+-+-+ + * Max Resp Time =3D (mant | 0x10) << (exp + 3) + * QQI =3D (mant | 0x10) << (exp + 3) + */ +static inline unsigned long igmpv3_exp_field_decode(const u8 code) +{ + if (code < IGMPV3_EXP_MIN_THRESHOLD) { + return code; + } else { + unsigned long mc_man, mc_exp; + + mc_exp =3D IGMPV3_FP_EXP(code); + mc_man =3D IGMPV3_FP_MAN(code); + + return (mc_man | 0x10) << (mc_exp + 3); + } +} + +/* Calculate Max Resp Time from Maximum Response Code + * + * RFC3376, relevant sections: + * - 4.1.1. Maximum Response Code + * - 8.3. Query Response Interval + * + * After decode, MRC represents the Maximum Response Time (MRT) in + * units of 0.1 seconds (100 ms). + */ +static inline unsigned long igmpv3_mrt(const struct igmpv3_query *ih3) +{ + return igmpv3_exp_field_decode(ih3->code); +} + +/* Calculate Querier's Query Interval from Querier's Query Interval Code + * + * RFC3376, relevant sections: + * - 4.1.7. QQIC (Querier's Query Interval Code) + * - 8.2. Query Interval + * - 8.12. Older Version Querier Present Timeout + * (the [Query Interval] in the last Query received) + * + * After decode, QQIC represents the Querier's Query Interval in units + * of seconds. + */ +static inline unsigned long igmpv3_qqi(const struct igmpv3_query *ih3) +{ + return igmpv3_exp_field_decode(ih3->qqic); +} =20 static inline int ip_mc_may_pull(struct sk_buff *skb, unsigned int len) { diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 881d866d687a..9fec76e887bc 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -3518,7 +3518,7 @@ static void br_ip4_multicast_query(struct net_bridge_= mcast *brmctx, goto out; =20 max_delay =3D ih3->code ? - IGMPV3_MRC(ih3->code) * (HZ / IGMP_TIMER_SCALE) : 1; + igmpv3_mrt(ih3) * (HZ / IGMP_TIMER_SCALE) : 1; } else { goto out; } diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index a674fb44ec25..d7eff36d98c3 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c @@ -991,7 +991,7 @@ static bool igmp_heard_query(struct in_device *in_dev, = struct sk_buff *skb, * different encoding. We use the v3 encoding as more likely * to be intended in a v3 query. */ - max_delay =3D IGMPV3_MRC(ih3->code)*(HZ/IGMP_TIMER_SCALE); + max_delay =3D igmpv3_mrt(ih3) * (HZ / IGMP_TIMER_SCALE); if (!max_delay) max_delay =3D 1; /* can't mod w/ 0 */ } else { /* v3 */ @@ -1006,7 +1006,7 @@ static bool igmp_heard_query(struct in_device *in_dev= , struct sk_buff *skb, ih3 =3D igmpv3_query_hdr(skb); } =20 - max_delay =3D IGMPV3_MRC(ih3->code)*(HZ/IGMP_TIMER_SCALE); + max_delay =3D igmpv3_mrt(ih3) * (HZ / IGMP_TIMER_SCALE); if (!max_delay) max_delay =3D 1; /* can't mod w/ 0 */ WRITE_ONCE(in_dev->mr_maxdelay, max_delay); @@ -1016,7 +1016,7 @@ static bool igmp_heard_query(struct in_device *in_dev= , struct sk_buff *skb, * configured value. */ in_dev->mr_qrv =3D ih3->qrv ?: READ_ONCE(net->ipv4.sysctl_igmp_qrv); - in_dev->mr_qi =3D IGMPV3_QQIC(ih3->qqic)*HZ ?: IGMP_QUERY_INTERVAL; + in_dev->mr_qi =3D igmpv3_qqi(ih3) * HZ ? : IGMP_QUERY_INTERVAL; =20 /* RFC3376, 8.3. Query Response Interval: * The number of seconds represented by the [Query Response --=20 2.43.0 From nobody Sun Jun 14 07:34:43 2026 Received: from mail-pj1-f44.google.com (mail-pj1-f44.google.com [209.85.216.44]) (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 601AD1FD4 for ; Fri, 1 May 2026 17:31:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.44 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777656718; cv=none; b=So4SpsLWReDE9z6trytbjqz3o2zOyfqF4NCTqmQPBOHcdiE2DUyxir3YpbBuyOGyd/DTgw9mN/M6EviTySqAhHogXbO4+ZAHDdvjlQaQHXiPdhl25G9VrmEJ75WKrgahpjMC/1hM+oE7owWUKy0NPv2ux9EWFk1XqUDBQHp7PAk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777656718; c=relaxed/simple; bh=PDn8j0lrnxkTWFi/Ss5XFw7DFZtI8b/CvWn3vrzRAiw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=eWaw3dGLD3ghC3DLzztlXl/jO1/t/U4DVoQswBd4YNXpaBgtzt7uzNiQdWx4SyEaI6CptfwJ05hF3cHC8N6iUKxW8Iun/3kkbZ0PGlIkYe+EmL3BqJmT980CiOifIZSok6pERDFVciKv7hqJlseYxFCIXbIoB2mUSzMVUWrsPek= 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=lSs2Ssgi; arc=none smtp.client-ip=209.85.216.44 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="lSs2Ssgi" Received: by mail-pj1-f44.google.com with SMTP id 98e67ed59e1d1-35d90833cacso1834793a91.2 for ; Fri, 01 May 2026 10:31:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1777656717; x=1778261517; 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=LslMTLSTH+cOBfpp7e2vjMYbfCy9riwOyI9tt0Uj2os=; b=lSs2SsgiY6CRUk4lGbfl4fvv4ydmkW8XFXq+pkbh0NZVYuU6TblA4n1gZbtZmSdXHt TnPJbiLm9vn3TugoMk60MXccE9GbYX3exAxfIQBVnaMazWUSkxkj6GETfjHM95n6PhWA 9sroLoqcvBeFkutTCbE4QfCpKCUCOg/2Y1565NcKnL1Ev05PiOb3MPCK6w+t73QJrsvc uhJw9Akxgsw9etCXCBG5tdSNLKITnHG/asNQudqCNCnri1CMgkAiza7nIyZo7E2Nw0T/ UaJNuSADswhxeZq7fw0UGXxtqmLOTxjILoupzGLVvSZkr2hO0VpX26YPrmbAmWfd2cUX +zZg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1777656717; x=1778261517; 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=LslMTLSTH+cOBfpp7e2vjMYbfCy9riwOyI9tt0Uj2os=; b=gu7vVW/EqOS6M/qAD+s6/VIxdDkp6CAVz0vJVBGjEt8Ik1LnIonRtPRkxh309nnrvX d7bzOlXGdI1KHX7Fo8Nu9kDkcEqJFOdYb3SJo75XmI4Beu7OLVG2tgmZLUuk/PCfvyzj fFITbSP2fU8nmGQy+hhvpyuCDwsbtCdqLTuMwt0v3cCiQIaw8KOeUzcqfvUKS9ijt6fY pKHYigWgeMM043ShicwwktTHvZfMUzwTGjWB34AE3lXlGm0M59MiMf5w+swnjaXUas3N VZJEbaECCJ1bn1Rc2E2P+uaLJ2fwW+FENTV+46rERU3Yeiz1SDSFC+TEAPz5dxXMO83c y56A== X-Forwarded-Encrypted: i=1; AFNElJ9PXNDSGNBfayF6T2m/RVNV0pGMZ1ZqE1qglENQFNOhr7hPEoxEDA5bjfgfZQUYe3Q9di86+gGGBaM+iFo=@vger.kernel.org X-Gm-Message-State: AOJu0Ywbky+Bqm3rpMc3RBxWlJN305DNWIMsLYHSjVDOszUn9uCxxC+3 h/n9YT7NruYWjy0WJuuu15F5dJttakirRJvwExjSteMHSfhVQDTjd7Qq X-Gm-Gg: AeBDievIDSVURLHqsGGRkEPL4/oACiedXS44O+qcHJABWErHXyQ11bYRKOvvJdvVOxR 0F7xkakPupCuASd3+CnJF0qevdf1LKQTq85lJrt1vW2mX15pXXdzpHncUIiiqZ2QC6ssClrCf+X ZBolvLn90pAvuBVudMbLfFCIWrVHTv+MuOMYrKZjgEWmYOf//shJ0UuU+E4LudlJCWJSG0sxNDT t31fCg/v8ZNwQAqvDng7UqteqyDvOv1ha/4RZTdl2c0/oUxB161+SpWXol/qs0p3R1VMdFDmdHi Qx1d11YWx8djFaSx+VlIdljMfhBGMnoJKnnD16gzJAmZWAtrkcp/K2mEe4uy5JHN8M4/jmM3aHp DluXOfSi06QZ5oGDh4PUOclke4MphbycQRnD6yxMj+bFljPQycHJEjYjBflNAccH5P7/H1itKd5 9G0fuKbtddROeKJ7R3LPxFJ5JPb9n55BOfYPKEnuKlTNTKZ3ze5A== X-Received: by 2002:a17:90b:5707:b0:364:a173:2d61 with SMTP id 98e67ed59e1d1-3650cd70c41mr143017a91.11.1777656716795; Fri, 01 May 2026 10:31:56 -0700 (PDT) Received: from DESKTOP-82PPU4A.localdomain ([202.8.116.84]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-364ebec73aasm2908906a91.2.2026.05.01.10.31.49 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 May 2026 10:31:56 -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 v5 2/5] ipv6: mld: rename mldv2_mrc() and add mldv2_qqi() Date: Fri, 1 May 2026 17:31:26 +0000 Message-ID: <20260501173130.3486-3-royujjal@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260501173130.3486-1-royujjal@gmail.com> References: <20260501173130.3486-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" Rename mldv2_mrc() to mldv2_mrd() as it is used to calculate the Maximum Response Delay from the Maximum Response Code. Introduce a new API mldv2_qqi() to define the existing calculation logic of QQI from QQIC. This also organizes the existing mld_update_qi() API. Reviewed-by: Ido Schimmel Signed-off-by: Ujjal Roy Reviewed-by: Nikolay Aleksandrov --- include/net/mld.h | 66 +++++++++++++++++++++++++++++++++------ net/bridge/br_multicast.c | 2 +- net/ipv6/mcast.c | 19 ++--------- 3 files changed, 61 insertions(+), 26 deletions(-) diff --git a/include/net/mld.h b/include/net/mld.h index c07359808493..10e402e0fe08 100644 --- a/include/net/mld.h +++ b/include/net/mld.h @@ -89,29 +89,77 @@ struct mld2_query { #define MLDV2_QQIC_EXP(value) (((value) >> 4) & 0x07) #define MLDV2_QQIC_MAN(value) ((value) & 0x0f) =20 -#define MLD_EXP_MIN_LIMIT 32768UL -#define MLDV1_MRD_MAX_COMPAT (MLD_EXP_MIN_LIMIT - 1) +/* MLDv2 QQIC floating-point exponential field min threshold */ +#define MLD_QQIC_MIN_THRESHOLD 128 +/* MLDv2 MRC floating-point exponential field min threshold */ +#define MLD_MRC_MIN_THRESHOLD 32768UL +#define MLDV1_MRD_MAX_COMPAT (MLD_MRC_MIN_THRESHOLD - 1) =20 #define MLD_MAX_QUEUE 8 #define MLD_MAX_SKBS 32 =20 -static inline unsigned long mldv2_mrc(const struct mld2_query *mlh2) +/* V2 exponential field decoding */ + +/* Calculate Maximum Response Delay from Maximum Response Code + * + * RFC3810, relevant sections: + * - 5.1.3. Maximum Response Code defines the decoding formula: + * 0 1 2 3 4 5 6 7 8 9 A B C D E F + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |1| exp | mant | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * Maximum Response Delay =3D (mant | 0x1000) << (exp+3) + * - 9.3. Query Response Interval + * + * After decode, MRC represents the Maximum Response Delay (MRD) in + * units of milliseconds. + */ +static inline unsigned long mldv2_mrd(const struct mld2_query *mlh2) { - /* RFC3810, 5.1.3. Maximum Response Code */ - unsigned long ret, mc_mrc =3D ntohs(mlh2->mld2q_mrc); + unsigned long mc_mrc =3D ntohs(mlh2->mld2q_mrc); =20 - if (mc_mrc < MLD_EXP_MIN_LIMIT) { - ret =3D mc_mrc; + if (mc_mrc < MLD_MRC_MIN_THRESHOLD) { + return mc_mrc; } else { unsigned long mc_man, mc_exp; =20 mc_exp =3D MLDV2_MRC_EXP(mc_mrc); mc_man =3D MLDV2_MRC_MAN(mc_mrc); =20 - ret =3D (mc_man | 0x1000) << (mc_exp + 3); + return (mc_man | 0x1000) << (mc_exp + 3); } +} =20 - return ret; +/* Calculate Querier's Query Interval from Querier's Query Interval Code + * + * RFC3810, relevant sections: + * - 5.1.9. QQIC (Querier's Query Interval Code) defines the decoding for= mula: + * 0 1 2 3 4 5 6 7 + * +-+-+-+-+-+-+-+-+ + * |1| exp | mant | + * +-+-+-+-+-+-+-+-+ + * QQI =3D (mant | 0x10) << (exp + 3) + * - 9.2. Query Interval + * - 9.12. Older Version Querier Present Timeout + * (the [Query Interval] in the last Query received) + * + * After decode, QQIC represents the Querier's Query Interval in units + * of seconds. + */ +static inline unsigned long mldv2_qqi(const struct mld2_query *mlh2) +{ + unsigned long qqic =3D mlh2->mld2q_qqic; + + if (qqic < MLD_QQIC_MIN_THRESHOLD) { + return qqic; + } else { + unsigned long mc_man, mc_exp; + + mc_exp =3D MLDV2_QQIC_EXP(qqic); + mc_man =3D MLDV2_QQIC_MAN(qqic); + + return (mc_man | 0x10) << (mc_exp + 3); + } } =20 #endif diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 9fec76e887bc..1438c023db62 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -3606,7 +3606,7 @@ static int br_ip6_multicast_query(struct net_bridge_m= cast *brmctx, mld2q->mld2q_suppress) goto out; =20 - max_delay =3D max(msecs_to_jiffies(mldv2_mrc(mld2q)), 1UL); + max_delay =3D max(msecs_to_jiffies(mldv2_mrd(mld2q)), 1UL); } =20 is_general_query =3D group && ipv6_addr_any(group); diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index 3330adcf26db..6ddc18ac59b9 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c @@ -1315,20 +1315,7 @@ static void mld_update_qi(struct inet6_dev *idev, * - 9.12. Older Version Querier Present Timeout * (the [Query Interval] in the last Query received) */ - unsigned long mc_qqi; - - if (mlh2->mld2q_qqic < 128) { - mc_qqi =3D mlh2->mld2q_qqic; - } else { - unsigned long mc_man, mc_exp; - - mc_exp =3D MLDV2_QQIC_EXP(mlh2->mld2q_qqic); - mc_man =3D MLDV2_QQIC_MAN(mlh2->mld2q_qqic); - - mc_qqi =3D (mc_man | 0x10) << (mc_exp + 3); - } - - idev->mc_qi =3D mc_qqi * HZ; + idev->mc_qi =3D mldv2_qqi(mlh2) * HZ; } =20 static void mld_update_qri(struct inet6_dev *idev, @@ -1338,7 +1325,7 @@ static void mld_update_qri(struct inet6_dev *idev, * - 5.1.3. Maximum Response Code * - 9.3. Query Response Interval */ - idev->mc_qri =3D msecs_to_jiffies(mldv2_mrc(mlh2)); + idev->mc_qri =3D msecs_to_jiffies(mldv2_mrd(mlh2)); } =20 static int mld_process_v1(struct inet6_dev *idev, struct mld_msg *mld, @@ -1390,7 +1377,7 @@ static int mld_process_v1(struct inet6_dev *idev, str= uct mld_msg *mld, static void mld_process_v2(struct inet6_dev *idev, struct mld2_query *mld, unsigned long *max_delay) { - *max_delay =3D max(msecs_to_jiffies(mldv2_mrc(mld)), 1UL); + *max_delay =3D max(msecs_to_jiffies(mldv2_mrd(mld)), 1UL); =20 mld_update_qrv(idev, mld); mld_update_qi(idev, mld); --=20 2.43.0 From nobody Sun Jun 14 07:34:43 2026 Received: from mail-pj1-f46.google.com (mail-pj1-f46.google.com [209.85.216.46]) (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 767C9309EEB for ; Fri, 1 May 2026 17:32:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.46 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777656726; cv=none; b=FSdVR6IVvbdDKLvLZGNzNpAppm7VUPPWoUtN7yoeTjRN3tyMd4VQEkWv8/aQY8AnQQwONzFQS/96Ynd6OZqBYA99etid+C+omdO1gH+oqaSjGx24cw4ovoHd+zIkKe86yYhpXGpXp9fGkbMZ4sWgZcquRMSGhFUEgVDXcsFIUEk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777656726; c=relaxed/simple; bh=ZVHW1z1PIb5ePVtbyq08NJ8dexrkCXfgDVaSH/sbAuc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=KFKTstKNYNYHG/aQH/CKZ4sRPUtIWXcjl0zoT2nW+MC9igS/dsOyj5zufAQ2XzZV01TnlwjO4JZY3vHhItj96lU4zBrgwOdB+Am1x1THxKRfLB0hIemQ1LxM8gq+9yNkMpPRaSfwoG5ZWL8USUhY9d3xju3s//lrorGaTEGuKtc= 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=JGrGYmJE; arc=none smtp.client-ip=209.85.216.46 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="JGrGYmJE" Received: by mail-pj1-f46.google.com with SMTP id 98e67ed59e1d1-35fc0d7c310so1525301a91.1 for ; Fri, 01 May 2026 10:32:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1777656725; x=1778261525; 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=qnFHFq0X3do40vbZFzPcxUaeVD7TkwqS7ui8TNvbysY=; b=JGrGYmJEHwHwqVz+YnEY8AHy3bKQ8xR4yG/DZL9J+kRWe6V73eS9bKg4sVa7/WA13V I4myyj61W8TPC3tpk1Abh5PHxEtkle5YW2nQviTUPPMChMHEZA4uh2mzjVcbPq7jCMl6 rUtVFHE+s87e/NumPxUsANYU+kZhnE++8IGLM/fbzu4DAcVo3fCv7Py1xM+JwdLU3Gmk r1ILSaCmwVsQGqLWmscE4I5L5nMkK6HNg3EV6ZtGrudOyJZQDFlbYSNOGJgDiIKOyxul 1M1CHgQYngHXBTKe9KCmiZaI6CM+hbz1AyCHPUaElElSTzubsibXLAo0OXHHjJdhEP+W ioCw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1777656725; x=1778261525; 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=qnFHFq0X3do40vbZFzPcxUaeVD7TkwqS7ui8TNvbysY=; b=CzJqWkYkVI8rOsrVP0fqs8RZtQizCcxkNignY3mPPPUBr72g5X7rrdSCAdQIkyDbUs h890NCZBOaxWn+XrwTF8PLAR4MJ5YjVSkNYEqC/PuviubzdNoRRKJLMDDoRSTVWHOV5Y tar0EuQrcs9Jz8xPvRRtau9vqxlpDZX5SVzCfP+tGdkMuTqcgN27yBwz1N+i4NObgIh7 nLjkWaM4FeeDbfknBTDfsW30UMM6nC0I7za5n/leBM48G+7VNe/PvRLs+lwa546ZDTxH DJG63Sfe9wxXvyFR8r2AHQjmsK+bcLFPHenP8RY4K4wwdKd4tyMznYHRNrIF83fWbNym JFKw== X-Forwarded-Encrypted: i=1; AFNElJ+g1v5+7gK7w7Hqmpp15UabJzIPLungURlK6M6C4zZHIh2gW8nDwhDraQp13Ik5aPORrDFYwBoexKSOtsI=@vger.kernel.org X-Gm-Message-State: AOJu0YwUQwwPOwEENfu/b0W81kN/cpqn7iqCD8uzY3kUDHtg+kBOXNZt LPP4TK3LjDCtg/5uB2jrrcfwC6lo7Qyksua5Bx+dUBgwrsjU+G2+lmvi X-Gm-Gg: AeBDieukQVFDACWlf0tTKPBVzL2+zt9hMHlky4cyLB3AVqEV6/D9xlQnBqZwdAZNn2G ncp0Ibg/6pWInOg7T3T2LnvcHmEuTAfE0xG7SSDdfNY2Px+d4XBBEfeJ5nSZ8tlc8PWE/5d83Vh LWgE4DC6Z8AxgrM9dR5bFYKYRPJa1dwDrPvN6qMDwHedsFpquZOpNrFOLOb4XsMhM2zYs0cMvXt hDSDVnCJGnqUaDNasz+ykNoidyjcVNDvISJvQWxruF8ki2lSv6kzyG68M3VS9veJRK+52bLATrm LXZa19eOvqj6cbdjSVGheGfTxvLELidflfEHzrBUskKyP3vckkEYFy4Z9FrwOJLLFoIjZjO+/EV qLAUgr9d6Y4XgspTw+209AbJ1fNQYEZ97bqclGexKqg0RoiV3N+ldNUBmI19VvVnDQqLeq2vHSi +25vJYRfSdXx1mrJMeVYopjcVPPdfm/FwkZyWmNZjWTQk5rrvDsQ== X-Received: by 2002:a17:90b:518e:b0:35f:b5df:449 with SMTP id 98e67ed59e1d1-3650cec16c5mr137991a91.21.1777656724709; Fri, 01 May 2026 10:32:04 -0700 (PDT) Received: from DESKTOP-82PPU4A.localdomain ([202.8.116.84]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-364ebec73aasm2908906a91.2.2026.05.01.10.31.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 May 2026 10:32:04 -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 v5 3/5] ipv4: igmp: encode multicast exponential fields Date: Fri, 1 May 2026 17:31:27 +0000 Message-ID: <20260501173130.3486-4-royujjal@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260501173130.3486-1-royujjal@gmail.com> References: <20260501173130.3486-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 IGMP, MRC and QQIC fields are not correctly encoded when generating query packets. Since the receiver of the query interprets these fields using the IGMPv3 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 MRC and QQIC fields (8-bit) are properly encoded when transmitting query packets with intervals that exceed their respective linear threshold value of 128 (for MRT/QQI). RFC3376: for both MRC and QQIC, values >=3D 128 represent the same floating-point encoding as follows: 0 1 2 3 4 5 6 7 +-+-+-+-+-+-+-+-+ |1| exp | mant | +-+-+-+-+-+-+-+-+ Reviewed-by: Ido Schimmel Signed-off-by: Ujjal Roy Reviewed-by: Nikolay Aleksandrov --- include/linux/igmp.h | 87 +++++++++++++++++++++++++++++++++++++++ net/bridge/br_multicast.c | 14 +++---- 2 files changed, 93 insertions(+), 8 deletions(-) diff --git a/include/linux/igmp.h b/include/linux/igmp.h index 0e095c9f234e..3a2d35a9f307 100644 --- a/include/linux/igmp.h +++ b/include/linux/igmp.h @@ -109,6 +109,93 @@ struct ip_mc_list { =20 /* IGMPv3 floating-point exponential field min threshold */ #define IGMPV3_EXP_MIN_THRESHOLD 128 +/* IGMPv3 FP max threshold (mant =3D 0xF, exp =3D 7) -> 31744 */ +#define IGMPV3_EXP_MAX_THRESHOLD 31744 + +/* V3 exponential field encoding */ + +/* IGMPv3 MRC/QQIC 8-bit exponential field encode + * + * RFC3376, 4.1.1 & 4.1.7. defines only the decoding formula: + * MRT/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 igmpv3_exp_field_encode(unsigned long value) +{ + u8 mc_exp, mc_man; + + /* MRC/QQIC < 128 is literal */ + if (value < IGMPV3_EXP_MIN_THRESHOLD) + return value; + + /* Saturate at max representable (mant =3D 0xF, exp =3D 7) -> 31744 */ + if (value >=3D IGMPV3_EXP_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; +} + +/* Calculate Maximum Response Code from Max Resp Time + * + * RFC3376, relevant sections: + * - 4.1.1. Maximum Response Code + * - 8.3. Query Response Interval + * + * MRC represents the encoded form of Max Resp Time (MRT); once + * decoded, the resulting value is in units of 0.1 seconds (100 ms). + */ +static inline u8 igmpv3_mrc(unsigned long mrt) +{ + return igmpv3_exp_field_encode(mrt); +} + +/* Calculate Querier's Query Interval Code from Querier's Query Interval + * + * RFC3376, relevant sections: + * - 4.1.7. QQIC (Querier's Query Interval Code) + * - 8.2. Query Interval + * - 8.12. Older Version Querier Present Timeout + * (the [Query Interval] in the last Query received) + * + * QQIC represents the encoded form of Querier's Query Interval (QQI); + * once decoded, the resulting value is in units of seconds. + */ +static inline u8 igmpv3_qqic(unsigned long qi) +{ + return igmpv3_exp_field_encode(qi); +} =20 /* V3 exponential field decoding */ =20 diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 1438c023db62..27010744d7ae 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -934,12 +934,12 @@ static struct sk_buff *br_ip4_multicast_alloc_query(s= truct net_bridge_mcast *brm size_t pkt_size, igmp_hdr_size; unsigned long now =3D jiffies; struct igmpv3_query *ihv3; + unsigned long lmqt, mrt; void *csum_start =3D NULL; __sum16 *csum =3D NULL; struct sk_buff *skb; struct igmphdr *ih; struct ethhdr *eth; - unsigned long lmqt; struct iphdr *iph; u16 lmqt_srcs =3D 0; =20 @@ -1004,15 +1004,15 @@ static struct sk_buff *br_ip4_multicast_alloc_query= (struct net_bridge_mcast *brm skb_put(skb, 24); =20 skb_set_transport_header(skb, skb->len); + mrt =3D group ? brmctx->multicast_last_member_interval : + brmctx->multicast_query_response_interval; *igmp_type =3D IGMP_HOST_MEMBERSHIP_QUERY; =20 switch (brmctx->multicast_igmp_version) { case 2: ih =3D igmp_hdr(skb); ih->type =3D IGMP_HOST_MEMBERSHIP_QUERY; - ih->code =3D (group ? brmctx->multicast_last_member_interval : - brmctx->multicast_query_response_interval) / - (HZ / IGMP_TIMER_SCALE); + ih->code =3D mrt / (HZ / IGMP_TIMER_SCALE); ih->group =3D group; ih->csum =3D 0; csum =3D &ih->csum; @@ -1021,11 +1021,9 @@ static struct sk_buff *br_ip4_multicast_alloc_query(= struct net_bridge_mcast *brm case 3: ihv3 =3D igmpv3_query_hdr(skb); ihv3->type =3D IGMP_HOST_MEMBERSHIP_QUERY; - ihv3->code =3D (group ? brmctx->multicast_last_member_interval : - brmctx->multicast_query_response_interval) / - (HZ / IGMP_TIMER_SCALE); + ihv3->code =3D igmpv3_mrc(mrt / (HZ / IGMP_TIMER_SCALE)); ihv3->group =3D group; - ihv3->qqic =3D brmctx->multicast_query_interval / HZ; + ihv3->qqic =3D igmpv3_qqic(brmctx->multicast_query_interval / HZ); ihv3->nsrcs =3D htons(lmqt_srcs); ihv3->resv =3D 0; ihv3->suppress =3D sflag; --=20 2.43.0 From nobody Sun Jun 14 07:34:43 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 9881A315D50 for ; Fri, 1 May 2026 17:32:12 +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=1777656734; cv=none; b=ZJ6hBuNCa3jRUTD2RT8bFtBKIcfo4Q71/HG4TEVePFIzHo/hEWvKIBkjBUsiKPiRiZwrZEwp0FLBfMW9nO60MMLt03mVGCoPoSHpcYSWlner3gS01ZXVTyvpmRRSgouCFIu8IUFZHm00L7Rua4S9zY3Utg7qmHWcMBMLPc+GH5U= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777656734; c=relaxed/simple; bh=xFftMd+sCP370S5N0WB8Cg5hFZYfV5pMqZcYKx1TRck=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=da8DKoixciIxm1vU7sG/3UbhMCtH7Z+J+HVyg616TcX9QAZFDecvbNJ6/xhjtEA6x3EdxuosSgVBWgRKLfwZG6+cvoy7eLMNHcY6sjSMx2c6foNPA5aXxat2Z6EI3JIyeMO9MFA50z+diyPFnK2rNS92LISYg/HSSBYo/NEaGno= 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=U8FGMb9f; 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="U8FGMb9f" Received: by mail-pj1-f48.google.com with SMTP id 98e67ed59e1d1-364f7c42c62so408702a91.0 for ; Fri, 01 May 2026 10:32:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1777656732; x=1778261532; 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=rb8PB47x5+EDLuCHmAsj4WHvgIwWlEboX+xOyLy788o=; b=U8FGMb9fyO4IOseItb1MjVgrUYk5PYqZ40EMpRSk0mEZh5BJVEBj0GmuRuEyxAuftn D0LYRpzAleKL8DU/4eGoA/F0xPIWodAY/Gl5F64Osjey1b6SzdE3Q3tPFkjDk85PGKPa 0hI4gArigU1k6eq4fV0bNF+hWMk6FIUvLfTLe//0XBW+SwJnXY0fj6yxSLRDZb0IIxOc bNn1damNztcJFYbBoxAnknj2p0z+ewwkWNEvOCCv4VWnfbpV0ga8HLJIk3CEXHfxvNz2 lObZ2rPOeonmF/WZveSUqdeKAEmI8ATkwiGKd6zC3aYGmclyTsPHUh6y1SQvztEYQBET QeQQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1777656732; x=1778261532; 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=rb8PB47x5+EDLuCHmAsj4WHvgIwWlEboX+xOyLy788o=; b=bVIHS3rzvZysdgyoPyZJA/V/LoG3+7sn1YNMozQpIS/djpHBvpCLHMkxvJ1un/6h4S 6YQg9mq6UI+M24EfsA42kG1xaGGKWuXQZsIKDpz3akXM+lcXEwjv6Oj0fAv/P7Ln+eM6 saHnI60nRldCY4PiGkYqgfyzNE5U6Vuy4/XRB7Y25UFRCYybxJHl/jtsp9RN0kZ0KZEy UK4uafpfyc98niRACGGu1FaAuEfrJ6Hy9FiyRIsfRqK3Auy+K2mADcJ+e0pYK4RS4oqO C84YUeVmut5Y7jY/uzRbLH9TTlSRZuTKEJ8j80NGmR9hUdhY3QyPurkU0XOmRhRVVtwl +O8Q== X-Forwarded-Encrypted: i=1; AFNElJ8Xv9NUSVv8i2trruQPRpXe6pO6Q9n80eWueti6BONlww20dTEpl/Xb0VuM722tpllXXChJlOtmQMm4pOw=@vger.kernel.org X-Gm-Message-State: AOJu0YyTCllJ7zciVY9epZtKguQTSCMDP30aY+84YuLTmH7yCE1sJCGt Gjmwv9oJy4/Sgp7DA3GmmDkAl+jrp64bzPVpuiHclUOmb5lA8fR6LJJY X-Gm-Gg: AeBDiet8PTFw4oHRnyrCfUMbNhE0lWux6F8a5BpY6GMJsT3Q3HsoLNl+THHXh7CKMSP nFxRBAXUaBdR/LAEcq008YOjIOOHN+o1QuoCJpsh9B2nPXTEovSGxVObSbKV2UtbawPhk5GwLOw 4w5LuXKyGhYVpuHUzvskKWM0JtI2ae5K7933W76v6bShLcxoeey0YkZu/SyaCBT8Q066BdMZr1E 0F8nGFqTUsG0b9Of8pfXVy4HMrMRL1pmTqTS05PoZBUBPj/7FtkfAt2KDiS+tZF9oHWhrpJAhsN WhhTXgYWYu3C/+ocOvutaFjjvOf/pfY2Cv85JpNc209QjVi4LJgS46sdK/oBO0fR8BxMmeGTAk/ f0UEcrqLMmSJExRgKfq1slM9ZQTN9c2Ie9UnY+tyEJBP+0RqX2XY5uM0uSZu3NmBf4YkxRk8eaq YcLw64sI/pSmaMnzX2NPMvp97A4l1NJa0VHzgVLQ0YLdn5LlGK2g== X-Received: by 2002:a17:90a:d444:b0:364:6558:99be with SMTP id 98e67ed59e1d1-3650ceaab7fmr129493a91.22.1777656731861; Fri, 01 May 2026 10:32:11 -0700 (PDT) Received: from DESKTOP-82PPU4A.localdomain ([202.8.116.84]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-364ebec73aasm2908906a91.2.2026.05.01.10.32.05 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 May 2026 10:32:11 -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 v5 4/5] ipv6: mld: encode multicast exponential fields Date: Fri, 1 May 2026 17:31:28 +0000 Message-ID: <20260501173130.3486-5-royujjal@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260501173130.3486-1-royujjal@gmail.com> References: <20260501173130.3486-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, MRC and QQIC 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 MRC (16-bit) and QQIC (8-bit) fields are properly encoded when transmitting query packets with intervals that exceed their respective linear thresholds (32768 for MRD; 128 for QQI). 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 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 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 | +-+-+-+-+-+-+-+-+ Reviewed-by: Ido Schimmel Signed-off-by: Ujjal Roy Reviewed-by: Nikolay Aleksandrov --- include/net/mld.h | 119 ++++++++++++++++++++++++++++++++++++++ net/bridge/br_multicast.c | 4 +- 2 files changed, 121 insertions(+), 2 deletions(-) diff --git a/include/net/mld.h b/include/net/mld.h index 10e402e0fe08..23255cc47ced 100644 --- a/include/net/mld.h +++ b/include/net/mld.h @@ -91,13 +91,132 @@ struct mld2_query { =20 /* MLDv2 QQIC floating-point exponential field min threshold */ #define MLD_QQIC_MIN_THRESHOLD 128 +/* MLDv2 QQIC FP max threshold (mant =3D 0xF, exp =3D 7) -> 31744 */ +#define MLD_QQIC_MAX_THRESHOLD 31744 /* MLDv2 MRC floating-point exponential field min threshold */ #define MLD_MRC_MIN_THRESHOLD 32768UL +/* MLDv2 MRC FP max threshold (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, 5.1.3. 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; + + /* 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 Querier's Query Interval + * + * QQIC represents the 8-bit encoded form of Querier's Query Interval (QQI= ); + * once decoded, the resulting value is in seconds. + * + * RFC3810, 5.1.9. 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; + + /* 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..49ceea3ff974 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(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 From nobody Sun Jun 14 07:34:43 2026 Received: from mail-pj1-f44.google.com (mail-pj1-f44.google.com [209.85.216.44]) (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 157C7313E10 for ; Fri, 1 May 2026 17:32:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.44 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777656741; cv=none; b=SnlkG+2hQbGHVoLZXeohBxGHavwB167HuGC2IWMOAA5JWDigVCqIe54TmjSp4eHikmtMEb2yU7Yt9bZXzZczZ0XtVTCtLs38MUMOlB1KnoHC46o7BYKoGAHl6zvFTmhWeqH1ukE2F3eu9qCLnDqUl37lXUu9Iouisrnn9qffoUw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777656741; c=relaxed/simple; bh=UNdRW3uKisT5Fvi5K3/wNmEi4x6RxXCvZYWzNG8kchQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=mH7nhprbttZNDxLMFnPEcOUmJvzG/9JzcrvehtrrU6SxdL51N0iEMqv0XcNAOeNvafLte+RmorU4lLziWrgAvHua/cBM8clsNRXmx2wnH4PAO9+yhFUGTy15fCWKlKJfxUQ/R8MF3FRa25L7SlMejPp1w+46mmiZj8Z8R/pFvxQ= 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=VLNT9R3J; arc=none smtp.client-ip=209.85.216.44 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="VLNT9R3J" Received: by mail-pj1-f44.google.com with SMTP id 98e67ed59e1d1-35fc0d7c310so1525473a91.1 for ; Fri, 01 May 2026 10:32:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1777656739; x=1778261539; 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=IzwTHkm3utnnP48DK2qyC96JgeUzR2iB5DEneSRP2HI=; b=VLNT9R3J+EkkBPhHzMUcxLoxxO7tRbNaTUbFkFDW1f52EBrrMUyhjmXn4psm54yO9N 1sy5ijNAjJGl686tSMCchfPQOc7he496jAfT/HRMDuAIWGlGiJ3I8jzas3I0kNKp0ONF /Kp867dz3U6YRUDP1HH7SRk6cOsBtE9WdrbpzBFNxdM2+QSKrJ4WjXpmXvqOIK1ZQmJv TCY8WzyMzHwaQhtrw6IuR9051n/42ZOm6AG2XC4a2F9vvplY8+c4Bd1/VoEyAuWm82c2 AhZlEHIrBnSHclPZlYoGfpfxIJ284kJy5I2Gf5JjEtGE2z9DyvXW/riJ81xltXZL1gdP C/yg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1777656739; x=1778261539; 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=IzwTHkm3utnnP48DK2qyC96JgeUzR2iB5DEneSRP2HI=; b=Om6BJ2ZnrV1GeF4fEbHdpc5Emts1rpN+SE6UVS/HAt5xODlxIo2PHpuORTZNngXi1O iQHW+4FjEEg2Ou53EkeUrQPoYKCeKfuE/PXKChHxq+AF1lVzuXcoC00xQRdO+URtEJlw fnUcD6KsXf0VuTqGRDkE3xdPRcvX+dX/arR3ZDe5IDl1HsQ4xOO7urGVF4d35Zj3oJ2w 5FqGB+QZCOWyXdqI3EmTMh/KH9qr3PukHVm6y2hMlnY0oiESEsegPnYRfThy2trpCxG6 4a/WGO4Ar2uslvN/IY+dmc1QwQwdha+1DhUvABEIsNphUDIp6+0orqRDgH7Y1on2GCJ4 nFQw== X-Forwarded-Encrypted: i=1; AFNElJ+R589K6RlXx0UqslYAlggA26s64EDhCnFrkhrQV6KrgXMHWqpnd/izG5DNX66leCwIYn+1+hFyg+EUNF8=@vger.kernel.org X-Gm-Message-State: AOJu0Ywu6HGxsFOjpQi7oXleE8YtZaxBkDH7dtOlwV8vwPcEkHXWz+Sy GsUJvBMs2kw2DjHP0aNjV+3h8dn/36Nmlc8KxLHseKvoMNsOILn4WzfM X-Gm-Gg: AeBDietJDNsIlgRNvY4nWC7yGF2DaV5DIHFSUnBPGtq6W798hivTe0CCd3arDWR0NyL uSryBSwa1BI5Kv9viVq6EOFSdxHiZcA1+WcD2y/T4Qtt8LjGz/hjp8+GaTgGYKw03/zcx3KzDIY dBxbX8+Ct4XpIZICFfScpom/y0xb8C05U4EUk2EqjkXsQP7k5n4ezzOvo4PV7kCI5Vfn/RWDFYz fNn7pFSkhIsV0ekc5DiVTMjo3HWHdrhp5bNomB4WrnPOOf60BKXSCJb1Mz8P4WwHQRdfdyV2FTT Vo/1xrRxfBgHM0UB3Gy9qcNS9ItituOBh8jQIE5la1szMvS78Yw5Cbn0q48YexmPI3OQ8rdZ1aJ YhZ7Goh2lmBn1mardsmVca7Ea31L2o1veLDitGQ0Nmji7CQjI/YKeHg5Cw42/27RBWPK8yzcfoN j6tm+cGBhNdrwwy2zbdyMLIcj9dwuuhdoxfm0urtVSvJlQLz4Q7w== X-Received: by 2002:a17:90b:278f:b0:35c:30a8:32a with SMTP id 98e67ed59e1d1-3650cdb8085mr166497a91.9.1777656739170; Fri, 01 May 2026 10:32:19 -0700 (PDT) Received: from DESKTOP-82PPU4A.localdomain ([202.8.116.84]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-364ebec73aasm2908906a91.2.2026.05.01.10.32.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 01 May 2026 10:32:18 -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 v5 5/5] selftests: net: bridge: add MRC and QQIC field encoding tests Date: Fri, 1 May 2026 17:31:29 +0000 Message-ID: <20260501173130.3486-6-royujjal@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260501173130.3486-1-royujjal@gmail.com> References: <20260501173130.3486-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" Enhance vlmc_query_intvl_test and vlmc_query_response_intvl_test in bridge_vlan_mcast.sh to validate IGMPv3/MLDv2 protocol compliance for MRC and QQIC field encoding across both linear and exponential ranges. TEST: Vlan multicast snooping enable [ OK ] TEST: Vlan mcast_query_interval global option default value [ OK ] TEST: Number of tagged IGMPv2 general query [ OK ] TEST: IGMPv3 QQIC linear value 60(s) [ OK ] TEST: MLDv2 QQIC linear value 60(s) [ OK ] TEST: IGMPv3 QQIC non linear value 160(s) [ OK ] TEST: MLDv2 QQIC non linear value 160(s) [ OK ] TEST: Vlan mcast_query_response_interval global option default value [ OK= ] TEST: IGMPv3 MRC linear value of 60(x0.1s) [ OK ] TEST: MLDv2 MRC linear value of 24000(ms) [ OK ] TEST: IGMPv3 MRC non linear value of 240(x0.1s) [ OK ] TEST: MLDv2 MRC non linear value of 48000(ms) [ OK ] Reviewed-by: Ido Schimmel Signed-off-by: Ujjal Roy Reviewed-by: Nikolay Aleksandrov --- .../net/forwarding/bridge_vlan_mcast.sh | 140 +++++++++++++++++- 1 file changed, 132 insertions(+), 8 deletions(-) diff --git a/tools/testing/selftests/net/forwarding/bridge_vlan_mcast.sh b/= tools/testing/selftests/net/forwarding/bridge_vlan_mcast.sh index e8031f68200a..07a377652a59 100755 --- a/tools/testing/selftests/net/forwarding/bridge_vlan_mcast.sh +++ b/tools/testing/selftests/net/forwarding/bridge_vlan_mcast.sh @@ -162,14 +162,27 @@ vlmc_query_cnt_setup() { local type=3D$1 local dev=3D$2 + local match=3D($3) =20 if [[ $type =3D=3D "igmp" ]]; then - tc filter add dev $dev egress pref 10 prot 802.1Q \ + # 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 goto chain 1 + # AND Type 0x11 (Query) at offset 0 of IGMP header + # 20 bytes IPv4 header + 4 bytes Router Alert option + IGMP[offset 0] + tc filter add dev "$dev" egress pref 20 chain 1 prot 802.1Q u32 \ + match u8 0x11 0xff at 24 "${match[@]}" \ action pass else - tc filter add dev $dev egress pref 10 prot 802.1Q \ + # 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 goto chain 1 + # AND Type 0x82 (Query) at offset 0 of MLD header + # 40 bytes IPv6 header + 8 bytes Hop-by-hop option + MLD[offset 0] + tc filter add dev "$dev" egress pref 20 chain 1 prot 802.1Q u32 \ + match u8 0x82 0xff at 48 "${match[@]}" \ action pass fi =20 @@ -181,7 +194,39 @@ 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 10 + tc filter del dev "$dev" egress pref 20 chain 1 + tc filter del dev "$dev" egress pref 10 +} + +vlmc_query_get_intvl_match() +{ + local type=3D$1 + local version=3D$2 + local test=3D$3 + local enc_val=3D$4 + + if [ "$test" =3D "qqic" ]; then + # QQIC is 8-bit floating point encoding for IGMPv3 and MLDv2 + if [ "${type}v${version}" =3D "igmpv3" ]; then + # QQIC is at offset 9 of IGMP header + # 20 bytes IPv4 header + 4 bytes Router Alert option + IGMP[offset 9] + echo "match u8 $enc_val 0xff at 33" + elif [ "${type}v${version}" =3D "mldv2" ]; then + # QQIC is at offset 25 of MLD header + # 40 bytes IPv6 header + 8 bytes Hop-by-hop option + MLD[offset 25] + echo "match u8 $enc_val 0xff at 73" + fi + elif [ "$test" =3D "mrc" ]; then + if [ "${type}v${version}" =3D "igmpv3" ]; then + # MRC is 8-bit floating point encoding at offset 1 of IGMP header + # 20 bytes IPv4 header + 4 bytes Router Alert option + IGMP[offset 1] + echo "match u8 $enc_val 0xff at 25" + elif [ "${type}v${version}" =3D "mldv2" ]; then + # MRC is 16-bit floating point encoding at offset 4 of MLD header + # 40 bytes IPv6 header + 8 bytes Hop-by-hop option + MLD[offset 4] + echo "match u16 $enc_val 0xffff at 52" + fi + fi } =20 vlmc_check_query() @@ -191,9 +236,13 @@ vlmc_check_query() local dev=3D$3 local expect=3D$4 local time=3D$5 + local test=3D$6 + local enc_val=3D$7 + local intvl_match=3D"" local ret=3D0 =20 - vlmc_query_cnt_setup $type $dev + intvl_match=3D"$(vlmc_query_get_intvl_match "$type" "$version" "$test" "$= enc_val")" + 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 +250,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 || \ @@ -448,8 +497,46 @@ 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" + 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 60 (0= x3c) + # which is 8-bit encoded value of 60 [units of seconds] + vlmc_check_query igmp 3 $swp1 1 1 qqic 0x3c + check_err $? "Wrong QQIC in generated IGMPv3 general queries" + log_test "IGMPv3 QQIC linear value 60(s)" + + RET=3D0 + # 1 is sent immediately, MLDv2 QQIC should match with linear value 60 (0x= 3c) + # which is 8-bit encoded value of 60 [units of seconds] + vlmc_check_query mld 2 $swp1 1 1 qqic 0x3c + check_err $? "Wrong QQIC in generated MLDv2 general queries" + log_test "MLDv2 QQIC linear value 60(s)" + + 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= 32 (0x84) + # which is 8-bit encoded value of 160 [units of seconds] + vlmc_check_query igmp 3 $swp1 1 1 qqic 0x84 + check_err $? "Wrong QQIC in generated IGMPv3 general queries" + log_test "IGMPv3 QQIC non linear value 160(s)" =20 + RET=3D0 + # 1 is sent immediately, MLDv2 QQIC should match with non linear value 13= 2 (0x84) + # which is 8-bit encoded value of 160 [units of seconds] + vlmc_check_query mld 2 $swp1 1 1 qqic 0x84 + check_err $? "Wrong QQIC in generated MLDv2 general queries" + log_test "MLDv2 QQIC non linear value 160(s)" + + 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 } @@ -469,10 +556,47 @@ 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" + 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" + 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 (0x= 3c) + # which is 8-bit encoded value of 60 [units of 0.1s =3D 6 seconds] + vlmc_check_query igmp 3 $swp1 1 1 mrc 0x3c + check_err $? "Wrong MRC in generated IGMPv3 general queries" + log_test "IGMPv3 MRC linear value of 60(x0.1s)" + + RET=3D0 + bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_query_respon= se_interval 2400 + check_err $? "Could not set mcast_query_response_interval in vlan 10" + # 1 is sent immediately, MLDv2 MRC should match with linear value 0x5dc0 = (24000) + # which is 16-bit encoded value of 24000 [units of ms / 24 seconds] + vlmc_check_query mld 2 $swp1 1 1 mrc 0x5dc0 + check_err $? "Wrong MRC in generated MLDv2 general queries" + log_test "MLDv2 MRC linear value of 24000(ms)" + + RET=3D0 + # 1 is sent immediately, IGMPv3 MRC should match with non linear value 14= 2 (0x8e) + # which is 8-bit encoded value of 240 [units of 0.1s =3D 24 seconds] + vlmc_check_query igmp 3 $swp1 1 1 mrc 0x8e + check_err $? "Wrong MRC in generated IGMPv3 general queries" + log_test "IGMPv3 MRC non linear value of 240(x0.1s)" + + RET=3D0 + bridge vlan global set vid 10 dev br0 mcast_snooping 1 mcast_query_respon= se_interval 4800 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 0x8= 770 (34672) + # which is 16-bit encoded value of 48000 [units of ms / 48 seconds] + vlmc_check_query mld 2 $swp1 1 1 mrc 0x8770 + check_err $? "Wrong MRC in generated MLDv2 general queries" + log_test "MLDv2 MRC non linear value of 48000(ms)" =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 --=20 2.43.0