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
13151315 struct sctp_stream_out {
13161316 __u16 ssn;
13171317 __u8 state;
1318+ __u64 abandoned_unsent[SCTP_PR_INDEX(MAX) + 1];
1319+ __u64 abandoned_sent[SCTP_PR_INDEX(MAX) + 1];
13181320 };
13191321
13201322 struct sctp_stream_in {
include/uapi/linux/sctp.h+1−0
@@ -115,6 +115,7 @@ typedef __s32 sctp_assoc_t; · 114 unmodified lines
115115 #define SCTP_PR_SUPPORTED 113
116116 #define SCTP_DEFAULT_PRINFO 114
117117 #define SCTP_PR_ASSOC_STATUS 115
118+#define SCTP_PR_STREAM_STATUS 116
118119 #define SCTP_RECONFIG_SUPPORTED 117
119120 #define SCTP_ENABLE_STREAM_RESET 118
120121 #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
306306
307307 if (SCTP_PR_TTL_ENABLED(chunk->sinfo.sinfo_flags) &&
308308 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) {
310313 chunk->asoc->abandoned_sent[SCTP_PR_INDEX(TTL)]++;
311− else
314+ streamout->abandoned_sent[SCTP_PR_INDEX(TTL)]++;
315+ } else {
312316 chunk->asoc->abandoned_unsent[SCTP_PR_INDEX(TTL)]++;
317+ streamout->abandoned_unsent[SCTP_PR_INDEX(TTL)]++;
318+ }
313319 return 1;
314320 } else if (SCTP_PR_RTX_ENABLED(chunk->sinfo.sinfo_flags) &&
315321 chunk->sent_count > chunk->sinfo.sinfo_timetolive) {
322+ struct sctp_stream_out *streamout =
323+ &chunk->asoc->stream->out[chunk->sinfo.sinfo_stream];
324+
316325 chunk->asoc->abandoned_sent[SCTP_PR_INDEX(RTX)]++;
326+ streamout->abandoned_sent[SCTP_PR_INDEX(RTX)]++;
317327 return 1;
318328 } else if (!SCTP_PR_POLICY(chunk->sinfo.sinfo_flags) &&
319329 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
353353 struct sctp_chunk *chk, *temp;
354354
355355 list_for_each_entry_safe(chk, temp, queue, transmitted_list) {
356+ struct sctp_stream_out *streamout;
357+
356358 if (!SCTP_PR_PRIO_ENABLED(chk->sinfo.sinfo_flags) ||
357359 chk->sinfo.sinfo_timetolive <= sinfo->sinfo_timetolive)
358360 continue;
@@ -361,8 +363,10 @@ static int sctp_prsctp_prune_sent(struct sctp_association *asoc, · 2 unmodified lines
361363 sctp_insert_list(&asoc->outqueue.abandoned,
362364 &chk->transmitted_list);
363365
366+ streamout = &asoc->stream->out[chk->sinfo.sinfo_stream];
364367 asoc->sent_cnt_removable--;
365368 asoc->abandoned_sent[SCTP_PR_INDEX(PRIO)]++;
369+ streamout->abandoned_sent[SCTP_PR_INDEX(PRIO)]++;
366370
367371 if (!chk->tsn_gap_acked) {
368372 if (chk->transport)
@@ -396,6 +400,12 @@ static int sctp_prsctp_prune_unsent(struct sctp_association *asoc, · 27 unmodified lines
396400 q->out_qlen -= chk->skb->len;
397401 asoc->sent_cnt_removable--;
398402 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+ }
399409
400410 msg_len -= SCTP_DATA_SNDSIZE(chk) +
401411 sizeof(struct sk_buff) +
net/sctp/socket.c+59−0
@@ -6576,6 +6576,61 @@ out: · 6575 unmodified lines
65766576 return retval;
65776577 }
65786578
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(&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+
6630+out:
6631+ return retval;
6632+}
6633+
65796634 static int sctp_getsockopt_reconfig_supported(struct sock *sk, int len,
65806635 char __user *optval,
65816636 int __user *optlen)
@@ -6825,6 +6880,10 @@ static int sctp_getsockopt(struct sock *sk, int level, int optname, · 243 unmodified lines
68256880 retval = sctp_getsockopt_pr_assocstatus(sk, len, optval,
68266881 optlen);
68276882 break;
6883+ case SCTP_PR_STREAM_STATUS:
6884+ retval = sctp_getsockopt_pr_streamstatus(sk, len, optval,
6885+ optlen);
6886+ break;
68286887 case SCTP_RECONFIG_SUPPORTED:
68296888 retval = sctp_getsockopt_reconfig_supported(sk, len, optval,
68306889 optlen);