RDMA/ocrdma: Support RoCE-v2 in the UD path
This patch adds following changes to support RoCE-v2 in the UD path. * During AH creation GID-type is resolved for a given gid-index. * Based on GID-type protocol header is built. * Work completion reports network header type and set IB_WC_WITH_NETWORK_HDR_TYPE flag in wc->wc_flags to indicate that the network header type is valid. Signed-off-by: Somnath Kotur <somnath.kotur@avagotech.com> Signed-off-by: Devesh Sharma <devesh.sharma@avagotech.com> Signed-off-by: Doug Ledford <dledford@redhat.com>
This commit is contained in:
@@ -55,6 +55,21 @@
|
||||
|
||||
#define OCRDMA_VID_PCP_SHIFT 0xD
|
||||
|
||||
static u16 ocrdma_hdr_type_to_proto_num(int devid, u8 hdr_type)
|
||||
{
|
||||
switch (hdr_type) {
|
||||
case OCRDMA_L3_TYPE_IB_GRH:
|
||||
return (u16)0x8915;
|
||||
case OCRDMA_L3_TYPE_IPV4:
|
||||
return (u16)0x0800;
|
||||
case OCRDMA_L3_TYPE_IPV6:
|
||||
return (u16)0x86dd;
|
||||
default:
|
||||
pr_err("ocrdma%d: Invalid network header\n", devid);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static inline int set_av_attr(struct ocrdma_dev *dev, struct ocrdma_ah *ah,
|
||||
struct ib_ah_attr *attr, union ib_gid *sgid,
|
||||
int pdid, bool *isvlan, u16 vlan_tag)
|
||||
@@ -63,10 +78,23 @@ static inline int set_av_attr(struct ocrdma_dev *dev, struct ocrdma_ah *ah,
|
||||
struct ocrdma_eth_vlan eth;
|
||||
struct ocrdma_grh grh;
|
||||
int eth_sz;
|
||||
u16 proto_num = 0;
|
||||
u8 nxthdr = 0x11;
|
||||
struct iphdr ipv4;
|
||||
union {
|
||||
struct sockaddr _sockaddr;
|
||||
struct sockaddr_in _sockaddr_in;
|
||||
struct sockaddr_in6 _sockaddr_in6;
|
||||
} sgid_addr, dgid_addr;
|
||||
|
||||
memset(ð, 0, sizeof(eth));
|
||||
memset(&grh, 0, sizeof(grh));
|
||||
|
||||
/* Protocol Number */
|
||||
proto_num = ocrdma_hdr_type_to_proto_num(dev->id, ah->hdr_type);
|
||||
if (!proto_num)
|
||||
return -EINVAL;
|
||||
nxthdr = (proto_num == 0x8915) ? 0x1b : 0x11;
|
||||
/* VLAN */
|
||||
if (!vlan_tag || (vlan_tag > 0xFFF))
|
||||
vlan_tag = dev->pvid;
|
||||
@@ -78,13 +106,13 @@ static inline int set_av_attr(struct ocrdma_dev *dev, struct ocrdma_ah *ah,
|
||||
dev->id);
|
||||
}
|
||||
eth.eth_type = cpu_to_be16(0x8100);
|
||||
eth.roce_eth_type = cpu_to_be16(OCRDMA_ROCE_ETH_TYPE);
|
||||
eth.roce_eth_type = cpu_to_be16(proto_num);
|
||||
vlan_tag |= (dev->sl & 0x07) << OCRDMA_VID_PCP_SHIFT;
|
||||
eth.vlan_tag = cpu_to_be16(vlan_tag);
|
||||
eth_sz = sizeof(struct ocrdma_eth_vlan);
|
||||
*isvlan = true;
|
||||
} else {
|
||||
eth.eth_type = cpu_to_be16(OCRDMA_ROCE_ETH_TYPE);
|
||||
eth.eth_type = cpu_to_be16(proto_num);
|
||||
eth_sz = sizeof(struct ocrdma_eth_basic);
|
||||
}
|
||||
/* MAC */
|
||||
@@ -93,18 +121,33 @@ static inline int set_av_attr(struct ocrdma_dev *dev, struct ocrdma_ah *ah,
|
||||
if (status)
|
||||
return status;
|
||||
ah->sgid_index = attr->grh.sgid_index;
|
||||
memcpy(&grh.sgid[0], sgid->raw, sizeof(union ib_gid));
|
||||
memcpy(&grh.dgid[0], attr->grh.dgid.raw, sizeof(attr->grh.dgid.raw));
|
||||
|
||||
grh.tclass_flow = cpu_to_be32((6 << 28) |
|
||||
(attr->grh.traffic_class << 24) |
|
||||
attr->grh.flow_label);
|
||||
/* 0x1b is next header value in GRH */
|
||||
grh.pdid_hoplimit = cpu_to_be32((pdid << 16) |
|
||||
(0x1b << 8) | attr->grh.hop_limit);
|
||||
/* Eth HDR */
|
||||
memcpy(&ah->av->eth_hdr, ð, eth_sz);
|
||||
memcpy((u8 *)ah->av + eth_sz, &grh, sizeof(struct ocrdma_grh));
|
||||
if (ah->hdr_type == RDMA_NETWORK_IPV4) {
|
||||
*((__be16 *)&ipv4) = htons((4 << 12) | (5 << 8) |
|
||||
attr->grh.traffic_class);
|
||||
ipv4.id = cpu_to_be16(pdid);
|
||||
ipv4.frag_off = htons(IP_DF);
|
||||
ipv4.tot_len = htons(0);
|
||||
ipv4.ttl = attr->grh.hop_limit;
|
||||
ipv4.protocol = nxthdr;
|
||||
rdma_gid2ip(&sgid_addr._sockaddr, sgid);
|
||||
ipv4.saddr = sgid_addr._sockaddr_in.sin_addr.s_addr;
|
||||
rdma_gid2ip(&dgid_addr._sockaddr, &attr->grh.dgid);
|
||||
ipv4.daddr = dgid_addr._sockaddr_in.sin_addr.s_addr;
|
||||
memcpy((u8 *)ah->av + eth_sz, &ipv4, sizeof(struct iphdr));
|
||||
} else {
|
||||
memcpy(&grh.sgid[0], sgid->raw, sizeof(union ib_gid));
|
||||
grh.tclass_flow = cpu_to_be32((6 << 28) |
|
||||
(attr->grh.traffic_class << 24) |
|
||||
attr->grh.flow_label);
|
||||
memcpy(&grh.dgid[0], attr->grh.dgid.raw,
|
||||
sizeof(attr->grh.dgid.raw));
|
||||
grh.pdid_hoplimit = cpu_to_be32((pdid << 16) |
|
||||
(nxthdr << 8) |
|
||||
attr->grh.hop_limit);
|
||||
memcpy((u8 *)ah->av + eth_sz, &grh, sizeof(struct ocrdma_grh));
|
||||
}
|
||||
if (*isvlan)
|
||||
ah->av->valid |= OCRDMA_AV_VLAN_VALID;
|
||||
ah->av->valid = cpu_to_le32(ah->av->valid);
|
||||
@@ -128,6 +171,7 @@ struct ib_ah *ocrdma_create_ah(struct ib_pd *ibpd, struct ib_ah_attr *attr)
|
||||
|
||||
if (atomic_cmpxchg(&dev->update_sl, 1, 0))
|
||||
ocrdma_init_service_level(dev);
|
||||
|
||||
ah = kzalloc(sizeof(*ah), GFP_ATOMIC);
|
||||
if (!ah)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
@@ -148,6 +192,8 @@ struct ib_ah *ocrdma_create_ah(struct ib_pd *ibpd, struct ib_ah_attr *attr)
|
||||
vlan_tag = vlan_dev_vlan_id(sgid_attr.ndev);
|
||||
dev_put(sgid_attr.ndev);
|
||||
}
|
||||
/* Get network header type for this GID */
|
||||
ah->hdr_type = ib_gid_to_network_type(sgid_attr.gid_type, &sgid);
|
||||
|
||||
if ((pd->uctx) &&
|
||||
(!rdma_is_multicast_addr((struct in6_addr *)attr->grh.dgid.raw)) &&
|
||||
|
Reference in New Issue
Block a user