iPXE
Data Structures | Defines | Functions | Variables
fcels.c File Reference

Fibre Channel Extended Link Services. More...

#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
#include <byteswap.h>
#include <ipxe/interface.h>
#include <ipxe/xfer.h>
#include <ipxe/iobuf.h>
#include <ipxe/process.h>
#include <ipxe/fc.h>
#include <ipxe/fcels.h>

Go to the source code of this file.

Data Structures

struct  fc_echo_request_frame
 ECHO request data. More...

Defines

#define FCELS_FMT   "FCELS %s %s %s %s"
 Fibre Channel ELS transaction debug message format.
#define FCELS_ARGS(els)
 Fibre Channel ELS transaction debug message arguments.
#define FC_ECHO_MAGIC   0x69505845
 ECHO magic marker.

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
static void fc_els_free (struct refcnt *refcnt)
 Free Fibre Channel ELS transaction.
static void fc_els_close (struct fc_els *els, int rc)
 Close Fibre Channel ELS transaction.
static struct fc_els_handlerfc_els_detect (struct fc_els *els, const void *data, size_t len)
 Detect Fibre Channel ELS frame handler.
int fc_els_tx (struct fc_els *els, const void *data, size_t len)
 Transmit Fibre Channel ELS frame.
static int fc_els_rx (struct fc_els *els, struct io_buffer *iobuf, struct xfer_metadata *meta)
 Receive Fibre Channel ELS frame.
static void fc_els_step (struct fc_els *els)
 Fibre Channel ELS process.
static struct fc_elsfc_els_create (struct fc_port *port, struct fc_port_id *port_id, struct fc_port_id *peer_port_id)
 Create ELS transaction.
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.
static int fc_els_respond (struct interface *xchg, struct fc_port *port, struct fc_port_id *port_id, struct fc_port_id *peer_port_id)
 Create ELS response.
static int fc_els_unknown_tx (struct fc_els *els __unused)
 Transmit unknown ELS request.
static int fc_els_unknown_tx_response (struct fc_els *els)
 Transmit unknown ELS response.
static int fc_els_unknown_rx (struct fc_els *els, void *data, size_t len)
 Receive unknown ELS.
static int fc_els_unknown_detect (struct fc_els *els __unused, const void *data __unused, size_t len __unused)
 Detect unknown ELS.
static int fc_els_flogi_tx (struct fc_els *els)
 Transmit FLOGI.
static int fc_els_flogi_rx (struct fc_els *els, void *data, size_t len)
 Receive FLOGI.
static int fc_els_flogi_detect (struct fc_els *els __unused, const void *data, size_t len __unused)
 Detect FLOGI.
int fc_els_flogi (struct interface *parent, struct fc_port *port)
 Create FLOGI request.
static int fc_els_plogi_tx (struct fc_els *els)
 Transmit PLOGI.
static int fc_els_plogi_rx (struct fc_els *els, void *data, size_t len)
 Receive PLOGI.
static int fc_els_plogi_detect (struct fc_els *els __unused, const void *data, size_t len __unused)
 Detect PLOGI.
int fc_els_plogi (struct interface *parent, struct fc_port *port, struct fc_port_id *peer_port_id)
 Create PLOGI request.
static int fc_els_logo_tx (struct fc_els *els)
 Transmit LOGO request.
static int fc_els_logo_tx_response (struct fc_els *els)
 Transmit LOGO response.
static void fc_els_logo_logout (struct fc_els *els, struct fc_port_id *peer_port_id)
 Log out individual peer or whole port as applicable.
static int fc_els_logo_rx_request (struct fc_els *els, void *data, size_t len)
 Receive LOGO request.
static int fc_els_logo_rx_response (struct fc_els *els, void *data __unused, size_t len __unused)
 Receive LOGO response.
static int fc_els_logo_rx (struct fc_els *els, void *data, size_t len)
 Receive LOGO.
static int fc_els_logo_detect (struct fc_els *els __unused, const void *data, size_t len __unused)
 Detect LOGO.
int fc_els_logo (struct interface *parent, struct fc_port *port, struct fc_port_id *peer_port_id)
 Create LOGO request.
static struct
fc_els_prli_descriptor
fc_els_prli_descriptor (unsigned int type)
 Find PRLI descriptor.
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.
int fc_els_prli (struct interface *parent, struct fc_port *port, struct fc_port_id *peer_port_id, unsigned int type)
 Create PRLI request.
static int fc_els_rtv_tx_response (struct fc_els *els)
 Transmit RTV response.
static int fc_els_rtv_rx (struct fc_els *els, void *data __unused, size_t len __unused)
 Receive RTV.
static int fc_els_rtv_detect (struct fc_els *els __unused, const void *data, size_t len __unused)
 Detect RTV.
static int fc_els_echo_tx (struct fc_els *els)
 Transmit ECHO.
static int fc_els_echo_rx_request (struct fc_els *els, void *data, size_t len)
 Receive ECHO request.
static int fc_els_echo_rx_response (struct fc_els *els, void *data, size_t len)
 Receive ECHO response.
static int fc_els_echo_rx (struct fc_els *els, void *data, size_t len)
 Receive ECHO.
static int fc_els_echo_detect (struct fc_els *els __unused, const void *data, size_t len __unused)
 Detect ECHO.

Variables

struct fc_els_handler
fc_els_unknown_handler 
__fc_els_handler
 Unknown ELS handler.
static struct interface_operation fc_els_xchg_op []
 Fibre Channel ELS exchange interface operations.
