From nobody Thu Apr 2 20:26:36 2026 Received: from mail-pl1-f174.google.com (mail-pl1-f174.google.com [209.85.214.174]) (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 8DC8C401495 for ; Thu, 26 Mar 2026 15:07:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.174 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774537676; cv=none; b=qKfp2SFoCk8mY0+yFGlZh9weNqvidBS+OZLG8n0BjascyKQm28rUjmCA4GpCZT0ZsyLosSYAh5muDGUZSpyxtndhzqo/tNETxxoqWLCNIHLTNwb1/n3mg584QAH1m8PcAl/fPu74qGILfZ8yms0iUjWOKYJirt/bG86/aJRSpVI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774537676; c=relaxed/simple; bh=WW0vISqU8GwrmrIC4NHoR+TFPQ7BlX0/FvDVbKYURp4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=JhPd8bD+GtUoUJvzq9g3w7NhMARbF0BDdObZ4GeSK49tYqoURWNw/AcaIv7CA32a3LCHD2ywrKm4Qc1ZnJGRFx1EVkrK4WCahNR3Lqyw3rdrXjYNc0ecqadsnCzw9c2XZfYhVrQBzli6C4wYaVP8NIj8HISPUL3NZVaCSJxi0TQ= 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=CJaOG865; arc=none smtp.client-ip=209.85.214.174 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="CJaOG865" Received: by mail-pl1-f174.google.com with SMTP id d9443c01a7336-2ab077e3f32so5056085ad.3 for ; Thu, 26 Mar 2026 08:07:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1774537675; x=1775142475; 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=O2s2FZ+Hg0ngcpnnbi9FLabs6QrxAbJsZ+G4M5k6jv8=; b=CJaOG865E1KdVQlf0Fb0vc7ZTte+c9JibJ0LX+yeIW2PLuGKzkhdl9huGoMZBZv9oG BT9zTzxHn36h+VaJLmQXBw9Qe5+i62NsuqCR2dIeoIqzMVmccPzgKd6585P+R3F8VQNq /FUwGxpcRcRhHnNq8aJUow2jBkAU3h3TenKlXbPlR6NLLKbVhGrSM23JPYNVKl3frQav JMSkUCP9O95Q7Dn92YEjf7oCBzi3maCG8V9XWjNzpQhUMFJk7WaF6pBSf7I2H9YKeuAG G1aa8Ex6JmOWhRRCw2Q/lnR7PH7dYaov0ib+cn+pstH+R71DQJ3uJw00HtVHYErRMdgN kqxQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1774537675; x=1775142475; 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=O2s2FZ+Hg0ngcpnnbi9FLabs6QrxAbJsZ+G4M5k6jv8=; b=lRIM8mp+zcA7G882iHDB0TEp2yM2BJj0Puoa5KnAWaw4ROHoHX0kbOn7hMzWeq2JGl M1kUJn9Ije71oNQxamJUmOofO651MdFCKS5YVlHrU2rLVbK9Q84ztAz5cNUokm72zbqv tZ//EqlEsm+ZNkYVwQxDWXBLe0OEtOMrJuH8HJkpNJCQsHgsrTsLmQNzl1iYA2vk+upN I2C0KVp77jQokygDsvBYE1tP6HzgPxaWFEMEjFvT26iFxUytB2yPocmRkOtH1jjnfuWv egL/BcTrviWxixEqcj7Ym95DpuhVsM4R7ELnskXd2AZ4pfgkqrjCcxVmF66C5heDRC7k sVLQ== X-Forwarded-Encrypted: i=1; AJvYcCXQRmPXyL+kPNydGo0SbIDZPEr7TUpM16C2rVtEHwIgUOvu/93Dh1W5mCwPcFKE5gtgavJtQLHErYvadQM=@vger.kernel.org X-Gm-Message-State: AOJu0YxrRFMWxw9b7ey+k9SpLaJ0TagHHlfi87fUn5HS0yWf0I+reJDJ xkNrRa2qK7urLsNrb1y6LZmUz//TyV7rtBPDzJn0rg1dLjhqMqHZy/Tpe4JsGG2X6b0= X-Gm-Gg: ATEYQzw0IcqRbUUqNO/7losgPtzQBBdDQX2JTvxqbBJLh+qXlKgPtCNysToERs6Usuv L0RvrpD2f2XnGSctG39YOvx9IXl3sWak7qE4t36xdnkO4F0e9tWmRbd58uZjXjrYtIrF1DhUQMq NA82kXzD3NLSPkI2D5uvQUcRl04/qJxzfQavypQDn0AfK+w5EQ6giKIc9WfQep2G4/lznyZBVT7 NUsUal0ammKgqlRAz8hhZJPw7nPu3Ev4jyGDDK1FRci8Q7UnhbzYBDRjX2fgWbri8qtD9MfuBXw MwTRtmIZE0QaJ0Rn41eYmfGGckaBEs1/U34Ve28J/4yswLc9bVJe+gOcHZDF+2JWMHoLLym7Q4s 8lBD6NDqQ8mMaOwm5PYMzGOax7fEAUGmlL9rD89W1+a+v9PSTL+bh813NIjWA0Gkvn83r7fY/qB BEO6VEwAXaulDb6q8URWOk9QR4ob+qzBRNkKvaKi5r X-Received: by 2002:a17:902:ef07:b0:2ae:ba5f:3ac3 with SMTP id d9443c01a7336-2b0b09a7468mr88751885ad.2.1774537674911; Thu, 26 Mar 2026 08:07:54 -0700 (PDT) Received: from DESKTOP-82PPU4A.localdomain ([202.8.116.170]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2b0bc8bb5fasm33146375ad.59.2026.03.26.08.07.50 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 26 Mar 2026 08:07:54 -0700 (PDT) From: Ujjal Roy To: "David S . Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Nikolay Aleksandrov , Ido Schimmel , David Ahern Cc: Ujjal Roy , bridge@lists.linux.dev, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 1/4] ipv4: igmp: get rid of IGMPV3_{QQIC,MRC} and simplify calculation Date: Thu, 26 Mar 2026 15:07:39 +0000 Message-ID: <20260326150742.50289-2-royujjal@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260326150742.50289-1-royujjal@gmail.com> References: <20260326150742.50289-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. Signed-off-by: Ujjal Roy --- include/linux/igmp.h | 78 +++++++++++++++++++++++++++++++++++---- net/bridge/br_multicast.c | 2 +- net/ipv4/igmp.c | 6 +-- 3 files changed, 74 insertions(+), 12 deletions(-) diff --git a/include/linux/igmp.h b/include/linux/igmp.h index 073b30a9b850..3c12c0a63492 100644 --- a/include/linux/igmp.h +++ b/include/linux/igmp.h @@ -92,15 +92,77 @@ 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) + * + * If Max Resp Code >=3D 128, Max Resp Code represents a floating-point + * value as follows: + * If QQIC >=3D 128, QQIC represents a floating-point value 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 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 QQI/MRT 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) +{ + /* RFC3376, relevant sections: + * - 4.1.1. Maximum Response Code + * - 4.1.7. QQIC (Querier's Query Interval Code) + */ + if (code < IGMPV3_EXP_MIN_THRESHOLD) { + return (unsigned long)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 */ +static inline unsigned long igmpv3_mrt(const struct igmpv3_query *ih3) +{ + /* RFC3376, relevant sections: + * - 4.1.1. Maximum Response Code + * - 8.3. Query Response Interval + */ + return igmpv3_exp_field_decode(ih3->code); +} + +/* Calculate Querier's Query Interval from Querier's Query Interval Code */ +static inline unsigned long igmpv3_qqi(const struct igmpv3_query *ih3) +{ + /* 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) + */ + 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..8c6102737096 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 Thu Apr 2 20:26:36 2026 Received: from mail-pl1-f172.google.com (mail-pl1-f172.google.com [209.85.214.172]) (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 4FA73401495 for ; Thu, 26 Mar 2026 15:08:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774537681; cv=none; b=hX0jsW+aAbC+cNbLCyzdh1L6xS9sK5LqCZIA+cpTlnxAVGSEgaKR9EENSMbUXa95tPnntQPBx1M+UbR5xbYmjWyGR6JWOilvHYjW5tZVwwhak76XOYjWn7Uhvf6GmNqF96C+MJoCoVLWhvu4cUYz4/7Zlk0Oh7livkbg5XbLV48= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774537681; c=relaxed/simple; bh=Plea5iBFdrt1H6d4ZGv0XEzQG+OQNdXeC+Jz94Z9T/M=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=O9yMWYM8Q9zhMOLNwx4a8Y34y2Rc9ag9EI8FlGwJ4DoTpDeWPNK4aUuP3KzTsZExt15+Sv8NmHsTfRJ1CcR28wY3E3JP4YbpxEadt4iL/NfPgYKQ94SAhmJomRSeJSb99ojDXLxjZ+OAqX1HYFKOzAJGJszJrxOo94Mgm+DDDmo= 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=OzvD6wdL; arc=none smtp.client-ip=209.85.214.172 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="OzvD6wdL" Received: by mail-pl1-f172.google.com with SMTP id d9443c01a7336-2b042533de1so6151045ad.0 for ; Thu, 26 Mar 2026 08:08:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1774537680; x=1775142480; 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=8Vd4SXqk71/8Mc4Vs55kpxlo3429C4j+4N2/E0Qv8FI=; b=OzvD6wdL0+Eh+i6LA9p9e/Fc4WUjS5WpLs1ZVDe3hBiGF7y2Ock3Rj1L/BPylPHIez rzxW3l2ecWAQ4EHXlh1jZSEHsTXa1wTwC0nlUY9pMqfELV2if07bTviIeP+1n1Dk5q72 iWLQyrPnMwRgveResDYyyh/LueCf4Qb+uoLdXWLmFNpfJVVDvMGzMMbYO+Q1JH2NDlnk awbLydHzl9vHKApPTLjBbgP5HDvsklYX3vVJE90A/pEu1LCaF1NZVAv5396iug6vDu2i nrYsoAsL+AliCghu/ZfuhFe6dhShE0S3Rxr/CPmzV4Apamt0V14fnUeGbt2f+R2GaEoV rXOQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1774537680; x=1775142480; 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=8Vd4SXqk71/8Mc4Vs55kpxlo3429C4j+4N2/E0Qv8FI=; b=Mk7tLQLdRCkxDnrS5xV8gpu/RA7KJqVyL90z3sgctRA26KgF7ZwHhc6W3rEvauC+nf itO60vNYcRhtUUD2NQNG39l1Qaa5z0nWyq0HeZeOnIQwgYnGvUIbCtHnslNHAYwejTCx gMCwLYmBeD0qh6rMeHEVPgF8poj1zYbRANfWFgf+s5+yDD+T3JdeC4R5aB6CtLmZ7jNQ ASsC8jUUNn15fRPxUTkyc7rAVNRxiuPpixWklfY+745qvEep6bikQr3m2CQXXypnHYVx 56HNVTfE2PkeR/zWB8AFnAsWrmhluux8F1Hf5v/wSQy6LqA3e51cdncvJw4ZqDdy8c9y 1CHg== X-Forwarded-Encrypted: i=1; AJvYcCXSDsL+4gHgQRjlCsjDwgn2++81FK6VoS2yAK52k8F4k6o3XAMhqJoWtv46rqpPsZo9rzqMx/i5J7e+2ko=@vger.kernel.org X-Gm-Message-State: AOJu0Yzzut6SZFuN9yra4SzkyNR6HPmArjEWYa7LMvbr0Fch6U3Uow85 /9woayeef7Al0auUcIjAOSyUq6ND2E8A9tXWD55QNapRomjm34z9DeZN X-Gm-Gg: ATEYQzyBFN4awIIMTi0COjG8v7TCZPkGKSB2RO0m/NFMhQTX3F9WbRdRaCIKil9CDtc lcv81+INIVUSKKViFWykoEv9jyPledYuPpd+NfM34jc52vp8Hu2cVoelT4gbNZpXU+/tm/+AKYQ nNZAVEMJbzKmBAm65y/Li7mw3y2fABVeaIGRHGOz3F/mP+VHVteerKtcXuPt3XY7pUITi2re1XB ioMK9vOOd/O0wUCCKjzWYSvo2iqXvxdqT8q6JY1bOJzb7yXt6GAMRHAOjnzhvYjIkbHVhSxqWTD LGp8dK4tjvieQaKC11AfWmqMdn5LQ2HWqAxMzLCs8KkN2yS8EQjWgX9qJo+P7lJ1YIoUd7YPj+W 0k7fI6WSJXKGJThuiqxcYXw4tUEdeywizOVnV5OzjXuEWTN51SAl8Yv1U80LMpVYO0f/mdMb824 ZdOQHySPfqgycW1vC4aPpD56kFNtXdYDgOai5veVKNLuPo6ZJqU+k= X-Received: by 2002:a17:903:2c04:b0:2ae:aa16:acf7 with SMTP id d9443c01a7336-2b0b0ad656fmr89027405ad.40.1774537679761; Thu, 26 Mar 2026 08:07:59 -0700 (PDT) Received: from DESKTOP-82PPU4A.localdomain ([202.8.116.170]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2b0bc8bb5fasm33146375ad.59.2026.03.26.08.07.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 26 Mar 2026 08:07:59 -0700 (PDT) From: Ujjal Roy To: "David S . Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Nikolay Aleksandrov , Ido Schimmel , David Ahern Cc: Ujjal Roy , bridge@lists.linux.dev, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 2/4] ipv6: mld: rename mldv2_mrc() and add mldv2_qqi() Date: Thu, 26 Mar 2026 15:07:40 +0000 Message-ID: <20260326150742.50289-3-royujjal@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260326150742.50289-1-royujjal@gmail.com> References: <20260326150742.50289-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 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. Added by e3f5b1704 ("net: ipv6: mld: get rid of MLDV2_MRC and simplify calc= ulation"). Signed-off-by: Ujjal Roy --- include/net/mld.h | 64 +++++++++++++++++++++++++++++++++------ net/bridge/br_multicast.c | 2 +- net/ipv6/mcast.c | 19 ++---------- 3 files changed, 58 insertions(+), 27 deletions(-) diff --git a/include/net/mld.h b/include/net/mld.h index c07359808493..6373eb76efe5 100644 --- a/include/net/mld.h +++ b/include/net/mld.h @@ -89,29 +89,73 @@ 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) +#define MLD_QQIC_MIN_THRESHOLD 128 +#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) -{ - /* RFC3810, 5.1.3. Maximum Response Code */ - unsigned long ret, mc_mrc =3D ntohs(mlh2->mld2q_mrc); +/* V2 exponential field decoding */ =20 - if (mc_mrc < MLD_EXP_MIN_LIMIT) { - ret =3D mc_mrc; +/* Calculate Maximum Response Delay from Maximum Response Code + * + * RFC3810, 5.1.3. 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) + */ +static inline unsigned long mldv2_mrd(const struct mld2_query *mlh2) +{ + /* RFC3810, relevant sections: + * - 5.1.3. Maximum Response Code + * - 9.3. Query Response Interval + */ + unsigned long mc_mrc =3D ntohs(mlh2->mld2q_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, 5.1.9. defines the decoding formula: + * 0 1 2 3 4 5 6 7 + * +-+-+-+-+-+-+-+-+ + * |1| exp | mant | + * +-+-+-+-+-+-+-+-+ + * QQI =3D (mant | 0x10) << (exp + 3) + */ +static inline unsigned long mldv2_qqi(const struct mld2_query *mlh2) +{ + /* RFC3810, relevant sections: + * - 5.1.9. QQIC (Querier's Query Interval Code) + * - 9.2. Query Interval + * - 9.12. Older Version Querier Present Timeout + * (the [Query Interval] in the last Query received) + */ + unsigned long qqic =3D ntohs(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 Thu Apr 2 20:26:36 2026 Received: from mail-pl1-f170.google.com (mail-pl1-f170.google.com [209.85.214.170]) (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 2F7E7402440 for ; Thu, 26 Mar 2026 15:08:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.170 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774537688; cv=none; b=TafomexN3oN+wEUVICu/CEQJtTc0RlFO+JaFsEwZ8C7cMQQgq2SUM0q4/yh/Rbi0uULzO2gI6LUb1jiMwC1afWHzuQX6ThAY36f4o6sjzX9hG0egsBq0vPDbrmrLrayXoYCnvlFQsr9KkRzU5qRDhq92dK2iX0JBw7NKbJtTi04= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774537688; c=relaxed/simple; bh=SrJ8v2JXUP4BQ/htK1TW22nfXu8yKqHl2EOzmrry8MI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=kwlbRaGbZQ6A8a9PIPRpJnobUNUqImVMDJmSrUYcLTv3gE347u8VLbV+N+Ks3WkEB/cjbqehiJY1slJCWdllDGCRDmsNfo4mGgbUrElcql4fTLXUvTRgkzp42vrP241IZ5Qo3vuEWwcgxliM8mzSA/VKm2HK9y44GOFZqUDDwgM= 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=K8JmEa61; arc=none smtp.client-ip=209.85.214.170 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="K8JmEa61" Received: by mail-pl1-f170.google.com with SMTP id d9443c01a7336-2adff872068so4538565ad.1 for ; Thu, 26 Mar 2026 08:08:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1774537684; x=1775142484; 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=htKXcnTzcKDeqjMpn8hCX3YfwiSQQ8z5MdKwPZHhth8=; b=K8JmEa61X/hHCAZKr8D26W7Ag72I8qjEWApS1FeDkX9VBEY06XBpymHYLnAFhyOts3 feb1Vzo8gPs0WLQ50hutkkV1KbGsDRf2oHLt85BUj0fOu/+kAebZeaCOh5yyrnIAasEA tyeAut7Fu/ZHMAHJm/Mk1lNFLECxLy1BCn1/g/dBTVHiE5C23CEgbHvX3o1ZiSUDaSkC +8uG4JbzNPu6yCBautg0VRFTLg66jqLFOwXRe9V+btCYxCXgtJe8m9v7FQhhI12IOqC/ AXrMKLJSqUSNcDSBvCOYpRpXwAnvUZGkamVQEDSdYNFnN0y1t9VVlmTrRD4kDVUYCLmg f08A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1774537684; x=1775142484; 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=htKXcnTzcKDeqjMpn8hCX3YfwiSQQ8z5MdKwPZHhth8=; b=sZCvWJhmi6n1SAbrumwmNW9hYfRkiccdsaqW0wGNlZ2UXvuuBaOO5mqRMAG5sa2/81 JJn1nRcdiCux/8mDRFBkdg3W3/89iI3wPyUcZw83xGHAnuU2H6x5fTr+dR2GZDXLiBP6 qAEd530XQGISFbYLDwY2hH2yTL2Y0mbTVrvtnMTFodqHhXJKa/4x5trOevafpGdNZY7p A83RsrlMLz9dii1c6G6OnhuqkSeG8PcFWQbEc5/3Ztj1FW99Sll2raxmSz54n8pBoPdD Wl5fo6qUYgAHHAGN5enZNl1RWgjnNgflmrr8XEKXfdP1LGPDhdcxarZJQ7MDBNaZEzIr 5ZRA== X-Forwarded-Encrypted: i=1; AJvYcCUNo0pqPBhelL4sn7sD4HhHjNAYjZNOVfkPl2EsRIPen+GFccPzEqKjeX0K2lOkq62EYmbF5Zgq3YDl9xg=@vger.kernel.org X-Gm-Message-State: AOJu0Yy4FeoLk7TaxpCjwcjXa/Ob74Qcxsy+3ofzs0JHLrXExO/RwAP0 gBq96oB6JdMvBTlRTcX5S+HMPodBoCIjD1YVwAKkLwTqiz6bXB2Bu6Mv X-Gm-Gg: ATEYQzwsYWyQlchYayUihtzTjGfIWwTqt5fHBkG4m+YF79SgwFstp+m9Ag/DF/ganr0 Gpq99D/h/Z66mT1hKkdyMJEN1BsuM2zi24WG4CoHBJme4IPDxalOTa+zxRQVi7+xe3Ms1HKP7eB eSluA05LGdcR+dMWp93htXEPPlQGWwmy0hl0AXMLNpeBnlFoQ57/SUAyqPy8FDAzLVw523OPn1A eVP8fJ6G3sU9hkjEECpLxgQoprZn43WrsGRVD3JOhltNnj8tSPqrtiZnbjyr73A258Scveesknj FOSYVPO42/8eltHjSiW+ki5X0dFPYPsJukMR4lXYXumXDnr2F0cZj2cgXOylNHade/RD6IwGCvD yAGKjjQQ/WBS7neGXcDusYS5vGvTuu38JLZQkKi3HUpqgP8DiKMyijKbdXiSlQiHZOsNAgUdEPy 60uBWIHmLrGKIhKBXdfgapv+VerzMkMcSLJji9S9Pl X-Received: by 2002:a17:903:3884:b0:2ae:5655:b16 with SMTP id d9443c01a7336-2b0b0a140d0mr86962365ad.21.1774537684401; Thu, 26 Mar 2026 08:08:04 -0700 (PDT) Received: from DESKTOP-82PPU4A.localdomain ([202.8.116.170]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2b0bc8bb5fasm33146375ad.59.2026.03.26.08.08.00 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 26 Mar 2026 08:08:03 -0700 (PDT) From: Ujjal Roy To: "David S . Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Nikolay Aleksandrov , Ido Schimmel , David Ahern Cc: Ujjal Roy , bridge@lists.linux.dev, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 3/4] ipv4: igmp: encode multicast exponential fields Date: Thu, 26 Mar 2026 15:07:41 +0000 Message-ID: <20260326150742.50289-4-royujjal@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260326150742.50289-1-royujjal@gmail.com> References: <20260326150742.50289-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, QQIC and MRC fields are not currently encoded when generating query packets. Since the receiver of the query interprets these fields using the IGMPv3 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 and MRC fields (8-bit) are properly encoded when transmitting query packets with intervals that exceed their respective linear threshold value of 128 (for QQI/MRT). RFC 3376: if QQIC/MRC >=3D 128, the QQIC/MRC field represents a floating-point value as follows: 0 1 2 3 4 5 6 7 +-+-+-+-+-+-+-+-+ |1| exp | mant | +-+-+-+-+-+-+-+-+ Signed-off-by: Ujjal Roy --- include/linux/igmp.h | 80 +++++++++++++++++++++++++++++++++++++++ net/bridge/br_multicast.c | 14 +++---- 2 files changed, 86 insertions(+), 8 deletions(-) diff --git a/include/linux/igmp.h b/include/linux/igmp.h index 3c12c0a63492..99fce6b0625f 100644 --- a/include/linux/igmp.h +++ b/include/linux/igmp.h @@ -110,6 +110,86 @@ struct ip_mc_list { =20 /* IGMPV3 floating-point exponential field threshold */ #define IGMPV3_EXP_MIN_THRESHOLD 128 +/* Max representable (mant =3D 0xF, exp =3D 7) -> 31744 */ +#define IGMPV3_EXP_MAX_THRESHOLD 31744 + +/* V3 exponential field encoding */ + +/* + * IGMPv3 QQIC/MRC 8-bit exponential field encode. + * + * RFC3376 defines only the decoding formula: + * QQI/MRT =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; + + /* RFC3376: QQIC/MRC < 128 is literal */ + if (value < IGMPV3_EXP_MIN_THRESHOLD) + return (u8)value; + + /* Saturate at max representable (mant =3D 0xF, exp =3D 7) -> 31744 */ + if (value >=3D IGMPV3_EXP_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; +} + +/* Calculate Maximum Response Code from Max Resp Time */ +static inline u8 igmpv3_mrc(unsigned long mrt) +{ + /* RFC3376, relevant sections: + * - 4.1.1. Maximum Response Code + * - 8.3. Query Response Interval + */ + return igmpv3_exp_field_encode(mrt); +} + +/* Calculate Querier's Query Interval Code from Query Interval */ +static inline u8 igmpv3_qqic(unsigned long qi) +{ + /* 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) + */ + 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..1de6242413e0 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -939,7 +939,7 @@ static struct sk_buff *br_ip4_multicast_alloc_query(str= uct net_bridge_mcast *brm struct sk_buff *skb; struct igmphdr *ih; struct ethhdr *eth; - unsigned long lmqt; + unsigned long lmqt, mrt; 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 Thu Apr 2 20:26:36 2026 Received: from mail-pl1-f181.google.com (mail-pl1-f181.google.com [209.85.214.181]) (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 C32A7402B8F for ; Thu, 26 Mar 2026 15:08:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.181 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774537691; cv=none; b=DyDsVriQy1nCOHQDDI1akRlbXf4B1jSvf4MvV1WWp8s6FJqLJAnxfSgOPdMebc2JwvDHQFeUlX0EsnCZzZAa667wtJEn7jVL16W3G0+PqC+iYveRToNQBHphDkFH2mo/B3Ja3uB3AtX78JUcDiXsiHIUGj3fXzDw9eoSzOyg4dc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774537691; c=relaxed/simple; bh=e55NJdo7/A3hpAJ6kxWohOaV0421uYsdnSxjy1Zm6Lw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=BVnKtGQ6/QUVmdWJgei6TsluBOOiGdltLNYpaaQ+ETghzV0FVV+wsGhJtlmjjJqaJIzSneRqY/Qr0pmcJdz7N4hroBDHv7F2Wd/vHXSFbrGogC2W6Sk7MXDjkFIuBijKPCB8j2tDzpk2qXrR0rcx9yuS+b/bBVRTnuRqPktG/70= 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=qHNMVPpp; arc=none smtp.client-ip=209.85.214.181 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="qHNMVPpp" Received: by mail-pl1-f181.google.com with SMTP id d9443c01a7336-2ad21f437eeso6673745ad.0 for ; Thu, 26 Mar 2026 08:08:09 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1774537689; x=1775142489; 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=49SPRabqR++4MRXv28bpRM0Zk1UkXQGuUNet1+Gr+HM=; b=qHNMVPppwIw4iacGM9wz+nuvNkEeCyPFWyMCMRLLvEC30sfUx+we9o+bVtjnk5xwA4 8zV0W65CevKwWTOP9nK9uiUYnoFzcfLSrKEx2mb5iXqCEdP1eWuAZEYy9itKh5LEZvY7 s1jnUxomVf+Jinjn4y2fOmWFpnh477rqNk711ugMO4HYYdWmxzpaaLszJi/WGOmLp7Lm B4yrhgqYGapGhb3RABoVSUq+us94syegHls927D82Sbnm6N/1a9DKmiDFhnmGKu2Jqv5 wVWEBZYLkJo2+PXlu8+AqnOBX1+hD1BJvxiIi37Dm1ktduxiIRhH/x4pwfTYEJ2GZNx+ Q0+w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1774537689; x=1775142489; 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=49SPRabqR++4MRXv28bpRM0Zk1UkXQGuUNet1+Gr+HM=; b=Huohc9T4Sy0T0gYC4ue6gwFbGy4GHrZNyf8x0k5zIBfwvent8mKi9VPi4kYogfyGp4 8ygjCUyCo9ALhGXFYWCd6bFsW6S9p+Pr4/Y1u3y8Le2E4cwrIAc0YRlBY/cLOZNW18Xi lXVb5qqAIhpOfYfPUx9jQrdNDzIZQxKxSIePCsEDuQCmhtW7ZJhN95+EIzS3bYQEGITS zzhPXGi/PbJSB4nwXOtTTaqVjFmaWTeSEB9wDbYqaW8BKP2+sNG9kqVu+ac6m7+sh3NJ HopCtf3IXhvAZh4uKA2JSsd7w5vSuLf0GQ4aUMUfOTUrz7dSIghCKhzUn7etkC4FUw3x vBdQ== X-Forwarded-Encrypted: i=1; AJvYcCWYLa2y+ruM3u97MbXptsgZCOsB8CaBeAcLohw0hkyE0EvPU1BE3BFjn4JJ2Ou8XO7X4sM/AnavHPK4PdI=@vger.kernel.org X-Gm-Message-State: AOJu0Yy2aWGOmvTzBogG1zUKon+tCgpx5eZjkQmBKpBF1uvrCImocHKU 7+WRmmQAJAJaA/n5b9GSafZc2RksIzOuMYi1AldEhIin0UMFgs5UAtn+ X-Gm-Gg: ATEYQzyxiIp+tjhplY0V+17LgLbBZNcZdQs8GjxmVwKzWuSa7WxQBL0pjfc+bSLAmep eipzOr4MOAStaTZ6NcS2PFzc2iqsjWxS8MszQQGZXqDe04UMIDOEhTeJ1p59N5F3QEGXG7jE/YR Ex9h/PTx0VZomOjQRkYNwTLhNq2xZ9fTl8TgbTjiFpey/CFluRe4oad9MNr2duHuVUUXlboPsHF Nk2cMLljhBKOqeiWRXflsM12gt37wJ8xCd4ddjXFW+bcHrBblPx+/4IrZIjtogP53p2/5YVVCOD hxfV0WuPPXleAHB+OouwXPr4h2gdca9lyeXGn7PwZOoNRh07MlMfXlb4V2DwW9hXCrBHLOATigw /d7m9MXalaoc1wQsWH1A1quZNBlUTVXC1/J02ExmZ6JbUKWzqny6fDpq0nyfqrRn7U2fMt+VTeR nfAiCJm0yUuhQloVSHq+Pm6FkcJ5BIK/DkDPo9E3KmsxNloPC7dns= X-Received: by 2002:a17:902:f712:b0:2b0:ba48:274 with SMTP id d9443c01a7336-2b0c4818b3cmr20475495ad.1.1774537689063; Thu, 26 Mar 2026 08:08:09 -0700 (PDT) Received: from DESKTOP-82PPU4A.localdomain ([202.8.116.170]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2b0bc8bb5fasm33146375ad.59.2026.03.26.08.08.04 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 26 Mar 2026 08:08:08 -0700 (PDT) From: Ujjal Roy To: "David S . Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Nikolay Aleksandrov , Ido Schimmel , David Ahern Cc: Ujjal Roy , bridge@lists.linux.dev, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 4/4] ipv6: mld: encode multicast exponential fields Date: Thu, 26 Mar 2026 15:07:42 +0000 Message-ID: <20260326150742.50289-5-royujjal@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260326150742.50289-1-royujjal@gmail.com> References: <20260326150742.50289-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 6373eb76efe5..0962312d29b9 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 1de6242413e0..c59dab6fff4e 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