X-Git-Url: https://git.openpandora.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=net%2Fdccp%2Finput.c;h=da6ec185ed5b5826e6df5b6d58f7870e26330cb9;hb=c58b8e4a25a1ba347a0e5d21984c97bd296f1691;hp=7371a2f3acf4f2826f4b47124a56fc3d0879af37;hpb=ea14fad0d416354a4e9bb1a04f32acba706f9548;p=pandora-kernel.git diff --git a/net/dccp/input.c b/net/dccp/input.c index 7371a2f3acf4..da6ec185ed5b 100644 --- a/net/dccp/input.c +++ b/net/dccp/input.c @@ -1,6 +1,6 @@ /* * net/dccp/input.c - * + * * An implementation of the DCCP protocol * Arnaldo Carvalho de Melo * @@ -82,16 +82,17 @@ static int dccp_check_seqno(struct sock *sk, struct sk_buff *skb) * Otherwise, * Drop packet and return */ - if (dh->dccph_type == DCCP_PKT_SYNC || + if (dh->dccph_type == DCCP_PKT_SYNC || dh->dccph_type == DCCP_PKT_SYNCACK) { if (between48(DCCP_SKB_CB(skb)->dccpd_ack_seq, dp->dccps_awl, dp->dccps_awh) && - !before48(DCCP_SKB_CB(skb)->dccpd_seq, dp->dccps_swl)) + dccp_delta_seqno(dp->dccps_swl, + DCCP_SKB_CB(skb)->dccpd_seq) >= 0) dccp_update_gsr(sk, DCCP_SKB_CB(skb)->dccpd_seq); else return -1; } - + /* * Step 6: Check sequence numbers * Let LSWL = S.SWL and LAWL = S.AWL @@ -136,7 +137,7 @@ static int dccp_check_seqno(struct sock *sk, struct sk_buff *skb) (unsigned long long) DCCP_SKB_CB(skb)->dccpd_seq, (unsigned long long) dp->dccps_swh, (DCCP_SKB_CB(skb)->dccpd_ack_seq == - DCCP_PKT_WITHOUT_ACK_SEQ) ? "doesn't exist" : "exists", + DCCP_PKT_WITHOUT_ACK_SEQ) ? "doesn't exist" : "exists", (unsigned long long) lawl, (unsigned long long) DCCP_SKB_CB(skb)->dccpd_ack_seq, (unsigned long long) dp->dccps_awh); @@ -185,8 +186,8 @@ static int __dccp_rcv_established(struct sock *sk, struct sk_buff *skb, dccp_rcv_close(sk, skb); return 0; case DCCP_PKT_REQUEST: - /* Step 7 - * or (S.is_server and P.type == Response) + /* Step 7 + * or (S.is_server and P.type == Response) * or (S.is_client and P.type == Request) * or (S.state >= OPEN and P.type == Request * and P.seqno >= S.OSR) @@ -203,7 +204,8 @@ static int __dccp_rcv_established(struct sock *sk, struct sk_buff *skb, if (dp->dccps_role != DCCP_ROLE_CLIENT) goto send_sync; check_seq: - if (!before48(DCCP_SKB_CB(skb)->dccpd_seq, dp->dccps_osr)) { + if (dccp_delta_seqno(dp->dccps_osr, + DCCP_SKB_CB(skb)->dccpd_seq) >= 0) { send_sync: dccp_send_sync(sk, DCCP_SKB_CB(skb)->dccpd_seq, DCCP_PKT_SYNC); @@ -264,7 +266,7 @@ static int dccp_rcv_request_sent_state_process(struct sock *sk, const struct dccp_hdr *dh, const unsigned len) { - /* + /* * Step 4: Prepare sequence numbers in REQUEST * If S.state == REQUEST, * If (P.type == Response or P.type == Reset) @@ -298,11 +300,19 @@ static int dccp_rcv_request_sent_state_process(struct sock *sk, if (dccp_parse_options(sk, skb)) goto out_invalid_packet; - if (dccp_msk(sk)->dccpms_send_ack_vector && - dccp_ackvec_add(dp->dccps_hc_rx_ackvec, sk, - DCCP_SKB_CB(skb)->dccpd_seq, - DCCP_ACKVEC_STATE_RECEIVED)) - goto out_invalid_packet; /* FIXME: change error code */ + /* Obtain RTT sample from SYN exchange (used by CCID 3) */ + if (dp->dccps_options_received.dccpor_timestamp_echo) { + struct timeval now; + + dccp_timestamp(sk, &now); + dp->dccps_syn_rtt = dccp_sample_rtt(sk, &now, NULL); + } + + if (dccp_msk(sk)->dccpms_send_ack_vector && + dccp_ackvec_add(dp->dccps_hc_rx_ackvec, sk, + DCCP_SKB_CB(skb)->dccpd_seq, + DCCP_ACKVEC_STATE_RECEIVED)) + goto out_invalid_packet; /* FIXME: change error code */ dp->dccps_isr = DCCP_SKB_CB(skb)->dccpd_seq; dccp_update_gsr(sk, dp->dccps_isr); @@ -332,7 +342,7 @@ static int dccp_rcv_request_sent_state_process(struct sock *sk, * from the Response * / * S.state := PARTOPEN * Set PARTOPEN timer - * Continue with S.state == PARTOPEN + * Continue with S.state == PARTOPEN * / * Step 12 will send the Ack completing the * three-way handshake * / */ @@ -363,7 +373,7 @@ static int dccp_rcv_request_sent_state_process(struct sock *sk, */ __kfree_skb(skb); return 0; - } + } dccp_send_ack(sk); return -1; } @@ -371,7 +381,7 @@ static int dccp_rcv_request_sent_state_process(struct sock *sk, out_invalid_packet: /* dccp_v4_do_rcv will send a reset */ DCCP_SKB_CB(skb)->dccpd_reset_code = DCCP_RESET_CODE_PACKET_ERROR; - return 1; + return 1; } static int dccp_rcv_respond_partopen_state_process(struct sock *sk, @@ -478,11 +488,11 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb, if (dcb->dccpd_ack_seq != DCCP_PKT_WITHOUT_ACK_SEQ) dccp_event_ack_recv(sk, skb); - if (dccp_msk(sk)->dccpms_send_ack_vector && + if (dccp_msk(sk)->dccpms_send_ack_vector && dccp_ackvec_add(dp->dccps_hc_rx_ackvec, sk, - DCCP_SKB_CB(skb)->dccpd_seq, - DCCP_ACKVEC_STATE_RECEIVED)) - goto discard; + DCCP_SKB_CB(skb)->dccpd_seq, + DCCP_ACKVEC_STATE_RECEIVED)) + goto discard; ccid_hc_rx_packet_recv(dp->dccps_hc_rx_ccid, sk, skb); ccid_hc_tx_packet_recv(dp->dccps_hc_tx_ccid, sk, skb); @@ -567,7 +577,7 @@ int dccp_rcv_state_process(struct sock *sk, struct sk_buff *skb, } } - if (!queued) { + if (!queued) { discard: __kfree_skb(skb); } @@ -575,3 +585,43 @@ discard: } EXPORT_SYMBOL_GPL(dccp_rcv_state_process); + +/** + * dccp_sample_rtt - Sample RTT from packet exchange + * + * @sk: connected dccp_sock + * @t_recv: receive timestamp of packet with timestamp echo + * @t_hist: packet history timestamp or NULL + */ +u32 dccp_sample_rtt(struct sock *sk, struct timeval *t_recv, + struct timeval *t_hist) +{ + struct dccp_sock *dp = dccp_sk(sk); + struct dccp_options_received *or = &dp->dccps_options_received; + suseconds_t delta; + + if (t_hist == NULL) { + if (!or->dccpor_timestamp_echo) { + DCCP_WARN("packet without timestamp echo\n"); + return DCCP_SANE_RTT_MAX; + } + timeval_sub_usecs(t_recv, or->dccpor_timestamp_echo * 10); + delta = timeval_usecs(t_recv); + } else + delta = timeval_delta(t_recv, t_hist); + + delta -= or->dccpor_elapsed_time * 10; /* either set or 0 */ + + if (unlikely(delta <= 0)) { + DCCP_WARN("unusable RTT sample %ld, using min\n", (long)delta); + return DCCP_SANE_RTT_MIN; + } + if (unlikely(delta - (suseconds_t)DCCP_SANE_RTT_MAX > 0)) { + DCCP_WARN("RTT sample %ld too large, using max\n", (long)delta); + return DCCP_SANE_RTT_MAX; + } + + return delta; +} + +EXPORT_SYMBOL_GPL(dccp_sample_rtt);