net/smc: improve smc_listen_work reason codes

Rework smc_listen_work() to provide improved reason codes when an
SMC connection is declined. This allows better debugging on user side.
This also adds 3 more detailed reason codes in smc_clc.h to indicate
what type of device was not found (ism or rdma or both), or if ism
cannot talk to the peer.

Signed-off-by: Karsten Graul <kgraul@linux.ibm.com>
Signed-off-by: Ursula Braun <ubraun@linux.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Karsten Graul 2019-04-12 12:57:29 +02:00 committed by David S. Miller
parent 228bae05be
commit 9aa68d298c
2 changed files with 54 additions and 46 deletions

View File

@ -503,8 +503,8 @@ static int smc_find_rdma_device(struct smc_sock *smc, struct smc_init_info *ini)
* used for the internal TCP socket * used for the internal TCP socket
*/ */
smc_pnet_find_roce_resource(smc->clcsock->sk, ini); smc_pnet_find_roce_resource(smc->clcsock->sk, ini);
if (!(ini->ib_dev)) if (!ini->ib_dev)
return SMC_CLC_DECL_CNFERR; /* configuration error */ return SMC_CLC_DECL_NOSMCRDEV;
return 0; return 0;
} }
@ -515,7 +515,7 @@ static int smc_find_ism_device(struct smc_sock *smc, struct smc_init_info *ini)
/* Find ISM device with same PNETID as connecting interface */ /* Find ISM device with same PNETID as connecting interface */
smc_pnet_find_ism_resource(smc->clcsock->sk, ini); smc_pnet_find_ism_resource(smc->clcsock->sk, ini);
if (!ini->ism_dev) if (!ini->ism_dev)
return SMC_CLC_DECL_CNFERR; /* configuration error */ return SMC_CLC_DECL_NOSMCDDEV;
return 0; return 0;
} }
@ -1155,7 +1155,7 @@ static int smc_listen_ism_init(struct smc_sock *new_smc,
if (*local_contact == SMC_FIRST_CONTACT) if (*local_contact == SMC_FIRST_CONTACT)
smc_lgr_forget(new_smc->conn.lgr); smc_lgr_forget(new_smc->conn.lgr);
smc_conn_free(&new_smc->conn); smc_conn_free(&new_smc->conn);
return SMC_CLC_DECL_CNFERR; return SMC_CLC_DECL_SMCDNOTALK;
} }
/* Create send and receive buffers */ /* Create send and receive buffers */
@ -1249,28 +1249,24 @@ static void smc_listen_work(struct work_struct *work)
pclc = (struct smc_clc_msg_proposal *)&buf; pclc = (struct smc_clc_msg_proposal *)&buf;
rc = smc_clc_wait_msg(new_smc, pclc, SMC_CLC_MAX_LEN, rc = smc_clc_wait_msg(new_smc, pclc, SMC_CLC_MAX_LEN,
SMC_CLC_PROPOSAL, CLC_WAIT_TIME); SMC_CLC_PROPOSAL, CLC_WAIT_TIME);
if (rc) { if (rc)
smc_listen_decline(new_smc, rc, 0); goto out_decl;
return;
}
/* IPSec connections opt out of SMC-R optimizations */ /* IPSec connections opt out of SMC-R optimizations */
if (using_ipsec(new_smc)) { if (using_ipsec(new_smc)) {
smc_listen_decline(new_smc, SMC_CLC_DECL_IPSEC, 0); rc = SMC_CLC_DECL_IPSEC;
return; goto out_decl;
} }
/* check for matching IP prefix and subnet length */ /* check for matching IP prefix and subnet length */
rc = smc_listen_prfx_check(new_smc, pclc); rc = smc_listen_prfx_check(new_smc, pclc);
if (rc) { if (rc)
smc_listen_decline(new_smc, rc, 0); goto out_decl;
return;
}
/* get vlan id from IP device */ /* get vlan id from IP device */
if (smc_vlan_by_tcpsk(new_smc->clcsock, &ini)) { if (smc_vlan_by_tcpsk(new_smc->clcsock, &ini)) {
smc_listen_decline(new_smc, SMC_CLC_DECL_GETVLANERR, 0); rc = SMC_CLC_DECL_GETVLANERR;
return; goto out_decl;
} }
mutex_lock(&smc_server_lgr_pending); mutex_lock(&smc_server_lgr_pending);
@ -1278,41 +1274,45 @@ static void smc_listen_work(struct work_struct *work)
smc_rx_init(new_smc); smc_rx_init(new_smc);
smc_tx_init(new_smc); smc_tx_init(new_smc);
/* prepare ISM check */
ini.is_smcd = true;
/* check if ISM is available */ /* check if ISM is available */
if ((pclc->hdr.path == SMC_TYPE_D || pclc->hdr.path == SMC_TYPE_B) && if (pclc->hdr.path == SMC_TYPE_D || pclc->hdr.path == SMC_TYPE_B) {
!smc_find_ism_device(new_smc, &ini) && ini.is_smcd = true; /* prepare ISM check */
!smc_listen_ism_init(new_smc, pclc, &ini, &local_contact)) { rc = smc_find_ism_device(new_smc, &ini);
ism_supported = true; if (!rc)
} else { rc = smc_listen_ism_init(new_smc, pclc, &ini,
&local_contact);
if (!rc)
ism_supported = true;
else if (pclc->hdr.path == SMC_TYPE_D)
goto out_unlock; /* skip RDMA and decline */
}
/* check if RDMA is available */
if (!ism_supported) { /* SMC_TYPE_R or SMC_TYPE_B */
/* prepare RDMA check */ /* prepare RDMA check */
memset(&ini, 0, sizeof(ini)); memset(&ini, 0, sizeof(ini));
ini.is_smcd = false; ini.is_smcd = false;
ini.ib_lcl = &pclc->lcl; ini.ib_lcl = &pclc->lcl;
} rc = smc_find_rdma_device(new_smc, &ini);
if (rc) {
/* check if RDMA is available */ /* no RDMA device found */
if (!ism_supported && if (pclc->hdr.path == SMC_TYPE_B)
((pclc->hdr.path != SMC_TYPE_R && pclc->hdr.path != SMC_TYPE_B) || /* neither ISM nor RDMA device found */
smc_vlan_by_tcpsk(new_smc->clcsock, &ini) || rc = SMC_CLC_DECL_NOSMCDEV;
smc_find_rdma_device(new_smc, &ini) || goto out_unlock;
smc_listen_rdma_init(new_smc, &ini, &local_contact) || }
smc_listen_rdma_reg(new_smc, local_contact))) { rc = smc_listen_rdma_init(new_smc, &ini, &local_contact);
/* SMC not supported, decline */ if (rc)
mutex_unlock(&smc_server_lgr_pending); goto out_unlock;
smc_listen_decline(new_smc, SMC_CLC_DECL_MODEUNSUPP, rc = smc_listen_rdma_reg(new_smc, local_contact);
local_contact); if (rc)
return; goto out_unlock;
} }
/* send SMC Accept CLC message */ /* send SMC Accept CLC message */
rc = smc_clc_send_accept(new_smc, local_contact); rc = smc_clc_send_accept(new_smc, local_contact);
if (rc) { if (rc)
mutex_unlock(&smc_server_lgr_pending); goto out_unlock;
smc_listen_decline(new_smc, rc, local_contact);
return;
}
/* SMC-D does not need this lock any more */ /* SMC-D does not need this lock any more */
if (ism_supported) if (ism_supported)
@ -1323,9 +1323,8 @@ static void smc_listen_work(struct work_struct *work)
SMC_CLC_CONFIRM, CLC_WAIT_TIME); SMC_CLC_CONFIRM, CLC_WAIT_TIME);
if (rc) { if (rc) {
if (!ism_supported) if (!ism_supported)
mutex_unlock(&smc_server_lgr_pending); goto out_unlock;
smc_listen_decline(new_smc, rc, local_contact); goto out_decl;
return;
} }
/* finish worker */ /* finish worker */
@ -1337,6 +1336,12 @@ static void smc_listen_work(struct work_struct *work)
} }
smc_conn_save_peer_info(new_smc, &cclc); smc_conn_save_peer_info(new_smc, &cclc);
smc_listen_out_connected(new_smc); smc_listen_out_connected(new_smc);
return;
out_unlock:
mutex_unlock(&smc_server_lgr_pending);
out_decl:
smc_listen_decline(new_smc, rc, local_contact);
} }
static void smc_tcp_listen_work(struct work_struct *work) static void smc_tcp_listen_work(struct work_struct *work)

