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.c109
1 files changed, 39 insertions, 70 deletions
diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c
index 60e3a5f9fcb4..ff41977f1edc 100644
--- a/net/dccp/ccids/ccid3.c
+++ b/net/dccp/ccids/ccid3.c
@@ -40,6 +40,15 @@
40#include "../packet_history.h" 40#include "../packet_history.h"
41#include "ccid3.h" 41#include "ccid3.h"
42 42
43/*
44 * Reason for maths with 10 here is to avoid 32 bit overflow when a is big.
45 */
46static inline u32 usecs_div(const u32 a, const u32 b)
47{
48 const u32 tmp = a * (USEC_PER_SEC / 10);
49 return b > 20 ? tmp / (b / 10) : tmp;
50}
51
43#ifdef CCID3_DEBUG 52#ifdef CCID3_DEBUG
44extern int ccid3_debug; 53extern int ccid3_debug;
45 54
@@ -748,20 +757,13 @@ static u32 ccid3_calc_x(u16 s, u32 R, u32 p)
748/* Calculate new t_ipi (inter packet interval) by t_ipi = s / X_inst */ 757/* Calculate new t_ipi (inter packet interval) by t_ipi = s / X_inst */
749static inline void ccid3_calc_new_t_ipi(struct ccid3_hc_tx_sock *hctx) 758static inline void ccid3_calc_new_t_ipi(struct ccid3_hc_tx_sock *hctx)
750{ 759{
751 if (hctx->ccid3hctx_state == TFRC_SSTATE_NO_FBACK) 760 /*
752 return; 761 * If no feedback spec says t_ipi is 1 second (set elsewhere and then
753 /* if no feedback spec says t_ipi is 1 second (set elsewhere and then 762 * doubles after every no feedback timer (separate function)
754 * doubles after every no feedback timer (separate function) */ 763 */
755 764 if (hctx->ccid3hctx_state != TFRC_SSTATE_NO_FBACK)
756 if (hctx->ccid3hctx_x < 10) { 765 hctx->ccid3hctx_t_ipi = usecs_div(hctx->ccid3hctx_s,
757 ccid3_pr_debug("ccid3_calc_new_t_ipi - ccid3hctx_x < 10\n"); 766 hctx->ccid3hctx_x);
758 hctx->ccid3hctx_x = 10;
759 }
760 hctx->ccid3hctx_t_ipi = (hctx->ccid3hctx_s * 100000)
761 / (hctx->ccid3hctx_x / 10);
762 /* reason for above maths with 10 in there is to avoid 32 bit
763 * overflow for jumbo packets */
764
765} 767}
766 768
767/* Calculate new delta by delta = min(t_ipi / 2, t_gran / 2) */ 769/* Calculate new delta by delta = min(t_ipi / 2, t_gran / 2) */
@@ -769,7 +771,6 @@ static inline void ccid3_calc_new_delta(struct ccid3_hc_tx_sock *hctx)
769{ 771{
770 hctx->ccid3hctx_delta = min_t(u32, hctx->ccid3hctx_t_ipi / 2, 772 hctx->ccid3hctx_delta = min_t(u32, hctx->ccid3hctx_t_ipi / 2,
771 TFRC_OPSYS_HALF_TIME_GRAN); 773 TFRC_OPSYS_HALF_TIME_GRAN);
772
773} 774}
774 775
775/* 776/*
@@ -802,22 +803,13 @@ static void ccid3_hc_tx_update_x(struct sock *sk)
802 do_gettimeofday(&now); 803 do_gettimeofday(&now);
803 if (timeval_delta(&now, &hctx->ccid3hctx_t_ld) >= 804 if (timeval_delta(&now, &hctx->ccid3hctx_t_ld) >=
804 hctx->ccid3hctx_rtt) { 805 hctx->ccid3hctx_rtt) {
805 /* Avoid divide by zero below */ 806 hctx->ccid3hctx_x = max_t(u32, min_t(u32, hctx->ccid3hctx_x_recv,
806 const u32 rtt = max_t(u32, hctx->ccid3hctx_rtt, 10); 807 hctx->ccid3hctx_x) * 2,
807 808 usecs_div(hctx->ccid3hctx_s,
808 hctx->ccid3hctx_x = max_t(u32, min_t(u32, 2 * hctx->ccid3hctx_x_recv, 809 hctx->ccid3hctx_rtt));
809 2 * hctx->ccid3hctx_x),
810 ((hctx->ccid3hctx_s * 100000) /
811 (rtt / 10)));
812 /* Using 100000 and 10 to avoid 32 bit overflow for jumbo frames */
813 hctx->ccid3hctx_t_ld = now; 810 hctx->ccid3hctx_t_ld = now;
814 } 811 }
815 } 812 }
816
817 if (hctx->ccid3hctx_x == 0) {
818 ccid3_pr_debug("ccid3hctx_x = 0!\n");
819 hctx->ccid3hctx_x = 1;
820 }
821} 813}
822 814
823static void ccid3_hc_tx_no_feedback_timer(unsigned long data) 815static void ccid3_hc_tx_no_feedback_timer(unsigned long data)
@@ -826,7 +818,6 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data)
826 struct dccp_sock *dp = dccp_sk(sk); 818 struct dccp_sock *dp = dccp_sk(sk);
827 unsigned long next_tmout = 0; 819 unsigned long next_tmout = 0;
828 struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private; 820 struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private;
829 u32 rtt;
830 821
831 bh_lock_sock(sk); 822 bh_lock_sock(sk);
832 if (sock_owned_by_user(sk)) { 823 if (sock_owned_by_user(sk)) {
@@ -840,19 +831,14 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data)
840 ccid3_pr_debug("%s, sk=%p, state=%s\n", dccp_role(sk), sk, 831 ccid3_pr_debug("%s, sk=%p, state=%s\n", dccp_role(sk), sk,
841 ccid3_tx_state_name(hctx->ccid3hctx_state)); 832 ccid3_tx_state_name(hctx->ccid3hctx_state));
842 833
843 if (hctx->ccid3hctx_x < 10) {
844 ccid3_pr_debug("TFRC_SSTATE_NO_FBACK ccid3hctx_x < 10\n");
845 hctx->ccid3hctx_x = 10;
846 }
847
848 switch (hctx->ccid3hctx_state) { 834 switch (hctx->ccid3hctx_state) {
849 case TFRC_SSTATE_TERM: 835 case TFRC_SSTATE_TERM:
850 goto out; 836 goto out;
851 case TFRC_SSTATE_NO_FBACK: 837 case TFRC_SSTATE_NO_FBACK:
852 /* Halve send rate */ 838 /* Halve send rate */
853 hctx->ccid3hctx_x /= 2; 839 hctx->ccid3hctx_x /= 2;
854 if (hctx->ccid3hctx_x < 840 if (hctx->ccid3hctx_x < (hctx->ccid3hctx_s /
855 (hctx->ccid3hctx_s / TFRC_MAX_BACK_OFF_TIME)) 841 TFRC_MAX_BACK_OFF_TIME))
856 hctx->ccid3hctx_x = (hctx->ccid3hctx_s / 842 hctx->ccid3hctx_x = (hctx->ccid3hctx_s /
857 TFRC_MAX_BACK_OFF_TIME); 843 TFRC_MAX_BACK_OFF_TIME);
858 844
@@ -861,9 +847,9 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data)
861 dccp_role(sk), sk, 847 dccp_role(sk), sk,
862 ccid3_tx_state_name(hctx->ccid3hctx_state), 848 ccid3_tx_state_name(hctx->ccid3hctx_state),
863 hctx->ccid3hctx_x); 849 hctx->ccid3hctx_x);
864 next_tmout = max_t(u32, 2 * (hctx->ccid3hctx_s * 100000) / (hctx->ccid3hctx_x / 10), 850 next_tmout = max_t(u32, 2 * usecs_div(hctx->ccid3hctx_s,
851 hctx->ccid3hctx_x),
865 TFRC_INITIAL_TIMEOUT); 852 TFRC_INITIAL_TIMEOUT);
866 /* do above maths with 100000 and 10 to prevent overflow on 32 bit */
867 /* 853 /*
868 * FIXME - not sure above calculation is correct. See section 854 * FIXME - not sure above calculation is correct. See section
869 * 5 of CCID3 11 should adjust tx_t_ipi and double that to 855 * 5 of CCID3 11 should adjust tx_t_ipi and double that to
@@ -875,12 +861,9 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data)
875 * Check if IDLE since last timeout and recv rate is less than 861 * Check if IDLE since last timeout and recv rate is less than
876 * 4 packets per RTT 862 * 4 packets per RTT
877 */ 863 */
878 rtt = hctx->ccid3hctx_rtt;
879 if (rtt < 10)
880 rtt = 10;
881 /* stop divide by zero below */
882 if (!hctx->ccid3hctx_idle || 864 if (!hctx->ccid3hctx_idle ||
883 (hctx->ccid3hctx_x_recv >= 4 * (hctx->ccid3hctx_s * 100000) / (rtt / 10))) { 865 (hctx->ccid3hctx_x_recv >=
866 4 * usecs_div(hctx->ccid3hctx_s, hctx->ccid3hctx_rtt))) {
884 ccid3_pr_debug("%s, sk=%p, state=%s, not idle\n", 867 ccid3_pr_debug("%s, sk=%p, state=%s, not idle\n",
885 dccp_role(sk), sk, 868 dccp_role(sk), sk,
886 ccid3_tx_state_name(hctx->ccid3hctx_state)); 869 ccid3_tx_state_name(hctx->ccid3hctx_state));
@@ -905,13 +888,13 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data)
905 /* Update sending rate */ 888 /* Update sending rate */
906 ccid3_hc_tx_update_x(sk); 889 ccid3_hc_tx_update_x(sk);
907 } 890 }
908 if (hctx->ccid3hctx_x == 0) { 891 /*
909 ccid3_pr_debug("TFRC_SSTATE_FBACK ccid3hctx_x = 0!\n"); 892 * Schedule no feedback timer to expire in
910 hctx->ccid3hctx_x = 10; 893 * max(4 * R, 2 * s / X)
911 } 894 */
912 /* Schedule no feedback timer to expire in max(4 * R, 2 * s / X) */
913 next_tmout = max_t(u32, hctx->ccid3hctx_t_rto, 895 next_tmout = max_t(u32, hctx->ccid3hctx_t_rto,
914 2 * (hctx->ccid3hctx_s * 100000) / (hctx->ccid3hctx_x / 10)); 896 2 * usecs_div(hctx->ccid3hctx_s,
897 hctx->ccid3hctx_x));
915 break; 898 break;
916 default: 899 default:
917 printk(KERN_CRIT "%s: %s, sk=%p, Illegal state (%d)!\n", 900 printk(KERN_CRIT "%s: %s, sk=%p, Illegal state (%d)!\n",
@@ -1053,8 +1036,10 @@ static void ccid3_hc_tx_packet_sent(struct sock *sk, int more, int len)
1053 * Algorithm in "8.1. Window Counter Valuer" in 1036 * Algorithm in "8.1. Window Counter Valuer" in
1054 * draft-ietf-dccp-ccid3-11.txt 1037 * draft-ietf-dccp-ccid3-11.txt
1055 */ 1038 */
1056 quarter_rtt = timeval_delta(&now, &hctx->ccid3hctx_t_last_win_count) / 1039 quarter_rtt = timeval_delta(&now, &hctx->ccid3hctx_t_last_win_count);
1057 (hctx->ccid3hctx_rtt / 4); 1040 if (likely(hctx->ccid3hctx_rtt > 8))
1041 quarter_rtt /= hctx->ccid3hctx_rtt / 4;
1042
1058 if (quarter_rtt > 0) { 1043 if (quarter_rtt > 0) {
1059 hctx->ccid3hctx_t_last_win_count = now; 1044 hctx->ccid3hctx_t_last_win_count = now;
1060 hctx->ccid3hctx_last_win_count = (hctx->ccid3hctx_last_win_count + 1045 hctx->ccid3hctx_last_win_count = (hctx->ccid3hctx_last_win_count +
@@ -1171,13 +1156,6 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
1171 hctx->ccid3hctx_rtt = (hctx->ccid3hctx_rtt * 9) / 10 + 1156 hctx->ccid3hctx_rtt = (hctx->ccid3hctx_rtt * 9) / 10 +
1172 r_sample / 10; 1157 r_sample / 10;
1173 1158
1174 /*
1175 * XXX: this is to avoid a division by zero in ccid3_hc_tx_packet_sent
1176 * implemention of the new window count.
1177 */
1178 if (hctx->ccid3hctx_rtt < 4)
1179 hctx->ccid3hctx_rtt = 4;
1180
1181 ccid3_pr_debug("%s, sk=%p, New RTT estimate=%uus, " 1159 ccid3_pr_debug("%s, sk=%p, New RTT estimate=%uus, "
1182 "r_sample=%us\n", dccp_role(sk), sk, 1160 "r_sample=%us\n", dccp_role(sk), sk,
1183 hctx->ccid3hctx_rtt, r_sample); 1161 hctx->ccid3hctx_rtt, r_sample);
@@ -1220,21 +1198,14 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
1220 dccp_tx_hist_purge_older(ccid3_tx_hist, 1198 dccp_tx_hist_purge_older(ccid3_tx_hist,
1221 &hctx->ccid3hctx_hist, packet); 1199 &hctx->ccid3hctx_hist, packet);
1222 1200
1223 if (hctx->ccid3hctx_x < 10) {
1224 ccid3_pr_debug("ccid3_hc_tx_packet_recv hctx_x < 10\n");
1225 hctx->ccid3hctx_x = 10;
1226 }
1227 /* to prevent divide by zero below */
1228
1229 /* 1201 /*
1230 * Schedule no feedback timer to expire in 1202 * Schedule no feedback timer to expire in
1231 * max(4 * R, 2 * s / X) 1203 * max(4 * R, 2 * s / X)
1232 */ 1204 */
1233 next_tmout = max(hctx->ccid3hctx_t_rto, 1205 next_tmout = max(hctx->ccid3hctx_t_rto,
1234 (2 * (hctx->ccid3hctx_s * 100000) / 1206 2 * usecs_div(hctx->ccid3hctx_s,
1235 (hctx->ccid3hctx_x / 10))); 1207 hctx->ccid3hctx_x));
1236 /* maths with 100000 and 10 is to prevent overflow with 32 bit */ 1208
1237
1238 ccid3_pr_debug("%s, sk=%p, Scheduled no feedback timer to " 1209 ccid3_pr_debug("%s, sk=%p, Scheduled no feedback timer to "
1239 "expire in %lu jiffies (%luus)\n", 1210 "expire in %lu jiffies (%luus)\n",
1240 dccp_role(sk), sk, 1211 dccp_role(sk), sk,
@@ -1350,8 +1321,6 @@ static int ccid3_hc_tx_init(struct sock *sk)
1350 1321
1351 /* Set transmission rate to 1 packet per second */ 1322 /* Set transmission rate to 1 packet per second */
1352 hctx->ccid3hctx_x = hctx->ccid3hctx_s; 1323 hctx->ccid3hctx_x = hctx->ccid3hctx_s;
1353 /* See ccid3_hc_tx_packet_sent win_count calculatation */
1354 hctx->ccid3hctx_rtt = 4;
1355 hctx->ccid3hctx_t_rto = USEC_PER_SEC; 1324 hctx->ccid3hctx_t_rto = USEC_PER_SEC;
1356 hctx->ccid3hctx_state = TFRC_SSTATE_NO_SENT; 1325 hctx->ccid3hctx_state = TFRC_SSTATE_NO_SENT;
1357 INIT_LIST_HEAD(&hctx->ccid3hctx_hist); 1326 INIT_LIST_HEAD(&hctx->ccid3hctx_hist);