aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/dccp/ccids/ccid3.c72
-rw-r--r--net/dccp/ccids/ccid3.h10
-rw-r--r--net/dccp/ccids/lib/loss_interval.c18
-rw-r--r--net/dccp/ccids/lib/tfrc.c10
-rw-r--r--net/dccp/dccp.h7
5 files changed, 84 insertions, 33 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)
diff --git a/net/dccp/ccids/ccid3.h b/net/dccp/ccids/ccid3.h
index 6ceeb8013f58..e9f6ff4f0552 100644
--- a/net/dccp/ccids/ccid3.h
+++ b/net/dccp/ccids/ccid3.h
@@ -41,7 +41,7 @@
41#include <linux/list.h> 41#include <linux/list.h>
42#include <linux/types.h> 42#include <linux/types.h>
43#include <linux/tfrc.h> 43#include <linux/tfrc.h>
44#include "lib/packet_history.h" 44#include "lib/tfrc.h"
45#include "../ccid.h" 45#include "../ccid.h"
46 46
47/* Two seconds as per RFC 3448 4.2 */ 47/* Two seconds as per RFC 3448 4.2 */
@@ -141,8 +141,8 @@ enum ccid3_hc_rx_states {
141 * @ccid3hcrx_bytes_recv - Total sum of DCCP payload bytes 141 * @ccid3hcrx_bytes_recv - Total sum of DCCP payload bytes
142 * @ccid3hcrx_tstamp_last_feedback - Time at which last feedback was sent 142 * @ccid3hcrx_tstamp_last_feedback - Time at which last feedback was sent
143 * @ccid3hcrx_tstamp_last_ack - Time at which last feedback was sent 143 * @ccid3hcrx_tstamp_last_ack - Time at which last feedback was sent
144 * @ccid3hcrx_hist - Packet history 144 * @ccid3hcrx_hist - Packet history (loss detection + RTT sampling)
145 * @ccid3hcrx_li_hist - Loss Interval History 145 * @ccid3hcrx_li_hist - Loss Interval database
146 * @ccid3hcrx_s - Received packet size in bytes 146 * @ccid3hcrx_s - Received packet size in bytes
147 * @ccid3hcrx_pinv - Inverse of Loss Event Rate (RFC 4342, sec. 8.5) 147 * @ccid3hcrx_pinv - Inverse of Loss Event Rate (RFC 4342, sec. 8.5)
148 */ 148 */
@@ -156,9 +156,9 @@ struct ccid3_hc_rx_sock {
156 u32 ccid3hcrx_bytes_recv; 156 u32 ccid3hcrx_bytes_recv;
157 ktime_t ccid3hcrx_tstamp_last_feedback; 157 ktime_t ccid3hcrx_tstamp_last_feedback;
158 struct tfrc_rx_hist ccid3hcrx_hist; 158 struct tfrc_rx_hist ccid3hcrx_hist;
159 struct list_head ccid3hcrx_li_hist; 159 struct tfrc_loss_hist ccid3hcrx_li_hist;
160 u16 ccid3hcrx_s; 160 u16 ccid3hcrx_s;
161 u32 ccid3hcrx_pinv; 161#define ccid3hcrx_pinv ccid3hcrx_li_hist.i_mean
162}; 162};
163 163
164static inline struct ccid3_hc_rx_sock *ccid3_hc_rx_sk(const struct sock *sk) 164static inline struct ccid3_hc_rx_sock *ccid3_hc_rx_sk(const struct sock *sk)
diff --git a/net/dccp/ccids/lib/loss_interval.c b/net/dccp/ccids/lib/loss_interval.c
index 39980d1f5352..8b962c1f14b8 100644
--- a/net/dccp/ccids/lib/loss_interval.c
+++ b/net/dccp/ccids/lib/loss_interval.c
@@ -435,18 +435,18 @@ int tfrc_lh_interval_add(struct tfrc_loss_hist *lh, struct tfrc_rx_hist *rh,
435} 435}
436EXPORT_SYMBOL_GPL(tfrc_lh_interval_add); 436EXPORT_SYMBOL_GPL(tfrc_lh_interval_add);
437 437
438int __init dccp_li_init(void) 438int __init tfrc_li_init(void)
439{ 439{
440 dccp_li_cachep = kmem_cache_create("dccp_li_hist", 440 tfrc_lh_slab = kmem_cache_create("tfrc_li_hist",
441 sizeof(struct dccp_li_hist_entry), 441 sizeof(struct tfrc_loss_interval), 0,
442 0, SLAB_HWCACHE_ALIGN, NULL); 442 SLAB_HWCACHE_ALIGN, NULL);
443 return dccp_li_cachep == NULL ? -ENOBUFS : 0; 443 return tfrc_lh_slab == NULL ? -ENOBUFS : 0;
444} 444}
445 445
446void dccp_li_exit(void) 446void tfrc_li_exit(void)
447{ 447{
448 if (dccp_li_cachep != NULL) { 448 if (tfrc_lh_slab != NULL) {
449 kmem_cache_destroy(dccp_li_cachep); 449 kmem_cache_destroy(tfrc_lh_slab);
450 dccp_li_cachep = NULL; 450 tfrc_lh_slab = NULL;
451 } 451 }
452} 452}
diff --git a/net/dccp/ccids/lib/tfrc.c b/net/dccp/ccids/lib/tfrc.c
index 20763fa75d44..d1dfbb8de64c 100644
--- a/net/dccp/ccids/lib/tfrc.c
+++ b/net/dccp/ccids/lib/tfrc.c
@@ -19,12 +19,12 @@ extern void tfrc_tx_packet_history_exit(void);
19extern int tfrc_rx_packet_history_init(void); 19extern int tfrc_rx_packet_history_init(void);
20extern void tfrc_rx_packet_history_exit(void); 20extern void tfrc_rx_packet_history_exit(void);
21 21
22extern int dccp_li_init(void); 22extern int tfrc_li_init(void);
23extern void dccp_li_exit(void); 23extern void tfrc_li_exit(void);
24 24
25static int __init tfrc_module_init(void) 25static int __init tfrc_module_init(void)
26{ 26{
27 int rc = dccp_li_init(); 27 int rc = tfrc_li_init();
28 28
29 if (rc) 29 if (rc)
30 goto out; 30 goto out;
@@ -41,7 +41,7 @@ static int __init tfrc_module_init(void)
41out_free_tx_history: 41out_free_tx_history:
42 tfrc_tx_packet_history_exit(); 42 tfrc_tx_packet_history_exit();
43out_free_loss_intervals: 43out_free_loss_intervals:
44 dccp_li_exit(); 44 tfrc_li_exit();
45out: 45out:
46 return rc; 46 return rc;
47} 47}
@@ -50,7 +50,7 @@ static void __exit tfrc_module_exit(void)
50{ 50{
51 tfrc_rx_packet_history_exit(); 51 tfrc_rx_packet_history_exit();
52 tfrc_tx_packet_history_exit(); 52 tfrc_tx_packet_history_exit();
53 dccp_li_exit(); 53 tfrc_li_exit();
54} 54}
55 55
56module_init(tfrc_module_init); 56module_init(tfrc_module_init);
diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h
index f4a5ea116e34..07dcbe73b50c 100644
--- a/net/dccp/dccp.h
+++ b/net/dccp/dccp.h
@@ -74,9 +74,12 @@ extern void dccp_time_wait(struct sock *sk, int state, int timeo);
74 74
75#define DCCP_RTO_MAX ((unsigned)(120 * HZ)) /* FIXME: using TCP value */ 75#define DCCP_RTO_MAX ((unsigned)(120 * HZ)) /* FIXME: using TCP value */
76 76
77/* bounds for sampled RTT values from packet exchanges (in usec) */ 77/*
78 * RTT sampling: sanity bounds and fallback RTT value from RFC 4340, section 3.4
79 */
78#define DCCP_SANE_RTT_MIN 100 80#define DCCP_SANE_RTT_MIN 100
79#define DCCP_SANE_RTT_MAX (4 * USEC_PER_SEC) 81#define DCCP_FALLBACK_RTT (USEC_PER_SEC / 5)
82#define DCCP_SANE_RTT_MAX (3 * USEC_PER_SEC)
80 83
81/* Maximal interval between probes for local resources. */ 84/* Maximal interval between probes for local resources. */
82#define DCCP_RESOURCE_PROBE_INTERVAL ((unsigned)(HZ / 2U)) 85#define DCCP_RESOURCE_PROBE_INTERVAL ((unsigned)(HZ / 2U))