static struct interface_descriptor fc_els_xchg_desc
 Fibre Channel ELS exchange interface descriptor.
static struct interface_operation fc_els_job_op []
 Fibre Channel ELS job control interface operations.
static struct interface_descriptor fc_els_job_desc
 Fibre Channel ELS job control interface descriptor.
static struct process_descriptor fc_els_process_desc
 Fibre Channel ELS process descriptor.
struct fc_responder
fc_els_responder 
__fc_responder
 Fibre Channel ELS responder.

Detailed Description

Fibre Channel Extended Link Services.

Definition in file fcels.c.


Define Documentation

#define FCELS_FMT   "FCELS %s %s %s %s"
#define FCELS_ARGS (   els)
Value:
(els)->port->name,                                              \
        ( (els)->handler ? (els)->handler->name : "unknown ELS" ),      \
        ( fc_els_is_request ( els ) ? "to" : "from" ),                  \
        fc_id_ntoa ( &(els)->peer_port_id )

Fibre Channel ELS transaction debug message arguments.

Definition at line 49 of file fcels.c.

Referenced by fc_els_close(), fc_els_echo_rx_request(), fc_els_echo_rx_response(), fc_els_flogi_rx(), fc_els_logo_rx_request(), fc_els_plogi_rx(), fc_els_prli_rx(), fc_els_rtv_rx(), fc_els_rx(), fc_els_step(), fc_els_tx(), and fc_els_unknown_rx().

#define FC_ECHO_MAGIC   0x69505845

ECHO magic marker.

Definition at line 1228 of file fcels.c.

Referenced by fc_els_echo_rx_response(), and fc_els_echo_tx().


Function Documentation

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL  )
static void fc_els_free ( struct refcnt refcnt) [static]

Free Fibre Channel ELS transaction.

Parameters:
refcntReference count

Definition at line 62 of file fcels.c.

References assert, container_of, fc_port_put(), free, fc_els::port, fc_els::process, and process_running().

Referenced by fc_els_create().

                                                  {
        struct fc_els *els = container_of ( refcnt, struct fc_els, refcnt );

        assert ( ! process_running ( &els->process ) );
        fc_port_put ( els->port );
        free ( els );
}
static void fc_els_close ( struct fc_els els,
int  rc 
) [static]

Close Fibre Channel ELS transaction.

Parameters:
elsFibre Channel ELS transaction
rcReason for close

Definition at line 76 of file fcels.c.

References DBGC, FCELS_ARGS, FCELS_FMT, intf_shutdown(), fc_els::job, fc_els::process, process_del(), strerror(), and fc_els::xchg.

Referenced by fc_els_rx(), and fc_els_step().

                                                        {

        if ( rc != 0 ) {
                DBGC ( els, FCELS_FMT " complete (%s)\n",
                       FCELS_ARGS ( els ), strerror ( rc ) );
        }

        /* Stop process */
        process_del ( &els->process );

        /* Shut down interfaces */
        intf_shutdown ( &els->xchg, rc );
        intf_shutdown ( &els->job, rc );
}
static struct fc_els_handler* fc_els_detect ( struct fc_els els,
const void *  data,
size_t  len 
) [static, read]

Detect Fibre Channel ELS frame handler.

Parameters:
elsFibre Channel ELS transaction
commandELS command code
Return values:
handlerELS handler, or NULL

Definition at line 98 of file fcels.c.

References data, fc_els_handler::detect, FC_ELS_HANDLERS, for_each_table_entry, NULL, and rc.

Referenced by fc_els_rx().

                                                            {
        const struct fc_els_frame_common *frame = data;
        struct fc_els_handler *handler;
        int rc;

        /* Sanity check */
        if ( len < sizeof ( *frame ) )
                return NULL;

        /* Try each handler in turn */
        for_each_table_entry ( handler, FC_ELS_HANDLERS ) {
                if ( ( rc = handler->detect ( els, data, len ) ) == 0 )
                        return handler;
        }

        return NULL;
}
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;
}
static int fc_els_rx ( struct fc_els els,
struct io_buffer iobuf,
struct xfer_metadata meta 
) [static]

Receive Fibre Channel ELS frame.

Parameters:
elsFibre Channel ELS transaction
iobufI/O buffer
metaData transfer metadata
Return values:
rcReturn status code

Definition at line 159 of file fcels.c.

