History

sctp: add SCTP_PR_STREAM_STATUS sockopt for prsctp

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.

Xin Long committed 9 years ago

Commit d229d481 parent cdccf745 files · +84 −2Browse files

Unified · Split

5 files
  1. include/net/sctp/structs.h +2 −0
  2. include/uapi/linux/sctp.h +1 −0
  3. net/sctp/chunk.c +12 −2
  4. net/sctp/outqueue.c +10 −0
  5. net/sctp/socket.c +59 −0
include/net/sctp/structs.h+2−0
@@ -1315,6 +1315,8 @@ struct sctp_inithdr_host { · 1314 unmodified lines
1315struct sctp_stream_out {1315struct 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
1320struct sctp_stream_in {1322struct sctp_stream_in {
include/uapi/linux/sctp.h+1−0
@@ -115,6 +115,7 @@ typedef __s32 sctp_assoc_t; · 114 unmodified lines
115#define SCTP_PR_SUPPORTED 113115#define SCTP_PR_SUPPORTED 113
116#define SCTP_DEFAULT_PRINFO 114116#define SCTP_DEFAULT_PRINFO 114
117#define SCTP_PR_ASSOC_STATUS 115117#define SCTP_PR_ASSOC_STATUS 115
118#define SCTP_PR_STREAM_STATUS 116
118#define SCTP_RECONFIG_SUPPORTED 117119#define SCTP_RECONFIG_SUPPORTED 117
119#define SCTP_ENABLE_STREAM_RESET 118120#define SCTP_ENABLE_STREAM_RESET 118
120#define SCTP_RESET_STREAMS 119121#define SCTP_RESET_STREAMS 119
net/sctp/chunk.c+12−2
@@ -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 else314 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 &&
net/sctp/outqueue.c+10−0
@@ -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) +
net/sctp/socket.c+59−0
@@ -6576,6 +6576,61 @@ out: · 6575 unmodified lines
6576 return retval;6576 return retval;
6577}6577}
6578 6578
6579static 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(&params, 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, &params, len)) {
6624 retval = -EFAULT;
6625 goto out;
6626 }
6627
6628 retval = 0;
6629
6630out:
6631 return retval;
6632}
6633
6579static int sctp_getsockopt_reconfig_supported(struct sock *sk, int len,6634static 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);