Skip to content

Commit a387ff8

Browse files
kuba-moodavem330
authored andcommitted
dev_addr_list: put the first addr on the tree
Since all netdev->dev_addr modifications go via dev_addr_mod() we can put it on the list. When address is change remove it and add it back. Signed-off-by: Jakub Kicinski <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent d07b26f commit a387ff8

File tree

1 file changed

+34
-28
lines changed

1 file changed

+34
-28
lines changed

net/core/dev_addr_lists.c

Lines changed: 34 additions & 28 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) {
@@ -571,8 +575,10 @@ void dev_addr_mod(struct net_device *dev, unsigned int offset,
571575
dev_addr_check(dev);
572576

573577
ha = container_of(dev->dev_addr, struct netdev_hw_addr, addr[0]);
578+
rb_erase(&ha->node, &dev->dev_addrs.tree);
574579
memcpy(&ha->addr[offset], addr, len);
575580
memcpy(&dev->dev_addr_shadow[offset], addr, len);
581+
WARN_ON(__hw_addr_insert(&dev->dev_addrs, ha, dev->addr_len));
576582
}
577583
EXPORT_SYMBOL(dev_addr_mod);
578584

0 commit comments

Comments
 (0)