From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-wr2-f12.google.com (mail-wr2-f12.google.com [74.125.225.76]) (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 D2D6F46EC69 for ; Mon, 28 Sep 2026 07:53:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.225.76 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790581993; cv=none; b=FpCqv35Kb8D+gu4qiU2SwZmaLmKXSXMiOWktpqAW9XhFdL425mQ0W8WVeQt20IQKwZdz+MioWQWSGbndwf8FdUYdt0UvMBwNJ+fINcZJM/BhzYleQC+9HiT7g5BFYLin5gkgOiho9CWETEigDoIko+IOrTTpStWFyl2ORRaoxa4= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790581993; c=relaxed/simple; bh=aA/zrPMspakEuvzH3RaiPDVitAjjOTzjf/L/Kpmyf0I=; h=Message-ID:Date:MIME-Version:Subject:To:Cc:References:From: In-Reply-To:Content-Type; b=MA5bZWbuHU36lmhgemkCu/xl4un2kqDWsP3RgGbVpJarItH/pwEUJOtGiAk38oWvBmUjDYKLAv+MSGNPTqGfgLHwnjyr3Lhr664M5iFgZnWgcQ/qHUSNL3iWH1ooUQ9i4pCjpU/9svbd4nTuKZeA3O3aIQD6VR6cW0DY6ClsWdA= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=6wind.com; spf=pass smtp.mailfrom=6wind.com; dkim=pass (2048-bit key) header.d=6wind.com header.i=@6wind.com header.b=jFJ+16CF; arc=none smtp.client-ip=74.125.225.76 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=6wind.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=6wind.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=6wind.com header.i=@6wind.com header.b="jFJ+16CF" Received: by mail-wr2-f12.google.com with SMTP id ffacd0b85a97d-48436686a40so307949f8f.3 for ; Mon, 28 Sep 2026 00:53:10 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=6wind.com; s=google; t=1790581989; x=1791186789; darn=vger.kernel.org; h=content-transfer-encoding:content-type:in-reply-to:organization :content-language:from:references:cc:to:subject:reply-to:user-agent :mime-version:date:message-id:from:to:cc:subject:date:message-id :reply-to:content-type; bh=BF10bhz/UbdNdYSJY9TUFjfFC06TQP6+N+yfVQ0ryuw=; b=jFJ+16CFM+jjpt2BWFeCO0quo16TnjakV33xfGKLyK/hjPepDAD0KA0xNzxQi+Us72 jQVCm+wnHpKDbXX5oGaU+FSTNaSMk6fmEvZqLQdtxoJWUTol0NvVJbSzlV5Hu/aL4LPT DiTdbnzeISIkNohNqdaYaHHc29U3qdP3oLmv+sz0Vdy3qhEjbMls5wjGibT9UH9bVGtL aDwFnm2fBF9/GdwWAJGp2z1j9Oi3lAcH0Cky89rXK2yKmsn/ziBVKd+w+GUWgxjHlWBr quwHEC79+TfhQRf3934ZIIpEC3CDg2bnKgPfH3VEkTMANujdjmaE0VQeK5MtUTFO75XB d+sA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1790581989; x=1791186789; h=content-transfer-encoding:content-type:in-reply-to:organization :content-language:from:references:cc:to:subject:reply-to:user-agent :mime-version:date:message-id:x-gm-gg:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to:content-type; bh=BF10bhz/UbdNdYSJY9TUFjfFC06TQP6+N+yfVQ0ryuw=; b=e9/ZuwFZI5xjLynYvSEF+QL64Qh0nZsPeQzODkAfDZ0HUAbW3ExDhkK4Sc8+WkUGhs 4gPQD3toVF1sJe0+oyzmpgdIFjlDcPr3Z0Nbf+ppM7KH9doO6EWC9186gxpnvTlqbDr6 H2vkW5QHKfcJN4rdPIMEU1dxW/B9VusO3ZRP57eYimfyKf8i8MW5h7jTWAbXZEFB3yyn Z7a+mnlkYE02uWQZmrel8xFmxbZUWspgAiPELjQtnFyTIYRWKj8/F3hJbJOpwkGMaHj2 U2PI5iqFuypKYuIsXKP7oZwCLU0+E+vQkJnkLaFSFJ31YGLdAseEeEPGFYPDGOYR1EUN 9DjA== X-Forwarded-Encrypted: i=1; AKwUvBwG6B2O6+YK48CFEi0Rz83wxclB/NmXUIZI5hA1rR3PFy3Zkyqy+HlYDgbI4iF0CcIPzoRYaUoBzFSExOo=@vger.kernel.org X-Gm-Message-State: AFuF++l71/a2L8pEwuXLKTK1ZRr/PRzV1w5J6ipev/Y0VCvWcDMtNax9 15OvkYYu0M51oKXL/3QsH+bG9vvcH80RFnS19Z/POaaV5hkTxIhmzkw7qbyaxCUFIfg= X-Gm-Gg: AYBFou1WBbvPKN5ZoND+Dz9AKVBRD3C2mTKHj0sGpCzJUQ7KFEw0x3Nwc7IJ5NgAD7O dZwmasO0jtVbD0FtS+LTLtk94kr+eNIPgQpLkHUJTiQyGIq1gWtuwjKlEEd+mr8T1+jwztbyuHC AG9+cyNgKGa/xzejtWnaVaQQzOBGNDDMnLkTBjRVhkRIKblrR54pTGSPKNVub+wMUgPD63jx0Iw 1RdlSUkwBg5G9Wpp0tye9fQ4x1FqysFko/X2Cxms4WF9FZurtTJ9dTd9GA5iFxFUj9Bl6CagDMS CgX2OXijw5uFR2ariKT1VVHcaFB1nkqj1F0dPKWxxZt/g7tJ/AOysM7fE6TEtnEqpwjtViN9qFl gMZ/hvSMw1kUrU6hi8G+OTUsZIDna8RONFfa1wnCnqsc5v2Zefa8WdF0a2AuEDUlltO20LkCESl iJUrRpp2IQq1EnzFOsnv2Zu77+fQCqeiwUlEh3oCxHHVHm8qH0xIxOdqJIxZ+xubyRMY6it03n7 //MTTQbJVbbav/KjWePHj39nDA9ZKeLPjCU+440Xh8xMbvW7lw= X-Received: by 2002:a05:600c:a414:b0:49f:ff2c:e0cf with SMTP id 5b1f17b1804b1-49fff2ce1a7mr66131745e9.0.1790581988608; Mon, 28 Sep 2026 00:53:08 -0700 (PDT) Received: from ?IPV6:2a01:e0a:ab7:2110:6a1d:efff:fe52:1959? ([2a01:e0a:ab7:2110:6a1d:efff:fe52:1959]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4a001922102sm122800265e9.15.2026.09.28.00.53.07 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Mon, 28 Sep 2026 00:53:08 -0700 (PDT) Message-ID: Date: Mon, 28 Sep 2026 09:53:07 +0200 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Reply-To: nicolas.dichtel@6wind.com Subject: Re: [PATCH net-next v8 2/5] net: add a generation counter for dev->mc changes To: Yuyang Huang Cc: Aleksandr Loktionov , Andrew Lunn , "David S. Miller" , David Ahern , Donald Hunter , Eric Dumazet , Ido Schimmel , Jacob Keller , Jakub Kicinski , Kuniyuki Iwashima , Nikolaos Gkarlis , Paolo Abeni , Sabrina Dubroca , Shuah Khan , Simon Horman , Stanislav Fomichev , Willem de Bruijn , linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, netdev@vger.kernel.org References: <20260927002427.4519-1-sigefriedhyy@gmail.com> <20260927002427.4519-3-sigefriedhyy@gmail.com> From: Nicolas Dichtel Content-Language: en-US Organization: 6WIND In-Reply-To: <20260927002427.4519-3-sigefriedhyy@gmail.com> Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Le 27/09/2026 à 02:24, Yuyang Huang a écrit : > A multi-part RTM_GETMULTICAST dump of dev->mc resumes by position, so > entries added or removed between two dump rounds can be skipped or > repeated. The IPv4 and IPv6 dumps report that with NLM_F_DUMP_INTR by > stamping cb->seq from a per netns generation counter combined with > dev_base_seq, see inet_base_seq(). > > Add the equivalent for the device multicast lists: a per netns counter > bumped whenever an entry is added to or removed from any dev->mc. The > list helpers do not know which device a list belongs to, so give > netdev_hw_addr_list an owner, set for the lists of a device and NULL > for snapshots and other standalone lists, and change list->count > through helpers that bump the counter of dev_net(owner) when the list > is dev->mc. That covers the dev_mc_* helpers, both lists of a sync, > the hardware sync helpers drivers call from their rx mode callbacks or > their own workers and the reconciliation after an asynchronous rx mode > update. It is atomic since the writers only hold the address lock of > their own device. > > Used by the following patch for the AF_PACKET multicast dump. > > Signed-off-by: Yuyang Huang If another version is needed, you can rename counter to _counter to highlight that the helpers should be used. > --- > include/linux/netdevice.h | 5 ++++ > include/net/net_namespace.h | 1 + > net/core/dev_addr_lists.c | 52 +++++++++++++++++++++++++++++++------ > 3 files changed, 50 insertions(+), 8 deletions(-) > > diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h > index d037faff7c44..69d1cde0a38a 100644 > --- a/include/linux/netdevice.h > +++ b/include/linux/netdevice.h > @@ -256,6 +256,11 @@ struct netdev_hw_addr_list { > > /* Auxiliary tree for faster lookup on addition and deletion */ > struct rb_root tree; > + > + /* The device a list belongs to, NULL for snapshots and other > + * standalone lists > + */ > + struct net_device *owner; > }; > > #define netdev_hw_addr_list_count(l) ((l)->count) > diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h > index 46b4c67e2966..d8c681ab5c74 100644 > --- a/include/net/net_namespace.h > +++ b/include/net/net_namespace.h > @@ -71,6 +71,7 @@ struct net { > spinlock_t rules_mod_lock; > > unsigned int dev_base_seq; /* protected by rtnl_mutex */ > + atomic_t dev_mc_genid; /* bumped on dev->mc changes */ > u32 ifindex; > > spinlock_t nsid_lock; > diff --git a/net/core/dev_addr_lists.c b/net/core/dev_addr_lists.c > index 08528ca0a8b3..c941c3ec1007 100644 > --- a/net/core/dev_addr_lists.c > +++ b/net/core/dev_addr_lists.c > @@ -16,6 +16,37 @@ > > #include "dev.h" > > +/* Only dev->mc is tracked, RTM_GETMULTICAST dumps use the netns generation > + * counter to detect changes between dump rounds. > + */ > +static void __hw_addr_changed(struct netdev_hw_addr_list *list) > +{ > + struct net_device *dev = list->owner; > + > + if (dev && list == &dev->mc) > + atomic_inc(&dev_net(dev)->dev_mc_genid); > +} > + > +static void __hw_addr_count_inc(struct netdev_hw_addr_list *list) static void __hw_addr_count_add(struct netdev_hw_addr_list *list, int value) > +{ > + list->count++; list->count += value;> + __hw_addr_changed(list); > +} #define __hw_addr_count_inc(l) __hw_addr_count_add(l, 1) > + > +static void __hw_addr_count_dec(struct netdev_hw_addr_list *list) > +{ > + list->count--; > + __hw_addr_changed(list); > +} > + > +static void __hw_addr_count_reset(struct netdev_hw_addr_list *list) > +{ > + if (!list->count) > + return; > + list->count = 0; > + __hw_addr_changed(list); > +} > + > /* > * General list handling functions > */ > @@ -125,7 +156,7 @@ static int __hw_addr_add_ex(struct netdev_hw_addr_list *list, > rb_insert_color(&ha->node, &list->tree); > > list_add_tail_rcu(&ha->list, &list->list); > - list->count++; > + __hw_addr_count_inc(list); > > return 0; > } > @@ -161,7 +192,7 @@ static int __hw_addr_del_entry(struct netdev_hw_addr_list *list, > > list_del_rcu(&ha->list); > kfree_rcu(ha, rcu_head); > - list->count--; > + __hw_addr_count_dec(list); > return 0; > } > > @@ -492,7 +523,7 @@ void __hw_addr_flush(struct netdev_hw_addr_list *list) > list_del_rcu(&ha->list); > kfree_rcu(ha, rcu_head); > } > - list->count = 0; > + __hw_addr_count_reset(list); > } > EXPORT_SYMBOL_IF_KUNIT(__hw_addr_flush); > > @@ -501,6 +532,7 @@ void __hw_addr_init(struct netdev_hw_addr_list *list) > INIT_LIST_HEAD(&list->list); > list->count = 0; > list->tree = RB_ROOT; > + list->owner = NULL; > } > EXPORT_SYMBOL(__hw_addr_init); For correctness, __hw_addr_splice() should use helper: @@ -509,8 +509,8 @@ static void __hw_addr_splice(struct netdev_hw_addr_list *dst, { src->tree = RB_ROOT; list_splice_init(&src->list, &dst->list); - dst->count += src->count; - src->count = 0; + __hw_addr_count_add(dst, src->count); + __hw_addr_count_reset(src); } Renaming struct netdev_hw_addr_list->count to _count would help to check all users and highlight that modifying _count should be done with helpers. > > @@ -536,7 +568,7 @@ int __hw_addr_list_snapshot(struct netdev_hw_addr_list *snap, > entry = list_first_entry(&cache->list, > struct netdev_hw_addr, list); > list_del(&entry->list); > - cache->count--; > + __hw_addr_count_dec(cache); > memcpy(entry->addr, ha->addr, addr_len); > entry->type = ha->type; > entry->global_use = false; > @@ -554,7 +586,7 @@ int __hw_addr_list_snapshot(struct netdev_hw_addr_list *snap, > > list_add_tail(&entry->list, &snap->list); > __hw_addr_insert(snap, entry, addr_len); > - snap->count++; > + __hw_addr_count_inc(snap); > } > > return 0; > @@ -604,14 +636,14 @@ void __hw_addr_list_reconcile(struct netdev_hw_addr_list *real_list, > if (delta > 0) { > rb_erase(&ref_ha->node, &ref->tree); > list_del(&ref_ha->list); > - ref->count--; > + __hw_addr_count_dec(ref); > ref_ha->sync_cnt = delta; > ref_ha->refcount = delta; > list_add_tail_rcu(&ref_ha->list, > &real_list->list); > __hw_addr_insert(real_list, ref_ha, > addr_len); > - real_list->count++; > + __hw_addr_count_inc(real_list); > } > continue; > } > @@ -622,7 +654,7 @@ void __hw_addr_list_reconcile(struct netdev_hw_addr_list *real_list, > rb_erase(&real_ha->node, &real_list->tree); > list_del_rcu(&real_ha->list); > kfree_rcu(real_ha, rcu_head); > - real_list->count--; > + __hw_addr_count_dec(real_list); > } > } > > @@ -685,6 +717,7 @@ int dev_addr_init(struct net_device *dev) > /* rtnl_mutex must be held here */ > > __hw_addr_init(&dev->dev_addrs); > + dev->dev_addrs.owner = dev; > memset(addr, 0, sizeof(addr)); > err = __hw_addr_add(&dev->dev_addrs, addr, sizeof(addr), > NETDEV_HW_ADDR_T_LAN); > @@ -962,6 +995,7 @@ EXPORT_SYMBOL(dev_uc_flush); > void dev_uc_init(struct net_device *dev) > { > __hw_addr_init(&dev->uc); > + dev->uc.owner = dev; > } > EXPORT_SYMBOL(dev_uc_init); > > @@ -1177,6 +1211,7 @@ EXPORT_SYMBOL(dev_mc_flush); > void dev_mc_init(struct net_device *dev) > { > __hw_addr_init(&dev->mc); > + dev->mc.owner = dev; > } > EXPORT_SYMBOL(dev_mc_init); > > @@ -1348,6 +1383,7 @@ static void netif_rx_mode_retry(struct timer_list *t) > void netif_rx_mode_init(struct net_device *dev) > { > __hw_addr_init(&dev->rx_mode_addr_cache); > + dev->rx_mode_addr_cache.owner = dev; > timer_setup(&dev->rx_mode_retry_timer, netif_rx_mode_retry, 0); > } >