Commit 42042dbb authored by Karsten Graul's avatar Karsten Graul Committed by David S. Miller

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: default avatarKarsten Graul <kgraul@linux.ibm.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent ed990df2
...@@ -608,7 +608,9 @@ static int smc_find_rdma_device(struct smc_sock *smc, struct smc_init_info *ini) ...@@ -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 * used for the internal TCP socket
*/ */
smc_pnet_find_roce_resource(smc->clcsock->sk, ini); 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 SMC_CLC_DECL_NOSMCRDEV;
return 0; return 0;
} }
...@@ -692,27 +694,42 @@ static int smc_find_proposal_devices(struct smc_sock *smc, ...@@ -692,27 +694,42 @@ static int smc_find_proposal_devices(struct smc_sock *smc,
int rc = 0; int rc = 0;
/* check if there is an ism device available */ /* check if there is an ism device available */
if (ini->smcd_version & SMC_V1) { if (!(ini->smcd_version & SMC_V1) ||
if (smc_find_ism_device(smc, ini) || smc_find_ism_device(smc, ini) ||
smc_connect_ism_vlan_setup(smc, ini)) { smc_connect_ism_vlan_setup(smc, ini))
if (ini->smc_type_v1 == SMC_TYPE_B) ini->smcd_version &= ~SMC_V1;
ini->smc_type_v1 = SMC_TYPE_R; /* else ISM V1 is supported for this connection */
else
ini->smc_type_v1 = SMC_TYPE_N; /* check if there is an rdma device available */
} /* else ISM V1 is supported for this connection */ if (!(ini->smcr_version & SMC_V1) ||
if (smc_find_rdma_device(smc, ini)) { smc_find_rdma_device(smc, ini))
if (ini->smc_type_v1 == SMC_TYPE_B) ini->smcr_version &= ~SMC_V1;
ini->smc_type_v1 = SMC_TYPE_D; /* else RDMA is supported for this connection */
else
ini->smc_type_v1 = SMC_TYPE_N; ini->smc_type_v1 = smc_indicated_type(ini->smcd_version & SMC_V1,
} /* else RDMA is supported for this connection */ ini->smcr_version & SMC_V1);
}
if (smc_ism_is_v2_capable() && smc_find_ism_v2_device_clnt(smc, ini)) /* check if there is an ism v2 device available */
ini->smc_type_v2 = SMC_TYPE_N; 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 neither ISM nor RDMA are supported, fallback */
if (!smcr_indicated(ini->smc_type_v1) && if (ini->smc_type_v1 == SMC_TYPE_N && ini->smc_type_v2 == SMC_TYPE_N)
ini->smc_type_v1 == SMC_TYPE_N && ini->smc_type_v2 == SMC_TYPE_N)
rc = SMC_CLC_DECL_NOSMCDEV; rc = SMC_CLC_DECL_NOSMCDEV;
return rc; return rc;
...@@ -950,17 +967,24 @@ static int smc_connect_ism(struct smc_sock *smc, ...@@ -950,17 +967,24 @@ static int smc_connect_ism(struct smc_sock *smc,
static int smc_connect_check_aclc(struct smc_init_info *ini, static int smc_connect_check_aclc(struct smc_init_info *ini,
struct smc_clc_msg_accept_confirm *aclc) struct smc_clc_msg_accept_confirm *aclc)
{ {
if ((aclc->hdr.typev1 == SMC_TYPE_R && if (aclc->hdr.typev1 != SMC_TYPE_R &&
!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_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;
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; return 0;
} }
...@@ -991,14 +1015,15 @@ static int __smc_connect(struct smc_sock *smc) ...@@ -991,14 +1015,15 @@ static int __smc_connect(struct smc_sock *smc)
return smc_connect_decline_fallback(smc, SMC_CLC_DECL_MEM, return smc_connect_decline_fallback(smc, SMC_CLC_DECL_MEM,
version); version);
ini->smcd_version = SMC_V1; ini->smcd_version = SMC_V1 | SMC_V2;
ini->smcd_version |= smc_ism_is_v2_capable() ? SMC_V2 : 0; ini->smcr_version = SMC_V1 | SMC_V2;
ini->smc_type_v1 = SMC_TYPE_B; 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 */ /* get vlan id from IP device */
if (smc_vlan_by_tcpsk(smc->clcsock, ini)) { if (smc_vlan_by_tcpsk(smc->clcsock, ini)) {
ini->smcd_version &= ~SMC_V1; ini->smcd_version &= ~SMC_V1;
ini->smcr_version = 0;
ini->smc_type_v1 = SMC_TYPE_N; ini->smc_type_v1 = SMC_TYPE_N;
if (!ini->smcd_version) { if (!ini->smcd_version) {
rc = SMC_CLC_DECL_GETVLANERR; rc = SMC_CLC_DECL_GETVLANERR;
...@@ -1026,15 +1051,17 @@ static int __smc_connect(struct smc_sock *smc) ...@@ -1026,15 +1051,17 @@ static int __smc_connect(struct smc_sock *smc)
/* 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);
version = aclc->hdr.version == SMC_V1 ? SMC_V1 : SMC_V2; version = aclc->hdr.version == SMC_V1 ? SMC_V1 : SMC_V2;
ini->smcd_version = version;
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) {
ini->smcr_version = version;
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) {
ini->smcd_version = version;
rc = smc_connect_ism(smc, aclc, ini); rc = smc_connect_ism(smc, aclc, ini);
}
if (rc) if (rc)
goto vlan_cleanup; goto vlan_cleanup;
......
...@@ -114,6 +114,17 @@ static int smc_clc_ueid_add(char *ueid) ...@@ -114,6 +114,17 @@ static int smc_clc_ueid_add(char *ueid)
return rc; 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) int smc_nl_add_ueid(struct sk_buff *skb, struct genl_info *info)
{ {
struct nlattr *nla_ueid = info->attrs[SMC_NLA_EID_TABLE_ENTRY]; struct nlattr *nla_ueid = info->attrs[SMC_NLA_EID_TABLE_ENTRY];
......
...@@ -282,6 +282,17 @@ static inline bool smcd_indicated(int smc_type) ...@@ -282,6 +282,17 @@ static inline bool smcd_indicated(int smc_type)
return smc_type == SMC_TYPE_D || smc_type == SMC_TYPE_B; 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 */ /* get SMC-D info from proposal message */
static inline struct smc_clc_msg_smcd * static inline struct smc_clc_msg_smcd *
smc_get_clc_msg_smcd(struct smc_clc_msg_proposal *prop) smc_get_clc_msg_smcd(struct smc_clc_msg_proposal *prop)
...@@ -343,6 +354,7 @@ void smc_clc_get_hostname(u8 **host); ...@@ -343,6 +354,7 @@ void smc_clc_get_hostname(u8 **host);
bool smc_clc_match_eid(u8 *negotiated_eid, bool smc_clc_match_eid(u8 *negotiated_eid,
struct smc_clc_v2_extension *smc_v2_ext, struct smc_clc_v2_extension *smc_v2_ext,
u8 *peer_eid, u8 *local_eid); 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_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_add_ueid(struct sk_buff *skb, struct genl_info *info);
int smc_nl_remove_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 { ...@@ -302,6 +302,31 @@ struct smc_link_group {
struct smc_clc_msg_local; 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 { struct smc_init_info {
u8 is_smcd; u8 is_smcd;
u8 smc_type_v1; u8 smc_type_v1;
...@@ -313,10 +338,13 @@ struct smc_init_info { ...@@ -313,10 +338,13 @@ struct smc_init_info {
u8 negotiated_eid[SMC_MAX_EID_LEN]; u8 negotiated_eid[SMC_MAX_EID_LEN];
/* SMC-R */ /* SMC-R */
struct smc_clc_msg_local *ib_lcl; struct smc_clc_msg_local *ib_lcl;
u8 smcr_version;
u8 check_smcrv2;
struct smc_ib_device *ib_dev; struct smc_ib_device *ib_dev;
u8 ib_gid[SMC_GID_SIZE]; u8 ib_gid[SMC_GID_SIZE];
u8 ib_port; u8 ib_port;
u32 ib_clcqpn; u32 ib_clcqpn;
struct smc_init_info_smcrv2 smcrv2;
/* SMC-D */ /* SMC-D */
u64 ism_peer_gid[SMC_MAX_ISM_DEVS + 1]; u64 ism_peer_gid[SMC_MAX_ISM_DEVS + 1];
struct smcd_dev *ism_dev[SMC_MAX_ISM_DEVS + 1]; struct smcd_dev *ism_dev[SMC_MAX_ISM_DEVS + 1];
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment