diff options
| -rw-r--r-- | include/linux/tcp.h | 15 | ||||
| -rw-r--r-- | include/net/sock.h | 6 | ||||
| -rw-r--r-- | include/net/tcp.h | 9 | ||||
| -rw-r--r-- | net/ipv4/tcp_input.c | 144 | ||||
| -rw-r--r-- | net/ipv4/tcp_output.c | 54 |
5 files changed, 202 insertions, 26 deletions
diff --git a/include/linux/tcp.h b/include/linux/tcp.h index 737b32e52956..0e1da6602e05 100644 --- a/include/linux/tcp.h +++ b/include/linux/tcp.h | |||
| @@ -307,6 +307,21 @@ struct tcp_sock { | |||
| 307 | struct tcp_sack_block duplicate_sack[1]; /* D-SACK block */ | 307 | struct tcp_sack_block duplicate_sack[1]; /* D-SACK block */ |
| 308 | struct tcp_sack_block selective_acks[4]; /* The SACKS themselves*/ | 308 | struct tcp_sack_block selective_acks[4]; /* The SACKS themselves*/ |
| 309 | 309 | ||
| 310 | struct tcp_sack_block recv_sack_cache[4]; | ||
| 311 | |||
| 312 | /* from STCP, retrans queue hinting */ | ||
| 313 | struct sk_buff* lost_skb_hint; | ||
| 314 | |||
| 315 | struct sk_buff *scoreboard_skb_hint; | ||
| 316 | struct sk_buff *retransmit_skb_hint; | ||
| 317 | struct sk_buff *forward_skb_hint; | ||
| 318 | struct sk_buff *fastpath_skb_hint; | ||
| 319 | |||
| 320 | int fastpath_cnt_hint; | ||
| 321 | int lost_cnt_hint; | ||
| 322 | int retransmit_cnt_hint; | ||
| 323 | int forward_cnt_hint; | ||
| 324 | |||
| 310 | __u16 advmss; /* Advertised MSS */ | 325 | __u16 advmss; /* Advertised MSS */ |
| 311 | __u16 prior_ssthresh; /* ssthresh saved at recovery start */ | 326 | __u16 prior_ssthresh; /* ssthresh saved at recovery start */ |
| 312 | __u32 lost_out; /* Lost packets */ | 327 | __u32 lost_out; /* Lost packets */ |
diff --git a/include/net/sock.h b/include/net/sock.h index ff13c4cc287a..982b4ecd187b 100644 --- a/include/net/sock.h +++ b/include/net/sock.h | |||
| @@ -1247,6 +1247,12 @@ static inline struct page *sk_stream_alloc_page(struct sock *sk) | |||
| 1247 | (skb != (struct sk_buff *)&(sk)->sk_write_queue); \ | 1247 | (skb != (struct sk_buff *)&(sk)->sk_write_queue); \ |
| 1248 | skb = skb->next) | 1248 | skb = skb->next) |
| 1249 | 1249 | ||
| 1250 | /*from STCP for fast SACK Process*/ | ||
| 1251 | #define sk_stream_for_retrans_queue_from(skb, sk) \ | ||
| 1252 | for (; (skb != (sk)->sk_send_head) && \ | ||
| 1253 | (skb != (struct sk_buff *)&(sk)->sk_write_queue); \ | ||
| 1254 | skb = skb->next) | ||
| 1255 | |||
| 1250 | /* | 1256 | /* |
| 1251 | * Default write policy as shown to user space via poll/select/SIGIO | 1257 | * Default write policy as shown to user space via poll/select/SIGIO |
| 1252 | */ | 1258 | */ |
diff --git a/include/net/tcp.h b/include/net/tcp.h index 6e6f0f3f1dd8..0f9848011972 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h | |||
| @@ -1207,6 +1207,15 @@ static inline void tcp_mib_init(void) | |||
| 1207 | TCP_ADD_STATS_USER(TCP_MIB_MAXCONN, -1); | 1207 | TCP_ADD_STATS_USER(TCP_MIB_MAXCONN, -1); |
| 1208 | } | 1208 | } |
| 1209 | 1209 | ||
| 1210 | /*from STCP */ | ||
| 1211 | static inline void clear_all_retrans_hints(struct tcp_sock *tp){ | ||
| 1212 | tp->lost_skb_hint = NULL; | ||
| 1213 | tp->scoreboard_skb_hint = NULL; | ||
| 1214 | tp->retransmit_skb_hint = NULL; | ||
| 1215 | tp->forward_skb_hint = NULL; | ||
| 1216 | tp->fastpath_skb_hint = NULL; | ||
| 1217 | } | ||
| 1218 | |||
| 1210 | /* /proc */ | 1219 | /* /proc */ |
| 1211 | enum tcp_seq_states { | 1220 | enum tcp_seq_states { |
| 1212 | TCP_SEQ_STATE_LISTENING, | 1221 | TCP_SEQ_STATE_LISTENING, |
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 34cfa58eab76..40a26b7157b4 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
| @@ -897,18 +897,32 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_ | |||
| 897 | int prior_fackets; | 897 | int prior_fackets; |
| 898 | u32 lost_retrans = 0; | 898 | u32 lost_retrans = 0; |
| 899 | int flag = 0; | 899 | int flag = 0; |
| 900 | int dup_sack = 0; | ||
| 900 | int i; | 901 | int i; |
| 901 | 902 | ||
| 902 | if (!tp->sacked_out) | 903 | if (!tp->sacked_out) |
| 903 | tp->fackets_out = 0; | 904 | tp->fackets_out = 0; |
| 904 | prior_fackets = tp->fackets_out; | 905 | prior_fackets = tp->fackets_out; |
| 905 | 906 | ||
| 906 | for (i=0; i<num_sacks; i++, sp++) { | 907 | /* SACK fastpath: |
| 907 | struct sk_buff *skb; | 908 | * if the only SACK change is the increase of the end_seq of |
| 908 | __u32 start_seq = ntohl(sp->start_seq); | 909 | * the first block then only apply that SACK block |
| 909 | __u32 end_seq = ntohl(sp->end_seq); | 910 | * and use retrans queue hinting otherwise slowpath */ |
| 910 | int fack_count = 0; | 911 | flag = 1; |
| 911 | int dup_sack = 0; | 912 | for (i = 0; i< num_sacks; i++) { |
| 913 | __u32 start_seq = ntohl(sp[i].start_seq); | ||
| 914 | __u32 end_seq = ntohl(sp[i].end_seq); | ||
| 915 | |||
| 916 | if (i == 0){ | ||
| 917 | if (tp->recv_sack_cache[i].start_seq != start_seq) | ||
| 918 | flag = 0; | ||
| 919 | } else { | ||
| 920 | if ((tp->recv_sack_cache[i].start_seq != start_seq) || | ||
| 921 | (tp->recv_sack_cache[i].end_seq != end_seq)) | ||
| 922 | flag = 0; | ||
| 923 | } | ||
| 924 | tp->recv_sack_cache[i].start_seq = start_seq; | ||
| 925 | tp->recv_sack_cache[i].end_seq = end_seq; | ||
| 912 | 926 | ||
| 913 | /* Check for D-SACK. */ | 927 | /* Check for D-SACK. */ |
| 914 | if (i == 0) { | 928 | if (i == 0) { |
| @@ -940,15 +954,58 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_ | |||
| 940 | if (before(ack, prior_snd_una - tp->max_window)) | 954 | if (before(ack, prior_snd_una - tp->max_window)) |
| 941 | return 0; | 955 | return 0; |
| 942 | } | 956 | } |
| 957 | } | ||
| 958 | |||
| 959 | if (flag) | ||
| 960 | num_sacks = 1; | ||
| 961 | else { | ||
| 962 | int j; | ||
| 963 | tp->fastpath_skb_hint = NULL; | ||
| 964 | |||
| 965 | /* order SACK blocks to allow in order walk of the retrans queue */ | ||
| 966 | for (i = num_sacks-1; i > 0; i--) { | ||
| 967 | for (j = 0; j < i; j++){ | ||
| 968 | if (after(ntohl(sp[j].start_seq), | ||
| 969 | ntohl(sp[j+1].start_seq))){ | ||
| 970 | sp[j].start_seq = htonl(tp->recv_sack_cache[j+1].start_seq); | ||
| 971 | sp[j].end_seq = htonl(tp->recv_sack_cache[j+1].end_seq); | ||
| 972 | sp[j+1].start_seq = htonl(tp->recv_sack_cache[j].start_seq); | ||
| 973 | sp[j+1].end_seq = htonl(tp->recv_sack_cache[j].end_seq); | ||
| 974 | } | ||
| 975 | |||
| 976 | } | ||
| 977 | } | ||
| 978 | } | ||
| 979 | |||
| 980 | /* clear flag as used for different purpose in following code */ | ||
| 981 | flag = 0; | ||
| 982 | |||
| 983 | for (i=0; i<num_sacks; i++, sp++) { | ||
| 984 | struct sk_buff *skb; | ||
| 985 | __u32 start_seq = ntohl(sp->start_seq); | ||
| 986 | __u32 end_seq = ntohl(sp->end_seq); | ||
| 987 | int fack_count; | ||
| 988 | |||
| 989 | /* Use SACK fastpath hint if valid */ | ||
| 990 | if (tp->fastpath_skb_hint) { | ||
| 991 | skb = tp->fastpath_skb_hint; | ||
| 992 | fack_count = tp->fastpath_cnt_hint; | ||
| 993 | } else { | ||
| 994 | skb = sk->sk_write_queue.next; | ||
| 995 | fack_count = 0; | ||
| 996 | } | ||
| 943 | 997 | ||
| 944 | /* Event "B" in the comment above. */ | 998 | /* Event "B" in the comment above. */ |
| 945 | if (after(end_seq, tp->high_seq)) | 999 | if (after(end_seq, tp->high_seq)) |
| 946 | flag |= FLAG_DATA_LOST; | 1000 | flag |= FLAG_DATA_LOST; |
| 947 | 1001 | ||
| 948 | sk_stream_for_retrans_queue(skb, sk) { | 1002 | sk_stream_for_retrans_queue_from(skb, sk) { |
| 949 | int in_sack, pcount; | 1003 | int in_sack, pcount; |
| 950 | u8 sacked; | 1004 | u8 sacked; |
| 951 | 1005 | ||
| 1006 | tp->fastpath_skb_hint = skb; | ||
| 1007 | tp->fastpath_cnt_hint = fack_count; | ||
| 1008 | |||
| 952 | /* The retransmission queue is always in order, so | 1009 | /* The retransmission queue is always in order, so |
| 953 | * we can short-circuit the walk early. | 1010 | * we can short-circuit the walk early. |
| 954 | */ | 1011 | */ |
| @@ -1023,6 +1080,9 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_ | |||
| 1023 | TCP_SKB_CB(skb)->sacked &= ~(TCPCB_LOST|TCPCB_SACKED_RETRANS); | 1080 | TCP_SKB_CB(skb)->sacked &= ~(TCPCB_LOST|TCPCB_SACKED_RETRANS); |
| 1024 | tp->lost_out -= tcp_skb_pcount(skb); | 1081 | tp->lost_out -= tcp_skb_pcount(skb); |
| 1025 | tp->retrans_out -= tcp_skb_pcount(skb); | 1082 | tp->retrans_out -= tcp_skb_pcount(skb); |
| 1083 | |||
| 1084 | /* clear lost hint */ | ||
| 1085 | tp->retransmit_skb_hint = NULL; | ||
| 1026 | } | 1086 | } |
| 1027 | } else { | 1087 | } else { |
| 1028 | /* New sack for not retransmitted frame, | 1088 | /* New sack for not retransmitted frame, |
| @@ -1035,6 +1095,9 @@ tcp_sacktag_write_queue(struct sock *sk, struct sk_buff *ack_skb, u32 prior_snd_ | |||
| 1035 | if (sacked & TCPCB_LOST) { | 1095 | if (sacked & TCPCB_LOST) { |
| 1036 | TCP_SKB_CB(skb)->sacked &= ~TCPCB_LOST; | 1096 | TCP_SKB_CB(skb)->sacked &= ~TCPCB_LOST; |
| 1037 | tp->lost_out -= tcp_skb_pcount(skb); | 1097 | tp->lost_out -= tcp_skb_pcount(skb); |