References fc_els_frame_common::command, io_buffer::data, DBGC, DBGC2, DBGC2_HDA, DBGC_HDA, xfer_metadata::dest, dest, done, EACCES, EINVAL, fc_els_close(), fc_els_detect(), fc_els_is_request(), FC_ELS_LS_ACC, FCELS_ARGS, FCELS_FMT, free_iob(), fc_els::handler, iob_len(), len, memcpy(), fc_els::peer_port_id, fc_els::port_id, rc, fc_els_handler::rx, sockaddr_fc::sfc_port_id, xfer_metadata::src, src, and strerror().

                                                    {
        struct fc_els_frame_common *frame = iobuf->data;
        struct sockaddr_fc *src = ( ( struct sockaddr_fc * ) meta->src );
        struct sockaddr_fc *dest = ( ( struct sockaddr_fc * ) meta->dest );
        size_t len = iob_len ( iobuf );
        int rc;

        /* Sanity check */
        if ( len < sizeof ( *frame ) ) {
                DBGC ( els, FCELS_FMT " received underlength frame:\n",
                       FCELS_ARGS ( els ) );
                DBGC_HDA ( els, 0, frame, len );
                rc = -EINVAL;
                goto done;
        }
        if ( ! src ) {
                DBGC ( els, FCELS_FMT " received frame missing source "
                       "address:\n", FCELS_ARGS ( els ) );
                rc = -EINVAL;
                goto done;
        }
        if ( ! dest ) {
                DBGC ( els, FCELS_FMT " received frame missing destination "
                       "address:\n", FCELS_ARGS ( els ) );
                rc = -EINVAL;
                goto done;
        }

        /* Check for rejection responses */
        if ( fc_els_is_request ( els ) &&
             ( frame->command != FC_ELS_LS_ACC ) ) {
                DBGC ( els, FCELS_FMT " rejected:\n", FCELS_ARGS ( els ) );
                DBGC_HDA ( els, 0, frame, len );
                rc = -EACCES;
                goto done;
        }

        /* Update port IDs */
        memcpy ( &els->port_id, &dest->sfc_port_id, sizeof ( els->port_id ) );
        memcpy ( &els->peer_port_id, &src->sfc_port_id,
                 sizeof ( els->peer_port_id ) );

        /* Determine handler, if necessary */
        if ( ! els->handler )
                els->handler = fc_els_detect ( els, frame, len );
        if ( ! els->handler )
                els->handler = &fc_els_unknown_handler;

        DBGC2 ( els, FCELS_FMT " received:\n", FCELS_ARGS ( els ) );
        DBGC2_HDA ( els, 0, frame, len );

        /* Handle received frame */
        if ( ( rc = els->handler->rx ( els, frame, len ) ) != 0 ) {
                DBGC ( els, FCELS_FMT " could not handle received frame: "
                       "%s\n", FCELS_ARGS ( els ), strerror ( rc ) );
                DBGC_HDA ( els, 0, frame, len );
                goto done;
        }

 done:
        /* Free I/O buffer */
        free_iob ( iobuf );

        /* Close transaction */
        fc_els_close ( els, rc );

        return rc;
}
static void fc_els_step ( struct fc_els els) [static]

Fibre Channel ELS process.

Parameters:
elsFibre Channel ELS transaction

Definition at line 254 of file fcels.c.

References assert, DBGC, fc_els_close(), fc_els_is_request(), FC_TYPE_ELS, fc_xchg_originate(), FCELS_ARGS, FCELS_FMT, fc_els::handler, fc_els::peer_port_id, fc_els::port, rc, strerror(), fc_els_handler::tx, and fc_els::xchg.

                                               {
        int xchg_id;
        int rc;

        /* Sanity check */
        assert ( fc_els_is_request ( els ) );

        /* Create exchange */
        if ( ( xchg_id = fc_xchg_originate ( &els->xchg, els->port,
                                             &els->peer_port_id,
                                             FC_TYPE_ELS ) ) < 0 ) {
                rc = xchg_id;
                DBGC ( els, FCELS_FMT " could not create exchange: %s\n",
                       FCELS_ARGS ( els ), strerror ( rc ) );
                fc_els_close ( els, rc );
                return;
        }

        /* Transmit request */
        if ( ( rc = els->handler->tx ( els ) ) != 0 ) {
                DBGC ( els, FCELS_FMT " could not transmit request: %s\n",
                       FCELS_ARGS ( els ), strerror ( rc ) );
                fc_els_close ( els, rc );
                return;
        }
}
static struct fc_els* fc_els_create ( struct fc_port port,
struct fc_port_id port_id,
struct fc_port_id peer_port_id 
) [static, read]

Create ELS transaction.

Parameters:
portFibre Channel port
port_idLocal port ID
peer_port_idPeer port ID
Return values:
elsFibre Channel ELS transaction, or NULL

Definition at line 293 of file fcels.c.

References fc_els_free(), fc_port_get(), intf_init(), fc_els::job, memcpy(), NULL, fc_els::peer_port_id, fc_els::port, fc_els::port_id, fc_els::process, process_init_stopped(), ref_init, fc_els::refcnt, fc_els::xchg, and zalloc().

Referenced by fc_els_request(), and fc_els_respond().

                                                                         {
        struct fc_els *els;

        /* Allocate and initialise structure */
        els = zalloc ( sizeof ( *els ) );
        if ( ! els )
                return NULL;
        ref_init ( &els->refcnt, fc_els_free );
        intf_init ( &els->job, &fc_els_job_desc, &els->refcnt );
        intf_init ( &els->xchg, &fc_els_xchg_desc, &els->refcnt );
        process_init_stopped ( &els->process, &fc_els_process_desc,
                               &els->refcnt );
        els->port = fc_port_get ( port );
        memcpy ( &els->port_id, port_id, sizeof ( els->port_id ) );
        memcpy ( &els->peer_port_id, peer_port_id,
                 sizeof ( els->peer_port_id ) );
        return els;
}
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;
}
static int fc_els_respond ( struct interface xchg,
struct fc_port port,
struct fc_port_id port_id,
struct fc_port_id peer_port_id 
) [static]

Create ELS response.

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

Definition at line 351 of file fcels.c.

References ENOMEM, fc_els_create(), intf_plug_plug(), ref_put, fc_els::refcnt, and fc_els::xchg.

                                                              {
        struct fc_els *els;

        /* Allocate and initialise structure */
        els = fc_els_create ( port, port_id, peer_port_id );
        if ( ! els )
                return -ENOMEM;

        /* Attach to exchange interface, mortalise self, and return */
        intf_plug_plug ( &els->xchg, xchg );
        ref_put ( &els->refcnt );
        return 0;
}
static int fc_els_unknown_tx ( struct fc_els *els  __unused) [static]

