OSDN Git Service

net/smc: improve smc_listen_work reason codes
authorKarsten Graul <kgraul@linux.ibm.com>
Fri, 12 Apr 2019 10:57:29 +0000 (12:57 +0200)
committerDavid S. Miller <davem@davemloft.net>
Fri, 12 Apr 2019 17:50:56 +0000 (10:50 -0700)
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>
net/smc/af_smc.c
net/smc/smc_clc.h

index 951af05..5e38b16 100644 (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
         */
        smc_pnet_find_roce_resource(smc->clcsock->sk, ini);
-       if (!(ini->ib_dev))
-               return SMC_CLC_DECL_CNFERR; /* configuration error */
+       if (!ini->ib_dev)
+               return SMC_CLC_DECL_NOSMCRDEV;
        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  */
        smc_pnet_find_ism_resource(smc->clcsock->sk, ini);
        if (!ini->ism_dev)
-               return SMC_CLC_DECL_CNFERR; /* configuration error */
+               return SMC_CLC_DECL_NOSMCDDEV;
        return 0;
 }
 
@@ -1155,7 +1155,7 @@ static int smc_listen_ism_init(struct smc_sock *new_smc,
                if (*local_contact == SMC_FIRST_CONTACT)
                        smc_lgr_forget(new_smc->conn.lgr);
                smc_conn_free(&new_smc->conn);
-               return SMC_CLC_DECL_CNFERR;
+               return SMC_CLC_DECL_SMCDNOTALK;
        }
 
        /* 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;
        rc = smc_clc_wait_msg(new_smc, pclc, SMC_CLC_MAX_LEN,
                              SMC_CLC_PROPOSAL, CLC_WAIT_TIME);
-       if (rc) {
-               smc_listen_decline(new_smc, rc, 0);
-               return;
-       }
+       if (rc)
+               goto out_decl;
 
        /* IPSec connections opt out of SMC-R optimizations */
        if (using_ipsec(new_smc)) {
-               smc_listen_decline(new_smc, SMC_CLC_DECL_IPSEC, 0);
-               return;
+               rc = SMC_CLC_DECL_IPSEC;
+               goto out_decl;
        }
 
        /* check for matching IP prefix and subnet length */
        rc = smc_listen_prfx_check(new_smc, pclc);
-       if (rc) {
-               smc_listen_decline(new_smc, rc, 0);
-               return;
-       }
+       if (rc)
+               goto out_decl;
 
        /* get vlan id from IP device */
        if (smc_vlan_by_tcpsk(new_smc->clcsock, &ini)) {
-               smc_listen_decline(new_smc, SMC_CLC_DECL_GETVLANERR, 0);
-               return;
+               rc = SMC_CLC_DECL_GETVLANERR;
+               goto out_decl;
        }
 
        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_tx_init(new_smc);
 
-       /* prepare ISM check */
-       ini.is_smcd = true;
        /* check if ISM is available */
-       if ((pclc->hdr.path == SMC_TYPE_D || pclc->hdr.path == SMC_TYPE_B) &&
-           !smc_find_ism_device(new_smc, &ini) &&
-           !smc_listen_ism_init(new_smc, pclc, &ini, &local_contact)) {
-               ism_supported = true;
-       } else {
+       if (pclc->hdr.path == SMC_TYPE_D || pclc->hdr.path == SMC_TYPE_B) {
+               ini.is_smcd = true; /* prepare ISM check */
+               rc = smc_find_ism_device(new_smc, &ini);
+               if (!rc)
+                       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 */
                memset(&ini, 0, sizeof(ini));
                ini.is_smcd = false;
                ini.ib_lcl = &pclc->lcl;
-       }
-
-       /* check if RDMA is available */
-       if (!ism_supported &&
-           ((pclc->hdr.path != SMC_TYPE_R && pclc->hdr.path != SMC_TYPE_B) ||
-            smc_vlan_by_tcpsk(new_smc->clcsock, &ini) ||
-            smc_find_rdma_device(new_smc, &ini) ||
-            smc_listen_rdma_init(new_smc, &ini, &local_contact) ||
-            smc_listen_rdma_reg(new_smc, local_contact))) {
-               /* SMC not supported, decline */
-               mutex_unlock(&smc_server_lgr_pending);
-               smc_listen_decline(new_smc, SMC_CLC_DECL_MODEUNSUPP,
-                                  local_contact);
-               return;
+               rc = smc_find_rdma_device(new_smc, &ini);
+               if (rc) {
+                       /* no RDMA device found */
+                       if (pclc->hdr.path == SMC_TYPE_B)
+                               /* neither ISM nor RDMA device found */
+                               rc = SMC_CLC_DECL_NOSMCDEV;
+                       goto out_unlock;
+               }
+               rc = smc_listen_rdma_init(new_smc, &ini, &local_contact);
+               if (rc)
+                       goto out_unlock;
+               rc = smc_listen_rdma_reg(new_smc, local_contact);
+               if (rc)
+                       goto out_unlock;
        }
 
        /* send SMC Accept CLC message */
        rc = smc_clc_send_accept(new_smc, local_contact);
-       if (rc) {
-               mutex_unlock(&smc_server_lgr_pending);
-               smc_listen_decline(new_smc, rc, local_contact);
-               return;
-       }
+       if (rc)
+               goto out_unlock;
 
        /* SMC-D does not need this lock any more */
        if (ism_supported)
@@ -1323,9 +1323,8 @@ static void smc_listen_work(struct work_struct *work)
                              SMC_CLC_CONFIRM, CLC_WAIT_TIME);
        if (rc) {
                if (!ism_supported)
-                       mutex_unlock(&smc_server_lgr_pending);
-               smc_listen_decline(new_smc, rc, local_contact);
-               return;
+                       goto out_unlock;
+               goto out_decl;
        }
 
        /* finish worker */
@@ -1337,6 +1336,12 @@ static void smc_listen_work(struct work_struct *work)
        }
        smc_conn_save_peer_info(new_smc, &cclc);
        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)
index 96a9eab..39f06da 100644 (file)
 #define SMC_CLC_DECL_CNFERR    0x03000000  /* configuration error            */
 #define SMC_CLC_DECL_PEERNOSMC 0x03010000  /* peer did not indicate SMC      */
 #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_RMBE_EC   0x03050000  /* peer has eyecatcher in RMBE    */
 #define SMC_CLC_DECL_OPTUNSUPP 0x03060000  /* fastopen sockopt not supported */