@ -1447,7 +1447,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 +1715,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 ) ;
}
}
@ -1719,10 +1729,23 @@ static struct timewait_sock_ops tcp6_timewait_sock_ops = {
. twsk_destructor = tcp_twsk_destructor ,
} ;
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 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 ) ,