View File

@ -34,7 +34,10 @@
#define SMC_CLC_DECL_CNFERR 0x03000000 /* configuration error */ #define SMC_CLC_DECL_CNFERR 0x03000000 /* configuration error */
#define SMC_CLC_DECL_PEERNOSMC 0x03010000 /* peer did not indicate SMC */ #define SMC_CLC_DECL_PEERNOSMC 0x03010000 /* peer did not indicate SMC */
#define SMC_CLC_DECL_IPSEC 0x03020000 /* IPsec usage */ #define SMC_CLC_DECL_IPSEC 0x03020000 /* IPsec usage */
#define SMC_CLC_DECL_NOSMCDEV 0x03030000 /* no SMC device found */ #define SMC_CLC_DECL_NOSMCDEV 0x03030000 /* no SMC device found (R or D) */
#define SMC_CLC_DECL_NOSMCDDEV 0x03030001 /* no SMC-D device found */
#define SMC_CLC_DECL_NOSMCRDEV 0x03030002 /* no SMC-R device found */
#define SMC_CLC_DECL_SMCDNOTALK 0x03030003 /* SMC-D dev can't talk to peer */
#define SMC_CLC_DECL_MODEUNSUPP 0x03040000 /* smc modes do not match (R or D)*/ #define SMC_CLC_DECL_MODEUNSUPP 0x03040000 /* smc modes do not match (R or D)*/
#define SMC_CLC_DECL_RMBE_EC 0x03050000 /* peer has eyecatcher in RMBE */ #define SMC_CLC_DECL_RMBE_EC 0x03050000 /* peer has eyecatcher in RMBE */
#define SMC_CLC_DECL_OPTUNSUPP 0x03060000 /* fastopen sockopt not supported */ #define SMC_CLC_DECL_OPTUNSUPP 0x03060000 /* fastopen sockopt not supported */