Пример #1
0
static inline int set_av_attr(struct ocrdma_dev *dev, struct ocrdma_ah *ah,
                              struct ib_ah_attr *attr, int pdid)
{
    int status = 0;
    u16 vlan_tag;
    bool vlan_enabled = false;
    struct ocrdma_eth_vlan eth;
    struct ocrdma_grh grh;
    int eth_sz;

    memset(&eth, 0, sizeof(eth));
    memset(&grh, 0, sizeof(grh));

    ah->sgid_index = attr->grh.sgid_index;

    vlan_tag = attr->vlan_id;
    if (!vlan_tag || (vlan_tag > 0xFFF))
        vlan_tag = dev->pvid;
    if (vlan_tag && (vlan_tag < 0x1000)) {
        eth.eth_type = cpu_to_be16(0x8100);
        eth.roce_eth_type = cpu_to_be16(OCRDMA_ROCE_ETH_TYPE);
        vlan_tag |= (dev->sl & 0x07) << OCRDMA_VID_PCP_SHIFT;
        eth.vlan_tag = cpu_to_be16(vlan_tag);
        eth_sz = sizeof(struct ocrdma_eth_vlan);
        vlan_enabled = true;
    } else {
        eth.eth_type = cpu_to_be16(OCRDMA_ROCE_ETH_TYPE);
        eth_sz = sizeof(struct ocrdma_eth_basic);
    }
    memcpy(&eth.smac[0], &dev->nic_info.mac_addr[0], ETH_ALEN);
    memcpy(&eth.dmac[0], attr->dmac, ETH_ALEN);
    status = ocrdma_resolve_dmac(dev, attr, &eth.dmac[0]);
    if (status)
        return status;
    status = ocrdma_query_gid(&dev->ibdev, 1, attr->grh.sgid_index,
                              (union ib_gid *)&grh.sgid[0]);
    if (status)
        return status;

    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);

    memcpy(&grh.dgid[0], attr->grh.dgid.raw, sizeof(attr->grh.dgid.raw));
    memcpy(&ah->av->eth_hdr, &eth, eth_sz);
    memcpy((u8 *)ah->av + eth_sz, &grh, sizeof(struct ocrdma_grh));
    if (vlan_enabled)
        ah->av->valid |= OCRDMA_AV_VLAN_VALID;
    ah->av->valid = cpu_to_le32(ah->av->valid);
    return status;
}
Пример #2
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)
{
	int status;
	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(&eth, 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;
	if (vlan_tag || dev->pfc_state) {
		if (!vlan_tag) {
			pr_err("ocrdma%d:Using VLAN with PFC is recommended\n",
				dev->id);
			pr_err("ocrdma%d:Using VLAN 0 for this connection\n",
				dev->id);
		}
		eth.eth_type = cpu_to_be16(0x8100);
		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(proto_num);
		eth_sz = sizeof(struct ocrdma_eth_basic);
	}
	/* MAC */
	memcpy(&eth.smac[0], &dev->nic_info.mac_addr[0], ETH_ALEN);
	status = ocrdma_resolve_dmac(dev, attr, &eth.dmac[0]);
	if (status)
		return status;
	ah->sgid_index = attr->grh.sgid_index;
	/* Eth HDR */
	memcpy(&ah->av->eth_hdr, &eth, eth_sz);
	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);
	return status;
}