Skip to content

Commit

Permalink
net/smc: Dynamic control handshake limitation by socket options
Browse files Browse the repository at this point in the history
This patch aims to add dynamic control for SMC handshake limitation for
every smc sockets, in production environment, it is possible for the
same applications to handle different service types, and may have
different opinion on SMC handshake limitation.

This patch try socket options to complete it, since we don't have socket
option level for SMC yet, which requires us to implement it at the same
time.

This patch does the following:

- add new socket option level: SOL_SMC.
- add new SMC socket option: SMC_LIMIT_HS.
- provide getter/setter for SMC socket options.

Link: https://lore.kernel.org/all/20f504f961e1a803f85d64229ad84260434203bd.1644323503.git.alibuda@linux.alibaba.com/
Signed-off-by: D. Wythe <alibuda@linux.alibaba.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
D. Wythe authored and David S. Miller committed Feb 11, 2022
1 parent 48b6190 commit a6a6fe2
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 1 deletion.
1 change: 1 addition & 0 deletions include/linux/socket.h
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,7 @@ struct ucred {
#define SOL_XDP 283
#define SOL_MPTCP 284
#define SOL_MCTP 285
#define SOL_SMC 286

/* IPX options */
#define IPX_TYPE 1
Expand Down
4 changes: 4 additions & 0 deletions include/uapi/linux/smc.h
Original file line number Diff line number Diff line change
Expand Up @@ -284,4 +284,8 @@ enum {
__SMC_NLA_SEID_TABLE_MAX,
SMC_NLA_SEID_TABLE_MAX = __SMC_NLA_SEID_TABLE_MAX - 1
};

/* SMC socket options */
#define SMC_LIMIT_HS 1 /* constraint on smc handshake */

#endif /* _UAPI_LINUX_SMC_H */
69 changes: 68 additions & 1 deletion net/smc/af_smc.c
Original file line number Diff line number Diff line change
Expand Up @@ -2326,7 +2326,8 @@ static int smc_listen(struct socket *sock, int backlog)

inet_csk(smc->clcsock->sk)->icsk_af_ops = &smc->af_ops;

tcp_sk(smc->clcsock->sk)->smc_hs_congested = smc_hs_congested;
if (smc->limit_smc_hs)
tcp_sk(smc->clcsock->sk)->smc_hs_congested = smc_hs_congested;

rc = kernel_listen(smc->clcsock, backlog);
if (rc) {
Expand Down Expand Up @@ -2621,6 +2622,67 @@ static int smc_shutdown(struct socket *sock, int how)
return rc ? rc : rc1;
}

static int __smc_getsockopt(struct socket *sock, int level, int optname,
char __user *optval, int __user *optlen)
{
struct smc_sock *smc;
int val, len;

smc = smc_sk(sock->sk);

if (get_user(len, optlen))
return -EFAULT;

len = min_t(int, len, sizeof(int));

if (len < 0)
return -EINVAL;

switch (optname) {
case SMC_LIMIT_HS:
val = smc->limit_smc_hs;
break;
default:
return -EOPNOTSUPP;
}

if (put_user(len, optlen))
return -EFAULT;
if (copy_to_user(optval, &val, len))
return -EFAULT;

return 0;
}

static int __smc_setsockopt(struct socket *sock, int level, int optname,
sockptr_t optval, unsigned int optlen)
{
struct sock *sk = sock->sk;
struct smc_sock *smc;
int val, rc;

smc = smc_sk(sk);

lock_sock(sk);
switch (optname) {
case SMC_LIMIT_HS:
if (optlen < sizeof(int))
return -EINVAL;
if (copy_from_sockptr(&val, optval, sizeof(int)))
return -EFAULT;

smc->limit_smc_hs = !!val;
rc = 0;
break;
default:
rc = -EOPNOTSUPP;
break;
}
release_sock(sk);

return rc;
}

static int smc_setsockopt(struct socket *sock, int level, int optname,
sockptr_t optval, unsigned int optlen)
{
Expand All @@ -2630,6 +2692,8 @@ static int smc_setsockopt(struct socket *sock, int level, int optname,

if (level == SOL_TCP && optname == TCP_ULP)
return -EOPNOTSUPP;
else if (level == SOL_SMC)
return __smc_setsockopt(sock, level, optname, optval, optlen);

smc = smc_sk(sk);

Expand Down Expand Up @@ -2712,6 +2776,9 @@ static int smc_getsockopt(struct socket *sock, int level, int optname,
struct smc_sock *smc;
int rc;

if (level == SOL_SMC)
return __smc_getsockopt(sock, level, optname, optval, optlen);

smc = smc_sk(sock->sk);
mutex_lock(&smc->clcsock_release_lock);
if (!smc->clcsock) {
Expand Down
1 change: 1 addition & 0 deletions net/smc/smc.h
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,7 @@ struct smc_sock { /* smc sock container */
struct work_struct smc_listen_work;/* prepare new accept socket */
struct list_head accept_q; /* sockets to be accepted */
spinlock_t accept_q_lock; /* protects accept_q */
bool limit_smc_hs; /* put constraint on handshake */
bool use_fallback; /* fallback to tcp */
int fallback_rsn; /* reason for fallback */
u32 peer_diagnosis; /* decline reason from peer */
Expand Down

0 comments on commit a6a6fe2

Please sign in to comment.