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

Commit b7403217 authored by Parav Pandit's avatar Parav Pandit Committed by Jason Gunthorpe
Browse files

IB: Make ib_init_ah_attr_from_wc set sgid_attr



The work completion is inspected to determine what dgid table entry was
used to receieve the packet, produces a sgid_attr that matches and sticks
it in the ah_attr.

All callers of this function are now required to release the ah_attr on
success.

Signed-off-by: default avatarParav Pandit <parav@mellanox.com>
Signed-off-by: default avatarJason Gunthorpe <jgg@mellanox.com>
Signed-off-by: default avatarLeon Romanovsky <leonro@mellanox.com>
parent 70324739
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -1091,6 +1091,9 @@ static void cm_destroy_id(struct ib_cm_id *cm_id, int err)
	wait_for_completion(&cm_id_priv->comp);
	while ((work = cm_dequeue_work(cm_id_priv)) != NULL)
		cm_free_work(work);

	rdma_destroy_ah_attr(&cm_id_priv->av.ah_attr);
	rdma_destroy_ah_attr(&cm_id_priv->alt_av.ah_attr);
	kfree(cm_id_priv->private_data);
	kfree(cm_id_priv);
}
+1 −0
Original line number Diff line number Diff line
@@ -268,6 +268,7 @@ static void recv_handler(struct ib_mad_agent *agent,
		packet->mad.hdr.traffic_class = grh->traffic_class;
		memcpy(packet->mad.hdr.gid, &grh->dgid, 16);
		packet->mad.hdr.flow_label = cpu_to_be32(grh->flow_label);
		rdma_destroy_ah_attr(&ah_attr);
	}

	if (queue_packet(file, agent, packet))
+56 −54
Original line number Diff line number Diff line
@@ -636,16 +636,16 @@ static bool find_gid_index(const union ib_gid *gid,
	return true;
}

static int get_sgid_index_from_eth(struct ib_device *device, u8 port_num,
static const struct ib_gid_attr *
get_sgid_attr_from_eth(struct ib_device *device, u8 port_num,
		       u16 vlan_id, const union ib_gid *sgid,
				   enum ib_gid_type gid_type,
				   u16 *gid_index)
		       enum ib_gid_type gid_type)
{
	struct find_gid_index_context context = {.vlan_id = vlan_id,
						 .gid_type = gid_type};

	return ib_find_gid_by_filter(device, sgid, port_num, find_gid_index,
				     &context, gid_index);
	return rdma_find_gid_by_filter(device, sgid, port_num, find_gid_index,
				       &context);
}

