aboutsummaryrefslogtreecommitdiffstats
path: root/net/dccp/ccids/ccid3.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/dccp/ccids/ccid3.c')
-rw-r--r--net/dccp/ccids/ccid3.c72
1 files changed, 60 insertions, 12 deletions
diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c
index 8266dfde89c1..8f112d18d450 100644
--- a/net/dccp/ccids/ccid3.c
+++ b/net/dccp/ccids/ccid3.c
@@ -1,6 +1,7 @@
1/* 1/*
2 * net/dccp/ccids/ccid3.c 2 * net/dccp/ccids/ccid3.c
3 * 3 *
4 * Copyright (c) 2007 The University of Aberdeen, Scotland, UK
4 * Copyright (c) 2005-7 The University of Waikato, Hamilton, New Zealand. 5 * Copyright (c) 2005-7 The University of Waikato, Hamilton, New Zealand.
5 * Copyright (c) 2005-7 Ian McDonald <ian.mcdonald@jandi.co.nz> 6 * Copyright (c) 2005-7 Ian McDonald <ian.mcdonald@jandi.co.nz>
6 * 7 *
@@ -33,11 +34,7 @@
33 * along with this program; if not, write to the Free Software 34 * along with this program; if not, write to the Free Software
34 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 35 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
35 */ 36 */
36#include "../ccid.h"
37#include "../dccp.h" 37#include "../dccp.h"
38#include "lib/packet_history.h"
39#include "lib/loss_interval.h"
40#include "lib/tfrc.h"
41#include "ccid3.h" 38#include "ccid3.h"
42 39
43#include <asm/unaligned.h> 40#include <asm/unaligned.h>
@@ -757,6 +754,46 @@ static int ccid3_hc_rx_insert_options(struct sock *sk, struct sk_buff *skb)
757 return 0; 754 return 0;
758} 755}
759 756
757/** ccid3_first_li - Implements [RFC 3448, 6.3.1]
758 *
759 * Determine the length of the first loss interval via inverse lookup.
760 * Assume that X_recv can be computed by the throughput equation
761 * s
762 * X_recv = --------
763 * R * fval
764 * Find some p such that f(p) = fval; return 1/p (scaled).
765 */
766static u32 ccid3_first_li(struct sock *sk)
767{
768 struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
769 u32 x_recv, p, delta;
770 u64 fval;
771
772 if (hcrx->ccid3hcrx_rtt == 0) {
773 DCCP_WARN("No RTT estimate available, using fallback RTT\n");
774 hcrx->ccid3hcrx_rtt = DCCP_FALLBACK_RTT;
775 }
776
777 delta = ktime_to_us(net_timedelta(hcrx->ccid3hcrx_tstamp_last_feedback));
778 x_recv = scaled_div32(hcrx->ccid3hcrx_bytes_recv, delta);
779 if (x_recv == 0) { /* would also trigger divide-by-zero */
780 DCCP_WARN("X_recv==0\n");
781 if ((x_recv = hcrx->ccid3hcrx_x_recv) == 0) {
782 DCCP_BUG("stored value of X_recv is zero");
783 return ~0U;
784 }
785 }
786
787 fval = scaled_div(hcrx->ccid3hcrx_s, hcrx->ccid3hcrx_rtt);
788 fval = scaled_div32(fval, x_recv);
789 p = tfrc_calc_x_reverse_lookup(fval);
790
791 ccid3_pr_debug("%s(%p), receive rate=%u bytes/s, implied "
792 "loss rate=%u\n", dccp_role(sk), sk, x_recv, p);
793
794 return p == 0 ? ~0U : scaled_div(1, p);
795}
796
760static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) 797static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
761{ 798{
762 struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk); 799 struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk);
@@ -794,6 +831,14 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
794 /* 831 /*
795 * Handle pending losses and otherwise check for new loss 832 * Handle pending losses and otherwise check for new loss
796 */ 833 */
834 if (tfrc_rx_hist_loss_pending(&hcrx->ccid3hcrx_hist) &&
835 tfrc_rx_handle_loss(&hcrx->ccid3hcrx_hist,
836 &hcrx->ccid3hcrx_li_hist,
837 skb, ndp, ccid3_first_li, sk) ) {
838 do_feedback = CCID3_FBACK_PARAM_CHANGE;
839 goto done_receiving;
840 }
841
797 if (tfrc_rx_hist_new_loss_indicated(&hcrx->ccid3hcrx_hist, skb, ndp)) 842 if (tfrc_rx_hist_new_loss_indicated(&hcrx->ccid3hcrx_hist, skb, ndp))
798 goto update_records; 843 goto update_records;
799 844
@@ -803,7 +848,7 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
803 if (unlikely(!is_data_packet)) 848 if (unlikely(!is_data_packet))
804 goto update_records; 849 goto update_records;
805 850
806 if (list_empty(&hcrx->ccid3hcrx_li_hist)) { /* no loss so far: p = 0 */ 851 if (!tfrc_lh_is_initialised(&hcrx->ccid3hcrx_li_hist)) {
807 const u32 sample = tfrc_rx_hist_sample_rtt(&hcrx->ccid3hcrx_hist, skb); 852 const u32 sample = tfrc_rx_hist_sample_rtt(&hcrx->ccid3hcrx_hist, skb);
808 /* 853 /*
809 * Empty loss history: no loss so far, hence p stays 0. 854 * Empty loss history: no loss so far, hence p stays 0.
@@ -812,6 +857,13 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
812 */ 857 */
813 if (sample != 0) 858 if (sample != 0)
814 hcrx->ccid3hcrx_rtt = tfrc_ewma(hcrx->ccid3hcrx_rtt, sample, 9); 859 hcrx->ccid3hcrx_rtt = tfrc_ewma(hcrx->ccid3hcrx_rtt, sample, 9);
860
861 } else if (tfrc_lh_update_i_mean(&hcrx->ccid3hcrx_li_hist, skb)) {
862 /*
863 * Step (3) of [RFC 3448, 6.1]: Recompute I_mean and, if I_mean
864 * has decreased (resp. p has increased), send feedback now.
865 */
866 do_feedback = CCID3_FBACK_PARAM_CHANGE;
815 } 867 }
816 868
817 /* 869 /*
@@ -823,6 +875,7 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
823update_records: 875update_records:
824 tfrc_rx_hist_add_packet(&hcrx->ccid3hcrx_hist, skb, ndp); 876 tfrc_rx_hist_add_packet(&hcrx->ccid3hcrx_hist, skb, ndp);
825 877
878done_receiving:
826 if (do_feedback) 879 if (do_feedback)
827 ccid3_hc_rx_send_feedback(sk, skb, do_feedback); 880 ccid3_hc_rx_send_feedback(sk, skb, do_feedback);
828} 881}
@@ -831,10 +884,8 @@ static int ccid3_hc_rx_init(struct ccid *ccid, struct sock *sk)
831{ 884{
832 struct ccid3_hc_rx_sock *hcrx = ccid_priv(ccid); 885 struct ccid3_hc_rx_sock *hcrx = ccid_priv(ccid);
833 886
834 ccid3_pr_debug("entry\n");
835
836 hcrx->ccid3hcrx_state = TFRC_RSTATE_NO_DATA; 887 hcrx->ccid3hcrx_state = TFRC_RSTATE_NO_DATA;
837 INIT_LIST_HEAD(&hcrx->ccid3hcrx_li_hist); 888 tfrc_lh_init(&hcrx->ccid3hcrx_li_hist);
838 return tfrc_rx_hist_alloc(&hcrx->ccid3hcrx_hist); 889 return tfrc_rx_hist_alloc(&hcrx->ccid3hcrx_hist);
839} 890}
840 891
@@ -844,11 +895,8 @@ static void ccid3_hc_rx_exit(struct sock *sk)
844 895
845 ccid3_hc_rx_set_state(sk, TFRC_RSTATE_TERM); 896 ccid3_hc_rx_set_state(sk, TFRC_RSTATE_TERM);
846 897
847 /* Empty packet history */
848 tfrc_rx_hist_purge(&hcrx->ccid3hcrx_hist); 898 tfrc_rx_hist_purge(&hcrx->ccid3hcrx_hist);
849 899 tfrc_lh_cleanup(&hcrx->ccid3hcrx_li_hist);
850 /* Empty loss interval history */
851 dccp_li_hist_purge(&hcrx->ccid3hcrx_li_hist);
852} 900}
853 901
854static void ccid3_hc_rx_get_info(struct sock *sk, struct tcp_info *info) 902static void ccid3_hc_rx_get_info(struct sock *sk, struct tcp_info *info)