aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGerrit Renker <gerrit@erg.abdn.ac.uk>2007-12-12 11:06:14 -0500
committerDavid S. Miller <davem@davemloft.net>2008-01-28 17:57:20 -0500
commit954c2db868ce896325dced91d5fba5e2226897a4 (patch)
treed74b480530878c25eb770293d786f2e78ace90e7
parentde0d411cb8ea51175f52d935faead5c542b6e007 (diff)
[CCID3]: Interface CCID3 code with newer Loss Intervals Database
This hooks up the TFRC Loss Interval database with CCID 3 packet reception. In addition, it makes the CCID-specific computation of the first loss interval (which requires access to all the guts of CCID3) local to ccid3.c. The patch also fixes an omission in the DCCP code, that of a default / fallback RTT value (defined in section 3.4 of RFC 4340 as 0.2 sec); while at it, the upper bound of 4 seconds for an RTT sample has been reduced to match the initial TCP RTO value of 3 seconds from[RFC 1122, 4.2.3.1]. Signed-off-by: Gerrit Renker <gerrit@erg.abdn.ac.uk> Signed-off-by: Ian McDonald <ian.mcdonald@jandi.co.nz> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-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))