aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@mandriva.com>2005-08-27 17:18:18 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2005-08-29 19:11:56 -0400
commitb6ee3d4ada4e85d9b9b9164c1327ef0850c79d5e (patch)
tree26dfc68ab042ebb8186fe3a93a34723cb1faaae1
parent1f2333aea3269e196c44ae9a220e714cc1427792 (diff)
[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>
-rw-r--r--net/dccp/ccids/ccid3.c127
-rw-r--r--net/dccp/dccp.h44
-rw-r--r--net/dccp/options.c5
3 files changed, 98 insertions, 78 deletions
diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c
index 225c53013172..60e3a5f9fcb4 100644
--- a/net/dccp/ccids/ccid3.c
+++ b/net/dccp/ccids/ccid3.c
@@ -156,26 +156,6 @@ static inline void ccid3_hc_tx_set_state(struct sock *sk,
156 hctx->ccid3hctx_state = state; 156 hctx->ccid3hctx_state = state;
157} 157}
158 158
159static 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
171static 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#define CALCX_ARRSIZE 500 159#define CALCX_ARRSIZE 500
180 160
181#define CALCX_SPLIT 50000 161#define CALCX_SPLIT 50000
@@ -816,18 +796,22 @@ static void ccid3_hc_tx_update_x(struct sock *sk)
816 2 * hctx->ccid3hctx_x_recv), 796 2 * hctx->ccid3hctx_x_recv),
817 (hctx->ccid3hctx_s / 797 (hctx->ccid3hctx_s /
818 TFRC_MAX_BACK_OFF_TIME)); 798 TFRC_MAX_BACK_OFF_TIME));
819 } else if (now_delta(hctx->ccid3hctx_t_ld) >= hctx->ccid3hctx_rtt) { 799 } else {
820 u32 rtt = hctx->ccid3hctx_rtt; 800 struct timeval now;
821 if (rtt < 10) { 801
822 rtt = 10; 802 do_gettimeofday(&now);
823 } /* avoid divide by zero below */ 803 if (timeval_delta(&now, &hctx->ccid3hctx_t_ld) >=
824 804 hctx->ccid3hctx_rtt) {
825 hctx->ccid3hctx_x = max_t(u32, min_t(u32, 2 * hctx->ccid3hctx_x_recv, 805 /* Avoid divide by zero below */
826 2 * hctx->ccid3hctx_x), 806 const u32 rtt = max_t(u32, hctx->ccid3hctx_rtt, 10);
827 ((hctx->ccid3hctx_s * 100000) / 807
828 (rtt / 10))); 808 hctx->ccid3hctx_x = max_t(u32, min_t(u32, 2 * hctx->ccid3hctx_x_recv,
829 /* Using 100000 and 10 to avoid 32 bit overflow for jumbo frames */ 809 2 * hctx->ccid3hctx_x),
830 do_gettimeofday(&hctx->ccid3hctx_t_ld); 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;
814 }
831 } 815 }
832 816
833 if (hctx->ccid3hctx_x == 0) { 817 if (hctx->ccid3hctx_x == 0) {
@@ -999,14 +983,15 @@ static int ccid3_hc_tx_send_packet(struct sock *sk,
999 983
1000 /* Set nominal send time for initial packet */ 984 /* Set nominal send time for initial packet */
1001 hctx->ccid3hctx_t_nom = now; 985 hctx->ccid3hctx_t_nom = now;
1002 (hctx->ccid3hctx_t_nom).tv_usec += hctx->ccid3hctx_t_ipi; 986 timeval_add_usecs(&hctx->ccid3hctx_t_nom,
1003 timeval_fix(&(hctx->ccid3hctx_t_nom)); 987 hctx->ccid3hctx_t_ipi);
1004 ccid3_calc_new_delta(hctx); 988 ccid3_calc_new_delta(hctx);
1005 rc = 0; 989 rc = 0;
1006 break; 990 break;
1007 case TFRC_SSTATE_NO_FBACK: 991 case TFRC_SSTATE_NO_FBACK:
1008 case TFRC_SSTATE_FBACK: 992 case TFRC_SSTATE_FBACK:
1009 delay = now_delta(hctx->ccid3hctx_t_nom) - hctx->ccid3hctx_delta; 993 delay = (timeval_delta(&now, &hctx->ccid3hctx_t_nom) -
994 hctx->ccid3hctx_delta);
1010 ccid3_pr_debug("send_packet delay=%ld\n", delay); 995 ccid3_pr_debug("send_packet delay=%ld\n", delay);
1011 delay /= -1000; 996 delay /= -1000;
1012 /* divide by -1000 is to convert to ms and get sign right */ 997 /* divide by -1000 is to convert to ms and get sign right */
@@ -1068,7 +1053,7 @@ static void ccid3_hc_tx_packet_sent(struct sock *sk, int more, int len)
1068 * Algorithm in "8.1. Window Counter Valuer" in 1053 * Algorithm in "8.1. Window Counter Valuer" in
1069 * draft-ietf-dccp-ccid3-11.txt 1054 * draft-ietf-dccp-ccid3-11.txt
1070 */ 1055 */
1071 quarter_rtt = now_delta(hctx->ccid3hctx_t_last_win_count) / 1056 quarter_rtt = timeval_delta(&now, &hctx->ccid3hctx_t_last_win_count) /
1072 (hctx->ccid3hctx_rtt / 4); 1057 (hctx->ccid3hctx_rtt / 4);
1073 if (quarter_rtt > 0) { 1058 if (quarter_rtt > 0) {
1074 hctx->ccid3hctx_t_last_win_count = now; 1059 hctx->ccid3hctx_t_last_win_count = now;
@@ -1102,8 +1087,8 @@ static void ccid3_hc_tx_packet_sent(struct sock *sk, int more, int len)
1102 hctx->ccid3hctx_t_nom = now; 1087 hctx->ccid3hctx_t_nom = now;
1103 ccid3_calc_new_t_ipi(hctx); 1088 ccid3_calc_new_t_ipi(hctx);
1104 ccid3_calc_new_delta(hctx); 1089 ccid3_calc_new_delta(hctx);
1105 (hctx->ccid3hctx_t_nom).tv_usec += hctx->ccid3hctx_t_ipi; 1090 timeval_add_usecs(&hctx->ccid3hctx_t_nom,
1106 timeval_fix(&(hctx->ccid3hctx_t_nom)); 1091 hctx->ccid3hctx_t_ipi);
1107 } 1092 }
1108 break; 1093 break;
1109 default: 1094 default:
@@ -1167,7 +1152,7 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
1167 } 1152 }
1168 1153
1169 /* Update RTT */ 1154 /* Update RTT */
1170 r_sample = now_delta(packet->dccphtx_tstamp); 1155 r_sample = timeval_now_delta(&packet->dccphtx_tstamp);
1171 /* FIXME: */ 1156 /* FIXME: */
1172 // r_sample -= usecs_to_jiffies(t_elapsed * 10); 1157 // r_sample -= usecs_to_jiffies(t_elapsed * 10);
1173 1158
@@ -1224,15 +1209,11 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
1224 ccid3_hc_tx_update_x(sk); 1209 ccid3_hc_tx_update_x(sk);
1225 1210
1226 /* Update next send time */ 1211 /* Update next send time */
1227 if (hctx->ccid3hctx_t_ipi > (hctx->ccid3hctx_t_nom).tv_usec) { 1212 timeval_sub_usecs(&hctx->ccid3hctx_t_nom,
1228 hctx->ccid3hctx_t_nom.tv_usec += USEC_PER_SEC; 1213 hctx->ccid3hctx_t_ipi);
1229 (hctx->ccid3hctx_t_nom).tv_sec--;
1230 }
1231 /* FIXME - if no feedback then t_ipi can go > 1 second */
1232 (hctx->ccid3hctx_t_nom).tv_usec -= hctx->ccid3hctx_t_ipi;
1233 ccid3_calc_new_t_ipi(hctx); 1214 ccid3_calc_new_t_ipi(hctx);
1234 (hctx->ccid3hctx_t_nom).tv_usec += hctx->ccid3hctx_t_ipi; 1215 timeval_add_usecs(&hctx->ccid3hctx_t_nom,
1235 timeval_fix(&(hctx->ccid3hctx_t_nom)); 1216 hctx->ccid3hctx_t_ipi);
1236 ccid3_calc_new_delta(hctx); 1217 ccid3_calc_new_delta(hctx);
1237 1218
1238 /* remove all packets older than the one acked from history */ 1219 /* remove all packets older than the one acked from history */
@@ -1559,20 +1540,24 @@ static void ccid3_hc_rx_send_feedback(struct sock *sk)
1559 struct dccp_sock *dp = dccp_sk(sk); 1540 struct dccp_sock *dp = dccp_sk(sk);
1560 struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private; 1541 struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private;
1561 struct dccp_rx_hist_entry *packet; 1542 struct dccp_rx_hist_entry *packet;
1543 struct timeval now;
1562 1544
1563 ccid3_pr_debug("%s, sk=%p\n", dccp_role(sk), sk); 1545 ccid3_pr_debug("%s, sk=%p\n", dccp_role(sk), sk);
1564 1546
1547 do_gettimeofday(&now);
1548
1565 switch (hcrx->ccid3hcrx_state) { 1549 switch (hcrx->ccid3hcrx_state) {
1566 case TFRC_RSTATE_NO_DATA: 1550 case TFRC_RSTATE_NO_DATA:
1567 hcrx->ccid3hcrx_x_recv = 0; 1551 hcrx->ccid3hcrx_x_recv = 0;
1568 break; 1552 break;
1569 case TFRC_RSTATE_DATA: { 1553 case TFRC_RSTATE_DATA: {
1570 u32 delta = now_delta(hcrx->ccid3hcrx_tstamp_last_feedback); 1554 const u32 delta = timeval_delta(&now,
1555 &hcrx->ccid3hcrx_tstamp_last_feedback);
1571 1556
1572 if (delta == 0)
1573 delta = 1; /* to prevent divide by zero */
1574 hcrx->ccid3hcrx_x_recv = (hcrx->ccid3hcrx_bytes_recv * 1557 hcrx->ccid3hcrx_x_recv = (hcrx->ccid3hcrx_bytes_recv *
1575 USEC_PER_SEC) / delta; 1558 USEC_PER_SEC);
1559 if (likely(delta > 1))
1560 hcrx->ccid3hcrx_x_recv /= delta;
1576 } 1561 }
1577 break; 1562 break;
1578 default: 1563 default:
@@ -1590,13 +1575,14 @@ static void ccid3_hc_rx_send_feedback(struct sock *sk)
1590 return; 1575 return;
1591 } 1576 }
1592 1577
1593 do_gettimeofday(&(hcrx->ccid3hcrx_tstamp_last_feedback)); 1578 hcrx->ccid3hcrx_tstamp_last_feedback = now;
1594 hcrx->ccid3hcrx_last_counter = packet->dccphrx_ccval; 1579 hcrx->ccid3hcrx_last_counter = packet->dccphrx_ccval;
1595 hcrx->ccid3hcrx_seqno_last_counter = packet->dccphrx_seqno; 1580 hcrx->ccid3hcrx_seqno_last_counter = packet->dccphrx_seqno;
1596 hcrx->ccid3hcrx_bytes_recv = 0; 1581 hcrx->ccid3hcrx_bytes_recv = 0;
1597 1582
1598 /* Convert to multiples of 10us */ 1583 /* Convert to multiples of 10us */
1599 hcrx->ccid3hcrx_elapsed_time = now_delta(packet->dccphrx_tstamp) / 10; 1584 hcrx->ccid3hcrx_elapsed_time =
1585 timeval_delta(&now, &packet->dccphrx_tstamp) / 10;
1600 if (hcrx->ccid3hcrx_p == 0) 1586 if (hcrx->ccid3hcrx_p == 0)
1601 hcrx->ccid3hcrx_pinv = ~0; 1587 hcrx->ccid3hcrx_pinv = ~0;
1602 else 1588 else
@@ -1676,7 +1662,7 @@ static u32 ccid3_hc_rx_calc_first_li(struct sock *sk)
1676 struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private; 1662 struct ccid3_hc_rx_sock *hcrx = dp->dccps_hc_rx_ccid_private;
1677 struct dccp_rx_hist_entry *entry, *next, *tail = NULL; 1663 struct dccp_rx_hist_entry *entry, *next, *tail = NULL;
1678 u32 rtt, delta, x_recv, fval, p, tmp2; 1664 u32 rtt, delta, x_recv, fval, p, tmp2;
1679 struct timeval tstamp = { 0 }, tmp_tv; 1665 struct timeval tstamp = { 0, };
1680 int interval = 0; 1666 int interval = 0;
1681 int win_count = 0; 1667 int win_count = 0;
1682 int step = 0; 1668 int step = 0;
@@ -1718,18 +1704,16 @@ static u32 ccid3_hc_rx_calc_first_li(struct sock *sk)
1718 interval = 1; 1704 interval = 1;
1719 } 1705 }
1720found: 1706found:
1721 timeval_sub(tstamp,tail->dccphrx_tstamp,&tmp_tv); 1707 rtt = timeval_delta(&tstamp, &tail->dccphrx_tstamp) * 4 / interval;
1722 rtt = (tmp_tv.tv_sec * USEC_PER_SEC + tmp_tv.tv_usec) * 4 / interval;
1723 ccid3_pr_debug("%s, sk=%p, approximated RTT to %uus\n", 1708 ccid3_pr_debug("%s, sk=%p, approximated RTT to %uus\n",
1724 dccp_role(sk), sk, rtt); 1709 dccp_role(sk), sk, rtt);
1725 if (rtt == 0) 1710 if (rtt == 0)
1726 rtt = 1; 1711 rtt = 1;
1727 1712
1728 delta = now_delta(hcrx->ccid3hcrx_tstamp_last_feedback); 1713 delta = timeval_now_delta(&hcrx->ccid3hcrx_tstamp_last_feedback);
1729 if (delta == 0) 1714 x_recv = hcrx->ccid3hcrx_bytes_recv * USEC_PER_SEC;
1730 delta = 1; 1715 if (likely(delta > 1))
1731 1716 x_recv /= delta;
1732 x_recv = (hcrx->ccid3hcrx_bytes_recv * USEC_PER_SEC) / delta;
1733 1717
1734 tmp1 = (u64)x_recv * (u64)rtt; 1718 tmp1 = (u64)x_recv * (u64)rtt;
1735 do_div(tmp1,10000000); 1719 do_div(tmp1,10000000);
@@ -1926,7 +1910,6 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
1926 const struct dccp_options_received *opt_recv; 1910 const struct dccp_options_received *opt_recv;
1927 struct dccp_rx_hist_entry *packet; 1911 struct dccp_rx_hist_entry *packet;
1928 struct timeval now; 1912 struct timeval now;
1929 u32 now_usecs;
1930 u8 win_count; 1913 u8 win_count;
1931 u32 p_prev; 1914 u32 p_prev;
1932 int ins; 1915 int ins;
@@ -1948,8 +1931,7 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
1948 break; 1931 break;
1949 p_prev = hcrx->ccid3hcrx_rtt; 1932 p_prev = hcrx->ccid3hcrx_rtt;
1950 do_gettimeofday(&now); 1933 do_gettimeofday(&now);
1951 now_usecs = now.tv_sec * USEC_PER_SEC + now.tv_usec; 1934 hcrx->ccid3hcrx_rtt = timeval_usecs(&now) -
1952 hcrx->ccid3hcrx_rtt = now_usecs -
1953 (opt_recv->dccpor_timestamp_echo - 1935 (opt_recv->dccpor_timestamp_echo -
1954 opt_recv->dccpor_elapsed_time) * 10; 1936 opt_recv->dccpor_elapsed_time) * 10;
1955 if (p_prev != hcrx->ccid3hcrx_rtt) 1937 if (p_prev != hcrx->ccid3hcrx_rtt)
@@ -1994,15 +1976,16 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb)
1994 case TFRC_RSTATE_DATA: 1976 case TFRC_RSTATE_DATA:
1995 hcrx->ccid3hcrx_bytes_recv += skb->len - 1977 hcrx->ccid3hcrx_bytes_recv += skb->len -
1996 dccp_hdr(skb)->dccph_doff * 4; 1978 dccp_hdr(skb)->dccph_doff * 4;
1997 if (ins == 0) { 1979 if (ins != 0)
1998 if (now_delta(hcrx->ccid3hcrx_tstamp_last_ack) >= 1980 break;
1999 hcrx->ccid3hcrx_rtt) { 1981
2000 do_gettimeofday(&hcrx->ccid3hcrx_tstamp_last_ack); 1982 do_gettimeofday(&now);
2001 ccid3_hc_rx_send_feedback(sk); 1983 if (timeval_delta(&now, &hcrx->ccid3hcrx_tstamp_last_ack) >=
2002 } 1984 hcrx->ccid3hcrx_rtt) {
2003 return; 1985 hcrx->ccid3hcrx_tstamp_last_ack = now;
1986 ccid3_hc_rx_send_feedback(sk);
2004 } 1987 }
2005 break; 1988 return;
2006 default: 1989 default:
2007 printk(KERN_CRIT "%s: %s, sk=%p, Illegal state (%d)!\n", 1990 printk(KERN_CRIT "%s: %s, sk=%p, Illegal state (%d)!\n",
2008 __FUNCTION__, dccp_role(sk), sk, hcrx->ccid3hcrx_state); 1991 __FUNCTION__, dccp_role(sk), sk, hcrx->ccid3hcrx_state);
diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h
index 6ba21509e797..5cd9e794bbe2 100644
--- a/net/dccp/dccp.h
+++ b/net/dccp/dccp.h
@@ -429,17 +429,53 @@ extern int dccp_ackpkts_add(struct dccp_ackpkts *ap, u64 ackno, u8 state);
429extern void dccp_ackpkts_check_rcv_ackno(struct dccp_ackpkts *ap, 429extern void dccp_ackpkts_check_rcv_ackno(struct dccp_ackpkts *ap,
430 struct sock *sk, u64 ackno); 430 struct sock *sk, u64 ackno);
431 431
432static inline suseconds_t timeval_usecs(const struct timeval *tv)
433{
434 return tv->tv_sec * USEC_PER_SEC + tv->tv_usec;
435}
436
437static 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
450static 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
460static 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 * Returns the difference in usecs between timeval 471 * Returns the difference in usecs between timeval
434 * passed in and current time 472 * passed in and current time
435 */ 473 */
436static inline u32 now_delta(struct timeval tv) 474static inline suseconds_t timeval_now_delta(const struct timeval *tv)
437{ 475{
438 struct timeval now; 476 struct timeval now;
439
440 do_gettimeofday(&now); 477 do_gettimeofday(&now);
441 return (now.tv_sec - tv.tv_sec) * USEC_PER_SEC + 478 return timeval_delta(&now, tv);
442 (now.tv_usec - tv.tv_usec);
443} 479}
444 480
445#ifdef CONFIG_IP_DCCP_DEBUG 481#ifdef CONFIG_IP_DCCP_DEBUG
diff --git a/net/dccp/options.c b/net/dccp/options.c
index eabcc8f1c625..382c5894acb2 100644
--- a/net/dccp/options.c
+++ b/net/dccp/options.c
@@ -359,7 +359,7 @@ static void dccp_insert_option_ack_vector(struct sock *sk, struct sk_buff *skb)
359#endif 359#endif
360 struct dccp_ackpkts *ap = dp->dccps_hc_rx_ackpkts; 360 struct dccp_ackpkts *ap = dp->dccps_hc_rx_ackpkts;
361 int len = ap->dccpap_buf_vector_len + 2; 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 unsigned char *to, *from; 363 unsigned char *to, *from;
364 364
365 if (elapsed_time != 0) 365 if (elapsed_time != 0)
@@ -451,7 +451,8 @@ static void dccp_insert_option_timestamp_echo(struct sock *sk,
451 "CLIENT TX opt: " : "server TX opt: "; 451 "CLIENT TX opt: " : "server TX opt: ";
452#endif 452#endif
453 u32 tstamp_echo; 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 const int elapsed_time_len = dccp_elapsed_time_len(elapsed_time); 456 const int elapsed_time_len = dccp_elapsed_time_len(elapsed_time);
456 const int len = 6 + elapsed_time_len; 457 const int len = 6 + elapsed_time_len;
457 unsigned char *to; 458 unsigned char *to;