Transmit unknown ELS request.

Parameters:
elsFibre Channel ELS transaction
Return values:
rcReturn status code

Definition at line 386 of file fcels.c.

References ENOTSUP.

                                                             {
        return -ENOTSUP;
}
static int fc_els_unknown_tx_response ( struct fc_els els) [static]

Transmit unknown ELS response.

Parameters:
elsFibre Channel ELS transaction
Return values:
rcReturn status code

Definition at line 396 of file fcels.c.

References fc_ls_rjt_frame::command, FC_ELS_LS_RJT, FC_ELS_RJT_UNSUPPORTED, fc_els_tx(), memset(), and fc_ls_rjt_frame::reason.

Referenced by fc_els_unknown_rx().

                                                             {
        struct fc_ls_rjt_frame ls_rjt;

        /* Construct LS_RJT */
        memset ( &ls_rjt, 0, sizeof ( ls_rjt ) );
        ls_rjt.command = FC_ELS_LS_RJT;
        ls_rjt.reason = FC_ELS_RJT_UNSUPPORTED;

        /* Transmit LS_RJT */
        return fc_els_tx ( els, &ls_rjt, sizeof ( ls_rjt ) );
}
static int fc_els_unknown_rx ( struct fc_els els,
void *  data,
size_t  len 
) [static]

Receive unknown ELS.

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

Definition at line 416 of file fcels.c.

References DBGC, DBGC_HDA, fc_els_is_request(), fc_els_unknown_tx_response(), FCELS_ARGS, FCELS_FMT, and rc.

                                                                            {
        int rc;

        DBGC ( els, FCELS_FMT ":\n", FCELS_ARGS ( els ) );
        DBGC_HDA ( els, 0, data, len );

        /* Transmit response, if applicable */
        if ( ! fc_els_is_request ( els ) ) {
                if ( ( rc = fc_els_unknown_tx_response ( els ) ) != 0 )
                        return rc;
        }

        return 0;
}
static int fc_els_unknown_detect ( struct fc_els *els  __unused,
const void *data  __unused,
size_t len  __unused 
) [static]

Detect unknown ELS.

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

Definition at line 439 of file fcels.c.

References ENOTSUP.

                                                         {
        return -ENOTSUP;
}
static int fc_els_flogi_tx ( struct fc_els els) [static]

Transmit FLOGI.

Parameters:
elsFibre Channel ELS transaction
Return values:
rcReturn status code

Definition at line 466 of file fcels.c.

References fc_login_frame::class3, fc_login_frame::command, fc_login_frame::common, fc_login_common::credit, FC_ELS_FLOGI, fc_els_tx(), fc_els_tx_command(), FC_LOGIN_CLASS_SEQUENTIAL, FC_LOGIN_CLASS_VALID, FC_LOGIN_CONTINUOUS_OFFSET, FC_LOGIN_DEFAULT_B2B, FC_LOGIN_DEFAULT_MTU, FC_LOGIN_VERSION, fc_login_common::flags, fc_login_class::flags, htons, memcpy(), memset(), fc_login_common::mtu, fc_login_frame::node_wwn, fc_port::node_wwn, fc_els::port, fc_login_frame::port_wwn, fc_port::port_wwn, and fc_login_common::version.

Referenced by fc_els_flogi_rx().

                                                  {
        struct fc_login_frame flogi;

        /* Construct FLOGI */
        memset ( &flogi, 0, sizeof ( flogi ) );
        flogi.command = fc_els_tx_command ( els, FC_ELS_FLOGI );
        flogi.common.version = htons ( FC_LOGIN_VERSION );
        flogi.common.credit = htons ( FC_LOGIN_DEFAULT_B2B );
        flogi.common.flags = htons ( FC_LOGIN_CONTINUOUS_OFFSET );
        flogi.common.mtu = htons ( FC_LOGIN_DEFAULT_MTU );
        memcpy ( &flogi.port_wwn, &els->port->port_wwn,
                 sizeof ( flogi.port_wwn ) );
        memcpy ( &flogi.node_wwn, &els->port->node_wwn,
                 sizeof ( flogi.node_wwn ) );
        flogi.class3.flags = htons ( FC_LOGIN_CLASS_VALID |
                                     FC_LOGIN_CLASS_SEQUENTIAL );

        /* Transmit FLOGI */
        return fc_els_tx ( els, &flogi, sizeof ( flogi ) );
}
static int fc_els_flogi_rx ( struct fc_els els,
void *  data,
size_t  len 
) [static]

Receive FLOGI.

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

Definition at line 495 of file fcels.c.

