Received: by 2002:a05:7412:3290:b0:fa:6e18:a558 with SMTP id ev16csp662134rdb; Fri, 26 Jan 2024 07:08:26 -0800 (PST) X-Google-Smtp-Source: AGHT+IG9R31+Db9gWj7kPyn3oqhVwn8rNGKw0i8ifuGeW/KhYvZ8DtgfDtdAuPBvI0feL7uZpQZf X-Received: by 2002:a17:903:11d2:b0:1d5:f36c:8740 with SMTP id q18-20020a17090311d200b001d5f36c8740mr1536700plh.44.1706281706133; Fri, 26 Jan 2024 07:08:26 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1706281705; cv=pass; d=google.com; s=arc-20160816; b=HRsekQqjCPBQEDeClmE8YD5ogrNBujrw7yeOIrz8kP9JNmx5IOFujB5gqcb4cB3Crw D0RBTij4l49IXTa6lnWbtJZhEXqFgyP/1F1gSS/DPegU87PKWs1weOE/1bnRYhY11hcb v1DUl2NiMJL15JiBcbGASnS4V/LYlNANl6iQsKsw8jILCPz0FH9NMJ/PXT5ym+7CxnWw YBwjqf12V1B5HHf8z83oQyHXNBR6nZJTRao/sZUWKzSIFiwIS9E19ZpdLN4y20ghZ04O SHbwn2x036H2V7SAn+gwJ43WyE9nix72ufJLjh9KT91OGczad6bvU9+wheiMBNDH0v4H FrOg== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:message-id:date:subject:cc:to :from; bh=YSh0pxawl9jn40E6SdFZFc6giUIchWJMmV6FLhrYGIM=; fh=zuk+c/ZrZxgyvUkmbeHtOb7SdaA6SHoBcUW1Rm22yzI=; b=TTfSsCohtbCIJHrz+bDPBTItyTpZHSth9kkR202Ks+SmY9uKztc7nMnn/umbF2r2Ab fdfP+OBS+c+jvmA6WypyMdWRDltZwnJd/e/hMEL16gmLxnoTZlZzCtsz31+x4kqJwkCN W3fx8wBp6h1vsLb1XYIM8LWeccMT+WdP5q/AVDcuXbqf5HLeZqybsA/VsEVs2EZJkhZj pLinMfjZ5HEw7CDtrivxSJTQDOxJXNSlOHZFaXeUUtAPXxu7Mx1RKmhZIZvVs6l1M6Gu HvgBfXYF+MYBPuYVCdm8qW921/xUIIxr+xhQ+WRvMseusJ47x/LVNr5/GMe1dOVEpWsi VQyA== ARC-Authentication-Results: i=2; mx.google.com; arc=pass (i=1 spf=pass spfdomain=c0d3.blue); spf=pass (google.com: domain of linux-kernel+bounces-40221-linux.lists.archive=gmail.com@vger.kernel.org designates 147.75.48.161 as permitted sender) smtp.mailfrom="linux-kernel+bounces-40221-linux.lists.archive=gmail.com@vger.kernel.org" Return-Path: Received: from sy.mirrors.kernel.org (sy.mirrors.kernel.org. [147.75.48.161]) by mx.google.com with ESMTPS id z11-20020a170902834b00b001d750613651si1221906pln.203.2024.01.26.07.08.24 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 26 Jan 2024 07:08:25 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-40221-linux.lists.archive=gmail.com@vger.kernel.org designates 147.75.48.161 as permitted sender) client-ip=147.75.48.161; Authentication-Results: mx.google.com; arc=pass (i=1 spf=pass spfdomain=c0d3.blue); spf=pass (google.com: domain of linux-kernel+bounces-40221-linux.lists.archive=gmail.com@vger.kernel.org designates 147.75.48.161 as permitted sender) smtp.mailfrom="linux-kernel+bounces-40221-linux.lists.archive=gmail.com@vger.kernel.org" Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sy.mirrors.kernel.org (Postfix) with ESMTPS id DB954B2481C for ; Fri, 26 Jan 2024 14:45:40 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 25F9C1D524; Fri, 26 Jan 2024 14:45:01 +0000 (UTC) Received: from mail.aperture-lab.de (mail.aperture-lab.de [116.203.183.178]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 820911CF8B; Fri, 26 Jan 2024 14:44:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=116.203.183.178 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706280300; cv=none; b=FKFmztut/kZ18CV6ETVyaEC34FaYvUQoK6TrdzwIg91aN3PiyuUrd5XuaMEZH6ZIuhieilQh8HWVbGxh5hQ1PenZHr1y6UGJdcx3MatZkemB/KeD6BbRBPJcTOEH80p43llWZ7bk3Q77GXvTuf34Lo1jyaYo/QQUGy3rh2RcGdQ= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1706280300; c=relaxed/simple; bh=uHtepOo8gbOXT2LRNekmrAe1Ci4v1SSIgleK9lZ3iak=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version:Content-Type; b=Yd/wNtyr2sjnkD/29L34Udsqmw/M2hRvIVJtTJdKpTiA3foPe01to4lT4NgkaciDvf/aHCC3XiEkgC0hYBeSiO/Hn7UeuNdui71WIRoPqxUpkMwk+kFkRv7ljasVmWRcPDyvk/VXFHqorPkCzcnmPBGi04CXGFhk4uVeQiq+/vE= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=c0d3.blue; spf=pass smtp.mailfrom=c0d3.blue; arc=none smtp.client-ip=116.203.183.178 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=c0d3.blue Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=c0d3.blue Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id 25D5040B8F; Fri, 26 Jan 2024 15:36:37 +0100 (CET) From: =?UTF-8?q?Linus=20L=C3=BCssing?= To: netdev@vger.kernel.org Cc: bridge@lists.linux.dev, b.a.t.m.a.n@lists.open-mesh.org, linux-kernel@vger.kernel.org, Roopa Prabhu , Nikolay Aleksandrov , "David S . Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , =?UTF-8?q?Linus=20L=C3=BCssing?= Subject: [PATCH net] bridge: mcast: fix disabled snooping after long uptime Date: Fri, 26 Jan 2024 15:36:07 +0100 Message-ID: <20240126143607.5649-1-linus.luessing@c0d3.blue> X-Mailer: git-send-email 2.42.0 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Last-TLS-Session-Version: TLSv1.3 The original idea of the delay_time check was to not apply multicast snooping too early when an MLD querier appears. And to instead wait at least for MLD reports to arrive before switching from flooding to group based, MLD snooped forwarding, to avoid temporary packet loss. However in a batman-adv mesh network it was noticed that after 248 days of uptime 32bit MIPS based devices would start to signal that they had stopped applying multicast snooping due to missing queriers - even though they were the elected querier and still sending MLD queries themselves. While time_is_before_jiffies() generally is safe against jiffies wrap-arounds, like the code comments in jiffies.h explain, it won't be able to track a difference larger than ULONG_MAX/2. With a 32bit large jiffies and one jiffies tick every 10ms (CONFIG_HZ=100) on these MIPS devices running OpenWrt this would result in a difference larger than ULONG_MAX/2 after 248 (= 2^32/100/60/60/24/2) days and time_is_before_jiffies() would then start to return false instead of true. Leading to multicast snooping not being applied to multicast packets anymore. Fix this issue by using a proper timer_list object which won't have this ULONG_MAX/2 difference limitation. Fixes: b00589af3b04 ("bridge: disable snooping if there is no querier") Signed-off-by: Linus Lüssing --- net/bridge/br_multicast.c | 20 +++++++++++++++----- net/bridge/br_private.h | 4 ++-- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index d7d021af1029..df14ee36ea20 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -1762,6 +1762,10 @@ static void br_ip6_multicast_querier_expired(struct timer_list *t) } #endif +static inline void br_multicast_query_delay_expired(struct timer_list *t) +{ +} + static void br_multicast_select_own_querier(struct net_bridge_mcast *brmctx, struct br_ip *ip, struct sk_buff *skb) @@ -3198,7 +3202,7 @@ br_multicast_update_query_timer(struct net_bridge_mcast *brmctx, unsigned long max_delay) { if (!timer_pending(&query->timer)) - query->delay_time = jiffies + max_delay; + mod_timer(&query->delay_timer, jiffies + max_delay); mod_timer(&query->timer, jiffies + brmctx->multicast_querier_interval); } @@ -4041,13 +4045,11 @@ void br_multicast_ctx_init(struct net_bridge *br, brmctx->multicast_querier_interval = 255 * HZ; brmctx->multicast_membership_interval = 260 * HZ; - brmctx->ip4_other_query.delay_time = 0; brmctx->ip4_querier.port_ifidx = 0; seqcount_spinlock_init(&brmctx->ip4_querier.seq, &br->multicast_lock); brmctx->multicast_igmp_version = 2; #if IS_ENABLED(CONFIG_IPV6) brmctx->multicast_mld_version = 1; - brmctx->ip6_other_query.delay_time = 0; brmctx->ip6_querier.port_ifidx = 0; seqcount_spinlock_init(&brmctx->ip6_querier.seq, &br->multicast_lock); #endif @@ -4056,6 +4058,8 @@ void br_multicast_ctx_init(struct net_bridge *br, br_ip4_multicast_local_router_expired, 0); timer_setup(&brmctx->ip4_other_query.timer, br_ip4_multicast_querier_expired, 0); + timer_setup(&brmctx->ip4_other_query.delay_timer, + br_multicast_query_delay_expired, 0); timer_setup(&brmctx->ip4_own_query.timer, br_ip4_multicast_query_expired, 0); #if IS_ENABLED(CONFIG_IPV6) @@ -4063,6 +4067,8 @@ void br_multicast_ctx_init(struct net_bridge *br, br_ip6_multicast_local_router_expired, 0); timer_setup(&brmctx->ip6_other_query.timer, br_ip6_multicast_querier_expired, 0); + timer_setup(&brmctx->ip6_other_query.delay_timer, + br_multicast_query_delay_expired, 0); timer_setup(&brmctx->ip6_own_query.timer, br_ip6_multicast_query_expired, 0); #endif @@ -4197,10 +4203,12 @@ static void __br_multicast_stop(struct net_bridge_mcast *brmctx) { del_timer_sync(&brmctx->ip4_mc_router_timer); del_timer_sync(&brmctx->ip4_other_query.timer); + del_timer_sync(&brmctx->ip4_other_query.delay_timer); del_timer_sync(&brmctx->ip4_own_query.timer); #if IS_ENABLED(CONFIG_IPV6) del_timer_sync(&brmctx->ip6_mc_router_timer); del_timer_sync(&brmctx->ip6_other_query.timer); + del_timer_sync(&brmctx->ip6_other_query.delay_timer); del_timer_sync(&brmctx->ip6_own_query.timer); #endif } @@ -4643,13 +4651,15 @@ int br_multicast_set_querier(struct net_bridge_mcast *brmctx, unsigned long val) max_delay = brmctx->multicast_query_response_interval; if (!timer_pending(&brmctx->ip4_other_query.timer)) - brmctx->ip4_other_query.delay_time = jiffies + max_delay; + mod_timer(&brmctx->ip4_other_query.delay_timer, + jiffies + max_delay); br_multicast_start_querier(brmctx, &brmctx->ip4_own_query); #if IS_ENABLED(CONFIG_IPV6) if (!timer_pending(&brmctx->ip6_other_query.timer)) - brmctx->ip6_other_query.delay_time = jiffies + max_delay; + mod_timer(&brmctx->ip6_other_query.delay_timer, + jiffies + max_delay); br_multicast_start_querier(brmctx, &brmctx->ip6_own_query); #endif diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index b0a92c344722..86ea5e6689b5 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -78,7 +78,7 @@ struct bridge_mcast_own_query { /* other querier */ struct bridge_mcast_other_query { struct timer_list timer; - unsigned long delay_time; + struct timer_list delay_timer; }; /* selected querier */ @@ -1159,7 +1159,7 @@ __br_multicast_querier_exists(struct net_bridge_mcast *brmctx, own_querier_enabled = false; } - return time_is_before_jiffies(querier->delay_time) && + return !timer_pending(&querier->delay_timer) && (own_querier_enabled || timer_pending(&querier->timer)); } -- 2.43.0