aboutsummaryrefslogtreecommitdiffstats
path: root/net/dccp/options.c
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 /net/dccp/options.c
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>
Diffstat (limited to 'net/dccp/options.c')
-rw-r--r--net/dccp/options.c87
1 files changed, 59 insertions, 28 deletions
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);