Re: ip address limit

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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 */
 

-
: send the line "unsubscribe linux-net" in
the body of a message to majordomo@vger.rutgers.edu


[Index of Archives]     [Netdev]     [Ethernet Bridging]     [Linux 802.1Q VLAN]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Git]     [Bugtraq]     [Yosemite News and Information]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux PCI]     [Linux Admin]     [Samba]

  Powered by Linux