return;
}
+/**
+ * lpfc_get_enc_info - Return encryption information about the session for
+ * a given remote port.
+ * @rport: ptr to fc_rport from scsi transport fc
+ *
+ * Given an rport object, iterate through the fc_nodes list to find node
+ * corresponding with rport. Pass the encryption information from the node to
+ * rport's encryption attribute for reporting to upper layers. Information is
+ * passed through nlp_enc_info struct which contains encryption status.
+ *
+ * Returns:
+ * - Address of rport's fc_encryption_info struct
+ * - NULL when not found
+ **/
+static struct fc_encryption_info *
+lpfc_get_enc_info(struct fc_rport *rport)
+{
+ struct Scsi_Host *shost = rport_to_shost(rport);
+ struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+ struct fc_encryption_info *ef = NULL;
+ struct lpfc_nodelist *ndlp, *next_ndlp;
+ unsigned long iflags;
+
+ spin_lock_irqsave(&vport->fc_nodes_list_lock, iflags);
+ list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) {
+ if (ndlp->rport && ndlp->rport == rport) {
+ ef = &rport->enc_info;
+ ef->status = ndlp->nlp_enc_info.status;
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&vport->fc_nodes_list_lock, iflags);
+ return ef;
+}
+
+
/*
* The LPFC driver treats linkdown handling as target loss events so there
* are no sysfs handlers for link_down_tmo.
.get_fc_host_stats = lpfc_get_stats,
.reset_fc_host_stats = lpfc_reset_stats,
+ .get_fc_rport_enc_info = lpfc_get_enc_info,
+
.dd_fcrport_size = sizeof(struct lpfc_rport_data),
.show_rport_maxframe_size = 1,
.show_rport_supported_classes = 1,
.get_fc_host_stats = lpfc_get_stats,
.reset_fc_host_stats = lpfc_reset_stats,
+ .get_fc_rport_enc_info = lpfc_get_enc_info,
+
.dd_fcrport_size = sizeof(struct lpfc_rport_data),
.show_rport_maxframe_size = 1,
.show_rport_supported_classes = 1,
ndlp->nlp_rpi);
len += scnprintf(buf+len, size-len, "flag:x%08lx ",
ndlp->nlp_flag);
+ if (ndlp->nlp_enc_info.status) {
+ len += scnprintf(buf + len,
+ size - len, "ENCRYPTED");
+ len += scnprintf(buf + len, size - len,
+ ndlp->nlp_enc_info.level
+ ? "(CNSA2.0) " : "(CNSA1.0) ");
+ }
if (!ndlp->nlp_type)
len += scnprintf(buf+len, size-len, "UNKNOWN_TYPE ");
if (ndlp->nlp_type & NLP_FC_NODE)
unsigned long xri_bitmap[XRI_BITMAP_ULONGS];
};
+struct lpfc_enc_info {
+ u8 status; /* encryption status for session */
+ u8 level; /* CNSA encryption level */
+};
+
enum lpfc_fc4_xpt_flags {
NLP_XPT_REGD = 0x1,
SCSI_XPT_REGD = 0x2,
uint8_t vmid_support; /* destination VMID support */
#define NLP_NVME_NSLER 0x1 /* NVME NSLER device */
+ struct lpfc_enc_info nlp_enc_info; /* Encryption information struct */
+
struct timer_list nlp_delayfunc; /* Used for delayed ELS cmds */
struct lpfc_hba *phba;
struct fc_rport *rport; /* scsi_transport_fc port structure */
lpfc_nlp_put(ndlp);
return;
}
+
+/**
+ * lpfc_check_encryption - Reports an ndlp's encryption information
+ * @phba: pointer to lpfc hba data structure.
+ * @ndlp: pointer to a node-list data structure.
+ * @cmdiocb: pointer to lpfc command iocbq data structure.
+ * @rspiocb: pointer to lpfc response iocbq data structure.
+ *
+ * This routine is called in the completion callback function for issuing
+ * or receiving a Port Login (PLOGI) command. In a PLOGI completion, if FEDIF
+ * is supported, encryption information will be provided in completion status
+ * data. If @phba supports FEDIF, a log message containing encryption
+ * information will be logged. Encryption status is also saved for encryption
+ * reporting with upper layer through the rport encryption attribute.
+ **/
+static void
+lpfc_check_encryption(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
+ struct lpfc_iocbq *cmdiocb, struct lpfc_iocbq *rspiocb)
+{
+ struct lpfc_vport *vport = cmdiocb->vport;
+ u32 did = ndlp->nlp_DID;
+ struct lpfc_enc_info *nlp_enc_info = &ndlp->nlp_enc_info;
+ char enc_status[FC_RPORT_ENCRYPTION_STATUS_MAX_LEN] = {0};
+ char enc_level[8] = "N/A";
+ u8 encryption;
+
+ if (phba->sli4_hba.encryption_support &&
+ ((did & Fabric_DID_MASK) != Fabric_DID_MASK)) {
+ encryption = bf_get(lpfc_wcqe_c_enc,
+ &rspiocb->wcqe_cmpl);
+ nlp_enc_info->status = encryption;
+
+ strscpy(enc_status, encryption ? "Encrypted" : "Unencrypted",
+ sizeof(enc_status));
+
+ if (encryption) {
+ nlp_enc_info->level = bf_get(lpfc_wcqe_c_enc_lvl,
+ &rspiocb->wcqe_cmpl);
+ strscpy(enc_level, nlp_enc_info->level ? "CNSA2.0" :
+ "CNSA1.0",
+ sizeof(enc_level));
+ }
+
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_ENCRYPTION,
+ "0924 DID:x%06x %s Session "
+ "Established, Encryption Level:%s "
+ "rpi:x%x\n",
+ ndlp->nlp_DID, enc_status, enc_level,
+ ndlp->nlp_rpi);
+ }
+}
+
/**
* lpfc_cmpl_els_plogi - Completion callback function for plogi
* @phba: pointer to lpfc hba data structure.
goto out;
ndlp = lpfc_plogi_confirm_nport(phba, prsp->virt, ndlp);
+ lpfc_check_encryption(phba, ndlp, cmdiocb, rspiocb);
+
sp = (struct serv_parm *)((u8 *)prsp->virt +
sizeof(u32));
goto out;
}
+ if (!ulp_status && test_bit(NLP_RCV_PLOGI, &ndlp->nlp_flag))
+ lpfc_check_encryption(phba, ndlp, cmdiocb, rspiocb);
+
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP,
"ELS rsp cmpl: status:x%x/x%x did:x%x",
ulp_status, ulp_word4, did);
clear_bit(NLP_NPR_ADISC, &ndlp->nlp_flag);
if (acc_plogi)
clear_bit(NLP_LOGO_ACC, &ndlp->nlp_flag);
+ memset(&ndlp->nlp_enc_info, 0, sizeof(ndlp->nlp_enc_info));
return 1;
}
clear_bit(NLP_LOGO_ACC, &ndlp->nlp_flag);
#define lpfc_wcqe_c_cmf_bw_MASK 0x0FFFFFFF
#define lpfc_wcqe_c_cmf_bw_WORD total_data_placed
uint32_t parameter;
+#define lpfc_wcqe_c_enc_SHIFT 31
+#define lpfc_wcqe_c_enc_MASK 0x00000001
+#define lpfc_wcqe_c_enc_WORD parameter
+#define lpfc_wcqe_c_enc_lvl_SHIFT 30
+#define lpfc_wcqe_c_enc_lvl_MASK 0x00000001
+#define lpfc_wcqe_c_enc_lvl_WORD parameter
#define lpfc_wcqe_c_bg_edir_SHIFT 5
#define lpfc_wcqe_c_bg_edir_MASK 0x00000001
#define lpfc_wcqe_c_bg_edir_WORD parameter
#define lpfc_mbx_rd_conf_topology_SHIFT 24
#define lpfc_mbx_rd_conf_topology_MASK 0x000000FF
#define lpfc_mbx_rd_conf_topology_WORD word2
- uint32_t rsvd_3;
+ uint32_t word3;
+#define lpfc_mbx_rd_conf_fedif_SHIFT 6
+#define lpfc_mbx_rd_conf_fedif_MASK 0x00000001
+#define lpfc_mbx_rd_conf_fedif_WORD word3
uint32_t word4;
#define lpfc_mbx_rd_conf_e_d_tov_SHIFT 0
#define lpfc_mbx_rd_conf_e_d_tov_MASK 0x0000FFFF
(phba->sli4_hba.max_cfg_param.max_vpi - 1) : 0;
phba->max_vports = phba->max_vpi;
+ if (bf_get(lpfc_mbx_rd_conf_fedif, rd_config))
+ phba->sli4_hba.encryption_support = true;
+ else
+ phba->sli4_hba.encryption_support = false;
+
/* Next decide on FPIN or Signal E2E CGN support
* For congestion alarms and warnings valid combination are:
* 1. FPIN alarms / FPIN warnings
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
- * Copyright (C) 2017-2023 Broadcom. All Rights Reserved. The term *
+ * Copyright (C) 2017-2025 Broadcom. All Rights Reserved. The term *
* “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
* Copyright (C) 2004-2009 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
#define LOG_RSVD1 0x01000000 /* Reserved */
#define LOG_RSVD2 0x02000000 /* Reserved */
#define LOG_CGN_MGMT 0x04000000 /* Congestion Mgmt events */
+#define LOG_ENCRYPTION 0x40000000 /* EDIF Encryption events. */
#define LOG_TRACE_EVENT 0x80000000 /* Dmp the DBG log on this err */
#define LOG_ALL_MSG 0x7fffffff /* LOG all messages */
#define LPFC_FP_EQ_MAX_INTR_SEC 10000
uint32_t intr_enable;
+
+ /* Indicates whether SLI Port supports FEDIF */
+ bool encryption_support;
+
struct lpfc_bmbx bmbx;
struct lpfc_max_cfg_param max_cfg_param;
uint16_t extents_in_use; /* must allocate resource extents. */