net/smc: prepare for SMC-Rv2 connection
Prepare the connection establishment with SMC-Rv2. Detect eligible RoCE cards and indicate all supported SMC modes for the connection. Signed-off-by: Karsten Graul <kgraul@linux.ibm.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
ed990df29f
commit
42042dbbc2
|
@ -608,7 +608,9 @@ static int smc_find_rdma_device(struct smc_sock *smc, struct smc_init_info *ini)
|
|||
* used for the internal TCP socket
|
||||
*/
|
||||
smc_pnet_find_roce_resource(smc->clcsock->sk, ini);
|
||||
if (!ini->ib_dev)
|
||||
if (!ini->check_smcrv2 && !ini->ib_dev)
|
||||
return SMC_CLC_DECL_NOSMCRDEV;
|
||||
if (ini->check_smcrv2 && !ini->smcrv2.ib_dev_v2)
|
||||
return SMC_CLC_DECL_NOSMCRDEV;
|
||||
return 0;
|
||||
}
|
||||
|
@ -692,27 +694,42 @@ static int smc_find_proposal_devices(struct smc_sock *smc,
|
|||
int rc = 0;
|
||||
|
||||
/* check if there is an ism device available */
|
||||
if (ini->smcd_version & SMC_V1) {
|
||||
if (smc_find_ism_device(smc, ini) ||
|
||||
smc_connect_ism_vlan_setup(smc, ini)) {
|
||||
if (ini->smc_type_v1 == SMC_TYPE_B)
|
||||
ini->smc_type_v1 = SMC_TYPE_R;
|
||||
else
|
||||
ini->smc_type_v1 = SMC_TYPE_N;
|
||||
} /* else ISM V1 is supported for this connection */
|
||||
if (smc_find_rdma_device(smc, ini)) {
|
||||
if (ini->smc_type_v1 == SMC_TYPE_B)
|
||||
ini->smc_type_v1 = SMC_TYPE_D;
|
||||
else
|
||||
ini->smc_type_v1 = SMC_TYPE_N;
|
||||
} /* else RDMA is supported for this connection */
|
||||
}
|
||||
if (smc_ism_is_v2_capable() && smc_find_ism_v2_device_clnt(smc, ini))
|
||||
ini->smc_type_v2 = SMC_TYPE_N;
|
||||
if (!(ini->smcd_version & SMC_V1) ||
|
||||
smc_find_ism_device(smc, ini) ||
|
||||
smc_connect_ism_vlan_setup(smc, ini))
|
||||
ini->smcd_version &= ~SMC_V1;
|
||||
/* else ISM V1 is supported for this connection */
|
||||
|
||||
/* check if there is an rdma device available */
|
||||
if (!(ini->smcr_version & SMC_V1) ||
|
||||
smc_find_rdma_device(smc, ini))
|
||||
ini->smcr_version &= ~SMC_V1;
|
||||
/* else RDMA is supported for this connection */
|
||||
|
||||
ini->smc_type_v1 = smc_indicated_type(ini->smcd_version & SMC_V1,
|
||||
ini->smcr_version & SMC_V1);
|
||||
|
||||
/* check if there is an ism v2 device available */
|
||||
if (!(ini->smcd_version & SMC_V2) ||
|
||||
!smc_ism_is_v2_capable() ||
|
||||
smc_find_ism_v2_device_clnt(smc, ini))
|
||||
ini->smcd_version &= ~SMC_V2;
|
||||
|
||||
/* check if there is an rdma v2 device available */
|
||||
ini->check_smcrv2 = true;
|
||||
ini->smcrv2.saddr = smc->clcsock->sk->sk_rcv_saddr;
|
||||
if (!(ini->smcr_version & SMC_V2) ||
|
||||
smc->clcsock->sk->sk_family != AF_INET ||
|
||||
!smc_clc_ueid_count() ||
|
||||
smc_find_rdma_device(smc, ini))
|
||||
ini->smcr_version &= ~SMC_V2;
|
||||
ini->check_smcrv2 = false;
|
||||
|
||||
ini->smc_type_v2 = smc_indicated_type(ini->smcd_version & SMC_V2,
|
||||
ini->smcr_version & SMC_V2);
|
||||
|
||||
/* if neither ISM nor RDMA are supported, fallback */
|
||||
if (!smcr_indicated(ini->smc_type_v1) &&
|
||||
ini->smc_type_v1 == SMC_TYPE_N && ini->smc_type_v2 == SMC_TYPE_N)
|
||||
if (ini->smc_type_v1 == SMC_TYPE_N && ini->smc_type_v2 == SMC_TYPE_N)
|
||||
rc = SMC_CLC_DECL_NOSMCDEV;
|
||||
|
||||
return rc;
|
||||
|
@ -950,17 +967,24 @@ connect_abort:
|
|||
static int smc_connect_check_aclc(struct smc_init_info *ini,
|
||||
struct smc_clc_msg_accept_confirm *aclc)
|
||||
{
|
||||
if ((aclc->hdr.typev1 == SMC_TYPE_R &&
|
||||
!smcr_indicated(ini->smc_type_v1)) ||
|
||||
(aclc->hdr.typev1 == SMC_TYPE_D &&
|
||||
((!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)))))
|
||||
if (aclc->hdr.typev1 != SMC_TYPE_R &&
|
||||
aclc->hdr.typev1 != SMC_TYPE_D)
|
||||
return SMC_CLC_DECL_MODEUNSUPP;
|
||||
|
||||
if (aclc->hdr.version >= SMC_V2) {
|
||||
if ((aclc->hdr.typev1 == SMC_TYPE_R &&
|
||||
!smcr_indicated(ini->smc_type_v2)) ||
|
||||
(aclc->hdr.typev1 == SMC_TYPE_D &&
|
||||
!smcd_indicated(ini->smc_type_v2)))
|
||||
return SMC_CLC_DECL_MODEUNSUPP;
|
||||
} else {
|
||||
if ((aclc->hdr.typev1 == SMC_TYPE_R &&
|
||||
!smcr_indicated(ini->smc_type_v1)) ||
|
||||
(aclc->hdr.typev1 == SMC_TYPE_D &&
|
||||
!smcd_indicated(ini->smc_type_v1)))
|
||||
return SMC_CLC_DECL_MODEUNSUPP;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -991,14 +1015,15 @@ static int __smc_connect(struct smc_sock *smc)
|
|||
return smc_connect_decline_fallback(smc, SMC_CLC_DECL_MEM,
|
||||
version);
|
||||
|
||||
ini->smcd_version = SMC_V1;
|
||||
ini->smcd_version |= smc_ism_is_v2_capable() ? SMC_V2 : 0;
|
||||
ini->smcd_version = SMC_V1 | SMC_V2;
|
||||
ini->smcr_version = SMC_V1 | SMC_V2;
|
||||
ini->smc_type_v1 = SMC_TYPE_B;
|
||||
ini->smc_type_v2 = smc_ism_is_v2_capable() ? SMC_TYPE_D : SMC_TYPE_N;
|
||||
ini->smc_type_v2 = SMC_TYPE_B;
|
||||
|
||||
/* get vlan id from IP device */
|
||||
if (smc_vlan_by_tcpsk(smc->clcsock, ini)) {
|
||||
ini->smcd_version &= ~SMC_V1;
|
||||
ini->smcr_version = 0;
|
||||
ini->smc_type_v1 = SMC_TYPE_N;
|
||||
if (!ini->smcd_version) {
|
||||
rc = SMC_CLC_DECL_GETVLANERR;
|
||||
|
@ -1026,15 +1051,17 @@ static int __smc_connect(struct smc_sock *smc)
|
|||
/* check if smc modes and versions of CLC proposal and accept match */
|
||||
rc = smc_connect_check_aclc(ini, aclc);
|
||||
version = aclc->hdr.version == SMC_V1 ? SMC_V1 : SMC_V2;
|
||||
ini->smcd_version = version;
|
||||
if (rc)
|
||||
goto vlan_cleanup;
|
||||
|
||||
/* depending on previous steps, connect using rdma or ism */
|
||||
if (aclc->hdr.typev1 == SMC_TYPE_R)
|
||||
if (aclc->hdr.typev1 == SMC_TYPE_R) {
|
||||
ini->smcr_version = version;
|
||||
rc = smc_connect_rdma(smc, aclc, ini);
|
||||
else if (aclc->hdr.typev1 == SMC_TYPE_D)
|
||||
} else if (aclc->hdr.typev1 == SMC_TYPE_D) {
|
||||
ini->smcd_version = version;
|
||||
rc = smc_connect_ism(smc, aclc, ini);
|
||||
}
|
||||
if (rc)
|
||||
goto vlan_cleanup;
|
||||
|
||||
|
|
|
@ -114,6 +114,17 @@ err_out:
|
|||
return rc;
|
||||
}
|
||||
|
||||
int smc_clc_ueid_count(void)
|
||||
{
|
||||
int count;
|
||||
|
||||
read_lock(&smc_clc_eid_table.lock);
|
||||
count = smc_clc_eid_table.ueid_cnt;
|
||||
read_unlock(&smc_clc_eid_table.lock);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
int smc_nl_add_ueid(struct sk_buff *skb, struct genl_info *info)
|
||||
{
|
||||
struct nlattr *nla_ueid = info->attrs[SMC_NLA_EID_TABLE_ENTRY];
|
||||
|
|
|
@ -282,6 +282,17 @@ static inline bool smcd_indicated(int smc_type)
|
|||
return smc_type == SMC_TYPE_D || smc_type == SMC_TYPE_B;
|
||||
}
|
||||
|
||||
static inline u8 smc_indicated_type(int is_smcd, int is_smcr)
|
||||
{
|
||||
if (is_smcd && is_smcr)
|
||||
return SMC_TYPE_B;
|
||||
if (is_smcd)
|
||||
return SMC_TYPE_D;
|
||||
if (is_smcr)
|
||||
return SMC_TYPE_R;
|
||||
return SMC_TYPE_N;
|
||||
}
|
||||
|
||||
/* 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)
|
||||
|
@ -343,6 +354,7 @@ void smc_clc_get_hostname(u8 **host);
|
|||
bool smc_clc_match_eid(u8 *negotiated_eid,
|
||||
struct smc_clc_v2_extension *smc_v2_ext,
|
||||
u8 *peer_eid, u8 *local_eid);
|
||||
int smc_clc_ueid_count(void);
|
||||
int smc_nl_dump_ueid(struct sk_buff *skb, struct netlink_callback *cb);
|
||||
int smc_nl_add_ueid(struct sk_buff *skb, struct genl_info *info);
|
||||
int smc_nl_remove_ueid(struct sk_buff *skb, struct genl_info *info);
|
||||
|
|
|
@ -302,6 +302,31 @@ struct smc_link_group {
|
|||
|
||||
struct smc_clc_msg_local;
|
||||
|
||||
#define GID_LIST_SIZE 2
|
||||
|
||||
struct smc_gidlist {
|
||||
u8 len;
|
||||
u8 list[GID_LIST_SIZE][SMC_GID_SIZE];
|
||||
};
|
||||
|
||||
struct smc_init_info_smcrv2 {
|
||||
/* Input fields */
|
||||
__be32 saddr;
|
||||
struct sock *clc_sk;
|
||||
__be32 daddr;
|
||||
|
||||
/* Output fields when saddr is set */
|
||||
struct smc_ib_device *ib_dev_v2;
|
||||
u8 ib_port_v2;
|
||||
u8 ib_gid_v2[SMC_GID_SIZE];
|
||||
|
||||
/* Additional output fields when clc_sk and daddr is set as well */
|
||||
u8 uses_gateway;
|
||||
u8 nexthop_mac[ETH_ALEN];
|
||||
|
||||
struct smc_gidlist gidlist;
|
||||
};
|
||||
|
||||
struct smc_init_info {
|
||||
u8 is_smcd;
|
||||
u8 smc_type_v1;
|
||||
|
@ -313,10 +338,13 @@ struct smc_init_info {
|
|||
u8 negotiated_eid[SMC_MAX_EID_LEN];
|
||||
/* SMC-R */
|
||||
struct smc_clc_msg_local *ib_lcl;
|
||||
u8 smcr_version;
|
||||
u8 check_smcrv2;
|
||||
struct smc_ib_device *ib_dev;
|
||||
u8 ib_gid[SMC_GID_SIZE];
|
||||
u8 ib_port;
|
||||
u32 ib_clcqpn;
|
||||
struct smc_init_info_smcrv2 smcrv2;
|
||||
/* SMC-D */
|
||||
u64 ism_peer_gid[SMC_MAX_ISM_DEVS + 1];
|
||||
struct smcd_dev *ism_dev[SMC_MAX_ISM_DEVS + 1];
|
||||
|
|
Loading…
Reference in New Issue