|
@@ -23,9 +23,15 @@
|
|
|
#include "smc_core.h"
|
|
|
#include "smc_clc.h"
|
|
|
#include "smc_ib.h"
|
|
|
+#include "smc_ism.h"
|
|
|
+
|
|
|
+#define SMCR_CLC_ACCEPT_CONFIRM_LEN 68
|
|
|
+#define SMCD_CLC_ACCEPT_CONFIRM_LEN 48
|
|
|
|
|
|
/* eye catcher "SMCR" EBCDIC for CLC messages */
|
|
|
static const char SMC_EYECATCHER[4] = {'\xe2', '\xd4', '\xc3', '\xd9'};
|
|
|
+/* eye catcher "SMCD" EBCDIC for CLC messages */
|
|
|
+static const char SMCD_EYECATCHER[4] = {'\xe2', '\xd4', '\xc3', '\xc4'};
|
|
|
|
|
|
/* check if received message has a correct header length and contains valid
|
|
|
* heading and trailing eyecatchers
|
|
@@ -38,10 +44,14 @@ static bool smc_clc_msg_hdr_valid(struct smc_clc_msg_hdr *clcm)
|
|
|
struct smc_clc_msg_decline *dclc;
|
|
|
struct smc_clc_msg_trail *trl;
|
|
|
|
|
|
- if (memcmp(clcm->eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER)))
|
|
|
+ if (memcmp(clcm->eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER)) &&
|
|
|
+ memcmp(clcm->eyecatcher, SMCD_EYECATCHER, sizeof(SMCD_EYECATCHER)))
|
|
|
return false;
|
|
|
switch (clcm->type) {
|
|
|
case SMC_CLC_PROPOSAL:
|
|
|
+ if (clcm->path != SMC_TYPE_R && clcm->path != SMC_TYPE_D &&
|
|
|
+ clcm->path != SMC_TYPE_B)
|
|
|
+ return false;
|
|
|
pclc = (struct smc_clc_msg_proposal *)clcm;
|
|
|
pclc_prfx = smc_clc_proposal_get_prefix(pclc);
|
|
|
if (ntohs(pclc->hdr.length) !=
|
|
@@ -56,10 +66,16 @@ static bool smc_clc_msg_hdr_valid(struct smc_clc_msg_hdr *clcm)
|
|
|
break;
|
|
|
case SMC_CLC_ACCEPT:
|
|
|
case SMC_CLC_CONFIRM:
|
|
|
+ if (clcm->path != SMC_TYPE_R && clcm->path != SMC_TYPE_D)
|
|
|
+ return false;
|
|
|
clc = (struct smc_clc_msg_accept_confirm *)clcm;
|
|
|
- if (ntohs(clc->hdr.length) != sizeof(*clc))
|
|
|
+ if ((clcm->path == SMC_TYPE_R &&
|
|
|
+ ntohs(clc->hdr.length) != SMCR_CLC_ACCEPT_CONFIRM_LEN) ||
|
|
|
+ (clcm->path == SMC_TYPE_D &&
|
|
|
+ ntohs(clc->hdr.length) != SMCD_CLC_ACCEPT_CONFIRM_LEN))
|
|
|
return false;
|
|
|
- trl = &clc->trl;
|
|
|
+ trl = (struct smc_clc_msg_trail *)
|
|
|
+ ((u8 *)clc + ntohs(clc->hdr.length) - sizeof(*trl));
|
|
|
break;
|
|
|
case SMC_CLC_DECLINE:
|
|
|
dclc = (struct smc_clc_msg_decline *)clcm;
|
|
@@ -70,7 +86,8 @@ static bool smc_clc_msg_hdr_valid(struct smc_clc_msg_hdr *clcm)
|
|
|
default:
|
|
|
return false;
|
|
|
}
|
|
|
- if (memcmp(trl->eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER)))
|
|
|
+ if (memcmp(trl->eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER)) &&
|
|
|
+ memcmp(trl->eyecatcher, SMCD_EYECATCHER, sizeof(SMCD_EYECATCHER)))
|
|
|
return false;
|
|
|
return true;
|
|
|
}
|
|
@@ -295,6 +312,9 @@ int smc_clc_wait_msg(struct smc_sock *smc, void *buf, int buflen,
|
|
|
datlen = ntohs(clcm->length);
|
|
|
if ((len < sizeof(struct smc_clc_msg_hdr)) ||
|
|
|
(datlen > buflen) ||
|
|
|
+ (clcm->version != SMC_CLC_V1) ||
|
|
|
+ (clcm->path != SMC_TYPE_R && clcm->path != SMC_TYPE_D &&
|
|
|
+ clcm->path != SMC_TYPE_B) ||
|
|
|
((clcm->type != SMC_CLC_DECLINE) &&
|
|
|
(clcm->type != expected_type))) {
|
|
|
smc->sk.sk_err = EPROTO;
|
|
@@ -356,17 +376,18 @@ int smc_clc_send_decline(struct smc_sock *smc, u32 peer_diag_info)
|
|
|
}
|
|
|
|
|
|
/* send CLC PROPOSAL message across internal TCP socket */
|
|
|
-int smc_clc_send_proposal(struct smc_sock *smc,
|
|
|
- struct smc_ib_device *smcibdev,
|
|
|
- u8 ibport)
|
|
|
+int smc_clc_send_proposal(struct smc_sock *smc, int smc_type,
|
|
|
+ struct smc_ib_device *ibdev, u8 ibport,
|
|
|
+ struct smcd_dev *ismdev)
|
|
|
{
|
|
|
struct smc_clc_ipv6_prefix ipv6_prfx[SMC_CLC_MAX_V6_PREFIX];
|
|
|
struct smc_clc_msg_proposal_prefix pclc_prfx;
|
|
|
+ struct smc_clc_msg_smcd pclc_smcd;
|
|
|
struct smc_clc_msg_proposal pclc;
|
|
|
struct smc_clc_msg_trail trl;
|
|
|
int len, i, plen, rc;
|
|
|
int reason_code = 0;
|
|
|
- struct kvec vec[4];
|
|
|
+ struct kvec vec[5];
|
|
|
struct msghdr msg;
|
|
|
|
|
|
/* retrieve ip prefixes for CLC proposal msg */
|
|
@@ -381,18 +402,34 @@ int smc_clc_send_proposal(struct smc_sock *smc,
|
|
|
memset(&pclc, 0, sizeof(pclc));
|
|
|
memcpy(pclc.hdr.eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER));
|
|
|
pclc.hdr.type = SMC_CLC_PROPOSAL;
|
|
|
- pclc.hdr.length = htons(plen);
|
|
|
pclc.hdr.version = SMC_CLC_V1; /* SMC version */
|
|
|
- memcpy(pclc.lcl.id_for_peer, local_systemid, sizeof(local_systemid));
|
|
|
- memcpy(&pclc.lcl.gid, &smcibdev->gid[ibport - 1], SMC_GID_SIZE);
|
|
|
- memcpy(&pclc.lcl.mac, &smcibdev->mac[ibport - 1], ETH_ALEN);
|
|
|
- pclc.iparea_offset = htons(0);
|
|
|
+ pclc.hdr.path = smc_type;
|
|
|
+ if (smc_type == SMC_TYPE_R || smc_type == SMC_TYPE_B) {
|
|
|
+ /* add SMC-R specifics */
|
|
|
+ memcpy(pclc.lcl.id_for_peer, local_systemid,
|
|
|
+ sizeof(local_systemid));
|
|
|
+ memcpy(&pclc.lcl.gid, &ibdev->gid[ibport - 1], SMC_GID_SIZE);
|
|
|
+ memcpy(&pclc.lcl.mac, &ibdev->mac[ibport - 1], ETH_ALEN);
|
|
|
+ pclc.iparea_offset = htons(0);
|
|
|
+ }
|
|
|
+ if (smc_type == SMC_TYPE_D || smc_type == SMC_TYPE_B) {
|
|
|
+ /* add SMC-D specifics */
|
|
|
+ memset(&pclc_smcd, 0, sizeof(pclc_smcd));
|
|
|
+ plen += sizeof(pclc_smcd);
|
|
|
+ pclc.iparea_offset = htons(SMC_CLC_PROPOSAL_MAX_OFFSET);
|
|
|
+ pclc_smcd.gid = ismdev->local_gid;
|
|
|
+ }
|
|
|
+ pclc.hdr.length = htons(plen);
|
|
|
|
|
|
memcpy(trl.eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER));
|
|
|
memset(&msg, 0, sizeof(msg));
|
|
|
i = 0;
|
|
|
vec[i].iov_base = &pclc;
|
|
|
vec[i++].iov_len = sizeof(pclc);
|
|
|
+ if (smc_type == SMC_TYPE_D || smc_type == SMC_TYPE_B) {
|
|
|
+ vec[i].iov_base = &pclc_smcd;
|
|
|
+ vec[i++].iov_len = sizeof(pclc_smcd);
|
|
|
+ }
|
|
|
vec[i].iov_base = &pclc_prfx;
|
|
|
vec[i++].iov_len = sizeof(pclc_prfx);
|
|
|
if (pclc_prfx.ipv6_prefixes_cnt > 0) {
|
|
@@ -428,35 +465,56 @@ int smc_clc_send_confirm(struct smc_sock *smc)
|
|
|
struct kvec vec;
|
|
|
int len;
|
|
|
|
|
|
- link = &conn->lgr->lnk[SMC_SINGLE_LINK];
|
|
|
/* send SMC Confirm CLC msg */
|
|
|
memset(&cclc, 0, sizeof(cclc));
|
|
|
- memcpy(cclc.hdr.eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER));
|
|
|
cclc.hdr.type = SMC_CLC_CONFIRM;
|
|
|
- cclc.hdr.length = htons(sizeof(cclc));
|
|
|
cclc.hdr.version = SMC_CLC_V1; /* SMC version */
|
|
|
- memcpy(cclc.lcl.id_for_peer, local_systemid, sizeof(local_systemid));
|
|
|
- memcpy(&cclc.lcl.gid, &link->smcibdev->gid[link->ibport - 1],
|
|
|
- SMC_GID_SIZE);
|
|
|
- memcpy(&cclc.lcl.mac, &link->smcibdev->mac[link->ibport - 1], ETH_ALEN);
|
|
|
- hton24(cclc.qpn, link->roce_qp->qp_num);
|
|
|
- cclc.rmb_rkey =
|
|
|
- htonl(conn->rmb_desc->mr_rx[SMC_SINGLE_LINK]->rkey);
|
|
|
- cclc.rmbe_idx = 1; /* for now: 1 RMB = 1 RMBE */
|
|
|
- cclc.rmbe_alert_token = htonl(conn->alert_token_local);
|
|
|
- cclc.qp_mtu = min(link->path_mtu, link->peer_mtu);
|
|
|
- cclc.rmbe_size = conn->rmbe_size_short;
|
|
|
- cclc.rmb_dma_addr = cpu_to_be64(
|
|
|
- (u64)sg_dma_address(conn->rmb_desc->sgt[SMC_SINGLE_LINK].sgl));
|
|
|
- hton24(cclc.psn, link->psn_initial);
|
|
|
-
|
|
|
- memcpy(cclc.trl.eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER));
|
|
|
+ if (smc->conn.lgr->is_smcd) {
|
|
|
+ /* SMC-D specific settings */
|
|
|
+ memcpy(cclc.hdr.eyecatcher, SMCD_EYECATCHER,
|
|
|
+ sizeof(SMCD_EYECATCHER));
|
|
|
+ cclc.hdr.path = SMC_TYPE_D;
|
|
|
+ cclc.hdr.length = htons(SMCD_CLC_ACCEPT_CONFIRM_LEN);
|
|
|
+ cclc.gid = conn->lgr->smcd->local_gid;
|
|
|
+ cclc.token = conn->rmb_desc->token;
|
|
|
+ cclc.dmbe_size = conn->rmbe_size_short;
|
|
|
+ cclc.dmbe_idx = 0;
|
|
|
+ memcpy(&cclc.linkid, conn->lgr->id, SMC_LGR_ID_SIZE);
|
|
|
+ memcpy(cclc.smcd_trl.eyecatcher, SMCD_EYECATCHER,
|
|
|
+ sizeof(SMCD_EYECATCHER));
|
|
|
+ } else {
|
|
|
+ /* SMC-R specific settings */
|
|
|
+ link = &conn->lgr->lnk[SMC_SINGLE_LINK];
|
|
|
+ memcpy(cclc.hdr.eyecatcher, SMC_EYECATCHER,
|
|
|
+ sizeof(SMC_EYECATCHER));
|
|
|
+ cclc.hdr.path = SMC_TYPE_R;
|
|
|
+ cclc.hdr.length = htons(SMCR_CLC_ACCEPT_CONFIRM_LEN);
|
|
|
+ memcpy(cclc.lcl.id_for_peer, local_systemid,
|
|
|
+ sizeof(local_systemid));
|
|
|
+ memcpy(&cclc.lcl.gid, &link->smcibdev->gid[link->ibport - 1],
|
|
|
+ SMC_GID_SIZE);
|
|
|
+ memcpy(&cclc.lcl.mac, &link->smcibdev->mac[link->ibport - 1],
|
|
|
+ ETH_ALEN);
|
|
|
+ hton24(cclc.qpn, link->roce_qp->qp_num);
|
|
|
+ cclc.rmb_rkey =
|
|
|
+ htonl(conn->rmb_desc->mr_rx[SMC_SINGLE_LINK]->rkey);
|
|
|
+ cclc.rmbe_idx = 1; /* for now: 1 RMB = 1 RMBE */
|
|
|
+ cclc.rmbe_alert_token = htonl(conn->alert_token_local);
|
|
|
+ cclc.qp_mtu = min(link->path_mtu, link->peer_mtu);
|
|
|
+ cclc.rmbe_size = conn->rmbe_size_short;
|
|
|
+ cclc.rmb_dma_addr = cpu_to_be64((u64)sg_dma_address
|
|
|
+ (conn->rmb_desc->sgt[SMC_SINGLE_LINK].sgl));
|
|
|
+ hton24(cclc.psn, link->psn_initial);
|
|
|
+ memcpy(cclc.smcr_trl.eyecatcher, SMC_EYECATCHER,
|
|
|
+ sizeof(SMC_EYECATCHER));
|
|
|
+ }
|
|
|
|
|
|
memset(&msg, 0, sizeof(msg));
|
|
|
vec.iov_base = &cclc;
|
|
|
- vec.iov_len = sizeof(cclc);
|
|
|
- len = kernel_sendmsg(smc->clcsock, &msg, &vec, 1, sizeof(cclc));
|
|
|
- if (len < sizeof(cclc)) {
|
|
|
+ vec.iov_len = ntohs(cclc.hdr.length);
|
|
|
+ len = kernel_sendmsg(smc->clcsock, &msg, &vec, 1,
|
|
|
+ ntohs(cclc.hdr.length));
|
|
|
+ if (len < ntohs(cclc.hdr.length)) {
|
|
|
if (len >= 0) {
|
|
|
reason_code = -ENETUNREACH;
|
|
|
smc->sk.sk_err = -reason_code;
|
|
@@ -479,35 +537,58 @@ int smc_clc_send_accept(struct smc_sock *new_smc, int srv_first_contact)
|
|
|
int rc = 0;
|
|
|
int len;
|
|
|
|
|
|
- link = &conn->lgr->lnk[SMC_SINGLE_LINK];
|
|
|
memset(&aclc, 0, sizeof(aclc));
|
|
|
- memcpy(aclc.hdr.eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER));
|
|
|
aclc.hdr.type = SMC_CLC_ACCEPT;
|
|
|
- aclc.hdr.length = htons(sizeof(aclc));
|
|
|
aclc.hdr.version = SMC_CLC_V1; /* SMC version */
|
|
|
if (srv_first_contact)
|
|
|
aclc.hdr.flag = 1;
|
|
|
- memcpy(aclc.lcl.id_for_peer, local_systemid, sizeof(local_systemid));
|
|
|
- memcpy(&aclc.lcl.gid, &link->smcibdev->gid[link->ibport - 1],
|
|
|
- SMC_GID_SIZE);
|
|
|
- memcpy(&aclc.lcl.mac, link->smcibdev->mac[link->ibport - 1], ETH_ALEN);
|
|
|
- hton24(aclc.qpn, link->roce_qp->qp_num);
|
|
|
- aclc.rmb_rkey =
|
|
|
- htonl(conn->rmb_desc->mr_rx[SMC_SINGLE_LINK]->rkey);
|
|
|
- aclc.rmbe_idx = 1; /* as long as 1 RMB = 1 RMBE */
|
|
|
- aclc.rmbe_alert_token = htonl(conn->alert_token_local);
|
|
|
- aclc.qp_mtu = link->path_mtu;
|
|
|
- aclc.rmbe_size = conn->rmbe_size_short,
|
|
|
- aclc.rmb_dma_addr = cpu_to_be64(
|
|
|
- (u64)sg_dma_address(conn->rmb_desc->sgt[SMC_SINGLE_LINK].sgl));
|
|
|
- hton24(aclc.psn, link->psn_initial);
|
|
|
- memcpy(aclc.trl.eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER));
|
|
|
+
|
|
|
+ if (new_smc->conn.lgr->is_smcd) {
|
|
|
+ /* SMC-D specific settings */
|
|
|
+ aclc.hdr.length = htons(SMCD_CLC_ACCEPT_CONFIRM_LEN);
|
|
|
+ memcpy(aclc.hdr.eyecatcher, SMCD_EYECATCHER,
|
|
|
+ sizeof(SMCD_EYECATCHER));
|
|
|
+ aclc.hdr.path = SMC_TYPE_D;
|
|
|
+ aclc.gid = conn->lgr->smcd->local_gid;
|
|
|
+ aclc.token = conn->rmb_desc->token;
|
|
|
+ aclc.dmbe_size = conn->rmbe_size_short;
|
|
|
+ aclc.dmbe_idx = 0;
|
|
|
+ memcpy(&aclc.linkid, conn->lgr->id, SMC_LGR_ID_SIZE);
|
|
|
+ memcpy(aclc.smcd_trl.eyecatcher, SMCD_EYECATCHER,
|
|
|
+ sizeof(SMCD_EYECATCHER));
|
|
|
+ } else {
|
|
|
+ /* SMC-R specific settings */
|
|
|
+ aclc.hdr.length = htons(SMCR_CLC_ACCEPT_CONFIRM_LEN);
|
|
|
+ memcpy(aclc.hdr.eyecatcher, SMC_EYECATCHER,
|
|
|
+ sizeof(SMC_EYECATCHER));
|
|
|
+ aclc.hdr.path = SMC_TYPE_R;
|
|
|
+ link = &conn->lgr->lnk[SMC_SINGLE_LINK];
|
|
|
+ memcpy(aclc.lcl.id_for_peer, local_systemid,
|
|
|
+ sizeof(local_systemid));
|
|
|
+ memcpy(&aclc.lcl.gid, &link->smcibdev->gid[link->ibport - 1],
|
|
|
+ SMC_GID_SIZE);
|
|
|
+ memcpy(&aclc.lcl.mac, link->smcibdev->mac[link->ibport - 1],
|
|
|
+ ETH_ALEN);
|
|
|
+ hton24(aclc.qpn, link->roce_qp->qp_num);
|
|
|
+ aclc.rmb_rkey =
|
|
|
+ htonl(conn->rmb_desc->mr_rx[SMC_SINGLE_LINK]->rkey);
|
|
|
+ aclc.rmbe_idx = 1; /* as long as 1 RMB = 1 RMBE */
|
|
|
+ aclc.rmbe_alert_token = htonl(conn->alert_token_local);
|
|
|
+ aclc.qp_mtu = link->path_mtu;
|
|
|
+ aclc.rmbe_size = conn->rmbe_size_short,
|
|
|
+ aclc.rmb_dma_addr = cpu_to_be64((u64)sg_dma_address
|
|
|
+ (conn->rmb_desc->sgt[SMC_SINGLE_LINK].sgl));
|
|
|
+ hton24(aclc.psn, link->psn_initial);
|
|
|
+ memcpy(aclc.smcr_trl.eyecatcher, SMC_EYECATCHER,
|
|
|
+ sizeof(SMC_EYECATCHER));
|
|
|
+ }
|
|
|
|
|
|
memset(&msg, 0, sizeof(msg));
|
|
|
vec.iov_base = &aclc;
|
|
|
- vec.iov_len = sizeof(aclc);
|
|
|
- len = kernel_sendmsg(new_smc->clcsock, &msg, &vec, 1, sizeof(aclc));
|
|
|
- if (len < sizeof(aclc)) {
|
|
|
+ vec.iov_len = ntohs(aclc.hdr.length);
|
|
|
+ len = kernel_sendmsg(new_smc->clcsock, &msg, &vec, 1,
|
|
|
+ ntohs(aclc.hdr.length));
|
|
|
+ if (len < ntohs(aclc.hdr.length)) {
|
|
|
if (len >= 0)
|
|
|
new_smc->sk.sk_err = EPROTO;
|
|
|
else
|