int ib_get_gids_from_rdma_hdr(const union rdma_network_hdr *hdr,
@@ -689,37 +689,24 @@ EXPORT_SYMBOL(ib_get_gids_from_rdma_hdr);
static int ib_resolve_unicast_gid_dmac(struct ib_device *device,
				       struct rdma_ah_attr *ah_attr)
{
	struct ib_gid_attr sgid_attr;
	struct ib_global_route *grh;
	struct ib_global_route *grh = rdma_ah_retrieve_grh(ah_attr);
	const struct ib_gid_attr *sgid_attr = grh->sgid_attr;
	int hop_limit = 0xff;
	union ib_gid sgid;
	int ret;

	grh = rdma_ah_retrieve_grh(ah_attr);

	ret = ib_get_cached_gid(device, rdma_ah_get_port_num(ah_attr),
				grh->sgid_index, &sgid, &sgid_attr);
	if (ret || !sgid_attr.ndev) {
		if (!ret)
			ret = -ENXIO;
		return ret;
	}
	int ret = 0;

	/* If destination is link local and source GID is RoCEv1,
	 * IP stack is not used.
	 */
	if (rdma_link_local_addr((struct in6_addr *)grh->dgid.raw) &&
	    sgid_attr.gid_type == IB_GID_TYPE_ROCE) {
	    sgid_attr->gid_type == IB_GID_TYPE_ROCE) {
		rdma_get_ll_mac((struct in6_addr *)grh->dgid.raw,
				ah_attr->roce.dmac);
		goto done;
		return ret;
	}

	ret = rdma_addr_find_l2_eth_by_grh(&sgid, &grh->dgid,
	ret = rdma_addr_find_l2_eth_by_grh(&sgid_attr->gid, &grh->dgid,
					   ah_attr->roce.dmac,
					   sgid_attr.ndev, &hop_limit);
done:
	dev_put(sgid_attr.ndev);
					   sgid_attr->ndev, &hop_limit);

	grh->hop_limit = hop_limit;
	return ret;
@@ -734,16 +721,18 @@ static int ib_resolve_unicast_gid_dmac(struct ib_device *device,
 * as sgid and, sgid is used as dgid because sgid contains destinations
 * GID whom to respond to.
 *
 * On success the caller is responsible to call rdma_destroy_ah_attr on the
 * attr.
 */
int ib_init_ah_attr_from_wc(struct ib_device *device, u8 port_num,
			    const struct ib_wc *wc, const struct ib_grh *grh,
			    struct rdma_ah_attr *ah_attr)
{
	u32 flow_class;
	u16 gid_index;
	int ret;
	enum rdma_network_type net_type = RDMA_NETWORK_IB;
	enum ib_gid_type gid_type = IB_GID_TYPE_IB;
	const struct ib_gid_attr *sgid_attr;
	int hoplimit = 0xff;
	union ib_gid dgid;
	union ib_gid sgid;
@@ -774,40 +763,49 @@ int ib_init_ah_attr_from_wc(struct ib_device *device, u8 port_num,
		if (!(wc->wc_flags & IB_WC_GRH))
			return -EPROTOTYPE;

		ret = get_sgid_index_from_eth(device, port_num,
		sgid_attr = get_sgid_attr_from_eth(device, port_num,
						   vlan_id, &dgid,
					      gid_type, &gid_index);
		if (ret)
			return ret;
						   gid_type);
		if (IS_ERR(sgid_attr))
			return PTR_ERR(sgid_attr);

		flow_class = be32_to_cpu(grh->version_tclass_flow);
		rdma_ah_set_grh(ah_attr, &sgid,
		rdma_move_grh_sgid_attr(ah_attr,
					&sgid,
					flow_class & 0xFFFFF,
				(u8)gid_index, hoplimit,
				(flow_class >> 20) & 0xFF);
		return ib_resolve_unicast_gid_dmac(device, ah_attr);
	} else {
		rdma_ah_set_dlid(ah_attr, wc->slid);
		rdma_ah_set_path_bits(ah_attr, wc->dlid_path_bits);
					hoplimit,
					(flow_class >> 20) & 0xFF,
					sgid_attr);

		if (wc->wc_flags & IB_WC_GRH) {
			if (dgid.global.interface_id != cpu_to_be64(IB_SA_WELL_KNOWN_GUID)) {
				ret = ib_find_cached_gid_by_port(device, &dgid,
								 IB_GID_TYPE_IB,
								 port_num, NULL,
								 &gid_index);
		ret = ib_resolve_unicast_gid_dmac(device, ah_attr);
		if (ret)
			rdma_destroy_ah_attr(ah_attr);

		return ret;
	} else {
				gid_index = 0;
			}
		rdma_ah_set_dlid(ah_attr, wc->slid);
		rdma_ah_set_path_bits(ah_attr, wc->dlid_path_bits);

		if ((wc->wc_flags & IB_WC_GRH) == 0)
			return 0;

		if (dgid.global.interface_id !=
					cpu_to_be64(IB_SA_WELL_KNOWN_GUID)) {
			sgid_attr = rdma_find_gid_by_port(
				device, &dgid, IB_GID_TYPE_IB, port_num, NULL);
		} else
			sgid_attr = rdma_get_gid_attr(device, port_num, 0);

		if (IS_ERR(sgid_attr))
			return PTR_ERR(sgid_attr);
		flow_class = be32_to_cpu(grh->version_tclass_flow);
			rdma_ah_set_grh(ah_attr, &sgid,
		rdma_move_grh_sgid_attr(ah_attr,
					&sgid,
					flow_class & 0xFFFFF,
					(u8)gid_index, hoplimit,
					(flow_class >> 20) & 0xFF);
		}
					hoplimit,
					(flow_class >> 20) & 0xFF,
					sgid_attr);

		return 0;
	}
}
@@ -860,13 +858,17 @@ struct ib_ah *ib_create_ah_from_wc(struct ib_pd *pd, const struct ib_wc *wc,
				   const struct ib_grh *grh, u8 port_num)
{
	struct rdma_ah_attr ah_attr;
	struct ib_ah *ah;
	int ret;

	ret = ib_init_ah_attr_from_wc(pd->device, port_num, wc, grh, &ah_attr);
	if (ret)
		return ERR_PTR(ret);

	return rdma_create_ah(pd, &ah_attr);
	ah = rdma_create_ah(pd, &ah_attr);

	rdma_destroy_ah_attr(&ah_attr);
	return ah;
}
EXPORT_SYMBOL(ib_create_ah_from_wc);

+7 −0
Original line number Diff line number Diff line
@@ -3150,6 +3150,13 @@ int ib_get_rdma_header_version(const union rdma_network_hdr *hdr);
 *   ignored unless the work completion indicates that the GRH is valid.
 * @ah_attr: Returned attributes that can be used when creating an address
 *   handle for replying to the message.
 * When ib_init_ah_attr_from_wc() returns success,
 * (a) for IB link layer it optionally contains a reference to SGID attribute
 * when GRH is present for IB link layer.
 * (b) for RoCE link layer it contains a reference to SGID attribute.
 * User must invoke rdma_cleanup_ah_attr_gid_attr() to release reference to SGID
 * attributes which are initialized using ib_init_ah_attr_from_wc().
 *
 */
int ib_init_ah_attr_from_wc(struct ib_device *device, u8 port_num,
			    const struct ib_wc *wc, const struct ib_grh *grh,