Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=bf742482d7a647c5c6f03f78eb35a862e159ecf5
Commit:     bf742482d7a647c5c6f03f78eb35a862e159ecf5
Parent:     75ebe8f73610636be8bbd8d73db883512850e6be
Author:     Patrick McHardy <[EMAIL PROTECTED]>
AuthorDate: Wed Jun 27 01:26:19 2007 -0700
Committer:  David S. Miller <[EMAIL PROTECTED]>
CommitDate: Tue Jul 10 22:15:54 2007 -0700

    [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]>
---
 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 7a8f22f..aa389c7 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.
@@ -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);
diff --git a/net/core/dev.c b/net/core/dev.c
index a0a46e7..18759cc 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -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;
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to