diff options
Diffstat (limited to 'net/dccp')
-rw-r--r-- | net/dccp/ccids/ccid3.c | 39 |
1 files changed, 22 insertions, 17 deletions
diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index bdd13de4f422..89ef1183e48c 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c | |||
@@ -785,12 +785,12 @@ static u32 ccid3_hc_rx_calc_first_li(struct sock *sk) | |||
785 | { | 785 | { |
786 | struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk); | 786 | struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk); |
787 | struct dccp_rx_hist_entry *entry, *next, *tail = NULL; | 787 | struct dccp_rx_hist_entry *entry, *next, *tail = NULL; |
788 | u32 rtt, delta, x_recv, fval, p, tmp2; | 788 | u32 rtt, delta, x_recv, p; |
789 | struct timeval tstamp = { 0, }; | 789 | struct timeval tstamp = { 0, }; |
790 | int interval = 0; | 790 | int interval = 0; |
791 | int win_count = 0; | 791 | int win_count = 0; |
792 | int step = 0; | 792 | int step = 0; |
793 | u64 tmp1; | 793 | u64 fval; |
794 | 794 | ||
795 | list_for_each_entry_safe(entry, next, &hcrx->ccid3hcrx_hist, | 795 | list_for_each_entry_safe(entry, next, &hcrx->ccid3hcrx_hist, |
796 | dccphrx_node) { | 796 | dccphrx_node) { |
@@ -834,30 +834,35 @@ found: | |||
834 | ccid3_pr_debug("%s, sk=%p, approximated RTT to %uus\n", | 834 | ccid3_pr_debug("%s, sk=%p, approximated RTT to %uus\n", |
835 | dccp_role(sk), sk, rtt); | 835 | dccp_role(sk), sk, rtt); |
836 | 836 | ||
837 | if (rtt == 0) { | 837 | /* |
838 | DCCP_WARN("RTT==0, setting to 1\n"); | 838 | * Determine the length of the first loss interval via inverse lookup. |
839 | rtt = 1; | 839 | * Assume that X_recv can be computed by the throughput equation |
840 | * s | ||
841 | * X_recv = -------- | ||
842 | * R * fval | ||
843 | * Find some p such that f(p) = fval; return 1/p [RFC 3448, 6.3.1]. | ||
844 | */ | ||
845 | if (rtt == 0) { /* would result in divide-by-zero */ | ||
846 | DCCP_WARN("RTT==0, returning 1/p = 1\n"); | ||
847 | return 1000000; | ||
840 | } | 848 | } |
841 | 849 | ||
842 | dccp_timestamp(sk, &tstamp); | 850 | dccp_timestamp(sk, &tstamp); |
843 | delta = timeval_delta(&tstamp, &hcrx->ccid3hcrx_tstamp_last_feedback); | 851 | delta = timeval_delta(&tstamp, &hcrx->ccid3hcrx_tstamp_last_feedback); |
844 | x_recv = scaled_div32(hcrx->ccid3hcrx_bytes_recv, delta); | 852 | x_recv = scaled_div32(hcrx->ccid3hcrx_bytes_recv, delta); |
845 | 853 | ||
846 | if (x_recv == 0) | 854 | if (x_recv == 0) { /* would also trigger divide-by-zero */ |
847 | x_recv = hcrx->ccid3hcrx_x_recv; | 855 | DCCP_WARN("X_recv==0\n"); |
848 | 856 | if ((x_recv = hcrx->ccid3hcrx_x_recv) == 0) { | |
849 | tmp1 = (u64)x_recv * (u64)rtt; | 857 | DCCP_BUG("stored value of X_recv is zero"); |
850 | do_div(tmp1,10000000); | 858 | return 1000000; |
851 | tmp2 = (u32)tmp1; | 859 | } |
852 | |||
853 | if (!tmp2) { | ||
854 | DCCP_CRIT("tmp2 = 0, x_recv = %u, rtt =%u\n", x_recv, rtt); | ||
855 | return ~0; | ||
856 | } | 860 | } |
857 | 861 | ||
858 | fval = (hcrx->ccid3hcrx_s * 100000) / tmp2; | 862 | fval = scaled_div(hcrx->ccid3hcrx_s, rtt); |
859 | /* do not alter order above or you will get overflow on 32 bit */ | 863 | fval = scaled_div32(fval, x_recv); |
860 | p = tfrc_calc_x_reverse_lookup(fval); | 864 | p = tfrc_calc_x_reverse_lookup(fval); |
865 | |||
861 | ccid3_pr_debug("%s, sk=%p, receive rate=%u bytes/s, implied " | 866 | ccid3_pr_debug("%s, sk=%p, receive rate=%u bytes/s, implied " |
862 | "loss rate=%u\n", dccp_role(sk), sk, x_recv, p); | 867 | "loss rate=%u\n", dccp_role(sk), sk, x_recv, p); |
863 | 868 | ||