[NET]: dev: introduce generic net_device address lists
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>
This commit is contained in:
committed by
David S. Miller
parent
75ebe8f736
commit
bf742482d7
@@ -177,6 +177,14 @@ struct netif_rx_stats
|
|||||||
|
|
||||||
DECLARE_PER_CPU(struct netif_rx_stats, netdev_rx_stat);
|
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.
|
* We tag multicasts with these structures.
|
||||||
@@ -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_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 int dev_mc_add(struct net_device *dev, void *addr, int alen, int newonly);
|
||||||
extern void dev_mc_discard(struct net_device *dev);
|
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_promiscuity(struct net_device *dev, int inc);
|
||||||
extern void dev_set_allmulti(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);
|
extern void netdev_state_change(struct net_device *dev);
|
||||||
|
@@ -2553,6 +2553,75 @@ void dev_set_allmulti(struct net_device *dev, int inc)
|
|||||||
dev_mc_upload(dev);
|
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 dev_get_flags(const struct net_device *dev)
|
||||||
{
|
{
|
||||||
unsigned flags;
|
unsigned flags;
|
||||||
|
Reference in New Issue
Block a user