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); |
