diff options
Diffstat (limited to 'net/dccp/options.c')
-rw-r--r-- | net/dccp/options.c | 90 |
1 files changed, 61 insertions, 29 deletions
diff --git a/net/dccp/options.c b/net/dccp/options.c index 382c5894acb2..d4c4242d8dd7 100644 --- a/net/dccp/options.c +++ b/net/dccp/options.c | |||
@@ -72,6 +72,7 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb) | |||
72 | struct dccp_options_received *opt_recv = &dp->dccps_options_received; | 72 | struct dccp_options_received *opt_recv = &dp->dccps_options_received; |
73 | unsigned char opt, len; | 73 | unsigned char opt, len; |
74 | unsigned char *value; | 74 | unsigned char *value; |
75 | u32 elapsed_time; | ||
75 | 76 | ||
76 | memset(opt_recv, 0, sizeof(*opt_recv)); | 77 | memset(opt_recv, 0, sizeof(*opt_recv)); |
77 | 78 | ||
@@ -139,7 +140,7 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb) | |||
139 | opt_recv->dccpor_timestamp = ntohl(*(u32 *)value); | 140 | opt_recv->dccpor_timestamp = ntohl(*(u32 *)value); |
140 | 141 | ||
141 | dp->dccps_timestamp_echo = opt_recv->dccpor_timestamp; | 142 | dp->dccps_timestamp_echo = opt_recv->dccpor_timestamp; |
142 | do_gettimeofday(&dp->dccps_timestamp_time); | 143 | dccp_timestamp(sk, &dp->dccps_timestamp_time); |
143 | 144 | ||
144 | dccp_pr_debug("%sTIMESTAMP=%u, ackno=%llu\n", | 145 | dccp_pr_debug("%sTIMESTAMP=%u, ackno=%llu\n", |
145 | debug_prefix, opt_recv->dccpor_timestamp, | 146 | debug_prefix, opt_recv->dccpor_timestamp, |
@@ -159,18 +160,18 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb) | |||
159 | (unsigned long long) | 160 | (unsigned long long) |
160 | DCCP_SKB_CB(skb)->dccpd_ack_seq); | 161 | DCCP_SKB_CB(skb)->dccpd_ack_seq); |
161 | 162 | ||
162 | if (len > 4) { | ||
163 | if (len == 6) | ||
164 | opt_recv->dccpor_elapsed_time = | ||
165 | ntohs(*(u16 *)(value + 4)); | ||
166 | else | ||
167 | opt_recv->dccpor_elapsed_time = | ||
168 | ntohl(*(u32 *)(value + 4)); | ||
169 | 163 | ||
170 | dccp_pr_debug("%sTIMESTAMP_ECHO ELAPSED_TIME=%d\n", | 164 | if (len == 4) |
171 | debug_prefix, | 165 | break; |
172 | opt_recv->dccpor_elapsed_time); | 166 | |
173 | } | 167 | if (len == 6) |
168 | elapsed_time = ntohs(*(u16 *)(value + 4)); | ||
169 | else | ||
170 | elapsed_time = ntohl(*(u32 *)(value + 4)); | ||
171 | |||
172 | /* Give precedence to the biggest ELAPSED_TIME */ | ||
173 | if (elapsed_time > opt_recv->dccpor_elapsed_time) | ||
174 | opt_recv->dccpor_elapsed_time = elapsed_time; | ||
174 | break; | 175 | break; |
175 | case DCCPO_ELAPSED_TIME: | 176 | case DCCPO_ELAPSED_TIME: |
176 | if (len != 2 && len != 4) | 177 | if (len != 2 && len != 4) |
@@ -180,14 +181,15 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb) | |||
180 | continue; | 181 | continue; |
181 | 182 | ||
182 | if (len == 2) | 183 | if (len == 2) |
183 | opt_recv->dccpor_elapsed_time = | 184 | elapsed_time = ntohs(*(u16 *)value); |
184 | ntohs(*(u16 *)value); | ||
185 | else | 185 | else |
186 | opt_recv->dccpor_elapsed_time = | 186 | elapsed_time = ntohl(*(u32 *)value); |
187 | ntohl(*(u32 *)value); | 187 | |
188 | if (elapsed_time > opt_recv->dccpor_elapsed_time) | ||
189 | opt_recv->dccpor_elapsed_time = elapsed_time; | ||
188 | 190 | ||
189 | dccp_pr_debug("%sELAPSED_TIME=%d\n", debug_prefix, | 191 | dccp_pr_debug("%sELAPSED_TIME=%d\n", debug_prefix, |
190 | opt_recv->dccpor_elapsed_time); | 192 | elapsed_time); |
191 | break; | 193 | break; |
192 | /* | 194 | /* |
193 | * From draft-ietf-dccp-spec-11.txt: | 195 | * From draft-ietf-dccp-spec-11.txt: |
@@ -359,9 +361,13 @@ static void dccp_insert_option_ack_vector(struct sock *sk, struct sk_buff *skb) | |||
359 | #endif | 361 | #endif |
360 | struct dccp_ackpkts *ap = dp->dccps_hc_rx_ackpkts; | 362 | struct dccp_ackpkts *ap = dp->dccps_hc_rx_ackpkts; |
361 | int len = ap->dccpap_buf_vector_len + 2; | 363 | int len = ap->dccpap_buf_vector_len + 2; |
362 | const u32 elapsed_time = timeval_now_delta(&ap->dccpap_time) / 10; | 364 | struct timeval now; |
365 | u32 elapsed_time; | ||
363 | unsigned char *to, *from; | 366 | unsigned char *to, *from; |
364 | 367 | ||
368 | dccp_timestamp(sk, &now); | ||
369 | elapsed_time = timeval_delta(&now, &ap->dccpap_time) / 10; | ||
370 | |||
365 | if (elapsed_time != 0) | 371 | if (elapsed_time != 0) |
366 | dccp_insert_option_elapsed_time(sk, skb, elapsed_time); | 372 | dccp_insert_option_elapsed_time(sk, skb, elapsed_time); |
367 | 373 | ||
@@ -426,13 +432,29 @@ static void dccp_insert_option_ack_vector(struct sock *sk, struct sk_buff *skb) | |||
426 | (unsigned long long) ap->dccpap_ack_ackno); | 432 | (unsigned long long) ap->dccpap_ack_ackno); |
427 | } | 433 | } |
428 | 434 | ||
435 | void dccp_timestamp(const struct sock *sk, struct timeval *tv) | ||
436 | { | ||
437 | const struct dccp_sock *dp = dccp_sk(sk); | ||
438 | |||
439 | do_gettimeofday(tv); | ||
440 | tv->tv_sec -= dp->dccps_epoch.tv_sec; | ||
441 | tv->tv_usec -= dp->dccps_epoch.tv_usec; | ||
442 | |||
443 | while (tv->tv_usec < 0) { | ||
444 | tv->tv_sec--; | ||
445 | tv->tv_usec += USEC_PER_SEC; | ||
446 | } | ||
447 | } | ||
448 | |||
449 | EXPORT_SYMBOL_GPL(dccp_timestamp); | ||
450 | |||
429 | void dccp_insert_option_timestamp(struct sock *sk, struct sk_buff *skb) | 451 | void dccp_insert_option_timestamp(struct sock *sk, struct sk_buff *skb) |
430 | { | 452 | { |
431 | struct timeval tv; | 453 | struct timeval tv; |
432 | u32 now; | 454 | u32 now; |
433 | 455 | ||
434 | do_gettimeofday(&tv); | 456 | dccp_timestamp(sk, &tv); |
435 | now = (tv.tv_sec * USEC_PER_SEC + tv.tv_usec) / 10; | 457 | now = timeval_usecs(&tv) / 10; |
436 | /* yes this will overflow but that is the point as we want a | 458 | /* yes this will overflow but that is the point as we want a |
437 | * 10 usec 32 bit timer which mean it wraps every 11.9 hours */ | 459 | * 10 usec 32 bit timer which mean it wraps every 11.9 hours */ |
438 | 460 | ||
@@ -450,13 +472,17 @@ static void dccp_insert_option_timestamp_echo(struct sock *sk, | |||
450 | const char *debug_prefix = dp->dccps_role == DCCP_ROLE_CLIENT ? | 472 | const char *debug_prefix = dp->dccps_role == DCCP_ROLE_CLIENT ? |
451 | "CLIENT TX opt: " : "server TX opt: "; | 473 | "CLIENT TX opt: " : "server TX opt: "; |
452 | #endif | 474 | #endif |
475 | struct timeval now; | ||
453 | u32 tstamp_echo; | 476 | u32 tstamp_echo; |
454 | const u32 elapsed_time = | 477 | u32 elapsed_time; |
455 | timeval_now_delta(&dp->dccps_timestamp_time) / 10; | 478 | int len, elapsed_time_len; |
456 | const int elapsed_time_len = dccp_elapsed_time_len(elapsed_time); | ||
457 | const int len = 6 + elapsed_time_len; | ||
458 | unsigned char *to; | 479 | unsigned char *to; |
459 | 480 | ||
481 | dccp_timestamp(sk, &now); | ||
482 | elapsed_time = timeval_delta(&now, &dp->dccps_timestamp_time) / 10; | ||
483 | elapsed_time_len = dccp_elapsed_time_len(elapsed_time); | ||
484 | len = 6 + elapsed_time_len; | ||
485 | |||
460 | if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN) { | 486 | if (DCCP_SKB_CB(skb)->dccpd_opt_len + len > DCCP_MAX_OPT_LEN) { |
461 | LIMIT_NETDEBUG(KERN_INFO "DCCP: packet too small to insert " | 487 | LIMIT_NETDEBUG(KERN_INFO "DCCP: packet too small to insert " |
462 | "timestamp echo!\n"); | 488 | "timestamp echo!\n"); |
@@ -505,13 +531,18 @@ void dccp_insert_options(struct sock *sk, struct sk_buff *skb) | |||
505 | (dp->dccps_hc_rx_ackpkts->dccpap_buf_ackno != | 531 | (dp->dccps_hc_rx_ackpkts->dccpap_buf_ackno != |
506 | DCCP_MAX_SEQNO + 1)) | 532 | DCCP_MAX_SEQNO + 1)) |
507 | dccp_insert_option_ack_vector(sk, skb); | 533 | dccp_insert_option_ack_vector(sk, skb); |
508 | |||
509 | if (dp->dccps_timestamp_echo != 0) | 534 | if (dp->dccps_timestamp_echo != 0) |
510 | dccp_insert_option_timestamp_echo(sk, skb); | 535 | dccp_insert_option_timestamp_echo(sk, skb); |
511 | } | 536 | } |
512 | 537 | ||
513 | ccid_hc_rx_insert_options(dp->dccps_hc_rx_ccid, sk, skb); | 538 | if (dp->dccps_hc_rx_insert_options) { |
514 | ccid_hc_tx_insert_options(dp->dccps_hc_tx_ccid, sk, skb); | 539 | ccid_hc_rx_insert_options(dp->dccps_hc_rx_ccid, sk, skb); |
540 | dp->dccps_hc_rx_insert_options = 0; | ||
541 | } | ||
542 | if (dp->dccps_hc_tx_insert_options) { | ||
543 | ccid_hc_tx_insert_options(dp->dccps_hc_tx_ccid, sk, skb); | ||
544 | dp->dccps_hc_tx_insert_options = 0; | ||
545 | } | ||
515 | 546 | ||
516 | /* XXX: insert other options when appropriate */ | 547 | /* XXX: insert other options when appropriate */ |
517 | 548 | ||
@@ -616,7 +647,8 @@ static inline int dccp_ackpkts_set_buf_head_state(struct dccp_ackpkts *ap, | |||
616 | /* | 647 | /* |
617 | * Implements the draft-ietf-dccp-spec-11.txt Appendix A | 648 | * Implements the draft-ietf-dccp-spec-11.txt Appendix A |
618 | */ | 649 | */ |
619 | int dccp_ackpkts_add(struct dccp_ackpkts *ap, u64 ackno, u8 state) | 650 | int dccp_ackpkts_add(struct dccp_ackpkts *ap, const struct sock *sk, |
651 | u64 ackno, u8 state) | ||
620 | { | 652 | { |
621 | /* | 653 | /* |
622 | * Check at the right places if the buffer is full, if it is, tell the | 654 | * Check at the right places if the buffer is full, if it is, tell the |
@@ -697,7 +729,7 @@ int dccp_ackpkts_add(struct dccp_ackpkts *ap, u64 ackno, u8 state) | |||
697 | } | 729 | } |
698 | 730 | ||
699 | ap->dccpap_buf_ackno = ackno; | 731 | ap->dccpap_buf_ackno = ackno; |
700 | do_gettimeofday(&ap->dccpap_time); | 732 | dccp_timestamp(sk, &ap->dccpap_time); |
701 | out: | 733 | out: |
702 | dccp_pr_debug(""); | 734 | dccp_pr_debug(""); |
703 | dccp_ackpkts_print(ap); | 735 | dccp_ackpkts_print(ap); |