Skip to content

Commit

Permalink
[NET]: dev: introduce generic net_device address lists
Browse files Browse the repository at this point in the history
Introduce struct dev_addr_list and list maintenance functions
based on dev_mc_list and the related functions. This will be
used by follow-up patches for both multicast and secondary
unicast addresses.

Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Patrick McHardy authored and David S. Miller committed Jul 11, 2007
1 parent 75ebe8f commit bf74248
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 0 deletions.
11 changes: 11 additions & 0 deletions include/linux/netdevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,14 @@ struct netif_rx_stats

DECLARE_PER_CPU(struct netif_rx_stats, netdev_rx_stat);

struct dev_addr_list
{
struct dev_addr_list *next;
u8 da_addr[MAX_ADDR_LEN];
u8 da_addrlen;
int da_users;
int da_gusers;
};

/*
* We tag multicasts with these structures.
Expand Down Expand Up @@ -1008,6 +1016,9 @@ extern void dev_mc_upload(struct net_device *dev);
extern int dev_mc_delete(struct net_device *dev, void *addr, int alen, int all);
extern int dev_mc_add(struct net_device *dev, void *addr, int alen, int newonly);
extern void dev_mc_discard(struct net_device *dev);
extern int __dev_addr_delete(struct dev_addr_list **list, void *addr, int alen, int all);
extern int __dev_addr_add(struct dev_addr_list **list, void *addr, int alen, int newonly);
extern void __dev_addr_discard(struct dev_addr_list **list);
extern void dev_set_promiscuity(struct net_device *dev, int inc);
extern void dev_set_allmulti(struct net_device *dev, int inc);
extern void netdev_state_change(struct net_device *dev);
Expand Down
69 changes: 69 additions & 0 deletions net/core/dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -2553,6 +2553,75 @@ void dev_set_allmulti(struct net_device *dev, int inc)
dev_mc_upload(dev);
}

int __dev_addr_delete(struct dev_addr_list **list, void *addr, int alen,
int glbl)
{
struct dev_addr_list *da;

for (; (da = *list) != NULL; list = &da->next) {
if (memcmp(da->da_addr, addr, da->da_addrlen) == 0 &&
alen == da->da_addrlen) {
if (glbl) {
int old_glbl = da->da_gusers;
da->da_gusers = 0;
if (old_glbl == 0)
break;
}
if (--da->da_users)
return 0;

*list = da->next;
kfree(da);
return 0;
}
}
return -ENOENT;
}

int __dev_addr_add(struct dev_addr_list **list, void *addr, int alen, int glbl)
{
struct dev_addr_list *da;

for (da = *list; da != NULL; da = da->next) {
if (memcmp(da->da_addr, addr, da->da_addrlen) == 0 &&
da->da_addrlen == alen) {
if (glbl) {
int old_glbl = da->da_gusers;
da->da_gusers = 1;
if (old_glbl)
return 0;
}
da->da_users++;
return 0;
}
}

da = kmalloc(sizeof(*da), GFP_ATOMIC);
if (da == NULL)
return -ENOMEM;
memcpy(da->da_addr, addr, alen);
da->da_addrlen = alen;
da->da_users = 1;
da->da_gusers = glbl ? 1 : 0;
da->next = *list;
*list = da;
return 0;
}

void __dev_addr_discard(struct dev_addr_list **list)
{
struct dev_addr_list *tmp;

while (*list != NULL) {
tmp = *list;
*list = tmp->next;
if (tmp->da_users > tmp->da_gusers)
printk("__dev_addr_discard: address leakage! "
"da_users=%d\n", tmp->da_users);
kfree(tmp);
}
}

unsigned dev_get_flags(const struct net_device *dev)
{
unsigned flags;
Expand Down

0 comments on commit bf74248

Please sign in to comment.