IB/hfi1: Add support to process 16B header errors

Enhance hdr_rcverr() to also handle errors during
16B bypass packet receive.

Reviewed-by: Dennis Dalessandro <dennis.dalessandro@intel.com>
Signed-off-by: Don Hiatt <don.hiatt@intel.com>
Signed-off-by: Dennis Dalessandro <dennis.dalessandro@intel.com>
Signed-off-by: Doug Ledford <dledford@redhat.com>
This commit is contained in:
Don Hiatt 2017-08-04 13:54:10 -07:00 committed by Doug Ledford
parent 30e07416cf
commit 5786adf3fd
6 changed files with 112 additions and 33 deletions

View file

@ -269,8 +269,7 @@ static void rcv_hdrerr(struct hfi1_ctxtdata *rcd, struct hfi1_pportdata *ppd,
{ {
struct ib_header *rhdr = packet->hdr; struct ib_header *rhdr = packet->hdr;
u32 rte = rhf_rcv_type_err(packet->rhf); u32 rte = rhf_rcv_type_err(packet->rhf);
u8 lnh = ib_get_lnh(rhdr); u32 mlid_base;
bool has_grh = false;
struct hfi1_ibport *ibp = rcd_to_iport(rcd); struct hfi1_ibport *ibp = rcd_to_iport(rcd);
struct hfi1_devdata *dd = ppd->dd; struct hfi1_devdata *dd = ppd->dd;
struct rvt_dev_info *rdi = &dd->verbs_dev.rdi; struct rvt_dev_info *rdi = &dd->verbs_dev.rdi;
@ -278,14 +277,20 @@ static void rcv_hdrerr(struct hfi1_ctxtdata *rcd, struct hfi1_pportdata *ppd,
if (packet->rhf & (RHF_VCRC_ERR | RHF_ICRC_ERR)) if (packet->rhf & (RHF_VCRC_ERR | RHF_ICRC_ERR))
return; return;
if (lnh == HFI1_LRH_BTH) { if (packet->etype == RHF_RCV_TYPE_BYPASS) {
packet->ohdr = &rhdr->u.oth;
} else if (lnh == HFI1_LRH_GRH) {
has_grh = true;
packet->ohdr = &rhdr->u.l.oth;
packet->grh = &rhdr->u.l.grh;
} else {
goto drop; goto drop;
} else {
u8 lnh = ib_get_lnh(rhdr);
mlid_base = be16_to_cpu(IB_MULTICAST_LID_BASE);
if (lnh == HFI1_LRH_BTH) {
packet->ohdr = &rhdr->u.oth;
} else if (lnh == HFI1_LRH_GRH) {
packet->ohdr = &rhdr->u.l.oth;
packet->grh = &rhdr->u.l.grh;
} else {
goto drop;
}
} }
if (packet->rhf & RHF_TID_ERR) { if (packet->rhf & RHF_TID_ERR) {
@ -293,14 +298,13 @@ static void rcv_hdrerr(struct hfi1_ctxtdata *rcd, struct hfi1_pportdata *ppd,
u32 tlen = rhf_pkt_len(packet->rhf); /* in bytes */ u32 tlen = rhf_pkt_len(packet->rhf); /* in bytes */
u32 dlid = ib_get_dlid(rhdr); u32 dlid = ib_get_dlid(rhdr);
u32 qp_num; u32 qp_num;
u32 mlid_base = be16_to_cpu(IB_MULTICAST_LID_BASE);
/* Sanity check packet */ /* Sanity check packet */
if (tlen < 24) if (tlen < 24)
goto drop; goto drop;
/* Check for GRH */ /* Check for GRH */
if (has_grh) { if (packet->grh) {
u32 vtf; u32 vtf;
struct ib_grh *grh = packet->grh; struct ib_grh *grh = packet->grh;
@ -1370,6 +1374,35 @@ static inline void hfi1_setup_ib_header(struct hfi1_packet *packet)
packet->hlen = (u8 *)packet->rhf_addr - (u8 *)packet->hdr; packet->hlen = (u8 *)packet->rhf_addr - (u8 *)packet->hdr;
} }
static int hfi1_bypass_ingress_pkt_check(struct hfi1_packet *packet)
{
struct hfi1_pportdata *ppd = packet->rcd->ppd;
/* slid and dlid cannot be 0 */
if ((!packet->slid) || (!packet->dlid))
return -EINVAL;
/* Compare port lid with incoming packet dlid */
if ((!(hfi1_is_16B_mcast(packet->dlid))) &&
(packet->dlid !=
opa_get_lid(be32_to_cpu(OPA_LID_PERMISSIVE), 16B))) {
if (packet->dlid != ppd->lid)
return -EINVAL;
}
/* No multicast packets with SC15 */
if ((hfi1_is_16B_mcast(packet->dlid)) && (packet->sc == 0xF))
return -EINVAL;
/* Packets with permissive DLID always on SC15 */
if ((packet->dlid == opa_get_lid(be32_to_cpu(OPA_LID_PERMISSIVE),
16B)) &&
(packet->sc != 0xF))
return -EINVAL;
return 0;
}
static int hfi1_setup_9B_packet(struct hfi1_packet *packet) static int hfi1_setup_9B_packet(struct hfi1_packet *packet)
{ {
struct hfi1_ibport *ibp = rcd_to_iport(packet->rcd); struct hfi1_ibport *ibp = rcd_to_iport(packet->rcd);
@ -1479,6 +1512,9 @@ static int hfi1_setup_bypass_packet(struct hfi1_packet *packet)
packet->fecn = hfi1_16B_get_fecn(packet->hdr); packet->fecn = hfi1_16B_get_fecn(packet->hdr);
packet->becn = hfi1_16B_get_becn(packet->hdr); packet->becn = hfi1_16B_get_becn(packet->hdr);
if (hfi1_bypass_ingress_pkt_check(packet))
goto drop;
return 0; return 0;
drop: drop:
hfi1_cdbg(PKT, "%s: packet dropped\n", __func__); hfi1_cdbg(PKT, "%s: packet dropped\n", __func__);

View file

@ -372,6 +372,10 @@ struct hfi1_packet {
#define OPA_16B_FECN_SHIFT 28 #define OPA_16B_FECN_SHIFT 28
#define OPA_16B_L2_MASK 0x60000000ull #define OPA_16B_L2_MASK 0x60000000ull
#define OPA_16B_L2_SHIFT 29 #define OPA_16B_L2_SHIFT 29
#define OPA_16B_PKEY_MASK 0xFFFF0000ull
#define OPA_16B_PKEY_SHIFT 16
#define OPA_16B_LEN_MASK 0x7FF00000ull
#define OPA_16B_LEN_SHIFT 20
/* /*
* OPA 16B L2/L4 Encodings * OPA 16B L2/L4 Encodings
@ -420,6 +424,11 @@ static inline u8 hfi1_16B_get_l2(struct hfi1_16b_header *hdr)
return (u8)((hdr->lrh[1] & OPA_16B_L2_MASK) >> OPA_16B_L2_SHIFT); return (u8)((hdr->lrh[1] & OPA_16B_L2_MASK) >> OPA_16B_L2_SHIFT);
} }
static inline u16 hfi1_16B_get_pkey(struct hfi1_16b_header *hdr)
{
return (u16)((hdr->lrh[2] & OPA_16B_PKEY_MASK) >> OPA_16B_PKEY_SHIFT);
}
/* /*
* BTH * BTH
*/ */
@ -1597,9 +1606,9 @@ static void ingress_pkey_table_fail(struct hfi1_pportdata *ppd, u16 pkey,
* by HW and rcv_pkey_check function should be called instead. * by HW and rcv_pkey_check function should be called instead.
*/ */
static inline int ingress_pkey_check(struct hfi1_pportdata *ppd, u16 pkey, static inline int ingress_pkey_check(struct hfi1_pportdata *ppd, u16 pkey,
u8 sc5, u8 idx, u16 slid) u8 sc5, u8 idx, u32 slid, bool force)
{ {
if (!(ppd->part_enforce & HFI1_PART_ENFORCE_IN)) if (!(force) && !(ppd->part_enforce & HFI1_PART_ENFORCE_IN))
return 0; return 0;
/* If SC15, pkey[0:14] must be 0x7fff */ /* If SC15, pkey[0:14] must be 0x7fff */

View file

@ -227,15 +227,23 @@ int hfi1_ruc_check_hdr(struct hfi1_ibport *ibp, struct hfi1_packet *packet)
u32 sl = packet->sl; u32 sl = packet->sl;
int migrated; int migrated;
u32 bth0, bth1; u32 bth0, bth1;
u16 pkey;
bth0 = be32_to_cpu(packet->ohdr->bth[0]); bth0 = be32_to_cpu(packet->ohdr->bth[0]);
bth1 = be32_to_cpu(packet->ohdr->bth[1]); bth1 = be32_to_cpu(packet->ohdr->bth[1]);
migrated = bth0 & IB_BTH_MIG_REQ; if (packet->etype == RHF_RCV_TYPE_BYPASS) {
pkey = hfi1_16B_get_pkey(packet->hdr);
migrated = bth1 & OPA_BTH_MIG_REQ;
} else {
pkey = ib_bth_get_pkey(packet->ohdr);
migrated = bth0 & IB_BTH_MIG_REQ;
}
if (qp->s_mig_state == IB_MIG_ARMED && migrated) { if (qp->s_mig_state == IB_MIG_ARMED && migrated) {
if (!packet->grh) { if (!packet->grh) {
if (rdma_ah_get_ah_flags(&qp->alt_ah_attr) & if ((rdma_ah_get_ah_flags(&qp->alt_ah_attr) &
IB_AH_GRH) IB_AH_GRH) &&
(packet->etype != RHF_RCV_TYPE_BYPASS))
return 1; return 1;
} else { } else {
const struct ib_global_route *grh; const struct ib_global_route *grh;
@ -254,10 +262,10 @@ int hfi1_ruc_check_hdr(struct hfi1_ibport *ibp, struct hfi1_packet *packet)
grh->dgid.global.interface_id)) grh->dgid.global.interface_id))
return 1; return 1;
} }
if (unlikely(rcv_pkey_check(ppd_from_ibp(ibp), (u16)bth0, if (unlikely(rcv_pkey_check(ppd_from_ibp(ibp), pkey,
sc5, slid))) { sc5, slid))) {
hfi1_bad_pkey(ibp, (u16)bth0, sl, hfi1_bad_pkey(ibp, pkey, sl, 0, qp->ibqp.qp_num,
0, qp->ibqp.qp_num, slid, dlid); slid, dlid);
return 1; return 1;
} }
/* Validate the SLID. See Ch. 9.6.1.5 and 17.2.8 */ /* Validate the SLID. See Ch. 9.6.1.5 and 17.2.8 */
@ -270,8 +278,9 @@ int hfi1_ruc_check_hdr(struct hfi1_ibport *ibp, struct hfi1_packet *packet)
spin_unlock_irqrestore(&qp->s_lock, flags); spin_unlock_irqrestore(&qp->s_lock, flags);
} else { } else {
if (!packet->grh) { if (!packet->grh) {
if (rdma_ah_get_ah_flags(&qp->remote_ah_attr) & if ((rdma_ah_get_ah_flags(&qp->remote_ah_attr) &
IB_AH_GRH) IB_AH_GRH) &&
(packet->etype != RHF_RCV_TYPE_BYPASS))
return 1; return 1;
} else { } else {
const struct ib_global_route *grh; const struct ib_global_route *grh;
@ -290,10 +299,10 @@ int hfi1_ruc_check_hdr(struct hfi1_ibport *ibp, struct hfi1_packet *packet)
grh->dgid.global.interface_id)) grh->dgid.global.interface_id))
return 1; return 1;
} }
if (unlikely(rcv_pkey_check(ppd_from_ibp(ibp), (u16)bth0, if (unlikely(rcv_pkey_check(ppd_from_ibp(ibp), pkey,
sc5, slid))) { sc5, slid))) {
hfi1_bad_pkey(ibp, (u16)bth0, sl, hfi1_bad_pkey(ibp, pkey, sl, 0, qp->ibqp.qp_num,
0, qp->ibqp.qp_num, slid, dlid); slid, dlid);
return 1; return 1;
} }
/* Validate the SLID. See Ch. 9.6.1.5 */ /* Validate the SLID. See Ch. 9.6.1.5 */

View file

@ -109,7 +109,8 @@ static void ud_loopback(struct rvt_qp *sqp, struct rvt_swqe *swqe)
slid = ppd->lid | (rdma_ah_get_path_bits(ah_attr) & slid = ppd->lid | (rdma_ah_get_path_bits(ah_attr) &
((1 << ppd->lmc) - 1)); ((1 << ppd->lmc) - 1));
if (unlikely(ingress_pkey_check(ppd, pkey, sc5, if (unlikely(ingress_pkey_check(ppd, pkey, sc5,
qp->s_pkey_index, slid))) { qp->s_pkey_index,
slid, false))) {
hfi1_bad_pkey(ibp, pkey, hfi1_bad_pkey(ibp, pkey,
rdma_ah_get_sl(ah_attr), rdma_ah_get_sl(ah_attr),
sqp->ibqp.qp_num, qp->ibqp.qp_num, sqp->ibqp.qp_num, qp->ibqp.qp_num,

View file

@ -568,6 +568,24 @@ static u64 hfi1_fault_tx(struct rvt_qp *qp, u8 opcode, u64 pbc)
return pbc; return pbc;
} }
static int hfi1_do_pkey_check(struct hfi1_packet *packet)
{
struct hfi1_ctxtdata *rcd = packet->rcd;
struct hfi1_pportdata *ppd = rcd->ppd;
struct hfi1_16b_header *hdr = packet->hdr;
u16 pkey;
/* Pkey check needed only for bypass packets */
if (packet->etype != RHF_RCV_TYPE_BYPASS)
return 0;
/* Perform pkey check */
pkey = hfi1_16B_get_pkey(hdr);
return ingress_pkey_check(ppd, pkey, packet->sc,
packet->qp->s_pkey_index,
packet->slid, true);
}
static inline void hfi1_handle_packet(struct hfi1_packet *packet, static inline void hfi1_handle_packet(struct hfi1_packet *packet,
bool is_mcast) bool is_mcast)
{ {
@ -594,6 +612,8 @@ static inline void hfi1_handle_packet(struct hfi1_packet *packet,
goto drop; goto drop;
list_for_each_entry_rcu(p, &mcast->qp_list, list) { list_for_each_entry_rcu(p, &mcast->qp_list, list) {
packet->qp = p->qp; packet->qp = p->qp;
if (hfi1_do_pkey_check(packet))
goto drop;
spin_lock_irqsave(&packet->qp->r_lock, flags); spin_lock_irqsave(&packet->qp->r_lock, flags);
packet_handler = qp_ok(packet); packet_handler = qp_ok(packet);
if (likely(packet_handler)) if (likely(packet_handler))
@ -613,15 +633,16 @@ static inline void hfi1_handle_packet(struct hfi1_packet *packet,
qp_num = ib_bth_get_qpn(packet->ohdr); qp_num = ib_bth_get_qpn(packet->ohdr);
rcu_read_lock(); rcu_read_lock();
packet->qp = rvt_lookup_qpn(rdi, &ibp->rvp, qp_num); packet->qp = rvt_lookup_qpn(rdi, &ibp->rvp, qp_num);
if (!packet->qp) { if (!packet->qp)
rcu_read_unlock(); goto unlock_drop;
goto drop;
} if (hfi1_do_pkey_check(packet))
goto unlock_drop;
if (unlikely(hfi1_dbg_fault_opcode(packet->qp, packet->opcode, if (unlikely(hfi1_dbg_fault_opcode(packet->qp, packet->opcode,
true))) { true)))
rcu_read_unlock(); goto unlock_drop;
goto drop;
}
spin_lock_irqsave(&packet->qp->r_lock, flags); spin_lock_irqsave(&packet->qp->r_lock, flags);
packet_handler = qp_ok(packet); packet_handler = qp_ok(packet);
if (likely(packet_handler)) if (likely(packet_handler))
@ -632,6 +653,8 @@ static inline void hfi1_handle_packet(struct hfi1_packet *packet,
rcu_read_unlock(); rcu_read_unlock();
} }
return; return;
unlock_drop:
rcu_read_unlock();
drop: drop:
ibp->rvp.n_pkt_drops++; ibp->rvp.n_pkt_drops++;
} }

View file

@ -95,6 +95,7 @@ struct hfi1_packet;
#define HFI1_VENDOR_IPG cpu_to_be16(0xFFA0) #define HFI1_VENDOR_IPG cpu_to_be16(0xFFA0)
#define IB_DEFAULT_GID_PREFIX cpu_to_be64(0xfe80000000000000ULL) #define IB_DEFAULT_GID_PREFIX cpu_to_be64(0xfe80000000000000ULL)
#define OPA_BTH_MIG_REQ BIT(31)
#define RC_OP(x) IB_OPCODE_RC_##x #define RC_OP(x) IB_OPCODE_RC_##x
#define UC_OP(x) IB_OPCODE_UC_##x #define UC_OP(x) IB_OPCODE_UC_##x