diff options
| author | David S. Miller <davem@davemloft.net> | 2012-08-22 14:21:38 -0700 | 
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2012-08-22 14:21:38 -0700 | 
| commit | 1304a7343b30fc4f16045412efdbb4179a3d9255 (patch) | |
| tree | 83d667ac4f62e30f70305ce4cc7e030e3465f92e /net/ipv6/tcp_ipv6.c | |
| parent | 1d76efe1577b4323609b1bcbfafa8b731eda071a (diff) | |
| parent | 23dcfa61bac244e1200ff9ad19c6e9144dcb6bb5 (diff) | |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Diffstat (limited to 'net/ipv6/tcp_ipv6.c')
| -rw-r--r-- | net/ipv6/tcp_ipv6.c | 29 | 
1 files changed, 27 insertions, 2 deletions
| diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index aa41b0e6b163..cd49de3678fb 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -94,6 +94,18 @@ static struct tcp_md5sig_key *tcp_v6_md5_do_lookup(struct sock *sk,  }  #endif +static void inet6_sk_rx_dst_set(struct sock *sk, const struct sk_buff *skb) +{ +	struct dst_entry *dst = skb_dst(skb); +	const struct rt6_info *rt = (const struct rt6_info *)dst; + +	dst_hold(dst); +	sk->sk_rx_dst = dst; +	inet_sk(sk)->rx_dst_ifindex = skb->skb_iif; +	if (rt->rt6i_node) +		inet6_sk(sk)->rx_dst_cookie = rt->rt6i_node->fn_sernum; +} +  static void tcp_v6_hash(struct sock *sk)  {  	if (sk->sk_state != TCP_CLOSE) { @@ -1270,6 +1282,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,  	newsk->sk_gso_type = SKB_GSO_TCPV6;  	__ip6_dst_store(newsk, dst, NULL, NULL); +	inet6_sk_rx_dst_set(newsk, skb);  	newtcp6sk = (struct tcp6_sock *)newsk;  	inet_sk(newsk)->pinet6 = &newtcp6sk->inet6; @@ -1447,7 +1460,17 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)  		opt_skb = skb_clone(skb, sk_gfp_atomic(sk, GFP_ATOMIC));  	if (sk->sk_state == TCP_ESTABLISHED) { /* Fast path */ +		struct dst_entry *dst = sk->sk_rx_dst; +  		sock_rps_save_rxhash(sk, skb); +		if (dst) { +			if (inet_sk(sk)->rx_dst_ifindex != skb->skb_iif || +			    dst->ops->check(dst, np->rx_dst_cookie) == NULL) { +				dst_release(dst); +				sk->sk_rx_dst = NULL; +			} +		} +  		if (tcp_rcv_established(sk, skb, tcp_hdr(skb), skb->len))  			goto reset;  		if (opt_skb) @@ -1705,9 +1728,9 @@ static void tcp_v6_early_demux(struct sk_buff *skb)  			struct dst_entry *dst = sk->sk_rx_dst;  			struct inet_sock *icsk = inet_sk(sk);  			if (dst) -				dst = dst_check(dst, 0); +				dst = dst_check(dst, inet6_sk(sk)->rx_dst_cookie);  			if (dst && -			    icsk->rx_dst_ifindex == inet6_iif(skb)) +			    icsk->rx_dst_ifindex == skb->skb_iif)  				skb_dst_set_noref(skb, dst);  		}  	} @@ -1723,6 +1746,7 @@ static const struct inet_connection_sock_af_ops ipv6_specific = {  	.queue_xmit	   = inet6_csk_xmit,  	.send_check	   = tcp_v6_send_check,  	.rebuild_header	   = inet6_sk_rebuild_header, +	.sk_rx_dst_set	   = inet6_sk_rx_dst_set,  	.conn_request	   = tcp_v6_conn_request,  	.syn_recv_sock	   = tcp_v6_syn_recv_sock,  	.net_header_len	   = sizeof(struct ipv6hdr), @@ -1754,6 +1778,7 @@ static const struct inet_connection_sock_af_ops ipv6_mapped = {  	.queue_xmit	   = ip_queue_xmit,  	.send_check	   = tcp_v4_send_check,  	.rebuild_header	   = inet_sk_rebuild_header, +	.sk_rx_dst_set	   = inet_sk_rx_dst_set,  	.conn_request	   = tcp_v6_conn_request,  	.syn_recv_sock	   = tcp_v6_syn_recv_sock,  	.net_header_len	   = sizeof(struct iphdr), | 
