diff options
author | Ian McDonald <iam4@cs.waikato.ac.nz> | 2005-08-19 23:23:43 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2005-08-29 19:02:34 -0400 |
commit | 1bc0986957b63a2fbbc46ab95d3d1d72830bda83 (patch) | |
tree | 8be8f0e0e19f58cc5cc9cb7d789f3283436712ed /net/dccp/options.c | |
parent | bf0ff9e578ba7dd8331005f00ad7310122011f43 (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.c | 87 |
1 files changed, 59 insertions, 28 deletions
diff --git a/net/dccp/options.c b/net/dccp/options.c index 85a86bd61f4..7ecffdf8575 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) | |||
414 | static inline void dccp_insert_option_timestamp(struct sock *sk, | 429 | static 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 | ||
462 | void dccp_insert_options(struct sock *sk, struct sk_buff *skb) | 492 | void 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); |
669 | out: | 700 | out: |
670 | dccp_pr_debug(""); | 701 | dccp_pr_debug(""); |
671 | dccp_ackpkts_print(ap); | 702 | dccp_ackpkts_print(ap); |