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: Eric Dumazet <edumazet@google.com>
This commit is contained in:
parent
e1b59459da
commit
62e2e54091
|
|
@ -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 *
|
||||||
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,
|
||||||
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,
|
||||||
|
|
||||||
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:
|
||||||
|
|
||||||
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:
|
||||||
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:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue