Commit 6b5e633a authored by Arnaldo Carvalho de Melo's avatar Arnaldo Carvalho de Melo Committed by David S. Miller

[CCID3]: Introduce usecs_div

To avoid open coding this all over the place.
Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@mandriva.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent b6ee3d4a
...@@ -40,6 +40,15 @@ ...@@ -40,6 +40,15 @@
#include "../packet_history.h" #include "../packet_history.h"
#include "ccid3.h" #include "ccid3.h"
/*
* Reason for maths with 10 here is to avoid 32 bit overflow when a is big.
*/
static inline u32 usecs_div(const u32 a, const u32 b)
{
const u32 tmp = a * (USEC_PER_SEC / 10);
return b > 20 ? tmp / (b / 10) : tmp;
}
#ifdef CCID3_DEBUG #ifdef CCID3_DEBUG
extern int ccid3_debug; extern int ccid3_debug;
...@@ -748,20 +757,13 @@ static u32 ccid3_calc_x(u16 s, u32 R, u32 p) ...@@ -748,20 +757,13 @@ static u32 ccid3_calc_x(u16 s, u32 R, u32 p)
/* Calculate new t_ipi (inter packet interval) by t_ipi = s / X_inst */ /* Calculate new t_ipi (inter packet interval) by t_ipi = s / X_inst */
static inline void ccid3_calc_new_t_ipi(struct ccid3_hc_tx_sock *hctx) static inline void ccid3_calc_new_t_ipi(struct ccid3_hc_tx_sock *hctx)
{ {
if (hctx->ccid3hctx_state == TFRC_SSTATE_NO_FBACK) /*
return; * If no feedback spec says t_ipi is 1 second (set elsewhere and then
/* if no feedback spec says t_ipi is 1 second (set elsewhere and then * doubles after every no feedback timer (separate function)
* doubles after every no feedback timer (separate function) */ */
if (hctx->ccid3hctx_state != TFRC_SSTATE_NO_FBACK)
if (hctx->ccid3hctx_x < 10) { hctx->ccid3hctx_t_ipi = usecs_div(hctx->ccid3hctx_s,
ccid3_pr_debug("ccid3_calc_new_t_ipi - ccid3hctx_x < 10\n"); hctx->ccid3hctx_x);
hctx->ccid3hctx_x = 10;
}
hctx->ccid3hctx_t_ipi = (hctx->ccid3hctx_s * 100000)
/ (hctx->ccid3hctx_x / 10);
/* reason for above maths with 10 in there is to avoid 32 bit
* overflow for jumbo packets */
} }
/* Calculate new delta by delta = min(t_ipi / 2, t_gran / 2) */ /* 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,7 +771,6 @@ static inline void ccid3_calc_new_delta(struct ccid3_hc_tx_sock *hctx)
{ {
hctx->ccid3hctx_delta = min_t(u32, hctx->ccid3hctx_t_ipi / 2, hctx->ccid3hctx_delta = min_t(u32, hctx->ccid3hctx_t_ipi / 2,
TFRC_OPSYS_HALF_TIME_GRAN); TFRC_OPSYS_HALF_TIME_GRAN);
} }
/* /*
...@@ -802,22 +803,13 @@ static void ccid3_hc_tx_update_x(struct sock *sk) ...@@ -802,22 +803,13 @@ static void ccid3_hc_tx_update_x(struct sock *sk)
do_gettimeofday(&now); do_gettimeofday(&now);
if (timeval_delta(&now, &hctx->ccid3hctx_t_ld) >= if (timeval_delta(&now, &hctx->ccid3hctx_t_ld) >=
hctx->ccid3hctx_rtt) { hctx->ccid3hctx_rtt) {
/* Avoid divide by zero below */ hctx->ccid3hctx_x = max_t(u32, min_t(u32, hctx->ccid3hctx_x_recv,
const u32 rtt = max_t(u32, hctx->ccid3hctx_rtt, 10); hctx->ccid3hctx_x) * 2,
usecs_div(hctx->ccid3hctx_s,
hctx->ccid3hctx_x = max_t(u32, min_t(u32, 2 * hctx->ccid3hctx_x_recv, hctx->ccid3hctx_rtt));
2 * hctx->ccid3hctx_x),
((hctx->ccid3hctx_s * 100000) /
(rtt / 10)));
/* Using 100000 and 10 to avoid 32 bit overflow for jumbo frames */
hctx->ccid3hctx_t_ld = now; hctx->ccid3hctx_t_ld = now;
} }
} }
if (hctx->ccid3hctx_x == 0) {
ccid3_pr_debug("ccid3hctx_x = 0!\n");
hctx->ccid3hctx_x = 1;
}
} }
static void ccid3_hc_tx_no_feedback_timer(unsigned long data) static 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,7 +818,6 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data)
struct dccp_sock *dp = dccp_sk(sk); struct dccp_sock *dp = dccp_sk(sk);
unsigned long next_tmout = 0; unsigned long next_tmout = 0;
struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private; struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private;
u32 rtt;
bh_lock_sock(sk); bh_lock_sock(sk);
if (sock_owned_by_user(sk)) { if (sock_owned_by_user(sk)) {
...@@ -840,19 +831,14 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data) ...@@ -840,19 +831,14 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data)
ccid3_pr_debug("%s, sk=%p, state=%s\n", dccp_role(sk), sk, ccid3_pr_debug("%s, sk=%p, state=%s\n", dccp_role(sk), sk,
ccid3_tx_state_name(hctx->ccid3hctx_state)); ccid3_tx_state_name(hctx->ccid3hctx_state));
if (hctx->ccid3hctx_x < 10) {
ccid3_pr_debug("TFRC_SSTATE_NO_FBACK ccid3hctx_x < 10\n");
hctx->ccid3hctx_x = 10;
}
switch (hctx->ccid3hctx_state) { switch (hctx->ccid3hctx_state) {
case TFRC_SSTATE_TERM: case TFRC_SSTATE_TERM:
goto out; goto out;
case TFRC_SSTATE_NO_FBACK: case TFRC_SSTATE_NO_FBACK:
/* Halve send rate */ /* Halve send rate */
hctx->ccid3hctx_x /= 2; hctx->ccid3hctx_x /= 2;
if (hctx->ccid3hctx_x < if (hctx->ccid3hctx_x < (hctx->ccid3hctx_s /
(hctx->ccid3hctx_s / TFRC_MAX_BACK_OFF_TIME)) TFRC_MAX_BACK_OFF_TIME))
hctx->ccid3hctx_x = (hctx->ccid3hctx_s / hctx->ccid3hctx_x = (hctx->ccid3hctx_s /
TFRC_MAX_BACK_OFF_TIME); TFRC_MAX_BACK_OFF_TIME);
...@@ -861,9 +847,9 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data) ...@@ -861,9 +847,9 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data)
dccp_role(sk), sk, dccp_role(sk), sk,
ccid3_tx_state_name(hctx->ccid3hctx_state), ccid3_tx_state_name(hctx->ccid3hctx_state),
hctx->ccid3hctx_x); hctx->ccid3hctx_x);
next_tmout = max_t(u32, 2 * (hctx->ccid3hctx_s * 100000) / (hctx->ccid3hctx_x / 10), next_tmout = max_t(u32, 2 * usecs_div(hctx->ccid3hctx_s,
hctx->ccid3hctx_x),
TFRC_INITIAL_TIMEOUT); TFRC_INITIAL_TIMEOUT);
/* do above maths with 100000 and 10 to prevent overflow on 32 bit */
/* /*
* FIXME - not sure above calculation is correct. See section * FIXME - not sure above calculation is correct. See section
* 5 of CCID3 11 should adjust tx_t_ipi and double that to * 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,12 +861,9 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data)
* Check if IDLE since last timeout and recv rate is less than * Check if IDLE since last timeout and recv rate is less than
* 4 packets per RTT * 4 packets per RTT
*/ */
rtt = hctx->ccid3hctx_rtt;
if (rtt < 10)
rtt = 10;
/* stop divide by zero below */
if (!hctx->ccid3hctx_idle || if (!hctx->ccid3hctx_idle ||
(hctx->ccid3hctx_x_recv >= 4 * (hctx->ccid3hctx_s * 100000) / (rtt / 10))) { (hctx->ccid3hctx_x_recv >=
4 * usecs_div(hctx->ccid3hctx_s, hctx->ccid3hctx_rtt))) {
ccid3_pr_debug("%s, sk=%p, state=%s, not idle\n", ccid3_pr_debug("%s, sk=%p, state=%s, not idle\n",
dccp_role(sk), sk, dccp_role(sk), sk,
ccid3_tx_state_name(hctx->ccid3hctx_state)); ccid3_tx_state_name(hctx->ccid3hctx_state));
...@@ -905,13 +888,13 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data) ...@@ -905,13 +888,13 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data)
/* Update sending rate */ /* Update sending rate */
ccid3_hc_tx_update_x(sk); ccid3_hc_tx_update_x(sk);
} }
if (hctx->ccid3hctx_x == 0) { /*
ccid3_pr_debug("TFRC_SSTATE_FBACK ccid3hctx_x = 0!\n"); * Schedule no feedback timer to expire in
hctx->ccid3hctx_x = 10; * max(4 * R, 2 * s / X)
} */
/* Schedule no feedback timer to expire in max(4 * R, 2 * s / X) */
next_tmout = max_t(u32, hctx->ccid3hctx_t_rto, next_tmout = max_t(u32, hctx->ccid3hctx_t_rto,
2 * (hctx->ccid3hctx_s * 100000) / (hctx->ccid3hctx_x / 10)); 2 * usecs_div(hctx->ccid3hctx_s,
hctx->ccid3hctx_x));
break; break;
default: default:
printk(KERN_CRIT "%s: %s, sk=%p, Illegal state (%d)!\n", 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,8 +1036,10 @@ static void ccid3_hc_tx_packet_sent(struct sock *sk, int more, int len)
* Algorithm in "8.1. Window Counter Valuer" in * Algorithm in "8.1. Window Counter Valuer" in
* draft-ietf-dccp-ccid3-11.txt * draft-ietf-dccp-ccid3-11.txt
*/ */
quarter_rtt = timeval_delta(&now, &hctx->ccid3hctx_t_last_win_count) / quarter_rtt = timeval_delta(&now, &hctx->ccid3hctx_t_last_win_count);
(hctx->ccid3hctx_rtt / 4); if (likely(hctx->ccid3hctx_rtt > 8))
quarter_rtt /= hctx->ccid3hctx_rtt / 4;
if (quarter_rtt > 0) { if (quarter_rtt > 0) {
hctx->ccid3hctx_t_last_win_count = now; hctx->ccid3hctx_t_last_win_count = now;
hctx->ccid3hctx_last_win_count = (hctx->ccid3hctx_last_win_count + 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,13 +1156,6 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
hctx->ccid3hctx_rtt = (hctx->ccid3hctx_rtt * 9) / 10 + hctx->ccid3hctx_rtt = (hctx->ccid3hctx_rtt * 9) / 10 +
r_sample / 10; r_sample / 10;
/*
* XXX: this is to avoid a division by zero in ccid3_hc_tx_packet_sent
* implemention of the new window count.
*/
if (hctx->ccid3hctx_rtt < 4)
hctx->ccid3hctx_rtt = 4;
ccid3_pr_debug("%s, sk=%p, New RTT estimate=%uus, " ccid3_pr_debug("%s, sk=%p, New RTT estimate=%uus, "
"r_sample=%us\n", dccp_role(sk), sk, "r_sample=%us\n", dccp_role(sk), sk,
hctx->ccid3hctx_rtt, r_sample); hctx->ccid3hctx_rtt, r_sample);
...@@ -1220,21 +1198,14 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) ...@@ -1220,21 +1198,14 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
dccp_tx_hist_purge_older(ccid3_tx_hist, dccp_tx_hist_purge_older(ccid3_tx_hist,
&hctx->ccid3hctx_hist, packet); &hctx->ccid3hctx_hist, packet);
if (hctx->ccid3hctx_x < 10) {
ccid3_pr_debug("ccid3_hc_tx_packet_recv hctx_x < 10\n");
hctx->ccid3hctx_x = 10;
}
/* to prevent divide by zero below */
/* /*
* Schedule no feedback timer to expire in * Schedule no feedback timer to expire in
* max(4 * R, 2 * s / X) * max(4 * R, 2 * s / X)
*/ */
next_tmout = max(hctx->ccid3hctx_t_rto, next_tmout = max(hctx->ccid3hctx_t_rto,
(2 * (hctx->ccid3hctx_s * 100000) / 2 * usecs_div(hctx->ccid3hctx_s,
(hctx->ccid3hctx_x / 10))); hctx->ccid3hctx_x));
/* maths with 100000 and 10 is to prevent overflow with 32 bit */
ccid3_pr_debug("%s, sk=%p, Scheduled no feedback timer to " ccid3_pr_debug("%s, sk=%p, Scheduled no feedback timer to "
"expire in %lu jiffies (%luus)\n", "expire in %lu jiffies (%luus)\n",
dccp_role(sk), sk, dccp_role(sk), sk,
...@@ -1350,8 +1321,6 @@ static int ccid3_hc_tx_init(struct sock *sk) ...@@ -1350,8 +1321,6 @@ static int ccid3_hc_tx_init(struct sock *sk)
/* Set transmission rate to 1 packet per second */ /* Set transmission rate to 1 packet per second */
hctx->ccid3hctx_x = hctx->ccid3hctx_s; hctx->ccid3hctx_x = hctx->ccid3hctx_s;
/* See ccid3_hc_tx_packet_sent win_count calculatation */
hctx->ccid3hctx_rtt = 4;
hctx->ccid3hctx_t_rto = USEC_PER_SEC; hctx->ccid3hctx_t_rto = USEC_PER_SEC;
hctx->ccid3hctx_state = TFRC_SSTATE_NO_SENT; hctx->ccid3hctx_state = TFRC_SSTATE_NO_SENT;
INIT_LIST_HEAD(&hctx->ccid3hctx_hist); INIT_LIST_HEAD(&hctx->ccid3hctx_hist);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment