aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/ipv4/ip_gre.c128
1 files changed, 88 insertions, 40 deletions
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index 0101521f366..4a43739c903 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -164,67 +164,113 @@ static DEFINE_RWLOCK(ipgre_lock);
164 164
165/* Given src, dst and key, find appropriate for input tunnel. */ 165/* Given src, dst and key, find appropriate for input tunnel. */
166 166
167static struct ip_tunnel * ipgre_tunnel_lookup(struct net *net, 167static struct ip_tunnel * ipgre_tunnel_lookup(struct net_device *dev,
168 __be32 remote, __be32 local, 168 __be32 remote, __be32 local,
169 __be32 key, __be16 gre_proto) 169 __be32 key, __be16 gre_proto)
170{ 170{
171 struct net *net = dev_net(dev);
172 int link = dev->ifindex;
171 unsigned h0 = HASH(remote); 173 unsigned h0 = HASH(remote);
172 unsigned h1 = HASH(key); 174 unsigned h1 = HASH(key);
173 struct ip_tunnel *t; 175 struct ip_tunnel *t, *sel[4] = { NULL, NULL, NULL, NULL };
174 struct ip_tunnel *t2 = NULL;
175 struct ipgre_net *ign = net_generic(net, ipgre_net_id); 176 struct ipgre_net *ign = net_generic(net, ipgre_net_id);
176 int dev_type = (gre_proto == htons(ETH_P_TEB)) ? 177 int dev_type = (gre_proto == htons(ETH_P_TEB)) ?
177 ARPHRD_ETHER : ARPHRD_IPGRE; 178 ARPHRD_ETHER : ARPHRD_IPGRE;
179 int idx;
178 180
179 for (t = ign->tunnels_r_l[h0^h1]; t; t = t->next) { 181 for (t = ign->tunnels_r_l[h0^h1]; t; t = t->next) {
180 if (local == t->parms.iph.saddr && remote == t->parms.iph.daddr) { 182 if (local != t->parms.iph.saddr ||
181 if (t->parms.i_key == key && t->dev->flags & IFF_UP) { 183 remote != t->parms.iph.daddr ||
182 if (t->dev->type == dev_type) 184 key != t->parms.i_key ||
183 return t; 185 !(t->dev->flags & IFF_UP))
184 if (t->dev->type == ARPHRD_IPGRE && !t2) 186 continue;
185 t2 = t; 187
186 } 188 if (t->dev->type != ARPHRD_IPGRE &&
187 } 189 t->dev->type != dev_type)
190 continue;
191
192 idx = 0;
193 if (t->parms.link != link)
194 idx |= 1;
195 if (t->dev->type != dev_type)
196 idx |= 2;
197 if (idx == 0)
198 return t;
199 if (sel[idx] == NULL)
200 sel[idx] = t;
188 } 201 }
189 202
190 for (t = ign->tunnels_r[h0^h1]; t; t = t->next) { 203 for (t = ign->tunnels_r[h0^h1]; t; t = t->next) {
191 if (remote == t->parms.iph.daddr) { 204 if (remote != t->parms.iph.daddr ||
192 if (t->parms.i_key == key && t->dev->flags & IFF_UP) { 205 key != t->parms.i_key ||
193 if (t->dev->type == dev_type) 206 !(t->dev->flags & IFF_UP))
194 return t; 207 continue;
195 if (t->dev->type == ARPHRD_IPGRE && !t2) 208
196 t2 = t; 209 if (t->dev->type != ARPHRD_IPGRE &&
197 } 210 t->dev->type != dev_type)
198 } 211 continue;
212
213 idx = 0;
214 if (t->parms.link != link)
215 idx |= 1;
216 if (t->dev->type != dev_type)
217 idx |= 2;
218 if (idx == 0)
219 return t;
220 if (sel[idx] == NULL)
221 sel[idx] = t;
199 } 222 }
200 223
201 for (t = ign->tunnels_l[h1]; t; t = t->next) { 224 for (t = ign->tunnels_l[h1]; t; t = t->next) {
202 if (local == t->parms.iph.saddr || 225 if ((local != t->parms.iph.saddr &&
203 (local == t->parms.iph.daddr && 226 (local != t->parms.iph.daddr ||
204 ipv4_is_multicast(local))) { 227 !ipv4_is_multicast(local))) ||
205 if (t->parms.i_key == key && t->dev->flags & IFF_UP) { 228 key != t->parms.i_key ||
206 if (t->dev->type == dev_type) 229 !(t->dev->flags & IFF_UP))
207 return t; 230 continue;
208 if (t->dev->type == ARPHRD_IPGRE && !t2) 231
209 t2 = t; 232 if (t->dev->type != ARPHRD_IPGRE &&
210 } 233 t->dev->type != dev_type)
211 } 234 continue;
235
236 idx = 0;
237 if (t->parms.link != link)
238 idx |= 1;
239 if (t->dev->type != dev_type)
240 idx |= 2;
241 if (idx == 0)
242 return t;
243 if (sel[idx] == NULL)
244 sel[idx] = t;
212 } 245 }
213 246
214 for (t = ign->tunnels_wc[h1]; t; t = t->next) { 247 for (t = ign->tunnels_wc[h1]; t; t = t->next) {
215 if (t->parms.i_key == key && t->dev->flags & IFF_UP) { 248 if (t->parms.i_key != key ||
216 if (t->dev->type == dev_type) 249 !(t->dev->flags & IFF_UP))
217 return t; 250 continue;
218 if (t->dev->type == ARPHRD_IPGRE && !t2) 251
219 t2 = t; 252 if (t->dev->type != ARPHRD_IPGRE &&
220 } 253 t->dev->type != dev_type)
254 continue;
255
256 idx = 0;
257 if (t->parms.link != link)
258 idx |= 1;
259 if (t->dev->type != dev_type)
260 idx |= 2;
261 if (idx == 0)
262 return t;
263 if (sel[idx] == NULL)
264 sel[idx] = t;
221 } 265 }
222 266
223 if (t2) 267 for (idx = 1; idx < ARRAY_SIZE(sel); idx++)
224 return t2; 268 if (sel[idx] != NULL)
269 return sel[idx];
225 270
226 if (ign->fb_tunnel_dev->flags&IFF_UP) 271 if (ign->fb_tunnel_dev->flags & IFF_UP)
227 return netdev_priv(ign->fb_tunnel_dev); 272 return netdev_priv(ign->fb_tunnel_dev);
273
228 return NULL; 274 return NULL;
229} 275}
230 276
@@ -284,6 +330,7 @@ static struct ip_tunnel *ipgre_tunnel_find(struct net *net,
284 __be32 remote = parms->iph.daddr; 330 __be32 remote = parms->iph.daddr;
285 __be32 local = parms->iph.saddr; 331 __be32 local = parms->iph.saddr;
286 __be32 key = parms->i_key; 332 __be32 key = parms->i_key;
333 int link = parms->link;
287 struct ip_tunnel *t, **tp; 334 struct ip_tunnel *t, **tp;
288 struct ipgre_net *ign = net_generic(net, ipgre_net_id); 335 struct ipgre_net *ign = net_generic(net, ipgre_net_id);
289 336
@@ -291,6 +338,7 @@ static struct ip_tunnel *ipgre_tunnel_find(struct net *net,
291 if (local == t->parms.iph.saddr && 338 if (local == t->parms.iph.saddr &&
292 remote == t->parms.iph.daddr && 339 remote == t->parms.iph.daddr &&
293 key == t->parms.i_key && 340 key == t->parms.i_key &&
341 link == t->parms.link &&
294 type == t->dev->type) 342 type == t->dev->type)
295 break; 343 break;
296 344
@@ -421,7 +469,7 @@ static void ipgre_err(struct sk_buff *skb, u32 info)
421 } 469 }
422 470
423 read_lock(&ipgre_lock); 471 read_lock(&ipgre_lock);
424 t = ipgre_tunnel_lookup(dev_net(skb->dev), iph->daddr, iph->saddr, 472 t = ipgre_tunnel_lookup(skb->dev, iph->daddr, iph->saddr,
425 flags & GRE_KEY ? 473 flags & GRE_KEY ?
426 *(((__be32 *)p) + (grehlen / 4) - 1) : 0, 474 *(((__be32 *)p) + (grehlen / 4) - 1) : 0,
427 p[1]); 475 p[1]);
@@ -518,7 +566,7 @@ static int ipgre_rcv(struct sk_buff *skb)
518 gre_proto = *(__be16 *)(h + 2); 566 gre_proto = *(__be16 *)(h + 2);
519 567
520 read_lock(&ipgre_lock); 568 read_lock(&ipgre_lock);
521 if ((tunnel = ipgre_tunnel_lookup(dev_net(skb->dev), 569 if ((tunnel = ipgre_tunnel_lookup(skb->dev,
522 iph->saddr, iph->daddr, key, 570 iph->saddr, iph->daddr, key,
523 gre_proto))) { 571 gre_proto))) {
524 struct net_device_stats *stats = &tunnel->dev->stats; 572 struct net_device_stats *stats = &tunnel->dev->stats;