mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-02 01:37:17 -04:00
Merge branch 'smc-features'
Guangguan Wang says: ==================== net/smc: several features's implementation for smc v2.1 This patch set implement several new features in SMC v2.1(https:// www.ibm.com/support/pages/node/7009315), including vendor unique experimental options, max connections per lgr negotiation, max links per lgr negotiation. v1 - v2: - rename field fce_v20 to fce_v2_base in struct smc_clc_first_contact_ext_v2x - use smc_get_clc_first_contact_ext in smc_connect _rdma_v2_prepare - adding comment about field vendor_oui in struct smc_clc_msg_smcd - remove comment about SMC_CONN_PER_LGR_MAX in smc_ clc_srv_v2x_features_validate - rename smc_clc_clnt_v2x_features_validate RFC v2 - v1: - more description in commit message - modify SMC_CONN_PER_LGR_xxx and SMC_LINKS_ADD_LNK_xxx macro defination and usage - rename field release_ver to release_nr - remove redundant release version check in client - explicitly set the rc value in smc_llc_cli/srv_add_link RFC v1 - RFC v2: - Remove ini pointer NULL check and fix code style in smc_clc_send_confirm_accept. - Optimize the max_conns check in smc_clc_xxx_v2x_features_validate. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
@@ -107,6 +107,8 @@ enum {
|
||||
enum {
|
||||
SMC_NLA_LGR_R_V2_UNSPEC,
|
||||
SMC_NLA_LGR_R_V2_DIRECT, /* u8 */
|
||||
SMC_NLA_LGR_R_V2_MAX_CONNS, /* u8 */
|
||||
SMC_NLA_LGR_R_V2_MAX_LINKS, /* u8 */
|
||||
__SMC_NLA_LGR_R_V2_MAX,
|
||||
SMC_NLA_LGR_R_V2_MAX = __SMC_NLA_LGR_R_V2_MAX - 1
|
||||
};
|
||||
|
||||
@@ -641,20 +641,22 @@ static int smcr_clnt_conf_first_link(struct smc_sock *smc)
|
||||
smc_llc_link_active(link);
|
||||
smcr_lgr_set_type(link->lgr, SMC_LGR_SINGLE);
|
||||
|
||||
/* optional 2nd link, receive ADD LINK request from server */
|
||||
qentry = smc_llc_wait(link->lgr, NULL, SMC_LLC_WAIT_TIME,
|
||||
SMC_LLC_ADD_LINK);
|
||||
if (!qentry) {
|
||||
struct smc_clc_msg_decline dclc;
|
||||
if (link->lgr->max_links > 1) {
|
||||
/* optional 2nd link, receive ADD LINK request from server */
|
||||
qentry = smc_llc_wait(link->lgr, NULL, SMC_LLC_WAIT_TIME,
|
||||
SMC_LLC_ADD_LINK);
|
||||
if (!qentry) {
|
||||
struct smc_clc_msg_decline dclc;
|
||||
|
||||
rc = smc_clc_wait_msg(smc, &dclc, sizeof(dclc),
|
||||
SMC_CLC_DECLINE, CLC_WAIT_TIME_SHORT);
|
||||
if (rc == -EAGAIN)
|
||||
rc = 0; /* no DECLINE received, go with one link */
|
||||
return rc;
|
||||
rc = smc_clc_wait_msg(smc, &dclc, sizeof(dclc),
|
||||
SMC_CLC_DECLINE, CLC_WAIT_TIME_SHORT);
|
||||
if (rc == -EAGAIN)
|
||||
rc = 0; /* no DECLINE received, go with one link */
|
||||
return rc;
|
||||
}
|
||||
smc_llc_flow_qentry_clr(&link->lgr->llc_flow_lcl);
|
||||
smc_llc_cli_add_link(link, qentry);
|
||||
}
|
||||
smc_llc_flow_qentry_clr(&link->lgr->llc_flow_lcl);
|
||||
smc_llc_cli_add_link(link, qentry);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1144,7 +1146,7 @@ static int smc_connect_ism_vlan_cleanup(struct smc_sock *smc,
|
||||
|
||||
#define SMC_CLC_MAX_ACCEPT_LEN \
|
||||
(sizeof(struct smc_clc_msg_accept_confirm_v2) + \
|
||||
sizeof(struct smc_clc_first_contact_ext) + \
|
||||
sizeof(struct smc_clc_first_contact_ext_v2x) + \
|
||||
sizeof(struct smc_clc_msg_trail))
|
||||
|
||||
/* CLC handshake during connect */
|
||||
@@ -1198,8 +1200,8 @@ static int smc_connect_rdma_v2_prepare(struct smc_sock *smc,
|
||||
struct smc_clc_msg_accept_confirm_v2 *clc_v2 =
|
||||
(struct smc_clc_msg_accept_confirm_v2 *)aclc;
|
||||
struct smc_clc_first_contact_ext *fce =
|
||||
(struct smc_clc_first_contact_ext *)
|
||||
(((u8 *)clc_v2) + sizeof(*clc_v2));
|
||||
smc_get_clc_first_contact_ext(clc_v2, false);
|
||||
int rc;
|
||||
|
||||
if (!ini->first_contact_peer || aclc->hdr.version == SMC_V1)
|
||||
return 0;
|
||||
@@ -1218,6 +1220,12 @@ static int smc_connect_rdma_v2_prepare(struct smc_sock *smc,
|
||||
return SMC_CLC_DECL_NOINDIRECT;
|
||||
}
|
||||
}
|
||||
|
||||
ini->release_nr = fce->release;
|
||||
rc = smc_clc_clnt_v2x_features_validate(fce, ini);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1236,6 +1244,8 @@ static int smc_connect_rdma(struct smc_sock *smc,
|
||||
memcpy(ini->peer_systemid, aclc->r0.lcl.id_for_peer, SMC_SYSTEMID_LEN);
|
||||
memcpy(ini->peer_gid, aclc->r0.lcl.gid, SMC_GID_SIZE);
|
||||
memcpy(ini->peer_mac, aclc->r0.lcl.mac, ETH_ALEN);
|
||||
ini->max_conns = SMC_CONN_PER_LGR_MAX;
|
||||
ini->max_links = SMC_LINKS_ADD_LNK_MAX;
|
||||
|
||||
reason_code = smc_connect_rdma_v2_prepare(smc, aclc, ini);
|
||||
if (reason_code)
|
||||
@@ -1386,6 +1396,16 @@ static int smc_connect_ism(struct smc_sock *smc,
|
||||
struct smc_clc_msg_accept_confirm_v2 *aclc_v2 =
|
||||
(struct smc_clc_msg_accept_confirm_v2 *)aclc;
|
||||
|
||||
if (ini->first_contact_peer) {
|
||||
struct smc_clc_first_contact_ext *fce =
|
||||
smc_get_clc_first_contact_ext(aclc_v2, true);
|
||||
|
||||
ini->release_nr = fce->release;
|
||||
rc = smc_clc_clnt_v2x_features_validate(fce, ini);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = smc_v2_determine_accepted_chid(aclc_v2, ini);
|
||||
if (rc)
|
||||
return rc;
|
||||
@@ -1420,7 +1440,7 @@ static int smc_connect_ism(struct smc_sock *smc,
|
||||
}
|
||||
|
||||
rc = smc_clc_send_confirm(smc, ini->first_contact_local,
|
||||
aclc->hdr.version, eid, NULL);
|
||||
aclc->hdr.version, eid, ini);
|
||||
if (rc)
|
||||
goto connect_abort;
|
||||
mutex_unlock(&smc_server_lgr_pending);
|
||||
@@ -1870,10 +1890,12 @@ static int smcr_serv_conf_first_link(struct smc_sock *smc)
|
||||
smc_llc_link_active(link);
|
||||
smcr_lgr_set_type(link->lgr, SMC_LGR_SINGLE);
|
||||
|
||||
down_write(&link->lgr->llc_conf_mutex);
|
||||
/* initial contact - try to establish second link */
|
||||
smc_llc_srv_add_link(link, NULL);
|
||||
up_write(&link->lgr->llc_conf_mutex);
|
||||
if (link->lgr->max_links > 1) {
|
||||
down_write(&link->lgr->llc_conf_mutex);
|
||||
/* initial contact - try to establish second link */
|
||||
smc_llc_srv_add_link(link, NULL);
|
||||
up_write(&link->lgr->llc_conf_mutex);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1996,6 +2018,10 @@ static int smc_listen_v2_check(struct smc_sock *new_smc,
|
||||
}
|
||||
}
|
||||
|
||||
ini->release_nr = pclc_v2_ext->hdr.flag.release;
|
||||
if (pclc_v2_ext->hdr.flag.release > SMC_RELEASE)
|
||||
ini->release_nr = SMC_RELEASE;
|
||||
|
||||
out:
|
||||
if (!ini->smcd_version && !ini->smcr_version)
|
||||
return rc;
|
||||
@@ -2430,6 +2456,10 @@ static void smc_listen_work(struct work_struct *work)
|
||||
if (rc)
|
||||
goto out_decl;
|
||||
|
||||
rc = smc_clc_srv_v2x_features_validate(pclc, ini);
|
||||
if (rc)
|
||||
goto out_decl;
|
||||
|
||||
mutex_lock(&smc_server_lgr_pending);
|
||||
smc_close_init(new_smc);
|
||||
smc_rx_init(new_smc);
|
||||
@@ -2443,7 +2473,7 @@ static void smc_listen_work(struct work_struct *work)
|
||||
/* send SMC Accept CLC message */
|
||||
accept_version = ini->is_smcd ? ini->smcd_version : ini->smcr_version;
|
||||
rc = smc_clc_send_accept(new_smc, ini->first_contact_local,
|
||||
accept_version, ini->negotiated_eid);
|
||||
accept_version, ini->negotiated_eid, ini);
|
||||
if (rc)
|
||||
goto out_unlock;
|
||||
|
||||
@@ -2462,6 +2492,18 @@ static void smc_listen_work(struct work_struct *work)
|
||||
goto out_decl;
|
||||
}
|
||||
|
||||
rc = smc_clc_v2x_features_confirm_check(cclc, ini);
|
||||
if (rc) {
|
||||
if (!ini->is_smcd)
|
||||
goto out_unlock;
|
||||
goto out_decl;
|
||||
}
|
||||
|
||||
/* fce smc release version is needed in smc_listen_rdma_finish,
|
||||
* so save fce info here.
|
||||
*/
|
||||
smc_conn_save_peer_info_fce(new_smc, cclc);
|
||||
|
||||
/* finish worker */
|
||||
if (!ini->is_smcd) {
|
||||
rc = smc_listen_rdma_finish(new_smc, cclc,
|
||||
|
||||
@@ -21,7 +21,10 @@
|
||||
|
||||
#define SMC_V1 1 /* SMC version V1 */
|
||||
#define SMC_V2 2 /* SMC version V2 */
|
||||
#define SMC_RELEASE 0
|
||||
|
||||
#define SMC_RELEASE_0 0
|
||||
#define SMC_RELEASE_1 1
|
||||
#define SMC_RELEASE SMC_RELEASE_1 /* the latest release version */
|
||||
|
||||
#define SMCPROTO_SMC 0 /* SMC protocol, IPv4 */
|
||||
#define SMCPROTO_SMC6 1 /* SMC protocol, IPv6 */
|
||||
|
||||
@@ -391,9 +391,7 @@ smc_clc_msg_acc_conf_valid(struct smc_clc_msg_accept_confirm_v2 *clc_v2)
|
||||
return false;
|
||||
} else {
|
||||
if (hdr->typev1 == SMC_TYPE_D &&
|
||||
ntohs(hdr->length) != SMCD_CLC_ACCEPT_CONFIRM_LEN_V2 &&
|
||||
(ntohs(hdr->length) != SMCD_CLC_ACCEPT_CONFIRM_LEN_V2 +
|
||||
sizeof(struct smc_clc_first_contact_ext)))
|
||||
ntohs(hdr->length) < SMCD_CLC_ACCEPT_CONFIRM_LEN_V2)
|
||||
return false;
|
||||
if (hdr->typev1 == SMC_TYPE_R &&
|
||||
ntohs(hdr->length) < SMCR_CLC_ACCEPT_CONFIRM_LEN_V2)
|
||||
@@ -420,13 +418,29 @@ smc_clc_msg_decl_valid(struct smc_clc_msg_decline *dclc)
|
||||
return true;
|
||||
}
|
||||
|
||||
static void smc_clc_fill_fce(struct smc_clc_first_contact_ext *fce, int *len)
|
||||
static int smc_clc_fill_fce(struct smc_clc_first_contact_ext_v2x *fce,
|
||||
struct smc_init_info *ini)
|
||||
{
|
||||
int ret = sizeof(*fce);
|
||||
|
||||
memset(fce, 0, sizeof(*fce));
|
||||
fce->os_type = SMC_CLC_OS_LINUX;
|
||||
fce->release = SMC_RELEASE;
|
||||
memcpy(fce->hostname, smc_hostname, sizeof(smc_hostname));
|
||||
(*len) += sizeof(*fce);
|
||||
fce->fce_v2_base.os_type = SMC_CLC_OS_LINUX;
|
||||
fce->fce_v2_base.release = ini->release_nr;
|
||||
memcpy(fce->fce_v2_base.hostname, smc_hostname, sizeof(smc_hostname));
|
||||
if (ini->is_smcd && ini->release_nr < SMC_RELEASE_1) {
|
||||
ret = sizeof(struct smc_clc_first_contact_ext);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (ini->release_nr >= SMC_RELEASE_1) {
|
||||
if (!ini->is_smcd) {
|
||||
fce->max_conns = ini->max_conns;
|
||||
fce->max_links = ini->max_links;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* check if received message has a correct header length and contains valid
|
||||
@@ -927,8 +941,11 @@ int smc_clc_send_proposal(struct smc_sock *smc, struct smc_init_info *ini)
|
||||
sizeof(struct smc_clc_smcd_gid_chid);
|
||||
}
|
||||
}
|
||||
if (smcr_indicated(ini->smc_type_v2))
|
||||
if (smcr_indicated(ini->smc_type_v2)) {
|
||||
memcpy(v2_ext->roce, ini->smcrv2.ib_gid_v2, SMC_GID_SIZE);
|
||||
v2_ext->max_conns = SMC_CONN_PER_LGR_PREFER;
|
||||
v2_ext->max_links = SMC_LINKS_PER_LGR_MAX_PREFER;
|
||||
}
|
||||
|
||||
pclc_base->hdr.length = htons(plen);
|
||||
memcpy(trl->eyecatcher, SMC_EYECATCHER, sizeof(SMC_EYECATCHER));
|
||||
@@ -986,13 +1003,13 @@ static int smc_clc_send_confirm_accept(struct smc_sock *smc,
|
||||
u8 *eid, struct smc_init_info *ini)
|
||||
{
|
||||
struct smc_connection *conn = &smc->conn;
|
||||
struct smc_clc_first_contact_ext_v2x fce;
|
||||
struct smc_clc_msg_accept_confirm *clc;
|
||||
struct smc_clc_first_contact_ext fce;
|
||||
struct smc_clc_fce_gid_ext gle;
|
||||
struct smc_clc_msg_trail trl;
|
||||
int i, len, fce_len;
|
||||
struct kvec vec[5];
|
||||
struct msghdr msg;
|
||||
int i, len;
|
||||
|
||||
/* send SMC Confirm CLC msg */
|
||||
clc = (struct smc_clc_msg_accept_confirm *)clc_v2;
|
||||
@@ -1018,8 +1035,10 @@ static int smc_clc_send_confirm_accept(struct smc_sock *smc,
|
||||
if (eid && eid[0])
|
||||
memcpy(clc_v2->d1.eid, eid, SMC_MAX_EID_LEN);
|
||||
len = SMCD_CLC_ACCEPT_CONFIRM_LEN_V2;
|
||||
if (first_contact)
|
||||
smc_clc_fill_fce(&fce, &len);
|
||||
if (first_contact) {
|
||||
fce_len = smc_clc_fill_fce(&fce, ini);
|
||||
len += fce_len;
|
||||
}
|
||||
clc_v2->hdr.length = htons(len);
|
||||
}
|
||||
memcpy(trl.eyecatcher, SMCD_EYECATCHER,
|
||||
@@ -1063,15 +1082,14 @@ static int smc_clc_send_confirm_accept(struct smc_sock *smc,
|
||||
memcpy(clc_v2->r1.eid, eid, SMC_MAX_EID_LEN);
|
||||
len = SMCR_CLC_ACCEPT_CONFIRM_LEN_V2;
|
||||
if (first_contact) {
|
||||
smc_clc_fill_fce(&fce, &len);
|
||||
fce.v2_direct = !link->lgr->uses_gateway;
|
||||
memset(&gle, 0, sizeof(gle));
|
||||
if (ini && clc->hdr.type == SMC_CLC_CONFIRM) {
|
||||
fce_len = smc_clc_fill_fce(&fce, ini);
|
||||
len += fce_len;
|
||||
fce.fce_v2_base.v2_direct = !link->lgr->uses_gateway;
|
||||
if (clc->hdr.type == SMC_CLC_CONFIRM) {
|
||||
memset(&gle, 0, sizeof(gle));
|
||||
gle.gid_cnt = ini->smcrv2.gidlist.len;
|
||||
len += sizeof(gle);
|
||||
len += gle.gid_cnt * sizeof(gle.gid[0]);
|
||||
} else {
|
||||
len += sizeof(gle.reserved);
|
||||
}
|
||||
}
|
||||
clc_v2->hdr.length = htons(len);
|
||||
@@ -1094,7 +1112,7 @@ static int smc_clc_send_confirm_accept(struct smc_sock *smc,
|
||||
sizeof(trl);
|
||||
if (version > SMC_V1 && first_contact) {
|
||||
vec[i].iov_base = &fce;
|
||||
vec[i++].iov_len = sizeof(fce);
|
||||
vec[i++].iov_len = fce_len;
|
||||
if (!conn->lgr->is_smcd) {
|
||||
if (clc->hdr.type == SMC_CLC_CONFIRM) {
|
||||
vec[i].iov_base = &gle;
|
||||
@@ -1102,9 +1120,6 @@ static int smc_clc_send_confirm_accept(struct smc_sock *smc,
|
||||
vec[i].iov_base = &ini->smcrv2.gidlist.list;
|
||||
vec[i++].iov_len = gle.gid_cnt *
|
||||
sizeof(gle.gid[0]);
|
||||
} else {
|
||||
vec[i].iov_base = &gle.reserved;
|
||||
vec[i++].iov_len = sizeof(gle.reserved);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1141,7 +1156,7 @@ int smc_clc_send_confirm(struct smc_sock *smc, bool clnt_first_contact,
|
||||
|
||||
/* send CLC ACCEPT message across internal TCP socket */
|
||||
int smc_clc_send_accept(struct smc_sock *new_smc, bool srv_first_contact,
|
||||
u8 version, u8 *negotiated_eid)
|
||||
u8 version, u8 *negotiated_eid, struct smc_init_info *ini)
|
||||
{
|
||||
struct smc_clc_msg_accept_confirm_v2 aclc_v2;
|
||||
int len;
|
||||
@@ -1149,13 +1164,95 @@ int smc_clc_send_accept(struct smc_sock *new_smc, bool srv_first_contact,
|
||||
memset(&aclc_v2, 0, sizeof(aclc_v2));
|
||||
aclc_v2.hdr.type = SMC_CLC_ACCEPT;
|
||||
len = smc_clc_send_confirm_accept(new_smc, &aclc_v2, srv_first_contact,
|
||||
version, negotiated_eid, NULL);
|
||||
version, negotiated_eid, ini);
|
||||
if (len < ntohs(aclc_v2.hdr.length))
|
||||
len = len >= 0 ? -EPROTO : -new_smc->clcsock->sk->sk_err;
|
||||
|
||||
return len > 0 ? 0 : len;
|
||||
}
|
||||
|
||||
int smc_clc_srv_v2x_features_validate(struct smc_clc_msg_proposal *pclc,
|
||||
struct smc_init_info *ini)
|
||||
{
|
||||
struct smc_clc_v2_extension *pclc_v2_ext;
|
||||
|
||||
ini->max_conns = SMC_CONN_PER_LGR_MAX;
|
||||
ini->max_links = SMC_LINKS_ADD_LNK_MAX;
|
||||
|
||||
if ((!(ini->smcd_version & SMC_V2) && !(ini->smcr_version & SMC_V2)) ||
|
||||
ini->release_nr < SMC_RELEASE_1)
|
||||
return 0;
|
||||
|
||||
pclc_v2_ext = smc_get_clc_v2_ext(pclc);
|
||||
if (!pclc_v2_ext)
|
||||
return SMC_CLC_DECL_NOV2EXT;
|
||||
|
||||
if (ini->smcr_version & SMC_V2) {
|
||||
ini->max_conns = min_t(u8, pclc_v2_ext->max_conns, SMC_CONN_PER_LGR_PREFER);
|
||||
if (ini->max_conns < SMC_CONN_PER_LGR_MIN)
|
||||
return SMC_CLC_DECL_MAXCONNERR;
|
||||
|
||||
ini->max_links = min_t(u8, pclc_v2_ext->max_links, SMC_LINKS_PER_LGR_MAX_PREFER);
|
||||
if (ini->max_links < SMC_LINKS_ADD_LNK_MIN)
|
||||
return SMC_CLC_DECL_MAXLINKERR;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int smc_clc_clnt_v2x_features_validate(struct smc_clc_first_contact_ext *fce,
|
||||
struct smc_init_info *ini)
|
||||
{
|
||||
struct smc_clc_first_contact_ext_v2x *fce_v2x =
|
||||
(struct smc_clc_first_contact_ext_v2x *)fce;
|
||||
|
||||
if (ini->release_nr < SMC_RELEASE_1)
|
||||
return 0;
|
||||
|
||||
if (!ini->is_smcd) {
|
||||
if (fce_v2x->max_conns < SMC_CONN_PER_LGR_MIN)
|
||||
return SMC_CLC_DECL_MAXCONNERR;
|
||||
ini->max_conns = fce_v2x->max_conns;
|
||||
|
||||
if (fce_v2x->max_links > SMC_LINKS_ADD_LNK_MAX ||
|
||||
fce_v2x->max_links < SMC_LINKS_ADD_LNK_MIN)
|
||||
return SMC_CLC_DECL_MAXLINKERR;
|
||||
ini->max_links = fce_v2x->max_links;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int smc_clc_v2x_features_confirm_check(struct smc_clc_msg_accept_confirm *cclc,
|
||||
struct smc_init_info *ini)
|
||||
{
|
||||
struct smc_clc_msg_accept_confirm_v2 *clc_v2 =
|
||||
(struct smc_clc_msg_accept_confirm_v2 *)cclc;
|
||||
struct smc_clc_first_contact_ext *fce =
|
||||
smc_get_clc_first_contact_ext(clc_v2, ini->is_smcd);
|
||||
struct smc_clc_first_contact_ext_v2x *fce_v2x =
|
||||
(struct smc_clc_first_contact_ext_v2x *)fce;
|
||||
|
||||
if (cclc->hdr.version == SMC_V1 ||
|
||||
!(cclc->hdr.typev2 & SMC_FIRST_CONTACT_MASK))
|
||||
return 0;
|
||||
|
||||
if (ini->release_nr != fce->release)
|
||||
return SMC_CLC_DECL_RELEASEERR;
|
||||
|
||||
if (fce->release < SMC_RELEASE_1)
|
||||
return 0;
|
||||
|
||||
if (!ini->is_smcd) {
|
||||
if (fce_v2x->max_conns != ini->max_conns)
|
||||
return SMC_CLC_DECL_MAXCONNERR;
|
||||
if (fce_v2x->max_links != ini->max_links)
|
||||
return SMC_CLC_DECL_MAXLINKERR;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void smc_clc_get_hostname(u8 **host)
|
||||
{
|
||||
*host = &smc_hostname[0];
|
||||
|
||||
@@ -45,6 +45,9 @@
|
||||
#define SMC_CLC_DECL_NOSEID 0x03030006 /* peer sent no SEID */
|
||||
#define SMC_CLC_DECL_NOSMCD2DEV 0x03030007 /* no SMC-Dv2 device found */
|
||||
#define SMC_CLC_DECL_NOUEID 0x03030008 /* peer sent no UEID */
|
||||
#define SMC_CLC_DECL_RELEASEERR 0x03030009 /* release version negotiate failed */
|
||||
#define SMC_CLC_DECL_MAXCONNERR 0x0303000a /* max connections negotiate failed */
|
||||
#define SMC_CLC_DECL_MAXLINKERR 0x0303000b /* max links negotiate failed */
|
||||
#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 */
|
||||
@@ -133,7 +136,9 @@ struct smc_clc_smcd_gid_chid {
|
||||
struct smc_clc_v2_extension {
|
||||
struct smc_clnt_opts_area_hdr hdr;
|
||||
u8 roce[16]; /* RoCEv2 GID */
|
||||
u8 reserved[16];
|
||||
u8 max_conns;
|
||||
u8 max_links;
|
||||
u8 reserved[14];
|
||||
u8 user_eids[][SMC_MAX_EID_LEN];
|
||||
};
|
||||
|
||||
@@ -147,7 +152,9 @@ struct smc_clc_msg_proposal_prefix { /* prefix part of clc proposal message*/
|
||||
struct smc_clc_msg_smcd { /* SMC-D GID information */
|
||||
struct smc_clc_smcd_gid_chid ism; /* ISM native GID+CHID of requestor */
|
||||
__be16 v2_ext_offset; /* SMC Version 2 Extension Offset */
|
||||
u8 reserved[28];
|
||||
u8 vendor_oui[3]; /* vendor organizationally unique identifier */
|
||||
u8 vendor_exp_options[5];
|
||||
u8 reserved[20];
|
||||
};
|
||||
|
||||
struct smc_clc_smcd_v2_extension {
|
||||
@@ -231,8 +238,19 @@ struct smc_clc_first_contact_ext {
|
||||
u8 hostname[SMC_MAX_HOSTNAME_LEN];
|
||||
};
|
||||
|
||||
struct smc_clc_first_contact_ext_v2x {
|
||||
struct smc_clc_first_contact_ext fce_v2_base;
|
||||
u8 max_conns; /* for SMC-R only */
|
||||
u8 max_links; /* for SMC-R only */
|
||||
u8 reserved3[2];
|
||||
__be32 vendor_exp_options;
|
||||
u8 reserved4[8];
|
||||
} __packed; /* format defined in
|
||||
* IBM Shared Memory Communications Version 2 (Third Edition)
|
||||
* (https://www.ibm.com/support/pages/node/7009315)
|
||||
*/
|
||||
|
||||
struct smc_clc_fce_gid_ext {
|
||||
u8 reserved[16];
|
||||
u8 gid_cnt;
|
||||
u8 reserved2[3];
|
||||
u8 gid[][SMC_GID_SIZE];
|
||||
@@ -370,6 +388,27 @@ smc_get_clc_smcd_v2_ext(struct smc_clc_v2_extension *prop_v2ext)
|
||||
ntohs(prop_v2ext->hdr.smcd_v2_ext_offset));
|
||||
}
|
||||
|
||||
static inline struct smc_clc_first_contact_ext *
|
||||
smc_get_clc_first_contact_ext(struct smc_clc_msg_accept_confirm_v2 *clc_v2,
|
||||
bool is_smcd)
|
||||
{
|
||||
int clc_v2_len;
|
||||
|
||||
if (clc_v2->hdr.version == SMC_V1 ||
|
||||
!(clc_v2->hdr.typev2 & SMC_FIRST_CONTACT_MASK))
|
||||
return NULL;
|
||||
|
||||
if (is_smcd)
|
||||
clc_v2_len =
|
||||
offsetofend(struct smc_clc_msg_accept_confirm_v2, d1);
|
||||
else
|
||||
clc_v2_len =
|
||||
offsetofend(struct smc_clc_msg_accept_confirm_v2, r1);
|
||||
|
||||
return (struct smc_clc_first_contact_ext *)(((u8 *)clc_v2) +
|
||||
clc_v2_len);
|
||||
}
|
||||
|
||||
struct smcd_dev;
|
||||
struct smc_init_info;
|
||||
|
||||
@@ -382,7 +421,13 @@ int smc_clc_send_proposal(struct smc_sock *smc, struct smc_init_info *ini);
|
||||
int smc_clc_send_confirm(struct smc_sock *smc, bool clnt_first_contact,
|
||||
u8 version, u8 *eid, struct smc_init_info *ini);
|
||||
int smc_clc_send_accept(struct smc_sock *smc, bool srv_first_contact,
|
||||
u8 version, u8 *negotiated_eid);
|
||||
u8 version, u8 *negotiated_eid, struct smc_init_info *ini);
|
||||
int smc_clc_srv_v2x_features_validate(struct smc_clc_msg_proposal *pclc,
|
||||
struct smc_init_info *ini);
|
||||
int smc_clc_clnt_v2x_features_validate(struct smc_clc_first_contact_ext *fce,
|
||||
struct smc_init_info *ini);
|
||||
int smc_clc_v2x_features_confirm_check(struct smc_clc_msg_accept_confirm *cclc,
|
||||
struct smc_init_info *ini);
|
||||
void smc_clc_init(void) __init;
|
||||
void smc_clc_exit(void);
|
||||
void smc_clc_get_hostname(u8 **host);
|
||||
|
||||
@@ -319,6 +319,10 @@ static int smc_nl_fill_smcr_lgr_v2(struct smc_link_group *lgr,
|
||||
goto errattr;
|
||||
if (nla_put_u8(skb, SMC_NLA_LGR_R_V2_DIRECT, !lgr->uses_gateway))
|
||||
goto errv2attr;
|
||||
if (nla_put_u8(skb, SMC_NLA_LGR_R_V2_MAX_CONNS, lgr->max_conns))
|
||||
goto errv2attr;
|
||||
if (nla_put_u8(skb, SMC_NLA_LGR_R_V2_MAX_LINKS, lgr->max_links))
|
||||
goto errv2attr;
|
||||
|
||||
nla_nest_end(skb, v2_attrs);
|
||||
return 0;
|
||||
@@ -895,9 +899,13 @@ static int smc_lgr_create(struct smc_sock *smc, struct smc_init_info *ini)
|
||||
lgr->uses_gateway = ini->smcrv2.uses_gateway;
|
||||
memcpy(lgr->nexthop_mac, ini->smcrv2.nexthop_mac,
|
||||
ETH_ALEN);
|
||||
lgr->max_conns = ini->max_conns;
|
||||
lgr->max_links = ini->max_links;
|
||||
} else {
|
||||
ibdev = ini->ib_dev;
|
||||
ibport = ini->ib_port;
|
||||
lgr->max_conns = SMC_CONN_PER_LGR_MAX;
|
||||
lgr->max_links = SMC_LINKS_ADD_LNK_MAX;
|
||||
}
|
||||
memcpy(lgr->pnet_id, ibdev->pnetid[ibport - 1],
|
||||
SMC_MAX_PNETID_LEN);
|
||||
@@ -1664,6 +1672,9 @@ void smcr_port_add(struct smc_ib_device *smcibdev, u8 ibport)
|
||||
!rdma_dev_access_netns(smcibdev->ibdev, lgr->net))
|
||||
continue;
|
||||
|
||||
if (lgr->type == SMC_LGR_SINGLE && lgr->max_links <= 1)
|
||||
continue;
|
||||
|
||||
/* trigger local add link processing */
|
||||
link = smc_llc_usable_link(lgr);
|
||||
if (link)
|
||||
@@ -1888,7 +1899,7 @@ int smc_conn_create(struct smc_sock *smc, struct smc_init_info *ini)
|
||||
(ini->smcd_version == SMC_V2 ||
|
||||
lgr->vlan_id == ini->vlan_id) &&
|
||||
(role == SMC_CLNT || ini->is_smcd ||
|
||||
(lgr->conns_num < SMC_RMBS_PER_LGR_MAX &&
|
||||
(lgr->conns_num < lgr->max_conns &&
|
||||
!bitmap_full(lgr->rtokens_used_mask, SMC_RMBS_PER_LGR_MAX)))) {
|
||||
/* link group found */
|
||||
ini->first_contact_local = 0;
|
||||
|
||||
@@ -22,6 +22,15 @@
|
||||
#include "smc_ib.h"
|
||||
|
||||
#define SMC_RMBS_PER_LGR_MAX 255 /* max. # of RMBs per link group */
|
||||
#define SMC_CONN_PER_LGR_MIN 16 /* min. # of connections per link group */
|
||||
#define SMC_CONN_PER_LGR_MAX 255 /* max. # of connections per link group,
|
||||
* also is the default value for SMC-R v1 and v2.0
|
||||
*/
|
||||
#define SMC_CONN_PER_LGR_PREFER 255 /* Preferred connections per link group used for
|
||||
* SMC-R v2.1 and later negotiation, vendors or
|
||||
* distrubutions may modify it to a value between
|
||||
* 16-255 as needed.
|
||||
*/
|
||||
|
||||
struct smc_lgr_list { /* list of link group definition */
|
||||
struct list_head list;
|
||||
@@ -164,6 +173,15 @@ struct smc_link {
|
||||
*/
|
||||
#define SMC_LINKS_PER_LGR_MAX 3
|
||||
#define SMC_SINGLE_LINK 0
|
||||
#define SMC_LINKS_ADD_LNK_MIN 1 /* min. # of links per link group */
|
||||
#define SMC_LINKS_ADD_LNK_MAX 2 /* max. # of links per link group, also is the
|
||||
* default value for smc-r v1.0 and v2.0
|
||||
*/
|
||||
#define SMC_LINKS_PER_LGR_MAX_PREFER 2 /* Preferred max links per link group used for
|
||||
* SMC-R v2.1 and later negotiation, vendors or
|
||||
* distrubutions may modify it to a value between
|
||||
* 1-2 as needed.
|
||||
*/
|
||||
|
||||
/* tx/rx buffer list element for sndbufs list and rmbs list of a lgr */
|
||||
struct smc_buf_desc {
|
||||
@@ -331,6 +349,10 @@ struct smc_link_group {
|
||||
__be32 saddr;
|
||||
/* net namespace */
|
||||
struct net *net;
|
||||
u8 max_conns;
|
||||
/* max conn can be assigned to lgr */
|
||||
u8 max_links;
|
||||
/* max links can be added in lgr */
|
||||
};
|
||||
struct { /* SMC-D */
|
||||
u64 peer_gid;
|
||||
@@ -374,6 +396,9 @@ struct smc_init_info {
|
||||
u8 is_smcd;
|
||||
u8 smc_type_v1;
|
||||
u8 smc_type_v2;
|
||||
u8 release_nr;
|
||||
u8 max_conns;
|
||||
u8 max_links;
|
||||
u8 first_contact_peer;
|
||||
u8 first_contact_local;
|
||||
unsigned short vlan_id;
|
||||
|
||||
@@ -52,14 +52,13 @@ struct smc_llc_msg_confirm_link { /* type 0x01 */
|
||||
u8 link_num;
|
||||
u8 link_uid[SMC_LGR_ID_SIZE];
|
||||
u8 max_links;
|
||||
u8 reserved[9];
|
||||
u8 max_conns;
|
||||
u8 reserved[8];
|
||||
};
|
||||
|
||||
#define SMC_LLC_FLAG_ADD_LNK_REJ 0x40
|
||||
#define SMC_LLC_REJ_RSN_NO_ALT_PATH 1
|
||||
|
||||
#define SMC_LLC_ADD_LNK_MAX_LINKS 2
|
||||
|
||||
struct smc_llc_msg_add_link { /* type 0x02 */
|
||||
struct smc_llc_hdr hd;
|
||||
u8 sender_mac[ETH_ALEN];
|
||||
@@ -471,7 +470,12 @@ int smc_llc_send_confirm_link(struct smc_link *link,
|
||||
hton24(confllc->sender_qp_num, link->roce_qp->qp_num);
|
||||
confllc->link_num = link->link_id;
|
||||
memcpy(confllc->link_uid, link->link_uid, SMC_LGR_ID_SIZE);
|
||||
confllc->max_links = SMC_LLC_ADD_LNK_MAX_LINKS;
|
||||
confllc->max_links = SMC_LINKS_ADD_LNK_MAX;
|
||||
if (link->lgr->smc_version == SMC_V2 &&
|
||||
link->lgr->peer_smc_release >= SMC_RELEASE_1) {
|
||||
confllc->max_conns = link->lgr->max_conns;
|
||||
confllc->max_links = link->lgr->max_links;
|
||||
}
|
||||
/* send llc message */
|
||||
rc = smc_wr_tx_send(link, pend);
|
||||
put_out:
|
||||
@@ -1041,6 +1045,11 @@ int smc_llc_cli_add_link(struct smc_link *link, struct smc_llc_qentry *qentry)
|
||||
goto out_reject;
|
||||
}
|
||||
|
||||
if (lgr->type == SMC_LGR_SINGLE && lgr->max_links <= 1) {
|
||||
rc = 0;
|
||||
goto out_reject;
|
||||
}
|
||||
|
||||
ini->vlan_id = lgr->vlan_id;
|
||||
if (lgr->smc_version == SMC_V2) {
|
||||
ini->check_smcrv2 = true;
|
||||
@@ -1165,6 +1174,9 @@ static void smc_llc_cli_add_link_invite(struct smc_link *link,
|
||||
lgr->type == SMC_LGR_ASYMMETRIC_PEER)
|
||||
goto out;
|
||||
|
||||
if (lgr->type == SMC_LGR_SINGLE && lgr->max_links <= 1)
|
||||
goto out;
|
||||
|
||||
ini = kzalloc(sizeof(*ini), GFP_KERNEL);
|
||||
if (!ini)
|
||||
goto out;
|
||||
@@ -1410,6 +1422,11 @@ int smc_llc_srv_add_link(struct smc_link *link,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (lgr->type == SMC_LGR_SINGLE && lgr->max_links <= 1) {
|
||||
rc = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* ignore client add link recommendation, start new flow */
|
||||
ini->vlan_id = lgr->vlan_id;
|
||||
if (lgr->smc_version == SMC_V2) {
|
||||
|
||||
Reference in New Issue
Block a user