Skip to content

Commit ee9dfbe

Browse files
Ursula Braundavem330
authored andcommitted
net/smc: handle sockopts forcing fallback
Several TCP sockopts do not work for SMC. One example are the TCP_FASTOPEN sockopts, since SMC-connection setup is based on the TCP three-way-handshake. If the SMC socket is still in state SMC_INIT, such sockopts trigger fallback to TCP. Otherwise an error is returned. Signed-off-by: Ursula Braun <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 3382576 commit ee9dfbe

File tree

1 file changed

+50
-4
lines changed

1 file changed

+50
-4
lines changed

net/smc/af_smc.c

Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -391,6 +391,9 @@ static int smc_connect_rdma(struct smc_sock *smc)
391391

392392
sock_hold(&smc->sk); /* sock put in passive closing */
393393

394+
if (smc->use_fallback)
395+
goto out_connected;
396+
394397
if (!tcp_sk(smc->clcsock->sk)->syn_smc) {
395398
/* peer has not signalled SMC-capability */
396399
smc->use_fallback = true;
@@ -790,6 +793,9 @@ static void smc_listen_work(struct work_struct *work)
790793
int rc = 0;
791794
u8 ibport;
792795

796+
if (new_smc->use_fallback)
797+
goto out_connected;
798+
793799
/* check if peer is smc capable */
794800
if (!tcp_sk(newclcsock->sk)->syn_smc) {
795801
new_smc->use_fallback = true;
@@ -968,7 +974,7 @@ static void smc_tcp_listen_work(struct work_struct *work)
968974
continue;
969975

970976
new_smc->listen_smc = lsmc;
971-
new_smc->use_fallback = false; /* assume rdma capability first*/
977+
new_smc->use_fallback = lsmc->use_fallback;
972978
sock_hold(lsk); /* sock_put in smc_listen_work */
973979
INIT_WORK(&new_smc->smc_listen_work, smc_listen_work);
974980
smc_copy_sock_settings_to_smc(new_smc);
@@ -1004,7 +1010,8 @@ static int smc_listen(struct socket *sock, int backlog)
10041010
* them to the clc socket -- copy smc socket options to clc socket
10051011
*/
10061012
smc_copy_sock_settings_to_clc(smc);
1007-
tcp_sk(smc->clcsock->sk)->syn_smc = 1;
1013+
if (!smc->use_fallback)
1014+
tcp_sk(smc->clcsock->sk)->syn_smc = 1;
10081015

10091016
rc = kernel_listen(smc->clcsock, backlog);
10101017
if (rc)
@@ -1097,6 +1104,16 @@ static int smc_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
10971104
(sk->sk_state != SMC_APPCLOSEWAIT1) &&
10981105
(sk->sk_state != SMC_INIT))
10991106
goto out;
1107+
1108+
if (msg->msg_flags & MSG_FASTOPEN) {
1109+
if (sk->sk_state == SMC_INIT) {
1110+
smc->use_fallback = true;
1111+
} else {
1112+
rc = -EINVAL;
1113+
goto out;
1114+
}
1115+
}
1116+
11001117
if (smc->use_fallback)
11011118
rc = smc->clcsock->ops->sendmsg(smc->clcsock, msg, len);
11021119
else
@@ -1274,14 +1291,43 @@ static int smc_setsockopt(struct socket *sock, int level, int optname,
12741291
{
12751292
struct sock *sk = sock->sk;
12761293
struct smc_sock *smc;
1294+
int rc;
12771295

12781296
smc = smc_sk(sk);
12791297

12801298
/* generic setsockopts reaching us here always apply to the
12811299
* CLC socket
12821300
*/
1283-
return smc->clcsock->ops->setsockopt(smc->clcsock, level, optname,
1284-
optval, optlen);
1301+
rc = smc->clcsock->ops->setsockopt(smc->clcsock, level, optname,
1302+
optval, optlen);
1303+
if (smc->clcsock->sk->sk_err) {
1304+
sk->sk_err = smc->clcsock->sk->sk_err;
1305+
sk->sk_error_report(sk);
1306+
}
1307+
if (rc)
1308+
return rc;
1309+
1310+
lock_sock(sk);
1311+
switch (optname) {
1312+
case TCP_ULP:
1313+
case TCP_FASTOPEN:
1314+
case TCP_FASTOPEN_CONNECT:
1315+
case TCP_FASTOPEN_KEY:
1316+
case TCP_FASTOPEN_NO_COOKIE:
1317+
/* option not supported by SMC */
1318+
if (sk->sk_state == SMC_INIT) {
1319+
smc->use_fallback = true;
1320+
} else {
1321+
if (!smc->use_fallback)
1322+
rc = -EINVAL;
1323+
}
1324+
break;
1325+
default:
1326+
break;
1327+
}
1328+
release_sock(sk);
1329+
1330+
return rc;
12851331
}
12861332

12871333
static int smc_getsockopt(struct socket *sock, int level, int optname,

0 commit comments

Comments
 (0)