aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/tcp.h15
-rw-r--r--include/net/sock.h6
-rw-r--r--include/net/tcp.h9
-rw-r--r--net/ipv4/tcp_input.c144
-rw-r--r--net/ipv4/tcp_output.c54
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 */
1211static 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 */
1211enum tcp_seq_states { 1220enum 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);