On Sun, Aug 13, 2000 at 12:40:53PM -0400, Dennis wrote:
> At 04:49 AM 8/13/00 +0200, Sven Koch wrote:
> >On Sun, 13 Aug 2000, Andi Kleen wrote:
> >
> >> > The number of IP addresses on one interface in kernel 2.2.x is only
> >> > limited by physical memory as far as I can tell. In a test I was able to
> >> > assign over 7000 numbers to one eth - worked without problems, only
> >> > ifconfig took nearly 10 minutes to get me a list (old 233mhz machine
> >> > with suse 6.4 and suse kernel 2.2.14)
> >>
> >> The 10 minutes were probably caused by the name resolver in ifconfig.
> >> Try ifconfig -n
>
> I dont believe there is a name lookup with ifconfig. We see the same issue
> with ifconfig with 1000 DLCIs with no IP addresses assigned at all. Its
> something in the way that ifconfig gets the info...ifconfig on other OSs
> with similar setups return with no additional delay.
>
> I could understand if you did a -a, but there is really no good
> explanation of why an ifconfig on a specific interface would take so long
> to get the info. I reported it a while back without much interest.
You apparently did not report it to the maintainers (just sending it to lists
may cause it being lost)
ifconfig has to read full /proc/net/dev to find out if the device has statistics
or not. It also did read the whole address list in the same go, making
ifconfig name equivalent to ifconfig -a.
It also did some inefficient list operations, because it was never designed
for thousands of interfaces.
The following patch should fix it. It makes the list operations
a lot more efficient by exploiting the sorting order (as long as your
aliases are numerically sorted in the system insert is O(1)), and does less
work when you specified a device name.
Listing 7000 ordered aliases takes about 90s on a K6-4000 now.
-Andi
Index: ifconfig.c
===================================================================
RCS file: /cvs/net-tools/ifconfig.c,v
retrieving revision 1.40
diff -u -u -r1.40 ifconfig.c
--- ifconfig.c 2000/07/31 01:13:33 1.40
+++ ifconfig.c 2000/08/13 23:16:43
@@ -112,7 +112,7 @@
} else {
struct interface *ife;
- ife = lookup_interface(ifname,1);
+ ife = lookup_interface(ifname);
res = do_if_fetch(ife);
if (res >= 0)
ife_print(ife);
@@ -1037,7 +1037,7 @@
struct interface *i;
struct sockaddr_in *sin;
- i = lookup_interface(parent, 1);
+ i = lookup_interface(parent);
if (!i)
return -1;
if (do_if_fetch(i) < 0)
Index: include/interface.h
===================================================================
RCS file: /cvs/net-tools/include/interface.h,v
retrieving revision 1.4
diff -u -u -r1.4 interface.h
--- include/interface.h 2000/05/21 19:35:34 1.4
+++ include/interface.h 2000/08/13 23:16:43
@@ -28,8 +28,7 @@
};
struct interface {
- struct interface *next;
-
+ struct interface *next, *prev;
char name[IFNAMSIZ]; /* interface name */
short type; /* if type */
short flags; /* various flags */
@@ -66,7 +65,7 @@
extern int for_all_interfaces(int (*)(struct interface *, void *), void *);
extern int free_interface_list(void);
-extern struct interface *lookup_interface(char *name, int readlist);
+extern struct interface *lookup_interface(char *name);
extern int if_readlist(void);
extern int do_if_fetch(struct interface *ife);
Index: lib/interface.c
===================================================================
RCS file: /cvs/net-tools/lib/interface.c,v
retrieving revision 1.9
diff -u -u -r1.9 interface.c
--- lib/interface.c 2000/05/21 19:35:34 1.9
+++ lib/interface.c 2000/08/13 23:16:44
@@ -4,6 +4,9 @@
10/1998 partly rewriten by Andi Kleen to support an interface list.
I don't claim that the list operations are efficient @).
+ 8/2000 Andi Kleen make the list operations a bit more efficient.
+ People are crazy enough to use thousands of aliases now.
+
$Id: interface.c,v 1.9 2000/05/21 19:35:34 pb Exp $
*/
@@ -83,39 +86,42 @@
int procnetdev_vsn = 1;
int ife_short;
+
+static struct interface *int_list, *int_last;
-static struct interface *int_list;
+static int if_readlist_proc(char *);
-void add_interface(struct interface *n)
+static struct interface *add_interface(char *name)
{
- struct interface *ife, **pp;
+ struct interface *ife, **nextp, *new;
- pp = &int_list;
- for (ife = int_list; ife; pp = &ife->next, ife = ife->next) {
- if (nstrcmp(ife->name, n->name) > 0)
- break;
- }
- n->next = (*pp);
- (*pp) = n;
+ for (ife = int_last; ife; ife = ife->prev) {
+ int n = nstrcmp(ife->name, name);
+ if (n == 0)
+ return ife;
+ if (n < 0)
+ break;
+ }
+ new(new);
+ safe_strncpy(new->name, name, IFNAMSIZ);
+ nextp = ife ? &ife->next : &int_list;
+ new->prev = ife;
+ new->next = *nextp;
+ if (new->next)
+ new->next->prev = new;
+ else
+ int_last = new;
+ *nextp = new;
+ return new;
}
-struct interface *lookup_interface(char *name, int readlist)
+struct interface *lookup_interface(char *name)
{
struct interface *ife = NULL;
-
- if (int_list || (readlist && if_readlist() >= 0)) {
- for (ife = int_list; ife; ife = ife->next) {
- if (!strcmp(ife->name, name))
- break;
- }
- }
-
- if (!ife) {
- new(ife);
- safe_strncpy(ife->name, name, IFNAMSIZ);
- add_interface(ife);
- }
+ if (if_readlist_proc(name) < 0)
+ return NULL;
+ ife = add_interface(name);
return ife;
}
@@ -182,7 +188,7 @@
ifr = ifc.ifc_req;
for (n = 0; n < ifc.ifc_len; n += sizeof(struct ifreq)) {
- lookup_interface(ifr->ifr_name,0);
+ add_interface(ifr->ifr_name);
ifr++;
}
err = 0;
@@ -292,13 +298,19 @@
return 0;
}
-int if_readlist(void)
+static int if_readlist_proc(char *target)
{
+ static int proc_read;
FILE *fh;
char buf[512];
struct interface *ife;
int err;
+ if (proc_read)
+ return 0;
+ if (!target)
+ proc_read = 1;
+
fh = fopen(_PATH_PROCNET_DEV, "r");
if (!fh) {
fprintf(stderr, _("Warning: cannot open %s (%s). Limited output.\n"),
@@ -336,22 +348,19 @@
err = 0;
while (fgets(buf, sizeof buf, fh)) {
- char *s;
-
- new(ife);
-
- s = get_name(ife->name, buf);
+ char *s, name[IFNAMSIZ];
+ s = get_name(name, buf);
+ ife = add_interface(name);
get_dev_fields(s, ife);
ife->statistics_valid = 1;
-
- add_interface(ife);
+ if (target && !strcmp(target,name))
+ break;
}
if (ferror(fh)) {
perror(_PATH_PROCNET_DEV);
err = -1;
+ proc_read = 0;
}
- if (!err)
- err = if_readconf();
#if 0
free(fmt);
@@ -359,6 +368,14 @@
fclose(fh);
return err;
}
+
+int if_readlist(void)
+{
+ int err = if_readlist_proc(NULL);
+ if (!err)
+ err = if_readconf();
+ return err;
+}
/* Support for fetching an IPX address */
-
To unsubscribe from this list: send the line "unsubscribe linux-net" in
the body of a message to [EMAIL PROTECTED]