diff options
author | David S. Miller <davem@davemloft.net> | 2010-09-21 19:00:40 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-09-21 19:00:40 -0400 |
commit | 98e684bd5c927cb94ff23fb6f1dd34dd346a19cf (patch) | |
tree | 4274d2b1d7c5314e1bb4d33197211aa8faa08687 | |
parent | e254c274ae19888e5693ba6d32576ab03a8ae8a4 (diff) | |
parent | 536bb20b45dee3f9b77b0d250f8ed0733a5cb025 (diff) |
Merge branch 'dccp' of git://eden-feed.erg.abdn.ac.uk/net-next-2.6
-rw-r--r-- | include/linux/dccp.h | 6 | ||||
-rw-r--r-- | net/dccp/ccid.h | 46 | ||||
-rw-r--r-- | net/dccp/ccids/ccid3.c | 78 | ||||
-rw-r--r-- | net/dccp/ccids/ccid3.h | 9 | ||||
-rw-r--r-- | net/dccp/ccids/lib/tfrc.h | 1 | ||||
-rw-r--r-- | net/dccp/ccids/lib/tfrc_equation.c | 14 | ||||
-rw-r--r-- | net/dccp/options.c | 25 |
7 files changed, 73 insertions, 106 deletions
diff --git a/include/linux/dccp.h b/include/linux/dccp.h index 7434a8353e23..7187bd8a75f6 100644 --- a/include/linux/dccp.h +++ b/include/linux/dccp.h | |||
@@ -165,8 +165,10 @@ enum { | |||
165 | DCCPO_TIMESTAMP_ECHO = 42, | 165 | DCCPO_TIMESTAMP_ECHO = 42, |
166 | DCCPO_ELAPSED_TIME = 43, | 166 | DCCPO_ELAPSED_TIME = 43, |
167 | DCCPO_MAX = 45, | 167 | DCCPO_MAX = 45, |
168 | DCCPO_MIN_CCID_SPECIFIC = 128, | 168 | DCCPO_MIN_RX_CCID_SPECIFIC = 128, /* from sender to receiver */ |
169 | DCCPO_MAX_CCID_SPECIFIC = 255, | 169 | DCCPO_MAX_RX_CCID_SPECIFIC = 191, |
170 | DCCPO_MIN_TX_CCID_SPECIFIC = 192, /* from receiver to sender */ | ||
171 | DCCPO_MAX_TX_CCID_SPECIFIC = 255, | ||
170 | }; | 172 | }; |
171 | /* maximum size of a single TLV-encoded DCCP option (sans type/len bytes) */ | 173 | /* maximum size of a single TLV-encoded DCCP option (sans type/len bytes) */ |
172 | #define DCCP_SINGLE_OPT_MAXLEN 253 | 174 | #define DCCP_SINGLE_OPT_MAXLEN 253 |
diff --git a/net/dccp/ccid.h b/net/dccp/ccid.h index 6df6f8ac9636..6d16a9070ff0 100644 --- a/net/dccp/ccid.h +++ b/net/dccp/ccid.h | |||
@@ -62,18 +62,14 @@ struct ccid_operations { | |||
62 | void (*ccid_hc_tx_exit)(struct sock *sk); | 62 | void (*ccid_hc_tx_exit)(struct sock *sk); |
63 | void (*ccid_hc_rx_packet_recv)(struct sock *sk, | 63 | void (*ccid_hc_rx_packet_recv)(struct sock *sk, |
64 | struct sk_buff *skb); | 64 | struct sk_buff *skb); |
65 | int (*ccid_hc_rx_parse_options)(struct sock *sk, | 65 | int (*ccid_hc_rx_parse_options)(struct sock *sk, u8 pkt, |
66 | unsigned char option, | 66 | u8 opt, u8 *val, u8 len); |
67 | unsigned char len, u16 idx, | ||
68 | unsigned char* value); | ||
69 | int (*ccid_hc_rx_insert_options)(struct sock *sk, | 67 | int (*ccid_hc_rx_insert_options)(struct sock *sk, |
70 | struct sk_buff *skb); | 68 | struct sk_buff *skb); |
71 | void (*ccid_hc_tx_packet_recv)(struct sock *sk, | 69 | void (*ccid_hc_tx_packet_recv)(struct sock *sk, |
72 | struct sk_buff *skb); | 70 | struct sk_buff *skb); |
73 | int (*ccid_hc_tx_parse_options)(struct sock *sk, | 71 | int (*ccid_hc_tx_parse_options)(struct sock *sk, u8 pkt, |
74 | unsigned char option, | 72 | u8 opt, u8 *val, u8 len); |
75 | unsigned char len, u16 idx, | ||
76 | unsigned char* value); | ||
77 | int (*ccid_hc_tx_send_packet)(struct sock *sk, | 73 | int (*ccid_hc_tx_send_packet)(struct sock *sk, |
78 | struct sk_buff *skb); | 74 | struct sk_buff *skb); |
79 | void (*ccid_hc_tx_packet_sent)(struct sock *sk, | 75 | void (*ccid_hc_tx_packet_sent)(struct sock *sk, |
@@ -168,27 +164,31 @@ static inline void ccid_hc_tx_packet_recv(struct ccid *ccid, struct sock *sk, | |||
168 | ccid->ccid_ops->ccid_hc_tx_packet_recv(sk, skb); | 164 | ccid->ccid_ops->ccid_hc_tx_packet_recv(sk, skb); |
169 | } | 165 | } |
170 | 166 | ||
167 | /** | ||
168 | * ccid_hc_tx_parse_options - Parse CCID-specific options sent by the receiver | ||
169 | * @pkt: type of packet that @opt appears on (RFC 4340, 5.1) | ||
170 | * @opt: the CCID-specific option type (RFC 4340, 5.8 and 10.3) | ||
171 | * @val: value of @opt | ||
172 | * @len: length of @val in bytes | ||
173 | */ | ||
171 | static inline int ccid_hc_tx_parse_options(struct ccid *ccid, struct sock *sk, | 174 | static inline int ccid_hc_tx_parse_options(struct ccid *ccid, struct sock *sk, |
172 | unsigned char option, | 175 | u8 pkt, u8 opt, u8 *val, u8 len) |
173 | unsigned char len, u16 idx, | ||
174 | unsigned char* value) | ||
175 | { | 176 | { |
176 | int rc = 0; | 177 | if (ccid->ccid_ops->ccid_hc_tx_parse_options == NULL) |
177 | if (ccid->ccid_ops->ccid_hc_tx_parse_options != NULL) | 178 | return 0; |
178 | rc = ccid->ccid_ops->ccid_hc_tx_parse_options(sk, option, len, idx, | 179 | return ccid->ccid_ops->ccid_hc_tx_parse_options(sk, pkt, opt, val, len); |
179 | value); | ||
180 | return rc; | ||
181 | } | 180 | } |
182 | 181 | ||
182 | /** | ||
183 | * ccid_hc_rx_parse_options - Parse CCID-specific options sent by the sender | ||
184 | * Arguments are analogous to ccid_hc_tx_parse_options() | ||
185 | */ | ||
183 | static inline int ccid_hc_rx_parse_options(struct ccid *ccid, struct sock *sk, | 186 | static inline int ccid_hc_rx_parse_options(struct ccid *ccid, struct sock *sk, |
184 | unsigned char option, | 187 | u8 pkt, u8 opt, u8 *val, u8 len) |
185 | unsigned char len, u16 idx, | ||
186 | unsigned char* value) | ||
187 | { | 188 | { |
188 | int rc = 0; | 189 | if (ccid->ccid_ops->ccid_hc_rx_parse_options == NULL) |
189 | if (ccid->ccid_ops->ccid_hc_rx_parse_options != NULL) | 190 | return 0; |
190 | rc = ccid->ccid_ops->ccid_hc_rx_parse_options(sk, option, len, idx, value); | 191 | return ccid->ccid_ops->ccid_hc_rx_parse_options(sk, pkt, opt, val, len); |
191 | return rc; | ||
192 | } | 192 | } |
193 | 193 | ||
194 | static inline int ccid_hc_rx_insert_options(struct ccid *ccid, struct sock *sk, | 194 | static inline int ccid_hc_rx_insert_options(struct ccid *ccid, struct sock *sk, |
diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index ce8059130070..c3f3a25bbd7a 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c | |||
@@ -54,7 +54,6 @@ static const char *ccid3_tx_state_name(enum ccid3_hc_tx_states state) | |||
54 | [TFRC_SSTATE_NO_SENT] = "NO_SENT", | 54 | [TFRC_SSTATE_NO_SENT] = "NO_SENT", |
55 | [TFRC_SSTATE_NO_FBACK] = "NO_FBACK", | 55 | [TFRC_SSTATE_NO_FBACK] = "NO_FBACK", |
56 | [TFRC_SSTATE_FBACK] = "FBACK", | 56 | [TFRC_SSTATE_FBACK] = "FBACK", |
57 | [TFRC_SSTATE_TERM] = "TERM", | ||
58 | }; | 57 | }; |
59 | 58 | ||
60 | return ccid3_state_names[state]; | 59 | return ccid3_state_names[state]; |
@@ -208,10 +207,13 @@ static void ccid3_hc_tx_no_feedback_timer(unsigned long data) | |||
208 | ccid3_pr_debug("%s(%p, state=%s) - entry\n", dccp_role(sk), sk, | 207 | ccid3_pr_debug("%s(%p, state=%s) - entry\n", dccp_role(sk), sk, |
209 | ccid3_tx_state_name(hc->tx_state)); | 208 | ccid3_tx_state_name(hc->tx_state)); |
210 | 209 | ||
210 | /* Ignore and do not restart after leaving the established state */ | ||
211 | if ((1 << sk->sk_state) & ~(DCCPF_OPEN | DCCPF_PARTOPEN)) | ||
212 | goto out; | ||
213 | |||
214 | /* Reset feedback state to "no feedback received" */ | ||
211 | if (hc->tx_state == TFRC_SSTATE_FBACK) | 215 | if (hc->tx_state == TFRC_SSTATE_FBACK) |
212 | ccid3_hc_tx_set_state(sk, TFRC_SSTATE_NO_FBACK); | 216 | ccid3_hc_tx_set_state(sk, TFRC_SSTATE_NO_FBACK); |
213 | else if (hc->tx_state != TFRC_SSTATE_NO_FBACK) | ||
214 | goto out; | ||
215 | 217 | ||
216 | /* | 218 | /* |
217 | * Determine new allowed sending rate X as per draft rfc3448bis-00, 4.4 | 219 | * Determine new allowed sending rate X as per draft rfc3448bis-00, 4.4 |
@@ -287,8 +289,7 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb) | |||
287 | if (unlikely(skb->len == 0)) | 289 | if (unlikely(skb->len == 0)) |
288 | return -EBADMSG; | 290 | return -EBADMSG; |
289 | 291 | ||
290 | switch (hc->tx_state) { | 292 | if (hc->tx_state == TFRC_SSTATE_NO_SENT) { |
291 | case TFRC_SSTATE_NO_SENT: | ||
292 | sk_reset_timer(sk, &hc->tx_no_feedback_timer, (jiffies + | 293 | sk_reset_timer(sk, &hc->tx_no_feedback_timer, (jiffies + |
293 | usecs_to_jiffies(TFRC_INITIAL_TIMEOUT))); | 294 | usecs_to_jiffies(TFRC_INITIAL_TIMEOUT))); |
294 | hc->tx_last_win_count = 0; | 295 | hc->tx_last_win_count = 0; |
@@ -323,9 +324,8 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb) | |||
323 | ccid3_update_send_interval(hc); | 324 | ccid3_update_send_interval(hc); |
324 | 325 | ||
325 | ccid3_hc_tx_set_state(sk, TFRC_SSTATE_NO_FBACK); | 326 | ccid3_hc_tx_set_state(sk, TFRC_SSTATE_NO_FBACK); |
326 | break; | 327 | |
327 | case TFRC_SSTATE_NO_FBACK: | 328 | } else { |
328 | case TFRC_SSTATE_FBACK: | ||
329 | delay = ktime_us_delta(hc->tx_t_nom, now); | 329 | delay = ktime_us_delta(hc->tx_t_nom, now); |
330 | ccid3_pr_debug("delay=%ld\n", (long)delay); | 330 | ccid3_pr_debug("delay=%ld\n", (long)delay); |
331 | /* | 331 | /* |
@@ -340,10 +340,6 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb) | |||
340 | return (u32)delay / USEC_PER_MSEC; | 340 | return (u32)delay / USEC_PER_MSEC; |
341 | 341 | ||
342 | ccid3_hc_tx_update_win_count(hc, now); | 342 | ccid3_hc_tx_update_win_count(hc, now); |
343 | break; | ||
344 | case TFRC_SSTATE_TERM: | ||
345 | DCCP_BUG("%s(%p) - Illegal state TERM", dccp_role(sk), sk); | ||
346 | return -EINVAL; | ||
347 | } | 343 | } |
348 | 344 | ||
349 | /* prepare to send now (add options etc.) */ | 345 | /* prepare to send now (add options etc.) */ |
@@ -369,21 +365,15 @@ static void ccid3_hc_tx_packet_sent(struct sock *sk, int more, | |||
369 | static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) | 365 | static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) |
370 | { | 366 | { |
371 | struct ccid3_hc_tx_sock *hc = ccid3_hc_tx_sk(sk); | 367 | struct ccid3_hc_tx_sock *hc = ccid3_hc_tx_sk(sk); |
372 | struct ccid3_options_received *opt_recv = &hc->tx_options_received; | ||
373 | struct tfrc_tx_hist_entry *acked; | 368 | struct tfrc_tx_hist_entry *acked; |
374 | ktime_t now; | 369 | ktime_t now; |
375 | unsigned long t_nfb; | 370 | unsigned long t_nfb; |
376 | u32 pinv, r_sample; | 371 | u32 r_sample; |
377 | 372 | ||
378 | /* we are only interested in ACKs */ | 373 | /* we are only interested in ACKs */ |
379 | if (!(DCCP_SKB_CB(skb)->dccpd_type == DCCP_PKT_ACK || | 374 | if (!(DCCP_SKB_CB(skb)->dccpd_type == DCCP_PKT_ACK || |
380 | DCCP_SKB_CB(skb)->dccpd_type == DCCP_PKT_DATAACK)) | 375 | DCCP_SKB_CB(skb)->dccpd_type == DCCP_PKT_DATAACK)) |
381 | return; | 376 | return; |
382 | /* ... and only in the established state */ | ||
383 | if (hc->tx_state != TFRC_SSTATE_FBACK && | ||
384 | hc->tx_state != TFRC_SSTATE_NO_FBACK) | ||
385 | return; | ||
386 | |||
387 | /* | 377 | /* |
388 | * Locate the acknowledged packet in the TX history. | 378 | * Locate the acknowledged packet in the TX history. |
389 | * | 379 | * |
@@ -403,17 +393,6 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
403 | r_sample = dccp_sample_rtt(sk, ktime_us_delta(now, acked->stamp)); | 393 | r_sample = dccp_sample_rtt(sk, ktime_us_delta(now, acked->stamp)); |
404 | hc->tx_rtt = tfrc_ewma(hc->tx_rtt, r_sample, 9); | 394 | hc->tx_rtt = tfrc_ewma(hc->tx_rtt, r_sample, 9); |
405 | 395 | ||
406 | /* Update receive rate in units of 64 * bytes/second */ | ||
407 | hc->tx_x_recv = opt_recv->ccid3or_receive_rate; | ||
408 | hc->tx_x_recv <<= 6; | ||
409 | |||
410 | /* Update loss event rate (which is scaled by 1e6) */ | ||
411 | pinv = opt_recv->ccid3or_loss_event_rate; | ||
412 | if (pinv == ~0U || pinv == 0) /* see RFC 4342, 8.5 */ | ||
413 | hc->tx_p = 0; | ||
414 | else /* can not exceed 100% */ | ||
415 | hc->tx_p = scaled_div(1, pinv); | ||
416 | |||
417 | /* | 396 | /* |
418 | * Update allowed sending rate X as per draft rfc3448bis-00, 4.2/3 | 397 | * Update allowed sending rate X as per draft rfc3448bis-00, 4.2/3 |
419 | */ | 398 | */ |
@@ -481,30 +460,36 @@ done_computing_x: | |||
481 | jiffies + usecs_to_jiffies(t_nfb)); | 460 | jiffies + usecs_to_jiffies(t_nfb)); |
482 | } | 461 | } |
483 | 462 | ||
484 | static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option, | 463 | static int ccid3_hc_tx_parse_options(struct sock *sk, u8 packet_type, |
485 | unsigned char len, u16 idx, | 464 | u8 option, u8 *optval, u8 optlen) |
486 | unsigned char *value) | ||
487 | { | 465 | { |
488 | struct ccid3_hc_tx_sock *hc = ccid3_hc_tx_sk(sk); | 466 | struct ccid3_hc_tx_sock *hc = ccid3_hc_tx_sk(sk); |
489 | struct ccid3_options_received *opt_recv = &hc->tx_options_received; | ||
490 | __be32 opt_val; | 467 | __be32 opt_val; |
491 | 468 | ||
492 | switch (option) { | 469 | switch (option) { |
493 | case TFRC_OPT_RECEIVE_RATE: | 470 | case TFRC_OPT_RECEIVE_RATE: |
494 | case TFRC_OPT_LOSS_EVENT_RATE: | 471 | case TFRC_OPT_LOSS_EVENT_RATE: |
495 | if (unlikely(len != 4)) { | 472 | /* Must be ignored on Data packets, cf. RFC 4342 8.3 and 8.5 */ |
473 | if (packet_type == DCCP_PKT_DATA) | ||
474 | break; | ||
475 | if (unlikely(optlen != 4)) { | ||
496 | DCCP_WARN("%s(%p), invalid len %d for %u\n", | 476 | DCCP_WARN("%s(%p), invalid len %d for %u\n", |
497 | dccp_role(sk), sk, len, option); | 477 | dccp_role(sk), sk, optlen, option); |
498 | return -EINVAL; | 478 | return -EINVAL; |
499 | } | 479 | } |
500 | opt_val = ntohl(get_unaligned((__be32 *)value)); | 480 | opt_val = ntohl(get_unaligned((__be32 *)optval)); |
501 | 481 | ||
502 | if (option == TFRC_OPT_RECEIVE_RATE) { | 482 | if (option == TFRC_OPT_RECEIVE_RATE) { |
503 | opt_recv->ccid3or_receive_rate = opt_val; | 483 | /* Receive Rate is kept in units of 64 bytes/second */ |
484 | hc->tx_x_recv = opt_val; | ||
485 | hc->tx_x_recv <<= 6; | ||
486 | |||
504 | ccid3_pr_debug("%s(%p), RECEIVE_RATE=%u\n", | 487 | ccid3_pr_debug("%s(%p), RECEIVE_RATE=%u\n", |
505 | dccp_role(sk), sk, opt_val); | 488 | dccp_role(sk), sk, opt_val); |
506 | } else { | 489 | } else { |
507 | opt_recv->ccid3or_loss_event_rate = opt_val; | 490 | /* Update the fixpoint Loss Event Rate fraction */ |
491 | hc->tx_p = tfrc_invert_loss_event_rate(opt_val); | ||
492 | |||
508 | ccid3_pr_debug("%s(%p), LOSS_EVENT_RATE=%u\n", | 493 | ccid3_pr_debug("%s(%p), LOSS_EVENT_RATE=%u\n", |
509 | dccp_role(sk), sk, opt_val); | 494 | dccp_role(sk), sk, opt_val); |
510 | } | 495 | } |
@@ -527,9 +512,7 @@ static void ccid3_hc_tx_exit(struct sock *sk) | |||
527 | { | 512 | { |
528 | struct ccid3_hc_tx_sock *hc = ccid3_hc_tx_sk(sk); | 513 | struct ccid3_hc_tx_sock *hc = ccid3_hc_tx_sk(sk); |
529 | 514 | ||
530 | ccid3_hc_tx_set_state(sk, TFRC_SSTATE_TERM); | ||
531 | sk_stop_timer(sk, &hc->tx_no_feedback_timer); | 515 | sk_stop_timer(sk, &hc->tx_no_feedback_timer); |
532 | |||
533 | tfrc_tx_hist_purge(&hc->tx_hist); | 516 | tfrc_tx_hist_purge(&hc->tx_hist); |
534 | } | 517 | } |
535 | 518 | ||
@@ -588,7 +571,6 @@ static const char *ccid3_rx_state_name(enum ccid3_hc_rx_states state) | |||
588 | static const char *const ccid3_rx_state_names[] = { | 571 | static const char *const ccid3_rx_state_names[] = { |
589 | [TFRC_RSTATE_NO_DATA] = "NO_DATA", | 572 | [TFRC_RSTATE_NO_DATA] = "NO_DATA", |
590 | [TFRC_RSTATE_DATA] = "DATA", | 573 | [TFRC_RSTATE_DATA] = "DATA", |
591 | [TFRC_RSTATE_TERM] = "TERM", | ||
592 | }; | 574 | }; |
593 | 575 | ||
594 | return ccid3_rx_state_names[state]; | 576 | return ccid3_rx_state_names[state]; |
@@ -614,14 +596,9 @@ static void ccid3_hc_rx_send_feedback(struct sock *sk, | |||
614 | { | 596 | { |
615 | struct ccid3_hc_rx_sock *hc = ccid3_hc_rx_sk(sk); | 597 | struct ccid3_hc_rx_sock *hc = ccid3_hc_rx_sk(sk); |
616 | struct dccp_sock *dp = dccp_sk(sk); | 598 | struct dccp_sock *dp = dccp_sk(sk); |
617 | ktime_t now; | 599 | ktime_t now = ktime_get_real(); |
618 | s64 delta = 0; | 600 | s64 delta = 0; |
619 | 601 | ||
620 | if (unlikely(hc->rx_state == TFRC_RSTATE_TERM)) | ||
621 | return; | ||
622 | |||
623 | now = ktime_get_real(); | ||
624 | |||
625 | switch (fbtype) { | 602 | switch (fbtype) { |
626 | case CCID3_FBACK_INITIAL: | 603 | case CCID3_FBACK_INITIAL: |
627 | hc->rx_x_recv = 0; | 604 | hc->rx_x_recv = 0; |
@@ -825,8 +802,6 @@ static void ccid3_hc_rx_exit(struct sock *sk) | |||
825 | { | 802 | { |
826 | struct ccid3_hc_rx_sock *hc = ccid3_hc_rx_sk(sk); | 803 | struct ccid3_hc_rx_sock *hc = ccid3_hc_rx_sk(sk); |
827 | 804 | ||
828 | ccid3_hc_rx_set_state(sk, TFRC_RSTATE_TERM); | ||
829 | |||
830 | tfrc_rx_hist_purge(&hc->rx_hist); | 805 | tfrc_rx_hist_purge(&hc->rx_hist); |
831 | tfrc_lh_cleanup(&hc->rx_li_hist); | 806 | tfrc_lh_cleanup(&hc->rx_li_hist); |
832 | } | 807 | } |
@@ -851,8 +826,7 @@ static int ccid3_hc_rx_getsockopt(struct sock *sk, const int optname, int len, | |||
851 | return -EINVAL; | 826 | return -EINVAL; |
852 | rx_info.tfrcrx_x_recv = hc->rx_x_recv; | 827 | rx_info.tfrcrx_x_recv = hc->rx_x_recv; |
853 | rx_info.tfrcrx_rtt = hc->rx_rtt; | 828 | rx_info.tfrcrx_rtt = hc->rx_rtt; |
854 | rx_info.tfrcrx_p = hc->rx_pinv == 0 ? ~0U : | 829 | rx_info.tfrcrx_p = tfrc_invert_loss_event_rate(hc->rx_pinv); |
855 | scaled_div(1, hc->rx_pinv); | ||
856 | len = sizeof(rx_info); | 830 | len = sizeof(rx_info); |
857 | val = &rx_info; | 831 | val = &rx_info; |
858 | break; | 832 | break; |
diff --git a/net/dccp/ccids/ccid3.h b/net/dccp/ccids/ccid3.h index 9eb90b863abd..1a9933c29672 100644 --- a/net/dccp/ccids/ccid3.h +++ b/net/dccp/ccids/ccid3.h | |||
@@ -67,17 +67,11 @@ enum ccid3_options { | |||
67 | TFRC_OPT_RECEIVE_RATE = 194, | 67 | TFRC_OPT_RECEIVE_RATE = 194, |
68 | }; | 68 | }; |
69 | 69 | ||
70 | struct ccid3_options_received { | ||
71 | u32 ccid3or_loss_event_rate; | ||
72 | u32 ccid3or_receive_rate; | ||
73 | }; | ||
74 | |||
75 | /* TFRC sender states */ | 70 | /* TFRC sender states */ |
76 | enum ccid3_hc_tx_states { | 71 | enum ccid3_hc_tx_states { |
77 | TFRC_SSTATE_NO_SENT = 1, | 72 | TFRC_SSTATE_NO_SENT = 1, |
78 | TFRC_SSTATE_NO_FBACK, | 73 | TFRC_SSTATE_NO_FBACK, |
79 | TFRC_SSTATE_FBACK, | 74 | TFRC_SSTATE_FBACK, |
80 | TFRC_SSTATE_TERM, | ||
81 | }; | 75 | }; |
82 | 76 | ||
83 | /** | 77 | /** |
@@ -98,7 +92,6 @@ enum ccid3_hc_tx_states { | |||
98 | * @tx_t_ld: Time last doubled during slow start | 92 | * @tx_t_ld: Time last doubled during slow start |
99 | * @tx_t_nom: Nominal send time of next packet | 93 | * @tx_t_nom: Nominal send time of next packet |
100 | * @tx_hist: Packet history | 94 | * @tx_hist: Packet history |
101 | * @tx_options_received: Parsed set of retrieved options | ||
102 | */ | 95 | */ |
103 | struct ccid3_hc_tx_sock { | 96 | struct ccid3_hc_tx_sock { |
104 | u64 tx_x; | 97 | u64 tx_x; |
@@ -116,7 +109,6 @@ struct ccid3_hc_tx_sock { | |||
116 | ktime_t tx_t_ld; | 109 | ktime_t tx_t_ld; |
117 | ktime_t tx_t_nom; | 110 | ktime_t tx_t_nom; |
118 | struct tfrc_tx_hist_entry *tx_hist; | 111 | struct tfrc_tx_hist_entry *tx_hist; |
119 | struct ccid3_options_received tx_options_received; | ||
120 | }; | 112 | }; |
121 | 113 | ||
122 | static inline struct ccid3_hc_tx_sock *ccid3_hc_tx_sk(const struct sock *sk) | 114 | static inline struct ccid3_hc_tx_sock *ccid3_hc_tx_sk(const struct sock *sk) |
@@ -130,7 +122,6 @@ static inline struct ccid3_hc_tx_sock *ccid3_hc_tx_sk(const struct sock *sk) | |||
130 | enum ccid3_hc_rx_states { | 122 | enum ccid3_hc_rx_states { |
131 | TFRC_RSTATE_NO_DATA = 1, | 123 | TFRC_RSTATE_NO_DATA = 1, |
132 | TFRC_RSTATE_DATA, | 124 | TFRC_RSTATE_DATA, |
133 | TFRC_RSTATE_TERM = 127, | ||
134 | }; | 125 | }; |
135 | 126 | ||
136 | /** | 127 | /** |
diff --git a/net/dccp/ccids/lib/tfrc.h b/net/dccp/ccids/lib/tfrc.h index 01bb48e96c2e..f8ee3f549770 100644 --- a/net/dccp/ccids/lib/tfrc.h +++ b/net/dccp/ccids/lib/tfrc.h | |||
@@ -57,6 +57,7 @@ static inline u32 tfrc_ewma(const u32 avg, const u32 newval, const u8 weight) | |||
57 | 57 | ||
58 | extern u32 tfrc_calc_x(u16 s, u32 R, u32 p); | 58 | extern u32 tfrc_calc_x(u16 s, u32 R, u32 p); |
59 | extern u32 tfrc_calc_x_reverse_lookup(u32 fvalue); | 59 | extern u32 tfrc_calc_x_reverse_lookup(u32 fvalue); |
60 | extern u32 tfrc_invert_loss_event_rate(u32 loss_event_rate); | ||
60 | 61 | ||
61 | extern int tfrc_tx_packet_history_init(void); | 62 | extern int tfrc_tx_packet_history_init(void); |
62 | extern void tfrc_tx_packet_history_exit(void); | 63 | extern void tfrc_tx_packet_history_exit(void); |
diff --git a/net/dccp/ccids/lib/tfrc_equation.c b/net/dccp/ccids/lib/tfrc_equation.c index 22ca1cf0eb55..a052a4377e26 100644 --- a/net/dccp/ccids/lib/tfrc_equation.c +++ b/net/dccp/ccids/lib/tfrc_equation.c | |||
@@ -687,3 +687,17 @@ u32 tfrc_calc_x_reverse_lookup(u32 fvalue) | |||
687 | index = tfrc_binsearch(fvalue, 0); | 687 | index = tfrc_binsearch(fvalue, 0); |
688 | return (index + 1) * 1000000 / TFRC_CALC_X_ARRSIZE; | 688 | return (index + 1) * 1000000 / TFRC_CALC_X_ARRSIZE; |
689 | } | 689 | } |
690 | |||
691 | /** | ||
692 | * tfrc_invert_loss_event_rate - Compute p so that 10^6 corresponds to 100% | ||
693 | * When @loss_event_rate is large, there is a chance that p is truncated to 0. | ||
694 | * To avoid re-entering slow-start in that case, we set p = TFRC_SMALLEST_P > 0. | ||
695 | */ | ||
696 | u32 tfrc_invert_loss_event_rate(u32 loss_event_rate) | ||
697 | { | ||
698 | if (loss_event_rate == UINT_MAX) /* see RFC 4342, 8.5 */ | ||
699 | return 0; | ||
700 | if (unlikely(loss_event_rate == 0)) /* map 1/0 into 100% */ | ||
701 | return 1000000; | ||
702 | return max_t(u32, scaled_div(1, loss_event_rate), TFRC_SMALLEST_P); | ||
703 | } | ||
diff --git a/net/dccp/options.c b/net/dccp/options.c index bfda087bd90d..92718511eac5 100644 --- a/net/dccp/options.c +++ b/net/dccp/options.c | |||
@@ -96,18 +96,11 @@ int dccp_parse_options(struct sock *sk, struct dccp_request_sock *dreq, | |||
96 | } | 96 | } |
97 | 97 | ||
98 | /* | 98 | /* |
99 | * CCID-Specific Options (from RFC 4340, sec. 10.3): | ||
100 | * | ||
101 | * Option numbers 128 through 191 are for options sent from the | ||
102 | * HC-Sender to the HC-Receiver; option numbers 192 through 255 | ||
103 | * are for options sent from the HC-Receiver to the HC-Sender. | ||
104 | * | ||
105 | * CCID-specific options are ignored during connection setup, as | 99 | * CCID-specific options are ignored during connection setup, as |
106 | * negotiation may still be in progress (see RFC 4340, 10.3). | 100 | * negotiation may still be in progress (see RFC 4340, 10.3). |
107 | * The same applies to Ack Vectors, as these depend on the CCID. | 101 | * The same applies to Ack Vectors, as these depend on the CCID. |
108 | * | ||
109 | */ | 102 | */ |
110 | if (dreq != NULL && (opt >= 128 || | 103 | if (dreq != NULL && (opt >= DCCPO_MIN_RX_CCID_SPECIFIC || |
111 | opt == DCCPO_ACK_VECTOR_0 || opt == DCCPO_ACK_VECTOR_1)) | 104 | opt == DCCPO_ACK_VECTOR_0 || opt == DCCPO_ACK_VECTOR_1)) |
112 | goto ignore_option; | 105 | goto ignore_option; |
113 | 106 | ||
@@ -226,23 +219,15 @@ int dccp_parse_options(struct sock *sk, struct dccp_request_sock *dreq, | |||
226 | dccp_pr_debug("%s rx opt: ELAPSED_TIME=%d\n", | 219 | dccp_pr_debug("%s rx opt: ELAPSED_TIME=%d\n", |
227 | dccp_role(sk), elapsed_time); | 220 | dccp_role(sk), elapsed_time); |
228 | break; | 221 | break; |
229 | case 128 ... 191: { | 222 | case DCCPO_MIN_RX_CCID_SPECIFIC ... DCCPO_MAX_RX_CCID_SPECIFIC: |
230 | const u16 idx = value - options; | ||
231 | |||
232 | if (ccid_hc_rx_parse_options(dp->dccps_hc_rx_ccid, sk, | 223 | if (ccid_hc_rx_parse_options(dp->dccps_hc_rx_ccid, sk, |
233 | opt, len, idx, | 224 | pkt_type, opt, value, len)) |
234 | value) != 0) | ||
235 | goto out_invalid_option; | 225 | goto out_invalid_option; |
236 | } | ||
237 | break; | 226 | break; |
238 | case 192 ... 255: { | 227 | case DCCPO_MIN_TX_CCID_SPECIFIC ... DCCPO_MAX_TX_CCID_SPECIFIC: |
239 | const u16 idx = value - options; | ||
240 | |||
241 | if (ccid_hc_tx_parse_options(dp->dccps_hc_tx_ccid, sk, | 228 | if (ccid_hc_tx_parse_options(dp->dccps_hc_tx_ccid, sk, |
242 | opt, len, idx, | 229 | pkt_type, opt, value, len)) |
243 | value) != 0) | ||
244 | goto out_invalid_option; | 230 | goto out_invalid_option; |
245 | } | ||
246 | break; | 231 | break; |
247 | default: | 232 | default: |
248 | DCCP_CRIT("DCCP(%p): option %d(len=%d) not " | 233 | DCCP_CRIT("DCCP(%p): option %d(len=%d) not " |