iPXE
Data Structures | Defines | Enumerations | Functions
fcels.h File Reference

Fibre Channel Extended Link Services. More...

#include <stdint.h>
#include <ipxe/fc.h>
#include <ipxe/tables.h>
#include <ipxe/refcnt.h>
#include <ipxe/list.h>
#include <ipxe/process.h>
#include <ipxe/interface.h>

Go to the source code of this file.

Data Structures

struct  fc_els_frame_common
 Fibre Channel ELS frame common parameters. More...
struct  fc_ls_rjt_frame
 A Fibre Channel LS_RJT frame. More...
struct  fc_login_common
 Fibre Channel "common" service parameters. More...
struct  fc_login_class
 Fibre Channel class-specific login parameters. More...
struct  fc_login_frame
 A Fibre Channel FLOGI/PLOGI frame. More...
struct  fc_logout_request_frame
 A Fibre Channel LOGO request frame. More...
struct  fc_logout_response_frame
 A Fibre Channel LOGO response frame. More...
struct  fc_prli_page
 A Fibre Channel PRLI service parameter page. More...
struct  fc_prli_frame
 A Fibre Channel PRLI frame. More...
struct  fc_rtv_request_frame
 A Fibre Channel RTV request frame. More...
struct  fc_rtv_response_frame
 A Fibre Channel RTV response frame. More...
struct  fc_echo_frame_header
 A Fibre Channel ECHO frame. More...
struct  fc_els
 A Fibre Channel extended link services transaction. More...
struct  fc_els_handler
 A Fibre Channel extended link services handler. More...
struct  fc_els_prli_descriptor
 A Fibre Channel ELS PRLI descriptor. More...

Defines

#define FC_LOGIN_VERSION   0x2020
 Fibre Channel default login version.
#define FC_LOGIN_DEFAULT_B2B   10
 Fibre Channel default buffer-to-buffer credit.
#define FC_LOGIN_CONTINUOUS_OFFSET   0x8000
 Continuously increasing relative offset.
#define FC_LOGIN_CLEAN   0x8000
 Clean address.
#define FC_LOGIN_MULTI_N   0x8000
 Multiple N_Port_ID support.
#define FC_LOGIN_RANDOM_OFFSET   0x4000
 Random relative offset.
#define FC_LOGIN_VIRTUAL   0x4000
 Virtual fabrics.
#define FC_LOGIN_VENDOR   0x2000
 Vendor version level.
#define FC_LOGIN_MULTI_F   0x2000
 Multiple N_Port_ID support.
#define FC_LOGIN_F_PORT   0x1000
 Forwarder port.
#define FC_LOGIN_ALT_CREDIT   0x0800
 Alternative credit management.
#define FC_LOGIN_NSS_STARTED   0x0800
 Name server session started.
#define FC_LOGIN_NSS_BEGIN   0x0400
 Begin name server session.
#define FC_LOGIN_HIRES_E_D_TOV   0x0400
 1ns error detection timer resolution
#define FC_LOGIN_BROADCAST   0x0100
 Broadcast supported.
#define FC_LOGIN_QUERY_BUF   0x0040
 Query buffer conditions.
#define FC_LOGIN_SECURITY   0x0020
 Security.
#define FC_LOGIN_CLOCK_SYNC   0x0010
 Clock sync primitive capable.
#define FC_LOGIN_SHORT_R_T_TOV   0x0008
 Short R_T timeout.
#define FC_LOGIN_DHD   0x0004
 Dynamic half duplex.
#define FC_LOGIN_CONTINUOUS_SEQ   0x0002
 Continuously increasing sequence count.
#define FC_LOGIN_PAYLOAD   0x0001
 Payload.
#define FC_LOGIN_DEFAULT_MTU   1452
 Fibre Channel default MTU.
#define FC_LOGIN_DEFAULT_MAX_SEQ   255
 Default maximum number of concurrent sequences.
#define FC_LOGIN_DEFAULT_REL_OFFS   0x1f
 Default relative offset by info category.
#define FC_LOGIN_DEFAULT_E_D_TOV   2000
 Default E_D timeout value.
#define FC_LOGIN_CLASS_VALID   0x8000
 Class valid.
#define FC_LOGIN_CLASS_SEQUENTIAL   0x0800
 Sequential delivery requested.
#define FC_PRLI_ESTABLISH   0x2000
 Establish image pair.
#define FC_PRLI_RESPONSE_MASK   0x0f00
 Response code mask.
#define FC_PRLI_RESPONSE_SUCCESS   0x0100
 Request was executed successfully.
#define FC_RTV_HIRES_E_D_TOV   0x0400
 1ns error detection timer resolution
#define FC_RTV_SHORT_R_T_TOV   0x0008
 Short R_T timeout.
#define FC_ELS_HANDLERS   __table ( struct fc_els_handler, "fc_els_handlers" )
 Fibre Channel ELS handler table.
#define __fc_els_handler   __table_entry ( FC_ELS_HANDLERS, 01 )
 Declare a Fibre Channel ELS handler.
#define FC_ELS_PRLI_DESCRIPTORS   __table ( struct fc_els_prli_descriptor, "fc_els_prli_descriptors" )
 Fibre Channel ELS PRLI descriptor table.
#define __fc_els_prli_descriptor   __table_entry ( FC_ELS_PRLI_DESCRIPTORS, 01 )
 Declare a Fibre Channel ELS PRLI descriptor.

Enumerations

enum  fc_els_command_code {
  FC_ELS_LS_RJT = 0x01, FC_ELS_LS_ACC = 0x02, FC_ELS_PLOGI = 0x03, FC_ELS_FLOGI = 0x04,
  FC_ELS_LOGO = 0x05, FC_ELS_RTV = 0x0e, FC_ELS_ECHO = 0x10, FC_ELS_PRLI = 0x20,
  FC_ELS_PRLO = 0x21
}
 Fibre Channel ELS command codes. More...
enum  fc_els_reject_reason {
  FC_ELS_RJT_INVALID_COMMAND = 0x01, FC_ELS_RJT_ILLOGICAL = 0x03, FC_ELS_RJT_BUSY = 0x05, FC_ELS_RJT_PROTOCOL = 0x07,
  FC_ELS_RJT_UNABLE = 0x09, FC_ELS_RJT_UNSUPPORTED = 0x0b, FC_ELS_RJT_IN_PROGRESS = 0x0e
}
 Fibre Channel ELS rejection reason codes. More...
enum  fc_els_flags { FC_ELS_REQUEST = 0x0001 }
 Fibre Channel extended link services transaction flags. More...

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
static int fc_els_is_request (struct fc_els *els)
 Check if Fibre Channel ELS transaction is a request.
static unsigned int fc_els_tx_command (struct fc_els *els, unsigned int request_command)
 Calculate ELS command to transmit.
int fc_els_tx (struct fc_els *els, const void *data, size_t len)
 Transmit Fibre Channel ELS frame.
int fc_els_request (struct interface *job, struct fc_port *port, struct fc_port_id *peer_port_id, struct fc_els_handler *handler)
 Create ELS request.
int fc_els_flogi (struct interface *parent, struct fc_port *port)
 Create FLOGI request.
int fc_els_plogi (struct interface *parent, struct fc_port *port, struct fc_port_id *peer_port_id)
 Create PLOGI request.
int fc_els_logo (struct interface *parent, struct fc_port *port, struct fc_port_id *peer_port_id)
 Create LOGO request.
int fc_els_prli (struct interface *parent, struct fc_port *port, struct fc_port_id *peer_port_id, unsigned int type)
 Create PRLI request.
int fc_els_prli_tx (struct fc_els *els, struct fc_els_prli_descriptor *descriptor, void *param)
 Transmit PRLI.
int fc_els_prli_rx (struct fc_els *els, struct fc_els_prli_descriptor *descriptor, void *data, size_t len)
 Receive PRLI.
int fc_els_prli_detect (struct fc_els *els __unused, struct fc_els_prli_descriptor *descriptor, const void *data, size_t len)
 Detect PRLI.

Detailed Description

Fibre Channel Extended Link Services.

Definition in file fcels.h.


Define Documentation

#define FC_LOGIN_VERSION   0x2020

Fibre Channel default login version.

Definition at line 102 of file fcels.h.

Referenced by fc_els_flogi_tx(), and fc_els_plogi_tx().

#define FC_LOGIN_DEFAULT_B2B   10

Fibre Channel default buffer-to-buffer credit.

Definition at line 105 of file fcels.h.

Referenced by fc_els_flogi_tx(), and fc_els_plogi_tx().

#define FC_LOGIN_CONTINUOUS_OFFSET   0x8000

Continuously increasing relative offset.

Definition at line 108 of file fcels.h.

Referenced by fc_els_flogi_tx(), and fc_els_plogi_tx().

#define FC_LOGIN_CLEAN   0x8000

Clean address.

Definition at line 111 of file fcels.h.

#define FC_LOGIN_MULTI_N   0x8000

Multiple N_Port_ID support.

Definition at line 114 of file fcels.h.

#define FC_LOGIN_RANDOM_OFFSET   0x4000

Random relative offset.

Definition at line 117 of file fcels.h.

#define FC_LOGIN_VIRTUAL   0x4000

Virtual fabrics.

Definition at line 120 of file fcels.h.

#define FC_LOGIN_VENDOR   0x2000

Vendor version level.

Definition at line 123 of file fcels.h.

#define FC_LOGIN_MULTI_F   0x2000

Multiple N_Port_ID support.

Definition at line 126 of file fcels.h.

#define FC_LOGIN_F_PORT   0x1000

Forwarder port.

Definition at line 129 of file fcels.h.

Referenced by fc_els_flogi_rx().

#define FC_LOGIN_ALT_CREDIT   0x0800

Alternative credit management.

Definition at line 132 of file fcels.h.

#define FC_LOGIN_NSS_STARTED   0x0800

Name server session started.

Definition at line 135 of file fcels.h.

#define FC_LOGIN_NSS_BEGIN   0x0400

Begin name server session.

Definition at line 138 of file fcels.h.

#define FC_LOGIN_HIRES_E_D_TOV   0x0400

1ns error detection timer resolution

Definition at line 141 of file fcels.h.

#define FC_LOGIN_BROADCAST   0x0100

Broadcast supported.

Definition at line 144 of file fcels.h.

#define FC_LOGIN_QUERY_BUF   0x0040

Query buffer conditions.

Definition at line 147 of file fcels.h.

#define FC_LOGIN_SECURITY   0x0020

Security.

Definition at line 150 of file fcels.h.

#define FC_LOGIN_CLOCK_SYNC   0x0010

Clock sync primitive capable.

Definition at line 153 of file fcels.h.

#define FC_LOGIN_SHORT_R_T_TOV   0x0008

Short R_T timeout.

Definition at line 156 of file fcels.h.

#define FC_LOGIN_DHD   0x0004

Dynamic half duplex.

Definition at line 159 of file fcels.h.

#define FC_LOGIN_CONTINUOUS_SEQ   0x0002

Continuously increasing sequence count.

Definition at line 162 of file fcels.h.

#define FC_LOGIN_PAYLOAD   0x0001

Payload.

Definition at line 165 of file fcels.h.

#define FC_LOGIN_DEFAULT_MTU   1452

Fibre Channel default MTU.

Definition at line 168 of file fcels.h.

Referenced by fc_els_flogi_tx(), fc_els_plogi_tx(), and fc_xchg_window().

#define FC_LOGIN_DEFAULT_MAX_SEQ   255

Default maximum number of concurrent sequences.

Definition at line 171 of file fcels.h.

Referenced by fc_els_plogi_tx().

#define FC_LOGIN_DEFAULT_REL_OFFS   0x1f

Default relative offset by info category.

Definition at line 174 of file fcels.h.

Referenced by fc_els_plogi_tx().

#define FC_LOGIN_DEFAULT_E_D_TOV   2000

Default E_D timeout value.

Definition at line 177 of file fcels.h.

Referenced by fc_els_plogi_tx(), and fc_els_rtv_tx_response().

#define FC_LOGIN_CLASS_VALID   0x8000

Class valid.

Definition at line 202 of file fcels.h.

Referenced by fc_els_flogi_tx(), and fc_els_plogi_tx().

#define FC_LOGIN_CLASS_SEQUENTIAL   0x0800

Sequential delivery requested.

Definition at line 205 of file fcels.h.

Referenced by fc_els_flogi_tx(), and fc_els_plogi_tx().

#define FC_PRLI_ESTABLISH   0x2000

Establish image pair.

Definition at line 264 of file fcels.h.

Referenced by fc_els_prli_rx(), and fc_els_prli_tx().

#define FC_PRLI_RESPONSE_MASK   0x0f00

Response code mask.

Definition at line 267 of file fcels.h.

#define FC_PRLI_RESPONSE_SUCCESS   0x0100

Request was executed successfully.

Definition at line 270 of file fcels.h.

Referenced by fc_els_prli_tx().

#define FC_RTV_HIRES_E_D_TOV   0x0400

1ns error detection timer resolution

Definition at line 309 of file fcels.h.

#define FC_RTV_SHORT_R_T_TOV   0x0008

Short R_T timeout.

Definition at line 312 of file fcels.h.

#define FC_ELS_HANDLERS   __table ( struct fc_els_handler, "fc_els_handlers" )

Fibre Channel ELS handler table.

Definition at line 380 of file fcels.h.

Referenced by fc_els_detect(), and parse_fc_els_handler().

struct fc_els_handler fc_els_echo_handler __fc_els_handler   __table_entry ( FC_ELS_HANDLERS, 01 )

Declare a Fibre Channel ELS handler.

ECHO ELS handler.

RTV ELS handler.

LOGO ELS handler.

PLOGI ELS handler.

FLOGI ELS handler.

Unknown ELS handler.

Definition at line 383 of file fcels.h.

#define FC_ELS_PRLI_DESCRIPTORS   __table ( struct fc_els_prli_descriptor, "fc_els_prli_descriptors" )

Fibre Channel ELS PRLI descriptor table.

Definition at line 396 of file fcels.h.

Referenced by fc_els_prli_descriptor().

Declare a Fibre Channel ELS PRLI descriptor.

FCP PRLI descriptor.

Definition at line 400 of file fcels.h.


Enumeration Type Documentation

Fibre Channel ELS command codes.

Enumerator:
FC_ELS_LS_RJT 

Link Service Reject.

FC_ELS_LS_ACC 

Link Service Accept.

FC_ELS_PLOGI 

Port Login.

FC_ELS_FLOGI 

Fabric Login.

FC_ELS_LOGO 

Logout.

FC_ELS_RTV 

Read Timeout Value.

FC_ELS_ECHO 

Echo.

FC_ELS_PRLI 

Process Login.

FC_ELS_PRLO 

Process Logout.

Definition at line 30 of file fcels.h.

                         {
        FC_ELS_LS_RJT = 0x01,           /**< Link Service Reject */
        FC_ELS_LS_ACC = 0x02,           /**< Link Service Accept */
        FC_ELS_PLOGI = 0x03,            /**< Port Login */
        FC_ELS_FLOGI = 0x04,            /**< Fabric Login */
        FC_ELS_LOGO = 0x05,             /**< Logout */
        FC_ELS_RTV = 0x0e,              /**< Read Timeout Value */
        FC_ELS_ECHO = 0x10,             /**< Echo */
        FC_ELS_PRLI = 0x20,             /**< Process Login */
        FC_ELS_PRLO = 0x21,             /**< Process Logout */
};

Fibre Channel ELS rejection reason codes.

Enumerator:
FC_ELS_RJT_INVALID_COMMAND 

Invalid ELS command code.

FC_ELS_RJT_ILLOGICAL 

Logical error.

FC_ELS_RJT_BUSY 

Logical busy.

FC_ELS_RJT_PROTOCOL 

Protocol error.

FC_ELS_RJT_UNABLE 

Unable to perform command request.

FC_ELS_RJT_UNSUPPORTED 

Command not supported.

FC_ELS_RJT_IN_PROGRESS 

Command already in progress.

Definition at line 57 of file fcels.h.

                          {
        /** Invalid ELS command code */
        FC_ELS_RJT_INVALID_COMMAND = 0x01,
        /** Logical error */
        FC_ELS_RJT_ILLOGICAL = 0x03,
        /** Logical busy */
        FC_ELS_RJT_BUSY = 0x05,
        /** Protocol error */
        FC_ELS_RJT_PROTOCOL = 0x07,
        /** Unable to perform command request */
        FC_ELS_RJT_UNABLE = 0x09,
        /** Command not supported */
        FC_ELS_RJT_UNSUPPORTED = 0x0b,
        /** Command already in progress */
        FC_ELS_RJT_IN_PROGRESS = 0x0e,
};

Fibre Channel extended link services transaction flags.

Enumerator:
FC_ELS_REQUEST 

ELS transaction is a request.

Definition at line 346 of file fcels.h.

                  {
        /** ELS transaction is a request */
        FC_ELS_REQUEST = 0x0001,
};

Function Documentation

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL  )
static int fc_els_is_request ( struct fc_els els) [inline, static]

Check if Fibre Channel ELS transaction is a request.

Parameters:
elsFibre Channel ELS transaction
Return values:
is_requestELS transaction is a request

Definition at line 408 of file fcels.h.

References FC_ELS_REQUEST, and fc_els::flags.

Referenced by fc_els_echo_rx(), fc_els_flogi_rx(), fc_els_logo_rx(), fc_els_plogi_rx(), fc_els_prli_rx(), fc_els_prli_tx(), fc_els_rtv_rx(), fc_els_rx(), fc_els_step(), fc_els_tx(), fc_els_tx_command(), and fc_els_unknown_rx().

                                                           {
        return ( els->flags & FC_ELS_REQUEST );
}
static unsigned int fc_els_tx_command ( struct fc_els els,
unsigned int  request_command 
) [inline, static]

Calculate ELS command to transmit.

Parameters:
elsFibre Channel ELS transaction
request_commandCommand for requests
commandCommand to transmit

Definition at line 419 of file fcels.h.

References fc_els_is_request(), and FC_ELS_LS_ACC.

Referenced by fc_els_flogi_tx(), fc_els_plogi_tx(), and fc_els_prli_tx().

                                                                              {
        return ( fc_els_is_request ( els ) ? request_command : FC_ELS_LS_ACC );
}
int fc_els_tx ( struct fc_els els,
const void *  data,
size_t  len 
)

Transmit Fibre Channel ELS frame.

Parameters:
elsFibre Channel ELS transaction
dataData to transmit
lenLength of data
Return values:
rcReturn status code

Definition at line 126 of file fcels.c.

References DBGC, DBGC2, DBGC2_HDA, xfer_metadata::dest, fc_els_is_request(), fc_fill_sockaddr(), FCELS_ARGS, FCELS_FMT, xfer_metadata::flags, memset(), fc_els::peer_port_id, rc, strerror(), fc_els::xchg, xfer_deliver_raw_meta(), XFER_FL_OUT, XFER_FL_OVER, and XFER_FL_RESPONSE.

Referenced by fc_els_echo_rx_request(), fc_els_echo_tx(), fc_els_flogi_tx(), fc_els_logo_tx(), fc_els_logo_tx_response(), fc_els_plogi_tx(), fc_els_prli_tx(), fc_els_rtv_tx_response(), and fc_els_unknown_tx_response().

                                                                   {
        struct xfer_metadata meta;
        struct sockaddr_fc dest;
        int rc;

        DBGC2 ( els, FCELS_FMT " transmitting:\n", FCELS_ARGS ( els ) );
        DBGC2_HDA ( els, 0, data, len );

        /* Construct metadata */
        memset ( &meta, 0, sizeof ( meta ) );
        meta.flags = ( fc_els_is_request ( els ) ?
                       XFER_FL_OVER : ( XFER_FL_RESPONSE | XFER_FL_OUT ) );
        meta.dest = fc_fill_sockaddr ( &dest, &els->peer_port_id );

        /* Transmit frame */
        if ( ( rc = xfer_deliver_raw_meta ( &els->xchg, data, len,
                                            &meta ) ) != 0 ) {
                DBGC ( els, FCELS_FMT " could not deliver frame: %s\n",
                       FCELS_ARGS ( els ), strerror ( rc ) );
                return rc;
        }

        return 0;
}
int fc_els_request ( struct interface job,
struct fc_port port,
struct fc_port_id peer_port_id,
struct fc_els_handler handler 
)

Create ELS request.

Parameters:
jobParent job-control interface
portFibre Channel port
peer_port_idPeer port ID
handlerELS handler
Return values:
rcReturn status code

Definition at line 323 of file fcels.c.

References ENOMEM, fc_els_create(), FC_ELS_REQUEST, fc_els::flags, fc_els::handler, intf_plug_plug(), fc_els::job, fc_port::port_id, fc_els::process, process_add(), ref_put, and fc_els::refcnt.

Referenced by fc_els_flogi(), fc_els_logo(), fc_els_plogi(), fc_els_prli(), and fcels().

                                                      {
        struct fc_els *els;

        /* Allocate and initialise structure */
        els = fc_els_create ( port, &port->port_id, peer_port_id );
        if ( ! els )
                return -ENOMEM;
        els->handler = handler;
        els->flags = FC_ELS_REQUEST;
        process_add ( &els->process );

        /* Attach to parent job interface, mortalise self, and return */
        intf_plug_plug ( &els->job, job );
        ref_put ( &els->refcnt );
        return 0;
}
int fc_els_flogi ( struct interface parent,
struct fc_port port 
)

Create FLOGI request.

Parameters:
parentParent interface
portFibre Channel port
Return values:
rcReturn status code

Definition at line 581 of file fcels.c.

References fc_els_request(), and fc_f_port_id.

Referenced by fc_port_examine().

                                                                    {

        return fc_els_request ( parent, port, &fc_f_port_id,
                                &fc_els_flogi_handler );
}
int fc_els_plogi ( struct interface parent,
struct fc_port port,
struct fc_port_id peer_port_id 
)

Create PLOGI request.

Parameters:
parentParent interface
portFibre Channel port
peer_port_idPeer port ID
Return values:
rcReturn status code

Definition at line 733 of file fcels.c.

References fc_els_request().

Referenced by fc_peer_plogi(), and fc_port_login().

                                                     {

        return fc_els_request ( parent, port, peer_port_id,
                                &fc_els_plogi_handler );
}
int fc_els_logo ( struct interface parent,
struct fc_port port,
struct fc_port_id peer_port_id 
)

Create LOGO request.

Parameters:
parentParent interface
portFibre Channel port
peer_port_idPeer port ID
Return values:
rcReturn status code

Definition at line 911 of file fcels.c.

References fc_els_request().

                                                    {

        return fc_els_request ( parent, port, peer_port_id,
                                &fc_els_logo_handler );
}
int fc_els_prli ( struct interface parent,
struct fc_port port,
struct fc_port_id peer_port_id,
unsigned int  type 
)

Create PRLI request.

Parameters:
parentParent interface
portFibre Channel port
peer_port_idPeer port ID
typeUpper-layer protocol type
Return values:
rcReturn status code

Definition at line 1124 of file fcels.c.

References ENOTSUP, fc_els_prli_descriptor(), fc_els_request(), and fc_els_prli_descriptor::handler.

Referenced by fc_ulp_examine().

                                                                       {
        struct fc_els_prli_descriptor *descriptor;

        /* Find a PRLI descriptor */
        descriptor = fc_els_prli_descriptor ( type );
        if ( ! descriptor )
                return -ENOTSUP;

        return fc_els_request ( parent, port, peer_port_id,
                                descriptor->handler );
}
int fc_els_prli_tx ( struct fc_els els,
struct fc_els_prli_descriptor descriptor,
void *  param 
)

Transmit PRLI.

Parameters:
elsFibre Channel ELS transaction
descriptorELS PRLI descriptor
paramService parameters
Return values:
rcReturn status code

Definition at line 950 of file fcels.c.

References __attribute__, ENOMEM, fc_els_is_request(), FC_ELS_PRLI, fc_els_tx(), fc_els_tx_command(), fc_link_ok(), FC_PRLI_ESTABLISH, FC_PRLI_RESPONSE_SUCCESS, fc_ulp_get_port_id_type(), fc_ulp_put(), htons, fc_ulp::link, memcpy(), memset(), fc_els_prli_descriptor::param_len, fc_els::peer_port_id, fc_els::port, fc_ulp::prli, rc, and fc_els_prli_descriptor::type.

Referenced by fcp_prli_tx().

                                                                              {
        struct {
                struct fc_prli_frame frame;
                uint8_t param[descriptor->param_len];
        } __attribute__ (( packed )) prli;
        struct fc_ulp *ulp;
        int rc;

        /* Get ULP */
        ulp = fc_ulp_get_port_id_type ( els->port, &els->peer_port_id,
                                        descriptor->type );
        if ( ! ulp ) {
                rc = -ENOMEM;
                goto err_get_port_id_type;
        }

        /* Build frame for transmission */
        memset ( &prli, 0, sizeof ( prli ) );
        prli.frame.command = fc_els_tx_command ( els, FC_ELS_PRLI );
        prli.frame.page_len =
                ( sizeof ( prli.frame.page ) + sizeof ( prli.param ) );
        prli.frame.len = htons ( sizeof ( prli ) );
        prli.frame.page.type = descriptor->type;
        if ( fc_els_is_request ( els ) ) {
                prli.frame.page.flags |= htons ( FC_PRLI_ESTABLISH );
        } else if ( fc_link_ok ( &ulp->link ) ) {
                prli.frame.page.flags |= htons ( FC_PRLI_ESTABLISH |
                                                    FC_PRLI_RESPONSE_SUCCESS );
        }
        memcpy ( &prli.param, param, sizeof ( prli.param ) );

        /* Transmit frame */
        if ( ( rc = fc_els_tx ( els, &prli, sizeof ( prli ) ) ) != 0 )
                goto err_tx;

        /* Drop temporary reference to ULP */
        fc_ulp_put ( ulp );

        return 0;

 err_tx:
        fc_ulp_put ( ulp );
 err_get_port_id_type:
        return rc;
}
int fc_els_prli_rx ( struct fc_els els,
struct fc_els_prli_descriptor descriptor,
void *  data,
size_t  len 
)

Receive PRLI.

Parameters:
elsFibre Channel ELS transaction
descriptorELS PRLI descriptor
frameELS frame
lenLength of ELS frame
Return values:
rcReturn status code

Definition at line 1006 of file fcels.c.

References __attribute__, data, DBGC, DBGC_HDA, EACCES, EINVAL, ENOMEM, fc_els_is_request(), fc_link_ok(), FC_PRLI_ESTABLISH, fc_ulp_get_port_id_type(), fc_ulp_login(), fc_ulp_logout(), fc_ulp_put(), FCELS_ARGS, FCELS_FMT, fc_els::handler, htons, fc_peer::link, fc_ulp::param, fc_els_prli_descriptor::param_len, fc_ulp::peer, fc_els::peer_port_id, fc_els::port, fc_ulp::prli, rc, strerror(), fc_els_handler::tx, and fc_els_prli_descriptor::type.

Referenced by fcp_prli_rx().

                                              {
        struct {
                struct fc_prli_frame frame;
                uint8_t param[descriptor->param_len];
        } __attribute__ (( packed )) *prli = data;
        struct fc_ulp *ulp;
        int rc;

        /* Sanity check */
        if ( len < sizeof ( *prli ) ) {
                DBGC ( els, FCELS_FMT " received underlength frame:\n",
                       FCELS_ARGS ( els ) );
                DBGC_HDA ( els, 0, data, len );
                rc = -EINVAL;
                goto err_sanity;
        }

        DBGC ( els, FCELS_FMT " has parameters:\n", FCELS_ARGS ( els ) );
        DBGC_HDA ( els, 0, prli->param, sizeof ( prli->param ) );

        /* Get ULP */
        ulp = fc_ulp_get_port_id_type ( els->port, &els->peer_port_id,
                                        descriptor->type );
        if ( ! ulp ) {
                rc = -ENOMEM;
                goto err_get_port_id_type;
        }

        /* Sanity check */
        if ( ! fc_link_ok ( &ulp->peer->link ) ) {
                DBGC ( els, FCELS_FMT " received while peer link is down\n",
                       FCELS_ARGS ( els ) );
                rc = -EINVAL;
                goto err_link;
        }

        /* Log in ULP, if applicable */
        if ( prli->frame.page.flags & htons ( FC_PRLI_ESTABLISH ) ) {
                if ( ( rc = fc_ulp_login ( ulp, prli->param,
                                           sizeof ( prli->param ),
                                           fc_els_is_request ( els ) ) ) != 0 ){
                        DBGC ( els, FCELS_FMT " could not log in ULP: %s\n",
                               FCELS_ARGS ( els ), strerror ( rc ) );
                        goto err_login;
                }
        } else {
                if ( fc_els_is_request ( els ) ) {
                        fc_ulp_logout ( ulp, -EACCES );
                } else {
                        /* This is just an information-gathering PRLI; do not
                         * log in or out
                         */
                }
        }

        /* Transmit response, if applicable */
        if ( ! fc_els_is_request ( els ) ) {
                if ( ( rc = els->handler->tx ( els ) ) != 0 )
                        goto err_tx;
        }

        /* Drop temporary reference to ULP */
        fc_ulp_put ( ulp );

        return 0;

 err_tx:
 err_login:
 err_link:
        fc_ulp_put ( ulp );
 err_get_port_id_type:
 err_sanity:
        return rc;
}
int fc_els_prli_detect ( struct fc_els *els  __unused,
struct fc_els_prli_descriptor descriptor,
const void *  data,
size_t  len 
)

Detect PRLI.

Parameters:
elsFibre Channel ELS transaction
descriptorELS PRLI descriptor
dataELS frame
lenLength of ELS frame
Return values:
rcReturn status code

Definition at line 1092 of file fcels.c.

References __attribute__, data, EINVAL, FC_ELS_PRLI, fc_ulp::param, fc_els_prli_descriptor::param_len, and fc_els_prli_descriptor::type.

Referenced by fcp_prli_detect().

                                                        {
        const struct {
                struct fc_prli_frame frame;
                uint8_t param[descriptor->param_len];
        } __attribute__ (( packed )) *prli = data;

        /* Check for PRLI */
        if ( prli->frame.command != FC_ELS_PRLI )
                return -EINVAL;

        /* Check for sufficient length to contain service parameter page */
        if ( len < sizeof ( *prli ) )
                return -EINVAL;

        /* Check for upper-layer protocol type */
        if ( prli->frame.page.type != descriptor->type )
                return -EINVAL;

        return 0;
}