Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7005ada6 authored by Ursula Braun's avatar Ursula Braun Committed by David S. Miller
Browse files

net/smc: use correct vlan gid of RoCE device



SMC code uses the base gid for VLAN traffic. The gids exchanged in
the CLC handshake and the gid index used for the QP have to switch
from the base gid to the appropriate vlan gid.

When searching for a matching IB device port for a certain vlan
device, it does not make sense to return an IB device port, which
is not enabled for the used vlan_id. Add another check whether a
vlan gid exists for a certain IB device port.

Signed-off-by: default avatarUrsula Braun <ubraun@linux.ibm.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 947541f3
Loading
Loading
Loading
Loading
+13 −11
Original line number Diff line number Diff line
@@ -370,8 +370,7 @@ static int smc_clnt_conf_first_link(struct smc_sock *smc)
	/* send add link reject message, only one link supported for now */
	rc = smc_llc_send_add_link(link,
				   link->smcibdev->mac[link->ibport - 1],
				   &link->smcibdev->gid[link->ibport - 1],
				   SMC_LLC_RESP);
				   link->gid, SMC_LLC_RESP);
	if (rc < 0)
		return SMC_CLC_DECL_TCL;

@@ -469,7 +468,7 @@ static int smc_connect_abort(struct smc_sock *smc, int reason_code,
/* check if there is a rdma device available for this connection. */
/* called for connect and listen */
static int smc_check_rdma(struct smc_sock *smc, struct smc_ib_device **ibdev,
			  u8 *ibport)
			  u8 *ibport, unsigned short vlan_id, u8 gid[])
{
	int reason_code = 0;

@@ -477,7 +476,8 @@ static int smc_check_rdma(struct smc_sock *smc, struct smc_ib_device **ibdev,
	 * within same PNETID that also contains the ethernet device
	 * used for the internal TCP socket
	 */
	smc_pnet_find_roce_resource(smc->clcsock->sk, ibdev, ibport);
	smc_pnet_find_roce_resource(smc->clcsock->sk, ibdev, ibport, vlan_id,
				    gid);
	if (!(*ibdev))
		reason_code = SMC_CLC_DECL_CNFERR; /* configuration error */

@@ -523,12 +523,12 @@ static int smc_connect_ism_vlan_cleanup(struct smc_sock *smc, bool is_smcd,
static int smc_connect_clc(struct smc_sock *smc, int smc_type,
			   struct smc_clc_msg_accept_confirm *aclc,
			   struct smc_ib_device *ibdev, u8 ibport,
			   struct smcd_dev *ismdev)
			   u8 gid[], struct smcd_dev *ismdev)
{
	int rc = 0;

	/* do inband token exchange */
	rc = smc_clc_send_proposal(smc, smc_type, ibdev, ibport, ismdev);
	rc = smc_clc_send_proposal(smc, smc_type, ibdev, ibport, gid, ismdev);
	if (rc)
		return rc;
	/* receive SMC Accept CLC message */
@@ -650,6 +650,7 @@ static int __smc_connect(struct smc_sock *smc)
	struct smc_clc_msg_accept_confirm aclc;
	struct smc_ib_device *ibdev;
	struct smcd_dev *ismdev;
	u8 gid[SMC_GID_SIZE];
	unsigned short vlan;
	int smc_type;
	int rc = 0;
@@ -681,7 +682,7 @@ static int __smc_connect(struct smc_sock *smc)
	}

	/* check if there is a rdma device available */
	if (!smc_check_rdma(smc, &ibdev, &ibport)) {
	if (!smc_check_rdma(smc, &ibdev, &ibport, vlan, gid)) {
		/* RDMA is supported for this connection */
		rdma_supported = true;
		if (ism_supported)
@@ -695,7 +696,7 @@ static int __smc_connect(struct smc_sock *smc)
		return smc_connect_decline_fallback(smc, SMC_CLC_DECL_CNFERR);

	/* perform CLC handshake */
	rc = smc_connect_clc(smc, smc_type, &aclc, ibdev, ibport, ismdev);
	rc = smc_connect_clc(smc, smc_type, &aclc, ibdev, ibport, gid, ismdev);
	if (rc) {
		smc_connect_ism_vlan_cleanup(smc, ism_supported, ismdev, vlan);
		return smc_connect_decline_fallback(smc, rc);
@@ -970,8 +971,7 @@ static int smc_serv_conf_first_link(struct smc_sock *smc)
	/* send ADD LINK request to client over the RoCE fabric */
	rc = smc_llc_send_add_link(link,
				   link->smcibdev->mac[link->ibport - 1],
				   &link->smcibdev->gid[link->ibport - 1],
				   SMC_LLC_REQ);
				   link->gid, SMC_LLC_REQ);
	if (rc < 0)
		return SMC_CLC_DECL_TCL;

@@ -1193,6 +1193,7 @@ static void smc_listen_work(struct work_struct *work)
	struct smcd_dev *ismdev;
	u8 buf[SMC_CLC_MAX_LEN];
	int local_contact = 0;
	unsigned short vlan;
	int reason_code = 0;
	int rc = 0;
	u8 ibport;
@@ -1241,7 +1242,8 @@ static void smc_listen_work(struct work_struct *work)
	/* check if RDMA is available */
	if (!ism_supported &&
	    ((pclc->hdr.path != SMC_TYPE_R && pclc->hdr.path != SMC_TYPE_B) ||
	     smc_check_rdma(new_smc, &ibdev, &ibport) ||
	     smc_vlan_by_tcpsk(new_smc->clcsock, &vlan) ||
	     smc_check_rdma(new_smc, &ibdev, &ibport, vlan, NULL) ||
	     smc_listen_rdma_check(new_smc, pclc) ||
	     smc_listen_rdma_init(new_smc, pclc, ibdev, ibport,
				  &local_contact) ||
+4 −6
Original line number Diff line number Diff line
@@ -378,7 +378,7 @@ 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, int smc_type,
			  struct smc_ib_device *ibdev, u8 ibport,
			  struct smc_ib_device *ibdev, u8 ibport, u8 gid[],
			  struct smcd_dev *ismdev)
{
	struct smc_clc_ipv6_prefix ipv6_prfx[SMC_CLC_MAX_V6_PREFIX];
@@ -409,7 +409,7 @@ int smc_clc_send_proposal(struct smc_sock *smc, int smc_type,
		/* 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.gid, gid, SMC_GID_SIZE);
		memcpy(&pclc.lcl.mac, &ibdev->mac[ibport - 1], ETH_ALEN);
		pclc.iparea_offset = htons(0);
	}
@@ -492,8 +492,7 @@ int smc_clc_send_confirm(struct smc_sock *smc)
		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.gid, link->gid, SMC_GID_SIZE);
		memcpy(&cclc.lcl.mac, &link->smcibdev->mac[link->ibport - 1],
		       ETH_ALEN);
		hton24(cclc.qpn, link->roce_qp->qp_num);
@@ -566,8 +565,7 @@ int smc_clc_send_accept(struct smc_sock *new_smc, int srv_first_contact)
		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.gid, link->gid, SMC_GID_SIZE);
		memcpy(&aclc.lcl.mac, link->smcibdev->mac[link->ibport - 1],
		       ETH_ALEN);
		hton24(aclc.qpn, link->roce_qp->qp_num);
+1 −1
Original line number Diff line number Diff line
@@ -179,7 +179,7 @@ int smc_clc_wait_msg(struct smc_sock *smc, void *buf, int buflen,
		     u8 expected_type);
int smc_clc_send_decline(struct smc_sock *smc, u32 peer_diag_info);
int smc_clc_send_proposal(struct smc_sock *smc, int smc_type,
			  struct smc_ib_device *smcibdev, u8 ibport,
			  struct smc_ib_device *smcibdev, u8 ibport, u8 gid[],
			  struct smcd_dev *ismdev);
int smc_clc_send_confirm(struct smc_sock *smc);
int smc_clc_send_accept(struct smc_sock *smc, int srv_first_contact);
+4 −33
Original line number Diff line number Diff line
@@ -219,6 +219,10 @@ static int smc_lgr_create(struct smc_sock *smc, bool is_smcd,
		get_random_bytes(rndvec, sizeof(rndvec));
		lnk->psn_initial = rndvec[0] + (rndvec[1] << 8) +
			(rndvec[2] << 16);
		rc = smc_ib_determine_gid(lnk->smcibdev, lnk->ibport,
					  vlan_id, lnk->gid, &lnk->sgid_index);
		if (rc)
			goto free_lgr;
		rc = smc_llc_link_init(lnk);
		if (rc)
			goto free_lgr;
@@ -522,37 +526,6 @@ int smc_vlan_by_tcpsk(struct socket *clcsock, unsigned short *vlan_id)
	return rc;
}

/* determine the link gid matching the vlan id of the link group */
static int smc_link_determine_gid(struct smc_link_group *lgr)
{
	struct smc_link *lnk = &lgr->lnk[SMC_SINGLE_LINK];
	struct ib_gid_attr gattr;
	union ib_gid gid;
	int i;

	if (!lgr->vlan_id) {
		lnk->gid = lnk->smcibdev->gid[lnk->ibport - 1];
		return 0;
	}

	for (i = 0; i < lnk->smcibdev->pattr[lnk->ibport - 1].gid_tbl_len;
	     i++) {
		if (ib_query_gid(lnk->smcibdev->ibdev, lnk->ibport, i, &gid,
				 &gattr))
			continue;
		if (gattr.ndev) {
			if (is_vlan_dev(gattr.ndev) &&
			    vlan_dev_vlan_id(gattr.ndev) == lgr->vlan_id) {
				lnk->gid = gid;
				dev_put(gattr.ndev);
				return 0;
			}
			dev_put(gattr.ndev);
		}
	}
	return -ENODEV;
}

static bool smcr_lgr_match(struct smc_link_group *lgr,
			   struct smc_clc_msg_local *lcl,
			   enum smc_lgr_role role)
@@ -631,8 +604,6 @@ int smc_conn_create(struct smc_sock *smc, bool is_smcd, int srv_first_contact,
		if (rc)
			goto out;
		smc_lgr_register_conn(conn); /* add smc conn to lgr */
		if (!is_smcd)
			rc = smc_link_determine_gid(conn->lgr);
	}
	conn->local_tx_ctrl.common.type = SMC_CDC_MSG_TYPE;
	conn->local_tx_ctrl.len = SMC_WR_TX_SIZE;
+3 −2
Original line number Diff line number Diff line
@@ -84,14 +84,15 @@ struct smc_link {
	wait_queue_head_t	wr_reg_wait;	/* wait for wr_reg result */
	enum smc_wr_reg_state	wr_reg_state;	/* state of wr_reg request */

	union ib_gid		gid;		/* gid matching used vlan id */
	u8			gid[SMC_GID_SIZE];/* gid matching used vlan id*/
	u8			sgid_index;	/* gid index for vlan id      */
	u32			peer_qpn;	/* QP number of peer */
	enum ib_mtu		path_mtu;	/* used mtu */
	enum ib_mtu		peer_mtu;	/* mtu size of peer */
	u32			psn_initial;	/* QP tx initial packet seqno */
	u32			peer_psn;	/* QP rx initial packet seqno */
	u8			peer_mac[ETH_ALEN];	/* = gid[8:10||13:15] */
	u8			peer_gid[sizeof(union ib_gid)];	/* gid of peer*/
	u8			peer_gid[SMC_GID_SIZE];	/* gid of peer*/
	u8			link_id;	/* unique # within link group */

	enum smc_link_state	state;		/* state of link */
Loading