aboutsummaryrefslogtreecommitdiffstats
path: root/net/dccp/input.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/dccp/input.c')
-rw-r--r--net/dccp/input.c54
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;
205check_seq: 206check_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) {
207send_sync: 209send_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
577EXPORT_SYMBOL_GPL(dccp_rcv_state_process); 587EXPORT_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 */
596u32 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
627EXPORT_SYMBOL_GPL(dccp_sample_rtt);