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: 24+ 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-10-01 23:31 ` netdev-bot+sashiko
2026-10-02 10:05 ` 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-10-01 23:31 ` netdev-bot+sashiko
2026-10-02 10:06 ` 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-10-05 23:49 ` Jakub Kicinski
2026-10-06 0:54 ` Yuyang Huang
2026-09-30 11:28 ` [PATCH net-next v9 4/6] net: add AF_PACKET multicast dumps Yuyang Huang
2026-10-01 23:31 ` netdev-bot+sashiko
2026-10-02 10:12 ` Yuyang Huang
2026-10-05 23:49 ` Jakub Kicinski
2026-10-06 1:09 ` Yuyang Huang
2026-09-30 11:28 ` [PATCH net-next v9 5/6] netlink: specs: rt-addr: document " Yuyang Huang
2026-10-01 23:31 ` netdev-bot+sashiko
2026-10-02 10:13 ` 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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.