References fc_login_frame::common, data, DBGC, DBGC_HDA, EINVAL, fc_els_flogi_tx(), fc_els_is_request(), fc_id_ntoa(), FC_LOGIN_F_PORT, fc_ntoa(), fc_port_login(), FCELS_ARGS, FCELS_FMT, fc_login_common::flags, htons, memcpy(), fc_login_frame::node_wwn, fc_els::peer_port_id, fc_els::port, fc_els::port_id, fc_login_frame::port_wwn, fc_port::ptp_link_port_id, rc, and strerror().

                                                                          {
        struct fc_login_frame *flogi = data;
        int has_fabric;
        int rc;

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

        /* Extract parameters */
        has_fabric = ( flogi->common.flags & htons ( FC_LOGIN_F_PORT ) );
        DBGC ( els, FCELS_FMT " has node %s\n", FCELS_ARGS ( els ),
               fc_ntoa ( &flogi->node_wwn ) );
        DBGC ( els, FCELS_FMT " has port %s\n", FCELS_ARGS ( els ),
               fc_ntoa ( &flogi->port_wwn ) );
        if ( has_fabric ) {
                DBGC ( els, FCELS_FMT " has fabric with", FCELS_ARGS ( els ) );
                DBGC ( els, " local ID %s\n", fc_id_ntoa ( &els->port_id ) );
        } else {
                DBGC ( els, FCELS_FMT " has point-to-point link\n",
                       FCELS_ARGS ( els ) );
        }

        /* Log in port */
        if ( ( rc = fc_port_login ( els->port, &els->port_id, &flogi->node_wwn,
                                    &flogi->port_wwn, has_fabric ) ) != 0 ) {
                DBGC ( els, FCELS_FMT " could not log in port: %s\n",
                       FCELS_ARGS ( els ), strerror ( rc ) );
                return rc;
        }

        /* Send any responses to the newly-assigned peer port ID, if
         * applicable.
         */
        if ( ! has_fabric ) {
                memcpy ( &els->peer_port_id, &els->port->ptp_link_port_id,
                         sizeof ( els->peer_port_id ) );
        }

        /* Transmit response, if applicable */
        if ( ! fc_els_is_request ( els ) ) {
                if ( ( rc = fc_els_flogi_tx ( els ) ) != 0 )
                        return rc;
        }

        return 0;
}
static int fc_els_flogi_detect ( struct fc_els *els  __unused,
const void *  data,
size_t len  __unused 
) [static]

Detect FLOGI.

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

Definition at line 555 of file fcels.c.

References fc_login_frame::command, data, EINVAL, and FC_ELS_FLOGI.

                                                       {
        const struct fc_login_frame *flogi = data;

        /* Check for FLOGI */
        if ( flogi->command != FC_ELS_FLOGI )
                return -EINVAL;

        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 );
}
static int fc_els_plogi_tx ( struct fc_els els) [static]

Transmit PLOGI.

Parameters:
elsFibre Channel ELS transaction
Return values:
rcReturn status code

Definition at line 600 of file fcels.c.

References fc_login_frame::class3, fc_login_frame::command, fc_login_frame::common, fc_login_common::credit, fc_login_common::e_d_tov, FC_ELS_PLOGI, fc_els_tx(), fc_els_tx_command(), FC_LOGIN_CLASS_SEQUENTIAL, FC_LOGIN_CLASS_VALID, FC_LOGIN_CONTINUOUS_OFFSET, FC_LOGIN_DEFAULT_B2B, FC_LOGIN_DEFAULT_E_D_TOV, FC_LOGIN_DEFAULT_MAX_SEQ, FC_LOGIN_DEFAULT_MTU, FC_LOGIN_DEFAULT_REL_OFFS, FC_LOGIN_VERSION, fc_login_common::flags, fc_login_class::flags, htonl, htons, fc_login_class::max_seq, fc_login_class::max_seq_per_xchg, memcpy(), memset(), fc_login_common::mtu, fc_login_class::mtu, fc_login_frame::node_wwn, fc_port::node_wwn, fc_login_common::plogi, fc_els::port, fc_login_frame::port_wwn, fc_port::port_wwn, fc_login_common::u, and fc_login_common::version.

Referenced by fc_els_plogi_rx().

                                                  {
        struct fc_login_frame plogi;

        /* Construct PLOGI */
        memset ( &plogi, 0, sizeof ( plogi ) );
        plogi.command = fc_els_tx_command ( els, FC_ELS_PLOGI );
        plogi.common.version = htons ( FC_LOGIN_VERSION );
        plogi.common.credit = htons ( FC_LOGIN_DEFAULT_B2B );
        plogi.common.flags = htons ( FC_LOGIN_CONTINUOUS_OFFSET );
        plogi.common.mtu = htons ( FC_LOGIN_DEFAULT_MTU );
        plogi.common.u.plogi.max_seq = htons ( FC_LOGIN_DEFAULT_MAX_SEQ );
        plogi.common.u.plogi.rel_offs = htons ( FC_LOGIN_DEFAULT_REL_OFFS );
        plogi.common.e_d_tov = htonl ( FC_LOGIN_DEFAULT_E_D_TOV );
        memcpy ( &plogi.port_wwn, &els->port->port_wwn,
                 sizeof ( plogi.port_wwn ) );
        memcpy ( &plogi.node_wwn, &els->port->node_wwn,
                 sizeof ( plogi.node_wwn ) );
        plogi.class3.flags = htons ( FC_LOGIN_CLASS_VALID |
                                     FC_LOGIN_CLASS_SEQUENTIAL );
        plogi.class3.mtu = htons ( FC_LOGIN_DEFAULT_MTU );
        plogi.class3.max_seq = htons ( FC_LOGIN_DEFAULT_MAX_SEQ );
        plogi.class3.max_seq_per_xchg = 1;

        /* Transmit PLOGI */
        return fc_els_tx ( els, &plogi, sizeof ( plogi ) );
}
static int fc_els_plogi_rx ( struct fc_els els,
void *  data,
size_t  len 
) [static]

Receive PLOGI.

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

Definition at line 635 of file fcels.c.

