Commit 62e2e540 authored by Eric Dumazet's avatar Eric Dumazet Committed by Stephen Hemminger

ip: speedup ip link

ip link has quadratic behavior because store_nlmsg()
has a head list pointer and search the end of list.

Provides a head/tail to cut time.

Time with 128000 net devices, to do "ip link show dev xxx"

Before: 2m3.594s
After: 0m2.830s
Signed-off-by: default avatarEric Dumazet <edumazet@google.com>
parent e1b59459
...@@ -717,6 +717,12 @@ struct nlmsg_list ...@@ -717,6 +717,12 @@ struct nlmsg_list
struct nlmsghdr h; struct nlmsghdr h;
}; };
struct nlmsg_chain
{
struct nlmsg_list *head;
struct nlmsg_list *tail;
};
static int print_selected_addrinfo(int ifindex, struct nlmsg_list *ainfo, FILE *fp) static int print_selected_addrinfo(int ifindex, struct nlmsg_list *ainfo, FILE *fp)
{ {
for ( ;ainfo ; ainfo = ainfo->next) { for ( ;ainfo ; ainfo = ainfo->next) {
...@@ -742,9 +748,8 @@ static int print_selected_addrinfo(int ifindex, struct nlmsg_list *ainfo, FILE * ...@@ -742,9 +748,8 @@ static int print_selected_addrinfo(int ifindex, struct nlmsg_list *ainfo, FILE *
static int store_nlmsg(const struct sockaddr_nl *who, struct nlmsghdr *n, static int store_nlmsg(const struct sockaddr_nl *who, struct nlmsghdr *n,
void *arg) void *arg)
{ {
struct nlmsg_list **linfo = (struct nlmsg_list**)arg; struct nlmsg_chain *lchain = (struct nlmsg_chain *)arg;
struct nlmsg_list *h; struct nlmsg_list *h;
struct nlmsg_list **lp;
h = malloc(n->nlmsg_len+sizeof(void*)); h = malloc(n->nlmsg_len+sizeof(void*));
if (h == NULL) if (h == NULL)
...@@ -753,8 +758,11 @@ static int store_nlmsg(const struct sockaddr_nl *who, struct nlmsghdr *n, ...@@ -753,8 +758,11 @@ static int store_nlmsg(const struct sockaddr_nl *who, struct nlmsghdr *n,
memcpy(&h->h, n, n->nlmsg_len); memcpy(&h->h, n, n->nlmsg_len);
h->next = NULL; h->next = NULL;
for (lp = linfo; *lp; lp = &(*lp)->next) /* NOTHING */; if (lchain->tail)
*lp = h; lchain->tail->next = h;
else
lchain->head = h;
lchain->tail = h;
ll_remember_index(who, n, NULL); ll_remember_index(who, n, NULL);
return 0; return 0;
...@@ -762,8 +770,8 @@ static int store_nlmsg(const struct sockaddr_nl *who, struct nlmsghdr *n, ...@@ -762,8 +770,8 @@ static int store_nlmsg(const struct sockaddr_nl *who, struct nlmsghdr *n,
static int ipaddr_list_or_flush(int argc, char **argv, int flush) static int ipaddr_list_or_flush(int argc, char **argv, int flush)
{ {
struct nlmsg_list *linfo = NULL; struct nlmsg_chain linfo = { NULL, NULL};
struct nlmsg_list *ainfo = NULL; struct nlmsg_chain ainfo = { NULL, NULL};
struct nlmsg_list *l, *n; struct nlmsg_list *l, *n;
char *filter_dev = NULL; char *filter_dev = NULL;
int no_link = 0; int no_link = 0;
...@@ -953,7 +961,7 @@ flush_done: ...@@ -953,7 +961,7 @@ flush_done:
if (filter.family && filter.family != AF_PACKET) { if (filter.family && filter.family != AF_PACKET) {
struct nlmsg_list **lp; struct nlmsg_list **lp;
lp=&linfo; lp = &linfo.head;
if (filter.oneline) if (filter.oneline)
no_link = 1; no_link = 1;
...@@ -963,7 +971,7 @@ flush_done: ...@@ -963,7 +971,7 @@ flush_done:
struct ifinfomsg *ifi = NLMSG_DATA(&l->h); struct ifinfomsg *ifi = NLMSG_DATA(&l->h);
struct nlmsg_list *a; struct nlmsg_list *a;
for (a=ainfo; a; a=a->next) { for (a = ainfo.head; a; a = a->next) {
struct nlmsghdr *n = &a->h; struct nlmsghdr *n = &a->h;
struct ifaddrmsg *ifa = NLMSG_DATA(n); struct ifaddrmsg *ifa = NLMSG_DATA(n);
...@@ -1010,12 +1018,12 @@ flush_done: ...@@ -1010,12 +1018,12 @@ flush_done:
} }
} }
for (l=linfo; l; l = n) { for (l = linfo.head; l; l = n) {
n = l->next; n = l->next;
if (no_link || print_linkinfo(NULL, &l->h, stdout) == 0) { if (no_link || print_linkinfo(NULL, &l->h, stdout) == 0) {
struct ifinfomsg *ifi = NLMSG_DATA(&l->h); struct ifinfomsg *ifi = NLMSG_DATA(&l->h);
if (filter.family != AF_PACKET) if (filter.family != AF_PACKET)
print_selected_addrinfo(ifi->ifi_index, ainfo, stdout); print_selected_addrinfo(ifi->ifi_index, ainfo.head, stdout);
} }
fflush(stdout); fflush(stdout);
free(l); free(l);
......
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