Before when implementing sctp prsctp, SCTP_PR_STREAM_STATUS wasn't added, as it needs to save abandoned_(un)sent for every stream. After sctp stream reconf is added in sctp, assoc has structure sctp_stream_out to save per stream info. This patch is to add SCTP_PR_STREAM_STATUS by putting the prsctp per stream statistics into sctp_stream_out. v1->v2: fix an indent issue.
Unified · Split
| @@ -1315,6 +1315,8 @@ struct sctp_inithdr_host { · 1314 unmodified lines | |||
| 1315 | struct sctp_stream_out { | 1315 | struct sctp_stream_out { |
| 1316 | __u16 ssn; | 1316 | __u16 ssn; |
| 1317 | __u8 state; | 1317 | __u8 state; |
| 1318 | __u64 abandoned_unsent[SCTP_PR_INDEX(MAX) + 1]; | ||
| 1319 | __u64 abandoned_sent[SCTP_PR_INDEX(MAX) + 1]; | ||
| 1318 | }; | 1320 | }; |
| 1319 | 1321 | ||
| 1320 | struct sctp_stream_in { | 1322 | struct sctp_stream_in { |
| @@ -115,6 +115,7 @@ typedef __s32 sctp_assoc_t; · 114 unmodified lines | |||
| 115 | #define SCTP_PR_SUPPORTED 113 | 115 | #define SCTP_PR_SUPPORTED 113 |
| 116 | #define SCTP_DEFAULT_PRINFO 114 | 116 | #define SCTP_DEFAULT_PRINFO 114 |
| 117 | #define SCTP_PR_ASSOC_STATUS 115 | 117 | #define SCTP_PR_ASSOC_STATUS 115 |
| 118 | #define SCTP_PR_STREAM_STATUS 116 | ||
| 118 | #define SCTP_RECONFIG_SUPPORTED 117 | 119 | #define SCTP_RECONFIG_SUPPORTED 117 |
| 119 | #define SCTP_ENABLE_STREAM_RESET 118 | 120 | #define SCTP_ENABLE_STREAM_RESET 118 |
| 120 | #define SCTP_RESET_STREAMS 119 | 121 | #define SCTP_RESET_STREAMS 119 |
| @@ -306,14 +306,24 @@ int sctp_chunk_abandoned(struct sctp_chunk *chunk) · 305 unmodified lines | |||
| 306 | 306 | ||
| 307 | if (SCTP_PR_TTL_ENABLED(chunk->sinfo.sinfo_flags) && | 307 | if (SCTP_PR_TTL_ENABLED(chunk->sinfo.sinfo_flags) && |
| 308 | time_after(jiffies, chunk->msg->expires_at)) { | 308 | time_after(jiffies, chunk->msg->expires_at)) { |
| 309 | if (chunk->sent_count) | 309 | struct sctp_stream_out *streamout = |
| 310 | &chunk->asoc->stream->out[chunk->sinfo.sinfo_stream]; | ||
| 311 | |||
| 312 | if (chunk->sent_count) { | ||
| 310 | chunk->asoc->abandoned_sent[SCTP_PR_INDEX(TTL)]++; | 313 | chunk->asoc->abandoned_sent[SCTP_PR_INDEX(TTL)]++; |
| 311 | else | 314 | streamout->abandoned_sent[SCTP_PR_INDEX(TTL)]++; |
| 315 | } else { | ||
| 312 | chunk->asoc->abandoned_unsent[SCTP_PR_INDEX(TTL)]++; | 316 | chunk->asoc->abandoned_unsent[SCTP_PR_INDEX(TTL)]++; |
| 317 | streamout->abandoned_unsent[SCTP_PR_INDEX(TTL)]++; | ||
| 318 | } | ||
| 313 | return 1; | 319 | return 1; |
| 314 | } else if (SCTP_PR_RTX_ENABLED(chunk->sinfo.sinfo_flags) && | 320 | } else if (SCTP_PR_RTX_ENABLED(chunk->sinfo.sinfo_flags) && |
| 315 | chunk->sent_count > chunk->sinfo.sinfo_timetolive) { | 321 | chunk->sent_count > chunk->sinfo.sinfo_timetolive) { |
| 322 | struct sctp_stream_out *streamout = | ||
| 323 | &chunk->asoc->stream->out[chunk->sinfo.sinfo_stream]; | ||
| 324 | |||
| 316 | chunk->asoc->abandoned_sent[SCTP_PR_INDEX(RTX)]++; | 325 | chunk->asoc->abandoned_sent[SCTP_PR_INDEX(RTX)]++; |
| 326 | streamout->abandoned_sent[SCTP_PR_INDEX(RTX)]++; | ||
| 317 | return 1; | 327 | return 1; |
| 318 | } else if (!SCTP_PR_POLICY(chunk->sinfo.sinfo_flags) && | 328 | } else if (!SCTP_PR_POLICY(chunk->sinfo.sinfo_flags) && |
| 319 | chunk->msg->expires_at && | 329 | chunk->msg->expires_at && |
| @@ -353,6 +353,8 @@ static int sctp_prsctp_prune_sent(struct sctp_association *asoc, · 352 unmodified lines | |||
| 353 | struct sctp_chunk *chk, *temp; | 353 | struct sctp_chunk *chk, *temp; |
| 354 | 354 | ||
| 355 | list_for_each_entry_safe(chk, temp, queue, transmitted_list) { | 355 | list_for_each_entry_safe(chk, temp, queue, transmitted_list) { |
| 356 | struct sctp_stream_out *streamout; | ||
| 357 | |||
| 356 | if (!SCTP_PR_PRIO_ENABLED(chk->sinfo.sinfo_flags) || | 358 | if (!SCTP_PR_PRIO_ENABLED(chk->sinfo.sinfo_flags) || |
| 357 | chk->sinfo.sinfo_timetolive <= sinfo->sinfo_timetolive) | 359 | chk->sinfo.sinfo_timetolive <= sinfo->sinfo_timetolive) |
| 358 | continue; | 360 | continue; |
| @@ -361,8 +363,10 @@ static int sctp_prsctp_prune_sent(struct sctp_association *asoc, · 2 unmodified lines | |||
| 361 | sctp_insert_list(&asoc->outqueue.abandoned, | 363 | sctp_insert_list(&asoc->outqueue.abandoned, |
| 362 | &chk->transmitted_list); | 364 | &chk->transmitted_list); |
| 363 | 365 | ||
| 366 | streamout = &asoc->stream->out[chk->sinfo.sinfo_stream]; | ||
| 364 | asoc->sent_cnt_removable--; | 367 | asoc->sent_cnt_removable--; |
| 365 | asoc->abandoned_sent[SCTP_PR_INDEX(PRIO)]++; | 368 | asoc->abandoned_sent[SCTP_PR_INDEX(PRIO)]++; |
| 369 | streamout->abandoned_sent[SCTP_PR_INDEX(PRIO)]++; | ||
| 366 | 370 | ||
| 367 | if (!chk->tsn_gap_acked) { | 371 | if (!chk->tsn_gap_acked) { |
| 368 | if (chk->transport) | 372 | if (chk->transport) |
| @@ -396,6 +400,12 @@ static int sctp_prsctp_prune_unsent(struct sctp_association *asoc, · 27 unmodified lines | |||
| 396 | q->out_qlen -= chk->skb->len; | 400 | q->out_qlen -= chk->skb->len; |
| 397 | asoc->sent_cnt_removable--; | 401 | asoc->sent_cnt_removable--; |
| 398 | asoc->abandoned_unsent[SCTP_PR_INDEX(PRIO)]++; | 402 | asoc->abandoned_unsent[SCTP_PR_INDEX(PRIO)]++; |
| 403 | if (chk->sinfo.sinfo_stream < asoc->stream->outcnt) { | ||
| 404 | struct sctp_stream_out *streamout = | ||
| 405 | &asoc->stream->out[chk->sinfo.sinfo_stream]; | ||
| 406 | |||
| 407 | streamout->abandoned_unsent[SCTP_PR_INDEX(PRIO)]++; | ||
| 408 | } | ||
| 399 | 409 | ||
| 400 | msg_len -= SCTP_DATA_SNDSIZE(chk) + | 410 | msg_len -= SCTP_DATA_SNDSIZE(chk) + |
| 401 | sizeof(struct sk_buff) + | 411 | sizeof(struct sk_buff) + |
| @@ -6576,6 +6576,61 @@ out: · 6575 unmodified lines | |||
| 6576 | return retval; | 6576 | return retval; |
| 6577 | } | 6577 | } |
| 6578 | 6578 | ||
| 6579 | static int sctp_getsockopt_pr_streamstatus(struct sock *sk, int len, | ||
| 6580 | char __user *optval, | ||
| 6581 | int __user *optlen) | ||
| 6582 | { | ||
| 6583 | struct sctp_stream_out *streamout; | ||
| 6584 | struct sctp_association *asoc; | ||
| 6585 | struct sctp_prstatus params; | ||
| 6586 | int retval = -EINVAL; | ||
| 6587 | int policy; | ||
| 6588 | |||
| 6589 | if (len < sizeof(params)) | ||
| 6590 | goto out; | ||
| 6591 | |||
| 6592 | len = sizeof(params); | ||
| 6593 | if (copy_from_user(¶ms, optval, len)) { | ||
| 6594 | retval = -EFAULT; | ||
| 6595 | goto out; | ||
| 6596 | } | ||
| 6597 | |||
| 6598 | policy = params.sprstat_policy; | ||
| 6599 | if (policy & ~SCTP_PR_SCTP_MASK) | ||
| 6600 | goto out; | ||
| 6601 | |||
| 6602 | asoc = sctp_id2assoc(sk, params.sprstat_assoc_id); | ||
| 6603 | if (!asoc || params.sprstat_sid >= asoc->stream->outcnt) | ||
| 6604 | goto out; | ||
| 6605 | |||
| 6606 | streamout = &asoc->stream->out[params.sprstat_sid]; | ||
| 6607 | if (policy == SCTP_PR_SCTP_NONE) { | ||
| 6608 | params.sprstat_abandoned_unsent = 0; | ||
| 6609 | params.sprstat_abandoned_sent = 0; | ||
| 6610 | for (policy = 0; policy <= SCTP_PR_INDEX(MAX); policy++) { | ||
| 6611 | params.sprstat_abandoned_unsent += | ||
| 6612 | streamout->abandoned_unsent[policy]; | ||
| 6613 | params.sprstat_abandoned_sent += | ||
| 6614 | streamout->abandoned_sent[policy]; | ||
| 6615 | } | ||
| 6616 | } else { | ||
| 6617 | params.sprstat_abandoned_unsent = | ||
| 6618 | streamout->abandoned_unsent[__SCTP_PR_INDEX(policy)]; | ||
| 6619 | params.sprstat_abandoned_sent = | ||
| 6620 | streamout->abandoned_sent[__SCTP_PR_INDEX(policy)]; | ||
| 6621 | } | ||
| 6622 | |||
| 6623 | if (put_user(len, optlen) || copy_to_user(optval, ¶ms, len)) { | ||
| 6624 | retval = -EFAULT; | ||
| 6625 | goto out; | ||
| 6626 | } | ||
| 6627 | |||
| 6628 | retval = 0; | ||
| 6629 | |||
| 6630 | out: | ||
| 6631 | return retval; | ||
| 6632 | } | ||
| 6633 | |||
| 6579 | static int sctp_getsockopt_reconfig_supported(struct sock *sk, int len, | 6634 | static int sctp_getsockopt_reconfig_supported(struct sock *sk, int len, |
| 6580 | char __user *optval, | 6635 | char __user *optval, |
| 6581 | int __user *optlen) | 6636 | int __user *optlen) |
| @@ -6825,6 +6880,10 @@ static int sctp_getsockopt(struct sock *sk, int level, int optname, · 243 unmodified lines | |||
| 6825 | retval = sctp_getsockopt_pr_assocstatus(sk, len, optval, | 6880 | retval = sctp_getsockopt_pr_assocstatus(sk, len, optval, |
| 6826 | optlen); | 6881 | optlen); |
| 6827 | break; | 6882 | break; |
| 6883 | case SCTP_PR_STREAM_STATUS: | ||
| 6884 | retval = sctp_getsockopt_pr_streamstatus(sk, len, optval, | ||
| 6885 | optlen); | ||
| 6886 | break; | ||
| 6828 | case SCTP_RECONFIG_SUPPORTED: | 6887 | case SCTP_RECONFIG_SUPPORTED: |
| 6829 | retval = sctp_getsockopt_reconfig_supported(sk, len, optval, | 6888 | retval = sctp_getsockopt_reconfig_supported(sk, len, optval, |
| 6830 | optlen); | 6889 | optlen); |