[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20180625133024.GB820@localhost.localdomain>
Date: Mon, 25 Jun 2018 10:30:25 -0300
From: Marcelo Ricardo Leitner <marcelo.leitner@...il.com>
To: Xin Long <lucien.xin@...il.com>
Cc: network dev <netdev@...r.kernel.org>, linux-sctp@...r.kernel.org,
Neil Horman <nhorman@...driver.com>,
Michael Tuexen <tuexen@...muenster.de>, davem@...emloft.net
Subject: Re: [PATCHv2 net-next] sctp: add support for SCTP_REUSE_PORT sockopt
On Mon, Jun 25, 2018 at 10:06:46AM +0800, Xin Long wrote:
> This feature is actually already supported by sk->sk_reuse which can be
> set by socket level opt SO_REUSEADDR. But it's not working exactly as
> RFC6458 demands in section 8.1.27, like:
>
> - This option only supports one-to-one style SCTP sockets
> - This socket option must not be used after calling bind()
> or sctp_bindx().
>
> Besides, SCTP_REUSE_PORT sockopt should be provided for user's programs.
> Otherwise, the programs with SCTP_REUSE_PORT from other systems will not
> work in linux.
>
> To separate it from the socket level version, this patch adds 'reuse' in
> sctp_sock and it works pretty much as sk->sk_reuse, but with some extra
> setup limitations that are needed when it is being enabled.
>
> "It should be noted that the behavior of the socket-level socket option
> to reuse ports and/or addresses for SCTP sockets is unspecified", so it
> leaves SO_REUSEADDR as is for the compatibility.
>
> Note that the name SCTP_REUSE_PORT is kind of confusing, it is identical
> to SO_REUSEADDR with some extra restriction, so here it uses 'reuse' in
> sctp_sock instead of 'reuseport'. As for sk->sk_reuseport support for
> SCTP, it will be added in another patch.
To help changelog readers later, please update to something like:
"""\
Note that the name SCTP_REUSE_PORT is somewhat confusing, as its
functionality is nearly identical to SO_REUSEADDR, but with some
extra restrictions. Here it uses 'reuse' in sctp_sock instead of
'reuseport'. As for sk->sk_reuseport support for SCTP, it will be
added in another patch.
"""
Makes sense, can you note the difference?
>
> Thanks to Neil to make this clear.
>
> v1->v2:
> - add sctp_sk->reuse to separate it from the socket level version.
>
> Acked-by: Neil Horman <nhorman@...driver.com>
> Signed-off-by: Xin Long <lucien.xin@...il.com>
> ---
> include/net/sctp/structs.h | 1 +
> include/uapi/linux/sctp.h | 1 +
> net/sctp/socket.c | 62 ++++++++++++++++++++++++++++++++++++++++------
> 3 files changed, 57 insertions(+), 7 deletions(-)
>
> diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
> index e0f962d..701a517 100644
> --- a/include/net/sctp/structs.h
> +++ b/include/net/sctp/structs.h
> @@ -220,6 +220,7 @@ struct sctp_sock {
> __u32 adaptation_ind;
> __u32 pd_point;
> __u16 nodelay:1,
> + reuse:1,
> disable_fragments:1,
> v4mapped:1,
> frag_interleave:1,
> diff --git a/include/uapi/linux/sctp.h b/include/uapi/linux/sctp.h
> index b64d583..c02986a 100644
> --- a/include/uapi/linux/sctp.h
> +++ b/include/uapi/linux/sctp.h
> @@ -100,6 +100,7 @@ typedef __s32 sctp_assoc_t;
> #define SCTP_RECVNXTINFO 33
> #define SCTP_DEFAULT_SNDINFO 34
> #define SCTP_AUTH_DEACTIVATE_KEY 35
> +#define SCTP_REUSE_PORT 36
>
> /* Internal Socket Options. Some of the sctp library functions are
> * implemented using these socket options.
> diff --git a/net/sctp/socket.c b/net/sctp/socket.c
> index 0e91e83..bf11f9c 100644
> --- a/net/sctp/socket.c
> +++ b/net/sctp/socket.c
> @@ -4170,6 +4170,28 @@ static int sctp_setsockopt_interleaving_supported(struct sock *sk,
> return retval;
> }
>
> +static int sctp_setsockopt_reuse_port(struct sock *sk, char __user *optval,
> + unsigned int optlen)
> +{
> + int val;
> +
> + if (!sctp_style(sk, TCP))
> + return -EOPNOTSUPP;
> +
> + if (sctp_sk(sk)->ep->base.bind_addr.port)
> + return -EFAULT;
> +
> + if (optlen < sizeof(int))
> + return -EINVAL;
> +
> + if (get_user(val, (int __user *)optval))
> + return -EFAULT;
> +
> + sctp_sk(sk)->reuse = !!val;
> +
> + return 0;
> +}
> +
> /* API 6.2 setsockopt(), getsockopt()
> *
> * Applications use setsockopt() and getsockopt() to set or retrieve
> @@ -4364,6 +4386,9 @@ static int sctp_setsockopt(struct sock *sk, int level, int optname,
> retval = sctp_setsockopt_interleaving_supported(sk, optval,
> optlen);
> break;
> + case SCTP_REUSE_PORT:
> + retval = sctp_setsockopt_reuse_port(sk, optval, optlen);
> + break;
> default:
> retval = -ENOPROTOOPT;
> break;
> @@ -7197,6 +7222,26 @@ static int sctp_getsockopt_interleaving_supported(struct sock *sk, int len,
> return retval;
> }
>
> +static int sctp_getsockopt_reuse_port(struct sock *sk, int len,
> + char __user *optval,
> + int __user *optlen)
> +{
> + int val;
> +
> + if (len < sizeof(int))
> + return -EINVAL;
> +
> + len = sizeof(int);
> + val = sctp_sk(sk)->reuse;
> + if (put_user(len, optlen))
> + return -EFAULT;
> +
> + if (copy_to_user(optval, &val, len))
> + return -EFAULT;
> +
> + return 0;
> +}
> +
> static int sctp_getsockopt(struct sock *sk, int level, int optname,
> char __user *optval, int __user *optlen)
> {
> @@ -7392,6 +7437,9 @@ static int sctp_getsockopt(struct sock *sk, int level, int optname,
> retval = sctp_getsockopt_interleaving_supported(sk, len, optval,
> optlen);
> break;
> + case SCTP_REUSE_PORT:
> + retval = sctp_getsockopt_reuse_port(sk, len, optval, optlen);
> + break;
> default:
> retval = -ENOPROTOOPT;
> break;
> @@ -7429,6 +7477,7 @@ static struct sctp_bind_bucket *sctp_bucket_create(
>
> static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr)
> {
> + bool reuse = (sk->sk_reuse || sctp_sk(sk)->reuse);
> struct sctp_bind_hashbucket *head; /* hash list */
> struct sctp_bind_bucket *pp;
> unsigned short snum;
> @@ -7501,13 +7550,11 @@ static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr)
> * used by other socket (pp->owner not empty); that other
> * socket is going to be sk2.
> */
> - int reuse = sk->sk_reuse;
> struct sock *sk2;
>
> pr_debug("%s: found a possible match\n", __func__);
>
> - if (pp->fastreuse && sk->sk_reuse &&
> - sk->sk_state != SCTP_SS_LISTENING)
> + if (pp->fastreuse && reuse && sk->sk_state != SCTP_SS_LISTENING)
> goto success;
>
> /* Run through the list of sockets bound to the port
> @@ -7525,7 +7572,7 @@ static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr)
> ep2 = sctp_sk(sk2)->ep;
>
> if (sk == sk2 ||
> - (reuse && sk2->sk_reuse &&
> + (reuse && (sk2->sk_reuse || sctp_sk(sk2)->reuse) &&
> sk2->sk_state != SCTP_SS_LISTENING))
> continue;
>
> @@ -7549,12 +7596,12 @@ static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr)
> * SO_REUSEADDR on this socket -sk-).
> */
> if (hlist_empty(&pp->owner)) {
> - if (sk->sk_reuse && sk->sk_state != SCTP_SS_LISTENING)
> + if (reuse && sk->sk_state != SCTP_SS_LISTENING)
> pp->fastreuse = 1;
> else
> pp->fastreuse = 0;
> } else if (pp->fastreuse &&
> - (!sk->sk_reuse || sk->sk_state == SCTP_SS_LISTENING))
> + (!reuse || sk->sk_state == SCTP_SS_LISTENING))
> pp->fastreuse = 0;
>
> /* We are set, so fill up all the data in the hash table
> @@ -7685,7 +7732,7 @@ int sctp_inet_listen(struct socket *sock, int backlog)
> err = 0;
> sctp_unhash_endpoint(ep);
> sk->sk_state = SCTP_SS_CLOSED;
> - if (sk->sk_reuse)
> + if (sk->sk_reuse || sctp_sk(sk)->reuse)
> sctp_sk(sk)->bind_hash->fastreuse = 1;
> goto out;
> }
> @@ -8550,6 +8597,7 @@ void sctp_copy_sock(struct sock *newsk, struct sock *sk,
> newsk->sk_no_check_tx = sk->sk_no_check_tx;
> newsk->sk_no_check_rx = sk->sk_no_check_rx;
> newsk->sk_reuse = sk->sk_reuse;
> + sctp_sk(newsk)->reuse = sp->reuse;
>
> newsk->sk_shutdown = sk->sk_shutdown;
> newsk->sk_destruct = sctp_destruct_sock;
> --
> 2.1.0
>
Powered by blists - more mailing lists