[CCID3]: Reorganise timeval handling

Introducing functions to add to or subtract from a timeval variable
and renaming now_delta to timeval_new_delta that calls do_gettimeofday
and then timeval_delta, that should be used when there are several
deltas made relative to the current time or setting variables to it,
so as to avoid calling do_gettimeofday excessively.

I'm leaving these "timeval_" prefixed funcions internal to DCCP for a
while till we're sure there are no subtle bugs in it.

It also is more correct as it checks if the number of usecs added to
or subtracted from a tv_usec field is more than 2 seconds.

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

authored by

Arnaldo Carvalho de Melo and committed by
David S. Miller
b6ee3d4a 1f2333ae

+98 -78
+55 -72
net/dccp/ccids/ccid3.c
··· 156 156 hctx->ccid3hctx_state = state; 157 157 } 158 158 159 - static void timeval_sub(struct timeval large, struct timeval small, 160 - struct timeval *result) 161 - { 162 - result->tv_sec = large.tv_sec-small.tv_sec; 163 - if (large.tv_usec < small.tv_usec) { 164 - (result->tv_sec)--; 165 - result->tv_usec = USEC_PER_SEC + 166 - large.tv_usec - small.tv_usec; 167 - } else 168 - result->tv_usec = large.tv_usec-small.tv_usec; 169 - } 170 - 171 - static inline void timeval_fix(struct timeval *tv) 172 - { 173 - if (tv->tv_usec >= USEC_PER_SEC) { 174 - tv->tv_sec++; 175 - tv->tv_usec -= USEC_PER_SEC; 176 - } 177 - } 178 - 179 159 #define CALCX_ARRSIZE 500 180 160 181 161 #define CALCX_SPLIT 50000 ··· 796 816 2 * hctx->ccid3hctx_x_recv), 797 817 (hctx->ccid3hctx_s / 798 818 TFRC_MAX_BACK_OFF_TIME)); 799 - } else if (now_delta(hctx->ccid3hctx_t_ld) >= hctx->ccid3hctx_rtt) { 800 - u32 rtt = hctx->ccid3hctx_rtt; 801 - if (rtt < 10) { 802 - rtt = 10; 803 - } /* avoid divide by zero below */ 804 - 805 - hctx->ccid3hctx_x = max_t(u32, min_t(u32, 2 * hctx->ccid3hctx_x_recv, 806 - 2 * hctx->ccid3hctx_x), 807 - ((hctx->ccid3hctx_s * 100000) / 808 - (rtt / 10))); 809 - /* Using 100000 and 10 to avoid 32 bit overflow for jumbo frames */ 810 - do_gettimeofday(&hctx->ccid3hctx_t_ld); 819 + } else { 820 + struct timeval now; 821 + 822 + do_gettimeofday(&now); 823 + if (timeval_delta(&now, &hctx->ccid3hctx_t_ld) >= 824 + hctx->ccid3hctx_rtt) { 825 + /* Avoid divide by zero below */ 826 + const u32 rtt = max_t(u32, hctx->ccid3hctx_rtt, 10); 827 + 828 + hctx->ccid3hctx_x = max_t(u32, min_t(u32, 2 * hctx->ccid3hctx_x_recv, 829 + 2 * hctx->ccid3hctx_x), 830 + ((hctx->ccid3hctx_s * 100000) / 831 + (rtt / 10))); 832 + /* Using 100000 and 10 to avoid 32 bit overflow for jumbo frames */ 833 + hctx->ccid3hctx_t_ld = now; 834 + } 811 835 } 812 836 813 837 if (hctx->ccid3hctx_x == 0) { ··· 983 999 984 1000 /* Set nominal send time for initial packet */ 985 1001 hctx->ccid3hctx_t_nom = now; 986 - (hctx->ccid3hctx_t_nom).tv_usec += hctx->ccid3hctx_t_ipi; 987 - timeval_fix(&(hctx->ccid3hctx_t_nom)); 1002 + timeval_add_usecs(&hctx->ccid3hctx_t_nom, 1003 + hctx->ccid3hctx_t_ipi); 988 1004 ccid3_calc_new_delta(hctx); 989 1005 rc = 0; 990 1006 break; 991 1007 case TFRC_SSTATE_NO_FBACK: 992 1008 case TFRC_SSTATE_FBACK: 993 - delay = now_delta(hctx->ccid3hctx_t_nom) - hctx->ccid3hctx_delta; 1009 + delay = (timeval_delta(&now, &hctx->ccid3hctx_t_nom) - 1010 + hctx->ccid3hctx_delta); 994 1011 ccid3_pr_debug("send_packet delay=%ld\n", delay); 995 1012 delay /= -1000; 996 1013 /* divide by -1000 is to convert to ms and get sign right */ ··· 1053 1068 * Algorithm in "8.1. Window Counter Valuer" in 1054 1069 * draft-ietf-dccp-ccid3-11.txt 1055 1070 */ 1056 - quarter_rtt = now_delta(hctx->ccid3hctx_t_last_win_count) / 1071 + quarter_rtt = timeval_delta(&now, &hctx->ccid3hctx_t_last_win_count) / 1057 1072 (hctx->ccid3hctx_rtt / 4); 1058 1073 if (quarter_rtt > 0) { 1059 1074 hctx->ccid3hctx_t_last_win_count = now; ··· 1087 1102 hctx->ccid3hctx_t_nom = now; 1088 1103 ccid3_calc_new_t_ipi(hctx); 1089 1104 ccid3_calc_new_delta(hctx); 1090 - (hctx->ccid3hctx_t_nom).tv_usec += hctx->ccid3hctx_t_ipi; 1091 - timeval_fix(&(hctx->ccid3hctx_t_nom)); 1105 + timeval_add_usecs(&hctx->ccid3hctx_t_nom, 1106 + hctx->ccid3hctx_t_ipi); 1092 1107 } 1093 1108 break; 1094 1109 default: ··· 1152 1167 } 1153 1168 1154 1169 /* Update RTT */ 1155 - r_sample = now_delta(packet->dccphtx_tstamp); 1170 + r_sample = timeval_now_delta(&packet->dccphtx_tstamp); 1156 1171 /* FIXME: */ 1157 1172 // r_sample -= usecs_to_jiffies(t_elapsed * 10); 1158 1173 ··· 1209 1224 ccid3_hc_tx_update_x(sk); 1210 1225 1211 1226 /* Update next send time */ 1212 - if (hctx->ccid3hctx_t_ipi > (hctx->ccid3hctx_t_nom).tv_usec) { 1213 - hctx->ccid3hctx_t_nom.tv_usec += USEC_PER_SEC; 1214 - (hctx->ccid3hctx_t_nom).tv_sec--; 1215 - } 1216 - /* FIXME - if no feedback then t_ipi can go > 1 second */ 1217 - (hctx->ccid3hctx_t_nom).tv_usec -= hctx->ccid3hctx_t_ipi; 1227 + timeval_sub_usecs(&hctx->ccid3hctx_t_nom, 1228 + hctx->ccid3hctx_t_ipi); 1218 1229 ccid3_calc_new_t_ipi(hctx); 1219 - (hctx->ccid3hctx_t_nom).tv_usec += hctx->ccid3hctx_t_ipi; 1220 - timeval_fix(&(hctx->ccid3hctx_t_nom)); 1230 + timeval_add_usecs(&hctx->ccid3hctx_t_nom, 1231 + hctx->ccid3hctx_t_ipi); 1221 1232 ccid3_calc_new_delta(hctx); 1222 1233 1223 1234 /* remove all packets older than the one acked from history */ ··· 1540 1559 struct dccp_sock *dp = dccp_sk(sk); 1541 1560 struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private; 1542 1561 struct dccp_rx_hist_entry *packet; 1562 + struct timeval now; 1543 1563 1544 1564 ccid3_pr_debug("%s, sk=%p\n", dccp_role(sk), sk); 1565 + 1566 + do_gettimeofday(&now); 1545 1567 1546 1568 switch (hcrx->ccid3hcrx_state) { 1547 1569 case TFRC_RSTATE_NO_DATA: 1548 1570 hcrx->ccid3hcrx_x_recv = 0; 1549 1571 break; 1550 1572 case TFRC_RSTATE_DATA: { 1551 - u32 delta = now_delta(hcrx->ccid3hcrx_tstamp_last_feedback); 1573 + const u32 delta = timeval_delta(&now, 1574 + &hcrx->ccid3hcrx_tstamp_last_feedback); 1552 1575 1553 - if (delta == 0) 1554 - delta = 1; /* to prevent divide by zero */ 1555 1576 hcrx->ccid3hcrx_x_recv = (hcrx->ccid3hcrx_bytes_recv * 1556 - USEC_PER_SEC) / delta; 1577 + USEC_PER_SEC); 1578 + if (likely(delta > 1)) 1579 + hcrx->ccid3hcrx_x_recv /= delta; 1557 1580 } 1558 1581 break; 1559 1582 default: ··· 1575 1590 return; 1576 1591 } 1577 1592 1578 - do_gettimeofday(&(hcrx->ccid3hcrx_tstamp_last_feedback)); 1593 + hcrx->ccid3hcrx_tstamp_last_feedback = now; 1579 1594 hcrx->ccid3hcrx_last_counter = packet->dccphrx_ccval; 1580 1595 hcrx->ccid3hcrx_seqno_last_counter = packet->dccphrx_seqno; 1581 1596 hcrx->ccid3hcrx_bytes_recv = 0; 1582 1597 1583 1598 /* Convert to multiples of 10us */ 1584 - hcrx->ccid3hcrx_elapsed_time = now_delta(packet->dccphrx_tstamp) / 10; 1599 + hcrx->ccid3hcrx_elapsed_time = 1600 + timeval_delta(&now, &packet->dccphrx_tstamp) / 10; 1585 1601 if (hcrx->ccid3hcrx_p == 0) 1586 1602 hcrx->ccid3hcrx_pinv = ~0; 1587 1603 else ··· 1662 1676 struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private; 1663 1677 struct dccp_rx_hist_entry *entry, *next, *tail = NULL; 1664 1678 u32 rtt, delta, x_recv, fval, p, tmp2; 1665 - struct timeval tstamp = { 0 }, tmp_tv; 1679 + struct timeval tstamp = { 0, }; 1666 1680 int interval = 0; 1667 1681 int win_count = 0; 1668 1682 int step = 0; ··· 1704 1718 interval = 1; 1705 1719 } 1706 1720 found: 1707 - timeval_sub(tstamp,tail->dccphrx_tstamp,&tmp_tv); 1708 - rtt = (tmp_tv.tv_sec * USEC_PER_SEC + tmp_tv.tv_usec) * 4 / interval; 1721 + rtt = timeval_delta(&tstamp, &tail->dccphrx_tstamp) * 4 / interval; 1709 1722 ccid3_pr_debug("%s, sk=%p, approximated RTT to %uus\n", 1710 1723 dccp_role(sk), sk, rtt); 1711 1724 if (rtt == 0) 1712 1725 rtt = 1; 1713 1726 1714 - delta = now_delta(hcrx->ccid3hcrx_tstamp_last_feedback); 1715 - if (delta == 0) 1716 - delta = 1; 1717 - 1718 - x_recv = (hcrx->ccid3hcrx_bytes_recv * USEC_PER_SEC) / delta; 1727 + delta = timeval_now_delta(&hcrx->ccid3hcrx_tstamp_last_feedback); 1728 + x_recv = hcrx->ccid3hcrx_bytes_recv * USEC_PER_SEC; 1729 + if (likely(delta > 1)) 1730 + x_recv /= delta; 1719 1731 1720 1732 tmp1 = (u64)x_recv * (u64)rtt; 1721 1733 do_div(tmp1,10000000); ··· 1910 1926 const struct dccp_options_received *opt_recv; 1911 1927 struct dccp_rx_hist_entry *packet; 1912 1928 struct timeval now; 1913 - u32 now_usecs; 1914 1929 u8 win_count; 1915 1930 u32 p_prev; 1916 1931 int ins; ··· 1931 1948 break; 1932 1949 p_prev = hcrx->ccid3hcrx_rtt; 1933 1950 do_gettimeofday(&now); 1934 - now_usecs = now.tv_sec * USEC_PER_SEC + now.tv_usec; 1935 - hcrx->ccid3hcrx_rtt = now_usecs - 1951 + hcrx->ccid3hcrx_rtt = timeval_usecs(&now) - 1936 1952 (opt_recv->dccpor_timestamp_echo - 1937 1953 opt_recv->dccpor_elapsed_time) * 10; 1938 1954 if (p_prev != hcrx->ccid3hcrx_rtt) ··· 1976 1994 case TFRC_RSTATE_DATA: 1977 1995 hcrx->ccid3hcrx_bytes_recv += skb->len - 1978 1996 dccp_hdr(skb)->dccph_doff * 4; 1979 - if (ins == 0) { 1980 - if (now_delta(hcrx->ccid3hcrx_tstamp_last_ack) >= 1981 - hcrx->ccid3hcrx_rtt) { 1982 - do_gettimeofday(&hcrx->ccid3hcrx_tstamp_last_ack); 1983 - ccid3_hc_rx_send_feedback(sk); 1984 - } 1985 - return; 1997 + if (ins != 0) 1998 + break; 1999 + 2000 + do_gettimeofday(&now); 2001 + if (timeval_delta(&now, &hcrx->ccid3hcrx_tstamp_last_ack) >= 2002 + hcrx->ccid3hcrx_rtt) { 2003 + hcrx->ccid3hcrx_tstamp_last_ack = now; 2004 + ccid3_hc_rx_send_feedback(sk); 1986 2005 } 1987 - break; 2006 + return; 1988 2007 default: 1989 2008 printk(KERN_CRIT "%s: %s, sk=%p, Illegal state (%d)!\n", 1990 2009 __FUNCTION__, dccp_role(sk), sk, hcrx->ccid3hcrx_state);
+40 -4
net/dccp/dccp.h
··· 429 429 extern void dccp_ackpkts_check_rcv_ackno(struct dccp_ackpkts *ap, 430 430 struct sock *sk, u64 ackno); 431 431 432 + static inline suseconds_t timeval_usecs(const struct timeval *tv) 433 + { 434 + return tv->tv_sec * USEC_PER_SEC + tv->tv_usec; 435 + } 436 + 437 + static inline suseconds_t timeval_delta(const struct timeval *large, 438 + const struct timeval *small) 439 + { 440 + time_t secs = large->tv_sec - small->tv_sec; 441 + suseconds_t usecs = large->tv_usec - small->tv_usec; 442 + 443 + if (usecs < 0) { 444 + secs--; 445 + usecs += USEC_PER_SEC; 446 + } 447 + return secs * USEC_PER_SEC + usecs; 448 + } 449 + 450 + static inline void timeval_add_usecs(struct timeval *tv, 451 + const suseconds_t usecs) 452 + { 453 + tv->tv_usec += usecs; 454 + while (tv->tv_usec >= USEC_PER_SEC) { 455 + tv->tv_sec++; 456 + tv->tv_usec -= USEC_PER_SEC; 457 + } 458 + } 459 + 460 + static inline void timeval_sub_usecs(struct timeval *tv, 461 + const suseconds_t usecs) 462 + { 463 + tv->tv_usec -= usecs; 464 + while (tv->tv_usec < 0) { 465 + tv->tv_sec--; 466 + tv->tv_usec += USEC_PER_SEC; 467 + } 468 + } 469 + 432 470 /* 433 471 * Returns the difference in usecs between timeval 434 472 * passed in and current time 435 473 */ 436 - static inline u32 now_delta(struct timeval tv) 474 + static inline suseconds_t timeval_now_delta(const struct timeval *tv) 437 475 { 438 476 struct timeval now; 439 - 440 477 do_gettimeofday(&now); 441 - return (now.tv_sec - tv.tv_sec) * USEC_PER_SEC + 442 - (now.tv_usec - tv.tv_usec); 478 + return timeval_delta(&now, tv); 443 479 } 444 480 445 481 #ifdef CONFIG_IP_DCCP_DEBUG
+3 -2
net/dccp/options.c
··· 359 359 #endif 360 360 struct dccp_ackpkts *ap = dp->dccps_hc_rx_ackpkts; 361 361 int len = ap->dccpap_buf_vector_len + 2; 362 - const u32 elapsed_time = now_delta(ap->dccpap_time) / 10; 362 + const u32 elapsed_time = timeval_now_delta(&ap->dccpap_time) / 10; 363 363 unsigned char *to, *from; 364 364 365 365 if (elapsed_time != 0) ··· 451 451 "CLIENT TX opt: " : "server TX opt: "; 452 452 #endif 453 453 u32 tstamp_echo; 454 - const u32 elapsed_time = now_delta(dp->dccps_timestamp_time) / 10; 454 + const u32 elapsed_time = 455 + timeval_now_delta(&dp->dccps_timestamp_time) / 10; 455 456 const int elapsed_time_len = dccp_elapsed_time_len(elapsed_time); 456 457 const int len = 6 + elapsed_time_len; 457 458 unsigned char *to;