diff options
author | Chad Dupuis <chad.dupuis@cavium.com> | 2017-05-31 16:33:57 +0300 |
---|---|---|
committer | Martin K. Petersen <martin.petersen@oracle.com> | 2017-06-13 03:48:06 +0300 |
commit | 384d5a9b412ea0fb60f999c13d39a1f007d87730 (patch) | |
tree | 128fc4e8cfe24c0824f530d1ce3d6db32054b4b8 /drivers/scsi/qedf/qedf_main.c | |
parent | b09fdc3aac6acc20587713e306692b12d31a2008 (diff) | |
download | linux-384d5a9b412ea0fb60f999c13d39a1f007d87730.tar.xz |
scsi: qedf: Add non-offload receive filters.
Drop invalid or unexpected FCoE frames that come into the non-offload path
since the FCoE firmware would not do the filtering for us.
Signed-off-by: Chad Dupuis <chad.dupuis@cavium.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Diffstat (limited to 'drivers/scsi/qedf/qedf_main.c')
-rw-r--r-- | drivers/scsi/qedf/qedf_main.c | 43 |
1 files changed, 43 insertions, 0 deletions
diff --git a/drivers/scsi/qedf/qedf_main.c b/drivers/scsi/qedf/qedf_main.c index ef0dc566d70f..b7d17e177cf0 100644 --- a/drivers/scsi/qedf/qedf_main.c +++ b/drivers/scsi/qedf/qedf_main.c @@ -2087,6 +2087,8 @@ static void qedf_recv_frame(struct qedf_ctx *qedf, u8 *dest_mac = NULL; struct fcoe_hdr *hp; struct qedf_rport *fcport; + struct fc_lport *vn_port; + u32 f_ctl; lport = qedf->lport; if (lport == NULL || lport->state == LPORT_ST_DISABLED) { @@ -2123,6 +2125,10 @@ static void qedf_recv_frame(struct qedf_ctx *qedf, fh = fc_frame_header_get(fp); + /* + * Invalid frame filters. + */ + if (fh->fh_r_ctl == FC_RCTL_DD_SOL_DATA && fh->fh_type == FC_TYPE_FCP) { /* Drop FCP data. We dont this in L2 path */ @@ -2148,6 +2154,43 @@ static void qedf_recv_frame(struct qedf_ctx *qedf, return; } + if (ntoh24(&dest_mac[3]) != ntoh24(fh->fh_d_id)) { + QEDF_ERR(&(qedf->dbg_ctx), "FC frame d_id mismatch with MAC %pM.\n", + dest_mac); + return; + } + + if (qedf->ctlr.state) { + if (!ether_addr_equal(mac, qedf->ctlr.dest_addr)) { + QEDF_ERR(&(qedf->dbg_ctx), "Wrong source address mac:%pM dest_addr:%pM.\n", + mac, qedf->ctlr.dest_addr); + kfree_skb(skb); + return; + } + } + + vn_port = fc_vport_id_lookup(lport, ntoh24(fh->fh_d_id)); + + /* + * If the destination ID from the frame header does not match what we + * have on record for lport and the search for a NPIV port came up + * empty then this is not addressed to our port so simply drop it. + */ + if (lport->port_id != ntoh24(fh->fh_d_id) && !vn_port) { + QEDF_ERR(&(qedf->dbg_ctx), "Dropping frame due to destination mismatch: lport->port_id=%x fh->d_id=%x.\n", + lport->port_id, ntoh24(fh->fh_d_id)); + kfree_skb(skb); + return; + } + + f_ctl = ntoh24(fh->fh_f_ctl); + if ((fh->fh_type == FC_TYPE_BLS) && (f_ctl & FC_FC_SEQ_CTX) && + (f_ctl & FC_FC_EX_CTX)) { + /* Drop incoming ABTS response that has both SEQ/EX CTX set */ + kfree_skb(skb); + return; + } + /* * If a connection is uploading, drop incoming FCoE frames as there * is a small window where we could try to return a frame while libfc |