diff options
-rw-r--r-- | net/dccp/ccids/ccid3.c | 72 | ||||
-rw-r--r-- | net/dccp/ccids/ccid3.h | 10 | ||||
-rw-r--r-- | net/dccp/ccids/lib/loss_interval.c | 18 | ||||
-rw-r--r-- | net/dccp/ccids/lib/tfrc.c | 10 | ||||
-rw-r--r-- | net/dccp/dccp.h | 7 |
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 | */ | ||
766 | static 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 | |||
760 | static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) | 797 | static 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) | |||
823 | update_records: | 875 | update_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 | ||
878 | done_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 | ||
854 | static void ccid3_hc_rx_get_info(struct sock *sk, struct tcp_info *info) | 902 | static 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 | ||
164 | static inline struct ccid3_hc_rx_sock *ccid3_hc_rx_sk(const struct sock *sk) | 164 | static 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 | } |
436 | EXPORT_SYMBOL_GPL(tfrc_lh_interval_add); | 436 | EXPORT_SYMBOL_GPL(tfrc_lh_interval_add); |
437 | 437 | ||
438 | int __init dccp_li_init(void) | 438 | int __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 | ||
446 | void dccp_li_exit(void) | 446 | void 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); | |||
19 | extern int tfrc_rx_packet_history_init(void); | 19 | extern int tfrc_rx_packet_history_init(void); |
20 | extern void tfrc_rx_packet_history_exit(void); | 20 | extern void tfrc_rx_packet_history_exit(void); |
21 | 21 | ||
22 | extern int dccp_li_init(void); | 22 | extern int tfrc_li_init(void); |
23 | extern void dccp_li_exit(void); | 23 | extern void tfrc_li_exit(void); |
24 | 24 | ||
25 | static int __init tfrc_module_init(void) | 25 | static 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) | |||
41 | out_free_tx_history: | 41 | out_free_tx_history: |
42 | tfrc_tx_packet_history_exit(); | 42 | tfrc_tx_packet_history_exit(); |
43 | out_free_loss_intervals: | 43 | out_free_loss_intervals: |
44 | dccp_li_exit(); | 44 | tfrc_li_exit(); |
45 | out: | 45 | out: |
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 | ||
56 | module_init(tfrc_module_init); | 56 | module_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)) |