mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	net/smc: CLC accept / confirm V2
The new format of SMCD V2 CLC accept and confirm is introduced, and building and checking of SMCD V2 CLC accepts / confirms is adapted accordingly. Signed-off-by: Ursula Braun <ubraun@linux.ibm.com> Signed-off-by: Karsten Graul <kgraul@linux.ibm.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									5c21c4ccaf
								
							
						
					
					
						commit
						a7c9c5f4af
					
				
					 3 changed files with 170 additions and 57 deletions
				
			
		
							
								
								
									
										101
									
								
								net/smc/af_smc.c
									
									
									
									
									
								
							
							
						
						
									
										101
									
								
								net/smc/af_smc.c
									
									
									
									
									
								
							| 
						 | 
					@ -660,9 +660,13 @@ static int smc_connect_ism_vlan_cleanup(struct smc_sock *smc,
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define SMC_CLC_MAX_ACCEPT_LEN \
 | 
				
			||||||
 | 
						(sizeof(struct smc_clc_msg_accept_confirm_v2) + \
 | 
				
			||||||
 | 
						 sizeof(struct smc_clc_msg_trail))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* CLC handshake during connect */
 | 
					/* CLC handshake during connect */
 | 
				
			||||||
static int smc_connect_clc(struct smc_sock *smc,
 | 
					static int smc_connect_clc(struct smc_sock *smc,
 | 
				
			||||||
			   struct smc_clc_msg_accept_confirm *aclc,
 | 
								   struct smc_clc_msg_accept_confirm_v2 *aclc2,
 | 
				
			||||||
			   struct smc_init_info *ini)
 | 
								   struct smc_init_info *ini)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int rc = 0;
 | 
						int rc = 0;
 | 
				
			||||||
| 
						 | 
					@ -672,8 +676,8 @@ static int smc_connect_clc(struct smc_sock *smc,
 | 
				
			||||||
	if (rc)
 | 
						if (rc)
 | 
				
			||||||
		return rc;
 | 
							return rc;
 | 
				
			||||||
	/* receive SMC Accept CLC message */
 | 
						/* receive SMC Accept CLC message */
 | 
				
			||||||
	return smc_clc_wait_msg(smc, aclc, sizeof(*aclc), SMC_CLC_ACCEPT,
 | 
						return smc_clc_wait_msg(smc, aclc2, SMC_CLC_MAX_ACCEPT_LEN,
 | 
				
			||||||
				CLC_WAIT_TIME);
 | 
									SMC_CLC_ACCEPT, CLC_WAIT_TIME);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* setup for RDMA connection of client */
 | 
					/* setup for RDMA connection of client */
 | 
				
			||||||
| 
						 | 
					@ -747,7 +751,8 @@ static int smc_connect_rdma(struct smc_sock *smc,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	smc_rmb_sync_sg_for_device(&smc->conn);
 | 
						smc_rmb_sync_sg_for_device(&smc->conn);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	reason_code = smc_clc_send_confirm(smc);
 | 
						reason_code = smc_clc_send_confirm(smc, ini->first_contact_local,
 | 
				
			||||||
 | 
										   SMC_V1);
 | 
				
			||||||
	if (reason_code)
 | 
						if (reason_code)
 | 
				
			||||||
		return smc_connect_abort(smc, reason_code,
 | 
							return smc_connect_abort(smc, reason_code,
 | 
				
			||||||
					 ini->first_contact_local);
 | 
										 ini->first_contact_local);
 | 
				
			||||||
| 
						 | 
					@ -773,6 +778,25 @@ static int smc_connect_rdma(struct smc_sock *smc,
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* The server has chosen one of the proposed ISM devices for the communication.
 | 
				
			||||||
 | 
					 * Determine from the CHID of the received CLC ACCEPT the ISM device chosen.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static int
 | 
				
			||||||
 | 
					smc_v2_determine_accepted_chid(struct smc_clc_msg_accept_confirm_v2 *aclc,
 | 
				
			||||||
 | 
								       struct smc_init_info *ini)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 0; i < ini->ism_offered_cnt + 1; i++) {
 | 
				
			||||||
 | 
							if (ini->ism_chid[i] == ntohs(aclc->chid)) {
 | 
				
			||||||
 | 
								ini->ism_selected = i;
 | 
				
			||||||
 | 
								return 0;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return -EPROTO;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* setup for ISM connection of client */
 | 
					/* setup for ISM connection of client */
 | 
				
			||||||
static int smc_connect_ism(struct smc_sock *smc,
 | 
					static int smc_connect_ism(struct smc_sock *smc,
 | 
				
			||||||
			   struct smc_clc_msg_accept_confirm *aclc,
 | 
								   struct smc_clc_msg_accept_confirm *aclc,
 | 
				
			||||||
| 
						 | 
					@ -781,9 +805,18 @@ static int smc_connect_ism(struct smc_sock *smc,
 | 
				
			||||||
	int rc = 0;
 | 
						int rc = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ini->is_smcd = true;
 | 
						ini->is_smcd = true;
 | 
				
			||||||
	ini->ism_peer_gid[0] = aclc->d0.gid;
 | 
					 | 
				
			||||||
	ini->first_contact_peer = aclc->hdr.typev2 & SMC_FIRST_CONTACT_MASK;
 | 
						ini->first_contact_peer = aclc->hdr.typev2 & SMC_FIRST_CONTACT_MASK;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (aclc->hdr.version == SMC_V2) {
 | 
				
			||||||
 | 
							struct smc_clc_msg_accept_confirm_v2 *aclc_v2 =
 | 
				
			||||||
 | 
								(struct smc_clc_msg_accept_confirm_v2 *)aclc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							rc = smc_v2_determine_accepted_chid(aclc_v2, ini);
 | 
				
			||||||
 | 
							if (rc)
 | 
				
			||||||
 | 
								return rc;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						ini->ism_peer_gid[ini->ism_selected] = aclc->d0.gid;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* there is only one lgr role for SMC-D; use server lock */
 | 
						/* there is only one lgr role for SMC-D; use server lock */
 | 
				
			||||||
	mutex_lock(&smc_server_lgr_pending);
 | 
						mutex_lock(&smc_server_lgr_pending);
 | 
				
			||||||
	rc = smc_conn_create(smc, ini);
 | 
						rc = smc_conn_create(smc, ini);
 | 
				
			||||||
| 
						 | 
					@ -805,7 +838,8 @@ static int smc_connect_ism(struct smc_sock *smc,
 | 
				
			||||||
	smc_rx_init(smc);
 | 
						smc_rx_init(smc);
 | 
				
			||||||
	smc_tx_init(smc);
 | 
						smc_tx_init(smc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rc = smc_clc_send_confirm(smc);
 | 
						rc = smc_clc_send_confirm(smc, ini->first_contact_local,
 | 
				
			||||||
 | 
									  aclc->hdr.version);
 | 
				
			||||||
	if (rc)
 | 
						if (rc)
 | 
				
			||||||
		return smc_connect_abort(smc, rc, ini->first_contact_local);
 | 
							return smc_connect_abort(smc, rc, ini->first_contact_local);
 | 
				
			||||||
	mutex_unlock(&smc_server_lgr_pending);
 | 
						mutex_unlock(&smc_server_lgr_pending);
 | 
				
			||||||
| 
						 | 
					@ -825,7 +859,12 @@ static int smc_connect_check_aclc(struct smc_init_info *ini,
 | 
				
			||||||
	if ((aclc->hdr.typev1 == SMC_TYPE_R &&
 | 
						if ((aclc->hdr.typev1 == SMC_TYPE_R &&
 | 
				
			||||||
	     !smcr_indicated(ini->smc_type_v1)) ||
 | 
						     !smcr_indicated(ini->smc_type_v1)) ||
 | 
				
			||||||
	    (aclc->hdr.typev1 == SMC_TYPE_D &&
 | 
						    (aclc->hdr.typev1 == SMC_TYPE_D &&
 | 
				
			||||||
	     !smcd_indicated(ini->smc_type_v1)))
 | 
						     ((!smcd_indicated(ini->smc_type_v1) &&
 | 
				
			||||||
 | 
						       !smcd_indicated(ini->smc_type_v2)) ||
 | 
				
			||||||
 | 
						      (aclc->hdr.version == SMC_V1 &&
 | 
				
			||||||
 | 
						       !smcd_indicated(ini->smc_type_v1)) ||
 | 
				
			||||||
 | 
						      (aclc->hdr.version == SMC_V2 &&
 | 
				
			||||||
 | 
						       !smcd_indicated(ini->smc_type_v2)))))
 | 
				
			||||||
		return SMC_CLC_DECL_MODEUNSUPP;
 | 
							return SMC_CLC_DECL_MODEUNSUPP;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
| 
						 | 
					@ -834,8 +873,10 @@ static int smc_connect_check_aclc(struct smc_init_info *ini,
 | 
				
			||||||
/* perform steps before actually connecting */
 | 
					/* perform steps before actually connecting */
 | 
				
			||||||
static int __smc_connect(struct smc_sock *smc)
 | 
					static int __smc_connect(struct smc_sock *smc)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct smc_clc_msg_accept_confirm aclc;
 | 
						struct smc_clc_msg_accept_confirm_v2 *aclc2;
 | 
				
			||||||
 | 
						struct smc_clc_msg_accept_confirm *aclc;
 | 
				
			||||||
	struct smc_init_info *ini = NULL;
 | 
						struct smc_init_info *ini = NULL;
 | 
				
			||||||
 | 
						u8 *buf = NULL;
 | 
				
			||||||
	int rc = 0;
 | 
						int rc = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (smc->use_fallback)
 | 
						if (smc->use_fallback)
 | 
				
			||||||
| 
						 | 
					@ -872,30 +913,40 @@ static int __smc_connect(struct smc_sock *smc)
 | 
				
			||||||
	if (rc)
 | 
						if (rc)
 | 
				
			||||||
		goto fallback;
 | 
							goto fallback;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						buf = kzalloc(SMC_CLC_MAX_ACCEPT_LEN, GFP_KERNEL);
 | 
				
			||||||
 | 
						if (!buf) {
 | 
				
			||||||
 | 
							rc = SMC_CLC_DECL_MEM;
 | 
				
			||||||
 | 
							goto fallback;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						aclc2 = (struct smc_clc_msg_accept_confirm_v2 *)buf;
 | 
				
			||||||
 | 
						aclc = (struct smc_clc_msg_accept_confirm *)aclc2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* perform CLC handshake */
 | 
						/* perform CLC handshake */
 | 
				
			||||||
	rc = smc_connect_clc(smc, &aclc, ini);
 | 
						rc = smc_connect_clc(smc, aclc2, ini);
 | 
				
			||||||
	if (rc)
 | 
						if (rc)
 | 
				
			||||||
		goto vlan_cleanup;
 | 
							goto vlan_cleanup;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* check if smc modes and versions of CLC proposal and accept match */
 | 
						/* check if smc modes and versions of CLC proposal and accept match */
 | 
				
			||||||
	rc = smc_connect_check_aclc(ini, &aclc);
 | 
						rc = smc_connect_check_aclc(ini, aclc);
 | 
				
			||||||
	if (rc)
 | 
						if (rc)
 | 
				
			||||||
		goto vlan_cleanup;
 | 
							goto vlan_cleanup;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* depending on previous steps, connect using rdma or ism */
 | 
						/* depending on previous steps, connect using rdma or ism */
 | 
				
			||||||
	if (aclc.hdr.typev1 == SMC_TYPE_R)
 | 
						if (aclc->hdr.typev1 == SMC_TYPE_R)
 | 
				
			||||||
		rc = smc_connect_rdma(smc, &aclc, ini);
 | 
							rc = smc_connect_rdma(smc, aclc, ini);
 | 
				
			||||||
	else if (aclc.hdr.typev1 == SMC_TYPE_D)
 | 
						else if (aclc->hdr.typev1 == SMC_TYPE_D)
 | 
				
			||||||
		rc = smc_connect_ism(smc, &aclc, ini);
 | 
							rc = smc_connect_ism(smc, aclc, ini);
 | 
				
			||||||
	if (rc)
 | 
						if (rc)
 | 
				
			||||||
		goto vlan_cleanup;
 | 
							goto vlan_cleanup;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	smc_connect_ism_vlan_cleanup(smc, ini);
 | 
						smc_connect_ism_vlan_cleanup(smc, ini);
 | 
				
			||||||
 | 
						kfree(buf);
 | 
				
			||||||
	kfree(ini);
 | 
						kfree(ini);
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
vlan_cleanup:
 | 
					vlan_cleanup:
 | 
				
			||||||
	smc_connect_ism_vlan_cleanup(smc, ini);
 | 
						smc_connect_ism_vlan_cleanup(smc, ini);
 | 
				
			||||||
 | 
						kfree(buf);
 | 
				
			||||||
fallback:
 | 
					fallback:
 | 
				
			||||||
	kfree(ini);
 | 
						kfree(ini);
 | 
				
			||||||
	return smc_connect_decline_fallback(smc, rc);
 | 
						return smc_connect_decline_fallback(smc, rc);
 | 
				
			||||||
| 
						 | 
					@ -1214,10 +1265,10 @@ static void smc_listen_out_err(struct smc_sock *new_smc)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* listen worker: decline and fall back if possible */
 | 
					/* listen worker: decline and fall back if possible */
 | 
				
			||||||
static void smc_listen_decline(struct smc_sock *new_smc, int reason_code,
 | 
					static void smc_listen_decline(struct smc_sock *new_smc, int reason_code,
 | 
				
			||||||
			       bool local_first)
 | 
								       struct smc_init_info *ini)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	/* RDMA setup failed, switch back to TCP */
 | 
						/* RDMA setup failed, switch back to TCP */
 | 
				
			||||||
	if (local_first)
 | 
						if (ini->first_contact_local)
 | 
				
			||||||
		smc_lgr_cleanup_early(&new_smc->conn);
 | 
							smc_lgr_cleanup_early(&new_smc->conn);
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
		smc_conn_free(&new_smc->conn);
 | 
							smc_conn_free(&new_smc->conn);
 | 
				
			||||||
| 
						 | 
					@ -1560,7 +1611,8 @@ static void smc_listen_work(struct work_struct *work)
 | 
				
			||||||
	struct smc_sock *new_smc = container_of(work, struct smc_sock,
 | 
						struct smc_sock *new_smc = container_of(work, struct smc_sock,
 | 
				
			||||||
						smc_listen_work);
 | 
											smc_listen_work);
 | 
				
			||||||
	struct socket *newclcsock = new_smc->clcsock;
 | 
						struct socket *newclcsock = new_smc->clcsock;
 | 
				
			||||||
	struct smc_clc_msg_accept_confirm cclc;
 | 
						struct smc_clc_msg_accept_confirm_v2 *cclc2;
 | 
				
			||||||
 | 
						struct smc_clc_msg_accept_confirm *cclc;
 | 
				
			||||||
	struct smc_clc_msg_proposal_area *buf;
 | 
						struct smc_clc_msg_proposal_area *buf;
 | 
				
			||||||
	struct smc_clc_msg_proposal *pclc;
 | 
						struct smc_clc_msg_proposal *pclc;
 | 
				
			||||||
	struct smc_init_info *ini = NULL;
 | 
						struct smc_init_info *ini = NULL;
 | 
				
			||||||
| 
						 | 
					@ -1624,7 +1676,8 @@ static void smc_listen_work(struct work_struct *work)
 | 
				
			||||||
		goto out_unlock;
 | 
							goto out_unlock;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* send SMC Accept CLC message */
 | 
						/* send SMC Accept CLC message */
 | 
				
			||||||
	rc = smc_clc_send_accept(new_smc, ini->first_contact_local);
 | 
						rc = smc_clc_send_accept(new_smc, ini->first_contact_local,
 | 
				
			||||||
 | 
									 ini->smcd_version == SMC_V2 ? SMC_V2 : SMC_V1);
 | 
				
			||||||
	if (rc)
 | 
						if (rc)
 | 
				
			||||||
		goto out_unlock;
 | 
							goto out_unlock;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1633,7 +1686,11 @@ static void smc_listen_work(struct work_struct *work)
 | 
				
			||||||
		mutex_unlock(&smc_server_lgr_pending);
 | 
							mutex_unlock(&smc_server_lgr_pending);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* receive SMC Confirm CLC message */
 | 
						/* receive SMC Confirm CLC message */
 | 
				
			||||||
	rc = smc_clc_wait_msg(new_smc, &cclc, sizeof(cclc),
 | 
						cclc2 = (struct smc_clc_msg_accept_confirm_v2 *)buf;
 | 
				
			||||||
 | 
						cclc = (struct smc_clc_msg_accept_confirm *)cclc2;
 | 
				
			||||||
 | 
						memset(buf, 0, sizeof(struct smc_clc_msg_proposal_area));
 | 
				
			||||||
 | 
						rc = smc_clc_wait_msg(new_smc, cclc2,
 | 
				
			||||||
 | 
								      sizeof(struct smc_clc_msg_proposal_area),
 | 
				
			||||||
			      SMC_CLC_CONFIRM, CLC_WAIT_TIME);
 | 
								      SMC_CLC_CONFIRM, CLC_WAIT_TIME);
 | 
				
			||||||
	if (rc) {
 | 
						if (rc) {
 | 
				
			||||||
		if (!ini->is_smcd)
 | 
							if (!ini->is_smcd)
 | 
				
			||||||
| 
						 | 
					@ -1643,20 +1700,20 @@ static void smc_listen_work(struct work_struct *work)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* finish worker */
 | 
						/* finish worker */
 | 
				
			||||||
	if (!ini->is_smcd) {
 | 
						if (!ini->is_smcd) {
 | 
				
			||||||
		rc = smc_listen_rdma_finish(new_smc, &cclc,
 | 
							rc = smc_listen_rdma_finish(new_smc, cclc,
 | 
				
			||||||
					    ini->first_contact_local);
 | 
										    ini->first_contact_local);
 | 
				
			||||||
		if (rc)
 | 
							if (rc)
 | 
				
			||||||
			goto out_unlock;
 | 
								goto out_unlock;
 | 
				
			||||||
		mutex_unlock(&smc_server_lgr_pending);
 | 
							mutex_unlock(&smc_server_lgr_pending);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	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);
 | 
				
			||||||
	goto out_free;
 | 
						goto out_free;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
out_unlock:
 | 
					out_unlock:
 | 
				
			||||||
	mutex_unlock(&smc_server_lgr_pending);
 | 
						mutex_unlock(&smc_server_lgr_pending);
 | 
				
			||||||
out_decl:
 | 
					out_decl:
 | 
				
			||||||
	smc_listen_decline(new_smc, rc, ini ? ini->first_contact_local : 0);
 | 
						smc_listen_decline(new_smc, rc, ini);
 | 
				
			||||||
out_free:
 | 
					out_free:
 | 
				
			||||||
	kfree(ini);
 | 
						kfree(ini);
 | 
				
			||||||
	kfree(buf);
 | 
						kfree(buf);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -27,6 +27,7 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define SMCR_CLC_ACCEPT_CONFIRM_LEN 68
 | 
					#define SMCR_CLC_ACCEPT_CONFIRM_LEN 68
 | 
				
			||||||
#define SMCD_CLC_ACCEPT_CONFIRM_LEN 48
 | 
					#define SMCD_CLC_ACCEPT_CONFIRM_LEN 48
 | 
				
			||||||
 | 
					#define SMCD_CLC_ACCEPT_CONFIRM_LEN_V2 78
 | 
				
			||||||
#define SMC_CLC_RECV_BUF_LEN	100
 | 
					#define SMC_CLC_RECV_BUF_LEN	100
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* eye catcher "SMCR" EBCDIC for CLC messages */
 | 
					/* eye catcher "SMCR" EBCDIC for CLC messages */
 | 
				
			||||||
| 
						 | 
					@ -75,12 +76,34 @@ static bool smc_clc_msg_prop_valid(struct smc_clc_msg_proposal *pclc)
 | 
				
			||||||
	return true;
 | 
						return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* check arriving CLC accept or confirm */
 | 
				
			||||||
 | 
					static bool
 | 
				
			||||||
 | 
					smc_clc_msg_acc_conf_valid(struct smc_clc_msg_accept_confirm_v2 *clc_v2)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct smc_clc_msg_hdr *hdr = &clc_v2->hdr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (hdr->typev1 != SMC_TYPE_R && hdr->typev1 != SMC_TYPE_D)
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						if (hdr->version == SMC_V1) {
 | 
				
			||||||
 | 
							if ((hdr->typev1 == SMC_TYPE_R &&
 | 
				
			||||||
 | 
							     ntohs(hdr->length) != SMCR_CLC_ACCEPT_CONFIRM_LEN) ||
 | 
				
			||||||
 | 
							    (hdr->typev1 == SMC_TYPE_D &&
 | 
				
			||||||
 | 
							     ntohs(hdr->length) != SMCD_CLC_ACCEPT_CONFIRM_LEN))
 | 
				
			||||||
 | 
								return false;
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							if (hdr->typev1 == SMC_TYPE_D &&
 | 
				
			||||||
 | 
							    ntohs(hdr->length) != SMCD_CLC_ACCEPT_CONFIRM_LEN_V2)
 | 
				
			||||||
 | 
								return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* check if received message has a correct header length and contains valid
 | 
					/* check if received message has a correct header length and contains valid
 | 
				
			||||||
 * heading and trailing eyecatchers
 | 
					 * heading and trailing eyecatchers
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static bool smc_clc_msg_hdr_valid(struct smc_clc_msg_hdr *clcm, bool check_trl)
 | 
					static bool smc_clc_msg_hdr_valid(struct smc_clc_msg_hdr *clcm, bool check_trl)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct smc_clc_msg_accept_confirm *clc;
 | 
						struct smc_clc_msg_accept_confirm_v2 *clc_v2;
 | 
				
			||||||
	struct smc_clc_msg_proposal *pclc;
 | 
						struct smc_clc_msg_proposal *pclc;
 | 
				
			||||||
	struct smc_clc_msg_decline *dclc;
 | 
						struct smc_clc_msg_decline *dclc;
 | 
				
			||||||
	struct smc_clc_msg_trail *trl;
 | 
						struct smc_clc_msg_trail *trl;
 | 
				
			||||||
| 
						 | 
					@ -98,16 +121,12 @@ static bool smc_clc_msg_hdr_valid(struct smc_clc_msg_hdr *clcm, bool check_trl)
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case SMC_CLC_ACCEPT:
 | 
						case SMC_CLC_ACCEPT:
 | 
				
			||||||
	case SMC_CLC_CONFIRM:
 | 
						case SMC_CLC_CONFIRM:
 | 
				
			||||||
		if (clcm->typev1 != SMC_TYPE_R && clcm->typev1 != SMC_TYPE_D)
 | 
							clc_v2 = (struct smc_clc_msg_accept_confirm_v2 *)clcm;
 | 
				
			||||||
			return false;
 | 
							if (!smc_clc_msg_acc_conf_valid(clc_v2))
 | 
				
			||||||
		clc = (struct smc_clc_msg_accept_confirm *)clcm;
 | 
					 | 
				
			||||||
		if ((clcm->typev1 == SMC_TYPE_R &&
 | 
					 | 
				
			||||||
		     ntohs(clc->hdr.length) != SMCR_CLC_ACCEPT_CONFIRM_LEN) ||
 | 
					 | 
				
			||||||
		    (clcm->typev1 == SMC_TYPE_D &&
 | 
					 | 
				
			||||||
		     ntohs(clc->hdr.length) != SMCD_CLC_ACCEPT_CONFIRM_LEN))
 | 
					 | 
				
			||||||
			return false;
 | 
								return false;
 | 
				
			||||||
		trl = (struct smc_clc_msg_trail *)
 | 
							trl = (struct smc_clc_msg_trail *)
 | 
				
			||||||
			((u8 *)clc + ntohs(clc->hdr.length) - sizeof(*trl));
 | 
								((u8 *)clc_v2 + ntohs(clc_v2->hdr.length) -
 | 
				
			||||||
 | 
												sizeof(*trl));
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case SMC_CLC_DECLINE:
 | 
						case SMC_CLC_DECLINE:
 | 
				
			||||||
		dclc = (struct smc_clc_msg_decline *)clcm;
 | 
							dclc = (struct smc_clc_msg_decline *)clcm;
 | 
				
			||||||
| 
						 | 
					@ -599,17 +618,19 @@ int smc_clc_send_proposal(struct smc_sock *smc, struct smc_init_info *ini)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* build and send CLC CONFIRM / ACCEPT message */
 | 
					/* build and send CLC CONFIRM / ACCEPT message */
 | 
				
			||||||
static int smc_clc_send_confirm_accept(struct smc_sock *smc,
 | 
					static int smc_clc_send_confirm_accept(struct smc_sock *smc,
 | 
				
			||||||
				       struct smc_clc_msg_accept_confirm *clc,
 | 
									       struct smc_clc_msg_accept_confirm_v2 *clc_v2,
 | 
				
			||||||
				       int first_contact)
 | 
									       int first_contact, u8 version)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct smc_connection *conn = &smc->conn;
 | 
						struct smc_connection *conn = &smc->conn;
 | 
				
			||||||
 | 
						struct smc_clc_msg_accept_confirm *clc;
 | 
				
			||||||
	struct smc_clc_msg_trail trl;
 | 
						struct smc_clc_msg_trail trl;
 | 
				
			||||||
	struct kvec vec[2];
 | 
						struct kvec vec[2];
 | 
				
			||||||
	struct msghdr msg;
 | 
						struct msghdr msg;
 | 
				
			||||||
	int i;
 | 
						int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* send SMC Confirm CLC msg */
 | 
						/* send SMC Confirm CLC msg */
 | 
				
			||||||
	clc->hdr.version = SMC_V1;		/* SMC version */
 | 
						clc = (struct smc_clc_msg_accept_confirm *)clc_v2;
 | 
				
			||||||
 | 
						clc->hdr.version = version;	/* SMC version */
 | 
				
			||||||
	if (first_contact)
 | 
						if (first_contact)
 | 
				
			||||||
		clc->hdr.typev2 |= SMC_FIRST_CONTACT_MASK;
 | 
							clc->hdr.typev2 |= SMC_FIRST_CONTACT_MASK;
 | 
				
			||||||
	if (conn->lgr->is_smcd) {
 | 
						if (conn->lgr->is_smcd) {
 | 
				
			||||||
| 
						 | 
					@ -617,12 +638,23 @@ static int smc_clc_send_confirm_accept(struct smc_sock *smc,
 | 
				
			||||||
		memcpy(clc->hdr.eyecatcher, SMCD_EYECATCHER,
 | 
							memcpy(clc->hdr.eyecatcher, SMCD_EYECATCHER,
 | 
				
			||||||
		       sizeof(SMCD_EYECATCHER));
 | 
							       sizeof(SMCD_EYECATCHER));
 | 
				
			||||||
		clc->hdr.typev1 = SMC_TYPE_D;
 | 
							clc->hdr.typev1 = SMC_TYPE_D;
 | 
				
			||||||
		clc->hdr.length = htons(SMCD_CLC_ACCEPT_CONFIRM_LEN);
 | 
					 | 
				
			||||||
		clc->d0.gid = conn->lgr->smcd->local_gid;
 | 
							clc->d0.gid = conn->lgr->smcd->local_gid;
 | 
				
			||||||
		clc->d0.token = conn->rmb_desc->token;
 | 
							clc->d0.token = conn->rmb_desc->token;
 | 
				
			||||||
		clc->d0.dmbe_size = conn->rmbe_size_short;
 | 
							clc->d0.dmbe_size = conn->rmbe_size_short;
 | 
				
			||||||
		clc->d0.dmbe_idx = 0;
 | 
							clc->d0.dmbe_idx = 0;
 | 
				
			||||||
		memcpy(&clc->d0.linkid, conn->lgr->id, SMC_LGR_ID_SIZE);
 | 
							memcpy(&clc->d0.linkid, conn->lgr->id, SMC_LGR_ID_SIZE);
 | 
				
			||||||
 | 
							if (version == SMC_V1) {
 | 
				
			||||||
 | 
								clc->hdr.length = htons(SMCD_CLC_ACCEPT_CONFIRM_LEN);
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								u8 *eid = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								clc_v2->chid = htons(smc_ism_get_chid(conn->lgr->smcd));
 | 
				
			||||||
 | 
								smc_ism_get_system_eid(conn->lgr->smcd, &eid);
 | 
				
			||||||
 | 
								if (eid)
 | 
				
			||||||
 | 
									memcpy(clc_v2->eid, eid, SMC_MAX_EID_LEN);
 | 
				
			||||||
 | 
								clc_v2->hdr.length =
 | 
				
			||||||
 | 
										htons(SMCD_CLC_ACCEPT_CONFIRM_LEN_V2);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		memcpy(trl.eyecatcher, SMCD_EYECATCHER,
 | 
							memcpy(trl.eyecatcher, SMCD_EYECATCHER,
 | 
				
			||||||
		       sizeof(SMCD_EYECATCHER));
 | 
							       sizeof(SMCD_EYECATCHER));
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
| 
						 | 
					@ -661,7 +693,10 @@ static int smc_clc_send_confirm_accept(struct smc_sock *smc,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	memset(&msg, 0, sizeof(msg));
 | 
						memset(&msg, 0, sizeof(msg));
 | 
				
			||||||
	i = 0;
 | 
						i = 0;
 | 
				
			||||||
	vec[i].iov_base = clc;
 | 
						vec[i].iov_base = clc_v2;
 | 
				
			||||||
 | 
						if (version > SMC_V1)
 | 
				
			||||||
 | 
							vec[i++].iov_len = SMCD_CLC_ACCEPT_CONFIRM_LEN_V2 - sizeof(trl);
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
		vec[i++].iov_len = (clc->hdr.typev1 == SMC_TYPE_D ?
 | 
							vec[i++].iov_len = (clc->hdr.typev1 == SMC_TYPE_D ?
 | 
				
			||||||
						SMCD_CLC_ACCEPT_CONFIRM_LEN :
 | 
											SMCD_CLC_ACCEPT_CONFIRM_LEN :
 | 
				
			||||||
						SMCR_CLC_ACCEPT_CONFIRM_LEN) -
 | 
											SMCR_CLC_ACCEPT_CONFIRM_LEN) -
 | 
				
			||||||
| 
						 | 
					@ -673,17 +708,19 @@ static int smc_clc_send_confirm_accept(struct smc_sock *smc,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* send CLC CONFIRM message across internal TCP socket */
 | 
					/* send CLC CONFIRM message across internal TCP socket */
 | 
				
			||||||
int smc_clc_send_confirm(struct smc_sock *smc)
 | 
					int smc_clc_send_confirm(struct smc_sock *smc, bool clnt_first_contact,
 | 
				
			||||||
 | 
								 u8 version)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct smc_clc_msg_accept_confirm cclc;
 | 
						struct smc_clc_msg_accept_confirm_v2 cclc_v2;
 | 
				
			||||||
	int reason_code = 0;
 | 
						int reason_code = 0;
 | 
				
			||||||
	int len;
 | 
						int len;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* send SMC Confirm CLC msg */
 | 
						/* send SMC Confirm CLC msg */
 | 
				
			||||||
	memset(&cclc, 0, sizeof(cclc));
 | 
						memset(&cclc_v2, 0, sizeof(cclc_v2));
 | 
				
			||||||
	cclc.hdr.type = SMC_CLC_CONFIRM;
 | 
						cclc_v2.hdr.type = SMC_CLC_CONFIRM;
 | 
				
			||||||
	len = smc_clc_send_confirm_accept(smc, &cclc, 0);
 | 
						len = smc_clc_send_confirm_accept(smc, &cclc_v2, clnt_first_contact,
 | 
				
			||||||
	if (len < ntohs(cclc.hdr.length)) {
 | 
										  version);
 | 
				
			||||||
 | 
						if (len < ntohs(cclc_v2.hdr.length)) {
 | 
				
			||||||
		if (len >= 0) {
 | 
							if (len >= 0) {
 | 
				
			||||||
			reason_code = -ENETUNREACH;
 | 
								reason_code = -ENETUNREACH;
 | 
				
			||||||
			smc->sk.sk_err = -reason_code;
 | 
								smc->sk.sk_err = -reason_code;
 | 
				
			||||||
| 
						 | 
					@ -696,15 +733,17 @@ int smc_clc_send_confirm(struct smc_sock *smc)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* send CLC ACCEPT message across internal TCP socket */
 | 
					/* send CLC ACCEPT message across internal TCP socket */
 | 
				
			||||||
int smc_clc_send_accept(struct smc_sock *new_smc, bool srv_first_contact)
 | 
					int smc_clc_send_accept(struct smc_sock *new_smc, bool srv_first_contact,
 | 
				
			||||||
 | 
								u8 version)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct smc_clc_msg_accept_confirm aclc;
 | 
						struct smc_clc_msg_accept_confirm_v2 aclc_v2;
 | 
				
			||||||
	int len;
 | 
						int len;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	memset(&aclc, 0, sizeof(aclc));
 | 
						memset(&aclc_v2, 0, sizeof(aclc_v2));
 | 
				
			||||||
	aclc.hdr.type = SMC_CLC_ACCEPT;
 | 
						aclc_v2.hdr.type = SMC_CLC_ACCEPT;
 | 
				
			||||||
	len = smc_clc_send_confirm_accept(new_smc, &aclc, srv_first_contact);
 | 
						len = smc_clc_send_confirm_accept(new_smc, &aclc_v2, srv_first_contact,
 | 
				
			||||||
	if (len < ntohs(aclc.hdr.length))
 | 
										  version);
 | 
				
			||||||
 | 
						if (len < ntohs(aclc_v2.hdr.length))
 | 
				
			||||||
		len = len >= 0 ? -EPROTO : -new_smc->clcsock->sk->sk_err;
 | 
							len = len >= 0 ? -EPROTO : -new_smc->clcsock->sk->sk_err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return len > 0 ? 0 : len;
 | 
						return len > 0 ? 0 : len;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -184,7 +184,7 @@ struct smcr_clc_msg_accept_confirm {	/* SMCR accept/confirm */
 | 
				
			||||||
	u8 psn[3];		/* packet sequence number */
 | 
						u8 psn[3];		/* packet sequence number */
 | 
				
			||||||
} __packed;
 | 
					} __packed;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct smcd_clc_msg_accept_confirm {	/* SMCD accept/confirm */
 | 
					struct smcd_clc_msg_accept_confirm_common {	/* SMCD accept/confirm */
 | 
				
			||||||
	u64 gid;		/* Sender GID */
 | 
						u64 gid;		/* Sender GID */
 | 
				
			||||||
	u64 token;		/* DMB token */
 | 
						u64 token;		/* DMB token */
 | 
				
			||||||
	u8 dmbe_idx;		/* DMBE index */
 | 
						u8 dmbe_idx;		/* DMBE index */
 | 
				
			||||||
| 
						 | 
					@ -197,17 +197,32 @@ struct smcd_clc_msg_accept_confirm {	/* SMCD accept/confirm */
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
	u16 reserved4;
 | 
						u16 reserved4;
 | 
				
			||||||
	__be32 linkid;		/* Link identifier */
 | 
						__be32 linkid;		/* Link identifier */
 | 
				
			||||||
	u32 reserved5[3];
 | 
					 | 
				
			||||||
} __packed;
 | 
					} __packed;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct smc_clc_msg_accept_confirm {	/* clc accept / confirm message */
 | 
					struct smc_clc_msg_accept_confirm {	/* clc accept / confirm message */
 | 
				
			||||||
	struct smc_clc_msg_hdr hdr;
 | 
						struct smc_clc_msg_hdr hdr;
 | 
				
			||||||
	union {
 | 
						union {
 | 
				
			||||||
		struct smcr_clc_msg_accept_confirm r0; /* SMC-R */
 | 
							struct smcr_clc_msg_accept_confirm r0; /* SMC-R */
 | 
				
			||||||
		struct smcd_clc_msg_accept_confirm d0; /* SMC-D */
 | 
							struct { /* SMC-D */
 | 
				
			||||||
 | 
								struct smcd_clc_msg_accept_confirm_common d0;
 | 
				
			||||||
 | 
								u32 reserved5[3];
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
} __packed;			/* format defined in RFC7609 */
 | 
					} __packed;			/* format defined in RFC7609 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct smc_clc_msg_accept_confirm_v2 {	/* clc accept / confirm message */
 | 
				
			||||||
 | 
						struct smc_clc_msg_hdr hdr;
 | 
				
			||||||
 | 
						union {
 | 
				
			||||||
 | 
							struct smcr_clc_msg_accept_confirm r0; /* SMC-R */
 | 
				
			||||||
 | 
							struct { /* SMC-D */
 | 
				
			||||||
 | 
								struct smcd_clc_msg_accept_confirm_common d0;
 | 
				
			||||||
 | 
								__be16 chid;
 | 
				
			||||||
 | 
								u8 eid[SMC_MAX_EID_LEN];
 | 
				
			||||||
 | 
								u8 reserved5[8];
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct smc_clc_msg_decline {	/* clc decline message */
 | 
					struct smc_clc_msg_decline {	/* clc decline message */
 | 
				
			||||||
	struct smc_clc_msg_hdr hdr;
 | 
						struct smc_clc_msg_hdr hdr;
 | 
				
			||||||
	u8 id_for_peer[SMC_SYSTEMID_LEN]; /* sender peer_id */
 | 
						u8 id_for_peer[SMC_SYSTEMID_LEN]; /* sender peer_id */
 | 
				
			||||||
| 
						 | 
					@ -285,7 +300,9 @@ int smc_clc_wait_msg(struct smc_sock *smc, void *buf, int buflen,
 | 
				
			||||||
		     u8 expected_type, unsigned long timeout);
 | 
							     u8 expected_type, unsigned long timeout);
 | 
				
			||||||
int smc_clc_send_decline(struct smc_sock *smc, u32 peer_diag_info);
 | 
					int smc_clc_send_decline(struct smc_sock *smc, u32 peer_diag_info);
 | 
				
			||||||
int smc_clc_send_proposal(struct smc_sock *smc, struct smc_init_info *ini);
 | 
					int smc_clc_send_proposal(struct smc_sock *smc, struct smc_init_info *ini);
 | 
				
			||||||
int smc_clc_send_confirm(struct smc_sock *smc);
 | 
					int smc_clc_send_confirm(struct smc_sock *smc, bool clnt_first_contact,
 | 
				
			||||||
int smc_clc_send_accept(struct smc_sock *smc, bool srv_first_contact);
 | 
								 u8 version);
 | 
				
			||||||
 | 
					int smc_clc_send_accept(struct smc_sock *smc, bool srv_first_contact,
 | 
				
			||||||
 | 
								u8 version);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue