diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv4/tcp_input.c | 34 |
1 files changed, 24 insertions, 10 deletions
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index c26076fb890e..7670ef968dce 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -936,13 +936,16 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_ | |||
936 | struct tcp_sock *tp = tcp_sk(sk); | 936 | struct tcp_sock *tp = tcp_sk(sk); |
937 | unsigned char *ptr = ack_skb->h.raw + TCP_SKB_CB(ack_skb)->sacked; | 937 | unsigned char *ptr = ack_skb->h.raw + TCP_SKB_CB(ack_skb)->sacked; |
938 | struct tcp_sack_block_wire *sp = (struct tcp_sack_block_wire *)(ptr+2); | 938 | struct tcp_sack_block_wire *sp = (struct tcp_sack_block_wire *)(ptr+2); |
939 | struct sk_buff *cached_skb; | ||
939 | int num_sacks = (ptr[1] - TCPOLEN_SACK_BASE)>>3; | 940 | int num_sacks = (ptr[1] - TCPOLEN_SACK_BASE)>>3; |
940 | int reord = tp->packets_out; | 941 | int reord = tp->packets_out; |
941 | int prior_fackets; | 942 | int prior_fackets; |
942 | u32 lost_retrans = 0; | 943 | u32 lost_retrans = 0; |
943 | int flag = 0; | 944 | int flag = 0; |
944 | int dup_sack = 0; | 945 | int dup_sack = 0; |
946 | int cached_fack_count; | ||
945 | int i; | 947 | int i; |
948 | int first_sack_index; | ||
946 | 949 | ||
947 | if (!tp->sacked_out) | 950 | if (!tp->sacked_out) |
948 | tp->fackets_out = 0; | 951 | tp->fackets_out = 0; |
@@ -1000,6 +1003,7 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_ | |||
1000 | } | 1003 | } |
1001 | } | 1004 | } |
1002 | 1005 | ||
1006 | first_sack_index = 0; | ||
1003 | if (flag) | 1007 | if (flag) |
1004 | num_sacks = 1; | 1008 | num_sacks = 1; |
1005 | else { | 1009 | else { |
@@ -1016,6 +1020,10 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_ | |||
1016 | tmp = sp[j]; | 1020 | tmp = sp[j]; |
1017 | sp[j] = sp[j+1]; | 1021 | sp[j] = sp[j+1]; |
1018 | sp[j+1] = tmp; | 1022 | sp[j+1] = tmp; |
1023 | |||
1024 | /* Track where the first SACK block goes to */ | ||
1025 | if (j == first_sack_index) | ||
1026 | first_sack_index = j+1; | ||
1019 | } | 1027 | } |
1020 | 1028 | ||
1021 | } | 1029 | } |
@@ -1025,20 +1033,22 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_ | |||
1025 | /* clear flag as used for different purpose in following code */ | 1033 | /* clear flag as used for different purpose in following code */ |
1026 | flag = 0; | 1034 | flag = 0; |
1027 | 1035 | ||
1036 | /* Use SACK fastpath hint if valid */ | ||
1037 | cached_skb = tp->fastpath_skb_hint; | ||
1038 | cached_fack_count = tp->fastpath_cnt_hint; | ||
1039 | if (!cached_skb) { | ||
1040 | cached_skb = sk->sk_write_queue.next; | ||
1041 | cached_fack_count = 0; | ||
1042 | } | ||
1043 | |||
1028 | for (i=0; i<num_sacks; i++, sp++) { | 1044 | for (i=0; i<num_sacks; i++, sp++) { |
1029 | struct sk_buff *skb; | 1045 | struct sk_buff *skb; |
1030 | __u32 start_seq = ntohl(sp->start_seq); | 1046 | __u32 start_seq = ntohl(sp->start_seq); |
1031 | __u32 end_seq = ntohl(sp->end_seq); | 1047 | __u32 end_seq = ntohl(sp->end_seq); |
1032 | int fack_count; | 1048 | int fack_count; |
1033 | 1049 | ||
1034 | /* Use SACK fastpath hint if valid */ | 1050 | skb = cached_skb; |
1035 | if (tp->fastpath_skb_hint) { | 1051 | fack_count = cached_fack_count; |
1036 | skb = tp->fastpath_skb_hint; | ||
1037 | fack_count = tp->fastpath_cnt_hint; | ||
1038 | } else { | ||
1039 | skb = sk->sk_write_queue.next; | ||
1040 | fack_count = 0; | ||
1041 | } | ||
1042 | 1052 | ||
1043 | /* Event "B" in the comment above. */ | 1053 | /* Event "B" in the comment above. */ |
1044 | if (after(end_seq, tp->high_seq)) | 1054 | if (after(end_seq, tp->high_seq)) |
@@ -1048,8 +1058,12 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_ | |||
1048 | int in_sack, pcount; | 1058 | int in_sack, pcount; |
1049 | u8 sacked; | 1059 | u8 sacked; |
1050 | 1060 | ||
1051 | tp->fastpath_skb_hint = skb; | 1061 | cached_skb = skb; |
1052 | tp->fastpath_cnt_hint = fack_count; | 1062 | cached_fack_count = fack_count; |
1063 | if (i == first_sack_index) { | ||
1064 | tp->fastpath_skb_hint = skb; | ||
1065 | tp->fastpath_cnt_hint = fack_count; | ||
1066 | } | ||
1053 | 1067 | ||
1054 | /* The retransmission queue is always in order, so | 1068 | /* The retransmission queue is always in order, so |
1055 | * we can short-circuit the walk early. | 1069 | * we can short-circuit the walk early. |