References data, DBGC, DBGC_HDA, EINVAL, ENOMEM, fc_els_is_request(), fc_els_plogi_tx(), fc_id_ntoa(), fc_link_ok(), fc_ntoa(), fc_peer_get_wwn(), fc_peer_login(), fc_peer_put(), FCELS_ARGS, FCELS_FMT, fc_port::link, fc_login_frame::node_wwn, fc_els::peer_port_id, fc_els::port, fc_login_frame::port_wwn, rc, and strerror().

                                                                          {
        struct fc_login_frame *plogi = data;
        struct fc_peer *peer;
        int rc;

        /* Sanity checks */
        if ( len < sizeof ( *plogi ) ) {
                DBGC ( els, FCELS_FMT " received underlength frame:\n",
                       FCELS_ARGS ( els ) );
                DBGC_HDA ( els, 0, data, len );
                rc = -EINVAL;
                goto err_sanity;
        }
        if ( ! fc_link_ok ( &els->port->link ) ) {
                DBGC ( els, FCELS_FMT " received while port link is down\n",
                       FCELS_ARGS ( els ) );
                rc = -EINVAL;
                goto err_sanity;
        }

        /* Extract parameters */
        DBGC ( els, FCELS_FMT " has node %s\n", FCELS_ARGS ( els ),
               fc_ntoa ( &plogi->node_wwn ) );
        DBGC ( els, FCELS_FMT " has port %s as %s\n",
               FCELS_ARGS ( els ), fc_ntoa ( &plogi->port_wwn ),
               fc_id_ntoa ( &els->peer_port_id ) );

        /* Get peer */
        peer = fc_peer_get_wwn ( &plogi->port_wwn );
        if ( ! peer ) {
                DBGC ( els, FCELS_FMT " could not create peer\n",
                       FCELS_ARGS ( els ) );
                rc = -ENOMEM;
                goto err_peer_get_wwn;
        }

        /* Record login */
        if ( ( rc = fc_peer_login ( peer, els->port,
                                    &els->peer_port_id ) ) != 0 ) {
                DBGC ( els, FCELS_FMT " could not log in peer: %s\n",
                       FCELS_ARGS ( els ), strerror ( rc ) );
                goto err_login;
        }

        /* Transmit response, if applicable */
        if ( ! fc_els_is_request ( els ) ) {
                if ( ( rc = fc_els_plogi_tx ( els ) ) != 0 )
                        goto err_plogi_tx;
        }

        /* Drop temporary reference to peer */
        fc_peer_put ( peer );

        return 0;

 err_plogi_tx:
 err_login:
        fc_peer_put ( peer );
 err_peer_get_wwn:
 err_sanity:
        return rc;
}
static int fc_els_plogi_detect ( struct fc_els *els  __unused,
const void *  data,
size_t len  __unused 
) [static]

Detect PLOGI.

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

Definition at line 706 of file fcels.c.

References fc_login_frame::command, data, EINVAL, and FC_ELS_PLOGI.

                                                       {
        const struct fc_login_frame *plogi = data;

        /* Check for PLOGI */
        if ( plogi->command != FC_ELS_PLOGI )
                return -EINVAL;

        return 0;
}
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 );
}
static int fc_els_logo_tx ( struct fc_els els) [static]

Transmit LOGO request.

Parameters:
elsFibre Channel ELS transaction
Return values:
rcReturn status code

Definition at line 753 of file fcels.c.

References fc_logout_request_frame::command, FC_ELS_LOGO, fc_els_tx(), memcpy(), memset(), fc_els::port, fc_logout_request_frame::port_id, fc_port::port_id, fc_logout_request_frame::port_wwn, and fc_port::port_wwn.

                                                 {
        struct fc_logout_request_frame logo;

        /* Construct LOGO */
        memset ( &logo, 0, sizeof ( logo ) );
        logo.command = FC_ELS_LOGO;
        memcpy ( &logo.port_id, &els->port->port_id, sizeof ( logo.port_id ) );
        memcpy ( &logo.port_wwn, &els->port->port_wwn,
                 sizeof ( logo.port_wwn ) );

        /* Transmit LOGO */
        return fc_els_tx ( els, &logo, sizeof ( logo ) );
}
static int fc_els_logo_tx_response ( struct fc_els els) [static]

Transmit LOGO response.

Parameters:
elsFibre Channel ELS transaction
Return values:
rcReturn status code

Definition at line 773 of file fcels.c.

References fc_logout_response_frame::command, FC_ELS_LS_ACC, fc_els_tx(), and memset().

Referenced by fc_els_logo_rx_request().

                                                          {
        struct fc_logout_response_frame logo;

        /* Construct LOGO */
        memset ( &logo, 0, sizeof ( logo ) );
        logo.command = FC_ELS_LS_ACC;

        /* Transmit LOGO */
        return fc_els_tx ( els, &logo, sizeof ( logo ) );
}
static void fc_els_logo_logout ( struct fc_els els,
struct fc_port_id peer_port_id 
) [static]

Log out individual peer or whole port as applicable.

Parameters:
elsFibre Channel ELS transaction
port_idPeer port ID

Definition at line 790 of file fcels.c.

References fc_f_port_id, fc_peer_get_port_id(), fc_peer_logout(), fc_peer_put(), fc_port_logout(), memcmp(), fc_els::port, and fc_port::port_id.

