16
16
* General list handling functions
17
17
*/
18
18
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
+
19
48
static struct netdev_hw_addr *
20
49
__hw_addr_create (const unsigned char * addr , int addr_len ,
21
50
unsigned char addr_type , bool global , bool sync )
@@ -50,11 +79,6 @@ static int __hw_addr_add_ex(struct netdev_hw_addr_list *list,
50
79
if (addr_len > MAX_ADDR_LEN )
51
80
return - EINVAL ;
52
81
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
-
58
82
while (* ins_point ) {
59
83
int diff ;
60
84
@@ -69,7 +93,6 @@ static int __hw_addr_add_ex(struct netdev_hw_addr_list *list,
69
93
} else if (diff > 0 ) {
70
94
ins_point = & parent -> rb_right ;
71
95
} else {
72
- found_it :
73
96
if (exclusive )
74
97
return - EEXIST ;
75
98
if (global ) {
@@ -94,16 +117,8 @@ static int __hw_addr_add_ex(struct netdev_hw_addr_list *list,
94
117
if (!ha )
95
118
return - ENOMEM ;
96
119
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 );
107
122
108
123
list_add_tail_rcu (& ha -> list , & list -> list );
109
124
list -> count ++ ;
@@ -138,8 +153,7 @@ static int __hw_addr_del_entry(struct netdev_hw_addr_list *list,
138
153
if (-- ha -> refcount )
139
154
return 0 ;
140
155
141
- if (!RB_EMPTY_NODE (& ha -> node ))
142
- rb_erase (& ha -> node , & list -> tree );
156
+ rb_erase (& ha -> node , & list -> tree );
143
157
144
158
list_del_rcu (& ha -> list );
145
159
kfree_rcu (ha , rcu_head );
@@ -151,18 +165,8 @@ static struct netdev_hw_addr *__hw_addr_lookup(struct netdev_hw_addr_list *list,
151
165
const unsigned char * addr , int addr_len ,
152
166
unsigned char addr_type )
153
167
{
154
- struct netdev_hw_addr * ha ;
155
168
struct rb_node * node ;
156
169
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
-
166
170
node = list -> tree .rb_node ;
167
171
168
172
while (node ) {
@@ -571,8 +575,10 @@ void dev_addr_mod(struct net_device *dev, unsigned int offset,
571
575
dev_addr_check (dev );
572
576
573
577
ha = container_of (dev -> dev_addr , struct netdev_hw_addr , addr [0 ]);
578
+ rb_erase (& ha -> node , & dev -> dev_addrs .tree );
574
579
memcpy (& ha -> addr [offset ], addr , len );
575
580
memcpy (& dev -> dev_addr_shadow [offset ], addr , len );
581
+ WARN_ON (__hw_addr_insert (& dev -> dev_addrs , ha , dev -> addr_len ));
576
582
}
577
583
EXPORT_SYMBOL (dev_addr_mod );
578
584
0 commit comments