aboutsummaryrefslogtreecommitdiffstats
path: root/net/dccp/options.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/dccp/options.c')
-rw-r--r--net/dccp/options.c90
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
435void 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
449EXPORT_SYMBOL_GPL(dccp_timestamp);
450
429void dccp_insert_option_timestamp(struct sock *sk, struct sk_buff *skb) 451void 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 */
619int dccp_ackpkts_add(struct dccp_ackpkts *ap, u64 ackno, u8 state) 650int 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);
701out: 733out:
702 dccp_pr_debug(""); 734 dccp_pr_debug("");
703 dccp_ackpkts_print(ap); 735 dccp_ackpkts_print(ap);