Referenced by fc_els_logo_rx_request(), and fc_els_logo_rx_response().

                                                                   {
        struct fc_peer *peer;

        if ( ( memcmp ( peer_port_id, &fc_f_port_id,
                        sizeof ( *peer_port_id ) ) == 0 ) ||
             ( memcmp ( peer_port_id, &els->port->port_id,
                        sizeof ( *peer_port_id ) ) == 0 ) ) {
                fc_port_logout ( els->port, 0 );
        } else {
                peer = fc_peer_get_port_id ( els->port, peer_port_id );
                if ( peer ) {
                        fc_peer_logout ( peer, 0 );
                        fc_peer_put ( peer );
                }
        }
}
static int fc_els_logo_rx_request ( struct fc_els els,
void *  data,
size_t  len 
) [static]

Receive LOGO request.

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

Definition at line 816 of file fcels.c.

References data, DBGC, DBGC_HDA, EINVAL, fc_els_logo_logout(), fc_els_logo_tx_response(), fc_id_ntoa(), fc_ntoa(), FCELS_ARGS, FCELS_FMT, fc_logout_request_frame::port_id, fc_logout_request_frame::port_wwn, and rc.

Referenced by fc_els_logo_rx().

                                                 {
        struct fc_logout_request_frame *logo = data;
        int rc;

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

        DBGC ( els, FCELS_FMT " has port %s as %s\n", FCELS_ARGS ( els ),
               fc_ntoa ( &logo->port_wwn ), fc_id_ntoa ( &logo->port_id ) );

        /* Log out individual peer or whole port as applicable */
        fc_els_logo_logout ( els, &logo->port_id );

        /* Transmit repsonse */
        if ( ( rc = fc_els_logo_tx_response ( els ) ) != 0 )
                return rc;

        return 0;
}
static int fc_els_logo_rx_response ( struct fc_els els,
void *data  __unused,
size_t len  __unused 
) [static]

Receive LOGO response.

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

Definition at line 850 of file fcels.c.

References fc_els_logo_logout(), and fc_els::peer_port_id.

Referenced by fc_els_logo_rx().

                                                           {

        /* Log out individual peer or whole port as applicable */
        fc_els_logo_logout ( els, &els->peer_port_id );

        return 0;
}
static int fc_els_logo_rx ( struct fc_els els,
void *  data,
size_t  len 
) [static]

Receive LOGO.

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

Definition at line 867 of file fcels.c.

References fc_els_is_request(), fc_els_logo_rx_request(), and fc_els_logo_rx_response().

                                                                         {

        if ( fc_els_is_request ( els ) ) {
                return fc_els_logo_rx_response ( els, data, len );
        } else {
                return fc_els_logo_rx_request ( els, data, len );
        }
}
static int fc_els_logo_detect ( struct fc_els *els  __unused,
const void *  data,
size_t len  __unused 
) [static]

Detect LOGO.

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

Definition at line 884 of file fcels.c.

References fc_logout_request_frame::command, data, EINVAL, and FC_ELS_LOGO.

                                                      {
        const struct fc_logout_request_frame *logo = data;

        /* Check for LOGO */
        if ( logo->command != FC_ELS_LOGO )
                return -EINVAL;

        return 0;
}
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 );
}
static struct fc_els_prli_descriptor* fc_els_prli_descriptor ( unsigned int  type) [static, read]

Find PRLI descriptor.

Parameters:
typeUpper-layer protocol type
Return values:
descriptorPRLI descriptor, or NULL

Definition at line 932 of file fcels.c.

References FC_ELS_PRLI_DESCRIPTORS, for_each_table_entry, NULL, and fc_els_prli_descriptor::type.

Referenced by fc_els_prli().

                                             {
        struct fc_els_prli_descriptor *descriptor;

        for_each_table_entry ( descriptor, FC_ELS_PRLI_DESCRIPTORS ) {
                if ( descriptor->type == type )
                        return descriptor;
        }
        return NULL;
}
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;
}
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 );
}
static int fc_els_rtv_tx_response ( struct fc_els els) [static]

Transmit RTV response.

Parameters:
elsFibre Channel ELS transaction
Return values:
rcReturn status code

Definition at line 1150 of file fcels.c.

References fc_rtv_response_frame::command, fc_rtv_response_frame::e_d_tov, FC_ELS_LS_ACC, fc_els_tx(), FC_LOGIN_DEFAULT_E_D_TOV, htonl, and memset().

Referenced by fc_els_rtv_rx().

                                                         {
        struct fc_rtv_response_frame rtv;

        /* Construct RTV */
        memset ( &rtv, 0, sizeof ( rtv ) );
        rtv.command = FC_ELS_LS_ACC;
        rtv.e_d_tov = htonl ( FC_LOGIN_DEFAULT_E_D_TOV );

        /* Transmit RTV */
        return fc_els_tx ( els, &rtv, sizeof ( rtv ) );
}
static int fc_els_rtv_rx ( struct fc_els els,
void *data  __unused,
size_t len  __unused 
) [static]

Receive RTV.

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

Definition at line 1170 of file fcels.c.

References DBGC, fc_els_is_request(), fc_els_rtv_tx_response(), FCELS_ARGS, FCELS_FMT, and rc.

                                                 {
        int rc;

        DBGC ( els, FCELS_FMT "\n", FCELS_ARGS ( els ) );

        /* Transmit response */
        if ( ! fc_els_is_request ( els ) ) {
                if ( ( rc = fc_els_rtv_tx_response ( els ) ) != 0 )
                        return rc;
        }

        return 0;
}
static int fc_els_rtv_detect ( struct fc_els *els  __unused,
const void *  data,
size_t len  __unused 
) [static]

Detect RTV.

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

Definition at line 1193 of file fcels.c.

