net/smc: add SMC-D support in CLC messages

There are two types of SMC: SMC-R and SMC-D. These types are signaled
within the CLC messages during the CLC handshake. This patch adds
support for and checks of the SMC type.

Also, SMC-R and SMC-D need to exchange different information during the
CLC handshake. So, this patch extends the current message formats to
support the SMC-D header fields. The Proposal message can contain both
SMC-R and SMC-D information. The Accept and Confirm messages contain
either SMC-R or SMC-D information.

Signed-off-by: Hans Wippel <hwippel@linux.ibm.com>
Signed-off-by: Ursula Braun <ubraun@linux.ibm.com>
Suggested-by: Thomas Richter <tmricht@linux.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Hans Wippel 2018-06-28 19:05:09 +02:00 committed by David S. Miller
parent 1619f77058
commit c758dfddc1
3 changed files with 206 additions and 79 deletions

View file

@ -451,14 +451,14 @@ static int smc_check_rdma(struct smc_sock *smc, struct smc_ib_device **ibdev,
} }
/* 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, int smc_type,
struct smc_clc_msg_accept_confirm *aclc, struct smc_clc_msg_accept_confirm *aclc,
struct smc_ib_device *ibdev, u8 ibport) struct smc_ib_device *ibdev, u8 ibport)
{ {
int rc = 0; int rc = 0;
/* do inband token exchange */ /* do inband token exchange */
rc = smc_clc_send_proposal(smc, ibdev, ibport); rc = smc_clc_send_proposal(smc, smc_type, ibdev, ibport, NULL);
if (rc) if (rc)
return rc; return rc;
/* receive SMC Accept CLC message */ /* receive SMC Accept CLC message */
@ -564,7 +564,7 @@ static int __smc_connect(struct smc_sock *smc)
return smc_connect_decline_fallback(smc, SMC_CLC_DECL_CNFERR); return smc_connect_decline_fallback(smc, SMC_CLC_DECL_CNFERR);
/* perform CLC handshake */ /* perform CLC handshake */
rc = smc_connect_clc(smc, &aclc, ibdev, ibport); rc = smc_connect_clc(smc, SMC_TYPE_R, &aclc, ibdev, ibport);
if (rc) if (rc)
return smc_connect_decline_fallback(smc, rc); return smc_connect_decline_fallback(smc, rc);
@ -1008,7 +1008,8 @@ static void smc_listen_work(struct work_struct *work)
smc_tx_init(new_smc); smc_tx_init(new_smc);
/* check if RDMA is available */ /* check if RDMA is available */
if (smc_check_rdma(new_smc, &ibdev, &ibport) || if ((pclc->hdr.path != SMC_TYPE_R && pclc->hdr.path != SMC_TYPE_B) ||
smc_check_rdma(new_smc, &ibdev, &ibport) ||
smc_listen_rdma_check(new_smc, pclc) || smc_listen_rdma_check(new_smc, pclc) ||
smc_listen_rdma_init(new_smc, pclc, ibdev, ibport, smc_listen_rdma_init(new_smc, pclc, ibdev, ibport,
&local_contact) || &local_contact) ||

View file

@ -23,9 +23,15 @@
#include "smc_core.h" #include "smc_core.h"
#include "smc_clc.h" #include "smc_clc.h"
#include "smc_ib.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 */ /* eye catcher "SMCR" EBCDIC for CLC messages */
static const char SMC_EYECATCHER[4] = {'\xe2', '\xd4', '\xc3', '\xd9'}; 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 /* check if received message has a correct header length and contains valid
* heading and trailing eyecatchers * 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_decline *dclc;
struct smc_clc_msg_trail *trl; 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; return false;
switch (clcm->type) { switch (clcm->type) {
case SMC_CLC_PROPOSAL: 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 = (struct smc_clc_msg_proposal *)clcm;
pclc_prfx = smc_clc_proposal_get_prefix(pclc); pclc_prfx = smc_clc_proposal_get_prefix(pclc);
if (ntohs(pclc->hdr.length) != if (ntohs(pclc->hdr.length) !=
@ -56,10 +66,16 @@ static bool smc_clc_msg_hdr_valid(struct smc_clc_msg_hdr *clcm)
break; break;
case SMC_CLC_ACCEPT: case SMC_CLC_ACCEPT:
case SMC_CLC_CONFIRM: case SMC_CLC_CONFIRM:
clc = (struct smc_clc_msg_accept_confirm *)clcm; if (clcm->path != SMC_TYPE_R && clcm->path != SMC_TYPE_D)
if (ntohs(clc->hdr.length) != sizeof(*clc))
return false; return false;
trl = &clc->trl; clc = (struct smc_clc_msg_accept_confirm *)clcm;
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 = (struct smc_clc_msg_trail *)
((u8 *)clc + ntohs(clc->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;
@ -70,7 +86,8 @@ static bool smc_clc_msg_hdr_valid(struct smc_clc_msg_hdr *clcm)
default: default:
return false; 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 false;
return true; return true;
} }
@ -295,6 +312,9 @@ int smc_clc_wait_msg(struct smc_sock *smc, void *buf, int buflen,
datlen = ntohs(clcm->length); datlen = ntohs(clcm->length);
if ((len < sizeof(struct smc_clc_msg_hdr)) || if ((len < sizeof(struct smc_clc_msg_hdr)) ||
(datlen > buflen) || (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 != SMC_CLC_DECLINE) &&
(clcm->type != expected_type))) { (clcm->type != expected_type))) {
smc->sk.sk_err = EPROTO; 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 */ /* send CLC PROPOSAL message across internal TCP socket */
int smc_clc_send_proposal(struct smc_sock *smc, int smc_clc_send_proposal(struct smc_sock *smc, int smc_type,
struct smc_ib_device *smcibdev, struct smc_ib_device *ibdev, u8 ibport,
u8 ibport) struct smcd_dev *ismdev)
{ {
struct smc_clc_ipv6_prefix ipv6_prfx[SMC_CLC_MAX_V6_PREFIX]; struct smc_clc_ipv6_prefix ipv6_prfx[SMC_CLC_MAX_V6_PREFIX];
struct smc_clc_msg_proposal_prefix pclc_prfx; 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_proposal pclc;
struct smc_clc_msg_trail trl; struct smc_clc_msg_trail trl;
int len, i, plen, rc; int len, i, plen, rc;
int reason_code = 0; int reason_code = 0;
struct kvec vec[4]; struct kvec vec[5];
struct msghdr msg; struct msghdr msg;
/* retrieve ip prefixes for CLC proposal 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)); memset(&pclc, 0, sizeof(pclc));
memcpy(pclc.hdr.eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER)); memcpy(pclc.hdr.eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER));
pclc.hdr.type = SMC_CLC_PROPOSAL; pclc.hdr.type = SMC_CLC_PROPOSAL;
pclc.hdr.length = htons(plen);
pclc.hdr.version = SMC_CLC_V1; /* SMC version */ pclc.hdr.version = SMC_CLC_V1; /* SMC version */
memcpy(pclc.lcl.id_for_peer, local_systemid, sizeof(local_systemid)); pclc.hdr.path = smc_type;
memcpy(&pclc.lcl.gid, &smcibdev->gid[ibport - 1], SMC_GID_SIZE); if (smc_type == SMC_TYPE_R || smc_type == SMC_TYPE_B) {
memcpy(&pclc.lcl.mac, &smcibdev->mac[ibport - 1], ETH_ALEN); /* 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); 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)); memcpy(trl.eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER));
memset(&msg, 0, sizeof(msg)); memset(&msg, 0, sizeof(msg));
i = 0; i = 0;
vec[i].iov_base = &pclc; vec[i].iov_base = &pclc;
vec[i++].iov_len = sizeof(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_base = &pclc_prfx;
vec[i++].iov_len = sizeof(pclc_prfx); vec[i++].iov_len = sizeof(pclc_prfx);
if (pclc_prfx.ipv6_prefixes_cnt > 0) { if (pclc_prfx.ipv6_prefixes_cnt > 0) {
@ -428,17 +465,36 @@ int smc_clc_send_confirm(struct smc_sock *smc)
struct kvec vec; struct kvec vec;
int len; int len;
link = &conn->lgr->lnk[SMC_SINGLE_LINK];
/* send SMC Confirm CLC msg */ /* send SMC Confirm CLC msg */
memset(&cclc, 0, sizeof(cclc)); memset(&cclc, 0, sizeof(cclc));
memcpy(cclc.hdr.eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER));
cclc.hdr.type = SMC_CLC_CONFIRM; cclc.hdr.type = SMC_CLC_CONFIRM;
cclc.hdr.length = htons(sizeof(cclc));
cclc.hdr.version = SMC_CLC_V1; /* SMC version */ cclc.hdr.version = SMC_CLC_V1; /* SMC version */
memcpy(cclc.lcl.id_for_peer, local_systemid, sizeof(local_systemid)); 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], memcpy(&cclc.lcl.gid, &link->smcibdev->gid[link->ibport - 1],
SMC_GID_SIZE); SMC_GID_SIZE);
memcpy(&cclc.lcl.mac, &link->smcibdev->mac[link->ibport - 1], ETH_ALEN); memcpy(&cclc.lcl.mac, &link->smcibdev->mac[link->ibport - 1],
ETH_ALEN);
hton24(cclc.qpn, link->roce_qp->qp_num); hton24(cclc.qpn, link->roce_qp->qp_num);
cclc.rmb_rkey = cclc.rmb_rkey =
htonl(conn->rmb_desc->mr_rx[SMC_SINGLE_LINK]->rkey); htonl(conn->rmb_desc->mr_rx[SMC_SINGLE_LINK]->rkey);
@ -446,17 +502,19 @@ int smc_clc_send_confirm(struct smc_sock *smc)
cclc.rmbe_alert_token = htonl(conn->alert_token_local); cclc.rmbe_alert_token = htonl(conn->alert_token_local);
cclc.qp_mtu = min(link->path_mtu, link->peer_mtu); cclc.qp_mtu = min(link->path_mtu, link->peer_mtu);
cclc.rmbe_size = conn->rmbe_size_short; cclc.rmbe_size = conn->rmbe_size_short;
cclc.rmb_dma_addr = cpu_to_be64( cclc.rmb_dma_addr = cpu_to_be64((u64)sg_dma_address
(u64)sg_dma_address(conn->rmb_desc->sgt[SMC_SINGLE_LINK].sgl)); (conn->rmb_desc->sgt[SMC_SINGLE_LINK].sgl));
hton24(cclc.psn, link->psn_initial); hton24(cclc.psn, link->psn_initial);
memcpy(cclc.smcr_trl.eyecatcher, SMC_EYECATCHER,
memcpy(cclc.trl.eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER)); sizeof(SMC_EYECATCHER));
}
memset(&msg, 0, sizeof(msg)); memset(&msg, 0, sizeof(msg));
vec.iov_base = &cclc; vec.iov_base = &cclc;
vec.iov_len = sizeof(cclc); vec.iov_len = ntohs(cclc.hdr.length);
len = kernel_sendmsg(smc->clcsock, &msg, &vec, 1, sizeof(cclc)); len = kernel_sendmsg(smc->clcsock, &msg, &vec, 1,
if (len < sizeof(cclc)) { ntohs(cclc.hdr.length));
if (len < ntohs(cclc.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;
@ -479,18 +537,38 @@ int smc_clc_send_accept(struct smc_sock *new_smc, int srv_first_contact)
int rc = 0; int rc = 0;
int len; int len;
link = &conn->lgr->lnk[SMC_SINGLE_LINK];
memset(&aclc, 0, sizeof(aclc)); memset(&aclc, 0, sizeof(aclc));
memcpy(aclc.hdr.eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER));
aclc.hdr.type = SMC_CLC_ACCEPT; aclc.hdr.type = SMC_CLC_ACCEPT;
aclc.hdr.length = htons(sizeof(aclc));
aclc.hdr.version = SMC_CLC_V1; /* SMC version */ aclc.hdr.version = SMC_CLC_V1; /* SMC version */
if (srv_first_contact) if (srv_first_contact)
aclc.hdr.flag = 1; aclc.hdr.flag = 1;
memcpy(aclc.lcl.id_for_peer, local_systemid, sizeof(local_systemid));
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], memcpy(&aclc.lcl.gid, &link->smcibdev->gid[link->ibport - 1],
SMC_GID_SIZE); SMC_GID_SIZE);
memcpy(&aclc.lcl.mac, link->smcibdev->mac[link->ibport - 1], ETH_ALEN); memcpy(&aclc.lcl.mac, link->smcibdev->mac[link->ibport - 1],
ETH_ALEN);
hton24(aclc.qpn, link->roce_qp->qp_num); hton24(aclc.qpn, link->roce_qp->qp_num);
aclc.rmb_rkey = aclc.rmb_rkey =
htonl(conn->rmb_desc->mr_rx[SMC_SINGLE_LINK]->rkey); htonl(conn->rmb_desc->mr_rx[SMC_SINGLE_LINK]->rkey);
@ -498,16 +576,19 @@ int smc_clc_send_accept(struct smc_sock *new_smc, int srv_first_contact)
aclc.rmbe_alert_token = htonl(conn->alert_token_local); aclc.rmbe_alert_token = htonl(conn->alert_token_local);
aclc.qp_mtu = link->path_mtu; aclc.qp_mtu = link->path_mtu;
aclc.rmbe_size = conn->rmbe_size_short, aclc.rmbe_size = conn->rmbe_size_short,
aclc.rmb_dma_addr = cpu_to_be64( aclc.rmb_dma_addr = cpu_to_be64((u64)sg_dma_address
(u64)sg_dma_address(conn->rmb_desc->sgt[SMC_SINGLE_LINK].sgl)); (conn->rmb_desc->sgt[SMC_SINGLE_LINK].sgl));
hton24(aclc.psn, link->psn_initial); hton24(aclc.psn, link->psn_initial);
memcpy(aclc.trl.eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER)); memcpy(aclc.smcr_trl.eyecatcher, SMC_EYECATCHER,
sizeof(SMC_EYECATCHER));
}
memset(&msg, 0, sizeof(msg)); memset(&msg, 0, sizeof(msg));
vec.iov_base = &aclc; vec.iov_base = &aclc;
vec.iov_len = sizeof(aclc); vec.iov_len = ntohs(aclc.hdr.length);
len = kernel_sendmsg(new_smc->clcsock, &msg, &vec, 1, sizeof(aclc)); len = kernel_sendmsg(new_smc->clcsock, &msg, &vec, 1,
if (len < sizeof(aclc)) { ntohs(aclc.hdr.length));
if (len < ntohs(aclc.hdr.length)) {
if (len >= 0) if (len >= 0)
new_smc->sk.sk_err = EPROTO; new_smc->sk.sk_err = EPROTO;
else else

View file

@ -23,6 +23,9 @@
#define SMC_CLC_DECLINE 0x04 #define SMC_CLC_DECLINE 0x04
#define SMC_CLC_V1 0x1 /* SMC version */ #define SMC_CLC_V1 0x1 /* SMC version */
#define SMC_TYPE_R 0 /* SMC-R only */
#define SMC_TYPE_D 1 /* SMC-D only */
#define SMC_TYPE_B 3 /* SMC-R and SMC-D */
#define CLC_WAIT_TIME (6 * HZ) /* max. wait time on clcsock */ #define CLC_WAIT_TIME (6 * HZ) /* max. wait time on clcsock */
#define SMC_CLC_DECL_MEM 0x01010000 /* insufficient memory resources */ #define SMC_CLC_DECL_MEM 0x01010000 /* insufficient memory resources */
#define SMC_CLC_DECL_TIMEOUT 0x02000000 /* timeout */ #define SMC_CLC_DECL_TIMEOUT 0x02000000 /* timeout */
@ -42,9 +45,11 @@ struct smc_clc_msg_hdr { /* header1 of clc messages */
#if defined(__BIG_ENDIAN_BITFIELD) #if defined(__BIG_ENDIAN_BITFIELD)
u8 version : 4, u8 version : 4,
flag : 1, flag : 1,
rsvd : 3; rsvd : 1,
path : 2;
#elif defined(__LITTLE_ENDIAN_BITFIELD) #elif defined(__LITTLE_ENDIAN_BITFIELD)
u8 rsvd : 3, u8 path : 2,
rsvd : 1,
flag : 1, flag : 1,
version : 4; version : 4;
#endif #endif
@ -77,6 +82,11 @@ struct smc_clc_msg_proposal_prefix { /* prefix part of clc proposal message*/
u8 ipv6_prefixes_cnt; /* number of IPv6 prefixes in prefix array */ u8 ipv6_prefixes_cnt; /* number of IPv6 prefixes in prefix array */
} __aligned(4); } __aligned(4);
struct smc_clc_msg_smcd { /* SMC-D GID information */
u64 gid; /* ISM GID of requestor */
u8 res[32];
};
struct smc_clc_msg_proposal { /* clc proposal message sent by Linux */ struct smc_clc_msg_proposal { /* clc proposal message sent by Linux */
struct smc_clc_msg_hdr hdr; struct smc_clc_msg_hdr hdr;
struct smc_clc_msg_local lcl; struct smc_clc_msg_local lcl;
@ -94,13 +104,15 @@ struct smc_clc_msg_proposal { /* clc proposal message sent by Linux */
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 {
struct { /* SMC-R */
struct smc_clc_msg_local lcl; struct smc_clc_msg_local lcl;
u8 qpn[3]; /* QP number */ u8 qpn[3]; /* QP number */
__be32 rmb_rkey; /* RMB rkey */ __be32 rmb_rkey; /* RMB rkey */
u8 rmbe_idx; /* Index of RMBE in RMB */ u8 rmbe_idx; /* Index of RMBE in RMB */
__be32 rmbe_alert_token;/* unique connection id */ __be32 rmbe_alert_token;/* unique connection id */
#if defined(__BIG_ENDIAN_BITFIELD) #if defined(__BIG_ENDIAN_BITFIELD)
u8 rmbe_size : 4, /* RMBE buf size (compressed notation) */ u8 rmbe_size : 4, /* buf size (compressed) */
qp_mtu : 4; /* QP mtu */ qp_mtu : 4; /* QP mtu */
#elif defined(__LITTLE_ENDIAN_BITFIELD) #elif defined(__LITTLE_ENDIAN_BITFIELD)
u8 qp_mtu : 4, u8 qp_mtu : 4,
@ -109,8 +121,28 @@ struct smc_clc_msg_accept_confirm { /* clc accept / confirm message */
u8 reserved; u8 reserved;
__be64 rmb_dma_addr; /* RMB virtual address */ __be64 rmb_dma_addr; /* RMB virtual address */
u8 reserved2; u8 reserved2;
u8 psn[3]; /* initial packet sequence number */ u8 psn[3]; /* packet sequence number */
struct smc_clc_msg_trail trl; /* eye catcher "SMCR" EBCDIC */ struct smc_clc_msg_trail smcr_trl;
/* eye catcher "SMCR" EBCDIC */
} __packed;
struct { /* SMC-D */
u64 gid; /* Sender GID */
u64 token; /* DMB token */
u8 dmbe_idx; /* DMBE index */
#if defined(__BIG_ENDIAN_BITFIELD)
u8 dmbe_size : 4, /* buf size (compressed) */
reserved3 : 4;
#elif defined(__LITTLE_ENDIAN_BITFIELD)
u8 reserved3 : 4,
dmbe_size : 4;
#endif
u16 reserved4;
u32 linkid; /* Link identifier */
u32 reserved5[3];
struct smc_clc_msg_trail smcd_trl;
/* eye catcher "SMCD" EBCDIC */
} __packed;
};
} __packed; /* format defined in RFC7609 */ } __packed; /* format defined in RFC7609 */
struct smc_clc_msg_decline { /* clc decline message */ struct smc_clc_msg_decline { /* clc decline message */
@ -129,13 +161,26 @@ smc_clc_proposal_get_prefix(struct smc_clc_msg_proposal *pclc)
((u8 *)pclc + sizeof(*pclc) + ntohs(pclc->iparea_offset)); ((u8 *)pclc + sizeof(*pclc) + ntohs(pclc->iparea_offset));
} }
/* get SMC-D info from proposal message */
static inline struct smc_clc_msg_smcd *
smc_get_clc_msg_smcd(struct smc_clc_msg_proposal *prop)
{
if (ntohs(prop->iparea_offset) != sizeof(struct smc_clc_msg_smcd))
return NULL;
return (struct smc_clc_msg_smcd *)(prop + 1);
}
struct smcd_dev;
int smc_clc_prfx_match(struct socket *clcsock, int smc_clc_prfx_match(struct socket *clcsock,
struct smc_clc_msg_proposal_prefix *prop); struct smc_clc_msg_proposal_prefix *prop);
int smc_clc_wait_msg(struct smc_sock *smc, void *buf, int buflen, int smc_clc_wait_msg(struct smc_sock *smc, void *buf, int buflen,
u8 expected_type); u8 expected_type);
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_ib_device *smcibdev, int smc_clc_send_proposal(struct smc_sock *smc, int smc_type,
u8 ibport); struct smc_ib_device *smcibdev, u8 ibport,
struct smcd_dev *ismdev);
int smc_clc_send_confirm(struct smc_sock *smc); int smc_clc_send_confirm(struct smc_sock *smc);
int smc_clc_send_accept(struct smc_sock *smc, int srv_first_contact); int smc_clc_send_accept(struct smc_sock *smc, int srv_first_contact);