aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorXin Long <lucien.xin@gmail.com>2016-07-09 07:47:42 -0400
committerDavid S. Miller <davem@davemloft.net>2016-07-11 16:25:39 -0400
commit826d253d57b11f69add81c8086d2e7f1dce5ec77 (patch)
treeb811d99d0748e7a3e84d39768e014f63adfa2d14
parentf959fb442c35f4b61fea341401b8463dd0a1b959 (diff)
sctp: add SCTP_PR_ASSOC_STATUS on sctp sockopt
This patch adds SCTP_PR_ASSOC_STATUS to sctp sockopt, which is used to dump the prsctp statistics info from the asoc. The prsctp statistics includes abandoned_sent/unsent from the asoc. abandoned_sent is the count of the packets we drop packets from retransmit/transmited queue, and abandoned_unsent is the count of the packets we drop from out_queue according to the policy. Note: another option for prsctp statistics dump described in rfc is SCTP_PR_STREAM_STATUS, which is used to dump the prsctp statistics info from each stream. But by now, linux doesn't yet have per stream statistics info, it needs rfc6525 to be implemented. As the prsctp statistics for each stream has to be based on per stream statistics, we will delay it until rfc6525 is done in linux. Signed-off-by: Xin Long <lucien.xin@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/net/sctp/structs.h3
-rw-r--r--include/uapi/linux/sctp.h12
-rw-r--r--net/sctp/socket.c62
3 files changed, 77 insertions, 0 deletions
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 07115ca9de4d..d8e464aacb20 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -1853,6 +1853,9 @@ struct sctp_association {
1853 prsctp_enable:1; 1853 prsctp_enable:1;
1854 1854
1855 struct sctp_priv_assoc_stats stats; 1855 struct sctp_priv_assoc_stats stats;
1856
1857 __u64 abandoned_unsent[SCTP_PR_INDEX(MAX) + 1];
1858 __u64 abandoned_sent[SCTP_PR_INDEX(MAX) + 1];
1856}; 1859};
1857 1860
1858 1861
diff --git a/include/uapi/linux/sctp.h b/include/uapi/linux/sctp.h
index 984cf2e9a61d..d304f4c9792c 100644
--- a/include/uapi/linux/sctp.h
+++ b/include/uapi/linux/sctp.h
@@ -114,6 +114,7 @@ typedef __s32 sctp_assoc_t;
114#define SCTP_GET_ASSOC_STATS 112 /* Read only */ 114#define SCTP_GET_ASSOC_STATS 112 /* Read only */
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 118
118/* PR-SCTP policies */ 119/* PR-SCTP policies */
119#define SCTP_PR_SCTP_NONE 0x0000 120#define SCTP_PR_SCTP_NONE 0x0000
@@ -926,6 +927,17 @@ struct sctp_paddrthlds {
926 __u16 spt_pathpfthld; 927 __u16 spt_pathpfthld;
927}; 928};
928 929
930/*
931 * Socket Option for Getting the Association/Stream-Specific PR-SCTP Status
932 */
933struct sctp_prstatus {
934 sctp_assoc_t sprstat_assoc_id;
935 __u16 sprstat_sid;
936 __u16 sprstat_policy;
937 __u64 sprstat_abandoned_unsent;
938 __u64 sprstat_abandoned_sent;
939};
940
929struct sctp_default_prinfo { 941struct sctp_default_prinfo {
930 sctp_assoc_t pr_assoc_id; 942 sctp_assoc_t pr_assoc_id;
931 __u32 pr_value; 943 __u32 pr_value;
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index c03fe1b76706..c3167c43a9c1 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -6330,6 +6330,64 @@ out:
6330 return retval; 6330 return retval;
6331} 6331}
6332 6332
6333static int sctp_getsockopt_pr_assocstatus(struct sock *sk, int len,
6334 char __user *optval,
6335 int __user *optlen)
6336{
6337 struct sctp_prstatus params;
6338 struct sctp_association *asoc;
6339 int policy;
6340 int retval = -EINVAL;
6341
6342 if (len < sizeof(params))
6343 goto out;
6344
6345 len = sizeof(params);
6346 if (copy_from_user(&params, optval, len)) {
6347 retval = -EFAULT;
6348 goto out;
6349 }
6350
6351 policy = params.sprstat_policy;
6352 if (policy & ~SCTP_PR_SCTP_MASK)
6353 goto out;
6354
6355 asoc = sctp_id2assoc(sk, params.sprstat_assoc_id);
6356 if (!asoc)
6357 goto out;
6358
6359 if (policy == SCTP_PR_SCTP_NONE) {
6360 params.sprstat_abandoned_unsent = 0;
6361 params.sprstat_abandoned_sent = 0;
6362 for (policy = 0; policy <= SCTP_PR_INDEX(MAX); policy++) {
6363 params.sprstat_abandoned_unsent +=
6364 asoc->abandoned_unsent[policy];
6365 params.sprstat_abandoned_sent +=
6366 asoc->abandoned_sent[policy];
6367 }
6368 } else {
6369 params.sprstat_abandoned_unsent =
6370 asoc->abandoned_unsent[__SCTP_PR_INDEX(policy)];
6371 params.sprstat_abandoned_sent =
6372 asoc->abandoned_sent[__SCTP_PR_INDEX(policy)];
6373 }
6374
6375 if (put_user(len, optlen)) {
6376 retval = -EFAULT;
6377 goto out;
6378 }
6379
6380 if (copy_to_user(optval, &params, len)) {
6381 retval = -EFAULT;
6382 goto out;
6383 }
6384
6385 retval = 0;
6386
6387out:
6388 return retval;
6389}
6390
6333static int sctp_getsockopt(struct sock *sk, int level, int optname, 6391static int sctp_getsockopt(struct sock *sk, int level, int optname,
6334 char __user *optval, int __user *optlen) 6392 char __user *optval, int __user *optlen)
6335{ 6393{
@@ -6490,6 +6548,10 @@ static int sctp_getsockopt(struct sock *sk, int level, int optname,
6490 retval = sctp_getsockopt_default_prinfo(sk, len, optval, 6548 retval = sctp_getsockopt_default_prinfo(sk, len, optval,
6491 optlen); 6549 optlen);
6492 break; 6550 break;
6551 case SCTP_PR_ASSOC_STATUS:
6552 retval = sctp_getsockopt_pr_assocstatus(sk, len, optval,
6553 optlen);
6554 break;
6493 default: 6555 default:
6494 retval = -ENOPROTOOPT; 6556 retval = -ENOPROTOOPT;
6495 break; 6557 break;