References fc_rtv_request_frame::command, data, EINVAL, and FC_ELS_RTV.

                                                     {
        const struct fc_rtv_request_frame *rtv = data;

        /* Check for RTV */
        if ( rtv->command != FC_ELS_RTV )
                return -EINVAL;

        return 0;
}
static int fc_els_echo_tx ( struct fc_els els) [static]

Transmit ECHO.

Parameters:
elsFibre Channel ELS transaction
Return values:
rcReturn status code

Definition at line 1236 of file fcels.c.

References fc_echo_frame_header::command, fc_echo_request_frame::echo, FC_ECHO_MAGIC, FC_ELS_ECHO, fc_els_tx(), htonl, fc_echo_request_frame::magic, and memset().

                                                 {
        struct fc_echo_request_frame echo;

        /* Construct ECHO */
        memset ( &echo, 0, sizeof ( echo ) );
        echo.echo.command = FC_ELS_ECHO;
        echo.magic = htonl ( FC_ECHO_MAGIC );

        /* Transmit ECHO */
        return fc_els_tx ( els, &echo, sizeof ( echo ) );
}
static int fc_els_echo_rx_request ( struct fc_els els,
void *  data,
size_t  len 
) [static]

Receive ECHO request.

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

Definition at line 1256 of file fcels.c.

References data, DBGC, echo(), FC_ELS_LS_ACC, fc_els_tx(), FCELS_ARGS, FCELS_FMT, and rc.

Referenced by fc_els_echo_rx().

                                                 {
        struct {
                struct fc_echo_frame_header echo;
                char payload[ len - sizeof ( struct fc_echo_frame_header ) ];
        } *echo = data;
        int rc;

        DBGC ( els, FCELS_FMT "\n", FCELS_ARGS ( els ) );

        /* Transmit response */
        echo->echo.command = FC_ELS_LS_ACC;
        if ( ( rc = fc_els_tx ( els, echo, sizeof ( *echo ) ) ) != 0 )
                return rc;

        /* Nothing to do */
        return 0;
}
static int fc_els_echo_rx_response ( struct fc_els els,
void *  data,
size_t  len 
) [static]

Receive ECHO response.

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

Definition at line 1283 of file fcels.c.

References data, DBGC, DBGC_HDA, echo(), EIO, FC_ECHO_MAGIC, FCELS_ARGS, FCELS_FMT, htonl, and fc_echo_request_frame::magic.

Referenced by fc_els_echo_rx().

                                                  {
        struct fc_echo_request_frame *echo = data;

        DBGC ( els, FCELS_FMT "\n", FCELS_ARGS ( els ) );

        /* Check response is correct */
        if ( ( len != sizeof ( *echo ) ) ||
             ( echo->magic != htonl ( FC_ECHO_MAGIC ) ) ) {
                DBGC ( els, FCELS_FMT " received bad echo response\n",
                       FCELS_ARGS ( els ) );
                DBGC_HDA ( els, 0, data, len );
                return -EIO;
        }

        return 0;
}
static int fc_els_echo_rx ( struct fc_els els,
void *  data,
size_t  len 
) [static]

Receive ECHO.

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

Definition at line 1309 of file fcels.c.

References fc_els_echo_rx_request(), fc_els_echo_rx_response(), and fc_els_is_request().

                                                                         {

        if ( fc_els_is_request ( els ) ) {
                return fc_els_echo_rx_response ( els, data, len );
        } else {
                return fc_els_echo_rx_request ( els, data, len );
        }
}
static int fc_els_echo_detect ( struct fc_els *els  __unused,
const void *  data,
size_t len  __unused 
) [static]

Detect ECHO.

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

Definition at line 1326 of file fcels.c.

References fc_echo_frame_header::command, data, echo(), EINVAL, and FC_ELS_ECHO.

                                                      {
        const struct fc_echo_frame_header *echo = data;

        /* Check for ECHO */
        if ( echo->command != FC_ELS_ECHO )
                return -EINVAL;

        return 0;
}

Variable Documentation

struct fc_els_handler fc_els_echo_handler __fc_els_handler
Initial value:
 {
        .name           = "UNKNOWN",
        .tx             = fc_els_unknown_tx,
        .rx             = fc_els_unknown_rx,
        .detect         = fc_els_unknown_detect,
}

Unknown ELS handler.

ECHO ELS handler.

RTV ELS handler.

LOGO ELS handler.

PLOGI ELS handler.

FLOGI ELS handler.

Definition at line 55 of file fcels.c.

Initial value:

Fibre Channel ELS exchange interface operations.

Definition at line 231 of file fcels.c.

Initial value:
        INTF_DESC ( struct fc_els, xchg, fc_els_xchg_op )

Fibre Channel ELS exchange interface descriptor.

Definition at line 237 of file fcels.c.

Initial value:
 {
        INTF_OP ( intf_close, struct fc_els *, fc_els_close ),
}

Fibre Channel ELS job control interface operations.

Definition at line 241 of file fcels.c.

Initial value:
        INTF_DESC ( struct fc_els, job, fc_els_job_op )

Fibre Channel ELS job control interface descriptor.

Definition at line 246 of file fcels.c.

Initial value:

Fibre Channel ELS process descriptor.

Definition at line 282 of file fcels.c.

struct fc_responder fc_els_responder __fc_responder
Initial value:
 {
        .type = FC_TYPE_ELS,
        .respond = fc_els_respond,
}

Fibre Channel ELS responder.

Definition at line 368 of file fcels.c.