diff options
| -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 " |
