Commit da306a2c authored by Andi Kleen's avatar Andi Kleen

Speed up list operations by exploiting that the interface list is ordered,
and the kernel list is normally ordered to.

This allows to list 7000 aliases in a reasonable time.
Also be a bit smarter on when to read SIOCGIFCONF.

The stupid IPv6 /proc parsing on every address still burns a lot of CPU
time.
parent 510362ea
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* that either displays or sets the characteristics of * that either displays or sets the characteristics of
* one or more of the system's networking interfaces. * one or more of the system's networking interfaces.
* *
* Version: $Id: ifconfig.c,v 1.40 2000/07/31 01:13:33 ecki Exp $ * Version: $Id: ifconfig.c,v 1.41 2000/08/14 07:57:19 ak Exp $
* *
* Author: Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org> * Author: Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
* and others. Copyright 1993 MicroWalt Corporation * and others. Copyright 1993 MicroWalt Corporation
...@@ -112,7 +112,7 @@ static int if_print(char *ifname) ...@@ -112,7 +112,7 @@ static int if_print(char *ifname)
} else { } else {
struct interface *ife; struct interface *ife;
ife = lookup_interface(ifname,1); ife = lookup_interface(ifname);
res = do_if_fetch(ife); res = do_if_fetch(ife);
if (res >= 0) if (res >= 0)
ife_print(ife); ife_print(ife);
...@@ -1037,7 +1037,7 @@ static int get_nmbc_parent(char *parent, ...@@ -1037,7 +1037,7 @@ static int get_nmbc_parent(char *parent,
struct interface *i; struct interface *i;
struct sockaddr_in *sin; struct sockaddr_in *sin;
i = lookup_interface(parent, 1); i = lookup_interface(parent);
if (!i) if (!i)
return -1; return -1;
if (do_if_fetch(i) < 0) if (do_if_fetch(i) < 0)
......
...@@ -28,8 +28,7 @@ struct user_net_device_stats { ...@@ -28,8 +28,7 @@ struct user_net_device_stats {
}; };
struct interface { struct interface {
struct interface *next; struct interface *next, *prev;
char name[IFNAMSIZ]; /* interface name */ char name[IFNAMSIZ]; /* interface name */
short type; /* if type */ short type; /* if type */
short flags; /* various flags */ short flags; /* various flags */
...@@ -66,7 +65,7 @@ extern int if_fetch(struct interface *ife); ...@@ -66,7 +65,7 @@ extern int if_fetch(struct interface *ife);
extern int for_all_interfaces(int (*)(struct interface *, void *), void *); extern int for_all_interfaces(int (*)(struct interface *, void *), void *);
extern int free_interface_list(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 if_readlist(void);
extern int do_if_fetch(struct interface *ife); extern int do_if_fetch(struct interface *ife);
......
...@@ -4,7 +4,10 @@ ...@@ -4,7 +4,10 @@
10/1998 partly rewriten by Andi Kleen to support an interface list. 10/1998 partly rewriten by Andi Kleen to support an interface list.
I don't claim that the list operations are efficient @). I don't claim that the list operations are efficient @).
$Id: interface.c,v 1.9 2000/05/21 19:35:34 pb Exp $ 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.10 2000/08/14 07:57:19 ak Exp $
*/ */
#include "config.h" #include "config.h"
...@@ -84,38 +87,41 @@ int procnetdev_vsn = 1; ...@@ -84,38 +87,41 @@ int procnetdev_vsn = 1;
int ife_short; int ife_short;
static struct interface *int_list; static struct interface *int_list, *int_last;
void add_interface(struct interface *n) static int if_readlist_proc(char *);
{
struct interface *ife, **pp;
pp = &int_list; static struct interface *add_interface(char *name)
for (ife = int_list; ife; pp = &ife->next, ife = ife->next) { {
if (nstrcmp(ife->name, n->name) > 0) struct interface *ife, **nextp, *new;
break;
for (ife = int_last; ife; ife = ife->prev) {
int n = nstrcmp(ife->name, name);
if (n == 0)
return ife;
if (n < 0)
break;
} }
n->next = (*pp); new(new);
(*pp) = n; 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; struct interface *ife = NULL;
if (int_list || (readlist && if_readlist() >= 0)) { if (if_readlist_proc(name) < 0)
for (ife = int_list; ife; ife = ife->next) { return NULL;
if (!strcmp(ife->name, name)) ife = add_interface(name);
break;
}
}
if (!ife) {
new(ife);
safe_strncpy(ife->name, name, IFNAMSIZ);
add_interface(ife);
}
return ife; return ife;
} }
...@@ -182,7 +188,7 @@ static int if_readconf(void) ...@@ -182,7 +188,7 @@ static int if_readconf(void)
ifr = ifc.ifc_req; ifr = ifc.ifc_req;
for (n = 0; n < ifc.ifc_len; n += sizeof(struct ifreq)) { for (n = 0; n < ifc.ifc_len; n += sizeof(struct ifreq)) {
lookup_interface(ifr->ifr_name,0); add_interface(ifr->ifr_name);
ifr++; ifr++;
} }
err = 0; err = 0;
...@@ -292,13 +298,19 @@ static int get_dev_fields(char *bp, struct interface *ife) ...@@ -292,13 +298,19 @@ static int get_dev_fields(char *bp, struct interface *ife)
return 0; return 0;
} }
int if_readlist(void) static int if_readlist_proc(char *target)
{ {
static int proc_read;
FILE *fh; FILE *fh;
char buf[512]; char buf[512];
struct interface *ife; struct interface *ife;
int err; int err;
if (proc_read)
return 0;
if (!target)
proc_read = 1;
fh = fopen(_PATH_PROCNET_DEV, "r"); fh = fopen(_PATH_PROCNET_DEV, "r");
if (!fh) { if (!fh) {
fprintf(stderr, _("Warning: cannot open %s (%s). Limited output.\n"), fprintf(stderr, _("Warning: cannot open %s (%s). Limited output.\n"),
...@@ -336,22 +348,19 @@ int if_readlist(void) ...@@ -336,22 +348,19 @@ int if_readlist(void)
err = 0; err = 0;
while (fgets(buf, sizeof buf, fh)) { while (fgets(buf, sizeof buf, fh)) {
char *s; char *s, name[IFNAMSIZ];
s = get_name(name, buf);
new(ife); ife = add_interface(name);
s = get_name(ife->name, buf);
get_dev_fields(s, ife); get_dev_fields(s, ife);
ife->statistics_valid = 1; ife->statistics_valid = 1;
if (target && !strcmp(target,name))
add_interface(ife); break;
} }
if (ferror(fh)) { if (ferror(fh)) {
perror(_PATH_PROCNET_DEV); perror(_PATH_PROCNET_DEV);
err = -1; err = -1;
proc_read = 0;
} }
if (!err)
err = if_readconf();
#if 0 #if 0
free(fmt); free(fmt);
...@@ -360,6 +369,14 @@ int if_readlist(void) ...@@ -360,6 +369,14 @@ int if_readlist(void)
return err; 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 */ /* Support for fetching an IPX address */
#if HAVE_AFIPX #if HAVE_AFIPX
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment