Open-FCoE Submission
Subsystems (2)
cover Open-FCoE Submission
The following series adds the following code to the SCSI subsystem.
1) FC and FCoE protocol definitions in header files
- Files are added in include/scsi/fc/
- New files are: fc_els.h, fc_encaps.h, fc_fc2.h, fc_fcp.h, fc_fs.h, fc_gs.h and fc_ns.h
2) libfc - a FC assist library
- Composed of 5 sub-components: Exchange Manager, Local Port Remote Port, Discovery and SCSI-FCP
- Uses libfc_function_template for cross-layer calls
- Uses struct fc_lport as primary object shared by all sub-modules
- Common code defined in include/scsi/libfc.h
3) fcoe - a FCoE initiator implementation
- Simple encapsulation and unpacking layer
- Interacts with netdev
- Initial support for FCoE offload
- Uses /sys/module/fcoe/parameters/create and destroy for enabling/disabling FCoE connection over a particular Ethernet adapter
- Works on any Ethernet adapter
These patches apply to both the scsi-misc and scsi-rc-fixes trees.
We've spent a lot of time recently improving stability and creating different interfaces for potential users. We'd like to be queued for the 2.6.29 merge window. We're actively developing this stack and we will continue to have a lot of changes, but I think that the code is at a good place right now and it's ready for inclusion. Please let me know what you think.
---
Robert Love (3):
fcoe: Fibre Channel over Ethernet
libfc: A modular Fibre Channel library
FC protocol definition header files
drivers/scsi/Kconfig | 13 drivers/scsi/Makefile | 2 drivers/scsi/fcoe/Makefile | 8 drivers/scsi/fcoe/fc_transport_fcoe.c | 446 +++++++ drivers/scsi/fcoe/fcoe_sw.c | 488 ++++++++ drivers/scsi/fcoe/libfcoe.c | 1506 +++++++++++++++++++++++ drivers/scsi/libfc/Makefile | 12 drivers/scsi/libfc/fc_disc.c | 932 ++++++++++++++ drivers/scsi/libfc/fc_elsct.c | 71 + drivers/scsi/libfc/fc_exch.c | 1971 +++++++++++++++++++++++++++++++ drivers/scsi/libfc/fc_fcp.c | 2130 +++++++++++++++++++++++++++++++++ drivers/scsi/libfc/fc_frame.c | 89 + drivers/scsi/libfc/fc_lport.c | 1525 ++++++++++++++++++++++++ drivers/scsi/libfc/fc_rport.c | 1277 ++++++++++++++++++++ include/scsi/fc/fc_els.h | 802 ++++++++++++ include/scsi/fc/fc_encaps.h | 138 ++ include/scsi/fc/fc_fc2.h | 124 ++ include/scsi/fc/fc_fcoe.h | 102 ++ include/scsi/fc/fc_fcp.h | 199 +++ include/scsi/fc/fc_fs.h | 340 +++++ include/scsi/fc/fc_gs.h | 93 + include/scsi/fc/fc_ns.h | 159 ++ include/scsi/fc_encode.h | 309 +++++ include/scsi/fc_frame.h | 239 ++++ include/scsi/fc_transport_fcoe.h | 54 + include/scsi/libfc.h | 917 ++++++++++++++ include/scsi/libfcoe.h | 177 +++ 27 files changed, 14123 insertions(+), 0 deletions(-) create mode 100644 drivers/scsi/fcoe/Makefile create mode 100644 drivers/scsi/fcoe/fc_transport_fcoe.c create mode 100644 drivers/scsi/fcoe/fcoe_sw.c create mode 100644 drivers/scsi/fcoe/libfcoe.c create mode 100644 drivers/scsi/libfc/Makefile create mode 100644 drivers/scsi/libfc/fc_disc.c create mode 100644 drivers/scsi/libfc/fc_elsct.c create mode 100644 drivers/scsi/libfc/fc_exch.c create mode 100644 drivers/scsi/libfc/fc_fcp.c create mode 100644 drivers/scsi/libfc/fc_frame.c create mode 100644 drivers/scsi/libfc/fc_lport.c create mode 100644 drivers/scsi/libfc/fc_rport.c create mode 100644 include/scsi/fc/fc_els.h create mode 100644 include/scsi/fc/fc_encaps.h create mode 100644 include/scsi/fc/fc_fc2.h create mode 100644 include/scsi/fc/fc_fcoe.h create mode 100644 include/scsi/fc/fc_fcp.h create mode 100644 include/scsi/fc/fc_fs.h create mode 100644 include/scsi/fc/fc_gs.h create mode 100644 include/scsi/fc/fc_ns.h create mode 100644 include/scsi/fc_encode.h create mode 100644 include/scsi/fc_frame.h create mode 100644 include/scsi/fc_transport_fcoe.h create mode 100644 include/scsi/libfc.h create mode 100644 include/scsi/libfcoe.h
Signature · 1 line
//Rob
PATCH 1/3 FC protocol definition header files
---
include/scsi/fc/fc_els.h | 802 +++++++++++++++++++++++++++++++++++++++++++ include/scsi/fc/fc_encaps.h | 138 +++++++ include/scsi/fc/fc_fc2.h | 124 +++++++ include/scsi/fc/fc_fcoe.h | 102 +++++ include/scsi/fc/fc_fcp.h | 199 +++++++++++ include/scsi/fc/fc_fs.h | 340 ++++++++++++++++++ include/scsi/fc/fc_gs.h | 93 +++++ include/scsi/fc/fc_ns.h | 159 +++++++++ 8 files changed, 1957 insertions(+), 0 deletions(-) create mode 100644 include/scsi/fc/fc_els.h create mode 100644 include/scsi/fc/fc_encaps.h create mode 100644 include/scsi/fc/fc_fc2.h create mode 100644 include/scsi/fc/fc_fcoe.h create mode 100644 include/scsi/fc/fc_fcp.h create mode 100644 include/scsi/fc/fc_fs.h create mode 100644 include/scsi/fc/fc_gs.h create mode 100644 include/scsi/fc/fc_ns.h
include/scsi/fc/fc_els.h new file +802 -0
@@ -0,0 +1,802 @@ +/* +* Copyright(c) 2007 Intel Corporation. All rights reserved. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program; if not, write to the Free Software Foundation, Inc., +* 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. +* +* Maintained at www.Open-FCoE.org +*/ + +#ifndef _FC_ELS_H_ +#define _FC_ELS_H_ + +/* +* Fibre Channel Switch - Enhanced Link Services definitions. +* From T11 FC-LS Rev 1.2 June 7, 2005. +*/ + +/* +* ELS Command codes - byte 0 of the frame payload +*/ +enum fc_els_cmd { +ELS_LS_RJT =0x01 ,/* ESL reject */ +ELS_LS_ACC =0x02 ,/* ESL Accept */ +ELS_PLOGI =0x03 ,/* N_Port login */ +ELS_FLOGI =0x04 ,/* F_Port login */ +ELS_LOGO =0x05 ,/* Logout */ +ELS_ABTX =0x06 ,/* Abort exchange - obsolete */ +ELS_RCS =0x07 ,/* read connection status */ +ELS_RES =0x08 ,/* read exchange status block */ +ELS_RSS =0x09 ,/* read sequence status block */ +ELS_RSI =0x0a ,/* read sequence initiative */ +ELS_ESTS =0x0b ,/* establish streaming */ +ELS_ESTC =0x0c ,/* estimate credit */ +ELS_ADVC =0x0d ,/* advise credit */ +ELS_RTV =0x0e ,/* read timeout value */ +ELS_RLS =0x0f ,/* read link error status block */ +ELS_ECHO =0x10 ,/* echo */ +ELS_TEST =0x11 ,/* test */ +ELS_RRQ =0x12 ,/* reinstate recovery qualifier */ +ELS_REC =0x13 ,/* read exchange concise */ +ELS_SRR =0x14 ,/* sequence retransmission request */ +ELS_PRLI =0x20 ,/* process login */ +ELS_PRLO =0x21 ,/* process logout */ +ELS_SCN =0x22 ,/* state change notification */ +ELS_TPLS =0x23 ,/* test process login state */ +ELS_TPRLO =0x24 ,/* third party process logout */ +ELS_LCLM =0x25 ,/* login control list mgmt (obs) */ +ELS_GAID =0x30 ,/* get alias_ID */ +ELS_FACT =0x31 ,/* fabric activate alias_id */ +ELS_FDACDT =0x32 ,/* fabric deactivate alias_id */ +ELS_NACT =0x33 ,/* N-port activate alias_id */ +ELS_NDACT =0x34 ,/* N-port deactivate alias_id */ +ELS_QOSR =0x40 ,/* quality of service request */ +ELS_RVCS =0x41 ,/* read virtual circuit status */ +ELS_PDISC =0x50 ,/* discover N_port service params */ +ELS_FDISC =0x51 ,/* discover F_port service params */ +ELS_ADISC =0x52 ,/* discover address */ +ELS_RNC =0x53 ,/* report node cap (obs) */ +ELS_FARP_REQ =0x54 ,/* FC ARP request */ +ELS_FARP_REPL =0x55 ,/* FC ARP reply */ +ELS_RPS =0x56 ,/* read port status block */ +ELS_RPL =0x57 ,/* read port list */ +ELS_RPBC =0x58 ,/* read port buffer condition */ +ELS_FAN =0x60 ,/* fabric address notification */ +ELS_RSCN =0x61 ,/* registered state change notification */ +ELS_SCR =0x62 ,/* state change registration */ +ELS_RNFT =0x63 ,/* report node FC-4 types */ +ELS_CSR =0x68 ,/* clock synch. request */ +ELS_CSU =0x69 ,/* clock synch. update */ +ELS_LINIT =0x70 ,/* loop initialize */ +ELS_LSTS =0x72 ,/* loop status */ +ELS_RNID =0x78 ,/* request node ID data */ +ELS_RLIR =0x79 ,/* registered link incident report */ +ELS_LIRR =0x7a ,/* link incident record registration */ +ELS_SRL =0x7b ,/* scan remote loop */ +ELS_SBRP =0x7c ,/* set bit-error reporting params */ +ELS_RPSC =0x7d ,/* report speed capabilities */ +ELS_QSA =0x7e ,/* query security attributes */ +ELS_EVFP =0x7f ,/* exchange virt. fabrics params */ +ELS_LKA =0x80 ,/* link keep-alive */ +ELS_AUTH_ELS =0x90 ,/* authentication ELS */ +}; + +/* +* Initializer useful for decoding table. +* Please keep this in sync with the above definitions. +*/ +#define FC_ELS_CMDS_INIT { \ + [ELS_LS_RJT] = "LS_RJT", \ + [ELS_LS_ACC] = "LS_ACC", \ + [ELS_PLOGI] = "PLOGI", \ + [ELS_FLOGI] = "FLOGI", \ + [ELS_LOGO] = "LOGO", \ + [ELS_ABTX] = "ABTX", \ + [ELS_RCS] = "RCS", \ + [ELS_RES] = "RES", \ + [ELS_RSS] = "RSS", \ + [ELS_RSI] = "RSI", \ + [ELS_ESTS] = "ESTS", \ + [ELS_ESTC] = "ESTC", \ + [ELS_ADVC] = "ADVC", \ + [ELS_RTV] = "RTV", \ + [ELS_RLS] = "RLS", \ + [ELS_ECHO] = "ECHO", \ + [ELS_TEST] = "TEST", \ + [ELS_RRQ] = "RRQ", \ + [ELS_REC] = "REC", \ + [ELS_SRR] = "SRR", \ + [ELS_PRLI] = "PRLI", \ + [ELS_PRLO] = "PRLO", \ + [ELS_SCN] = "SCN", \ + [ELS_TPLS] = "TPLS", \ + [ELS_TPRLO] = "TPRLO", \ + [ELS_LCLM] = "LCLM", \ + [ELS_GAID] = "GAID", \ + [ELS_FACT] = "FACT", \ + [ELS_FDACDT] = "FDACDT", \ + [ELS_NACT] = "NACT", \ + [ELS_NDACT] = "NDACT", \ + [ELS_QOSR] = "QOSR", \ + [ELS_RVCS] = "RVCS", \ + [ELS_PDISC] = "PDISC", \ + [ELS_FDISC] = "FDISC", \ + [ELS_ADISC] = "ADISC", \ + [ELS_RNC] = "RNC", \ + [ELS_FARP_REQ] = "FARP_REQ", \ + [ELS_FARP_REPL] = "FARP_REPL", \ + [ELS_RPS] = "RPS", \ + [ELS_RPL] = "RPL", \ + [ELS_RPBC] = "RPBC", \ + [ELS_FAN] = "FAN", \ + [ELS_RSCN] = "RSCN", \ + [ELS_SCR] = "SCR", \ + [ELS_RNFT] = "RNFT", \ + [ELS_CSR] = "CSR", \ + [ELS_CSU] = "CSU", \ + [ELS_LINIT] = "LINIT", \ + [ELS_LSTS] = "LSTS", \ + [ELS_RNID] = "RNID", \ + [ELS_RLIR] = "RLIR", \ + [ELS_LIRR] = "LIRR", \ + [ELS_SRL] = "SRL", \ + [ELS_SBRP] = "SBRP", \ + [ELS_RPSC] = "RPSC", \ + [ELS_QSA] = "QSA", \ + [ELS_EVFP] = "EVFP", \ + [ELS_LKA] = "LKA", \ + [ELS_AUTH_ELS] = "AUTH_ELS", \ +} + +/* +* LS_ACC payload. +*/ +struct fc_els_ls_acc { +__u8 la_cmd;/* command code ELS_LS_ACC */ +__u8 la_resv[3 ];/* reserved */ +}; + +/* +* ELS reject payload. +*/ +struct fc_els_ls_rjt { +__u8 er_cmd;/* command code ELS_LS_RJT */ +__u8 er_resv[4 ];/* reserved must be zero */ +__u8 er_reason;/* reason (enum fc_els_rjt_reason below) */ +__u8 er_explan;/* explanation (enum fc_els_rjt_explan below) */ +__u8 er_vendor;/* vendor specific code */ +}; + +/* +* ELS reject reason codes (er_reason). +*/ +enum fc_els_rjt_reason { +ELS_RJT_NONE =0 ,/* no reject - not to be sent */ +ELS_RJT_INVAL =0x01 ,/* invalid ELS command code */ +ELS_RJT_LOGIC =0x03 ,/* logical error */ +ELS_RJT_BUSY =0x05 ,/* logical busy */ +ELS_RJT_PROT =0x07 ,/* protocol error */ +ELS_RJT_UNAB =0x09 ,/* unable to perform command request */ +ELS_RJT_UNSUP =0x0b ,/* command not supported */ +ELS_RJT_INPROG =0x0e ,/* command already in progress */ +ELS_RJT_VENDOR =0xff ,/* vendor specific error */ +}; + + +/* +* reason code explanation (er_explan). +*/ +enum fc_els_rjt_explan { +ELS_EXPL_NONE =0x00 ,/* No additional explanation */ +ELS_EXPL_SPP_OPT_ERR =0x01 ,/* service parameter error - options */ +ELS_EXPL_SPP_ICTL_ERR =0x03 ,/* service parm error - initiator ctl */ +ELS_EXPL_AH =0x11 ,/* invalid association header */ +ELS_EXPL_AH_REQ =0x13 ,/* association_header required */ +ELS_EXPL_SID =0x15 ,/* invalid originator S_ID */ +ELS_EXPL_OXID_RXID =0x17 ,/* invalid OX_ID-RX_ID combination */ +ELS_EXPL_INPROG =0x19 ,/* Request already in progress */ +ELS_EXPL_PLOGI_REQD =0x1e ,/* N_Port login required */ +ELS_EXPL_INSUF_RES =0x29 ,/* insufficient resources */ +ELS_EXPL_UNAB_DATA =0x2a ,/* unable to supply requested data */ +ELS_EXPL_UNSUPR =0x2c ,/* Request not supported */ +ELS_EXPL_INV_LEN =0x2d ,/* Invalid payload length */ +/* TBD - above definitions incomplete */ +}; + +/* +* Common service parameters (N ports). +*/ +struct fc_els_csp { +__u8 sp_hi_ver;/* highest version supported (obs.) */ +__u8 sp_lo_ver;/* highest version supported (obs.) */ +__be16 sp_bb_cred;/* buffer-to-buffer credits */ +__be16 sp_features;/* common feature flags */ +__be16 sp_bb_data;/* b-b state number and data field sz */ +union { +struct { +__be16 _sp_tot_seq;/* total concurrent sequences */ +__be16 _sp_rel_off;/* rel. offset by info cat */ + } sp_plogi; +struct { +__be32 _sp_r_a_tov;/* resource alloc. timeout msec */ + } sp_flogi_acc; + } sp_u; +__be32 sp_e_d_tov;/* error detect timeout value */ +}; +#define sp_tot_seq sp_u.sp_plogi._sp_tot_seq +#define sp_rel_off sp_u.sp_plogi._sp_rel_off +#define sp_r_a_tov sp_u.sp_flogi_acc._sp_r_a_tov + +#define FC_SP_BB_DATA_MASK 0xfff/* mask for data field size in sp_bb_data */ + +/* +* Minimum and maximum values for max data field size in service parameters. +*/ +#define FC_SP_MIN_MAX_PAYLOAD FC_MIN_MAX_PAYLOAD +#define FC_SP_MAX_MAX_PAYLOAD FC_MAX_PAYLOAD + +/* +* sp_features +*/ +#define FC_SP_FT_CIRO 0x8000/* continuously increasing rel. off. */ +#define FC_SP_FT_CLAD 0x8000/* clean address (in FLOGI LS_ACC) */ +#define FC_SP_FT_RAND 0x4000/* random relative offset */ +#define FC_SP_FT_VAL 0x2000/* valid vendor version level */ +#define FC_SP_FT_FPORT 0x1000/* F port (1) vs. N port (0) */ +#define FC_SP_FT_ABB 0x0800/* alternate BB_credit management */ +#define FC_SP_FT_EDTR 0x0400/* E_D_TOV Resolution is nanoseconds */ +#define FC_SP_FT_MCAST 0x0200/* multicast */ +#define FC_SP_FT_BCAST 0x0100/* broadcast */ +#define FC_SP_FT_HUNT 0x0080/* hunt group */ +#define FC_SP_FT_SIMP 0x0040/* dedicated simplex */ +#define FC_SP_FT_SEC 0x0020/* reserved for security */ +#define FC_SP_FT_CSYN 0x0010/* clock synch. supported */ +#define FC_SP_FT_RTTOV 0x0008/* R_T_TOV value 100 uS, else 100 mS */ +#define FC_SP_FT_HALF 0x0004/* dynamic half duplex */ +#define FC_SP_FT_SEQC 0x0002/* SEQ_CNT */ +#define FC_SP_FT_PAYL 0x0001/* FLOGI payload length 256, else 116 */ + +/* +* Class-specific service parameters. +*/ +struct fc_els_cssp { +__be16 cp_class;/* class flags */ +__be16 cp_init;/* initiator flags */ +__be16 cp_recip;/* recipient flags */ +__be16 cp_rdfs;/* receive data field size */ +__be16 cp_con_seq;/* concurrent sequences */ +__be16 cp_ee_cred;/* N-port end-to-end credit */ +__u8 cp_resv1;/* reserved */ +__u8 cp_open_seq;/* open sequences per exchange */ +__u8 _cp_resv2[2 ];/* reserved */ +}; + +/* +* cp_class flags. +*/ +#define FC_CPC_VALID 0x8000/* class valid */ +#define FC_CPC_IMIX 0x4000/* intermix mode */ +#define FC_CPC_SEQ 0x0800/* sequential delivery */ +#define FC_CPC_CAMP 0x0200/* camp-on */ +#define FC_CPC_PRI 0x0080/* priority */ + +/* +* cp_init flags. +* (TBD: not all flags defined here). +*/ +#define FC_CPI_CSYN 0x0010/* clock synch. capable */ + +/* +* cp_recip flags. +*/ +#define FC_CPR_CSYN 0x0008/* clock synch. capable */ + +/* +* NFC_ELS_FLOGI: Fabric login request. +* NFC_ELS_PLOGI: Port login request (same format). +*/ +struct fc_els_flogi { +__u8 fl_cmd;/* command */ +__u8 _fl_resvd[3 ];/* must be zero */ +struct fc_els_csp fl_csp;/* common service parameters */ +__be64 fl_wwpn;/* port name */ +__be64 fl_wwnn;/* node name */ +struct fc_els_cssp fl_cssp[4 ];/* class 1-4 service parameters */ +__u8 fl_vend[16 ];/* vendor version level */ +} __attribute__((__packed__ )); + +/* +* Process login service parameter page. +*/ +struct fc_els_spp { +__u8 spp_type;/* type code or common service params */ +__u8 spp_type_ext;/* type code extension */ +__u8 spp_flags; +__u8 _spp_resvd; +__be32 spp_orig_pa;/* originator process associator */ +__be32 spp_resp_pa;/* responder process associator */ +__be32 spp_params;/* service parameters */ +}; + +/* +* spp_flags. +*/ +#define FC_SPP_OPA_VAL 0x80/* originator proc. assoc. valid */ +#define FC_SPP_RPA_VAL 0x40/* responder proc. assoc. valid */ +#define FC_SPP_EST_IMG_PAIR 0x20/* establish image pair */ +#define FC_SPP_RESP_MASK 0x0f/* mask for response code (below) */ + +/* +* SPP response code in spp_flags - lower 4 bits. +*/ +enum fc_els_spp_resp { +FC_SPP_RESP_ACK =1 ,/* request executed */ +FC_SPP_RESP_RES =2 ,/* unable due to lack of resources */ +FC_SPP_RESP_INIT =3 ,/* initialization not complete */ +FC_SPP_RESP_NO_PA =4 ,/* unknown process associator */ +FC_SPP_RESP_CONF =5 ,/* configuration precludes image pair */ +FC_SPP_RESP_COND =6 ,/* request completed conditionally */ +FC_SPP_RESP_MULT =7 ,/* unable to handle multiple SPPs */ +FC_SPP_RESP_INVL =8 ,/* SPP is invalid */ +}; + +/* +* ELS_RRQ - Reinstate Recovery Qualifier +*/ +struct fc_els_rrq { +__u8 rrq_cmd;/* command (0x12) */ +__u8 rrq_zero[3 ];/* specified as zero - part of cmd */ +__u8 rrq_resvd;/* reserved */ +__u8 rrq_s_id[3 ];/* originator FID */ +__be16 rrq_ox_id;/* originator exchange ID */ +__be16 rrq_rx_id;/* responders exchange ID */ +}; + +/* +* ELS_REC - Read exchange concise. +*/ +struct fc_els_rec { +__u8 rec_cmd;/* command (0x13) */ +__u8 rec_zero[3 ];/* specified as zero - part of cmd */ +__u8 rec_resvd;/* reserved */ +__u8 rec_s_id[3 ];/* originator FID */ +__be16 rec_ox_id;/* originator exchange ID */ +__be16 rec_rx_id;/* responders exchange ID */ +}; + +/* +* ELS_REC LS_ACC payload. +*/ +struct fc_els_rec_acc { +__u8 reca_cmd;/* accept (0x02) */ +__u8 reca_zero[3 ];/* specified as zero - part of cmd */ +__be16 reca_ox_id;/* originator exchange ID */ +__be16 reca_rx_id;/* responders exchange ID */ +__u8 reca_resvd1;/* reserved */ +__u8 reca_ofid[3 ];/* originator FID */ +__u8 reca_resvd2;/* reserved */ +__u8 reca_rfid[3 ];/* responder FID */ +__be32 reca_fc4value;/* FC4 value */ +__be32 reca_e_stat;/* ESB (exchange status block) status */ +}; + +/* +* ELS_PRLI - Process login request and response. +*/ +struct fc_els_prli { +__u8 prli_cmd;/* command */ +__u8 prli_spp_len;/* length of each serv. parm. page */ +__be16 prli_len;/* length of entire payload */ +/* service parameter pages follow */ +}; + +/* +* ELS_LOGO - process or fabric logout. +*/ +struct fc_els_logo { +__u8 fl_cmd;/* command code */ +__u8 fl_zero[3 ];/* specified as zero - part of cmd */ +__u8 fl_resvd;/* reserved */ +__u8 fl_n_port_id[3 ];/* N port ID */ +__be64 fl_n_port_wwn;/* port name */ +}; + +/* +* ELS_RTV - read timeout value. +*/ +struct fc_els_rtv { +__u8 rtv_cmd;/* command code 0x0e */ +__u8 rtv_zero[3 ];/* specified as zero - part of cmd */ +}; + +/* +* LS_ACC for ELS_RTV - read timeout value. +*/ +struct fc_els_rtv_acc { +__u8 rtv_cmd;/* command code 0x02 */ +__u8 rtv_zero[3 ];/* specified as zero - part of cmd */ +__be32 rtv_r_a_tov;/* resource allocation timeout value */ +__be32 rtv_e_d_tov;/* error detection timeout value */ +__be32 rtv_toq;/* timeout qualifier (see below) */ +}; + +/* +* rtv_toq bits. +*/ +#define FC_ELS_RTV_EDRES (1 << 26)/* E_D_TOV resolution is nS else mS */ +#define FC_ELS_RTV_RTTOV (1 << 19)/* R_T_TOV is 100 uS else 100 mS */ + +/* +* ELS_SCR - state change registration payload. +*/ +struct fc_els_scr { +__u8 scr_cmd;/* command code */ +__u8 scr_resv[6 ];/* reserved */ +__u8 scr_reg_func;/* registration function (see below) */ +}; + +enum fc_els_scr_func { +ELS_SCRF_FAB =1 ,/* fabric-detected registration */ +ELS_SCRF_NPORT =2 ,/* Nx_Port-detected registration */ +ELS_SCRF_FULL =3 ,/* full registration */ +ELS_SCRF_CLEAR =255 ,/* remove any current registrations */ +}; + +/* +* ELS_RSCN - registered state change notification payload. +*/ +struct fc_els_rscn { +__u8 rscn_cmd;/* RSCN opcode (0x61) */ +__u8 rscn_page_len;/* page length (4) */ +__be16 rscn_plen;/* payload length including this word */ + +/* followed by 4-byte generic affected Port_ID pages */ +}; + +struct fc_els_rscn_page { +__u8 rscn_page_flags;/* event and address format */ +__u8 rscn_fid[3 ];/* fabric ID */ +}; + +#define ELS_RSCN_EV_QUAL_BIT 2/* shift count for event qualifier */ +#define ELS_RSCN_EV_QUAL_MASK 0xf/* mask for event qualifier */ +#define ELS_RSCN_ADDR_FMT_BIT 0/* shift count for address format */ +#define ELS_RSCN_ADDR_FMT_MASK 0x3/* mask for address format */ + +enum fc_els_rscn_ev_qual { +ELS_EV_QUAL_NONE =0 ,/* unspecified */ +ELS_EV_QUAL_NS_OBJ =1 ,/* changed name server object */ +ELS_EV_QUAL_PORT_ATTR =2 ,/* changed port attribute */ +ELS_EV_QUAL_SERV_OBJ =3 ,/* changed service object */ +ELS_EV_QUAL_SW_CONFIG =4 ,/* changed switch configuration */ +ELS_EV_QUAL_REM_OBJ =5 ,/* removed object */ +}; + +enum fc_els_rscn_addr_fmt { +ELS_ADDR_FMT_PORT =0 ,/* rscn_fid is a port address */ +ELS_ADDR_FMT_AREA =1 ,/* rscn_fid is a area address */ +ELS_ADDR_FMT_DOM =2 ,/* rscn_fid is a domain address */ +ELS_ADDR_FMT_FAB =3 ,/* anything on fabric may have changed */ +}; + +/* +* ELS_RNID - request Node ID. +*/ +struct fc_els_rnid { +__u8 rnid_cmd;/* RNID opcode (0x78) */ +__u8 rnid_resv[3 ];/* reserved */ +__u8 rnid_fmt;/* data format */ +__u8 rnid_resv2[3 ];/* reserved */ +}; + +/* +* Node Identification Data formats (rnid_fmt) +*/ +enum fc_els_rnid_fmt { +ELS_RNIDF_NONE =0 ,/* no specific identification data */ +ELS_RNIDF_GEN =0xdf ,/* general topology discovery format */ +}; + +/* +* ELS_RNID response. +*/ +struct fc_els_rnid_resp { +__u8 rnid_cmd;/* response code (LS_ACC) */ +__u8 rnid_resv[3 ];/* reserved */ +__u8 rnid_fmt;/* data format */ +__u8 rnid_cid_len;/* common ID data length */ +__u8 rnid_resv2;/* reserved */ +__u8 rnid_sid_len;/* specific ID data length */ +}; + +struct fc_els_rnid_cid { +__be64 rnid_wwpn;/* N port name */ +__be64 rnid_wwnn;/* node name */ +}; + +struct fc_els_rnid_gen { +__u8 rnid_vend_id[16 ];/* vendor-unique ID */ +__be32 rnid_atype;/* associated type (see below) */ +__be32 rnid_phys_port;/* physical port number */ +__be32 rnid_att_nodes;/* number of attached nodes */ +__u8 rnid_node_mgmt;/* node management (see below) */ +__u8 rnid_ip_ver;/* IP version (see below) */ +__be16 rnid_prot_port;/* UDP / TCP port number */ +__be32 rnid_ip_addr[4 ];/* IP address */ +__u8 rnid_resvd[2 ];/* reserved */ +__be16 rnid_vend_spec;/* vendor-specific field */ +}; + +enum fc_els_rnid_atype { +ELS_RNIDA_UNK =0x01 ,/* unknown */ +ELS_RNIDA_OTHER =0x02 ,/* none of the following */ +ELS_RNIDA_HUB =0x03 , +ELS_RNIDA_SWITCH =0x04 , +ELS_RNIDA_GATEWAY =0x05 , +ELS_RNIDA_CONV =0x06 ,/* Obsolete, do not use this value */ +ELS_RNIDA_HBA =0x07 ,/* Obsolete, do not use this value */ +ELS_RNIDA_PROXY =0x08 ,/* Obsolete, do not use this value */ +ELS_RNIDA_STORAGE =0x09 , +ELS_RNIDA_HOST =0x0a , +ELS_RNIDA_SUBSYS =0x0b ,/* storage subsystem (e.g., RAID) */ +ELS_RNIDA_ACCESS =0x0e ,/* access device (e.g. media changer) */ +ELS_RNIDA_NAS =0x11 ,/* NAS server */ +ELS_RNIDA_BRIDGE =0x12 ,/* bridge */ +ELS_RNIDA_VIRT =0x13 ,/* virtualization device */ +ELS_RNIDA_MF =0xff ,/* multifunction device (bits below) */ +ELS_RNIDA_MF_HUB =1UL <<31 ,/* hub */ +ELS_RNIDA_MF_SW =1UL <<30 ,/* switch */ +ELS_RNIDA_MF_GW =1UL <<29 ,/* gateway */ +ELS_RNIDA_MF_ST =1UL <<28 ,/* storage */ +ELS_RNIDA_MF_HOST =1UL <<27 ,/* host */ +ELS_RNIDA_MF_SUB =1UL <<26 ,/* storage subsystem */ +ELS_RNIDA_MF_ACC =1UL <<25 ,/* storage access dev */ +ELS_RNIDA_MF_WDM =1UL <<24 ,/* wavelength division mux */ +ELS_RNIDA_MF_NAS =1UL <<23 ,/* NAS server */ +ELS_RNIDA_MF_BR =1UL <<22 ,/* bridge */ +ELS_RNIDA_MF_VIRT =1UL <<21 ,/* virtualization device */ +}; + +enum fc_els_rnid_mgmt { +ELS_RNIDM_SNMP =0 , +ELS_RNIDM_TELNET =1 , +ELS_RNIDM_HTTP =2 , +ELS_RNIDM_HTTPS =3 , +ELS_RNIDM_XML =4 ,/* HTTP + XML */ +}; + +enum fc_els_rnid_ipver { +ELS_RNIDIP_NONE =0 ,/* no IP support or node mgmt. */ +ELS_RNIDIP_V4 =1 ,/* IPv4 */ +ELS_RNIDIP_V6 =2 ,/* IPv6 */ +}; + +/* +* ELS RPL - Read Port List. +*/ +struct fc_els_rpl { +__u8 rpl_cmd;/* command */ +__u8 rpl_resv[5 ];/* reserved - must be zero */ +__be16 rpl_max_size;/* maximum response size or zero */ +__u8 rpl_resv1;/* reserved - must be zero */ +__u8 rpl_index[3 ];/* starting index */ +}; + +/* +* Port number block in RPL response. +*/ +struct fc_els_pnb { +__be32 pnb_phys_pn;/* physical port number */ +__u8 pnb_resv;/* reserved */ +__u8 pnb_port_id[3 ];/* port ID */ +__be64 pnb_wwpn;/* port name */ +}; + +/* +* RPL LS_ACC response. +*/ +struct fc_els_rpl_resp { +__u8 rpl_cmd;/* ELS_LS_ACC */ +__u8 rpl_resv1;/* reserved - must be zero */ +__be16 rpl_plen;/* payload length */ +__u8 rpl_resv2;/* reserved - must be zero */ +__u8 rpl_llen[3 ];/* list length */ +__u8 rpl_resv3;/* reserved - must be zero */ +__u8 rpl_index[3 ];/* starting index */ +struct fc_els_pnb rpl_pnb[1 ];/* variable number of PNBs */ +}; + +/* +* Link Error Status Block. +*/ +struct fc_els_lesb { +__be32 lesb_link_fail;/* link failure count */ +__be32 lesb_sync_loss;/* loss of synchronization count */ +__be32 lesb_sig_loss;/* loss of signal count */ +__be32 lesb_prim_err;/* primitive sequence error count */ +__be32 lesb_inv_word;/* invalid transmission word count */ +__be32 lesb_inv_crc;/* invalid CRC count */ +}; + +/* +* ELS RPS - Read Port Status Block request. +*/ +struct fc_els_rps { +__u8 rps_cmd;/* command */ +__u8 rps_resv[2 ];/* reserved - must be zero */ +__u8 rps_flag;/* flag - see below */ +__be64 rps_port_spec;/* port selection */ +}; + +enum fc_els_rps_flag { +FC_ELS_RPS_DID =0x00 ,/* port identified by D_ID of req. */ +FC_ELS_RPS_PPN =0x01 ,/* port_spec is physical port number */ +FC_ELS_RPS_WWPN =0x02 ,/* port_spec is port WWN */ +}; + +/* +* ELS RPS LS_ACC response. +*/ +struct fc_els_rps_resp { +__u8 rps_cmd;/* command - LS_ACC */ +__u8 rps_resv[2 ];/* reserved - must be zero */ +__u8 rps_flag;/* flag - see below */ +__u8 rps_resv2[2 ];/* reserved */ +__be16 rps_status;/* port status - see below */ +struct fc_els_lesb rps_lesb;/* link error status block */ +}; + +enum fc_els_rps_resp_flag { +FC_ELS_RPS_LPEV =0x01 ,/* L_port extension valid */ +}; + +enum fc_els_rps_resp_status { +FC_ELS_RPS_PTP =1 <<5 ,/* point-to-point connection */ +FC_ELS_RPS_LOOP =1 <<4 ,/* loop mode */ +FC_ELS_RPS_FAB =1 <<3 ,/* fabric present */ +FC_ELS_RPS_NO_SIG =1 <<2 ,/* loss of signal */ +FC_ELS_RPS_NO_SYNC =1 <<1 ,/* loss of synchronization */ +FC_ELS_RPS_RESET =1 <<0 ,/* in link reset protocol */ +}; + +/* +* ELS LIRR - Link Incident Record Registration request. +*/ +struct fc_els_lirr { +__u8 lirr_cmd;/* command */ +__u8 lirr_resv[3 ];/* reserved - must be zero */ +__u8 lirr_func;/* registration function */ +__u8 lirr_fmt;/* FC-4 type of RLIR requested */ +__u8 lirr_resv2[2 ];/* reserved - must be zero */ +}; + +enum fc_els_lirr_func { +ELS_LIRR_SET_COND =0x01 ,/* set - conditionally receive */ +ELS_LIRR_SET_UNCOND =0x02 ,/* set - unconditionally receive */ +ELS_LIRR_CLEAR =0xff /* clear registration */ +}; + +/* +* ELS SRL - Scan Remote Loop request. +*/ +struct fc_els_srl { +__u8 srl_cmd;/* command */ +__u8 srl_resv[3 ];/* reserved - must be zero */ +__u8 srl_flag;/* flag - see below */ +__u8 srl_flag_param[3 ];/* flag parameter */ +}; + +enum fc_els_srl_flag { +FC_ELS_SRL_ALL =0x00 ,/* scan all FL ports */ +FC_ELS_SRL_ONE =0x01 ,/* scan specified loop */ +FC_ELS_SRL_EN_PER =0x02 ,/* enable periodic scanning (param) */ +FC_ELS_SRL_DIS_PER =0x03 ,/* disable periodic scanning */ +}; + +/* +* ELS RLS - Read Link Error Status Block request. +*/ +struct fc_els_rls { +__u8 rls_cmd;/* command */ +__u8 rls_resv[4 ];/* reserved - must be zero */ +__u8 rls_port_id[3 ];/* port ID */ +}; + +/* +* ELS RLS LS_ACC Response. +*/ +struct fc_els_rls_resp { +__u8 rls_cmd;/* ELS_LS_ACC */ +__u8 rls_resv[3 ];/* reserved - must be zero */ +struct fc_els_lesb rls_lesb;/* link error status block */ +}; + +/* +* ELS RLIR - Registered Link Incident Report. +* This is followed by the CLIR and the CLID, described below. +*/ +struct fc_els_rlir { +__u8 rlir_cmd;/* command */ +__u8 rlir_resv[3 ];/* reserved - must be zero */ +__u8 rlir_fmt;/* format (FC4-type if type specific) */ +__u8 rlir_clr_len;/* common link incident record length */ +__u8 rlir_cld_len;/* common link incident desc. length */ +__u8 rlir_slr_len;/* spec. link incident record length */ +}; + +/* +* CLIR - Common Link Incident Record Data. - Sent via RLIR. +*/ +struct fc_els_clir { +__be64 clir_wwpn;/* incident port name */ +__be64 clir_wwnn;/* incident port node name */ +__u8 clir_port_type;/* incident port type */ +__u8 clir_port_id[3 ];/* incident port ID */ + +__be64 clir_conn_wwpn;/* connected port name */ +__be64 clir_conn_wwnn;/* connected node name */ +__be64 clir_fab_name;/* fabric name */ +__be32 clir_phys_port;/* physical port number */ +__be32 clir_trans_id;/* transaction ID */ +__u8 clir_resv[3 ];/* reserved */ +__u8 clir_ts_fmt;/* time stamp format */ +__be64 clir_timestamp;/* time stamp */ +}; + +/* +* CLIR clir_ts_fmt - time stamp format values. +*/ +enum fc_els_clir_ts_fmt { +ELS_CLIR_TS_UNKNOWN =0 ,/* time stamp field unknown */ +ELS_CLIR_TS_SEC_FRAC =1 ,/* time in seconds and fractions */ +ELS_CLIR_TS_CSU =2 ,/* time in clock synch update format */ +}; + +/* +* Common Link Incident Descriptor - sent via RLIR. +*/ +struct fc_els_clid { +__u8 clid_iq;/* incident qualifier flags */ +__u8 clid_ic;/* incident code */ +__be16 clid_epai;/* domain/area of ISL */ +}; + +/* +* CLID incident qualifier flags. +*/ +enum fc_els_clid_iq { +ELS_CLID_SWITCH =0x20 ,/* incident port is a switch node */ +ELS_CLID_E_PORT =0x10 ,/* incident is an ISL (E) port */ +ELS_CLID_SEV_MASK =0x0c ,/* severity 2-bit field mask */ +ELS_CLID_SEV_INFO =0x00 ,/* report is informational */ +ELS_CLID_SEV_INOP =0x08 ,/* link not operational */ +ELS_CLID_SEV_DEG =0x04 ,/* link degraded but operational */ +ELS_CLID_LASER =0x02 ,/* subassembly is a laser */ +ELS_CLID_FRU =0x01 ,/* format can identify a FRU */ +}; + +/* +* CLID incident code. +*/ +enum fc_els_clid_ic { +ELS_CLID_IC_IMPL =1 ,/* implicit incident */ +ELS_CLID_IC_BER =2 ,/* bit-error-rate threshold exceeded */ +ELS_CLID_IC_LOS =3 ,/* loss of synch or signal */ +ELS_CLID_IC_NOS =4 ,/* non-operational primitive sequence */ +ELS_CLID_IC_PST =5 ,/* primitive sequence timeout */ +ELS_CLID_IC_INVAL =6 ,/* invalid primitive sequence */ +ELS_CLID_IC_LOOP_TO =7 ,/* loop initialization time out */ +ELS_CLID_IC_LIP =8 ,/* receiving LIP */ +}; + +#endif /* _FC_ELS_H_ */
include/scsi/fc/fc_encaps.h new file +138 -0
138 lines not on this page · raw message
include/scsi/fc/fc_fc2.h new file +124 -0
124 lines not on this page · raw message
include/scsi/fc/fc_fcoe.h new file +102 -0
102 lines not on this page · raw message
include/scsi/fc/fc_fcp.h new file +199 -0
199 lines not on this page · raw message
include/scsi/fc/fc_fs.h new file +340 -0
340 lines not on this page · raw message
include/scsi/fc/fc_gs.h new file +93 -0
93 lines not on this page · raw message
include/scsi/fc/fc_ns.h new file +159 -0
159 lines not on this page · raw message
PATCH 2/3 libfc: A modular Fibre Channel library
In reply to Robert Love---
drivers/scsi/Kconfig | 6 drivers/scsi/Makefile | 1 drivers/scsi/libfc/Makefile | 12 drivers/scsi/libfc/fc_disc.c | 932 ++++++++++++++++++ drivers/scsi/libfc/fc_elsct.c | 71 + drivers/scsi/libfc/fc_exch.c | 1971 ++++++++++++++++++++++++++++++++++++++ drivers/scsi/libfc/fc_fcp.c | 2130 +++++++++++++++++++++++++++++++++++++++++ drivers/scsi/libfc/fc_frame.c | 89 ++ drivers/scsi/libfc/fc_lport.c | 1525 +++++++++++++++++++++++++++++ drivers/scsi/libfc/fc_rport.c | 1277 +++++++++++++++++++++++++ include/scsi/fc_encode.h | 309 ++++++ include/scsi/fc_frame.h | 239 +++++ include/scsi/libfc.h | 917 ++++++++++++++++++ 13 files changed, 9479 insertions(+), 0 deletions(-) create mode 100644 drivers/scsi/libfc/Makefile create mode 100644 drivers/scsi/libfc/fc_disc.c create mode 100644 drivers/scsi/libfc/fc_elsct.c create mode 100644 drivers/scsi/libfc/fc_exch.c create mode 100644 drivers/scsi/libfc/fc_fcp.c create mode 100644 drivers/scsi/libfc/fc_frame.c create mode 100644 drivers/scsi/libfc/fc_lport.c create mode 100644 drivers/scsi/libfc/fc_rport.c create mode 100644 include/scsi/fc_encode.h create mode 100644 include/scsi/fc_frame.h create mode 100644 include/scsi/libfc.h
drivers/scsi/Kconfig +6 -0
@@ -603,6 +603,12 @@ config SCSI_FLASHPOINT substantial, so users of MultiMaster Host Adapters may not wish to include it. +config LIBFC + tristate "LibFC module" + depends on SCSI && SCSI_FC_ATTRS + ---help--- + Fibre Channel library module + config SCSI_DMX3191D tristate "DMX3191D SCSI support" depends on PCI && SCSI
drivers/scsi/Makefile +1 -0
@@ -36,6 +36,7 @@ obj-$(CONFIG_SCSI_SAS_LIBSAS) += libsas/ obj-$(CONFIG_SCSI_SRP_ATTRS) += scsi_transport_srp.o obj-$(CONFIG_SCSI_DH) += device_handler/ +obj-$(CONFIG_LIBFC) += libfc/ obj-$(CONFIG_ISCSI_TCP) += libiscsi.o iscsi_tcp.o obj-$(CONFIG_INFINIBAND_ISER) += libiscsi.o obj-$(CONFIG_SCSI_A4000T) += 53c700.o a4000t.o
drivers/scsi/libfc/Makefile new file +12 -0
@@ -0,0 +1,12 @@ +# $Id: Makefile + +obj-$(CONFIG_LIBFC) += libfc.o + +libfc-objs := \ + fc_disc.o \ + fc_exch.o \ + fc_elsct.o \ + fc_frame.o \ + fc_lport.o \ + fc_rport.o \ + fc_fcp.o
drivers/scsi/libfc/fc_disc.c new file +932 -0
932 lines not on this page · raw message
drivers/scsi/libfc/fc_elsct.c new file +71 -0
71 lines not on this page · raw message
drivers/scsi/libfc/fc_exch.c new file +1971 -0
1,966 lines not on this page · raw message
drivers/scsi/libfc/fc_fcp.c new file +2130 -0
2,130 lines not on this page · raw message
drivers/scsi/libfc/fc_frame.c new file +89 -0
89 lines not on this page · raw message
drivers/scsi/libfc/fc_lport.c new file +1525 -0
1,525 lines not on this page · raw message
drivers/scsi/libfc/fc_rport.c new file +1277 -0
1,277 lines not on this page · raw message
include/scsi/fc_encode.h new file +309 -0
309 lines not on this page · raw message
include/scsi/fc_frame.h new file +239 -0
239 lines not on this page · raw message
include/scsi/libfc.h new file +917 -0
917 lines not on this page · raw message
The rest of this diff is not shown. View the raw message.
Part of the diff is not shown here. View the raw message.
Re: [PATCH 2/3] libfc: A modular Fibre Channel library
Robert Love <[email protected]> writes:
A quick review. I'm not a SCSI layer expert, so it's more general code comments.
Could you perhaps give a brief design overview of the library in the description?
What it does, where it sits on the stack etc.? Doesn't need to be very extensive, but should be understandable even for people not intimate with the FCoE spec.
drivers/scsi/libfc/fc_disc.c line 36
Quoted 2 lines
drivers/scsi/libfc/fc_disc.c new file +2
-0+#define FC_DISC_RETRY_LIMIT 3/* max retries */ +#define FC_DISC_RETRY_DELAY 500UL/* (msecs) delay */
Define is not used?
drivers/scsi/libfc/fc_disc.c line 46
Quoted 10 lines
drivers/scsi/libfc/fc_disc.c new file +10
-0+ +#define FC_DISC_DELAY 3 + +static int fc_disc_debug; + +#define FC_DEBUG_DISC(fmt...) \ + do { \ + if (fc_disc_debug) \ + FC_DBG(fmt); \ + } while (0)
In 2.6.28 there is dynamic_printk.h now to handle this.
Quoted 5 lines
drivers/scsi/libfc/fc_disc.c new file +5
-0+ +static struct mutex disc_list_lock; +static struct list_head disc_list; + +struct fc_disc {
drivers/scsi/libfc/fc_disc.c line 61
Quoted 10 lines
drivers/scsi/libfc/fc_disc.c new file +10
-0+unsigned char retry_count; +unsigned char delay; +unsigned char pending; +unsigned char requested; +unsigned short seq_count; +unsigned char buf_len; +enum fc_disc_event event; + +void (*disc_callback)(struct fc_lport *, +enum fc_disc_event );
While it may seem excessive for a single callback the tend is towards separate ->ops structures. They have the advantage that they can be made const which has at least some theoretical security advantages. Also callback numbers tend to grow over time.
Quoted 7 lines
drivers/scsi/libfc/fc_disc.c new file +7
-0+/** +* fc_disc_lookup_rport - lookup a remote port by port_id +* @lport: Fibre Channel host port instance +* @port_id: remote port port_id to match +*/ +struct fc_rport *fc_disc_lookup_rport (const struct fc_lport *lport, +u32 port_id)
drivers/scsi/libfc/fc_disc.c line 98
Quoted 10 lines
drivers/scsi/libfc/fc_disc.c new file +10
-0+{ +struct fc_disc *disc; +struct fc_rport *rport, *found =NULL ; +struct fc_rport_libfc_priv *rdata; +int disc_found =0 ; + +mutex_lock (&disc_list_lock); +list_for_each_entry (disc, &disc_list, list) { +if (disc->lport == lport) { +list_for_each_entry (rdata, &disc->rports, peers) {
Hopefully the max numbers of either of those are strictly bounded.
drivers/scsi/libfc/fc_disc.c line 129
Quoted 10 lines
drivers/scsi/libfc/fc_disc.c new file +10
-0+ +/** +* fc_disc_alloc - Allocate a discovery work object +* @lport: The FC lport associated with the discovery job +*/ +static inline struct fc_disc *fc_disc_alloc (struct fc_lport *lport) +{ +struct fc_disc *disc; + + disc =kzalloc (sizeof (struct fc_disc ),GFP_KERNEL );
This misses a NULL check
drivers/scsi/libfc/fc_disc.c line 137
Quoted 8 lines
drivers/scsi/libfc/fc_disc.c new file +8
-0+INIT_LIST_HEAD (&disc->list); +INIT_DELAYED_WORK (&disc->disc_work, fc_disc_timeout); +mutex_init (&disc->disc_mutex); +INIT_LIST_HEAD (&disc->rports); + + disc->lport = lport; + disc->delay =FC_DISC_DELAY ; + disc->event =DISC_EV_NONE ;
Is it ok that the callback (and probably some other fields) is not initialized here yet?
drivers/scsi/libfc/fc_disc.c line 141
Quoted 4 lines
drivers/scsi/libfc/fc_disc.c new file +4
-0+ +mutex_lock (&disc_list_lock); +list_add_tail (&disc->list, &disc_list); +mutex_unlock (&disc_list_lock);
... when you make this globally visible?
drivers/scsi/libfc/fc_disc.c line 201
Quoted 11 lines
drivers/scsi/libfc/fc_disc.c new file +11
-0+if (event ==RPORT_EV_CREATED ) { +mutex_lock (&disc_list_lock); +list_for_each_entry (disc, &disc_list, list) { +if (disc->lport == lport) { + found =1 ; +mutex_lock (&disc->disc_mutex); +list_add_tail (&rdata->peers, &disc->rports); +mutex_unlock (&disc->disc_mutex); + } + } +mutex_unlock (&disc_list_lock);
That's a lot of locks. Did you have a locking order comment somewhere?
drivers/scsi/libfc/fc_disc.c line 247
Quoted 7 lines
drivers/scsi/libfc/fc_disc.c new file +7
-0+if (!rp || rp->rscn_page_len !=sizeof (*pp)) + goto reject; + + len =ntohs (rp->rscn_plen); +if (len <sizeof (*rp)) + goto reject; + len -=sizeof (*rp);
Don't you need to check here than len is a multiple of sizeof(*pp) ? Otherwise bad input could make it loop a very long time.
Review
Quoted 2 lines
(quoted diff) +2
-0+ + for (pp = (void *)(rp + 1); len; len -= sizeof(*pp), pp++) {
Also len >= 0 is always safer.
drivers/scsi/libfc/fc_disc.c line 296
Quoted 7 lines
drivers/scsi/libfc/fc_disc.c new file +7
-0+ redisc, lport->state, disc->pending); +list_for_each_entry_safe (dp, next, &disc_ports, peers) { +list_del (&dp->peers); + rport = lport->tt.rport_lookup (lport, dp->ids.port_id); +if (rport) { + rdata =RPORT_TO_PRIV (rport); +list_del (&rdata->peers);
Hopefully there's a mutex here hold for that list.
drivers/scsi/libfc/fc_disc.c line 309
Quoted 13 lines
drivers/scsi/libfc/fc_disc.c new file +13
-0+ lport->tt.rport_logoff (rport); + } +fc_disc_single (disc, dp); + } + } +fc_frame_free (fp); +return ; +reject: + rjt_data.fp =NULL ; + rjt_data.reason =ELS_RJT_LOGIC ; + rjt_data.explan =ELS_EXPL_NONE ; + lport->tt.seq_els_rsp_send (sp,ELS_LS_RJT , &rjt_data); +fc_frame_free (fp);
Some statistics counter for that case would be probably useful.
drivers/scsi/libfc/fc_disc.c line 349
Quoted 7 lines
drivers/scsi/libfc/fc_disc.c new file +7
-0+ + op =fc_frame_payload_op (fp); +switch (op) { +case ELS_RSCN : +mutex_lock (&disc->disc_mutex); +fc_disc_recv_rscn_req (sp, fp, disc); +mutex_unlock (&disc->disc_mutex);
Ok yes seems the lock is hold.
drivers/scsi/libfc/fc_disc.c line 377
Quoted 6 lines
drivers/scsi/libfc/fc_disc.c new file +6
-0+ +list_for_each_entry_safe (rdata, next, &disc->rports, peers) { + rport =PRIV_TO_RPORT (rdata); +FC_DEBUG_DISC ("list_del(%6x)\n" , rport->port_id); +list_del (&rdata->peers); + lport->tt.rport_logoff (rport);
Hopefully that callback knows for which peer that is.
Quoted 7 lines
drivers/scsi/libfc/fc_disc.c new file +7
-0+static void fc_disc_start (void (*disc_callback)(struct fc_lport *, +enum fc_disc_event ), +struct fc_lport *lport) +{ +struct fc_rport *rport; +struct fc_rport_identifiers ids; +struct fc_disc *disc;
drivers/scsi/libfc/fc_disc.c line 407
Quoted 10 lines
drivers/scsi/libfc/fc_disc.c new file +10
-0+int found =0 ; + +mutex_lock (&disc_list_lock); +list_for_each_entry (disc, &disc_list, list) { +if (disc->lport == lport) { + found =1 ; +break ; + } + } +mutex_unlock (&disc_list_lock);
This seems to be opencoded a lot. Put it into some helper.
Quoted 8 lines
drivers/scsi/libfc/fc_disc.c new file +8
-0+ +/* +* Handle point-to-point mode as a simple discovery +* of the remote port. Yucky, yucky, yuck, yuck! +*/ + rport = disc->lport->ptp_rp; +if (rport) { + ids.port_id = rport->port_id;
drivers/scsi/libfc/fc_disc.c line 454
Quoted 10 lines
drivers/scsi/libfc/fc_disc.c new file +10
-0+ ids.port_name = rport->port_name; + ids.node_name = rport->node_name; + ids.roles =FC_RPORT_ROLE_UNKNOWN ; +get_device (&rport->dev); + +if (!fc_disc_new_target (disc, rport, &ids)) { + disc->event =DISC_EV_SUCCESS ; +fc_disc_done (disc); + } +put_device (&rport->dev);
The ref counting here seems a little dubious. If it's because disc_new_target can sleep then preemptible kernels can do that anyways. Or it's not needed.
Quoted 16 lines
drivers/scsi/libfc/fc_disc.c new file +16
-0+ } +if (((ids->port_name !=-1 ) || (ids->port_id !=-1 )) && + ids->port_id !=fc_host_port_id (lport->host) && + ids->port_name != lport->wwpn) { +if (!rport) { + rport = lport->tt.rport_lookup (lport, ids->port_id); +if (!rport) { +struct fc_disc_port dp; + dp.lp = lport; + dp.ids.port_id = ids->port_id; + dp.ids.port_name = ids->port_name; + dp.ids.node_name = ids->node_name; + dp.ids.roles = ids->roles; + rport =fc_rport_rogue_create (&dp); + } +if (!rport)
drivers/scsi/libfc/fc_disc.c line 522
Quoted 10 lines
drivers/scsi/libfc/fc_disc.c new file +10
-0+ error =ENOMEM ; + } +if (rport) { + rp = rport->dd_data; + rp->event_callback = fc_disc_rport_event; + rp->rp_state =RPORT_ST_INIT ; + lport->tt.rport_login (rport); + } + } +return error;
Unusual positive error return convention. Ok?
drivers/scsi/libfc/fc_disc.c line 572
Quoted 5 lines
drivers/scsi/libfc/fc_disc.c new file +5
-0+FC_DBG ("Error %ld, retries %d/%d\n" , +PTR_ERR (fp), disc->retry_count, +FC_DISC_RETRY_LIMIT ); + +if (!fp ||PTR_ERR (fp) == -FC_EX_TIMEOUT ) {
The mixing of non errnos into PTR_ERR is also unusual, but ok, but make sure you never leak them.
drivers/scsi/libfc/fc_disc.c line 580
Quoted 8 lines
drivers/scsi/libfc/fc_disc.c new file +8
-0+/* +* Memory allocation failure, or the exchange timed out, +* retry after delay. +*/ +if (disc->retry_count <FC_DISC_RETRY_LIMIT ) { +/* go ahead and retry */ +if (!fp) + delay =msecs_to_jiffies (500 );
Ah that was the missing define above?
drivers/scsi/libfc/fc_disc.c line 587
Quoted 7 lines
drivers/scsi/libfc/fc_disc.c new file +7
-0+else { + delay = jiffies + +msecs_to_jiffies (lport->e_d_tov); + +/* timeout faster first time */ +if (!disc->retry_count) + delay /=4 ;
You have to divide by four before you add to jiffies, dividing absolute jiffies doesn't make sense.
drivers/scsi/libfc/fc_disc.c line 665
Quoted 12 lines
drivers/scsi/libfc/fc_disc.c new file +12
-0+/* +* Handle partial name record left over from previous call. +*/ + bp = buf; + plen = len; + np = (struct fc_gpn_ft_resp *)bp; + tlen = disc->buf_len; +if (tlen) { +WARN_ON (tlen >=sizeof (*np)); + plen =sizeof (*np) - tlen; +WARN_ON (plen <=0 ); +WARN_ON (plen >=sizeof (*np));
I hope none of these WARN_ONs in network controllable. They nearly look like some of them are.
Ok stopping here for now. That's a lot of code. Perhaps split it up into a little smaller patches?
General impressions:
- Your locking is to complicated I think. Less locks is often more. For short locks we also recommend spinlocks which perform better (although you have to make sure you don't sleep then of course)
- I would double check everything that handles network data to make sure it's not exploitable.
-Andi
Signature · 1 line
[email protected]
RE: [PATCH 2/3] libfc: A modular Fibre Channel library
Quoted 5 lines · Andi Kleen
Robert Love <[email protected]> writes:
A quick review. I'm not a SCSI layer expert, so it's more general code comments.
Thanks. I appreciate all reviews.
Quoted 3 lines
Could you perhaps give a brief design overview of the library in the description?
Sure. I'll put it in the description when I re-submit.
It's fairly complicated, so even though I'm trying to be breif, this overview got a bit long. The library has 5 major layers/blocks- the EM, FCP, LP, RP, and disc. The EM is the Exchange Manager and it is used by each of the other four blocks. FCP is the mapping of SCSI commands to FC frames, it's the I/O path. The RP layer handles individual targets (i.e. remote ports). The LP block handles the host (or local port) for example, fabric login, registration with the directoy server, etc... The disc layer handles discovery, it queries the directoy server to find the targets/RPs that are in its zone.
The FC transport class already provides us some remote port functionality. It doesn't manage our RP state machine, but we interact with it to add/delete RPs from both sysfs, it's also what makes the SCSI-ml aware that there is storage available.
We have some diagrams that might be helpful, but they haven't been refreshed in a few months. They're at:
http://www.open-fcoe.org/openfc/wiki/index.php/Architecture
My incomplete ASCII representation looks like this.
---------------------------
| FC Transport Class
---------------------------
^
| (add/delete)
v
---------------------------
| RP
---------------------------
^ ^ | (targets) | (directory server) v | -------------- | | Disc | -------------- | ^ | | | v v
---------------------------
| LP
---------------------------
The EM is in-use by each of the blocks drawn above.
The I/O path is pretty straight-forward, kind of silly to draw.
-------------------------
| SCSI-ml
-------------------------
^
|
v
-------------------------
| FCP
-------------------------
^
|
v
-------------------------
| EM
-------------------------
Quoted 4 lines
What it does, where it sits on the stack etc.? Doesn't need to be very extensive, but should be understandable even for people not intimate with the FCoE spec.
So, libfc is an assist library, fcoe is the LLD. The stack looks roughly like this.
----------- -------------------- | SCSI-ml | | FC transport class ----------- -------------------- ^ ^ | | v v --------------------------- ------------- | FCoE | <- - -> | libfc | --------------------------- -------------
^
|
v
--------------------------
| netdev
--------------------------
fcoe is the LLD to the SCSI-ml and it allocates the scsi_host. When allocating the scsi_host it requests some memory for the fc_lport (as well as a fcoe structure) and then uses the libfc state machine to login to the fabric and register with the necessary entities. This process requires the lport to start a fc_rport for the directory server (we must be logged in to do discovery). Once that has occurred we start discovery which queries the directory server and returns us a list of targets. We create a fc_rport for each of those targets and have the RP layer log us into each of those targets. Once we're logged into a target we "add" it to the transport layer. It show up in sysfs and the SCSI-ml begins querying it (I/O).
We've been trying to make libfc as flexible as possible as we expect a variety of LLDs to use it eventually. Users could be traditional FC HBAs, SW only FCoE HBAs or offloaded FC/FCoE HBAs. Therefore each block (EM, FCP, RP, LP, disc) can be implemented by libfc or by a LLD. Our transport template in libfc.h defines all of the transition points between each of these blocks so that a LLD that doesn't want to use the library provided block can just assign its own functions in the template before starting the library.
For libfc we've also added an interface at the FCP layer to allow LLDs to partially use that layer. This interface allows the library to do the SCSI->FC mapping and then pass the FCP command down to the LLD. A mini FC framing mini-library, in fc_encode.h and an ELS/CT interface is also available.
For FCoE there has been recent work to support FCoE HBAs that offload various functionality.
Quoted 5 lines
drivers/scsi/libfc/fc_disc.c line 36
Quoted 2 lines
drivers/scsi/libfc/fc_disc.c new file +2
-0+#define FC_DISC_RETRY_LIMIT 3/* max retries */ +#define FC_DISC_RETRY_DELAY 500UL/* (msecs) delay */ Define is not used?
Yeah, I think you caught this below. I will fix it.
Quoted 4 lines
Quoted 4 lines
drivers/scsi/libfc/fc_disc.c new file +4
-0+ +#define FC_DISC_DELAY 3 + +static int fc_disc_debug;
Quoted 9 lines
drivers/scsi/libfc/fc_disc.c line 46
Quoted 6 lines
drivers/scsi/libfc/fc_disc.c new file +6
-0+ +#define FC_DEBUG_DISC(fmt...) \ + do { \ + if (fc_disc_debug) \ + FC_DBG(fmt); \ + } while (0)In 2.6.28 there is
dynamic_printk.hnow to handle this.
Excellent, we have this block in a few places. I'll change this.
Quoted 33 lines
Quoted 6 lines
drivers/scsi/libfc/fc_disc.c new file +5
-0+ +static struct mutex disc_list_lock; +static struct list_head disc_list; + +struct fc_disc {drivers/scsi/libfc/fc_disc.c line 61
Quoted 10 lines
drivers/scsi/libfc/fc_disc.c new file +10
-0+unsigned char retry_count; +unsigned char delay; +unsigned char pending; +unsigned char requested; +unsigned short seq_count; +unsigned char buf_len; +enum fc_disc_event event; + +void (*disc_callback)(struct fc_lport *, +enum fc_disc_event );While it may seem excessive for a single callback the tend is towards separate ->ops structures. They have the advantage that they can be made const which has at least some theoretical security advantages. Also callback numbers tend to grow over time.
Quoted 10 lines
drivers/scsi/libfc/fc_disc.c new file +10
-0+/** +* fc_disc_lookup_rport - lookup a remote port by port_id +* @lport: Fibre Channel host port instance +* @port_id: remote port port_id to match +*/ +struct fc_rport *fc_disc_lookup_rport (const struct fc_lport *lport, + u32 port_id) +{ +struct fc_disc *disc; +struct fc_rport *rport, *found =NULL ; +struct fc_rport_libfc_priv *rdata;
Quoted 9 lines
drivers/scsi/libfc/fc_disc.c line 98
Quoted 6 lines
drivers/scsi/libfc/fc_disc.c new file +6
-0+int disc_found =0 ; + +mutex_lock (&disc_list_lock); +list_for_each_entry (disc, &disc_list, list) { +if (disc->lport == lport) { +list_for_each_entry (rdata, &disc->rports, peers) {Hopefully the max numbers of either of those are strictly bounded.
The max number of discovery objects? It isn't bound now. I don't think that this discovery list is working out as well as I had hoped that it would. There is a patch on our mailing list now that removes this list and just attaches the disc object to the lport. This means that there is no lookup anymore. Since all incoming FC requests go though the lport first it can just follow its pointer, get the disc object and use it.
Quoted 11 lines
drivers/scsi/libfc/fc_disc.c line 129
Quoted 8 lines
drivers/scsi/libfc/fc_disc.c new file +8
-0+ +/** +* fc_disc_alloc - Allocate a discovery work object +* @lport: The FC lport associated with the discovery job + */ +static inline struct fc_disc *fc_disc_alloc (struct fc_lport *lport) +{ + struct fc_disc *disc; + + disc =kzalloc (sizeof (struct fc_disc ),GFP_KERNEL );This misses a NULL check
OK, will fix.
Quoted 31 lines
drivers/scsi/libfc/fc_disc.c line 137
Quoted 8 lines
drivers/scsi/libfc/fc_disc.c new file +8
-0+INIT_LIST_HEAD (&disc->list); +INIT_DELAYED_WORK (&disc->disc_work, fc_disc_timeout); +mutex_init (&disc->disc_mutex); +INIT_LIST_HEAD (&disc->rports); + + disc->lport = lport; + disc->delay =FC_DISC_DELAY ; + disc->event =DISC_EV_NONE ;Is it ok that the callback (and probably some other fields) is not initialized here yet?
drivers/scsi/libfc/fc_disc.c line 141
Quoted 4 lines
drivers/scsi/libfc/fc_disc.c new file +4
-0+ +mutex_lock (&disc_list_lock); +list_add_tail (&disc->list, &disc_list); +mutex_unlock (&disc_list_lock);... when you make this globally visible?
drivers/scsi/libfc/fc_disc.c line 201
Quoted 11 lines
drivers/scsi/libfc/fc_disc.c new file +11
-0+if (event ==RPORT_EV_CREATED ) { +mutex_lock (&disc_list_lock); +list_for_each_entry (disc, &disc_list, list) { +if (disc->lport == lport) { + found =1 ; +mutex_lock (&disc->disc_mutex); +list_add_tail (&rdata->peers, &disc->rports); +mutex_unlock (&disc->disc_mutex); + } + } +mutex_unlock (&disc_list_lock);
Quoted 2 lines
That's a lot of locks. Did you have a locking order comment somewhere?
I have a locking comment at the top of fc_lport.c as well as fc_rport.c, but they don't mention the discovery code. After we change the disc object management I'll make sure they're up-to-date. The locking has been particularly troublesome for me, so I'm sure it can be improved.
Quoted 11 lines
drivers/scsi/libfc/fc_disc.c line 247
Quoted 7 lines
drivers/scsi/libfc/fc_disc.c new file +7
-0+if (!rp || rp->rscn_page_len !=sizeof (*pp)) + goto reject; + + len =ntohs (rp->rscn_plen); +if (len <sizeof (*rp)) + goto reject; + len -=sizeof (*rp);Don't you need to check here than len is a multiple of
sizeof(*pp)? Otherwise bad input could make it loop a very long time.
I'll have to look into this. You're comment seems reasonable though.
Quoted 5 lines
Review
Quoted 2 lines
(quoted diff) +2
-0+ + for (pp = (void *)(rp + 1); len; len -= sizeof(*pp), pp++) {Also len >= 0 is always safer.
Noted.
Quoted 31 lines
Quoted 5 lines
drivers/scsi/libfc/fc_disc.c new file +3
-0+ redisc, lport->state, disc->pending); +list_for_each_entry_safe (dp, next, &disc_ports, peers) { + list_del(&dp->peers); + rport = lport->tt.rport_lookup(lport,
dp->ids.port_id); + if (rport) { + rdata =RPORT_TO_PRIV(rport);
+list_del(&rdata->peers);Hopefully there's a mutex here hold for that list.
drivers/scsi/libfc/fc_disc.c line 309
Quoted 13 lines
drivers/scsi/libfc/fc_disc.c new file +13
-0+ lport->tt.rport_logoff (rport); + } +fc_disc_single (disc, dp); + } + } +fc_frame_free (fp); +return ; +reject: + rjt_data.fp =NULL ; + rjt_data.reason =ELS_RJT_LOGIC ; + rjt_data.explan =ELS_EXPL_NONE ; + lport->tt.seq_els_rsp_send (sp,ELS_LS_RJT , &rjt_data); +fc_frame_free (fp);Some statistics counter for that case would be probably useful.
drivers/scsi/libfc/fc_disc.c line 349
Quoted 7 lines
drivers/scsi/libfc/fc_disc.c new file +7
-0+ + op =fc_frame_payload_op (fp); +switch (op) { +case ELS_RSCN : +mutex_lock (&disc->disc_mutex); +fc_disc_recv_rscn_req (sp, fp, disc); +mutex_unlock (&disc->disc_mutex);
Quoted 9 lines
Ok yes seems the lock is hold.
drivers/scsi/libfc/fc_disc.c
Quoted 5 lines
drivers/scsi/libfc/fc_disc.c new file +5
-0+ +list_for_each_entry_safe (rdata, next, &disc->rports, peers) { + rport =PRIV_TO_RPORT (rdata); +FC_DEBUG_DISC ("list_del(%6x)\n" , rport->port_id); +list_del (&rdata->peers); + lport->tt.rport_logoff (rport);Hopefully that callback knows for which peer that is.
I'm a little confused what you're referring to here. rport_logoff() is one of our transport template function pointers, so for the purely SW case the rport layer will handle the logoff(). I'm not sure if this is what you were getting at though.
Quoted 10 lines
Quoted 10 lines
drivers/scsi/libfc/fc_disc.c new file +10
-0+static void fc_disc_start (void (*disc_callback)(struct fc_lport *, + enum fc_disc_event), + struct fc_lport *lport) +{ +struct fc_rport *rport; +struct fc_rport_identifiers ids; +struct fc_disc *disc; +int found =0 ; + +mutex_lock (&disc_list_lock); +list_for_each_entry (disc, &disc_list, list) {
Quoted 8 lines
drivers/scsi/libfc/fc_disc.c line 336
Quoted 6 lines
drivers/scsi/libfc/fc_disc.c new file +6
-0+if (disc->lport == lport) { + found =1 ; +break ; + } + } +mutex_unlock (&disc_list_lock);This seems to be opencoded a lot. Put it into some helper.
Yes, we probably do this too much. If we end up not using the discovery list we can dump a lot of this code.
Quoted 14 lines
Quoted 14 lines
drivers/scsi/libfc/fc_disc.c new file +14
-0+ +/* +* Handle point-to-point mode as a simple discovery +* of the remote port. Yucky, yucky, yuck, yuck! +*/ + rport = disc->lport->ptp_rp; +if (rport) { + ids.port_id = rport->port_id; + ids.port_name = rport->port_name; + ids.node_name = rport->node_name; + ids.roles =FC_RPORT_ROLE_UNKNOWN ; +get_device (&rport->dev); + +if (!fc_disc_new_target (disc, rport, &ids)) {
Quoted 9 lines
drivers/scsi/libfc/fc_disc.c line 454
Quoted 4 lines
drivers/scsi/libfc/fc_disc.c new file +4
-0+ disc->event =DISC_EV_SUCCESS ; +fc_disc_done (disc); + } +put_device (&rport->dev);The ref counting here seems a little dubious. If it's because
disc_new_targetcan sleep then preemptible kernels can do that anyways. Or it's not needed.
OK, I'll have to look into this.
Quoted 26 lines
Quoted 15 lines
drivers/scsi/libfc/fc_disc.c new file +6
-0+ } +if (((ids->port_name !=-1 ) || (ids->port_id !=-1 )) && + ids->port_id !=fc_host_port_id (lport->host) && + ids->port_name != lport->wwpn) { +if (!rport) { + rport = lport->tt.rport_lookup (lport, ids->port_id); + if(!rport) { + struct
fc_disc_portdp;drivers/scsi/libfc/fc_disc.c new file +8
-0+ dp.lp = lport; + dp.ids.port_id = ids->port_id; + dp.ids.port_name = ids->port_name; + dp.ids.node_name = ids->node_name; + dp.ids.roles = ids->roles; + rport =fc_rport_rogue_create (&dp); + } +if (!rport)drivers/scsi/libfc/fc_disc.c line 522
Quoted 10 lines
drivers/scsi/libfc/fc_disc.c new file +10
-0+ error =ENOMEM ; + } +if (rport) { + rp = rport->dd_data; + rp->event_callback = fc_disc_rport_event; + rp->rp_state =RPORT_ST_INIT ; + lport->tt.rport_login (rport); + } + } +return error;
Quoted 2 lines
Unusual positive error return convention. Ok?
Just an oversight, I'll correct this.
Quoted 17 lines
drivers/scsi/libfc/fc_disc.c line 572
Quoted 5 lines
drivers/scsi/libfc/fc_disc.c new file +5
-0+FC_DBG ("Error %ld, retries %d/%d\n" , +PTR_ERR (fp), disc->retry_count, +FC_DISC_RETRY_LIMIT ); + +if (!fp ||PTR_ERR (fp) == -FC_EX_TIMEOUT ) {The mixing of non errnos into
PTR_ERRis also unusual, but ok, but make sure you never leak them.drivers/scsi/libfc/fc_disc.c line 580
Quoted 7 lines
(quoted diff) +2
-0+ /* + * Memory allocation failure, or the exchange timed out, + *retry after delay. + */
drivers/scsi/libfc/fc_disc.c new file +4
-0+if (disc->retry_count <FC_DISC_RETRY_LIMIT ) { +/* go ahead and retry */ +if (!fp) + delay =msecs_to_jiffies (500 );
Quoted 2 lines
Ah that was the missing define above?
Yeah, we'll take care of this.
Quoted 11 lines
drivers/scsi/libfc/fc_disc.c line 587
Quoted 7 lines
drivers/scsi/libfc/fc_disc.c new file +7
-0+else { + delay = jiffies + +msecs_to_jiffies (lport->e_d_tov); + +/* timeout faster first time */ +if (!disc->retry_count) + delay /=4 ;You have to divide by four before you add to jiffies, dividing absolute jiffies doesn't make sense.
Will do.
Quoted 12 lines
drivers/scsi/libfc/fc_disc.c line 665
Quoted 11 lines
drivers/scsi/libfc/fc_disc.c new file +11
-0+/* +* Handle partial name record left over from previous call. + */ + bp = buf; + plen = len; + np = (struct fc_gpn_ft_resp *)bp; + tlen = disc->buf_len; +if (tlen) { +WARN_ON (tlen >=sizeof (*np)); + plen =sizeof (*np) - tlen; +WARN_ON (plen <=0 ); +WARN_ON (plen >=sizeof (*np));
Quoted 6 lines
I hope none of these
WARN_ONsin network controllable. They nearly look like some of them are.Ok stopping here for now. That's a lot of code. Perhaps split it up into a little smaller patches?
OK, I can do that. Honestly, preparing these patches is a pain. We have a full git tree that isn't reviewable. So, I diff, splitdiff and then start putting things back together manually. Maybe, patches by the different blocks would be more easily reviewable...?
Most people are on vacation this week, including myself. We'll correct the called-out problems and re-send a patch next week.
Quoted 2 lines
General impressions:
- Your locking is to complicated I think. Less locks is often more.
So, the question for me is really if the discovery object should have its own lock or if it should share the lport's lock. I liked it having its own lock because it seemed to make it more modular, but the discovery code (as well as the EM) still relies on the lport and so it is in limbo a bit. It has its own members and lock, but still relies on the lport. If the pointer to the discovery object moves into the lport and the disc list goes away then maybe it makes sense to just use the lport lock. I guess I envisioned some meta-data eventually being passed between the lport and the discovery layer so they were more independent.
Quoted 6 lines
For short locks we also recommend spinlocks which perform better (although you have to make sure you don't sleep then of course)
- I would double check everything that handles network data to make sure it's not exploitable.-Andi
Thanks,
//Rob
RE: [PATCH 2/3] libfc: A modular Fibre Channel library
In reply to Andi KleenQuoted 2 lines · Andi Kleen
Robert Love <[email protected]> writes:
<snip>
Quoted 10 lines
drivers/scsi/libfc/fc_disc.c line 46
Quoted 7 lines
drivers/scsi/libfc/fc_disc.c new file +7
-0+static int fc_disc_debug; + +#define FC_DEBUG_DISC(fmt...) \ + do { \ + if (fc_disc_debug) \ + FC_DBG(fmt); \ + } while (0)In 2.6.28 there is
dynamic_printk.hnow to handle this.
I was looking into making this change, but the dynamic_printk doesn't do what we want. We have this code in each of our layers to allow us to turn on debugging at a sub-module level, as far as I can tell this isn't supported by the dynamic_printk.
I then thought that we could convert our debug statements to pr_debug() calls (I'm not sure what 'pr' stands for, but I think that's what I should use). However, that would cause us to do excessive printing if the kernel was configured with DEBUG (how do you set this?). This is especially true in the EM where code is executed frequently and some of our debug statements happen often when the EM debug define has a value. Also, it would mean that when debugging Open-FCoE, we'd have all kernel debug statements, not just our own.
What I really want is the ability to dynamically turn on or off our port code debug statements (LP, RP and disc) and then have a compile option for our I/O path and EM. We think that adding module parameter to toggle some of these prints would probably work best for our needs, but it's low on our priority list right now.
Open-iSCSI uses a method similar to what we're doing, just not to the degree that we're doing it and I didn't find much use of pr_debug in drivers/scsi/* or include/scsi/*.
PATCH 3/3 fcoe: Fibre Channel over Ethernet
In reply to Robert LoveEncapsulation protocol for running Fibre Channel over Ethernet interfaces. Creates virtual Fibre Channel host adapters using libfc.
This patch leaves two WARNINGs from checkpatch.pl regarding the use of NR_CPUS. We're using them to create per-cpu receive threads. Since these are WARNINGS and not ERRORS we'd like to fix this issue later.
---
drivers/scsi/Kconfig | 7 drivers/scsi/Makefile | 1 drivers/scsi/fcoe/Makefile | 8 drivers/scsi/fcoe/fc_transport_fcoe.c | 446 ++++++++++ drivers/scsi/fcoe/fcoe_sw.c | 488 +++++++++++ drivers/scsi/fcoe/libfcoe.c | 1506 +++++++++++++++++++++++++++++++++ include/scsi/fc_transport_fcoe.h | 54 + include/scsi/libfcoe.h | 177 ++++ 8 files changed, 2687 insertions(+), 0 deletions(-) create mode 100644 drivers/scsi/fcoe/Makefile create mode 100644 drivers/scsi/fcoe/fc_transport_fcoe.c create mode 100644 drivers/scsi/fcoe/fcoe_sw.c create mode 100644 drivers/scsi/fcoe/libfcoe.c create mode 100644 include/scsi/fc_transport_fcoe.h create mode 100644 include/scsi/libfcoe.h
drivers/scsi/Kconfig +7 -0
@@ -609,6 +609,13 @@ config LIBFC ---help--- Fibre Channel library module +config FCOE + tristate "FCoE module" + depends on SCSI + select LIBFC + ---help--- + Fibre Channel over Ethernet module + config SCSI_DMX3191D tristate "DMX3191D SCSI support" depends on PCI && SCSI
drivers/scsi/Makefile +1 -0
@@ -37,6 +37,7 @@ obj-$(CONFIG_SCSI_SRP_ATTRS) += scsi_transport_srp.o obj-$(CONFIG_SCSI_DH) += device_handler/ obj-$(CONFIG_LIBFC) += libfc/ +obj-$(CONFIG_FCOE) += fcoe/ obj-$(CONFIG_ISCSI_TCP) += libiscsi.o iscsi_tcp.o obj-$(CONFIG_INFINIBAND_ISER) += libiscsi.o obj-$(CONFIG_SCSI_A4000T) += 53c700.o a4000t.o
drivers/scsi/fcoe/Makefile new file +8 -0
@@ -0,0 +1,8 @@ +# $Id: Makefile + +obj-$(CONFIG_FCOE) += fcoe.o + +fcoe-y := \ + libfcoe.o \ + fcoe_sw.o \ + fc_transport_fcoe.o
drivers/scsi/fcoe/fc_transport_fcoe.c new file +446 -0
446 lines not on this page · raw message
drivers/scsi/fcoe/fcoe_sw.c new file +488 -0
488 lines not on this page · raw message
drivers/scsi/fcoe/libfcoe.c new file +1506 -0
1,506 lines not on this page · raw message
include/scsi/fc_transport_fcoe.h new file +54 -0
54 lines not on this page · raw message
include/scsi/libfcoe.h new file +177 -0
177 lines not on this page · raw message