Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 133862
b: refs/heads/master
c: 749c10f
h: refs/heads/master
v: v3
  • Loading branch information
Timo Teras authored and David S. Miller committed Jan 21, 2009
1 parent 7841c30 commit bae9a6e
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 41 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 57a574993d94671b495cdbe8aeb78b745abfe14f
refs/heads/master: 749c10f931923451a4c59b4435d182aa9ae27a4f
128 changes: 88 additions & 40 deletions trunk/net/ipv4/ip_gre.c
Original file line number Diff line number Diff line change
Expand Up @@ -164,67 +164,113 @@ static DEFINE_RWLOCK(ipgre_lock);

/* Given src, dst and key, find appropriate for input tunnel. */

static struct ip_tunnel * ipgre_tunnel_lookup(struct net *net,
static struct ip_tunnel * ipgre_tunnel_lookup(struct net_device *dev,
__be32 remote, __be32 local,
__be32 key, __be16 gre_proto)
{
struct net *net = dev_net(dev);
int link = dev->ifindex;
unsigned h0 = HASH(remote);
unsigned h1 = HASH(key);
struct ip_tunnel *t;
struct ip_tunnel *t2 = NULL;
struct ip_tunnel *t, *sel[4] = { NULL, NULL, NULL, NULL };
struct ipgre_net *ign = net_generic(net, ipgre_net_id);
int dev_type = (gre_proto == htons(ETH_P_TEB)) ?
ARPHRD_ETHER : ARPHRD_IPGRE;
int idx;

for (t = ign->tunnels_r_l[h0^h1]; t; t = t->next) {
if (local == t->parms.iph.saddr && remote == t->parms.iph.daddr) {
if (t->parms.i_key == key && t->dev->flags & IFF_UP) {
if (t->dev->type == dev_type)
return t;
if (t->dev->type == ARPHRD_IPGRE && !t2)
t2 = t;
}
}
if (local != t->parms.iph.saddr ||
remote != t->parms.iph.daddr ||
key != t->parms.i_key ||
!(t->dev->flags & IFF_UP))
continue;

if (t->dev->type != ARPHRD_IPGRE &&
t->dev->type != dev_type)
continue;

idx = 0;
if (t->parms.link != link)
idx |= 1;
if (t->dev->type != dev_type)
idx |= 2;
if (idx == 0)
return t;
if (sel[idx] == NULL)
sel[idx] = t;
}

for (t = ign->tunnels_r[h0^h1]; t; t = t->next) {
if (remote == t->parms.iph.daddr) {
if (t->parms.i_key == key && t->dev->flags & IFF_UP) {
if (t->dev->type == dev_type)
return t;
if (t->dev->type == ARPHRD_IPGRE && !t2)
t2 = t;
}
}
if (remote != t->parms.iph.daddr ||
key != t->parms.i_key ||
!(t->dev->flags & IFF_UP))
continue;

if (t->dev->type != ARPHRD_IPGRE &&
t->dev->type != dev_type)
continue;

idx = 0;
if (t->parms.link != link)
idx |= 1;
if (t->dev->type != dev_type)
idx |= 2;
if (idx == 0)
return t;
if (sel[idx] == NULL)
sel[idx] = t;
}

for (t = ign->tunnels_l[h1]; t; t = t->next) {
if (local == t->parms.iph.saddr ||
(local == t->parms.iph.daddr &&
ipv4_is_multicast(local))) {
if (t->parms.i_key == key && t->dev->flags & IFF_UP) {
if (t->dev->type == dev_type)
return t;
if (t->dev->type == ARPHRD_IPGRE && !t2)
t2 = t;
}
}
if ((local != t->parms.iph.saddr &&
(local != t->parms.iph.daddr ||
!ipv4_is_multicast(local))) ||
key != t->parms.i_key ||
!(t->dev->flags & IFF_UP))
continue;

if (t->dev->type != ARPHRD_IPGRE &&
t->dev->type != dev_type)
continue;

idx = 0;
if (t->parms.link != link)
idx |= 1;
if (t->dev->type != dev_type)
idx |= 2;
if (idx == 0)
return t;
if (sel[idx] == NULL)
sel[idx] = t;
}

for (t = ign->tunnels_wc[h1]; t; t = t->next) {
if (t->parms.i_key == key && t->dev->flags & IFF_UP) {
if (t->dev->type == dev_type)
return t;
if (t->dev->type == ARPHRD_IPGRE && !t2)
t2 = t;
}
if (t->parms.i_key != key ||
!(t->dev->flags & IFF_UP))
continue;

if (t->dev->type != ARPHRD_IPGRE &&
t->dev->type != dev_type)
continue;

idx = 0;
if (t->parms.link != link)
idx |= 1;
if (t->dev->type != dev_type)
idx |= 2;
if (idx == 0)
return t;
if (sel[idx] == NULL)
sel[idx] = t;
}

if (t2)
return t2;
for (idx = 1; idx < ARRAY_SIZE(sel); idx++)
if (sel[idx] != NULL)
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 NULL;
}

Expand Down Expand Up @@ -284,13 +330,15 @@ static struct ip_tunnel *ipgre_tunnel_find(struct net *net,
__be32 remote = parms->iph.daddr;
__be32 local = parms->iph.saddr;
__be32 key = parms->i_key;
int link = parms->link;
struct ip_tunnel *t, **tp;
struct ipgre_net *ign = net_generic(net, ipgre_net_id);

for (tp = __ipgre_bucket(ign, parms); (t = *tp) != NULL; tp = &t->next)
if (local == t->parms.iph.saddr &&
remote == t->parms.iph.daddr &&
key == t->parms.i_key &&
link == t->parms.link &&
type == t->dev->type)
break;

Expand Down Expand Up @@ -421,7 +469,7 @@ static void ipgre_err(struct sk_buff *skb, u32 info)
}

read_lock(&ipgre_lock);
t = ipgre_tunnel_lookup(dev_net(skb->dev), iph->daddr, iph->saddr,
t = ipgre_tunnel_lookup(skb->dev, iph->daddr, iph->saddr,
flags & GRE_KEY ?
*(((__be32 *)p) + (grehlen / 4) - 1) : 0,
p[1]);
Expand Down Expand Up @@ -518,7 +566,7 @@ static int ipgre_rcv(struct sk_buff *skb)
gre_proto = *(__be16 *)(h + 2);

read_lock(&ipgre_lock);
if ((tunnel = ipgre_tunnel_lookup(dev_net(skb->dev),
if ((tunnel = ipgre_tunnel_lookup(skb->dev,
iph->saddr, iph->daddr, key,
gre_proto))) {
struct net_device_stats *stats = &tunnel->dev->stats;
Expand Down

0 comments on commit bae9a6e

Please sign in to comment.