[CCID3]: Introduce usecs_div
authorArnaldo Carvalho de Melo <acme@mandriva.com>
Sat, 27 Aug 2005 23:11:28 +0000 (20:11 -0300)
committerDavid S. Miller <davem@sunset.davemloft.net>
Mon, 29 Aug 2005 23:12:03 +0000 (16:12 -0700)
To avoid open coding this all over the place.

Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/dccp/ccids/ccid3.c

index 60e3a5f..ff41977 100644 (file)
 #include "../packet_history.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
 extern int ccid3_debug;
 
@@ -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 */
 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 
-        * doubles after every no feedback timer (separate function) */
-       
-       if (hctx->ccid3hctx_x < 10) {
-               ccid3_pr_debug("ccid3_calc_new_t_ipi - ccid3hctx_x < 10\n");
-               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 */
-
+       /*
+        * If no feedback spec says t_ipi is 1 second (set elsewhere and then
+        * doubles after every no feedback timer (separate function)
+        */
+       if (hctx->ccid3hctx_state != TFRC_SSTATE_NO_FBACK)
+               hctx->ccid3hctx_t_ipi = usecs_div(hctx->ccid3hctx_s,
+                                                 hctx->ccid3hctx_x);
 }
 
 /* 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)
 {
        hctx->ccid3hctx_delta = min_t(u32, hctx->ccid3hctx_t_ipi / 2,
                                           TFRC_OPSYS_HALF_TIME_GRAN);
-
 }
 
 /*
@@ -802,22 +803,13 @@ static void ccid3_hc_tx_update_x(struct sock *sk)
                do_gettimeofday(&now);
                if (timeval_delta(&now, &hctx->ccid3hctx_t_ld) >=
                    hctx->ccid3hctx_rtt) {
-                       /* Avoid divide by zero below */
-                       const u32 rtt = max_t(u32, hctx->ccid3hctx_rtt, 10);
-                       
-                       hctx->ccid3hctx_x = max_t(u32, min_t(u32, 2 * hctx->ccid3hctx_x_recv,
-                                                                 2 * hctx->ccid3hctx_x),
-                                                      ((hctx->ccid3hctx_s * 100000) /
-                                                       (rtt / 10)));
-                       /* Using 100000 and 10 to avoid 32 bit overflow for jumbo frames */
+                       hctx->ccid3hctx_x = max_t(u32, min_t(u32, hctx->ccid3hctx_x_recv,
+                                                                 hctx->ccid3hctx_x) * 2,
+                                                      usecs_div(hctx->ccid3hctx_s,
+                                                                hctx->ccid3hctx_rtt));
                        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)
@@ -826,7 +818,6 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data)
        struct dccp_sock *dp = dccp_sk(sk);
        unsigned long next_tmout = 0;
        struct ccid3_hc_tx_sock *hctx = dp->dccps_hc_tx_ccid_private;
-       u32 rtt;
 
        bh_lock_sock(sk);
        if (sock_owned_by_user(sk)) {
@@ -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_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) {
        case TFRC_SSTATE_TERM:
                goto out;
        case TFRC_SSTATE_NO_FBACK:
                /* Halve send rate */
                hctx->ccid3hctx_x /= 2;
-               if (hctx->ccid3hctx_x <
-                   (hctx->ccid3hctx_s / TFRC_MAX_BACK_OFF_TIME))
+               if (hctx->ccid3hctx_x < (hctx->ccid3hctx_s /
+                                        TFRC_MAX_BACK_OFF_TIME))
                        hctx->ccid3hctx_x = (hctx->ccid3hctx_s /
                                             TFRC_MAX_BACK_OFF_TIME);
 
@@ -861,9 +847,9 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data)
                               dccp_role(sk), sk,
                               ccid3_tx_state_name(hctx->ccid3hctx_state),
                               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);
-               /* do above maths with 100000 and 10 to prevent overflow on 32 bit */
                /*
                 * FIXME - not sure above calculation is correct. See section
                 * 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)
                 * Check if IDLE since last timeout and recv rate is less than
                 * 4 packets per RTT
                 */
-               rtt = hctx->ccid3hctx_rtt;
-               if (rtt < 10)
-                       rtt = 10;
-               /* stop divide by zero below */
                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",
                                       dccp_role(sk), sk,
                                       ccid3_tx_state_name(hctx->ccid3hctx_state));
@@ -905,13 +888,13 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data)
                        /* Update sending rate */
                        ccid3_hc_tx_update_x(sk);
                }
-               if (hctx->ccid3hctx_x == 0) {
-                       ccid3_pr_debug("TFRC_SSTATE_FBACK ccid3hctx_x = 0!\n");
-                       hctx->ccid3hctx_x = 10;
-               }
-               /* Schedule no feedback timer to expire in 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, 
-                                  2 * (hctx->ccid3hctx_s * 100000) / (hctx->ccid3hctx_x / 10));
+                                       2 * usecs_div(hctx->ccid3hctx_s,
+                                                     hctx->ccid3hctx_x));
                break;
        default:
                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)
                 * Algorithm in "8.1. Window Counter Valuer" in
                 * draft-ietf-dccp-ccid3-11.txt
                 */
-               quarter_rtt = timeval_delta(&now, &hctx->ccid3hctx_t_last_win_count) /
-                             (hctx->ccid3hctx_rtt / 4);
+               quarter_rtt = timeval_delta(&now, &hctx->ccid3hctx_t_last_win_count);
+               if (likely(hctx->ccid3hctx_rtt > 8))
+                       quarter_rtt /= hctx->ccid3hctx_rtt / 4;
+
                if (quarter_rtt > 0) {
                        hctx->ccid3hctx_t_last_win_count = now;
                        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)
                        hctx->ccid3hctx_rtt = (hctx->ccid3hctx_rtt * 9) / 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, "
                               "r_sample=%us\n", dccp_role(sk), sk,
                               hctx->ccid3hctx_rtt, r_sample);
@@ -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,
                                         &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
                 * max(4 * R, 2 * s / X)
                 */
                next_tmout = max(hctx->ccid3hctx_t_rto,
-                                (2 * (hctx->ccid3hctx_s * 100000) /
-                                 (hctx->ccid3hctx_x / 10)));
-               /* maths with 100000 and 10 is to prevent overflow with 32 bit */
-
+                                2 * usecs_div(hctx->ccid3hctx_s,
+                                              hctx->ccid3hctx_x));
+                       
                ccid3_pr_debug("%s, sk=%p, Scheduled no feedback timer to "
                               "expire in %lu jiffies (%luus)\n",
                               dccp_role(sk), sk,
@@ -1350,8 +1321,6 @@ static int ccid3_hc_tx_init(struct sock *sk)
 
        /* Set transmission rate to 1 packet per second */
        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_state = TFRC_SSTATE_NO_SENT;
        INIT_LIST_HEAD(&hctx->ccid3hctx_hist);