Skip to content

Commit 979594c

Browse files
committed
Merge branch 'dev_addr-const'
Jakub Kicinski says: ==================== net: constify netdev->dev_addr Take care of a few stragglers and make netdev->dev_addr const. netdev->dev_addr can be held on the address tree like any other address now. ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents 1388d4a + 2c193f2 commit 979594c

File tree

8 files changed

+320
-41
lines changed

8 files changed

+320
-41
lines changed

drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -586,7 +586,7 @@ static inline int bnx2x_vfpf_release(struct bnx2x *bp) {return 0; }
586586
static inline int bnx2x_vfpf_init(struct bnx2x *bp) {return 0; }
587587
static inline void bnx2x_vfpf_close_vf(struct bnx2x *bp) {}
588588
static inline int bnx2x_vfpf_setup_q(struct bnx2x *bp, struct bnx2x_fastpath *fp, bool is_leading) {return 0; }
589-
static inline int bnx2x_vfpf_config_mac(struct bnx2x *bp, u8 *addr,
589+
static inline int bnx2x_vfpf_config_mac(struct bnx2x *bp, const u8 *addr,
590590
u8 vf_qid, bool set) {return 0; }
591591
static inline int bnx2x_vfpf_config_rss(struct bnx2x *bp,
592592
struct bnx2x_config_rss_params *params) {return 0; }

drivers/net/ethernet/i825xx/82596.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1178,7 +1178,8 @@ static struct net_device * __init i82596_probe(void)
11781178
DEB(DEB_PROBE,printk(KERN_INFO "%s: 82596 at %#3lx,", dev->name, dev->base_addr));
11791179

11801180
for (i = 0; i < 6; i++)
1181-
DEB(DEB_PROBE,printk(" %2.2X", dev->dev_addr[i] = eth_addr[i]));
1181+
DEB(DEB_PROBE,printk(" %2.2X", eth_addr[i]));
1182+
eth_hw_addr_set(dev, eth_addr);
11821183

11831184
DEB(DEB_PROBE,printk(" IRQ %d.\n", dev->irq));
11841185

include/linux/netdevice.h

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1942,6 +1942,8 @@ enum netdev_ml_priv_type {
19421942
* @unlink_list: As netif_addr_lock() can be called recursively,
19431943
* keep a list of interfaces to be deleted.
19441944
*
1945+
* @dev_addr_shadow: Copy of @dev_addr to catch direct writes.
1946+
*
19451947
* FIXME: cleanup struct net_device such that network protocol info
19461948
* moves out.
19471949
*/
@@ -2117,7 +2119,7 @@ struct net_device {
21172119
* Cache lines mostly used on receive path (including eth_type_trans())
21182120
*/
21192121
/* Interface address info used in eth_type_trans() */
2120-
unsigned char *dev_addr;
2122+
const unsigned char *dev_addr;
21212123

21222124
struct netdev_rx_queue *_rx;
21232125
unsigned int num_rx_queues;
@@ -2268,6 +2270,8 @@ struct net_device {
22682270

22692271
/* protected by rtnl_lock */
22702272
struct bpf_xdp_entity xdp_state[__MAX_XDP_MODE];
2273+
2274+
u8 dev_addr_shadow[MAX_ADDR_LEN];
22712275
};
22722276
#define to_net_dev(d) container_of(d, struct net_device, dev)
22732277

@@ -4268,30 +4272,27 @@ void __hw_addr_unsync_dev(struct netdev_hw_addr_list *list,
42684272
void __hw_addr_init(struct netdev_hw_addr_list *list);
42694273

42704274
/* Functions used for device addresses handling */
4275+
void dev_addr_mod(struct net_device *dev, unsigned int offset,
4276+
const void *addr, size_t len);
4277+
42714278
static inline void
42724279
__dev_addr_set(struct net_device *dev, const void *addr, size_t len)
42734280
{
4274-
memcpy(dev->dev_addr, addr, len);
4281+
dev_addr_mod(dev, 0, addr, len);
42754282
}
42764283

42774284
static inline void dev_addr_set(struct net_device *dev, const u8 *addr)
42784285
{
42794286
__dev_addr_set(dev, addr, dev->addr_len);
42804287
}
42814288

4282-
static inline void
4283-
dev_addr_mod(struct net_device *dev, unsigned int offset,
4284-
const void *addr, size_t len)
4285-
{
4286-
memcpy(&dev->dev_addr[offset], addr, len);
4287-
}
4288-
42894289
int dev_addr_add(struct net_device *dev, const unsigned char *addr,
42904290
unsigned char addr_type);
42914291
int dev_addr_del(struct net_device *dev, const unsigned char *addr,
42924292
unsigned char addr_type);
42934293
void dev_addr_flush(struct net_device *dev);
42944294
int dev_addr_init(struct net_device *dev);
4295+
void dev_addr_check(struct net_device *dev);
42954296

42964297
/* Functions used for unicast addresses handling */
42974298
int dev_uc_add(struct net_device *dev, const unsigned char *addr);

net/Kconfig

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -455,4 +455,9 @@ config ETHTOOL_NETLINK
455455
netlink. It provides better extensibility and some new features,
456456
e.g. notification messages.
457457

458+
config NETDEV_ADDR_LIST_TEST
459+
tristate "Unit tests for device address list"
460+
default KUNIT_ALL_TESTS
461+
depends on KUNIT
462+
458463
endif # if NET

net/core/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ obj-y += dev.o dev_addr_lists.o dst.o netevent.o \
1313
sock_diag.o dev_ioctl.o tso.o sock_reuseport.o \
1414
fib_notifier.o xdp.o flow_offload.o gro.o
1515

16+
obj-$(CONFIG_NETDEV_ADDR_LIST_TEST) += dev_addr_lists_test.o
17+
1618
obj-y += net-sysfs.o
1719
obj-$(CONFIG_PAGE_POOL) += page_pool.o
1820
obj-$(CONFIG_PROC_FS) += net-procfs.o

net/core/dev.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1377,6 +1377,7 @@ static int __dev_open(struct net_device *dev, struct netlink_ext_ack *extack)
13771377
int ret;
13781378

13791379
ASSERT_RTNL();
1380+
dev_addr_check(dev);
13801381

13811382
if (!netif_device_present(dev)) {
13821383
/* may be detached because parent is runtime-suspended */

net/core/dev_addr_lists.c

Lines changed: 63 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,35 @@
1616
* General list handling functions
1717
*/
1818

19+
static int __hw_addr_insert(struct netdev_hw_addr_list *list,
20+
struct netdev_hw_addr *new, int addr_len)
21+
{
22+
struct rb_node **ins_point = &list->tree.rb_node, *parent = NULL;
23+
struct netdev_hw_addr *ha;
24+
25+
while (*ins_point) {
26+
int diff;
27+
28+
ha = rb_entry(*ins_point, struct netdev_hw_addr, node);
29+
diff = memcmp(new->addr, ha->addr, addr_len);
30+
if (diff == 0)
31+
diff = memcmp(&new->type, &ha->type, sizeof(new->type));
32+
33+
parent = *ins_point;
34+
if (diff < 0)
35+
ins_point = &parent->rb_left;
36+
else if (diff > 0)
37+
ins_point = &parent->rb_right;
38+
else
39+
return -EEXIST;
40+
}
41+
42+
rb_link_node_rcu(&new->node, parent, ins_point);
43+
rb_insert_color(&new->node, &list->tree);
44+
45+
return 0;
46+
}
47+
1948
static struct netdev_hw_addr*
2049
__hw_addr_create(const unsigned char *addr, int addr_len,
2150
unsigned char addr_type, bool global, bool sync)
@@ -50,11 +79,6 @@ static int __hw_addr_add_ex(struct netdev_hw_addr_list *list,
5079
if (addr_len > MAX_ADDR_LEN)
5180
return -EINVAL;
5281

53-
ha = list_first_entry(&list->list, struct netdev_hw_addr, list);
54-
if (ha && !memcmp(addr, ha->addr, addr_len) &&
55-
(!addr_type || addr_type == ha->type))
56-
goto found_it;
57-
5882
while (*ins_point) {
5983
int diff;
6084

@@ -69,7 +93,6 @@ static int __hw_addr_add_ex(struct netdev_hw_addr_list *list,
6993
} else if (diff > 0) {
7094
ins_point = &parent->rb_right;
7195
} else {
72-
found_it:
7396
if (exclusive)
7497
return -EEXIST;
7598
if (global) {
@@ -94,16 +117,8 @@ static int __hw_addr_add_ex(struct netdev_hw_addr_list *list,
94117
if (!ha)
95118
return -ENOMEM;
96119

97-
/* The first address in dev->dev_addrs is pointed to by dev->dev_addr
98-
* and mutated freely by device drivers and netdev ops, so if we insert
99-
* it into the tree we'll end up with an invalid rbtree.
100-
*/
101-
if (list->count > 0) {
102-
rb_link_node(&ha->node, parent, ins_point);
103-
rb_insert_color(&ha->node, &list->tree);
104-
} else {
105-
RB_CLEAR_NODE(&ha->node);
106-
}
120+
rb_link_node(&ha->node, parent, ins_point);
121+
rb_insert_color(&ha->node, &list->tree);
107122

108123
list_add_tail_rcu(&ha->list, &list->list);
109124
list->count++;
@@ -138,8 +153,7 @@ static int __hw_addr_del_entry(struct netdev_hw_addr_list *list,
138153
if (--ha->refcount)
139154
return 0;
140155

141-
if (!RB_EMPTY_NODE(&ha->node))
142-
rb_erase(&ha->node, &list->tree);
156+
rb_erase(&ha->node, &list->tree);
143157

144158
list_del_rcu(&ha->list);
145159
kfree_rcu(ha, rcu_head);
@@ -151,18 +165,8 @@ static struct netdev_hw_addr *__hw_addr_lookup(struct netdev_hw_addr_list *list,
151165
const unsigned char *addr, int addr_len,
152166
unsigned char addr_type)
153167
{
154-
struct netdev_hw_addr *ha;
155168
struct rb_node *node;
156169

157-
/* The first address isn't inserted into the tree because in the dev->dev_addrs
158-
* list it's the address pointed to by dev->dev_addr which is freely mutated
159-
* in place, so we need to check it separately.
160-
*/
161-
ha = list_first_entry(&list->list, struct netdev_hw_addr, list);
162-
if (ha && !memcmp(addr, ha->addr, addr_len) &&
163-
(!addr_type || addr_type == ha->type))
164-
return ha;
165-
166170
node = list->tree.rb_node;
167171

168172
while (node) {
@@ -498,6 +502,21 @@ EXPORT_SYMBOL(__hw_addr_init);
498502
* Device addresses handling functions
499503
*/
500504

505+
/* Check that netdev->dev_addr is not written to directly as this would
506+
* break the rbtree layout. All changes should go thru dev_addr_set() and co.
507+
* Remove this check in mid-2024.
508+
*/
509+
void dev_addr_check(struct net_device *dev)
510+
{
511+
if (!memcmp(dev->dev_addr, dev->dev_addr_shadow, MAX_ADDR_LEN))
512+
return;
513+
514+
netdev_warn(dev, "Current addr: %*ph\n", MAX_ADDR_LEN, dev->dev_addr);
515+
netdev_warn(dev, "Expected addr: %*ph\n",
516+
MAX_ADDR_LEN, dev->dev_addr_shadow);
517+
netdev_WARN(dev, "Incorrect netdev->dev_addr\n");
518+
}
519+
501520
/**
502521
* dev_addr_flush - Flush device address list
503522
* @dev: device
@@ -509,11 +528,11 @@ EXPORT_SYMBOL(__hw_addr_init);
509528
void dev_addr_flush(struct net_device *dev)
510529
{
511530
/* rtnl_mutex must be held here */
531+
dev_addr_check(dev);
512532

513533
__hw_addr_flush(&dev->dev_addrs);
514534
dev->dev_addr = NULL;
515535
}
516-
EXPORT_SYMBOL(dev_addr_flush);
517536

518537
/**
519538
* dev_addr_init - Init device address list
@@ -547,7 +566,21 @@ int dev_addr_init(struct net_device *dev)
547566
}
548567
return err;
549568
}
550-
EXPORT_SYMBOL(dev_addr_init);
569+
570+
void dev_addr_mod(struct net_device *dev, unsigned int offset,
571+
const void *addr, size_t len)
572+
{
573+
struct netdev_hw_addr *ha;
574+
575+
dev_addr_check(dev);
576+
577+
ha = container_of(dev->dev_addr, struct netdev_hw_addr, addr[0]);
578+
rb_erase(&ha->node, &dev->dev_addrs.tree);
579+
memcpy(&ha->addr[offset], addr, len);
580+
memcpy(&dev->dev_addr_shadow[offset], addr, len);
581+
WARN_ON(__hw_addr_insert(&dev->dev_addrs, ha, dev->addr_len));
582+
}
583+
EXPORT_SYMBOL(dev_addr_mod);
551584

552585
/**
553586
* dev_addr_add - Add a device address

0 commit comments

Comments
 (0)