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 @@
* that either displays or sets the characteristics of
* 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>
* and others. Copyright 1993 MicroWalt Corporation
......@@ -112,7 +112,7 @@ static int if_print(char *ifname)
} 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 @@ static int get_nmbc_parent(char *parent,
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)
......
......@@ -28,8 +28,7 @@ struct user_net_device_stats {
};
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 if_fetch(struct interface *ife);
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);
......
......@@ -4,7 +4,10 @@
10/1998 partly rewriten by Andi Kleen to support an interface list.
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"
......@@ -84,38 +87,41 @@ int procnetdev_vsn = 1;
int ife_short;
static struct interface *int_list;
static struct interface *int_list, *int_last;
void add_interface(struct interface *n)
{
struct interface *ife, **pp;
static int if_readlist_proc(char *);
pp = &int_list;
for (ife = int_list; ife; pp = &ife->next, ife = ife->next) {
if (nstrcmp(ife->name, n->name) > 0)
break;
static struct interface *add_interface(char *name)
{
struct interface *ife, **nextp, *new;
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);
(*pp) = n;
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 @@ static int if_readconf(void)
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 @@ static int get_dev_fields(char *bp, struct interface *ife)
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 @@ int if_readlist(void)
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);
......@@ -360,6 +369,14 @@ int if_readlist(void)
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 */
#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