diff options
author | Marcelo Ricardo Leitner <marcelo.leitner@gmail.com> | 2017-10-03 18:20:15 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2017-10-03 19:27:29 -0400 |
commit | 0ccdf3c7fdeda511b10def19505178a9d2d3fccd (patch) | |
tree | 1db44b2bd6edbce191461a3ee0cb3622e19de2ba /net/sctp | |
parent | 13aa8770fe42d246c6f3a8eb814b85bccb428011 (diff) |
sctp: add sockopt to get/set stream scheduler parameters
As defined per RFC Draft ndata Section 4.3.3, named as
SCTP_STREAM_SCHEDULER_VALUE.
See-also: https://tools.ietf.org/html/draft-ietf-tsvwg-sctp-ndata-13
Tested-by: Xin Long <lucien.xin@gmail.com>
Signed-off-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/sctp')
-rw-r--r-- | net/sctp/socket.c | 77 |
1 files changed, 77 insertions, 0 deletions
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index ae35dbf2810f..88c28421ec15 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -3945,6 +3945,34 @@ out: | |||
3945 | return retval; | 3945 | return retval; |
3946 | } | 3946 | } |
3947 | 3947 | ||
3948 | static int sctp_setsockopt_scheduler_value(struct sock *sk, | ||
3949 | char __user *optval, | ||
3950 | unsigned int optlen) | ||
3951 | { | ||
3952 | struct sctp_association *asoc; | ||
3953 | struct sctp_stream_value params; | ||
3954 | int retval = -EINVAL; | ||
3955 | |||
3956 | if (optlen < sizeof(params)) | ||
3957 | goto out; | ||
3958 | |||
3959 | optlen = sizeof(params); | ||
3960 | if (copy_from_user(¶ms, optval, optlen)) { | ||
3961 | retval = -EFAULT; | ||
3962 | goto out; | ||
3963 | } | ||
3964 | |||
3965 | asoc = sctp_id2assoc(sk, params.assoc_id); | ||
3966 | if (!asoc) | ||
3967 | goto out; | ||
3968 | |||
3969 | retval = sctp_sched_set_value(asoc, params.stream_id, | ||
3970 | params.stream_value, GFP_KERNEL); | ||
3971 | |||
3972 | out: | ||
3973 | return retval; | ||
3974 | } | ||
3975 | |||
3948 | /* API 6.2 setsockopt(), getsockopt() | 3976 | /* API 6.2 setsockopt(), getsockopt() |
3949 | * | 3977 | * |
3950 | * Applications use setsockopt() and getsockopt() to set or retrieve | 3978 | * Applications use setsockopt() and getsockopt() to set or retrieve |
@@ -4129,6 +4157,9 @@ static int sctp_setsockopt(struct sock *sk, int level, int optname, | |||
4129 | case SCTP_STREAM_SCHEDULER: | 4157 | case SCTP_STREAM_SCHEDULER: |
4130 | retval = sctp_setsockopt_scheduler(sk, optval, optlen); | 4158 | retval = sctp_setsockopt_scheduler(sk, optval, optlen); |
4131 | break; | 4159 | break; |
4160 | case SCTP_STREAM_SCHEDULER_VALUE: | ||
4161 | retval = sctp_setsockopt_scheduler_value(sk, optval, optlen); | ||
4162 | break; | ||
4132 | default: | 4163 | default: |
4133 | retval = -ENOPROTOOPT; | 4164 | retval = -ENOPROTOOPT; |
4134 | break; | 4165 | break; |
@@ -6864,6 +6895,48 @@ out: | |||
6864 | return retval; | 6895 | return retval; |
6865 | } | 6896 | } |
6866 | 6897 | ||
6898 | static int sctp_getsockopt_scheduler_value(struct sock *sk, int len, | ||
6899 | char __user *optval, | ||
6900 | int __user *optlen) | ||
6901 | { | ||
6902 | struct sctp_stream_value params; | ||
6903 | struct sctp_association *asoc; | ||
6904 | int retval = -EFAULT; | ||
6905 | |||
6906 | if (len < sizeof(params)) { | ||
6907 | retval = -EINVAL; | ||
6908 | goto out; | ||
6909 | } | ||
6910 | |||
6911 | len = sizeof(params); | ||
6912 | if (copy_from_user(¶ms, optval, len)) | ||
6913 | goto out; | ||
6914 | |||
6915 | asoc = sctp_id2assoc(sk, params.assoc_id); | ||
6916 | if (!asoc) { | ||
6917 | retval = -EINVAL; | ||
6918 | goto out; | ||
6919 | } | ||
6920 | |||
6921 | retval = sctp_sched_get_value(asoc, params.stream_id, | ||
6922 | ¶ms.stream_value); | ||
6923 | if (retval) | ||
6924 | goto out; | ||
6925 | |||
6926 | if (put_user(len, optlen)) { | ||
6927 | retval = -EFAULT; | ||
6928 | goto out; | ||
6929 | } | ||
6930 | |||
6931 | if (copy_to_user(optval, ¶ms, len)) { | ||
6932 | retval = -EFAULT; | ||
6933 | goto out; | ||
6934 | } | ||
6935 | |||
6936 | out: | ||
6937 | return retval; | ||
6938 | } | ||
6939 | |||
6867 | static int sctp_getsockopt(struct sock *sk, int level, int optname, | 6940 | static int sctp_getsockopt(struct sock *sk, int level, int optname, |
6868 | char __user *optval, int __user *optlen) | 6941 | char __user *optval, int __user *optlen) |
6869 | { | 6942 | { |
@@ -7050,6 +7123,10 @@ static int sctp_getsockopt(struct sock *sk, int level, int optname, | |||
7050 | retval = sctp_getsockopt_scheduler(sk, len, optval, | 7123 | retval = sctp_getsockopt_scheduler(sk, len, optval, |
7051 | optlen); | 7124 | optlen); |
7052 | break; | 7125 | break; |
7126 | case SCTP_STREAM_SCHEDULER_VALUE: | ||
7127 | retval = sctp_getsockopt_scheduler_value(sk, len, optval, | ||
7128 | optlen); | ||
7129 | break; | ||
7053 | default: | 7130 | default: |
7054 | retval = -ENOPROTOOPT; | 7131 | retval = -ENOPROTOOPT; |
7055 | break; | 7132 | break; |