diff -purN orig/net/core/dev.c linux-2.4.21/net/core/dev.c --- orig/net/core/dev.c 2004-08-16 19:35:59.304359160 -0400 +++ linux-2.4.21/net/core/dev.c 2004-08-16 19:30:34.654713408 -0400 @@ -107,7 +107,7 @@ #ifdef CONFIG_PLIP extern int plip_init(void); #endif - +#include /* This define, if set, will randomly drop a packet when congestion * is more than moderate. It helps fairness in the multi-interface @@ -407,6 +407,107 @@ __setup("netdev=", netdev_boot_setup); ******************************************************************************************/ +struct dev_name_entry { + list_t list; + struct net_device **devices; + unsigned num_devices; + unsigned devices_size; + u8 basename_len; + char basename[IFNAMSIZ]; + struct net_device *default_devices[1]; +}; + +LIST_HEAD(dev_name_list); + +static int skip_atoi(const char *s) +{ + int i=0; + + while (isdigit(*s)) + i = i*10 + *s++ - '0'; + return i; +} + +static struct dev_name_entry *dev_get_dn(const char *name, int *idxp) +{ + list_t *pos; + int idx, i; + + for (i=0; name[i] && !isdigit(name[i]); i++) + ; + + idx = skip_atoi(name+i); + *idxp = idx; + + list_for_each(pos, &dev_name_list) { + struct dev_name_entry *dn = (struct dev_name_entry *)pos; + + if (dn->basename_len != i) + continue; + if (memcmp(dn->basename, name, i)) + continue; + + return dn; + } + return NULL; +} + +static void dev_add_name(struct net_device *dev) +{ + struct dev_name_entry *dn; + int idx; + + dn = dev_get_dn(dev->name, &idx); + if (!dn) { + int i; + + dn = kmalloc(sizeof(struct dev_name_entry), GFP_ATOMIC); + memset(dn, 0, sizeof(*dn)); + dn->devices = dn->default_devices; + dn->devices_size = 1; + list_add(&dn->list, &dev_name_list); + + strcpy(dn->basename, dev->name); + for (i=0; dn->basename[i] && !isdigit(dn->basename[i]); i++) + ; + dn->basename[i] = 0; + dn->basename_len = i; + } + + if (idx >= dn->devices_size) { + struct net_device **old = dn->devices; + size_t size; + + dn->devices_size *= 2; + size = dn->devices_size * sizeof(void *); + dn->devices = kmalloc(size, GFP_ATOMIC); + memcpy(dn->devices, old, size / 2); + memset(dn->devices + dn->devices_size/2, 0, size / 2); + + if (old != dn->default_devices) + kfree(old); + } + + if (dn->devices[idx]) + BUG(); + dn->devices[idx] = dev; +} + +static void dev_remove_name(struct net_device *dev) +{ + struct dev_name_entry *dn; + int idx; + + dn = dev_get_dn(dev->name, &idx); + if (!dn) + return; + if (idx >= dn->num_devices) + return; + + if (dev == dn->devices[idx]) + dn->devices[idx] = NULL; +} + /** * __dev_get_by_name - find a device by its name * @name: name to find @@ -422,8 +523,15 @@ __setup("netdev=", netdev_boot_setup); struct net_device *__dev_get_by_name(const char *name) { struct net_device *dev; + struct dev_name_entry *dn; + int idx; - for (dev = dev_base; dev != NULL; dev = dev->next) { + dn = dev_get_dn(name, &idx); + if (!dn) + return NULL; + if (idx >= dn->num_devices) + idx = 0; + for (dev = dn->devices[idx]; dev != NULL; dev = dev->next) { if (strncmp(dev->name, name, IFNAMSIZ) == 0) return dev; } @@ -2585,6 +2693,7 @@ int register_netdevice(struct net_device *dp = dev; dev_hold(dev); dev->deadbeaf = 0; + dev_add_name(dev); write_unlock_bh(&dev_base_lock); /* Notify protocols, that a new device appeared. */ @@ -2653,6 +2762,7 @@ int unregister_netdevice(struct net_devi for (dp = &dev_base; (d=*dp) != NULL; dp=&d->next) { if (d == dev) { write_lock_bh(&dev_base_lock); + dev_remove_name(dev); *dp = d->next; write_unlock_bh(&dev_base_lock); break; @@ -2884,6 +2994,7 @@ int __init net_dev_init(void) while ((dev = *dp) != NULL) { if (dev->deadbeaf) { write_lock_bh(&dev_base_lock); + dev_remove_name(dev); *dp = dev->next; write_unlock_bh(&dev_base_lock); dev_put(dev); diff -purN orig/net/core/dev.c linux-2.4.21/net/core/dev.c --- orig/net/core/dev.c 2004-08-16 23:04:53.000000000 -0400 +++ linux-2.4.21/net/core/dev.c 2004-08-17 01:20:36.358969064 -0400 @@ -410,7 +410,6 @@ __setup("netdev=", netdev_boot_setup); struct dev_name_entry { list_t list; struct net_device **devices; - unsigned num_devices; unsigned devices_size; u8 basename_len; char basename[IFNAMSIZ]; @@ -501,7 +500,7 @@ static void dev_remove_name(struct net_d dn = dev_get_dn(dev->name, &idx); if (!dn) return; - if (idx >= dn->num_devices) + if (idx >= dn->devices_size) return; if (dev == dn->devices[idx]) @@ -529,7 +528,7 @@ struct net_device *__dev_get_by_name(con dn = dev_get_dn(name, &idx); if (!dn) return NULL; - if (idx >= dn->num_devices) + if (idx >= dn->devices_size) idx = 0; for (dev = dn->devices[idx]; dev != NULL; dev = dev->next) { if (strncmp(dev->name, name, IFNAMSIZ) == 0) diff -purN orig/drivers/net/loopback.c linux-2.4.21/drivers/net/loopback.c --- orig/drivers/net/loopback.c 2004-08-17 01:39:36.748603488 -0400 +++ linux-2.4.21/drivers/net/loopback.c 2004-08-17 01:40:53.441944328 -0400 @@ -122,6 +122,7 @@ int __init loopback_init(struct net_devi return -ENOMEM; memset(dev->priv, 0, sizeof(struct net_device_stats)); dev->get_stats = get_stats; + dev_add_name(dev); /* * Fill in the generic fields of the device structure. diff -purN orig/net/core/dev.c linux-2.4.21/net/core/dev.c --- orig/net/core/dev.c 2004-08-17 01:30:40.860070928 -0400 +++ linux-2.4.21/net/core/dev.c 2004-08-17 01:40:01.085903656 -0400 @@ -451,7 +451,7 @@ static struct dev_name_entry *dev_get_dn return NULL; } -static void dev_add_name(struct net_device *dev) +void dev_add_name(struct net_device *dev) { struct dev_name_entry *dn; int idx;