Commit afcf1242 authored by Timo Teras's avatar Timo Teras Committed by David S. Miller

gre: optimize hash lookup

Instead of keeping candidate tunnel device from all categories,
keep only one candidate with best score. This optimizes stack
usage and speeds up exit code.
Signed-off-by: default avatarTimo Teras <timo.teras@iki.fi>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 3eacdf58
...@@ -172,11 +172,11 @@ static struct ip_tunnel * ipgre_tunnel_lookup(struct net_device *dev, ...@@ -172,11 +172,11 @@ static struct ip_tunnel * ipgre_tunnel_lookup(struct net_device *dev,
int link = dev->ifindex; int link = dev->ifindex;
unsigned h0 = HASH(remote); unsigned h0 = HASH(remote);
unsigned h1 = HASH(key); unsigned h1 = HASH(key);
struct ip_tunnel *t, *sel[4] = { NULL, NULL, NULL, NULL }; struct ip_tunnel *t, *cand = NULL;
struct ipgre_net *ign = net_generic(net, ipgre_net_id); struct ipgre_net *ign = net_generic(net, ipgre_net_id);
int dev_type = (gre_proto == htons(ETH_P_TEB)) ? int dev_type = (gre_proto == htons(ETH_P_TEB)) ?
ARPHRD_ETHER : ARPHRD_IPGRE; ARPHRD_ETHER : ARPHRD_IPGRE;
int idx; int score, cand_score = 4;
for (t = ign->tunnels_r_l[h0^h1]; t; t = t->next) { for (t = ign->tunnels_r_l[h0^h1]; t; t = t->next) {
if (local != t->parms.iph.saddr || if (local != t->parms.iph.saddr ||
...@@ -189,15 +189,18 @@ static struct ip_tunnel * ipgre_tunnel_lookup(struct net_device *dev, ...@@ -189,15 +189,18 @@ static struct ip_tunnel * ipgre_tunnel_lookup(struct net_device *dev,
t->dev->type != dev_type) t->dev->type != dev_type)
continue; continue;
idx = 0; score = 0;
if (t->parms.link != link) if (t->parms.link != link)
idx |= 1; score |= 1;
if (t->dev->type != dev_type) if (t->dev->type != dev_type)
idx |= 2; score |= 2;
if (idx == 0) if (score == 0)
return t; return t;
if (sel[idx] == NULL)
sel[idx] = t; if (score < cand_score) {
cand = t;
cand_score = score;
}
} }
for (t = ign->tunnels_r[h0^h1]; t; t = t->next) { for (t = ign->tunnels_r[h0^h1]; t; t = t->next) {
...@@ -210,15 +213,18 @@ static struct ip_tunnel * ipgre_tunnel_lookup(struct net_device *dev, ...@@ -210,15 +213,18 @@ static struct ip_tunnel * ipgre_tunnel_lookup(struct net_device *dev,
t->dev->type != dev_type) t->dev->type != dev_type)
continue; continue;
idx = 0; score = 0;
if (t->parms.link != link) if (t->parms.link != link)
idx |= 1; score |= 1;
if (t->dev->type != dev_type) if (t->dev->type != dev_type)
idx |= 2; score |= 2;
if (idx == 0) if (score == 0)
return t; return t;
if (sel[idx] == NULL)
sel[idx] = t; if (score < cand_score) {
cand = t;
cand_score = score;
}
} }
for (t = ign->tunnels_l[h1]; t; t = t->next) { for (t = ign->tunnels_l[h1]; t; t = t->next) {
...@@ -233,15 +239,18 @@ static struct ip_tunnel * ipgre_tunnel_lookup(struct net_device *dev, ...@@ -233,15 +239,18 @@ static struct ip_tunnel * ipgre_tunnel_lookup(struct net_device *dev,
t->dev->type != dev_type) t->dev->type != dev_type)
continue; continue;
idx = 0; score = 0;
if (t->parms.link != link) if (t->parms.link != link)
idx |= 1; score |= 1;
if (t->dev->type != dev_type) if (t->dev->type != dev_type)
idx |= 2; score |= 2;
if (idx == 0) if (score == 0)
return t; return t;
if (sel[idx] == NULL)
sel[idx] = t; if (score < cand_score) {
cand = t;
cand_score = score;
}
} }
for (t = ign->tunnels_wc[h1]; t; t = t->next) { for (t = ign->tunnels_wc[h1]; t; t = t->next) {
...@@ -253,20 +262,22 @@ static struct ip_tunnel * ipgre_tunnel_lookup(struct net_device *dev, ...@@ -253,20 +262,22 @@ static struct ip_tunnel * ipgre_tunnel_lookup(struct net_device *dev,
t->dev->type != dev_type) t->dev->type != dev_type)
continue; continue;
idx = 0; score = 0;
if (t->parms.link != link) if (t->parms.link != link)
idx |= 1; score |= 1;
if (t->dev->type != dev_type) if (t->dev->type != dev_type)
idx |= 2; score |= 2;
if (idx == 0) if (score == 0)
return t; return t;
if (sel[idx] == NULL)
sel[idx] = t; if (score < cand_score) {
cand = t;
cand_score = score;
}
} }
for (idx = 1; idx < ARRAY_SIZE(sel); idx++) if (cand != NULL)
if (sel[idx] != NULL) return cand;
return sel[idx];
if (ign->fb_tunnel_dev->flags & IFF_UP) if (ign->fb_tunnel_dev->flags & IFF_UP)
return netdev_priv(ign->fb_tunnel_dev); return netdev_priv(ign->fb_tunnel_dev);
......
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