[Open-FCoE] [RFC PATCH] [open-fcoe] Add FC pass-through support

Joe Eykholt jeykholt at cisco.com
Mon Apr 27 21:07:18 UTC 2009


Ma, Steve wrote:
> Joe,
> 
> What is the "fctraceroute" you mentioned in your comment?
> Is it in the old stuff we have?

No, it's future stuff.  It's part of FC-GS.  I'm not sure
whether it's supported by switches at this point.

	Joe

> 
> Thanks
> -Steve
> 
>> -----Original Message-----
>> From: Joe Eykholt [mailto:jeykholt at cisco.com]
>> Sent: Monday, April 20, 2009 11:39 AM
>> To: Ma, Steve
>> Cc: devel at open-fcoe.org
>> Subject: Re: [Open-FCoE] [RFC PATCH] [open-fcoe] Add FC pass-through
>> support
>>
>> Steve Ma wrote:
>>> This is an implementation of the FC pass-through support in FCoE
>>> via bsg interface according to the RFC published by James Smart
>>> on 11/18/2008 with the title "[RFC] FC pass thru - Rev IV"
>>> ---
>>>
>> This is great!   Hopefully we can use this for fcping and fctraceroute
>> eventually.
>>>  drivers/scsi/fcoe/fcoe_sw.c   |    2
>>>  drivers/scsi/libfc/fc_rport.c |  232
>> +++++++++++++++++++++++++++++++++++++++++
>>>  include/scsi/libfc.h          |    2
>>>  3 files changed, 236 insertions(+), 0 deletions(-)
>>>
>>> diff --git a/drivers/scsi/fcoe/fcoe_sw.c b/drivers/scsi/fcoe/fcoe_sw.c
>>> index 765a388..04f38af 100644
>>> --- a/drivers/scsi/fcoe/fcoe_sw.c
>>> +++ b/drivers/scsi/fcoe/fcoe_sw.c
>>> @@ -83,6 +83,8 @@ struct fc_function_template fcoe_sw_transport_function
>> = {
>>>  	.issue_fc_host_lip = fcoe_reset,
>>>
>>>  	.terminate_rport_io = fc_rport_terminate_io,
>>> +
>>> +	.bsg_request = fcoe_bsg_request,
>>>  };
>>>
>>>  static struct scsi_host_template fcoe_sw_shost_template = {
>>> diff --git a/drivers/scsi/libfc/fc_rport.c
>> b/drivers/scsi/libfc/fc_rport.c
>>> index dae6513..41d1519 100644
>>> --- a/drivers/scsi/libfc/fc_rport.c
>>> +++ b/drivers/scsi/libfc/fc_rport.c
>>> @@ -1314,3 +1314,235 @@ void fc_rport_terminate_io(struct fc_rport
>> *rport)
>>>  	lport->tt.exch_mgr_reset(lport, rport->port_id, 0);
>>>  }
>>>  EXPORT_SYMBOL(fc_rport_terminate_io);
>>> +
>>> +struct fcoe_bsg_info {
>>> +	struct fc_bsg_job *job;
>>> +	struct fc_lport *lport;
>>> +};
>>> +
>>> +static void fc_bsg_els_resp(struct fc_seq *sp, struct fc_frame *fp,
>>> +				void *rp_arg)
>>> +{
>>> +	struct fcoe_bsg_info *info = (struct fcoe_bsg_info *)rp_arg;
>>> +	struct fc_bsg_job *job = info->job;
>>> +	struct fc_lport *lport = info->lport;
>>> +	unsigned int len;
>>> +	void *pp;
>>> +
>>> +	mutex_lock(&lport->lp_mutex);
>>> +
>>> +	if (IS_ERR(fp))
>>> +		goto err;
>>> +
>>> +	len = fr_len(fp) - sizeof(struct fc_frame_header);
>>> +	pp = fc_frame_payload_get(fp, len);
>>> +
>>> +	sg_copy_from_buffer(job->reply_payload.sg_list,
>>> +			    job->reply_payload.sg_cnt,
>>> +			    pp, len);
>>> +	job->reply->reply_payload_rcv_len = job->reply_payload.payload_len;
>>> +
>>> +	if (fc_frame_payload_op(fp) == ELS_LS_ACC)
>>> +		job->reply->reply_data.ctels_reply.status
>>> +			= FC_CTELS_STATUS_OK;
>>> +	else
>>> +		job->reply->reply_data.ctels_reply.status
>>> +			= FC_CTELS_STATUS_REJECT;
>>> +err:
>>> +	fc_frame_free(fp);
>>> +	mutex_unlock(&lport->lp_mutex);
>>> +	kfree(info);
>>> +	job->state_flags = FC_RQST_STATE_DONE;
>>> +	job->job_done(job);
>>> +}
>>> +
>>> +static int fcoe_bsg_els_request(struct fc_bsg_job *job)
>>> +{
>>> +	struct fcoe_bsg_info *info;
>>> +	struct fc_rport *rport = job->rport;
>>> +	struct Scsi_Host *shost;
>>> +	struct fc_lport *lport;
>>> +	struct fc_frame *fp;
>>> +	struct fc_frame_header *fh;
>>> +	char *pp;
>>> +	int len;
>>> +	u32 did;
>>> +
>>> +	shost = rport ? rport_to_shost(rport) : job->shost;
>>> +	lport = shost_priv(shost);
>>> +
>>> +	if (!((lport->state == LPORT_ST_READY) &&
>>> +	    lport->link_up && !lport->qfull))
>>> +		return -EINVAL;
>>> +
>>> +
>>> +	fp = fc_frame_alloc(lport, sizeof(struct fc_frame_header) +
>>> +				job->request_payload.payload_len);
>>> +	if (!fp)
>>> +		return -EINVAL;
>>> +
>>> +	len = job->request_payload.payload_len;
>>> +	pp = fc_frame_payload_get(fp, len);
>>> +	memset(pp, 0, len);
>>> +
>>> +	sg_copy_to_buffer(job->request_payload.sg_list,
>>> +			  job->request_payload.sg_cnt,
>>> +			  pp, len);
>>> +
>>> +	switch (pp[0]) {
>>> +	case ELS_RNID:
>>> +	case ELS_RLS:
>>> +	case ELS_RCS:
>>> +		did = job->request->rqst_data.h_els.port_id[0]<<16 |
>>> +		      job->request->rqst_data.h_els.port_id[1]<<8  |
>>> +		      job->request->rqst_data.h_els.port_id[2];
>>>
>> Use ntoh24().  This applies in a few other places.  Also, there should
>> be spaces around the <<.
>>> +		break;
>>> +	default:
>>> +		if (!rport) {
>>> +			fc_frame_free(fp);
>>> +			return -EINVAL;
>>> +		}
>>> +		did = rport->port_id;
>>> +		break;
>>> +	}
>>> +
>>> +	fh = fc_frame_header_get(fp);
>>> +	fh->fh_r_ctl = FC_RCTL_ELS_REQ;
>>> +	hton24(fh->fh_d_id, did);
>>> +	hton24(fh->fh_s_id, fc_host_port_id(shost));
>>> +	fh->fh_type = FC_TYPE_ELS;
>>> +	hton24(fh->fh_f_ctl, FC_FC_FIRST_SEQ |
>>> +		FC_FC_END_SEQ | FC_FC_SEQ_INIT);
>>> +	fh->fh_cs_ctl = 0;
>>> +	fh->fh_df_ctl = 0;
>>> +	fh->fh_parm_offset = 0;
>>> +
>>> +	info = kzalloc(sizeof(struct fcoe_bsg_info), GFP_KERNEL);
>>> +	if (!info) {
>>> +		fc_frame_free(fp);
>>> +		return -EINVAL;
>>> +	}
>>> +
>>> +	info->job = job;
>>> +	info->lport = lport;
>>> +
>>> +	lport->tt.exch_seq_send(lport, fp, fc_bsg_els_resp,
>>> +				NULL, (void *)info, lport->e_d_tov);
>>> +	return 0;
>>> +}
>>> +
>>> +static void fc_bsg_ct_resp(struct fc_seq *sp, struct fc_frame *fp,
>>> +				void *rp_arg)
>>> +{
>>> +	struct fcoe_bsg_info *info = (struct fcoe_bsg_info *)rp_arg;
>>> +	struct fc_bsg_job *job = info->job;
>>> +	struct fc_lport *lport = info->lport;
>>> +	struct fc_ct_hdr *ct;
>>> +	unsigned int len;
>>> +	void *pp;
>>> +
>>> +	mutex_lock(&lport->lp_mutex);
>>> +
>>> +	if (IS_ERR(fp))
>>> +		goto err;
>>> +
>>> +	len = fr_len(fp) - sizeof(struct fc_frame_header);
>>> +	pp = fc_frame_payload_get(fp, len);
>>> +	sg_copy_from_buffer(job->reply_payload.sg_list,
>>> +			    job->reply_payload.sg_cnt,
>>> +			    pp, len);
>>> +	job->reply->reply_payload_rcv_len = job->reply_payload.payload_len;
>>> +
>>> +	ct = (struct fc_ct_hdr *)pp;
>>> +	if (ntohs(ct->ct_cmd) == FC_FS_ACC)
>>> +		job->reply->reply_data.ctels_reply.status
>>> +			= FC_CTELS_STATUS_OK;
>>>
>> Split this lines like this after the =.
>>> +	else
>>> +		job->reply->reply_data.ctels_reply.status
>>> +			= FC_CTELS_STATUS_REJECT;
>>> +err:
>>> +	fc_frame_free(fp);
>>> +	mutex_unlock(&lport->lp_mutex);
>>> +	kfree(info);
>>> +	job->state_flags = FC_RQST_STATE_DONE;
>>> +	job->job_done(job);
>>> +}
>>> +
>>> +static int fcoe_bsg_ct_request(struct fc_bsg_job *job)
>>> +{
>>> +	struct fcoe_bsg_info *info;
>>> +	struct fc_rport *rport = job->rport;
>>> +	struct Scsi_Host *shost;
>>> +	struct fc_lport *lport;
>>> +	struct fc_frame *fp;
>>> +	struct fc_frame_header *fh;
>>> +	struct fc_ct_req *ct;
>>> +	struct fc_ct_hdr *ct_hdr;
>>> +	size_t len;
>>> +	u32 did;
>>> +
>>> +	shost = rport ? rport_to_shost(rport) : job->shost;
>>> +	lport = shost_priv(shost);
>>> +
>>> +	if (!((lport->state == LPORT_ST_READY) &&
>>> +	    lport->link_up && !lport->qfull))
>>> +		return -EINVAL;
>>> +
>>> +	fp = fc_frame_alloc(lport, sizeof(struct fc_ct_hdr) +
>>> +				job->request_payload.payload_len);
>>> +	if (!fp)
>>> +		return -EINVAL;
>>> +
>>> +	len = job->request_payload.payload_len;
>>> +	ct = fc_frame_payload_get(fp, len);
>>> +	memset(ct, 0, len);
>>> +
>>> +	sg_copy_to_buffer(job->request_payload.sg_list,
>>> +			  job->request_payload.sg_cnt,
>>> +			  ct, len);
>>> +	ct_hdr = &ct->hdr;
>>> +	ct_hdr->ct_cmd = htons((u16)ct_hdr->ct_cmd);
>>> +	ct_hdr->ct_mr_size = htons((u16)ct_hdr->ct_mr_size);
>>> +	did = ct->hdr.ct_in_id[0]<<16 |
>>> +	      ct->hdr.ct_in_id[1]<<8  |
>>> +	      ct->hdr.ct_in_id[2];
>>> +
>>> +	fh = fc_frame_header_get(fp);
>>> +	fh->fh_r_ctl = FC_RCTL_DD_UNSOL_CTL;
>>> +	hton24(fh->fh_d_id, did);
>>> +	hton24(fh->fh_s_id, fc_host_port_id(shost));
>>> +	fh->fh_type = FC_TYPE_CT;
>>> +	hton24(fh->fh_f_ctl, FC_FC_FIRST_SEQ |
>>> +		FC_FC_END_SEQ | FC_FC_SEQ_INIT);
>>> +	fh->fh_cs_ctl = 0;
>>> +	fh->fh_df_ctl = 0;
>>> +	fh->fh_parm_offset = 0;
>>> +
>>> +	info = kzalloc(sizeof(struct fcoe_bsg_info), GFP_KERNEL);
>>> +	if (!info) {
>>> +		fc_frame_free(fp);
>>> +		return -EINVAL;
>>> +	}
>>> +
>>> +	info->job = job;
>>> +	info->lport = lport;
>>> +
>>> +	lport->tt.exch_seq_send(lport, fp, fc_bsg_ct_resp,
>>> +				NULL, (void *)info, lport->e_d_tov);
>>> +	return 0;
>>> +}
>>> +
>>> +int fcoe_bsg_request(struct fc_bsg_job *job)
>>> +{
>>> +	switch (job->request->msgcode) {
>>> +	case FC_BSG_RPT_ELS:
>>> +	case FC_BSG_HST_ELS_NOLOGIN:
>>> +		return fcoe_bsg_els_request(job);
>>> +	case FC_BSG_RPT_CT:
>>> +		return fcoe_bsg_ct_request(job);
>>> +	default:
>>> +		return -EINVAL;
>>> +	}
>>> +}
>>> +EXPORT_SYMBOL(fcoe_bsg_request);
>>> +
>>> diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h
>>> index a70eafa..221dff0 100644
>>> --- a/include/scsi/libfc.h
>>> +++ b/include/scsi/libfc.h
>>> @@ -25,6 +25,7 @@
>>>
>>>  #include <scsi/scsi_transport.h>
>>>  #include <scsi/scsi_transport_fc.h>
>>> +#include <scsi/scsi_bsg_fc.h>
>>>
>>>  #include <scsi/fc/fc_fcp.h>
>>>  #include <scsi/fc/fc_ns.h>
>>> @@ -778,6 +779,7 @@ int fc_set_mfs(struct fc_lport *lp, u32 mfs);
>>>   *****************************/
>>>  int fc_rport_init(struct fc_lport *lp);
>>>  void fc_rport_terminate_io(struct fc_rport *rp);
>>> +int fcoe_bsg_request(struct fc_bsg_job *job);
>>>
>>>  /*
>>>   * DISCOVERY LAYER
>>>
>>> _______________________________________________
>>> devel mailing list
>>> devel at open-fcoe.org
>>> http://www.open-fcoe.org/mailman/listinfo/devel
>>>
> 




More information about the devel mailing list