mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Yiming Qian <yimingqian591@gmail.com>
To: Nikolay Aleksandrov <razor@blackwall.org>,
	Ido Schimmel <idosch@nvidia.com>
Cc: "David S . Miller" <davem@davemloft.net>,
	Eric Dumazet <edumazet@google.com>,
	Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,
	Simon Horman <horms@kernel.org>,
	bridge@lists.linux.dev, netdev@vger.kernel.org,
	linux-kernel@vger.kernel.org,
	Yiming Qian <yimingqian591@gmail.com>
Subject: [PATCH net] net: bridge: don't under-estimate the VLAN tunnel info size
Date: Wed,  7 Oct 2026 05:59:37 +0000	[thread overview]
Message-ID: <20261007055939.63100-1-yimingqian591@gmail.com> (raw)

br_info_notify() sizes the notification skb with br_nlmsg_size() and then
fills it with br_fill_ifinfo().  If the fill does not fit, br_info_notify()
does WARN_ON(err == -EMSGSIZE) because that is supposed to mean a bug in
br_nlmsg_size().

br_nlmsg_size() (via br_get_link_af_size_filtered() and
br_get_vlan_tunnel_info_size()) only accounts for the VLANs that have a
tunnel mapping at that moment, while br_fill_vlan_tunnel_info() emits an
attribute for every VLAN that has one by the time it runs.  br_info_notify()
also runs without RTNL (e.g. from br_forward_delay_timer_expired()), so
tunnel mappings added or removed under RTNL between the size calculation and
the fill make the fill need more room than was reserved:

  WARNING: net/bridge/br_netlink.c:660 at br_info_notify+0x13f/0x150
  ...
  Call Trace:
   <IRQ>
   br_forward_delay_timer_expired+0x1b3/0x1f0
   call_timer_fn+0x2d/0xd0
   __run_timer_base+0x5ba/0x7d0
   run_timer_softirq+0x31/0x60
   handle_softirqs+0x17f/0x570
  ...
  Kernel panic - not syncing: kernel: panic_on_warn set ...

Size the tunnel info for the maximum number of attributes that
br_fill_vlan_tunnel_info() can emit for the VLAN group instead of for the
mappings that are currently installed.  Consecutive VIDs with consecutive
tunnel IDs are compressed into two attributes, so the fill never emits more
attributes than there are usable VLANs, which keeps br_nlmsg_size() an upper
bound of what the fill needs.

Fixes: efa5356b0d97 ("bridge: per vlan dst_metadata netlink support")
Cc: Yiming Qian <yimingqian591@gmail.com>
Signed-off-by: Yiming Qian <yimingqian591@gmail.com>
---
 net/bridge/br_netlink_tunnel.c | 44 ++++++++++++----------------------
 1 file changed, 15 insertions(+), 29 deletions(-)

diff --git a/net/bridge/br_netlink_tunnel.c b/net/bridge/br_netlink_tunnel.c
index e7eceab5b515d..74627323711c1 100644
--- a/net/bridge/br_netlink_tunnel.c
+++ b/net/bridge/br_netlink_tunnel.c
@@ -35,39 +35,25 @@ bool vlan_tunid_inrange(const struct net_bridge_vlan *v_curr,
 	return (be32_to_cpu(tunid_curr) - be32_to_cpu(tunid_last)) == 1;
 }
 
-static int __get_num_vlan_tunnel_infos(struct net_bridge_vlan_group *vg)
+/* Upper bound of the number of IFLA_BRIDGE_VLAN_TUNNEL_INFO attributes that
+ * br_fill_vlan_tunnel_info() can emit for @vg.
+ *
+ * br_info_notify() is also called without RTNL (e.g. from the STP timers), so
+ * the set of VLANs that have a tunnel mapping can change between the size
+ * calculation done by br_nlmsg_size() and the actual fill.  Account for the
+ * maximum instead of the currently used mappings: consecutive VIDs with
+ * consecutive tunnel IDs are compressed into two attributes, so the fill never
+ * emits more attributes than there are usable VLANs in the group.
+ */
+static int __get_max_num_vlan_tunnel_infos(struct net_bridge_vlan_group *vg)
 {
-	struct net_bridge_vlan *v, *vtbegin = NULL, *vtend = NULL;
+	struct net_bridge_vlan *v;
 	int num_tinfos = 0;
 
-	/* Count number of vlan infos */
 	list_for_each_entry_rcu(v, &vg->vlan_list, vlist) {
 		/* only a context, bridge vlan not activated */
-		if (!br_vlan_should_use(v) || !v->tinfo.tunnel_id)
-			continue;
-
-		if (!vtbegin) {
-			goto initvars;
-		} else if ((v->vid - vtend->vid) == 1 &&
-			   vlan_tunid_inrange(v, vtend)) {
-			vtend = v;
-			continue;
-		} else {
-			if ((vtend->vid - vtbegin->vid) > 0)
-				num_tinfos += 2;
-			else
-				num_tinfos += 1;
-		}
-initvars:
-		vtbegin = v;
-		vtend = v;
-	}
-
-	if (vtbegin && vtend) {
-		if ((vtend->vid - vtbegin->vid) > 0)
-			num_tinfos += 2;
-		else
-			num_tinfos += 1;
+		if (br_vlan_should_use(v))
+			num_tinfos++;
 	}
 
 	return num_tinfos;
@@ -81,7 +67,7 @@ int br_get_vlan_tunnel_info_size(struct net_bridge_vlan_group *vg)
 		return 0;
 
 	rcu_read_lock();
-	num_tinfos = __get_num_vlan_tunnel_infos(vg);
+	num_tinfos = __get_max_num_vlan_tunnel_infos(vg);
 	rcu_read_unlock();
 
 	return num_tinfos * __get_vlan_tinfo_size();
-- 
2.34.1


             reply	other threads:[~2026-10-07  5:59 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-07  5:59 Yiming Qian [this message]
2026-10-07  6:04 ` netdev-bot+sinfo
2026-10-07 14:35 ` Ido Schimmel

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261007055939.63100-1-yimingqian591@gmail.com \
    --to=yimingqian591@gmail.com \
    --cc=bridge@lists.linux.dev \
    --cc=davem@davemloft.net \
    --cc=edumazet@google.com \
    --cc=horms@kernel.org \
    --cc=idosch@nvidia.com \
    --cc=kuba@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    --cc=razor@blackwall.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®