Skip to content

Commit bf74248

Browse files
kaberDavid S. Miller
authored andcommitted
[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 <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 75ebe8f commit bf74248

File tree

2 files changed

+80
-0
lines changed

2 files changed

+80
-0
lines changed

include/linux/netdevice.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,14 @@ struct netif_rx_stats
177177

178178
DECLARE_PER_CPU(struct netif_rx_stats, netdev_rx_stat);
179179

180+
struct dev_addr_list
181+
{
182+
struct dev_addr_list *next;
183+
u8 da_addr[MAX_ADDR_LEN];
184+
u8 da_addrlen;
185+
int da_users;
186+
int da_gusers;
187+
};
180188

181189
/*
182190
* We tag multicasts with these structures.
@@ -1008,6 +1016,9 @@ extern void dev_mc_upload(struct net_device *dev);
10081016
extern int dev_mc_delete(struct net_device *dev, void *addr, int alen, int all);
10091017
extern int dev_mc_add(struct net_device *dev, void *addr, int alen, int newonly);
10101018
extern void dev_mc_discard(struct net_device *dev);
1019+
extern int __dev_addr_delete(struct dev_addr_list **list, void *addr, int alen, int all);
1020+
extern int __dev_addr_add(struct dev_addr_list **list, void *addr, int alen, int newonly);
1021+
extern void __dev_addr_discard(struct dev_addr_list **list);
10111022
extern void dev_set_promiscuity(struct net_device *dev, int inc);
10121023
extern void dev_set_allmulti(struct net_device *dev, int inc);
10131024
extern void netdev_state_change(struct net_device *dev);

net/core/dev.c

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2553,6 +2553,75 @@ void dev_set_allmulti(struct net_device *dev, int inc)
25532553
dev_mc_upload(dev);
25542554
}
25552555

2556+
int __dev_addr_delete(struct dev_addr_list **list, void *addr, int alen,
2557+
int glbl)
2558+
{
2559+
struct dev_addr_list *da;
2560+
2561+
for (; (da = *list) != NULL; list = &da->next) {
2562+
if (memcmp(da->da_addr, addr, da->da_addrlen) == 0 &&
2563+
alen == da->da_addrlen) {
2564+
if (glbl) {
2565+
int old_glbl = da->da_gusers;
2566+
da->da_gusers = 0;
2567+
if (old_glbl == 0)
2568+
break;
2569+
}
2570+
if (--da->da_users)
2571+
return 0;
2572+
2573+
*list = da->next;
2574+
kfree(da);
2575+
return 0;
2576+
}
2577+
}
2578+
return -ENOENT;
2579+
}
2580+
2581+
int __dev_addr_add(struct dev_addr_list **list, void *addr, int alen, int glbl)
2582+
{
2583+
struct dev_addr_list *da;
2584+
2585+
for (da = *list; da != NULL; da = da->next) {
2586+
if (memcmp(da->da_addr, addr, da->da_addrlen) == 0 &&
2587+
da->da_addrlen == alen) {
2588+
if (glbl) {
2589+
int old_glbl = da->da_gusers;
2590+
da->da_gusers = 1;
2591+
if (old_glbl)
2592+
return 0;
2593+
}
2594+
da->da_users++;
2595+
return 0;
2596+
}
2597+
}
2598+
2599+
da = kmalloc(sizeof(*da), GFP_ATOMIC);
2600+
if (da == NULL)
2601+
return -ENOMEM;
2602+
memcpy(da->da_addr, addr, alen);
2603+
da->da_addrlen = alen;
2604+
da->da_users = 1;
2605+
da->da_gusers = glbl ? 1 : 0;
2606+
da->next = *list;
2607+
*list = da;
2608+
return 0;
2609+
}
2610+
2611+
void __dev_addr_discard(struct dev_addr_list **list)
2612+
{
2613+
struct dev_addr_list *tmp;
2614+
2615+
while (*list != NULL) {
2616+
tmp = *list;
2617+
*list = tmp->next;
2618+
if (tmp->da_users > tmp->da_gusers)
2619+
printk("__dev_addr_discard: address leakage! "
2620+
"da_users=%d\n", tmp->da_users);
2621+
kfree(tmp);
2622+
}
2623+
}
2624+
25562625
unsigned dev_get_flags(const struct net_device *dev)
25572626
{
25582627
unsigned flags;

0 commit comments

Comments
 (0)