diff options
Diffstat (limited to 'net/dccp/input.c')
-rw-r--r-- | net/dccp/input.c | 54 |
1 files changed, 52 insertions, 2 deletions
diff --git a/net/dccp/input.c b/net/dccp/input.c index 78b043c458bf..da6ec185ed5b 100644 --- a/net/dccp/input.c +++ b/net/dccp/input.c | |||
@@ -86,7 +86,8 @@ static int dccp_check_seqno(struct sock *sk, struct sk_buff *skb) | |||
86 | dh->dccph_type == DCCP_PKT_SYNCACK) { | 86 | dh->dccph_type == DCCP_PKT_SYNCACK) { |
87 | if (between48(DCCP_SKB_CB(skb)->dccpd_ack_seq, | 87 | if (between48(DCCP_SKB_CB(skb)->dccpd_ack_seq, |
88 | dp->dccps_awl, dp->dccps_awh) && | 88 | dp->dccps_awl, dp->dccps_awh) && |
89 | !before48(DCCP_SKB_CB(skb)->dccpd_seq, dp->dccps_swl)) | 89 | dccp_delta_seqno(dp->dccps_swl, |
90 | DCCP_SKB_CB(skb)->dccpd_seq) >= 0) | ||
90 | dccp_update_gsr(sk, DCCP_SKB_CB(skb)->dccpd_seq); | 91 | dccp_update_gsr(sk, DCCP_SKB_CB(skb)->dccpd_seq); |
91 | else | 92 | else |
92 | return -1; | 93 | return -1; |
@@ -203,7 +204,8 @@ static int __dccp_rcv_established(struct sock *sk, struct sk_buff *skb, | |||
203 | if (dp->dccps_role != DCCP_ROLE_CLIENT) | 204 | if (dp->dccps_role != DCCP_ROLE_CLIENT) |
204 | goto send_sync; | 205 | goto send_sync; |
205 | check_seq: | 206 | check_seq: |
206 | if (!before48(DCCP_SKB_CB(skb)->dccpd_seq, dp->dccps_osr)) { | 207 | if (dccp_delta_seqno(dp->dccps_osr, |
208 | DCCP_SKB_CB(skb)->dccpd_seq) >= 0) { | ||
207 | send_sync: | 209 | send_sync: |
208 | dccp_send_sync(sk, DCCP_SKB_CB(skb)->dccpd_seq, | 210 | dccp_send_sync(sk, DCCP_SKB_CB(skb)->dccpd_seq, |
209 | DCCP_PKT_SYNC); | 211 | DCCP_PKT_SYNC); |
@@ -298,6 +300,14 @@ static int dccp_rcv_request_sent_state_process(struct sock *sk, | |||
298 | if (dccp_parse_options(sk, skb)) | 300 | if (dccp_parse_options(sk, skb)) |
299 | goto out_invalid_packet; | 301 | goto out_invalid_packet; |
300 | 302 | ||
303 | /* Obtain RTT sample from SYN exchange (used by CCID 3) */ | ||
304 | if (dp->dccps_options_received.dccpor_timestamp_echo) { | ||
305 | struct timeval now; | ||
306 | |||
307 | dccp_timestamp(sk, &now); | ||
308 | dp->dccps_syn_rtt = dccp_sample_rtt(sk, &now, NULL); | ||
309 | } | ||
310 | |||
301 | if (dccp_msk(sk)->dccpms_send_ack_vector && | 311 | if (dccp_msk(sk)->dccpms_send_ack_vector && |
302 | dccp_ackvec_add(dp->dccps_hc_rx_ackvec, sk, | 312 | dccp_ackvec_add(dp->dccps_hc_rx_ackvec, sk, |
303 | DCCP_SKB_CB(skb)->dccpd_seq, | 313 | DCCP_SKB_CB(skb)->dccpd_seq, |
@@ -575,3 +585,43 @@ discard: | |||
575 | } | 585 | } |
576 | 586 | ||
577 | EXPORT_SYMBOL_GPL(dccp_rcv_state_process); | 587 | EXPORT_SYMBOL_GPL(dccp_rcv_state_process); |
588 | |||
589 | /** | ||
590 | * dccp_sample_rtt - Sample RTT from packet exchange | ||
591 | * | ||
592 | * @sk: connected dccp_sock | ||
593 | * @t_recv: receive timestamp of packet with timestamp echo | ||
594 | * @t_hist: packet history timestamp or NULL | ||
595 | */ | ||
596 | u32 dccp_sample_rtt(struct sock *sk, struct timeval *t_recv, | ||
597 | struct timeval *t_hist) | ||
598 | { | ||
599 | struct dccp_sock *dp = dccp_sk(sk); | ||
600 | struct dccp_options_received *or = &dp->dccps_options_received; | ||
601 | suseconds_t delta; | ||
602 | |||
603 | if (t_hist == NULL) { | ||
604 | if (!or->dccpor_timestamp_echo) { | ||
605 | DCCP_WARN("packet without timestamp echo\n"); | ||
606 | return DCCP_SANE_RTT_MAX; | ||
607 | } | ||
608 | timeval_sub_usecs(t_recv, or->dccpor_timestamp_echo * 10); | ||
609 | delta = timeval_usecs(t_recv); | ||
610 | } else | ||
611 | delta = timeval_delta(t_recv, t_hist); | ||
612 | |||
613 | delta -= or->dccpor_elapsed_time * 10; /* either set or 0 */ | ||
614 | |||
615 | if (unlikely(delta <= 0)) { | ||
616 | DCCP_WARN("unusable RTT sample %ld, using min\n", (long)delta); | ||
617 | return DCCP_SANE_RTT_MIN; | ||
618 | } | ||
619 | if (unlikely(delta - (suseconds_t)DCCP_SANE_RTT_MAX > 0)) { | ||
620 | DCCP_WARN("RTT sample %ld too large, using max\n", (long)delta); | ||
621 | return DCCP_SANE_RTT_MAX; | ||
622 | } | ||
623 | |||
624 | return delta; | ||
625 | } | ||
626 | |||
627 | EXPORT_SYMBOL_GPL(dccp_sample_rtt); | ||