Skip to content

Commit

Permalink
dev_addr_list: put the first addr on the tree
Browse files Browse the repository at this point in the history
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 <kuba@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Jakub Kicinski authored and David S. Miller committed Nov 20, 2021
1 parent d07b26f commit a387ff8
Showing 1 changed file with 34 additions and 28 deletions.
62 changes: 34 additions & 28 deletions net/core/dev_addr_lists.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,35 @@
* General list handling functions
*/

static int __hw_addr_insert(struct netdev_hw_addr_list *list,
struct netdev_hw_addr *new, int addr_len)
{
struct rb_node **ins_point = &list->tree.rb_node, *parent = NULL;
struct netdev_hw_addr *ha;

while (*ins_point) {
int diff;

ha = rb_entry(*ins_point, struct netdev_hw_addr, node);
diff = memcmp(new->addr, ha->addr, addr_len);
if (diff == 0)
diff = memcmp(&new->type, &ha->type, sizeof(new->type));

parent = *ins_point;
if (diff < 0)
ins_point = &parent->rb_left;
else if (diff > 0)
ins_point = &parent->rb_right;
else
return -EEXIST;
}

rb_link_node_rcu(&new->node, parent, ins_point);
rb_insert_color(&new->node, &list->tree);

return 0;
}

static struct netdev_hw_addr*
__hw_addr_create(const unsigned char *addr, int addr_len,
unsigned char addr_type, bool global, bool sync)
Expand Down Expand Up @@ -50,11 +79,6 @@ static int __hw_addr_add_ex(struct netdev_hw_addr_list *list,
if (addr_len > MAX_ADDR_LEN)
return -EINVAL;

ha = list_first_entry(&list->list, struct netdev_hw_addr, list);
if (ha && !memcmp(addr, ha->addr, addr_len) &&
(!addr_type || addr_type == ha->type))
goto found_it;

while (*ins_point) {
int diff;

Expand All @@ -69,7 +93,6 @@ static int __hw_addr_add_ex(struct netdev_hw_addr_list *list,
} else if (diff > 0) {
ins_point = &parent->rb_right;
} else {
found_it:
if (exclusive)
return -EEXIST;
if (global) {
Expand All @@ -94,16 +117,8 @@ static int __hw_addr_add_ex(struct netdev_hw_addr_list *list,
if (!ha)
return -ENOMEM;

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

list_add_tail_rcu(&ha->list, &list->list);
list->count++;
Expand Down Expand Up @@ -138,8 +153,7 @@ static int __hw_addr_del_entry(struct netdev_hw_addr_list *list,
if (--ha->refcount)
return 0;

if (!RB_EMPTY_NODE(&ha->node))
rb_erase(&ha->node, &list->tree);
rb_erase(&ha->node, &list->tree);

list_del_rcu(&ha->list);
kfree_rcu(ha, rcu_head);
Expand All @@ -151,18 +165,8 @@ static struct netdev_hw_addr *__hw_addr_lookup(struct netdev_hw_addr_list *list,
const unsigned char *addr, int addr_len,
unsigned char addr_type)
{
struct netdev_hw_addr *ha;
struct rb_node *node;

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

node = list->tree.rb_node;

while (node) {
Expand Down Expand Up @@ -571,8 +575,10 @@ void dev_addr_mod(struct net_device *dev, unsigned int offset,
dev_addr_check(dev);

ha = container_of(dev->dev_addr, struct netdev_hw_addr, addr[0]);
rb_erase(&ha->node, &dev->dev_addrs.tree);
memcpy(&ha->addr[offset], addr, len);
memcpy(&dev->dev_addr_shadow[offset], addr, len);
WARN_ON(__hw_addr_insert(&dev->dev_addrs, ha, dev->addr_len));
}
EXPORT_SYMBOL(dev_addr_mod);

Expand Down

0 comments on commit a387ff8

Please sign in to comment.