aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIan McDonald <iam4@cs.waikato.ac.nz>2005-08-19 23:23:43 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2005-08-29 19:02:34 -0400
commit1bc0986957b63a2fbbc46ab95d3d1d72830bda83 (patch)
tree8be8f0e0e19f58cc5cc9cb7d789f3283436712ed
parentbf0ff9e578ba7dd8331005f00ad7310122011f43 (diff)
[DCCP]: Fix the timestamp options
This changes timestamp, timestamp echo, and elapsed time to use units of 10 usecs as per DCCP spec. This has been tested to verify that times are correct. Also fixed up length and used hton/ntoh more. Still to add in later patches: - actually use elapsed time to adjust RTT (commented out as was prior to this patch) - send options at times more closely following the spec (content is now correct) Signed-off-by: Ian McDonald <iam4@cs.waikato.ac.nz> Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/linux/dccp.h2
-rw-r--r--net/dccp/ccids/ccid3.c12
-rw-r--r--net/dccp/dccp.h19
-rw-r--r--net/dccp/options.c87
4 files changed, 79 insertions, 41 deletions
diff --git a/include/linux/dccp.h b/include/linux/dccp.h
index 3dccdd5108b5..9e3a1370b906 100644
--- a/include/linux/dccp.h
+++ b/include/linux/dccp.h
@@ -415,7 +415,7 @@ struct dccp_sock {
415 __u64 dccps_gsr; 415 __u64 dccps_gsr;
416 __u64 dccps_gar; 416 __u64 dccps_gar;
417 unsigned long dccps_service; 417 unsigned long dccps_service;
418 unsigned long dccps_timestamp_time; 418 struct timeval dccps_timestamp_time;
419 __u32 dccps_timestamp_echo; 419 __u32 dccps_timestamp_echo;
420 __u32 dccps_avg_packet_size; 420 __u32 dccps_avg_packet_size;
421 unsigned long dccps_ndp_count; 421 unsigned long dccps_ndp_count;
diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c
index 2dd3e94ba8f4..694149061b8b 100644
--- a/net/dccp/ccids/ccid3.c
+++ b/net/dccp/ccids/ccid3.c
@@ -2,12 +2,12 @@
2 * net/dccp/ccids/ccid3.c 2 * net/dccp/ccids/ccid3.c
3 * 3 *
4 * Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand. 4 * Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand.
5 * Copyright (c) 2005 Ian McDonald <iam4@cs.waikato.ac.nz>
5 * 6 *
6 * An implementation of the DCCP protocol 7 * An implementation of the DCCP protocol
7 * 8 *
8 * This code has been developed by the University of Waikato WAND 9 * This code has been developed by the University of Waikato WAND
9 * research group. For further information please see http://www.wand.net.nz/ 10 * research group. For further information please see http://www.wand.net.nz/
10 * or e-mail Ian McDonald - iam4@cs.waikato.ac.nz
11 * 11 *
12 * This code also uses code from Lulea University, rereleased as GPL by its 12 * This code also uses code from Lulea University, rereleased as GPL by its
13 * authors: 13 * authors:
@@ -174,14 +174,6 @@ static inline void timeval_fix(struct timeval *tv)
174 } 174 }
175} 175}
176 176
177/* returns the difference in usecs between timeval passed in and current time */
178static inline u32 now_delta(struct timeval tv) {
179 struct timeval now;
180
181 do_gettimeofday(&now);
182 return ((now.tv_sec-tv.tv_sec)*1000000+now.tv_usec-tv.tv_usec);
183}
184
185#define CALCX_ARRSIZE 500 177#define CALCX_ARRSIZE 500
186 178
187#define CALCX_SPLIT 50000 179#define CALCX_SPLIT 50000
@@ -1110,7 +1102,7 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
1110 struct ccid3_options_received *opt_recv; 1102 struct ccid3_options_received *opt_recv;
1111 struct dccp_tx_hist_entry *packet; 1103 struct dccp_tx_hist_entry *packet;
1112 unsigned long next_tmout; 1104 unsigned long next_tmout;
1113 u16 t_elapsed; 1105 u32 t_elapsed;
1114 u32 pinv; 1106 u32 pinv;
1115 u32 x_recv; 1107 u32 x_recv;
1116 u32 r_sample; 1108 u32 r_sample;
diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h
index 4efdce47000b..aab72b8d0703 100644
--- a/net/dccp/dccp.h
+++ b/net/dccp/dccp.h
@@ -4,7 +4,8 @@
4 * net/dccp/dccp.h 4 * net/dccp/dccp.h
5 * 5 *
6 * An implementation of the DCCP protocol 6 * An implementation of the DCCP protocol
7 * Arnaldo Carvalho de Melo <acme@conectiva.com.br> 7 * Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
8 * Copyright (c) 2005 Ian McDonald <iam4@cs.waikato.ac.nz>
8 * 9 *
9 * This program is free software; you can redistribute it and/or modify it 10 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License version 2 as 11 * under the terms of the GNU General Public License version 2 as
@@ -404,6 +405,7 @@ extern struct socket *dccp_ctl_socket;
404 * @dccpap_ack_nonce - the one-bit sum of the ECN Nonces for all State 0. 405 * @dccpap_ack_nonce - the one-bit sum of the ECN Nonces for all State 0.
405 * 406 *
406 * @dccpap_buf_len - circular buffer length 407 * @dccpap_buf_len - circular buffer length
408 * @dccpap_time - the time in usecs
407 * @dccpap_buf - circular buffer of acknowledgeable packets 409 * @dccpap_buf - circular buffer of acknowledgeable packets
408 */ 410 */
409struct dccp_ackpkts { 411struct dccp_ackpkts {
@@ -416,7 +418,7 @@ struct dccp_ackpkts {
416 unsigned int dccpap_buf_vector_len; 418 unsigned int dccpap_buf_vector_len;
417 unsigned int dccpap_ack_vector_len; 419 unsigned int dccpap_ack_vector_len;
418 unsigned int dccpap_buf_len; 420 unsigned int dccpap_buf_len;
419 unsigned long dccpap_time; 421 struct timeval dccpap_time;
420 u8 dccpap_buf_nonce; 422 u8 dccpap_buf_nonce;
421 u8 dccpap_ack_nonce; 423 u8 dccpap_ack_nonce;
422 u8 dccpap_buf[0]; 424 u8 dccpap_buf[0];
@@ -430,6 +432,19 @@ extern int dccp_ackpkts_add(struct dccp_ackpkts *ap, u64 ackno, u8 state);
430extern void dccp_ackpkts_check_rcv_ackno(struct dccp_ackpkts *ap, 432extern void dccp_ackpkts_check_rcv_ackno(struct dccp_ackpkts *ap,
431 struct sock *sk, u64 ackno); 433 struct sock *sk, u64 ackno);
432 434
435/*
436 * Returns the difference in usecs between timeval
437 * passed in and current time
438 */
439static inline u32 now_delta(struct timeval tv)
440{
441 struct timeval now;
442
443 do_gettimeofday(&now);
444 return (now.tv_sec - tv.tv_sec) * USEC_PER_SEC +
445 (now.tv_usec - tv.tv_usec);
446}
447
433#ifdef CONFIG_IP_DCCP_DEBUG 448#ifdef CONFIG_IP_DCCP_DEBUG
434extern void dccp_ackvector_print(const u64 ackno, 449extern void dccp_ackvector_print(const u64 ackno,
435 const unsigned char *vector, int len); 450 const unsigned char *vector, int len);
diff --git a/net/dccp/options.c b/net/dccp/options.c
index 85a86bd61f44..7ecffdf85756 100644
--- a/net/dccp/options.c
+++ b/net/dccp/options.c
@@ -2,8 +2,9 @@
2 * net/dccp/options.c 2 * net/dccp/options.c
3 * 3 *
4 * An implementation of the DCCP protocol 4 * An implementation of the DCCP protocol
5 * Aristeu Sergio Rozanski Filho <aris@cathedrallabs.org> 5 * Copyright (c) 2005 Aristeu Sergio Rozanski Filho <aris@cathedrallabs.org>
6 * Arnaldo Carvalho de Melo <acme@ghostprotocols.net> 6 * Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
7 * Copyright (c) 2005 Ian McDonald <iam4@cs.waikato.ac.nz>
7 * 8 *
8 * This program is free software; you can redistribute it and/or 9 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License 10 * modify it under the terms of the GNU General Public License
@@ -138,7 +139,7 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb)
138 opt_recv->dccpor_timestamp = ntohl(*(u32 *)value); 139 opt_recv->dccpor_timestamp = ntohl(*(u32 *)value);
139 140
140 dp->dccps_timestamp_echo = opt_recv->dccpor_timestamp; 141 dp->dccps_timestamp_echo = opt_recv->dccpor_timestamp;
141 dp->dccps_timestamp_time = jiffies; 142 do_gettimeofday(&dp->dccps_timestamp_time);
142 143
143 dccp_pr_debug("%sTIMESTAMP=%u, ackno=%llu\n", 144 dccp_pr_debug("%sTIMESTAMP=%u, ackno=%llu\n",
144 debug_prefix, opt_recv->dccpor_timestamp, 145 debug_prefix, opt_recv->dccpor_timestamp,
@@ -146,36 +147,45 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb)
146 DCCP_SKB_CB(skb)->dccpd_ack_seq); 147 DCCP_SKB_CB(skb)->dccpd_ack_seq);
147 break; 148 break;
148 case DCCPO_TIMESTAMP_ECHO: 149 case DCCPO_TIMESTAMP_ECHO:
149 if (len < 4 || len > 8) 150 if (len != 4 && len != 6 && len != 8)
150 goto out_invalid_option; 151 goto out_invalid_option;
151 152
152 opt_recv->dccpor_timestamp_echo = ntohl(*(u32 *)value); 153 opt_recv->dccpor_timestamp_echo = ntohl(*(u32 *)value);
153 154
154 dccp_pr_debug("%sTIMESTAMP_ECHO=%u, len=%d, ackno=%llu, " 155 dccp_pr_debug("%sTIMESTAMP_ECHO=%u, len=%d, ackno=%llu, ",
155 "diff=%u\n",
156 debug_prefix, 156 debug_prefix,
157 opt_recv->dccpor_timestamp_echo, 157 opt_recv->dccpor_timestamp_echo,
158 len + 2, 158 len + 2,
159 (unsigned long long) 159 (unsigned long long)
160 DCCP_SKB_CB(skb)->dccpd_ack_seq, 160 DCCP_SKB_CB(skb)->dccpd_ack_seq);
161 (tcp_time_stamp - 161
162 opt_recv->dccpor_timestamp_echo)); 162 if (len > 4) {
163 163 if (len == 6)
164 opt_recv->dccpor_elapsed_time = 164 opt_recv->dccpor_elapsed_time =
165 dccp_decode_value_var(value + 4, 165 ntohs(*(u16 *)(value + 4));
166 len - 4); 166 else
167 dccp_pr_debug("%sTIMESTAMP_ECHO ELAPSED_TIME=%d\n", 167 opt_recv->dccpor_elapsed_time =
168 ntohl(*(u32 *)(value + 4));
169
170 dccp_pr_debug("%sTIMESTAMP_ECHO ELAPSED_TIME=%d\n",
168 debug_prefix, 171 debug_prefix,
169 opt_recv->dccpor_elapsed_time); 172 opt_recv->dccpor_elapsed_time);
173 }
170 break; 174 break;
171 case DCCPO_ELAPSED_TIME: 175 case DCCPO_ELAPSED_TIME:
172 if (len > 4) 176 if (len != 2 && len != 4)
173 goto out_invalid_option; 177 goto out_invalid_option;
174 178
175 if (pkt_type == DCCP_PKT_DATA) 179 if (pkt_type == DCCP_PKT_DATA)
176 continue; 180 continue;
177 opt_recv->dccpor_elapsed_time = 181
178 dccp_decode_value_var(value, len); 182 if (len == 2)
183 opt_recv->dccpor_elapsed_time =
184 ntohs(*(u16 *)value);
185 else
186 opt_recv->dccpor_elapsed_time =
187 ntohl(*(u32 *)value);
188
179 dccp_pr_debug("%sELAPSED_TIME=%d\n", debug_prefix, 189 dccp_pr_debug("%sELAPSED_TIME=%d\n", debug_prefix,
180 opt_recv->dccpor_elapsed_time); 190 opt_recv->dccpor_elapsed_time);
181 break; 191 break;
@@ -309,8 +319,7 @@ void dccp_insert_option_elapsed_time(struct sock *sk,
309 const int len = 2 + elapsed_time_len; 319 const int len = 2 + elapsed_time_len;
310 unsigned char *to; 320 unsigned char *to;
311 321
312 /* If elapsed_time == 0... */ 322 if (elapsed_time_len == 0)
313 if (elapsed_time_len == 2)
314 return; 323 return;
315 324
316 if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN) { 325 if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN) {
@@ -325,7 +334,13 @@ void dccp_insert_option_elapsed_time(struct sock *sk,
325 *to++ = DCCPO_ELAPSED_TIME; 334 *to++ = DCCPO_ELAPSED_TIME;
326 *to++ = len; 335 *to++ = len;
327 336
328 dccp_encode_value_var(elapsed_time, to, elapsed_time_len); 337 if (elapsed_time_len == 2) {
338 const u16 var16 = htons((u16)elapsed_time);
339 memcpy(to, &var16, 2);
340 } else {
341 const u32 var32 = htonl(elapsed_time);
342 memcpy(to, &var32, 4);
343 }
329 344
330 dccp_pr_debug("%sELAPSED_TIME=%u, len=%d, seqno=%llu\n", 345 dccp_pr_debug("%sELAPSED_TIME=%u, len=%d, seqno=%llu\n",
331 debug_prefix, elapsed_time, 346 debug_prefix, elapsed_time,
@@ -344,7 +359,7 @@ static void dccp_insert_option_ack_vector(struct sock *sk, struct sk_buff *skb)
344#endif 359#endif
345 struct dccp_ackpkts *ap = dp->dccps_hc_rx_ackpkts; 360 struct dccp_ackpkts *ap = dp->dccps_hc_rx_ackpkts;
346 int len = ap->dccpap_buf_vector_len + 2; 361 int len = ap->dccpap_buf_vector_len + 2;
347 const u32 elapsed_time = jiffies_to_usecs(jiffies - ap->dccpap_time) / 10; 362 const u32 elapsed_time = now_delta(ap->dccpap_time) / 10;
348 unsigned char *to, *from; 363 unsigned char *to, *from;
349 364
350 if (elapsed_time != 0) 365 if (elapsed_time != 0)
@@ -414,7 +429,15 @@ static void dccp_insert_option_ack_vector(struct sock *sk, struct sk_buff *skb)
414static inline void dccp_insert_option_timestamp(struct sock *sk, 429static inline void dccp_insert_option_timestamp(struct sock *sk,
415 struct sk_buff *skb) 430 struct sk_buff *skb)
416{ 431{
417 const u32 now = htonl(tcp_time_stamp); 432 struct timeval tv;
433 u32 now;
434
435 do_gettimeofday(&tv);
436 now = (tv.tv_sec * USEC_PER_SEC + tv.tv_usec) / 10;
437 /* yes this will overflow but that is the point as we want a
438 * 10 usec 32 bit timer which mean it wraps every 11.9 hours */
439
440 now = htonl(now);
418 dccp_insert_option(sk, skb, DCCPO_TIMESTAMP, &now, sizeof(now)); 441 dccp_insert_option(sk, skb, DCCPO_TIMESTAMP, &now, sizeof(now));
419} 442}
420 443
@@ -427,8 +450,7 @@ static void dccp_insert_option_timestamp_echo(struct sock *sk,
427 "CLIENT TX opt: " : "server TX opt: "; 450 "CLIENT TX opt: " : "server TX opt: ";
428#endif 451#endif
429 u32 tstamp_echo; 452 u32 tstamp_echo;
430 const u32 elapsed_time = jiffies_to_usecs(jiffies - 453 const u32 elapsed_time = now_delta(dp->dccps_timestamp_time) / 10;
431 dp->dccps_timestamp_time) / 10;
432 const int elapsed_time_len = dccp_elapsed_time_len(elapsed_time); 454 const int elapsed_time_len = dccp_elapsed_time_len(elapsed_time);
433 const int len = 6 + elapsed_time_len; 455 const int len = 6 + elapsed_time_len;
434 unsigned char *to; 456 unsigned char *to;
@@ -448,7 +470,14 @@ static void dccp_insert_option_timestamp_echo(struct sock *sk,
448 tstamp_echo = htonl(dp->dccps_timestamp_echo); 470 tstamp_echo = htonl(dp->dccps_timestamp_echo);
449 memcpy(to, &tstamp_echo, 4); 471 memcpy(to, &tstamp_echo, 4);
450 to += 4; 472 to += 4;
451 dccp_encode_value_var(elapsed_time, to, elapsed_time_len); 473
474 if (elapsed_time_len == 2) {
475 const u16 var16 = htons((u16)elapsed_time);
476 memcpy(to, &var16, 2);
477 } else if (elapsed_time_len == 4) {
478 const u32 var32 = htonl(elapsed_time);
479 memcpy(to, &var32, 4);
480 }
452 481
453 dccp_pr_debug("%sTIMESTAMP_ECHO=%u, len=%d, seqno=%llu\n", 482 dccp_pr_debug("%sTIMESTAMP_ECHO=%u, len=%d, seqno=%llu\n",
454 debug_prefix, dp->dccps_timestamp_echo, 483 debug_prefix, dp->dccps_timestamp_echo,
@@ -456,7 +485,8 @@ static void dccp_insert_option_timestamp_echo(struct sock *sk,
456 (unsigned long long) DCCP_SKB_CB(skb)->dccpd_seq); 485 (unsigned long long) DCCP_SKB_CB(skb)->dccpd_seq);
457 486
458 dp->dccps_timestamp_echo = 0; 487 dp->dccps_timestamp_echo = 0;
459 dp->dccps_timestamp_time = 0; 488 dp->dccps_timestamp_time.tv_sec = 0;
489 dp->dccps_timestamp_time.tv_usec = 0;
460} 490}
461 491
462void dccp_insert_options(struct sock *sk, struct sk_buff *skb) 492void dccp_insert_options(struct sock *sk, struct sk_buff *skb)
@@ -514,7 +544,8 @@ struct dccp_ackpkts *dccp_ackpkts_alloc(const unsigned int len,
514 ap->dccpap_ack_seqno = DCCP_MAX_SEQNO + 1; 544 ap->dccpap_ack_seqno = DCCP_MAX_SEQNO + 1;
515 ap->dccpap_buf_nonce = ap->dccpap_buf_nonce = 0; 545 ap->dccpap_buf_nonce = ap->dccpap_buf_nonce = 0;
516 ap->dccpap_ack_ptr = 0; 546 ap->dccpap_ack_ptr = 0;
517 ap->dccpap_time = 0; 547 ap->dccpap_time.tv_sec = 0;
548 ap->dccpap_time.tv_usec = 0;
518 ap->dccpap_buf_vector_len = ap->dccpap_ack_vector_len = 0; 549 ap->dccpap_buf_vector_len = ap->dccpap_ack_vector_len = 0;
519 } 550 }
520 551
@@ -665,7 +696,7 @@ int dccp_ackpkts_add(struct dccp_ackpkts *ap, u64 ackno, u8 state)
665 } 696 }
666 697
667 ap->dccpap_buf_ackno = ackno; 698 ap->dccpap_buf_ackno = ackno;
668 ap->dccpap_time = jiffies; 699 do_gettimeofday(&ap->dccpap_time);
669out: 700out:
670 dccp_pr_debug(""); 701 dccp_pr_debug("");
671 dccp_ackpkts_print(ap); 702 dccp_ackpkts_print(ap);