From: Yuyang Huang <sigefriedhyy@gmail.com>
To: Yuyang Huang <sigefriedhyy@gmail.com>
Cc: Ajay Singh <ajay.kathat@microchip.com>,
Aleksandr Loktionov <aleksandr.loktionov@intel.com>,
Andrew Lunn <andrew+netdev@lunn.ch>,
Claudiu Beznea <claudiu.beznea@tuxon.dev>,
"David S. Miller" <davem@davemloft.net>,
David Ahern <dsahern@kernel.org>,
Donald Hunter <donald.hunter@gmail.com>,
Eric Dumazet <edumazet@google.com>,
Ido Schimmel <idosch@nvidia.com>,
Jacob Keller <jacob.e.keller@intel.com>,
Jakub Kicinski <kuba@kernel.org>,
Johannes Berg <johannes@sipsolutions.net>,
Kees Cook <kees@kernel.org>,
Kory Maincent <kory.maincent@bootlin.com>,
Kuniyuki Iwashima <kuniyu@google.com>,
Nicolas Dichtel <nicolas.dichtel@6wind.com>,
Nikolaos Gkarlis <nickgarlis@gmail.com>,
Paolo Abeni <pabeni@redhat.com>,
Sabrina Dubroca <sd@queasysnail.net>,
Shuah Khan <shuah@kernel.org>, Simon Horman <horms@kernel.org>,
Stanislav Fomichev <sdf.kernel@gmail.com>,
Vadim Fedorenko <vadim.fedorenko@linux.dev>,
Willem de Bruijn <willemb@google.com>,
linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org,
linux-wireless@vger.kernel.org, netdev@vger.kernel.org
Subject: [PATCH net-next v9 2/6] net: change netdev_hw_addr_list count through helpers
Date: Wed, 30 Sep 2026 20:28:38 +0900 [thread overview]
Message-ID: <20260930112842.21323-3-sigefriedhyy@gmail.com> (raw)
In-Reply-To: <20260930112842.21323-1-sigefriedhyy@gmail.com>
The count of a netdev_hw_addr_list is changed in several places of
dev_addr_lists.c and a few drivers read it directly. The next patch
needs to account every change of the count of dev->mc.
Add __hw_addr_count_add(), __hw_addr_count_inc(), __hw_addr_count_dec()
and __hw_addr_count_reset(), use them for every change of the count
and rename the field to _count so that a direct write stands out.
Readers keep using netdev_hw_addr_list_count() and the netdev_uc_count()
and netdev_mc_count() helpers, the few that read the field directly
are converted. No functional change.
Signed-off-by: Yuyang Huang <sigefriedhyy@gmail.com>
---
.../net/ethernet/cavium/octeon/octeon_mgmt.c | 4 +-
.../net/wireless/microchip/wilc1000/netdev.c | 8 ++--
include/linux/netdevice.h | 5 ++-
net/core/dev_addr_lists.c | 44 ++++++++++++++-----
net/core/dev_addr_lists_test.c | 18 ++++----
net/mac80211/driver-ops.h | 2 +-
6 files changed, 51 insertions(+), 30 deletions(-)
diff --git a/drivers/net/ethernet/cavium/octeon/octeon_mgmt.c b/drivers/net/ethernet/cavium/octeon/octeon_mgmt.c
index c190fc6538d4c..5e3c379b24234 100644
--- a/drivers/net/ethernet/cavium/octeon/octeon_mgmt.c
+++ b/drivers/net/ethernet/cavium/octeon/octeon_mgmt.c
@@ -573,14 +573,14 @@ static void octeon_mgmt_set_rx_filtering(struct net_device *netdev)
memset(&cam_state, 0, sizeof(cam_state));
- if ((netdev->flags & IFF_PROMISC) || netdev->uc.count > 7) {
+ if ((netdev->flags & IFF_PROMISC) || netdev_uc_count(netdev) > 7) {
cam_mode = 0;
available_cam_entries = 8;
} else {
/* One CAM entry for the primary address, leaves seven
* for the secondary addresses.
*/
- available_cam_entries = 7 - netdev->uc.count;
+ available_cam_entries = 7 - netdev_uc_count(netdev);
}
if (netdev->flags & IFF_MULTICAST) {
diff --git a/drivers/net/wireless/microchip/wilc1000/netdev.c b/drivers/net/wireless/microchip/wilc1000/netdev.c
index 956cb578bf37c..d3343113cea50 100644
--- a/drivers/net/wireless/microchip/wilc1000/netdev.c
+++ b/drivers/net/wireless/microchip/wilc1000/netdev.c
@@ -704,17 +704,17 @@ static void wilc_set_multicast_list(struct net_device *dev)
return;
if (dev->flags & IFF_ALLMULTI ||
- dev->mc.count > WILC_MULTICAST_TABLE_SIZE) {
+ netdev_mc_count(dev) > WILC_MULTICAST_TABLE_SIZE) {
wilc_setup_multicast_filter(vif, 0, 0, NULL);
return;
}
- if (dev->mc.count == 0) {
+ if (netdev_mc_empty(dev)) {
wilc_setup_multicast_filter(vif, 1, 0, NULL);
return;
}
- mc_list = kmalloc_array(dev->mc.count, ETH_ALEN, GFP_ATOMIC);
+ mc_list = kmalloc_array(netdev_mc_count(dev), ETH_ALEN, GFP_ATOMIC);
if (!mc_list)
return;
@@ -727,7 +727,7 @@ static void wilc_set_multicast_list(struct net_device *dev)
cur_mc += ETH_ALEN;
}
- if (wilc_setup_multicast_filter(vif, 1, dev->mc.count, mc_list))
+ if (wilc_setup_multicast_filter(vif, 1, netdev_mc_count(dev), mc_list))
kfree(mc_list);
}
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index d037faff7c44b..97dc053f234cc 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -252,13 +252,14 @@ struct netdev_hw_addr {
struct netdev_hw_addr_list {
struct list_head list;
- int count;
+ /* Only changed through the __hw_addr_count_* helpers */
+ int _count;
/* Auxiliary tree for faster lookup on addition and deletion */
struct rb_root tree;
};
-#define netdev_hw_addr_list_count(l) ((l)->count)
+#define netdev_hw_addr_list_count(l) ((l)->_count)
#define netdev_hw_addr_list_empty(l) (netdev_hw_addr_list_count(l) == 0)
#define netdev_hw_addr_list_for_each(ha, l) \
list_for_each_entry(ha, &(l)->list, list)
diff --git a/net/core/dev_addr_lists.c b/net/core/dev_addr_lists.c
index 08528ca0a8b31..23f5db99a702d 100644
--- a/net/core/dev_addr_lists.c
+++ b/net/core/dev_addr_lists.c
@@ -16,6 +16,26 @@
#include "dev.h"
+static void __hw_addr_count_add(struct netdev_hw_addr_list *list, int value)
+{
+ list->_count += value;
+}
+
+static void __hw_addr_count_inc(struct netdev_hw_addr_list *list)
+{
+ __hw_addr_count_add(list, 1);
+}
+
+static void __hw_addr_count_dec(struct netdev_hw_addr_list *list)
+{
+ __hw_addr_count_add(list, -1);
+}
+
+static void __hw_addr_count_reset(struct netdev_hw_addr_list *list)
+{
+ list->_count = 0;
+}
+
/*
* General list handling functions
*/
@@ -125,7 +145,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 +181,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,14 +512,14 @@ 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);
void __hw_addr_init(struct netdev_hw_addr_list *list)
{
INIT_LIST_HEAD(&list->list);
- list->count = 0;
+ list->_count = 0;
list->tree = RB_ROOT;
}
EXPORT_SYMBOL(__hw_addr_init);
@@ -509,8 +529,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);
}
/**
@@ -532,11 +552,11 @@ int __hw_addr_list_snapshot(struct netdev_hw_addr_list *snap,
struct netdev_hw_addr *ha, *entry;
list_for_each_entry(ha, &list->list, list) {
- if (cache->count) {
+ if (cache->_count) {
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 +574,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 +624,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 +642,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);
}
}
diff --git a/net/core/dev_addr_lists_test.c b/net/core/dev_addr_lists_test.c
index 260e71a2399f3..07c35a0af2b4d 100644
--- a/net/core/dev_addr_lists_test.c
+++ b/net/core/dev_addr_lists_test.c
@@ -291,7 +291,7 @@ static void dev_addr_test_snapshot_sync(struct kunit *test)
netif_addr_unlock_bh(netdev);
/* Real entry should now reflect the sync: sync_cnt=1, refcount=2 */
- KUNIT_EXPECT_EQ(test, 1, netdev->uc.count);
+ KUNIT_EXPECT_EQ(test, 1, netdev_uc_count(netdev));
ha = list_first_entry(&netdev->uc.list, struct netdev_hw_addr, list);
KUNIT_EXPECT_MEMEQ(test, ha->addr, addr, ETH_ALEN);
KUNIT_EXPECT_EQ(test, 1, ha->sync_cnt);
@@ -303,7 +303,7 @@ static void dev_addr_test_snapshot_sync(struct kunit *test)
dev_addr_test_unsync);
KUNIT_EXPECT_EQ(test, 0, datp->addr_synced);
KUNIT_EXPECT_EQ(test, 0, datp->addr_unsynced);
- KUNIT_EXPECT_EQ(test, 1, netdev->uc.count);
+ KUNIT_EXPECT_EQ(test, 1, netdev_uc_count(netdev));
__hw_addr_flush(&cache);
rtnl_unlock();
@@ -351,7 +351,7 @@ static void dev_addr_test_snapshot_remove_during_sync(struct kunit *test)
/* Concurrent removal: user deletes ADDR_A while driver was working */
memset(addr, ADDR_A, sizeof(addr));
KUNIT_EXPECT_EQ(test, 0, dev_uc_del(netdev, addr));
- KUNIT_EXPECT_EQ(test, 0, netdev->uc.count);
+ KUNIT_EXPECT_EQ(test, 0, netdev_uc_count(netdev));
/* Reconcile: ADDR_A gone from real list but driver synced it,
* so it gets re-inserted as stale (sync_cnt=1, refcount=1).
@@ -361,7 +361,7 @@ static void dev_addr_test_snapshot_remove_during_sync(struct kunit *test)
&cache);
netif_addr_unlock_bh(netdev);
- KUNIT_EXPECT_EQ(test, 1, netdev->uc.count);
+ KUNIT_EXPECT_EQ(test, 1, netdev_uc_count(netdev));
ha = list_first_entry(&netdev->uc.list, struct netdev_hw_addr, list);
KUNIT_EXPECT_MEMEQ(test, ha->addr, addr, ETH_ALEN);
KUNIT_EXPECT_EQ(test, 1, ha->sync_cnt);
@@ -373,7 +373,7 @@ static void dev_addr_test_snapshot_remove_during_sync(struct kunit *test)
dev_addr_test_unsync);
KUNIT_EXPECT_EQ(test, 0, datp->addr_synced);
KUNIT_EXPECT_EQ(test, 1 << ADDR_A, datp->addr_unsynced);
- KUNIT_EXPECT_EQ(test, 0, netdev->uc.count);
+ KUNIT_EXPECT_EQ(test, 0, netdev_uc_count(netdev));
__hw_addr_flush(&cache);
rtnl_unlock();
@@ -433,7 +433,7 @@ static void dev_addr_test_snapshot_readd_during_unsync(struct kunit *test)
* stale entry and bumps refcount from 1 -> 2. sync_cnt stays 1.
*/
KUNIT_EXPECT_EQ(test, 0, dev_uc_add(netdev, addr));
- KUNIT_EXPECT_EQ(test, 1, netdev->uc.count);
+ KUNIT_EXPECT_EQ(test, 1, netdev_uc_count(netdev));
/* Reconcile: ref sync_cnt=1 matches real sync_cnt=1, delta=-1
* applied. Result: sync_cnt=0, refcount=1 (fresh).
@@ -444,7 +444,7 @@ static void dev_addr_test_snapshot_readd_during_unsync(struct kunit *test)
netif_addr_unlock_bh(netdev);
/* Entry survives as fresh: needs re-sync to HW */
- KUNIT_EXPECT_EQ(test, 1, netdev->uc.count);
+ KUNIT_EXPECT_EQ(test, 1, netdev_uc_count(netdev));
ha = list_first_entry(&netdev->uc.list, struct netdev_hw_addr, list);
KUNIT_EXPECT_MEMEQ(test, ha->addr, addr, ETH_ALEN);
KUNIT_EXPECT_EQ(test, 0, ha->sync_cnt);
@@ -528,7 +528,7 @@ static void dev_addr_test_snapshot_add_and_remove(struct kunit *test)
* ADDR_B: refcount went from 2->1 via dev_uc_del (still present, stale)
* ADDR_C: sync propagated (sync_cnt=1, refcount=2)
*/
- KUNIT_EXPECT_EQ(test, 3, netdev->uc.count);
+ KUNIT_EXPECT_EQ(test, 3, netdev_uc_count(netdev));
netdev_hw_addr_list_for_each(ha, &netdev->uc) {
u8 id = ha->addr[0];
@@ -553,7 +553,7 @@ static void dev_addr_test_snapshot_add_and_remove(struct kunit *test)
dev_addr_test_unsync);
KUNIT_EXPECT_EQ(test, 0, datp->addr_synced);
KUNIT_EXPECT_EQ(test, 1 << ADDR_B, datp->addr_unsynced);
- KUNIT_EXPECT_EQ(test, 2, netdev->uc.count);
+ KUNIT_EXPECT_EQ(test, 2, netdev_uc_count(netdev));
__hw_addr_flush(&cache);
rtnl_unlock();
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index f1c0b87fddd5f..e80731c59ef50 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -187,7 +187,7 @@ static inline u64 drv_prepare_multicast(struct ieee80211_local *local,
{
u64 ret = 0;
- trace_drv_prepare_multicast(local, mc_list->count);
+ trace_drv_prepare_multicast(local, netdev_hw_addr_list_count(mc_list));
if (local->ops->prepare_multicast)
ret = local->ops->prepare_multicast(&local->hw, mc_list);
--
2.43.0
next prev parent reply other threads:[~2026-09-30 11:29 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-30 11:28 [PATCH net-next v9 0/6] rtnetlink: dump link-layer multicast addresses Yuyang Huang
2026-09-30 11:28 ` [PATCH net-next v9 1/6] netlink: specs: rt-addr: fix the type of target-netnsid Yuyang Huang
2026-09-30 11:28 ` Yuyang Huang [this message]
2026-09-30 13:03 ` [PATCH net-next v9 2/6] net: change netdev_hw_addr_list count through helpers Nicolas Dichtel
2026-09-30 13:43 ` Yuyang Huang
2026-09-30 14:08 ` Nicolas Dichtel
2026-09-30 14:13 ` Yuyang Huang
2026-09-30 11:28 ` [PATCH net-next v9 3/6] net: add a generation counter for dev->mc changes Yuyang Huang
2026-09-30 13:04 ` Nicolas Dichtel
2026-09-30 11:28 ` [PATCH net-next v9 4/6] net: add AF_PACKET multicast dumps Yuyang Huang
2026-09-30 11:28 ` [PATCH net-next v9 5/6] netlink: specs: rt-addr: document " Yuyang Huang
2026-09-30 11:28 ` [PATCH net-next v9 6/6] selftests: net: test " Yuyang Huang
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=20260930112842.21323-3-sigefriedhyy@gmail.com \
--to=sigefriedhyy@gmail.com \
--cc=ajay.kathat@microchip.com \
--cc=aleksandr.loktionov@intel.com \
--cc=andrew+netdev@lunn.ch \
--cc=claudiu.beznea@tuxon.dev \
--cc=davem@davemloft.net \
--cc=donald.hunter@gmail.com \
--cc=dsahern@kernel.org \
--cc=edumazet@google.com \
--cc=horms@kernel.org \
--cc=idosch@nvidia.com \
--cc=jacob.e.keller@intel.com \
--cc=johannes@sipsolutions.net \
--cc=kees@kernel.org \
--cc=kory.maincent@bootlin.com \
--cc=kuba@kernel.org \
--cc=kuniyu@google.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=linux-wireless@vger.kernel.org \
--cc=netdev@vger.kernel.org \
--cc=nickgarlis@gmail.com \
--cc=nicolas.dichtel@6wind.com \
--cc=pabeni@redhat.com \
--cc=sd@queasysnail.net \
--cc=sdf.kernel@gmail.com \
--cc=shuah@kernel.org \
--cc=vadim.fedorenko@linux.dev \
--cc=willemb@google.com \
/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®