diff options
Diffstat (limited to 'net/ipv6/ip6_tunnel.c')
| -rw-r--r-- | net/ipv6/ip6_tunnel.c | 16 | 
1 files changed, 14 insertions, 2 deletions
| diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 6a66adba0c22..0a4759b89da2 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c @@ -157,6 +157,7 @@ ip6_tnl_lookup(struct net *net, const struct in6_addr *remote, const struct in6_  	hash = HASH(&any, local);  	for_each_ip6_tunnel_rcu(ip6n->tnls_r_l[hash]) {  		if (ipv6_addr_equal(local, &t->parms.laddr) && +		    ipv6_addr_any(&t->parms.raddr) &&  		    (t->dev->flags & IFF_UP))  			return t;  	} @@ -164,6 +165,7 @@ ip6_tnl_lookup(struct net *net, const struct in6_addr *remote, const struct in6_  	hash = HASH(remote, &any);  	for_each_ip6_tunnel_rcu(ip6n->tnls_r_l[hash]) {  		if (ipv6_addr_equal(remote, &t->parms.raddr) && +		    ipv6_addr_any(&t->parms.laddr) &&  		    (t->dev->flags & IFF_UP))  			return t;  	} @@ -1032,6 +1034,7 @@ int ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev, __u8 dsfield,  	int mtu;  	unsigned int psh_hlen = sizeof(struct ipv6hdr) + t->encap_hlen;  	unsigned int max_headroom = psh_hlen; +	bool use_cache = false;  	u8 hop_limit;  	int err = -1; @@ -1064,7 +1067,15 @@ int ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev, __u8 dsfield,  		memcpy(&fl6->daddr, addr6, sizeof(fl6->daddr));  		neigh_release(neigh); -	} else if (!fl6->flowi6_mark) +	} else if (!(t->parms.flags & +		     (IP6_TNL_F_USE_ORIG_TCLASS | IP6_TNL_F_USE_ORIG_FWMARK))) { +		/* enable the cache only only if the routing decision does +		 * not depend on the current inner header value +		 */ +		use_cache = true; +	} + +	if (use_cache)  		dst = dst_cache_get(&t->dst_cache);  	if (!ip6_tnl_xmit_ctl(t, &fl6->saddr, &fl6->daddr)) @@ -1148,7 +1159,7 @@ route_lookup:  		if (t->encap.type != TUNNEL_ENCAP_NONE)  			goto tx_err_dst_release;  	} else { -		if (!fl6->flowi6_mark && ndst) +		if (use_cache && ndst)  			dst_cache_set_ip6(&t->dst_cache, ndst, &fl6->saddr);  	}  	skb_dst_set(skb, dst); @@ -1170,6 +1181,7 @@ route_lookup:  	if (err)  		return err; +	skb->protocol = htons(ETH_P_IPV6);  	skb_push(skb, sizeof(struct ipv6hdr));  	skb_reset_network_header(skb);  	ipv6h = ipv6_hdr(skb); |