[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]
---
commit 6d8fd140951de7cc8faab4922dba74dd1db3cae5
tree b80412116a867d544808f140e76cdf22bbc8b248
parent cdf660f0bd4cca9d2cbe86a31adc60d6fa8a60ec
author Patrick McHardy [EMAIL PROTECTED] Fri, 22 Jun 2007 03:25:26 +0200
committer Patrick McHardy [EMAIL PROTECTED] Fri, 22 Jun 2007 03:25:26 +0200
include/linux/netdevice.h | 11 +++
net/core/dev.c| 69 +
2 files changed, 80 insertions(+), 0 deletions(-)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index e7913ee..3785a8a 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -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.
@@ -1004,6 +1012,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 voiddev_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 voiddev_set_promiscuity(struct net_device *dev, int inc);
extern voiddev_set_allmulti(struct net_device *dev, int inc);
extern voidnetdev_state_change(struct net_device *dev);
diff --git a/net/core/dev.c b/net/core/dev.c
index 2609062..1496715 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -2551,6 +2551,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;
-
To unsubscribe from this list: send the line unsubscribe netdev in
the body of a message to [EMAIL PROTECTED]
More majordomo info at http://vger.kernel.org/majordomo-info.html