Commit c5c1cc9c authored by Ursula Braun's avatar Ursula Braun Committed by David S. Miller

smc: add SMC rendezvous protocol

The SMC protocol [1] uses a rendezvous protocol to negotiate SMC
capability between peers. The current Linux implementation does not yet
use this rendezvous protocol and, thus, is not compliant to RFC7609 and
incompatible with other SMC implementations like in zOS.
This patch adds support for the SMC rendezvous protocol. It uses a new
TCP experimental option. With this option, SMC capabilities are
exchanged between the peers during the TCP three way handshake.

[1] SMC-R Informational RFC: http://www.rfc-editor.org/info/rfc7609Signed-off-by: default avatarUrsula Braun <ubraun@linux.vnet.ibm.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 60e2a778
...@@ -390,6 +390,12 @@ static int smc_connect_rdma(struct smc_sock *smc) ...@@ -390,6 +390,12 @@ static int smc_connect_rdma(struct smc_sock *smc)
int rc = 0; int rc = 0;
u8 ibport; u8 ibport;
if (!tcp_sk(smc->clcsock->sk)->syn_smc) {
/* peer has not signalled SMC-capability */
smc->use_fallback = true;
goto out_connected;
}
/* IPSec connections opt out of SMC-R optimizations */ /* IPSec connections opt out of SMC-R optimizations */
if (using_ipsec(smc)) { if (using_ipsec(smc)) {
reason_code = SMC_CLC_DECL_IPSEC; reason_code = SMC_CLC_DECL_IPSEC;
...@@ -555,6 +561,7 @@ static int smc_connect(struct socket *sock, struct sockaddr *addr, ...@@ -555,6 +561,7 @@ static int smc_connect(struct socket *sock, struct sockaddr *addr,
} }
smc_copy_sock_settings_to_clc(smc); smc_copy_sock_settings_to_clc(smc);
tcp_sk(smc->clcsock->sk)->syn_smc = 1;
rc = kernel_connect(smc->clcsock, addr, alen, flags); rc = kernel_connect(smc->clcsock, addr, alen, flags);
if (rc) if (rc)
goto out; goto out;
...@@ -759,6 +766,12 @@ static void smc_listen_work(struct work_struct *work) ...@@ -759,6 +766,12 @@ static void smc_listen_work(struct work_struct *work)
u8 prefix_len; u8 prefix_len;
u8 ibport; u8 ibport;
/* check if peer is smc capable */
if (!tcp_sk(newclcsock->sk)->syn_smc) {
new_smc->use_fallback = true;
goto out_connected;
}
/* do inband token exchange - /* do inband token exchange -
*wait for and receive SMC Proposal CLC message *wait for and receive SMC Proposal CLC message
*/ */
...@@ -967,6 +980,7 @@ static int smc_listen(struct socket *sock, int backlog) ...@@ -967,6 +980,7 @@ static int smc_listen(struct socket *sock, int backlog)
* them to the clc socket -- copy smc socket options to clc socket * them to the clc socket -- copy smc socket options to clc socket
*/ */
smc_copy_sock_settings_to_clc(smc); smc_copy_sock_settings_to_clc(smc);
tcp_sk(smc->clcsock->sk)->syn_smc = 1;
rc = kernel_listen(smc->clcsock, backlog); rc = kernel_listen(smc->clcsock, backlog);
if (rc) if (rc)
...@@ -1409,6 +1423,7 @@ static int __init smc_init(void) ...@@ -1409,6 +1423,7 @@ static int __init smc_init(void)
goto out_sock; goto out_sock;
} }
static_branch_enable(&tcp_have_smc);
return 0; return 0;
out_sock: out_sock:
...@@ -1433,6 +1448,7 @@ static void __exit smc_exit(void) ...@@ -1433,6 +1448,7 @@ static void __exit smc_exit(void)
list_del_init(&lgr->list); list_del_init(&lgr->list);
smc_lgr_free(lgr); /* free link group */ smc_lgr_free(lgr); /* free link group */
} }
static_branch_disable(&tcp_have_smc);
smc_ib_unregister_client(); smc_ib_unregister_client();
sock_unregister(PF_SMC); sock_unregister(PF_SMC);
proto_unregister(&smc_proto); proto_unregister(&smc_proto);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment