iPXE
fc.c File Reference

Fibre Channel. More...

#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <assert.h>
#include <byteswap.h>
#include <ipxe/refcnt.h>
#include <ipxe/list.h>
#include <ipxe/tables.h>
#include <ipxe/timer.h>
#include <ipxe/retry.h>
#include <ipxe/interface.h>
#include <ipxe/xfer.h>
#include <ipxe/iobuf.h>
#include <ipxe/fc.h>
#include <ipxe/fcels.h>
#include <ipxe/fcns.h>

Go to the source code of this file.

Data Structures

struct  fc_exchange
 A Fibre Channel exchange. More...

Macros

#define EUNKNOWN_LINK_STATUS   __einfo_error ( EINFO_EUNKNOWN_LINK_STATUS )
 Default link status code.
#define EINFO_EUNKNOWN_LINK_STATUS    __einfo_uniqify ( EINFO_EINPROGRESS, 0x01, "Unknown" )
#define FC_TIMEOUT   ( 1 * TICKS_PER_SEC )
 Fibre Channel timeout.

Enumerations

enum  fc_exchange_flags { FC_XCHG_ORIGINATOR = 0x0001 , FC_XCHG_SEQ_INITIATIVE = 0x0002 , FC_XCHG_SEQ_FIRST = 0x0004 }
 Fibre Channel exchange flags. More...

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
 LIST_HEAD (fc_ports)
 List of Fibre Channel ports.
 LIST_HEAD (fc_peers)
 List of Fibre Channel peers.
const char * fc_id_ntoa (const struct fc_port_id *id)
 Format Fibre Channel port ID.
int fc_id_aton (const char *id_text, struct fc_port_id *id)
 Parse Fibre Channel port ID.
const char * fc_ntoa (const struct fc_name *wwn)
 Format Fibre Channel WWN.
int fc_aton (const char *wwn_text, struct fc_name *wwn)
 Parse Fibre Channel WWN.
struct sockaddrfc_fill_sockaddr (struct sockaddr_fc *sa_fc, struct fc_port_id *id)
 Fill Fibre Channel socket address.
static void fc_link_up (struct fc_link_state *link)
 Mark Fibre Channel link as up.
static void fc_link_err (struct fc_link_state *link, int rc)
 Mark Fibre Channel link as down.
static void fc_link_examine (struct fc_link_state *link)
 Examine Fibre Channel link state.
static void fc_link_expired (struct retry_timer *timer, int over __unused)
 Handle Fibre Channel link retry timer expiry.
static void fc_link_init (struct fc_link_state *link, void(*examine)(struct fc_link_state *link), struct refcnt *refcnt)
 Initialise Fibre Channel link state monitor.
static void fc_link_start (struct fc_link_state *link)
 Start monitoring Fibre Channel link state.
static void fc_link_stop (struct fc_link_state *link)
 Stop monitoring Fibre Channel link state.
static unsigned int fc_new_xchg_id (void)
 Create local Fibre Channel exchange identifier.
static unsigned int fc_new_seq_id (void)
 Create local Fibre Channel sequence identifier.
static void fc_xchg_free (struct refcnt *refcnt)
 Free Fibre Channel exchange.
static void fc_xchg_close (struct fc_exchange *xchg, int rc)
 Close Fibre Channel exchange.
static void fc_xchg_expired (struct retry_timer *timer, int over __unused)
 Handle exchange timeout.
static size_t fc_xchg_window (struct fc_exchange *xchg __unused)
 Check Fibre Channel exchange window.
static struct io_bufferfc_xchg_alloc_iob (struct fc_exchange *xchg, size_t len)
 Allocate Fibre Channel I/O buffer.
static int fc_xchg_tx (struct fc_exchange *xchg, struct io_buffer *iobuf, struct xfer_metadata *meta)
 Transmit data as part of a Fibre Channel exchange.
static int fc_xchg_rx (struct fc_exchange *xchg, struct io_buffer *iobuf, struct xfer_metadata *meta __unused)
 Receive data as part of a Fibre Channel exchange.
static struct fc_exchangefc_xchg_create (struct fc_port *port, struct fc_port_id *peer_port_id, unsigned int type)
 Create new Fibre Channel exchange.
int fc_xchg_originate (struct interface *parent, struct fc_port *port, struct fc_port_id *peer_port_id, unsigned int type)
 Originate a new Fibre Channel exchange.
static struct fc_exchangefc_xchg_respond (struct fc_port *port, struct fc_frame_header *fchdr)
 Open a new responder Fibre Channel exchange.
static void fc_port_close (struct fc_port *port, int rc)
 Close Fibre Channel port.
static struct fc_exchangefc_port_demux (struct fc_port *port, unsigned int xchg_id)
 Identify Fibre Channel exchange by local exchange ID.
static int fc_port_deliver (struct fc_port *port, struct io_buffer *iobuf, struct xfer_metadata *meta)
 Handle received frame from Fibre Channel port.
int fc_port_login (struct fc_port *port, struct fc_port_id *port_id, const struct fc_name *link_node_wwn, const struct fc_name *link_port_wwn, int has_fabric)
 Log in Fibre Channel port.
void fc_port_logout (struct fc_port *port, int rc)
 Log out Fibre Channel port.
static void fc_port_flogi_done (struct fc_port *port, int rc)
 Handle FLOGI completion.
static void fc_port_ns_plogi_done (struct fc_port *port, int rc)
 Handle name server PLOGI completion.
static void fc_port_examine (struct fc_link_state *link)
 Examine Fibre Channel port link state.
static void fc_port_window_changed (struct fc_port *port)
 Handle change of flow control window.
int fc_port_open (struct interface *transport, const struct fc_name *node_wwn, const struct fc_name *port_wwn, const char *name)
 Create Fibre Channel port.
struct fc_portfc_port_find (const char *name)
 Find Fibre Channel port by name.
static void fc_peer_close (struct fc_peer *peer, int rc)
 Close Fibre Channel peer.
static void fc_peer_increment (struct fc_peer *peer)
 Increment Fibre Channel peer active usage count.
static void fc_peer_decrement (struct fc_peer *peer)
 Decrement Fibre Channel peer active usage count.
int fc_peer_login (struct fc_peer *peer, struct fc_port *port, struct fc_port_id *port_id)
 Log in Fibre Channel peer.
void fc_peer_logout (struct fc_peer *peer, int rc)
 Log out Fibre Channel peer.
static void fc_peer_plogi_done (struct fc_peer *peer, int rc)
 Handle PLOGI completion.
static int fc_peer_plogi (struct fc_peer *peer, struct fc_port *port, struct fc_port_id *peer_port_id)
 Initiate PLOGI.
static void fc_peer_examine (struct fc_link_state *link)
 Examine Fibre Channel peer link state.
static struct fc_peerfc_peer_create (const struct fc_name *port_wwn)
 Create Fibre Channel peer.
struct fc_peerfc_peer_get_wwn (const struct fc_name *port_wwn)
 Get Fibre Channel peer by node name.
struct fc_peerfc_peer_get_port_id (struct fc_port *port, const struct fc_port_id *peer_port_id)
 Get Fibre Channel peer by port ID.
static void fc_ulp_free (struct refcnt *refcnt)
 Free Fibre Channel upper-layer protocol.
static void fc_ulp_close (struct fc_ulp *ulp, int rc)
 Close Fibre Channel upper-layer protocol.
void fc_ulp_attach (struct fc_ulp *ulp, struct fc_ulp_user *user)
 Attach Fibre Channel upper-layer protocol user.
void fc_ulp_detach (struct fc_ulp_user *user)
 Detach Fibre Channel upper-layer protocol user.
int fc_ulp_login (struct fc_ulp *ulp, const void *param, size_t param_len, int originated)
 Log in Fibre Channel upper-layer protocol.
void fc_ulp_logout (struct fc_ulp *ulp, int rc)
 Log out Fibre Channel upper-layer protocol.
static void fc_ulp_prli_done (struct fc_ulp *ulp, int rc)
 Handle PRLI completion.
static void fc_ulp_examine (struct fc_link_state *link)
 Examine Fibre Channel upper-layer protocol link state.
static struct fc_ulpfc_ulp_create (struct fc_peer *peer, unsigned int type)
 Create Fibre Channel upper-layer protocl.
static struct fc_ulpfc_ulp_get_type (struct fc_peer *peer, unsigned int type)
 Get Fibre Channel upper-layer protocol by peer and type.
struct fc_ulpfc_ulp_get_wwn_type (const struct fc_name *port_wwn, unsigned int type)
 Get Fibre Channel upper-layer protocol by port name and type.
struct fc_ulpfc_ulp_get_port_id_type (struct fc_port *port, const struct fc_port_id *peer_port_id, unsigned int type)
 Get Fibre Channel upper-layer protocol by port ID and type.
 REQUIRING_SYMBOL (fc_ports)
 REQUIRE_OBJECT (config_fc)

Variables

struct fc_port_id fc_empty_port_id = { .bytes = { 0x00, 0x00, 0x00 } }
 Unassigned port ID.
struct fc_port_id fc_f_port_id = { .bytes = { 0xff, 0xff, 0xfe } }
 F_Port contoller port ID.
struct fc_port_id fc_gs_port_id = { .bytes = { 0xff, 0xff, 0xfc } }
 Generic services port ID.
struct fc_port_id fc_ptp_low_port_id = { .bytes = { 0x01, 0x01, 0x01 } }
 Point-to-point low port ID.
struct fc_port_id fc_ptp_high_port_id = { .bytes = { 0x01, 0x01, 0x02 } }
 Point-to-point high port ID.
static const uint8_t fc_r_ctl_info_meta_flags [FC_R_CTL_INFO_MASK+1]
 Mapping from Fibre Channel routing control information to xfer metadata.
static struct interface_operation fc_xchg_ulp_op []
 Fibre Channel exchange ULP interface operations.
static struct interface_descriptor fc_xchg_ulp_desc
 Fibre Channel exchange ULP interface descriptor.
static struct interface_operation fc_port_transport_op []
 Fibre Channel port transport interface operations.
static struct interface_descriptor fc_port_transport_desc
 Fibre Channel port transport interface descriptor.
static struct interface_operation fc_port_flogi_op []
 Fibre Channel port FLOGI interface operations.
static struct interface_descriptor fc_port_flogi_desc
 Fibre Channel port FLOGI interface descriptor.
static struct interface_operation fc_port_ns_plogi_op []
 Fibre Channel port name server PLOGI interface operations.
static struct interface_descriptor fc_port_ns_plogi_desc
 Fibre Channel port name server PLOGI interface descriptor.
static struct interface_operation fc_peer_plogi_op []
 Fibre Channel peer PLOGI interface operations.
static struct interface_descriptor fc_peer_plogi_desc
 Fibre Channel peer PLOGI interface descriptor.
static struct interface_operation fc_ulp_prli_op []
 Fibre Channel upper-layer protocol PRLI interface operations.
static struct interface_descriptor fc_ulp_prli_desc
 Fibre Channel upper-layer protocol PRLI interface descriptor.

Detailed Description

Fibre Channel.

Definition in file fc.c.

Macro Definition Documentation

◆ EUNKNOWN_LINK_STATUS

#define EUNKNOWN_LINK_STATUS   __einfo_error ( EINFO_EUNKNOWN_LINK_STATUS )

Default link status code.

Definition at line 186 of file fc.c.

Referenced by alloc_netdev(), fc_link_err(), fc_link_init(), and netdev_link_down().

◆ EINFO_EUNKNOWN_LINK_STATUS

#define EINFO_EUNKNOWN_LINK_STATUS    __einfo_uniqify ( EINFO_EINPROGRESS, 0x01, "Unknown" )

Definition at line 187 of file fc.c.

187#define EINFO_EUNKNOWN_LINK_STATUS \
188 __einfo_uniqify ( EINFO_EINPROGRESS, 0x01, "Unknown" )

◆ FC_TIMEOUT

#define FC_TIMEOUT   ( 1 * TICKS_PER_SEC )

Fibre Channel timeout.

Definition at line 328 of file fc.c.

Referenced by fc_xchg_rx(), and fc_xchg_tx().

Enumeration Type Documentation

◆ fc_exchange_flags

Fibre Channel exchange flags.

Enumerator
FC_XCHG_ORIGINATOR 

We are the exchange originator.

FC_XCHG_SEQ_INITIATIVE 

We have the sequence initiative.

FC_XCHG_SEQ_FIRST 

This is the first sequence of the exchange.

Definition at line 318 of file fc.c.

318 {
319 /** We are the exchange originator */
320 FC_XCHG_ORIGINATOR = 0x0001,
321 /** We have the sequence initiative */
322 FC_XCHG_SEQ_INITIATIVE = 0x0002,
323 /** This is the first sequence of the exchange */
324 FC_XCHG_SEQ_FIRST = 0x0004,
325};
@ FC_XCHG_ORIGINATOR
We are the exchange originator.
Definition fc.c:320
@ FC_XCHG_SEQ_FIRST
This is the first sequence of the exchange.
Definition fc.c:324
@ FC_XCHG_SEQ_INITIATIVE
We have the sequence initiative.
Definition fc.c:322

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )

◆ LIST_HEAD() [1/2]

LIST_HEAD ( fc_ports )

List of Fibre Channel ports.

References fc_ports.

◆ LIST_HEAD() [2/2]

LIST_HEAD ( fc_peers )

List of Fibre Channel peers.

References fc_peers.

◆ fc_id_ntoa()

const char * fc_id_ntoa ( const struct fc_port_id * id)

Format Fibre Channel port ID.

Parameters
idFibre Channel port ID
Return values
id_textPort ID text

Definition at line 92 of file fc.c.

92 {
93 static char id_text[ FC_PORT_ID_STRLEN + 1 /* NUL */ ];
94
95 snprintf ( id_text, sizeof ( id_text ), "%02x.%02x.%02x",
96 id->bytes[0], id->bytes[1], id->bytes[2] );
97 return id_text;
98}
uint8_t id
Request identifier.
Definition ena.h:1
#define FC_PORT_ID_STRLEN
Length of Fibre Channel port identifier next.
Definition fc.h:43
int snprintf(char *buf, size_t size, const char *fmt,...)
Write a formatted string to a buffer.
Definition vsprintf.c:383

References FC_PORT_ID_STRLEN, id, and snprintf().

Referenced by fc_els_flogi_rx(), fc_els_logo_rx_request(), fc_els_plogi_rx(), fc_ns_query_deliver(), fc_peer_login(), fc_port_deliver(), fc_port_login(), fc_xchg_originate(), fc_xchg_respond(), fcels(), fcpeerstat(), and fcportstat().

◆ fc_id_aton()

int fc_id_aton ( const char * id_text,
struct fc_port_id * id )

Parse Fibre Channel port ID.

Parameters
id_textPort ID text
Return values
idFibre Channel port ID
rcReturn status code

Definition at line 107 of file fc.c.

107 {
108 char *ptr = ( ( char * ) id_text );
109 unsigned int i = 0;
110
111 while ( 1 ) {
112 id->bytes[i++] = strtoul ( ptr, &ptr, 16 );
113 if ( i == sizeof ( id->bytes ) )
114 return ( ( *ptr == '\0' ) ? 0 : -EINVAL );
115 if ( *ptr != '.' )
116 return -EINVAL;
117 ptr++;
118 }
119}
#define EINVAL
Invalid argument.
Definition errno.h:429
unsigned long strtoul(const char *string, char **endp, int base)
Convert string to numeric value.
Definition string.c:485

References EINVAL, id, and strtoul().

Referenced by parse_fc_port_id().

◆ fc_ntoa()

const char * fc_ntoa ( const struct fc_name * wwn)

Format Fibre Channel WWN.

Parameters
wwnFibre Channel WWN
Return values
wwn_textWWN text

Definition at line 127 of file fc.c.

127 {
128 static char wwn_text[ FC_NAME_STRLEN + 1 /* NUL */ ];
129
130 snprintf ( wwn_text, sizeof ( wwn_text ),
131 "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
132 wwn->bytes[0], wwn->bytes[1], wwn->bytes[2], wwn->bytes[3],
133 wwn->bytes[4], wwn->bytes[5], wwn->bytes[6], wwn->bytes[7] );
134 return wwn_text;
135}
uint64_t wwn
WWN.
Definition edd.h:1
#define FC_NAME_STRLEN
Length of Fibre Channel name text.
Definition fc.h:35

References FC_NAME_STRLEN, snprintf(), and wwn.

Referenced by fc_els_flogi_rx(), fc_els_logo_rx_request(), fc_els_plogi_rx(), fc_ns_query(), fc_ns_query_deliver(), fc_peer_close(), fc_peer_create(), fc_peer_examine(), fc_peer_login(), fc_peer_logout(), fc_peer_plogi(), fc_port_login(), fc_port_open(), fc_ulp_close(), fc_ulp_create(), fc_ulp_examine(), fc_ulp_login(), fc_ulp_logout(), fcoe_probe(), fcpdev_open(), fcpeerstat(), and fcportstat().

◆ fc_aton()

int fc_aton ( const char * wwn_text,
struct fc_name * wwn )

Parse Fibre Channel WWN.

Parameters
wwn_textWWN text
Return values
wwnFibre Channel WWN
rcReturn status code

Definition at line 144 of file fc.c.

144 {
145 char *ptr = ( ( char * ) wwn_text );
146 unsigned int i = 0;
147
148 while ( 1 ) {
149 wwn->bytes[i++] = strtoul ( ptr, &ptr, 16 );
150 if ( i == sizeof ( wwn->bytes ) )
151 return ( ( *ptr == '\0' ) ? 0 : -EINVAL );
152 if ( *ptr != ':' )
153 return -EINVAL;
154 ptr++;
155 }
156}

References EINVAL, strtoul(), and wwn.

Referenced by fcp_parse_uri().

◆ fc_fill_sockaddr()

struct sockaddr * fc_fill_sockaddr ( struct sockaddr_fc * sa_fc,
struct fc_port_id * id )

Fill Fibre Channel socket address.

Parameters
sa_fcFibre Channel socket address to fill in
idFibre Channel port ID
Return values
saSocket address

Definition at line 165 of file fc.c.

166 {
167 union {
168 struct sockaddr sa;
169 struct sockaddr_fc fc;
170 } *u = container_of ( sa_fc, typeof ( *u ), fc );
171
172 memset ( sa_fc, 0, sizeof ( *sa_fc ) );
173 sa_fc->sfc_family = AF_FC;
174 memcpy ( &sa_fc->sfc_port_id, id, sizeof ( sa_fc->sfc_port_id ) );
175 return &u->sa;
176}
typeof(acpi_finder=acpi_find)
ACPI table finder.
Definition acpi.c:48
union @104331263140136355135267063077374276003064103115 u
#define AF_FC
Fibre Channel addresses.
Definition socket.h:66
u16 fc
802.11 Frame Control field
Definition ieee80211.h:0
void * memcpy(void *dest, const void *src, size_t len) __nonnull
void * memset(void *dest, int character, size_t len) __nonnull
#define container_of(ptr, type, field)
Get containing structure.
Definition stddef.h:36
Fibre Channel socket address.
Definition fc.h:48
sa_family_t sfc_family
Socket address family (part of struct sockaddr)
Definition fc.h:53
struct fc_port_id sfc_port_id
Port ID.
Definition fc.h:55
Generalized socket address structure.
Definition socket.h:97
struct sockaddr sa
Definition syslog.c:57

References AF_FC, container_of, fc, memcpy(), memset(), sa, sockaddr_fc::sfc_family, sockaddr_fc::sfc_port_id, typeof(), and u.

Referenced by fc_els_tx(), and fc_xchg_rx().

◆ fc_link_up()

void fc_link_up ( struct fc_link_state * link)
static

Mark Fibre Channel link as up.

Parameters
linkFibre Channel link state monitor

Definition at line 195 of file fc.c.

195 {
196
197 /* Stop retry timer */
198 stop_timer ( &link->timer );
199
200 /* Record link state */
201 link->rc = 0;
202}
u32 link
Link to next descriptor.
Definition ar9003_mac.h:1
void stop_timer(struct retry_timer *timer)
Stop timer.
Definition retry.c:118

References link, and stop_timer().

Referenced by fc_peer_login(), fc_port_login(), and fc_ulp_login().

◆ fc_link_err()

void fc_link_err ( struct fc_link_state * link,
int rc )
static

Mark Fibre Channel link as down.

Parameters
linkFibre Channel link state monitor
rcLink state

Definition at line 210 of file fc.c.

210 {
211
212 /* Record link state */
213 if ( rc == 0 )
215 link->rc = rc;
216
217 /* Schedule another link examination */
219}
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
#define EUNKNOWN_LINK_STATUS
Default link status code.
Definition fc.c:186
#define FC_LINK_RETRY_DELAY
Delay between failed link-up attempts.
Definition fc.h:87
void start_timer_fixed(struct retry_timer *timer, unsigned long timeout)
Start timer with a specified timeout.
Definition retry.c:65

References EUNKNOWN_LINK_STATUS, FC_LINK_RETRY_DELAY, link, rc, and start_timer_fixed().

Referenced by fc_peer_logout(), fc_port_logout(), and fc_ulp_logout().

◆ fc_link_examine()

void fc_link_examine ( struct fc_link_state * link)
static

Examine Fibre Channel link state.

Parameters
linkFibre Channel link state monitor

Definition at line 226 of file fc.c.

226 {
227
228 link->examine ( link );
229}

References link.

Referenced by fc_link_expired(), fc_peer_login(), fc_peer_logout(), fc_port_login(), and fc_port_logout().

◆ fc_link_expired()

void fc_link_expired ( struct retry_timer * timer,
int over __unused )
static

Handle Fibre Channel link retry timer expiry.

Definition at line 234 of file fc.c.

234 {
235 struct fc_link_state *link =
237
238 /* Schedule another link examination */
240
241 /* Examine link */
243}
static void fc_link_examine(struct fc_link_state *link)
Examine Fibre Channel link state.
Definition fc.c:226
A timer.
Definition timer.h:29

References __unused, container_of, fc_link_examine(), FC_LINK_RETRY_DELAY, link, and start_timer_fixed().

Referenced by fc_link_init().

◆ fc_link_init()

void fc_link_init ( struct fc_link_state * link,
void(* examine )(struct fc_link_state *link),
struct refcnt * refcnt )
static

Initialise Fibre Channel link state monitor.

Parameters
linkFibre Channel link state monitor
examineExamine link state method
refcntReference counter

Definition at line 252 of file fc.c.

254 {
255
257 timer_init ( &link->timer, fc_link_expired, refcnt );
258 link->examine = examine;
259}
static void fc_link_expired(struct retry_timer *timer, int over __unused)
Handle Fibre Channel link retry timer expiry.
Definition fc.c:234
A reference counter.
Definition refcnt.h:27

References EUNKNOWN_LINK_STATUS, fc_link_state::examine, fc_link_expired(), and link.

Referenced by fc_peer_create(), fc_port_open(), and fc_ulp_create().

◆ fc_link_start()

void fc_link_start ( struct fc_link_state * link)
static

Start monitoring Fibre Channel link state.

Parameters
linkFibre Channel link state monitor

Definition at line 266 of file fc.c.

266 {
267 start_timer_nodelay ( &link->timer );
268}
static void start_timer_nodelay(struct retry_timer *timer)
Start timer with no delay.
Definition retry.h:100

References link, and start_timer_nodelay().

Referenced by fc_peer_create(), fc_port_window_changed(), fc_ulp_create(), and fc_ulp_login().

◆ fc_link_stop()

void fc_link_stop ( struct fc_link_state * link)
static

Stop monitoring Fibre Channel link state.

Parameters
linkFibre Channel link state monitor

Definition at line 275 of file fc.c.

275 {
276 stop_timer ( &link->timer );
277}

References link, and stop_timer().

Referenced by fc_peer_close(), fc_port_close(), fc_port_window_changed(), fc_ulp_close(), and fc_ulp_login().

◆ fc_new_xchg_id()

unsigned int fc_new_xchg_id ( void )
static

Create local Fibre Channel exchange identifier.

Return values
xchg_idLocal exchange ID

Definition at line 335 of file fc.c.

335 {
336 static uint16_t next_id = 0x0000;
337
338 /* We must avoid using FC_RX_ID_UNKNOWN (0xffff) */
339 next_id += 2;
340 return next_id;
341}
unsigned short uint16_t
Definition stdint.h:11

Referenced by fc_xchg_create().

◆ fc_new_seq_id()

unsigned int fc_new_seq_id ( void )
static

Create local Fibre Channel sequence identifier.

Return values
seq_idLocal sequence identifier

Definition at line 348 of file fc.c.

348 {
349 static uint8_t seq_id = 0x00;
350
351 return (++seq_id);
352}
unsigned char uint8_t
Definition stdint.h:10

Referenced by fc_xchg_create(), and fc_xchg_rx().

◆ fc_xchg_free()

void fc_xchg_free ( struct refcnt * refcnt)
static

Free Fibre Channel exchange.

Parameters
refcntReference count

Definition at line 359 of file fc.c.

359 {
360 struct fc_exchange *xchg =
362
363 assert ( ! timer_running ( &xchg->timer ) );
364 assert ( list_empty ( &xchg->list ) );
365
366 fc_port_put ( xchg->port );
367 free ( xchg );
368}
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:50
static void fc_port_put(struct fc_port *port)
Drop reference to Fibre Channel port.
Definition fc.h:316
#define list_empty(list)
Test whether a list is empty.
Definition list.h:137
static void(* free)(struct refcnt *refcnt))
Definition refcnt.h:55
A Fibre Channel exchange.
Definition fc.c:287
struct fc_port * port
Fibre Channel port.
Definition fc.c:291
struct retry_timer timer
Timeout timer.
Definition fc.c:311
struct list_head list
List of active exchanges within this port.
Definition fc.c:293

References assert, container_of, fc_port_put(), free, fc_exchange::list, list_empty, fc_exchange::port, and fc_exchange::timer.

Referenced by fc_xchg_create().

◆ fc_xchg_close()

void fc_xchg_close ( struct fc_exchange * xchg,
int rc )
static

Close Fibre Channel exchange.

Parameters
xchgFibre Channel exchange
rcReason for close

Definition at line 376 of file fc.c.

376 {
377 struct fc_port *port = xchg->port;
378
379 if ( rc != 0 ) {
380 DBGC2 ( port, "FCXCHG %s/%04x closed: %s\n",
381 port->name, xchg->xchg_id, strerror ( rc ) );
382 }
383
384 /* Stop timer */
385 stop_timer ( &xchg->timer );
386
387 /* If list still holds a reference, remove from list of open
388 * exchanges and drop list's reference.
389 */
390 if ( ! list_empty ( &xchg->list ) ) {
391 list_del ( &xchg->list );
392 INIT_LIST_HEAD ( &xchg->list );
393 ref_put ( &xchg->refcnt );
394 }
395
396 /* Shutdown interfaces */
397 intf_shutdown ( &xchg->ulp, rc );
398}
u8 port
Port number.
Definition CIB_PRM.h:3
#define DBGC2(...)
Definition compiler.h:522
void intf_shutdown(struct interface *intf, int rc)
Shut down an object interface.
Definition interface.c:279
#define list_del(list)
Delete an entry from a list.
Definition list.h:120
#define INIT_LIST_HEAD(list)
Initialise a list head.
Definition list.h:46
#define ref_put(refcnt)
Drop reference to object.
Definition refcnt.h:107
char * strerror(int errno)
Retrieve string representation of error number.
Definition strerror.c:79
struct refcnt refcnt
Reference count.
Definition fc.c:289
struct interface ulp
Upper-layer protocol interface.
Definition fc.c:314
uint16_t xchg_id
Local exchange ID.
Definition fc.c:302
A Fibre Channel port.
Definition fc.h:253

References DBGC2, INIT_LIST_HEAD, intf_shutdown(), fc_exchange::list, list_del, list_empty, fc_exchange::port, port, rc, ref_put, fc_exchange::refcnt, stop_timer(), strerror(), fc_exchange::timer, fc_exchange::ulp, and fc_exchange::xchg_id.

Referenced by fc_port_close(), fc_xchg_expired(), and fc_xchg_rx().

◆ fc_xchg_expired()

void fc_xchg_expired ( struct retry_timer * timer,
int over __unused )
static

Handle exchange timeout.

Parameters
timerTimeout timer
overFailure indicator

Definition at line 406 of file fc.c.

406 {
407 struct fc_exchange *xchg =
408 container_of ( timer, struct fc_exchange, timer );
409 struct fc_port *port = xchg->port;
410
411 DBGC ( port, "FCXCHG %s/%04x timed out\n", port->name, xchg->xchg_id );
412
413 /* Terminate the exchange */
414 fc_xchg_close ( xchg, -ETIMEDOUT );
415}
static void fc_xchg_close(struct fc_exchange *xchg, int rc)
Close Fibre Channel exchange.
Definition fc.c:376
#define DBGC(...)
Definition compiler.h:505
#define ETIMEDOUT
Connection timed out.
Definition errno.h:670

References __unused, container_of, DBGC, ETIMEDOUT, fc_xchg_close(), fc_exchange::port, port, and fc_exchange::xchg_id.

Referenced by fc_xchg_create().

◆ fc_xchg_window()

size_t fc_xchg_window ( struct fc_exchange *xchg __unused)
static

Check Fibre Channel exchange window.

Parameters
xchgFibre Channel exchange
Return values
lenLength opf window

Definition at line 423 of file fc.c.

423 {
424
425 /* We don't currently store the path MTU */
427}
#define FC_LOGIN_DEFAULT_MTU
Fibre Channel default MTU.
Definition fcels.h:169

References __unused, and FC_LOGIN_DEFAULT_MTU.

◆ fc_xchg_alloc_iob()

struct io_buffer * fc_xchg_alloc_iob ( struct fc_exchange * xchg,
size_t len )
static

Allocate Fibre Channel I/O buffer.

Parameters
xchgFibre Channel exchange
lenPayload length
Return values
iobufI/O buffer, or NULL

Definition at line 436 of file fc.c.

437 {
438 struct fc_port *port = xchg->port;
439 struct io_buffer *iobuf;
440
441 iobuf = xfer_alloc_iob ( &port->transport,
442 ( sizeof ( struct fc_frame_header ) + len ) );
443 if ( iobuf ) {
444 iob_reserve ( iobuf, sizeof ( struct fc_frame_header ) );
445 }
446 return iobuf;
447}
ring len
Length.
Definition dwmac.h:226
#define iob_reserve(iobuf, len)
Definition iobuf.h:72
A Fibre Channel Frame Header.
Definition fc.h:121
A persistent I/O buffer.
Definition iobuf.h:38
struct io_buffer * xfer_alloc_iob(struct interface *intf, size_t len)
Allocate I/O buffer.
Definition xfer.c:159

References iob_reserve, len, fc_exchange::port, port, and xfer_alloc_iob().

◆ fc_xchg_tx()

int fc_xchg_tx ( struct fc_exchange * xchg,
struct io_buffer * iobuf,
struct xfer_metadata * meta )
static

Transmit data as part of a Fibre Channel exchange.

Parameters
xchgFibre Channel exchange
iobufI/O buffer
metaData transfer metadata
Return values
rcReturn status code

Definition at line 457 of file fc.c.

458 {
459 struct fc_port *port = xchg->port;
460 struct sockaddr_fc *dest = ( ( struct sockaddr_fc * ) meta->dest );
461 struct fc_frame_header *fchdr;
462 unsigned int r_ctl;
463 unsigned int f_ctl_es;
464 int rc;
465
466 /* Sanity checks */
467 if ( ! ( xchg->flags & FC_XCHG_SEQ_INITIATIVE ) ) {
468 DBGC ( port, "FCXCHG %s/%04x cannot transmit while not "
469 "holding sequence initiative\n",
470 port->name, xchg->xchg_id );
471 rc = -EBUSY;
472 goto done;
473 }
474
475 /* Calculate routing control */
476 switch ( xchg->type ) {
477 case FC_TYPE_ELS:
479 if ( meta->flags & XFER_FL_RESPONSE ) {
481 } else {
483 }
484 break;
485 case FC_TYPE_CT:
487 if ( meta->flags & XFER_FL_RESPONSE ) {
489 } else {
491 }
492 break;
493 default:
495 switch ( meta->flags &
499 break;
500 case ( XFER_FL_CMD_STAT ):
502 break;
503 case ( XFER_FL_RESPONSE ):
505 break;
506 default:
508 break;
509 }
510 break;
511 }
512
513 /* Calculate exchange and sequence control */
514 f_ctl_es = 0;
515 if ( ! ( xchg->flags & FC_XCHG_ORIGINATOR ) )
517 if ( xchg->flags & FC_XCHG_SEQ_FIRST )
519 if ( meta->flags & XFER_FL_OUT )
521 if ( meta->flags & XFER_FL_OVER )
523
524 /* Create frame header */
525 fchdr = iob_push ( iobuf, sizeof ( *fchdr ) );
526 memset ( fchdr, 0, sizeof ( *fchdr ) );
527 fchdr->r_ctl = r_ctl;
528 memcpy ( &fchdr->d_id,
529 ( dest ? &dest->sfc_port_id : &xchg->peer_port_id ),
530 sizeof ( fchdr->d_id ) );
531 memcpy ( &fchdr->s_id, &port->port_id, sizeof ( fchdr->s_id ) );
532 fchdr->type = xchg->type;
533 fchdr->f_ctl_es = f_ctl_es;
534 fchdr->seq_id = xchg->seq_id;
535 fchdr->seq_cnt = htons ( xchg->seq_cnt++ );
536 fchdr->ox_id = htons ( ( xchg->flags & FC_XCHG_ORIGINATOR ) ?
537 xchg->xchg_id : xchg->peer_xchg_id );
538 fchdr->rx_id = htons ( ( xchg->flags & FC_XCHG_ORIGINATOR ) ?
539 xchg->peer_xchg_id : xchg->xchg_id );
540 if ( meta->flags & XFER_FL_ABS_OFFSET ) {
542 fchdr->parameter = htonl ( meta->offset );
543 }
544
545 /* Relinquish sequence initiative if applicable */
546 if ( meta->flags & XFER_FL_OVER ) {
548 xchg->seq_cnt = 0;
549 }
550
551 /* Reset timeout */
553
554 /* Deliver frame */
555 if ( ( rc = xfer_deliver_iob ( &port->transport,
556 iob_disown ( iobuf ) ) ) != 0 ) {
557 DBGC ( port, "FCXCHG %s/%04x cannot transmit: %s\n",
558 port->name, xchg->xchg_id, strerror ( rc ) );
559 goto done;
560 }
561
562 done:
563 free_iob ( iobuf );
564 return rc;
565}
if(len >=6 *4) __asm__ __volatile__("movsl" if(len >=5 *4) __asm__ __volatile__("movsl" if(len >=4 *4) __asm__ __volatile__("movsl" if(len >=3 *4) __asm__ __volatile__("movsl" if(len >=2 *4) __asm__ __volatile__("movsl" if(len >=1 *4) __asm__ __volatile__("movsl" if((len % 4) >=2) __asm__ __volatile__("movsw" if((len % 2) >=1) __asm__ __volatile__("movsb" retur dest)
Definition string.h:151
struct bofm_section_header done
Definition bofm_test.c:46
uint8_t meta
Metadata flags.
Definition ena.h:3
#define FC_TIMEOUT
Fibre Channel timeout.
Definition fc.c:328
@ FC_R_CTL_DATA
Device Data.
Definition fc.h:162
@ FC_R_CTL_ELS
Extended Link Services.
Definition fc.h:163
@ FC_TYPE_CT
Common Transport.
Definition fc.h:195
@ FC_TYPE_ELS
Extended Link Service.
Definition fc.h:193
@ FC_R_CTL_UNSOL_DATA
Unsolicited Data.
Definition fc.h:181
@ FC_R_CTL_UNSOL_CTRL
Unsolicited Control.
Definition fc.h:179
@ FC_R_CTL_UNSOL_CMD
Unsolicited Command.
Definition fc.h:183
@ FC_R_CTL_SOL_DATA
Solicited Data.
Definition fc.h:178
@ FC_R_CTL_CMD_STAT
Command Status.
Definition fc.h:184
@ FC_R_CTL_SOL_CTRL
Solicited Control.
Definition fc.h:180
@ FC_F_CTL_ES_FIRST
First Sequence of Exchange.
Definition fc.h:202
@ FC_F_CTL_ES_END
Last Data Frame of Sequence.
Definition fc.h:204
@ FC_F_CTL_ES_TRANSFER
Transfer Sequence Initiative.
Definition fc.h:205
@ FC_F_CTL_ES_LAST
Last Sequence of Exchange.
Definition fc.h:203
@ FC_F_CTL_ES_RESPONDER
Responder of Exchange.
Definition fc.h:200
@ FC_F_CTL_MISC_REL_OFF
Relative Offset Present.
Definition fc.h:210
#define EBUSY
Device or resource busy.
Definition errno.h:339
#define htonl(value)
Definition byteswap.h:134
#define htons(value)
Definition byteswap.h:136
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition iobuf.c:153
#define iob_push(iobuf, len)
Definition iobuf.h:89
#define iob_disown(iobuf)
Disown an I/O buffer.
Definition iobuf.h:217
uint16_t seq_cnt
Active sequence count.
Definition fc.c:308
unsigned int type
Data structure type.
Definition fc.c:298
struct fc_port_id peer_port_id
Peer port ID.
Definition fc.c:296
uint16_t peer_xchg_id
Peer exchange ID.
Definition fc.c:304
unsigned int flags
Flags.
Definition fc.c:300
uint8_t seq_id
Active sequence ID.
Definition fc.c:306
uint8_t f_ctl_es
Frame control - exchange and sequence.
Definition fc.h:137
struct fc_port_id d_id
Destination ID.
Definition fc.h:129
uint16_t rx_id
Responder exchange ID.
Definition fc.h:151
uint8_t type
Data structure type.
Definition fc.h:135
uint8_t f_ctl_misc
Frame control - miscellaneous.
Definition fc.h:141
uint32_t parameter
Parameter.
Definition fc.h:157
uint8_t r_ctl
Routing control.
Definition fc.h:127
uint8_t seq_id
Sequence ID.
Definition fc.h:143
struct fc_port_id s_id
Source ID.
Definition fc.h:133
uint16_t seq_cnt
Sequence count.
Definition fc.h:147
uint16_t ox_id
Originator exchange ID.
Definition fc.h:149
int xfer_deliver_iob(struct interface *intf, struct io_buffer *iobuf)
Deliver datagram as I/O buffer without metadata.
Definition xfer.c:256
#define XFER_FL_ABS_OFFSET
Offset is absolute.
Definition xfer.h:48
#define XFER_FL_OVER
Sender is relinquishing use of half-duplex channel.
Definition xfer.h:51
#define XFER_FL_RESPONSE
Data content is a response.
Definition xfer.h:64
#define XFER_FL_CMD_STAT
Data content represents a command or status message.
Definition xfer.h:61
#define XFER_FL_OUT
This is the final data transfer.
Definition xfer.h:54

References fc_frame_header::d_id, DBGC, dest, done, EBUSY, fc_frame_header::f_ctl_es, fc_frame_header::f_ctl_misc, FC_F_CTL_ES_END, FC_F_CTL_ES_FIRST, FC_F_CTL_ES_LAST, FC_F_CTL_ES_RESPONDER, FC_F_CTL_ES_TRANSFER, FC_F_CTL_MISC_REL_OFF, FC_R_CTL_CMD_STAT, FC_R_CTL_DATA, FC_R_CTL_ELS, FC_R_CTL_SOL_CTRL, FC_R_CTL_SOL_DATA, FC_R_CTL_UNSOL_CMD, FC_R_CTL_UNSOL_CTRL, FC_R_CTL_UNSOL_DATA, FC_TIMEOUT, FC_TYPE_CT, FC_TYPE_ELS, FC_XCHG_ORIGINATOR, FC_XCHG_SEQ_FIRST, FC_XCHG_SEQ_INITIATIVE, fc_exchange::flags, free_iob(), htonl, htons, iob_disown, iob_push, memcpy(), memset(), meta, fc_frame_header::ox_id, fc_frame_header::parameter, fc_exchange::peer_port_id, fc_exchange::peer_xchg_id, fc_exchange::port, port, fc_frame_header::r_ctl, rc, fc_frame_header::rx_id, fc_frame_header::s_id, fc_exchange::seq_cnt, fc_frame_header::seq_cnt, fc_exchange::seq_id, fc_frame_header::seq_id, start_timer_fixed(), strerror(), fc_exchange::timer, fc_exchange::type, fc_frame_header::type, fc_exchange::xchg_id, xfer_deliver_iob(), XFER_FL_ABS_OFFSET, XFER_FL_CMD_STAT, XFER_FL_OUT, XFER_FL_OVER, and XFER_FL_RESPONSE.

◆ fc_xchg_rx()

int fc_xchg_rx ( struct fc_exchange * xchg,
struct io_buffer * iobuf,
struct xfer_metadata *meta __unused )
static

Receive data as part of a Fibre Channel exchange.

Parameters
xchgFibre Channel exchange
iobufI/O buffer
metaData transfer metadata
Return values
rcReturn status code

Definition at line 587 of file fc.c.

588 {
589 struct fc_port *port = xchg->port;
590 struct fc_frame_header *fchdr = iobuf->data;
591 struct xfer_metadata fc_meta;
592 struct sockaddr_fc src;
593 struct sockaddr_fc dest;
594 int rc;
595
596 /* Record peer exchange ID */
597 xchg->peer_xchg_id =
598 ntohs ( ( fchdr->f_ctl_es & FC_F_CTL_ES_RESPONDER ) ?
599 fchdr->rx_id : fchdr->ox_id );
600
601 /* Sequence checks */
602 if ( xchg->flags & FC_XCHG_SEQ_INITIATIVE ) {
603 DBGC ( port, "FCXCHG %s/%04x received frame while holding "
604 "sequence initiative\n", port->name, xchg->xchg_id );
605 rc = -EBUSY;
606 goto done;
607 }
608 if ( ntohs ( fchdr->seq_cnt ) != xchg->seq_cnt ) {
609 DBGC ( port, "FCXCHG %s/%04x received out-of-order frame %d "
610 "(expected %d)\n", port->name, xchg->xchg_id,
611 ntohs ( fchdr->seq_cnt ), xchg->seq_cnt );
612 rc = -EPIPE;
613 goto done;
614 }
615 if ( xchg->seq_cnt == 0 )
616 xchg->seq_id = fchdr->seq_id;
617 xchg->seq_cnt++;
618 if ( fchdr->seq_id != xchg->seq_id ) {
619 DBGC ( port, "FCXCHG %s/%04x received frame for incorrect "
620 "sequence %02x (expected %02x)\n", port->name,
621 xchg->xchg_id, fchdr->seq_id, xchg->seq_id );
622 rc = -EPIPE;
623 goto done;
624 }
625
626 /* Check for end of sequence and transfer of sequence initiative */
627 if ( fchdr->f_ctl_es & FC_F_CTL_ES_END ) {
628 xchg->seq_cnt = 0;
629 if ( fchdr->f_ctl_es & FC_F_CTL_ES_TRANSFER ) {
631 xchg->seq_id = fc_new_seq_id();
632 }
633 }
634
635 /* Construct metadata */
636 memset ( &fc_meta, 0, sizeof ( fc_meta ) );
637 fc_meta.flags =
639 if ( fchdr->f_ctl_es & FC_F_CTL_ES_TRANSFER ) {
640 fc_meta.flags |= XFER_FL_OVER;
641 }
642 if ( ( fchdr->f_ctl_es & FC_F_CTL_ES_LAST ) &&
643 ( fchdr->f_ctl_es & FC_F_CTL_ES_END ) ) {
644 fc_meta.flags |= XFER_FL_OUT;
645 }
646 if ( fchdr->f_ctl_misc & FC_F_CTL_MISC_REL_OFF ) {
647 fc_meta.flags |= XFER_FL_ABS_OFFSET;
648 fc_meta.offset = ntohl ( fchdr->parameter );
649 }
650 fc_meta.src = fc_fill_sockaddr ( &src, &fchdr->s_id );
651 fc_meta.dest = fc_fill_sockaddr ( &dest, &fchdr->d_id );
652
653 /* Reset timeout */
655
656 /* Deliver via exchange's ULP interface */
657 iob_pull ( iobuf, sizeof ( *fchdr ) );
658 if ( ( rc = xfer_deliver ( &xchg->ulp, iob_disown ( iobuf ),
659 &fc_meta ) ) != 0 ) {
660 DBGC ( port, "FCXCHG %s/%04x cannot deliver frame: %s\n",
661 port->name, xchg->xchg_id, strerror ( rc ) );
662 goto done;
663 }
664
665 /* Close exchange if applicable */
666 if ( ( fchdr->f_ctl_es & FC_F_CTL_ES_LAST ) &&
667 ( fchdr->f_ctl_es & FC_F_CTL_ES_END ) ) {
668 fc_xchg_close ( xchg, 0 );
669 }
670
671 done:
672 free_iob ( iobuf );
673 return rc;
674}
static const void * src
Definition string.h:48
struct sockaddr * fc_fill_sockaddr(struct sockaddr_fc *sa_fc, struct fc_port_id *id)
Fill Fibre Channel socket address.
Definition fc.c:165
static const uint8_t fc_r_ctl_info_meta_flags[FC_R_CTL_INFO_MASK+1]
Mapping from Fibre Channel routing control information to xfer metadata.
Definition fc.c:568
static unsigned int fc_new_seq_id(void)
Create local Fibre Channel sequence identifier.
Definition fc.c:348
#define FC_R_CTL_INFO_MASK
Fibre Channel Routing Control Information mask.
Definition fc.h:188
#define EPIPE
Broken pipe.
Definition errno.h:620
#define ntohl(value)
Definition byteswap.h:135
#define ntohs(value)
Definition byteswap.h:137
#define iob_pull(iobuf, len)
Definition iobuf.h:107
void * data
Start of data.
Definition iobuf.h:53
Data transfer metadata.
Definition xfer.h:23
int xfer_deliver(struct interface *intf, struct io_buffer *iobuf, struct xfer_metadata *meta)
Deliver datagram.
Definition xfer.c:195

References __unused, fc_frame_header::d_id, io_buffer::data, DBGC, dest, xfer_metadata::dest, done, EBUSY, EPIPE, fc_frame_header::f_ctl_es, fc_frame_header::f_ctl_misc, FC_F_CTL_ES_END, FC_F_CTL_ES_LAST, FC_F_CTL_ES_RESPONDER, FC_F_CTL_ES_TRANSFER, FC_F_CTL_MISC_REL_OFF, fc_fill_sockaddr(), fc_new_seq_id(), FC_R_CTL_INFO_MASK, fc_r_ctl_info_meta_flags, FC_TIMEOUT, fc_xchg_close(), FC_XCHG_SEQ_INITIATIVE, fc_exchange::flags, xfer_metadata::flags, free_iob(), iob_disown, iob_pull, memset(), meta, ntohl, ntohs, xfer_metadata::offset, fc_frame_header::ox_id, fc_frame_header::parameter, fc_exchange::peer_xchg_id, fc_exchange::port, port, fc_frame_header::r_ctl, rc, fc_frame_header::rx_id, fc_frame_header::s_id, fc_exchange::seq_cnt, fc_frame_header::seq_cnt, fc_exchange::seq_id, fc_frame_header::seq_id, src, xfer_metadata::src, start_timer_fixed(), strerror(), fc_exchange::timer, fc_exchange::ulp, fc_exchange::xchg_id, xfer_deliver(), XFER_FL_ABS_OFFSET, XFER_FL_OUT, and XFER_FL_OVER.

Referenced by fc_port_deliver().

◆ fc_xchg_create()

struct fc_exchange * fc_xchg_create ( struct fc_port * port,
struct fc_port_id * peer_port_id,
unsigned int type )
static

Create new Fibre Channel exchange.

Parameters
portFibre Channel port
peer_port_idPeer port ID
Return values
xchgExchange, or NULL

Definition at line 695 of file fc.c.

697 {
698 struct fc_exchange *xchg;
699
700 /* Allocate and initialise structure */
701 xchg = zalloc ( sizeof ( *xchg ) );
702 if ( ! xchg )
703 return NULL;
704 ref_init ( &xchg->refcnt, fc_xchg_free );
705 intf_init ( &xchg->ulp, &fc_xchg_ulp_desc, &xchg->refcnt );
706 timer_init ( &xchg->timer, fc_xchg_expired, &xchg->refcnt );
707 xchg->port = fc_port_get ( port );
709 sizeof ( xchg->peer_port_id ) );
710 xchg->type = type;
711 xchg->xchg_id = fc_new_xchg_id();
713 xchg->seq_id = fc_new_seq_id();
714
715 /* Transfer reference to list of exchanges and return */
716 list_add ( &xchg->list, &port->xchgs );
717 return xchg;
718}
#define NULL
NULL pointer (VOID *)
Definition Base.h:322
uint32_t type
Operating system type.
Definition ena.h:1
static void fc_xchg_free(struct refcnt *refcnt)
Free Fibre Channel exchange.
Definition fc.c:359
static unsigned int fc_new_xchg_id(void)
Create local Fibre Channel exchange identifier.
Definition fc.c:335
static void fc_xchg_expired(struct retry_timer *timer, int over __unused)
Handle exchange timeout.
Definition fc.c:406
static struct interface_descriptor fc_xchg_ulp_desc
Fibre Channel exchange ULP interface descriptor.
Definition fc.c:685
#define FC_RX_ID_UNKNOWN
Responder exchange identifier used before first response.
Definition fc.h:214
static struct fc_port * fc_port_get(struct fc_port *port)
Get reference to Fibre Channel port.
Definition fc.h:305
static void intf_init(struct interface *intf, struct interface_descriptor *desc, struct refcnt *refcnt)
Initialise an object interface.
Definition interface.h:204
#define list_add(new, head)
Add a new entry to the head of a list.
Definition list.h:70
void * zalloc(size_t size)
Allocate cleared memory.
Definition malloc.c:662
#define ref_init(refcnt, free)
Initialise a reference counter.
Definition refcnt.h:65

References fc_new_seq_id(), fc_new_xchg_id(), fc_port_get(), FC_RX_ID_UNKNOWN, fc_xchg_expired(), fc_xchg_free(), fc_xchg_ulp_desc, intf_init(), fc_exchange::list, list_add, memcpy(), NULL, fc_exchange::peer_port_id, fc_exchange::peer_xchg_id, fc_exchange::port, port, ref_init, fc_exchange::refcnt, fc_exchange::seq_id, fc_exchange::timer, fc_exchange::type, type, fc_exchange::ulp, fc_exchange::xchg_id, and zalloc().

Referenced by fc_xchg_originate(), and fc_xchg_respond().

◆ fc_xchg_originate()

int fc_xchg_originate ( struct interface * parent,
struct fc_port * port,
struct fc_port_id * peer_port_id,
unsigned int type )

Originate a new Fibre Channel exchange.

Parameters
parentInterface to which to attach
portFibre Channel port
peer_port_idPeer port ID
Return values
xchg_idExchange ID, or negative error

Definition at line 728 of file fc.c.

729 {
730 struct fc_exchange *xchg;
731
732 /* Allocate and initialise structure */
734 if ( ! xchg )
735 return -ENOMEM;
738
739 DBGC2 ( port, "FCXCHG %s/%04x originating to %s (type %02x)\n",
740 port->name, xchg->xchg_id, fc_id_ntoa ( &xchg->peer_port_id ),
741 xchg->type );
742
743 /* Attach to parent interface and return */
744 intf_plug_plug ( &xchg->ulp, parent );
745 return xchg->xchg_id;
746}
static struct fc_exchange * fc_xchg_create(struct fc_port *port, struct fc_port_id *peer_port_id, unsigned int type)
Create new Fibre Channel exchange.
Definition fc.c:695
const char * fc_id_ntoa(const struct fc_port_id *id)
Format Fibre Channel port ID.
Definition fc.c:92
#define ENOMEM
Not enough space.
Definition errno.h:535
void intf_plug_plug(struct interface *a, struct interface *b)
Plug two object interfaces together.
Definition interface.c:108

References DBGC2, ENOMEM, fc_id_ntoa(), fc_xchg_create(), FC_XCHG_ORIGINATOR, FC_XCHG_SEQ_FIRST, FC_XCHG_SEQ_INITIATIVE, fc_exchange::flags, intf_plug_plug(), fc_exchange::peer_port_id, port, fc_exchange::type, type, fc_exchange::ulp, and fc_exchange::xchg_id.

Referenced by fc_els_step(), fc_ns_query_step(), and fcpdev_scsi_command().

◆ fc_xchg_respond()

struct fc_exchange * fc_xchg_respond ( struct fc_port * port,
struct fc_frame_header * fchdr )
static

Open a new responder Fibre Channel exchange.

Parameters
portFibre Channel port
fchdrFibre Channel frame header
Return values
xchgFibre Channel exchange, or NULL

Definition at line 755 of file fc.c.

756 {
757 struct fc_exchange *xchg;
758 struct fc_responder *responder;
759 unsigned int type = fchdr->type;
760 int rc;
761
762 /* Allocate and initialise structure */
763 xchg = fc_xchg_create ( port, &fchdr->s_id, type );
764 if ( ! xchg )
765 return NULL;
766 xchg->seq_id = fchdr->seq_id;
767
768 DBGC2 ( port, "FCXCHG %s/%04x responding to %s xchg %04x (type "
769 "%02x)\n", port->name, xchg->xchg_id,
770 fc_id_ntoa ( &xchg->peer_port_id ),
771 ntohs ( fchdr->ox_id ), xchg->type );
772
773 /* Find a responder, if any */
774 for_each_table_entry ( responder, FC_RESPONDERS ) {
775 if ( responder->type == type ) {
776 if ( ( rc = responder->respond ( &xchg->ulp, port,
777 &fchdr->d_id,
778 &fchdr->s_id ) ) !=0 ){
779 DBGC ( port, "FCXCHG %s/%04x could not "
780 "respond: %s\n", port->name,
781 xchg->xchg_id, strerror ( rc ) );
782 }
783 }
784 break;
785 }
786
787 /* We may or may not have a ULP attached at this point, but
788 * the exchange does exist.
789 */
790 return xchg;
791}
#define FC_RESPONDERS
Fibre Channel responder table.
Definition fc.h:240
A Fibre Channel responder.
Definition fc.h:223
unsigned int type
Type.
Definition fc.h:225
int(* respond)(struct interface *xchg, struct fc_port *port, struct fc_port_id *port_id, struct fc_port_id *peer_port_id)
Respond to exchange.
Definition fc.h:234
#define for_each_table_entry(pointer, table)
Iterate through all entries within a linker table.
Definition tables.h:386

References fc_frame_header::d_id, DBGC, DBGC2, fc_id_ntoa(), FC_RESPONDERS, fc_xchg_create(), for_each_table_entry, ntohs, NULL, fc_frame_header::ox_id, fc_exchange::peer_port_id, port, rc, fc_responder::respond, fc_frame_header::s_id, fc_exchange::seq_id, fc_frame_header::seq_id, strerror(), fc_exchange::type, fc_frame_header::type, fc_responder::type, type, fc_exchange::ulp, and fc_exchange::xchg_id.

Referenced by fc_port_deliver().

◆ fc_port_close()

void fc_port_close ( struct fc_port * port,
int rc )
static

Close Fibre Channel port.

Parameters
portFibre Channel port
rcReason for close

Definition at line 806 of file fc.c.

806 {
807 struct fc_exchange *xchg;
808 struct fc_exchange *tmp;
809
810 DBGC ( port, "FCPORT %s closed\n", port->name );
811
812 /* Log out port, if necessary */
813 if ( fc_link_ok ( &port->link ) )
815
816 /* Stop link monitor */
817 fc_link_stop ( &port->link );
818
819 /* Shut down interfaces */
820 intf_shutdown ( &port->transport, rc );
821 intf_shutdown ( &port->flogi, rc );
822 intf_shutdown ( &port->ns_plogi, rc );
823
824 /* Shut down any remaining exchanges */
825 list_for_each_entry_safe ( xchg, tmp, &port->xchgs, list )
826 fc_xchg_close ( xchg, rc );
827
828 /* Remove from list of ports */
829 list_del ( &port->list );
830 INIT_LIST_HEAD ( &port->list );
831}
static void fc_link_stop(struct fc_link_state *link)
Stop monitoring Fibre Channel link state.
Definition fc.c:275
void fc_port_logout(struct fc_port *port, int rc)
Log out Fibre Channel port.
Definition fc.c:1039
static int fc_link_ok(struct fc_link_state *link)
Check Fibre Channel link state.
Definition fc.h:109
unsigned long tmp
Definition linux_pci.h:65
#define list_for_each_entry_safe(pos, tmp, head, member)
Iterate over entries in a list, safe against deletion of the current entry.
Definition list.h:459

References DBGC, fc_link_ok(), fc_link_stop(), fc_port_logout(), fc_xchg_close(), INIT_LIST_HEAD, intf_shutdown(), fc_exchange::list, list_del, list_for_each_entry_safe, port, rc, and tmp.

◆ fc_port_demux()

struct fc_exchange * fc_port_demux ( struct fc_port * port,
unsigned int xchg_id )
static

Identify Fibre Channel exchange by local exchange ID.

Parameters
portFibre Channel port
xchg_idLocal exchange ID
Return values
xchgFibre Channel exchange, or NULL

Definition at line 840 of file fc.c.

841 {
842 struct fc_exchange *xchg;
843
844 list_for_each_entry ( xchg, &port->xchgs, list ) {
845 if ( xchg->xchg_id == xchg_id )
846 return xchg;
847 }
848 return NULL;
849}
#define list_for_each_entry(pos, head, member)
Iterate over entries in a list.
Definition list.h:432

References fc_exchange::list, list_for_each_entry, NULL, port, and fc_exchange::xchg_id.

Referenced by fc_port_deliver().

◆ fc_port_deliver()

int fc_port_deliver ( struct fc_port * port,
struct io_buffer * iobuf,
struct xfer_metadata * meta )
static

Handle received frame from Fibre Channel port.

Parameters
portFibre Channel port
iobufI/O buffer
metaData transfer metadata
Return values
rcReturn status code

Definition at line 859 of file fc.c.

860 {
861 struct fc_frame_header *fchdr = iobuf->data;
862 unsigned int xchg_id;
863 struct fc_exchange *xchg;
864 int rc;
865
866 /* Sanity check */
867 if ( iob_len ( iobuf ) < sizeof ( *fchdr ) ) {
868 DBGC ( port, "FCPORT %s received underlength frame (%zd "
869 "bytes)\n", port->name, iob_len ( iobuf ) );
870 rc = -EINVAL;
871 goto err_sanity;
872 }
873
874 /* Verify local port ID */
875 if ( ( memcmp ( &fchdr->d_id, &port->port_id,
876 sizeof ( fchdr->d_id ) ) != 0 ) &&
877 ( memcmp ( &fchdr->d_id, &fc_f_port_id,
878 sizeof ( fchdr->d_id ) ) != 0 ) &&
879 ( memcmp ( &port->port_id, &fc_empty_port_id,
880 sizeof ( port->port_id ) ) != 0 ) ) {
881 DBGC ( port, "FCPORT %s received frame for incorrect port ID "
882 "%s\n", port->name, fc_id_ntoa ( &fchdr->d_id ) );
883 rc = -ENOTCONN;
884 goto err_port_id;
885 }
886
887 /* Demultiplex amongst active exchanges */
889 fchdr->ox_id : fchdr->rx_id );
890 xchg = fc_port_demux ( port, xchg_id );
891
892 /* If we have no active exchange and this frame starts a new
893 * exchange, try to create a new responder exchange
894 */
895 if ( ( fchdr->f_ctl_es & FC_F_CTL_ES_FIRST ) &&
896 ( fchdr->seq_cnt == 0 ) ) {
897
898 /* Create new exchange */
899 xchg = fc_xchg_respond ( port, fchdr );
900 if ( ! xchg ) {
901 DBGC ( port, "FCPORT %s cannot create new exchange\n",
902 port->name );
903 rc = -ENOMEM;
904 goto err_respond;
905 }
906 }
907
908 /* Fail if no exchange exists */
909 if ( ! xchg ) {
910 DBGC ( port, "FCPORT %s xchg %04x unknown\n",
911 port->name, xchg_id );
912 rc = -ENOTCONN;
913 goto err_no_xchg;
914 }
915
916 /* Pass received frame to exchange */
917 ref_get ( &xchg->refcnt );
918 if ( ( rc = fc_xchg_rx ( xchg, iob_disown ( iobuf ), meta ) ) != 0 )
919 goto err_xchg_rx;
920
921 err_xchg_rx:
922 ref_put ( &xchg->refcnt );
923 err_no_xchg:
924 err_respond:
925 err_port_id:
926 err_sanity:
927 free_iob ( iobuf );
928 return rc;
929}
static struct fc_exchange * fc_xchg_respond(struct fc_port *port, struct fc_frame_header *fchdr)
Open a new responder Fibre Channel exchange.
Definition fc.c:755
struct fc_port_id fc_f_port_id
F_Port contoller port ID.
Definition fc.c:68
static int fc_xchg_rx(struct fc_exchange *xchg, struct io_buffer *iobuf, struct xfer_metadata *meta __unused)
Receive data as part of a Fibre Channel exchange.
Definition fc.c:587
struct fc_port_id fc_empty_port_id
Unassigned port ID.
Definition fc.c:65
static struct fc_exchange * fc_port_demux(struct fc_port *port, unsigned int xchg_id)
Identify Fibre Channel exchange by local exchange ID.
Definition fc.c:840
#define ENOTCONN
The socket is not connected.
Definition errno.h:570
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition iobuf.h:160
#define ref_get(refcnt)
Get additional reference to object.
Definition refcnt.h:93
int memcmp(const void *first, const void *second, size_t len)
Compare memory regions.
Definition string.c:115

References fc_frame_header::d_id, io_buffer::data, DBGC, EINVAL, ENOMEM, ENOTCONN, fc_frame_header::f_ctl_es, fc_empty_port_id, FC_F_CTL_ES_FIRST, FC_F_CTL_ES_RESPONDER, fc_f_port_id, fc_id_ntoa(), fc_port_demux(), fc_xchg_respond(), fc_xchg_rx(), free_iob(), iob_disown, iob_len(), memcmp(), meta, ntohs, fc_frame_header::ox_id, port, rc, ref_get, ref_put, fc_exchange::refcnt, fc_frame_header::rx_id, fc_frame_header::seq_cnt, and fc_exchange::xchg_id.

◆ fc_port_login()

int fc_port_login ( struct fc_port * port,
struct fc_port_id * port_id,
const struct fc_name * link_node_wwn,
const struct fc_name * link_port_wwn,
int has_fabric )

Log in Fibre Channel port.

Parameters
portFibre Channel port
port_idLocal port ID
link_node_wwnLink node name
link_port_wwnLink port name
has_fabricLink is to a fabric
Return values
rcReturn status code

Definition at line 941 of file fc.c.

943 {
944 struct fc_peer *peer;
945 struct fc_peer *tmp;
946 int rc;
947
948 /* Perform implicit logout if logged in and details differ */
949 if ( fc_link_ok ( &port->link ) &&
950 ( ( ( !! ( port->flags & FC_PORT_HAS_FABRIC ) ) !=
951 ( !! has_fabric ) ) ||
952 ( memcmp ( &port->link_node_wwn, link_node_wwn,
953 sizeof ( port->link_node_wwn ) ) != 0 ) ||
954 ( memcmp ( &port->link_port_wwn, link_port_wwn,
955 sizeof ( port->link_port_wwn ) ) != 0 ) ||
956 ( has_fabric &&
957 ( memcmp ( &port->port_id, port_id,
958 sizeof ( port->port_id ) ) != 0 ) ) ) ) {
959 fc_port_logout ( port, 0 );
960 }
961
962 /* Log in, if applicable */
963 if ( ! fc_link_ok ( &port->link ) ) {
964
965 /* Record link port name */
966 memcpy ( &port->link_node_wwn, link_node_wwn,
967 sizeof ( port->link_node_wwn ) );
968 memcpy ( &port->link_port_wwn, link_port_wwn,
969 sizeof ( port->link_port_wwn ) );
970 DBGC ( port, "FCPORT %s logged in to %s",
971 port->name, fc_ntoa ( &port->link_node_wwn ) );
972 DBGC ( port, " port %s\n", fc_ntoa ( &port->link_port_wwn ) );
973
974 /* Calculate local (and possibly remote) port IDs */
975 if ( has_fabric ) {
976 port->flags |= FC_PORT_HAS_FABRIC;
977 memcpy ( &port->port_id, port_id,
978 sizeof ( port->port_id ) );
979 } else {
980 port->flags &= ~FC_PORT_HAS_FABRIC;
981 if ( memcmp ( &port->port_wwn, link_port_wwn,
982 sizeof ( port->port_wwn ) ) > 0 ) {
983 memcpy ( &port->port_id, &fc_ptp_high_port_id,
984 sizeof ( port->port_id ) );
985 memcpy ( &port->ptp_link_port_id,
987 sizeof ( port->ptp_link_port_id ) );
988 } else {
989 memcpy ( &port->port_id, &fc_ptp_low_port_id,
990 sizeof ( port->port_id ) );
991 memcpy ( &port->ptp_link_port_id,
993 sizeof ( port->ptp_link_port_id ) );
994 }
995 }
996 DBGC ( port, "FCPORT %s logged in via a %s, with local ID "
997 "%s\n", port->name,
998 ( ( port->flags & FC_PORT_HAS_FABRIC ) ?
999 "fabric" : "point-to-point link" ),
1000 fc_id_ntoa ( &port->port_id ) );
1001 }
1002
1003 /* Log in to name server, if attached to a fabric */
1004 if ( has_fabric && ! ( port->flags & FC_PORT_HAS_NS ) ) {
1005
1006 DBGC ( port, "FCPORT %s attempting login to name server\n",
1007 port->name );
1008
1009 intf_restart ( &port->ns_plogi, -ECANCELED );
1010 if ( ( rc = fc_els_plogi ( &port->ns_plogi, port,
1011 &fc_gs_port_id ) ) != 0 ) {
1012 DBGC ( port, "FCPORT %s could not initiate name "
1013 "server PLOGI: %s\n",
1014 port->name, strerror ( rc ) );
1015 fc_port_logout ( port, rc );
1016 return rc;
1017 }
1018 }
1019
1020 /* Record login */
1021 fc_link_up ( &port->link );
1022
1023 /* Notify peers of link state change */
1025 fc_peer_get ( peer );
1026 fc_link_examine ( &peer->link );
1027 fc_peer_put ( peer );
1028 }
1029
1030 return 0;
1031}
struct fc_port_id fc_ptp_high_port_id
Point-to-point high port ID.
Definition fc.c:77
static void fc_link_up(struct fc_link_state *link)
Mark Fibre Channel link as up.
Definition fc.c:195
struct fc_port_id fc_ptp_low_port_id
Point-to-point low port ID.
Definition fc.c:74
const char * fc_ntoa(const struct fc_name *wwn)
Format Fibre Channel WWN.
Definition fc.c:127
struct fc_port_id fc_gs_port_id
Generic services port ID.
Definition fc.c:71
static void fc_peer_put(struct fc_peer *peer)
Drop reference to Fibre Channel peer.
Definition fc.h:391
@ FC_PORT_HAS_FABRIC
Port is attached to a fabric.
Definition fc.h:293
@ FC_PORT_HAS_NS
Port is logged in to a name server.
Definition fc.h:295
static struct fc_peer * fc_peer_get(struct fc_peer *peer)
Get reference to Fibre Channel peer.
Definition fc.h:380
struct list_head fc_peers
int fc_els_plogi(struct interface *parent, struct fc_port *port, struct fc_port_id *peer_port_id)
Create PLOGI request.
Definition fcels.c:733
#define ECANCELED
Operation canceled.
Definition errno.h:344
void intf_restart(struct interface *intf, int rc)
Shut down and restart an object interface.
Definition interface.c:344
struct mschapv2_challenge peer
Peer challenge.
Definition mschapv2.h:1
A Fibre Channel peer.
Definition fc.h:341
struct list_head list
List of all peers.
Definition fc.h:345
struct fc_port_id port_id
Peer port ID, if known.
Definition fc.h:357

References DBGC, ECANCELED, fc_els_plogi(), fc_gs_port_id, fc_id_ntoa(), fc_link_examine(), fc_link_ok(), fc_link_up(), fc_ntoa(), fc_peer_get(), fc_peer_put(), fc_peers, FC_PORT_HAS_FABRIC, FC_PORT_HAS_NS, fc_port_logout(), fc_ptp_high_port_id, fc_ptp_low_port_id, intf_restart(), fc_peer::list, list_for_each_entry_safe, memcmp(), memcpy(), peer, port, fc_peer::port_id, rc, strerror(), and tmp.

Referenced by fc_els_flogi_rx().

◆ fc_port_logout()

void fc_port_logout ( struct fc_port * port,
int rc )

Log out Fibre Channel port.

Parameters
portFibre Channel port
rcReason for logout

Definition at line 1039 of file fc.c.

1039 {
1040 struct fc_peer *peer;
1041 struct fc_peer *tmp;
1042
1043 DBGC ( port, "FCPORT %s logged out: %s\n",
1044 port->name, strerror ( rc ) );
1045
1046 /* Erase port details */
1047 memset ( &port->port_id, 0, sizeof ( port->port_id ) );
1048 port->flags = 0;
1049
1050 /* Record logout */
1051 fc_link_err ( &port->link, rc );
1052
1053 /* Notify peers of link state change */
1055 fc_peer_get ( peer );
1056 fc_link_examine ( &peer->link );
1057 fc_peer_put ( peer );
1058 }
1059}
static void fc_link_err(struct fc_link_state *link, int rc)
Mark Fibre Channel link as down.
Definition fc.c:210

References DBGC, fc_link_err(), fc_link_examine(), fc_peer_get(), fc_peer_put(), fc_peers, fc_peer::list, list_for_each_entry_safe, memset(), peer, port, rc, strerror(), and tmp.

Referenced by fc_els_logo_logout(), fc_port_close(), fc_port_examine(), fc_port_flogi_done(), fc_port_login(), and fc_port_window_changed().

◆ fc_port_flogi_done()

void fc_port_flogi_done ( struct fc_port * port,
int rc )
static

Handle FLOGI completion.

Parameters
portFibre Channel port
rcReason for completion

Definition at line 1067 of file fc.c.

1067 {
1068
1069 intf_restart ( &port->flogi, rc );
1070
1071 if ( rc != 0 )
1072 fc_port_logout ( port, rc );
1073}

References fc_port_logout(), intf_restart(), port, and rc.

◆ fc_port_ns_plogi_done()

void fc_port_ns_plogi_done ( struct fc_port * port,
int rc )
static

Handle name server PLOGI completion.

Parameters
portFibre Channel port
rcReason for completion

Definition at line 1081 of file fc.c.

1081 {
1082
1083 intf_restart ( &port->ns_plogi, rc );
1084
1085 if ( rc == 0 ) {
1086 port->flags |= FC_PORT_HAS_NS;
1087 DBGC ( port, "FCPORT %s logged in to name server\n",
1088 port->name );
1089 } else {
1090 DBGC ( port, "FCPORT %s could not log in to name server: %s\n",
1091 port->name, strerror ( rc ) );
1092 /* Absence of a name server is not a fatal error */
1093 }
1094}

References DBGC, FC_PORT_HAS_NS, intf_restart(), port, rc, and strerror().

◆ fc_port_examine()

void fc_port_examine ( struct fc_link_state * link)
static

Examine Fibre Channel port link state.

@ link Fibre Channel link state monitor

Definition at line 1101 of file fc.c.

1101 {
1102 struct fc_port *port = container_of ( link, struct fc_port, link );
1103 int rc;
1104
1105 /* Do nothing if already logged in */
1106 if ( fc_link_ok ( &port->link ) )
1107 return;
1108
1109 DBGC ( port, "FCPORT %s attempting login\n", port->name );
1110
1111 /* Try to create FLOGI ELS */
1112 intf_restart ( &port->flogi, -ECANCELED );
1113 if ( ( rc = fc_els_flogi ( &port->flogi, port ) ) != 0 ) {
1114 DBGC ( port, "FCPORT %s could not initiate FLOGI: %s\n",
1115 port->name, strerror ( rc ) );
1116 fc_port_logout ( port, rc );
1117 return;
1118 }
1119}
int fc_els_flogi(struct interface *parent, struct fc_port *port)
Create FLOGI request.
Definition fcels.c:581

References container_of, DBGC, ECANCELED, fc_els_flogi(), fc_link_ok(), fc_port_logout(), intf_restart(), link, port, rc, and strerror().

Referenced by fc_port_open().

◆ fc_port_window_changed()

void fc_port_window_changed ( struct fc_port * port)
static

Handle change of flow control window.

Parameters
portFibre Channel port

Definition at line 1126 of file fc.c.

1126 {
1127 size_t window;
1128
1129 /* Check if transport layer is ready */
1130 window = xfer_window ( &port->transport );
1131 if ( window > 0 ) {
1132
1133 /* Transport layer is ready. Start login if the link
1134 * is not already up.
1135 */
1136 if ( ! fc_link_ok ( &port->link ) )
1137 fc_link_start ( &port->link );
1138
1139 } else {
1140
1141 /* Transport layer is not ready. Log out port and
1142 * wait for transport layer before attempting log in
1143 * again.
1144 */
1146 fc_link_stop ( &port->link );
1147 }
1148}
static void fc_link_start(struct fc_link_state *link)
Start monitoring Fibre Channel link state.
Definition fc.c:266
size_t xfer_window(struct interface *intf)
Check flow control window.
Definition xfer.c:117

References ENOTCONN, fc_link_ok(), fc_link_start(), fc_link_stop(), fc_port_logout(), port, and xfer_window().

◆ fc_port_open()

int fc_port_open ( struct interface * transport,
const struct fc_name * node_wwn,
const struct fc_name * port_wwn,
const char * name )

Create Fibre Channel port.

Parameters
transportTransport interface
nodeFibre Channel node name
portFibre Channel port name
nameSymbolic port name
Return values
rcReturn status code

Definition at line 1189 of file fc.c.

1190 {
1191 struct fc_port *port;
1192
1193 /* Allocate and initialise structure */
1194 port = zalloc ( sizeof ( *port ) );
1195 if ( ! port )
1196 return -ENOMEM;
1197 ref_init ( &port->refcnt, NULL );
1198 intf_init ( &port->transport, &fc_port_transport_desc, &port->refcnt );
1199 fc_link_init ( &port->link, fc_port_examine, &port->refcnt );
1200 intf_init ( &port->flogi, &fc_port_flogi_desc, &port->refcnt );
1201 intf_init ( &port->ns_plogi, &fc_port_ns_plogi_desc, &port->refcnt );
1202 list_add_tail ( &port->list, &fc_ports );
1203 INIT_LIST_HEAD ( &port->xchgs );
1204 memcpy ( &port->node_wwn, node_wwn, sizeof ( port->node_wwn ) );
1205 memcpy ( &port->port_wwn, port_wwn, sizeof ( port->port_wwn ) );
1206 snprintf ( port->name, sizeof ( port->name ), "%s", name );
1207
1208 DBGC ( port, "FCPORT %s opened as %s",
1209 port->name, fc_ntoa ( &port->node_wwn ) );
1210 DBGC ( port, " port %s\n", fc_ntoa ( &port->port_wwn ) );
1211
1212 /* Attach to transport layer, mortalise self, and return */
1213 intf_plug_plug ( &port->transport, transport );
1214 ref_put ( &port->refcnt );
1215 return 0;
1216}
const char * name
Definition ath9k_hw.c:1986
static void fc_port_examine(struct fc_link_state *link)
Examine Fibre Channel port link state.
Definition fc.c:1101
static struct interface_descriptor fc_port_flogi_desc
Fibre Channel port FLOGI interface descriptor.
Definition fc.c:1168
static struct interface_descriptor fc_port_transport_desc
Fibre Channel port transport interface descriptor.
Definition fc.c:1159
static struct interface_descriptor fc_port_ns_plogi_desc
Fibre Channel port name server PLOGI interface descriptor.
Definition fc.c:1177
static void fc_link_init(struct fc_link_state *link, void(*examine)(struct fc_link_state *link), struct refcnt *refcnt)
Initialise Fibre Channel link state monitor.
Definition fc.c:252
struct list_head fc_ports
#define list_add_tail(new, head)
Add a new entry to the tail of a list.
Definition list.h:94
struct fc_name node_wwn
Node name.
Definition fc.h:264
struct fc_name port_wwn
Port name.
Definition fc.h:266
struct interface transport
Transport interface.
Definition fc.h:262

References DBGC, ENOMEM, fc_link_init(), fc_ntoa(), fc_port_examine(), fc_port_flogi_desc, fc_port_ns_plogi_desc, fc_port_transport_desc, fc_ports, INIT_LIST_HEAD, intf_init(), intf_plug_plug(), list_add_tail, memcpy(), name, fc_port::node_wwn, NULL, port, fc_port::port_wwn, ref_init, ref_put, snprintf(), fc_port::transport, and zalloc().

Referenced by fcoe_expired().

◆ fc_port_find()

struct fc_port * fc_port_find ( const char * name)

Find Fibre Channel port by name.

Parameters
nameFibre Channel port name
Return values
portFibre Channel port, or NULL

Definition at line 1224 of file fc.c.

1224 {
1225 struct fc_port *port;
1226
1228 if ( strcmp ( name, port->name ) == 0 )
1229 return port;
1230 }
1231 return NULL;
1232}
int strcmp(const char *first, const char *second)
Compare strings.
Definition string.c:174
struct list_head list
List of all ports.
Definition fc.h:257

References fc_ports, fc_port::list, list_for_each_entry, name, NULL, port, and strcmp().

Referenced by parse_fc_port().

◆ fc_peer_close()

void fc_peer_close ( struct fc_peer * peer,
int rc )
static

Close Fibre Channel peer.

Parameters
peerFibre Channel peer
rcReason for close

Definition at line 1247 of file fc.c.

1247 {
1248
1249 DBGC ( peer, "FCPEER %s closed: %s\n",
1250 fc_ntoa ( &peer->port_wwn ) , strerror ( rc ) );
1251
1252 /* Sanity check */
1253 assert ( list_empty ( &peer->ulps ) );
1254
1255 /* Stop link timer */
1256 fc_link_stop ( &peer->link );
1257
1258 /* Shut down interfaces */
1259 intf_shutdown ( &peer->plogi, rc );
1260
1261 /* Remove from list of peers */
1262 list_del ( &peer->list );
1263 INIT_LIST_HEAD ( &peer->list );
1264}

References assert, DBGC, fc_link_stop(), fc_ntoa(), INIT_LIST_HEAD, intf_shutdown(), list_del, list_empty, peer, rc, and strerror().

Referenced by fc_peer_logout().

◆ fc_peer_increment()

void fc_peer_increment ( struct fc_peer * peer)
static

Increment Fibre Channel peer active usage count.

Parameters
peerFibre Channel peer

Definition at line 1271 of file fc.c.

1271 {
1272
1273 /* Increment our usage count */
1274 peer->usage++;
1275}

References peer.

Referenced by fc_ulp_attach().

◆ fc_peer_decrement()

void fc_peer_decrement ( struct fc_peer * peer)
static

Decrement Fibre Channel peer active usage count.

Parameters
peerFibre Channel peer

Definition at line 1282 of file fc.c.

1282 {
1283
1284 /* Sanity check */
1285 assert ( peer->usage > 0 );
1286
1287 /* Decrement our usage count and log out if we reach zero */
1288 if ( --(peer->usage) == 0 )
1289 fc_peer_logout ( peer, 0 );
1290}
void fc_peer_logout(struct fc_peer *peer, int rc)
Log out Fibre Channel peer.
Definition fc.c:1347

References assert, fc_peer_logout(), and peer.

Referenced by fc_ulp_detach().

◆ fc_peer_login()

int fc_peer_login ( struct fc_peer * peer,
struct fc_port * port,
struct fc_port_id * port_id )

Log in Fibre Channel peer.

Parameters
peerFibre Channel peer
portFibre Channel port
port_idPort ID
Return values
rcReturn status code

Definition at line 1300 of file fc.c.

1301 {
1302 struct fc_ulp *ulp;
1303 struct fc_ulp *tmp;
1304
1305 /* Perform implicit logout if logged in and details differ */
1306 if ( fc_link_ok ( &peer->link ) &&
1307 ( ( peer->port != port ) ||
1308 ( memcmp ( &peer->port_id, port_id,
1309 sizeof ( peer->port_id ) ) !=0 ) ) ) {
1310 fc_peer_logout ( peer, 0 );
1311 }
1312
1313 /* Log in, if applicable */
1314 if ( ! fc_link_ok ( &peer->link ) ) {
1315
1316 /* Record peer details */
1317 assert ( peer->port == NULL );
1318 peer->port = fc_port_get ( port );
1319 memcpy ( &peer->port_id, port_id, sizeof ( peer->port_id ) );
1320 DBGC ( peer, "FCPEER %s logged in via %s as %s\n",
1321 fc_ntoa ( &peer->port_wwn ), peer->port->name,
1322 fc_id_ntoa ( &peer->port_id ) );
1323
1324 /* Add login reference */
1325 fc_peer_get ( peer );
1326 }
1327
1328 /* Record login */
1329 fc_link_up ( &peer->link );
1330
1331 /* Notify ULPs of link state change */
1332 list_for_each_entry_safe ( ulp, tmp, &peer->ulps, list ) {
1333 fc_ulp_get ( ulp );
1334 fc_link_examine ( &ulp->link );
1335 fc_ulp_put ( ulp );
1336 }
1337
1338 return 0;
1339}
static struct fc_ulp * fc_ulp_get(struct fc_ulp *ulp)
Get reference to Fibre Channel upper-layer protocol.
Definition fc.h:475
static void fc_ulp_put(struct fc_ulp *ulp)
Drop reference to Fibre Channel upper-layer protocol.
Definition fc.h:486
A Fibre Channel upper-layer protocol.
Definition fc.h:414
struct fc_link_state link
Link state monitor.
Definition fc.h:428
struct list_head list
List of upper-layer protocols.
Definition fc.h:420

References assert, DBGC, fc_id_ntoa(), fc_link_examine(), fc_link_ok(), fc_link_up(), fc_ntoa(), fc_peer_get(), fc_peer_logout(), fc_port_get(), fc_ulp_get(), fc_ulp_put(), fc_ulp::link, fc_ulp::list, list_for_each_entry_safe, memcmp(), memcpy(), NULL, peer, port, and tmp.

Referenced by fc_els_plogi_rx().

◆ fc_peer_logout()

void fc_peer_logout ( struct fc_peer * peer,
int rc )

Log out Fibre Channel peer.

Parameters
peerFibre Channel peer
rcReason for logout

Definition at line 1347 of file fc.c.

1347 {
1348 struct fc_ulp *ulp;
1349 struct fc_ulp *tmp;
1350
1351 DBGC ( peer, "FCPEER %s logged out: %s\n",
1352 fc_ntoa ( &peer->port_wwn ), strerror ( rc ) );
1353
1354 /* Drop login reference, if applicable */
1355 if ( fc_link_ok ( &peer->link ) )
1356 fc_peer_put ( peer );
1357
1358 /* Erase peer details */
1359 fc_port_put ( peer->port );
1360 peer->port = NULL;
1361
1362 /* Record logout */
1363 fc_link_err ( &peer->link, rc );
1364
1365 /* Notify ULPs of link state change */
1366 list_for_each_entry_safe ( ulp, tmp, &peer->ulps, list ) {
1367 fc_ulp_get ( ulp );
1368 fc_link_examine ( &ulp->link );
1369 fc_ulp_put ( ulp );
1370 }
1371
1372 /* Close peer if there are no active users */
1373 if ( peer->usage == 0 )
1374 fc_peer_close ( peer, rc );
1375}
static void fc_peer_close(struct fc_peer *peer, int rc)
Close Fibre Channel peer.
Definition fc.c:1247

References DBGC, fc_link_err(), fc_link_examine(), fc_link_ok(), fc_ntoa(), fc_peer_close(), fc_peer_put(), fc_port_put(), fc_ulp_get(), fc_ulp_put(), fc_ulp::link, fc_ulp::list, list_for_each_entry_safe, NULL, peer, rc, strerror(), and tmp.

Referenced by fc_els_logo_logout(), fc_peer_decrement(), fc_peer_examine(), fc_peer_login(), fc_peer_plogi(), and fc_peer_plogi_done().

◆ fc_peer_plogi_done()

void fc_peer_plogi_done ( struct fc_peer * peer,
int rc )
static

Handle PLOGI completion.

Parameters
peerFibre Channel peer
rcReason for completion

Definition at line 1383 of file fc.c.

1383 {
1384
1385 intf_restart ( &peer->plogi, rc );
1386
1387 if ( rc != 0 )
1388 fc_peer_logout ( peer, rc );
1389}

References fc_peer_logout(), intf_restart(), peer, and rc.

◆ fc_peer_plogi()

int fc_peer_plogi ( struct fc_peer * peer,
struct fc_port * port,
struct fc_port_id * peer_port_id )
static

Initiate PLOGI.

Parameters
peerFibre Channel peer
portFibre Channel port
peer_port_idPeer port ID
Return values
rcReturn status code

Definition at line 1399 of file fc.c.

1400 {
1401 int rc;
1402
1403 /* Try to create PLOGI ELS */
1404 intf_restart ( &peer->plogi, -ECANCELED );
1405 if ( ( rc = fc_els_plogi ( &peer->plogi, port, peer_port_id ) ) != 0 ) {
1406 DBGC ( peer, "FCPEER %s could not initiate PLOGI: %s\n",
1407 fc_ntoa ( &peer->port_wwn ), strerror ( rc ) );
1408 fc_peer_logout ( peer, rc );
1409 return rc;
1410 }
1411
1412 return 0;
1413}

References DBGC, ECANCELED, fc_els_plogi(), fc_ntoa(), fc_peer_logout(), intf_restart(), peer, port, rc, and strerror().

Referenced by fc_peer_examine().

◆ fc_peer_examine()

void fc_peer_examine ( struct fc_link_state * link)
static

Examine Fibre Channel peer link state.

@ link Fibre Channel link state monitor

Definition at line 1420 of file fc.c.

1420 {
1421 struct fc_peer *peer = container_of ( link, struct fc_peer, link );
1422 struct fc_port *port;
1423 int rc;
1424
1425 /* Check to see if underlying port link has gone down */
1426 if ( peer->port && ( ! fc_link_ok ( &peer->port->link ) ) ) {
1428 return;
1429 }
1430
1431 /* Do nothing if already logged in */
1432 if ( fc_link_ok ( &peer->link ) )
1433 return;
1434
1435 DBGC ( peer, "FCPEER %s attempting login\n",
1436 fc_ntoa ( &peer->port_wwn ) );
1437
1438 /* Sanity check */
1439 assert ( peer->port == NULL );
1440
1441 /* First, look for a port with the peer attached via a
1442 * point-to-point link.
1443 */
1445 if ( fc_link_ok ( &port->link ) &&
1446 ( ! ( port->flags & FC_PORT_HAS_FABRIC ) ) &&
1447 ( memcmp ( &peer->port_wwn, &port->link_port_wwn,
1448 sizeof ( peer->port_wwn ) ) == 0 ) ) {
1449 /* Use this peer port ID, and stop looking */
1450 fc_peer_plogi ( peer, port, &port->ptp_link_port_id );
1451 return;
1452 }
1453 }
1454
1455 /* If the peer is not directly attached, try initiating a name
1456 * server lookup on any suitable ports.
1457 */
1459 if ( fc_link_ok ( &port->link ) &&
1460 ( port->flags & FC_PORT_HAS_FABRIC ) &&
1461 ( port->flags & FC_PORT_HAS_NS ) ) {
1462 if ( ( rc = fc_ns_query ( peer, port,
1463 fc_peer_plogi ) ) != 0 ) {
1464 DBGC ( peer, "FCPEER %s could not attempt "
1465 "name server lookup on %s: %s\n",
1466 fc_ntoa ( &peer->port_wwn ), port->name,
1467 strerror ( rc ) );
1468 /* Non-fatal */
1469 }
1470 }
1471 }
1472}
static int fc_peer_plogi(struct fc_peer *peer, struct fc_port *port, struct fc_port_id *peer_port_id)
Initiate PLOGI.
Definition fc.c:1399
A Fibre Channel name server query.
Definition fcns.c:45

References assert, container_of, DBGC, ENOTCONN, fc_link_ok(), fc_ntoa(), fc_peer_logout(), fc_peer_plogi(), FC_PORT_HAS_FABRIC, FC_PORT_HAS_NS, fc_ports, link, fc_port::list, list_for_each_entry, memcmp(), NULL, peer, port, rc, and strerror().

Referenced by fc_peer_create().

◆ fc_peer_create()

struct fc_peer * fc_peer_create ( const struct fc_name * port_wwn)
static

Create Fibre Channel peer.

Parameters
port_wwnNode name
Return values
peerFibre Channel peer, or NULL

Definition at line 1489 of file fc.c.

1489 {
1490 struct fc_peer *peer;
1491
1492 /* Allocate and initialise structure */
1493 peer = zalloc ( sizeof ( *peer ) );
1494 if ( ! peer )
1495 return NULL;
1496 ref_init ( &peer->refcnt, NULL );
1497 fc_link_init ( &peer->link, fc_peer_examine, &peer->refcnt );
1498 intf_init ( &peer->plogi, &fc_peer_plogi_desc, &peer->refcnt );
1499 list_add_tail ( &peer->list, &fc_peers );
1500 memcpy ( &peer->port_wwn, port_wwn, sizeof ( peer->port_wwn ) );
1501 INIT_LIST_HEAD ( &peer->ulps );
1502
1503 /* Start link monitor */
1504 fc_link_start ( &peer->link );
1505
1506 DBGC ( peer, "FCPEER %s created\n", fc_ntoa ( &peer->port_wwn ) );
1507 return peer;
1508}
static struct interface_descriptor fc_peer_plogi_desc
Fibre Channel peer PLOGI interface descriptor.
Definition fc.c:1480
static void fc_peer_examine(struct fc_link_state *link)
Examine Fibre Channel peer link state.
Definition fc.c:1420
struct fc_name port_wwn
Port name.
Definition fc.h:348

References DBGC, fc_link_init(), fc_link_start(), fc_ntoa(), fc_peer_examine(), fc_peer_plogi_desc, fc_peers, INIT_LIST_HEAD, intf_init(), list_add_tail, memcpy(), NULL, peer, fc_peer::port_wwn, ref_init, and zalloc().

Referenced by fc_peer_get_wwn().

◆ fc_peer_get_wwn()

struct fc_peer * fc_peer_get_wwn ( const struct fc_name * port_wwn)

Get Fibre Channel peer by node name.

Parameters
port_wwnNode name
Return values
peerFibre Channel peer, or NULL

Definition at line 1516 of file fc.c.

1516 {
1517 struct fc_peer *peer;
1518
1519 /* Look for an existing peer */
1521 if ( memcmp ( &peer->port_wwn, port_wwn,
1522 sizeof ( peer->port_wwn ) ) == 0 )
1523 return fc_peer_get ( peer );
1524 }
1525
1526 /* Create a new peer */
1528 if ( ! peer )
1529 return NULL;
1530
1531 return peer;
1532}
static struct fc_peer * fc_peer_create(const struct fc_name *port_wwn)
Create Fibre Channel peer.
Definition fc.c:1489

References fc_peer_create(), fc_peer_get(), fc_peers, fc_peer::list, list_for_each_entry, memcmp(), NULL, peer, and fc_peer::port_wwn.

Referenced by fc_els_plogi_rx(), and fc_ulp_get_wwn_type().

◆ fc_peer_get_port_id()

struct fc_peer * fc_peer_get_port_id ( struct fc_port * port,
const struct fc_port_id * peer_port_id )

Get Fibre Channel peer by port ID.

Parameters
portFibre Channel port
peer_port_idPeer port ID
Return values
peerFibre Channel peer, or NULL

Definition at line 1541 of file fc.c.

1542 {
1543 struct fc_peer *peer;
1544
1545 /* Look for an existing peer */
1547 if ( ( peer->port == port ) &&
1548 ( memcmp ( &peer->port_id, peer_port_id,
1549 sizeof ( peer->port_id ) ) == 0 ) )
1550 return fc_peer_get ( peer );
1551 }
1552
1553 /* Cannot create a new peer, since we have no port name to use */
1554 return NULL;
1555}

References fc_peer_get(), fc_peers, fc_peer::list, list_for_each_entry, memcmp(), NULL, peer, and port.

Referenced by fc_els_logo_logout(), and fc_ulp_get_port_id_type().

◆ fc_ulp_free()

void fc_ulp_free ( struct refcnt * refcnt)
static

Free Fibre Channel upper-layer protocol.

Parameters
refcntReference count

Definition at line 1569 of file fc.c.

1569 {
1570 struct fc_ulp *ulp = container_of ( refcnt, struct fc_ulp, refcnt );
1571
1572 fc_peer_put ( ulp->peer );
1573 free ( ulp );
1574}
struct fc_peer * peer
Fibre Channel peer.
Definition fc.h:418

References container_of, fc_peer_put(), free, and fc_ulp::peer.

Referenced by fc_ulp_create().

◆ fc_ulp_close()

void fc_ulp_close ( struct fc_ulp * ulp,
int rc )
static

Close Fibre Channel upper-layer protocol.

Parameters
ulpFibre Channel upper-layer protocol
rcReason for close

Definition at line 1582 of file fc.c.

1582 {
1583
1584 DBGC ( ulp, "FCULP %s/%02x closed: %s\n",
1585 fc_ntoa ( &ulp->peer->port_wwn ), ulp->type, strerror ( rc ) );
1586
1587 /* Sanity check */
1588 assert ( list_empty ( &ulp->users ) );
1589
1590 /* Stop link monitor */
1591 fc_link_stop ( &ulp->link );
1592
1593 /* Shut down interfaces */
1594 intf_shutdown ( &ulp->prli, rc );
1595
1596 /* Remove from list of ULPs */
1597 list_del ( &ulp->list );
1598 INIT_LIST_HEAD ( &ulp->list );
1599}
unsigned int type
Type.
Definition fc.h:423
struct list_head users
Active users of this upper-layer protocol.
Definition fc.h:444
struct interface prli
PRLI interface.
Definition fc.h:430

References assert, DBGC, fc_link_stop(), fc_ntoa(), INIT_LIST_HEAD, intf_shutdown(), fc_ulp::link, fc_ulp::list, list_del, list_empty, fc_ulp::peer, fc_peer::port_wwn, fc_ulp::prli, rc, strerror(), fc_ulp::type, and fc_ulp::users.

Referenced by fc_ulp_logout().

◆ fc_ulp_attach()

void fc_ulp_attach ( struct fc_ulp * ulp,
struct fc_ulp_user * user )

Attach Fibre Channel upper-layer protocol user.

Parameters
ulpFibre Channel upper-layer protocol
userFibre Channel upper-layer protocol user

Definition at line 1607 of file fc.c.

1607 {
1608
1609 /* Sanity check */
1610 assert ( user->ulp == NULL );
1611
1612 /* Increment peer's usage count */
1613 fc_peer_increment ( ulp->peer );
1614
1615 /* Attach user */
1616 user->ulp = fc_ulp_get ( ulp );
1617 list_add ( &user->list, &ulp->users );
1618}
static void fc_peer_increment(struct fc_peer *peer)
Increment Fibre Channel peer active usage count.
Definition fc.c:1271
struct list_head list
List of users.
Definition fc.h:458
struct fc_ulp * ulp
Fibre Channel upper layer protocol.
Definition fc.h:456

References assert, fc_peer_increment(), fc_ulp_get(), fc_ulp_user::list, list_add, NULL, fc_ulp::peer, fc_ulp_user::ulp, and fc_ulp::users.

Referenced by fcpdev_open().

◆ fc_ulp_detach()

void fc_ulp_detach ( struct fc_ulp_user * user)

Detach Fibre Channel upper-layer protocol user.

Parameters
userFibre Channel upper-layer protocol user

Definition at line 1625 of file fc.c.

1625 {
1626 struct fc_ulp *ulp = user->ulp;
1627
1628 /* Do nothing if not attached */
1629 if ( ! ulp )
1630 return;
1631
1632 /* Sanity checks */
1633 list_check_contains_entry ( user, &ulp->users, list );
1634
1635 /* Detach user and log out if no users remain */
1636 list_del ( &user->list );
1637 if ( list_empty ( &ulp->users ) )
1638 fc_ulp_logout ( ulp, 0 );
1639
1640 /* Decrement our peer's usage count */
1641 fc_peer_decrement ( ulp->peer );
1642
1643 /* Drop reference */
1644 user->ulp = NULL;
1645 fc_ulp_put ( ulp );
1646}
static void fc_peer_decrement(struct fc_peer *peer)
Decrement Fibre Channel peer active usage count.
Definition fc.c:1282
void fc_ulp_logout(struct fc_ulp *ulp, int rc)
Log out Fibre Channel upper-layer protocol.
Definition fc.c:1727
#define list_check_contains_entry(entry, head, member)
Check list contains a specified entry.
Definition list.h:550

References fc_peer_decrement(), fc_ulp_logout(), fc_ulp_put(), fc_ulp::list, fc_ulp_user::list, list_check_contains_entry, list_del, list_empty, NULL, fc_ulp::peer, fc_ulp_user::ulp, and fc_ulp::users.

Referenced by fcpdev_close().

◆ fc_ulp_login()

int fc_ulp_login ( struct fc_ulp * ulp,
const void * param,
size_t param_len,
int originated )

Log in Fibre Channel upper-layer protocol.

Parameters
ulpFibre Channel upper-layer protocol
paramService parameters
param_lenLength of service parameters
originatedLogin was originated by us
Return values
rcReturn status code

Definition at line 1657 of file fc.c.

1658 {
1659 struct fc_ulp_user *user;
1660 struct fc_ulp_user *tmp;
1661
1662 /* Perform implicit logout if logged in and service parameters differ */
1663 if ( fc_link_ok ( &ulp->link ) &&
1664 ( ( ulp->param_len != param_len ) ||
1665 ( memcmp ( ulp->param, param, ulp->param_len ) != 0 ) ) ) {
1666 fc_ulp_logout ( ulp, 0 );
1667 }
1668
1669 /* Work around a bug in some versions of the Linux Fibre
1670 * Channel stack, which fail to fully initialise image pairs
1671 * established via a PRLI originated by the Linux stack
1672 * itself.
1673 */
1674 if ( originated )
1676 if ( ! ( ulp->flags & FC_ULP_ORIGINATED_LOGIN_OK ) ) {
1677 DBGC ( ulp, "FCULP %s/%02x sending extra PRLI to work around "
1678 "Linux bug\n",
1679 fc_ntoa ( &ulp->peer->port_wwn ), ulp->type );
1680 fc_link_stop ( &ulp->link );
1681 fc_link_start ( &ulp->link );
1682 return 0;
1683 }
1684
1685 /* Log in, if applicable */
1686 if ( ! fc_link_ok ( &ulp->link ) ) {
1687
1688 /* Record service parameters */
1689 assert ( ulp->param == NULL );
1690 assert ( ulp->param_len == 0 );
1691 ulp->param = malloc ( param_len );
1692 if ( ! ulp->param ) {
1693 DBGC ( ulp, "FCULP %s/%02x could not record "
1694 "parameters\n",
1695 fc_ntoa ( &ulp->peer->port_wwn ), ulp->type );
1696 return -ENOMEM;
1697 }
1698 memcpy ( ulp->param, param, param_len );
1699 ulp->param_len = param_len;
1700 DBGC ( ulp, "FCULP %s/%02x logged in with parameters:\n",
1701 fc_ntoa ( &ulp->peer->port_wwn ), ulp->type );
1702 DBGC_HDA ( ulp, 0, ulp->param, ulp->param_len );
1703
1704 /* Add login reference */
1705 fc_ulp_get ( ulp );
1706 }
1707
1708 /* Record login */
1709 fc_link_up ( &ulp->link );
1710
1711 /* Notify users of link state change */
1712 list_for_each_entry_safe ( user, tmp, &ulp->users, list ) {
1713 fc_ulp_user_get ( user );
1714 user->examine ( user );
1715 fc_ulp_user_put ( user );
1716 }
1717
1718 return 0;
1719}
static void fc_ulp_user_put(struct fc_ulp_user *user)
Drop reference to Fibre Channel upper-layer protocol user.
Definition fc.h:508
@ FC_ULP_ORIGINATED_LOGIN_OK
A login originated by us has succeeded.
Definition fc.h:450
static struct fc_ulp_user * fc_ulp_user_get(struct fc_ulp_user *user)
Get reference to Fibre Channel upper-layer protocol user.
Definition fc.h:497
#define DBGC_HDA(...)
Definition compiler.h:506
struct hv_monitor_parameter param[4][32]
Parameters.
Definition hyperv.h:13
void * malloc(size_t size)
Allocate memory.
Definition malloc.c:621
A Fibre Channel upper-layer protocol user.
Definition fc.h:454
void(* examine)(struct fc_ulp_user *user)
Examine link state.
Definition fc.h:465
unsigned int flags
Flags.
Definition fc.h:425
size_t param_len
Service parameter length.
Definition fc.h:434
void * param
Service parameters, if any.
Definition fc.h:432

References assert, DBGC, DBGC_HDA, ENOMEM, fc_ulp_user::examine, fc_link_ok(), fc_link_start(), fc_link_stop(), fc_link_up(), fc_ntoa(), fc_ulp_get(), fc_ulp_logout(), FC_ULP_ORIGINATED_LOGIN_OK, fc_ulp_user_get(), fc_ulp_user_put(), fc_ulp::flags, fc_ulp::link, fc_ulp_user::list, list_for_each_entry_safe, malloc(), memcmp(), memcpy(), NULL, fc_ulp::param, param, fc_ulp::param_len, fc_ulp::peer, fc_peer::port_wwn, tmp, fc_ulp::type, fc_ulp_user::ulp, and fc_ulp::users.

Referenced by fc_els_prli_rx().

◆ fc_ulp_logout()

void fc_ulp_logout ( struct fc_ulp * ulp,
int rc )

Log out Fibre Channel upper-layer protocol.

Parameters
ulpFibre Channel upper-layer protocol
rcReason for logout

Definition at line 1727 of file fc.c.

1727 {
1728 struct fc_ulp_user *user;
1729 struct fc_ulp_user *tmp;
1730
1731 DBGC ( ulp, "FCULP %s/%02x logged out: %s\n",
1732 fc_ntoa ( &ulp->peer->port_wwn ), ulp->type, strerror ( rc ) );
1733
1734 /* Drop login reference, if applicable */
1735 if ( fc_link_ok ( &ulp->link ) )
1736 fc_ulp_put ( ulp );
1737
1738 /* Discard service parameters */
1739 free ( ulp->param );
1740 ulp->param = NULL;
1741 ulp->param_len = 0;
1742 ulp->flags = 0;
1743
1744 /* Record logout */
1745 fc_link_err ( &ulp->link, rc );
1746
1747 /* Notify users of link state change */
1748 list_for_each_entry_safe ( user, tmp, &ulp->users, list ) {
1749 fc_ulp_user_get ( user );
1750 user->examine ( user );
1751 fc_ulp_user_put ( user );
1752 }
1753
1754 /* Close ULP if there are no clients attached */
1755 if ( list_empty ( &ulp->users ) )
1756 fc_ulp_close ( ulp, rc );
1757}
static void fc_ulp_close(struct fc_ulp *ulp, int rc)
Close Fibre Channel upper-layer protocol.
Definition fc.c:1582

References DBGC, fc_ulp_user::examine, fc_link_err(), fc_link_ok(), fc_ntoa(), fc_ulp_close(), fc_ulp_put(), fc_ulp_user_get(), fc_ulp_user_put(), fc_ulp::flags, free, fc_ulp::link, fc_ulp_user::list, list_empty, list_for_each_entry_safe, NULL, fc_ulp::param, fc_ulp::param_len, fc_ulp::peer, fc_peer::port_wwn, rc, strerror(), tmp, fc_ulp::type, fc_ulp_user::ulp, and fc_ulp::users.

Referenced by fc_els_prli_rx(), fc_ulp_detach(), fc_ulp_examine(), fc_ulp_login(), and fc_ulp_prli_done().

◆ fc_ulp_prli_done()

void fc_ulp_prli_done ( struct fc_ulp * ulp,
int rc )
static

Handle PRLI completion.

Parameters
ulpFibre Channel upper-layer protocol
rcReason for completion

Definition at line 1765 of file fc.c.

1765 {
1766
1767 intf_restart ( &ulp->prli, rc );
1768
1769 if ( rc != 0 )
1770 fc_ulp_logout ( ulp, rc );
1771}

References fc_ulp_logout(), intf_restart(), fc_ulp::prli, rc, and fc_ulp_user::ulp.

◆ fc_ulp_examine()

void fc_ulp_examine ( struct fc_link_state * link)
static

Examine Fibre Channel upper-layer protocol link state.

@ link Fibre Channel link state monitor

Definition at line 1778 of file fc.c.

1778 {
1779 struct fc_ulp *ulp = container_of ( link, struct fc_ulp, link );
1780 int rc;
1781
1782 /* Check to see if underlying peer link has gone down */
1783 if ( ! fc_link_ok ( &ulp->peer->link ) ) {
1784 fc_ulp_logout ( ulp, -ENOTCONN );
1785 return;
1786 }
1787
1788 /* Do nothing if already logged in */
1789 if ( fc_link_ok ( &ulp->link ) &&
1791 return;
1792
1793 DBGC ( ulp, "FCULP %s/%02x attempting login\n",
1794 fc_ntoa ( &ulp->peer->port_wwn ), ulp->type );
1795
1796 /* Try to create PRLI ELS */
1797 intf_restart ( &ulp->prli, -ECANCELED );
1798 if ( ( rc = fc_els_prli ( &ulp->prli, ulp->peer->port,
1799 &ulp->peer->port_id, ulp->type ) ) != 0 ) {
1800 DBGC ( ulp, "FCULP %s/%02x could not initiate PRLI: %s\n",
1801 fc_ntoa ( &ulp->peer->port_wwn ), ulp->type,
1802 strerror ( rc ) );
1803 fc_ulp_logout ( ulp, rc );
1804 return;
1805 }
1806}
int fc_els_prli(struct interface *parent, struct fc_port *port, struct fc_port_id *peer_port_id, unsigned int type)
Create PRLI request.
Definition fcels.c:1124
struct fc_link_state link
Link state monitor.
Definition fc.h:351
struct fc_port * port
Fibre Channel port, if known.
Definition fc.h:355

References container_of, DBGC, ECANCELED, ENOTCONN, fc_els_prli(), fc_link_ok(), fc_ntoa(), fc_ulp_logout(), FC_ULP_ORIGINATED_LOGIN_OK, fc_ulp::flags, intf_restart(), fc_peer::link, fc_ulp::link, link, fc_ulp::peer, fc_peer::port, fc_peer::port_id, fc_peer::port_wwn, fc_ulp::prli, rc, strerror(), and fc_ulp::type.

Referenced by fc_ulp_create().

◆ fc_ulp_create()

struct fc_ulp * fc_ulp_create ( struct fc_peer * peer,
unsigned int type )
static

Create Fibre Channel upper-layer protocl.

Parameters
peerFibre Channel peer
typeType
Return values
ulpFibre Channel upper-layer protocol, or NULL

Definition at line 1824 of file fc.c.

1825 {
1826 struct fc_ulp *ulp;
1827
1828 /* Allocate and initialise structure */
1829 ulp = zalloc ( sizeof ( *ulp ) );
1830 if ( ! ulp )
1831 return NULL;
1832 ref_init ( &ulp->refcnt, fc_ulp_free );
1833 fc_link_init ( &ulp->link, fc_ulp_examine, &ulp->refcnt );
1834 intf_init ( &ulp->prli, &fc_ulp_prli_desc, &ulp->refcnt );
1835 ulp->peer = fc_peer_get ( peer );
1836 list_add_tail ( &ulp->list, &peer->ulps );
1837 ulp->type = type;
1838 INIT_LIST_HEAD ( &ulp->users );
1839
1840 /* Start link state monitor */
1841 fc_link_start ( &ulp->link );
1842
1843 DBGC ( ulp, "FCULP %s/%02x created\n",
1844 fc_ntoa ( &ulp->peer->port_wwn ), ulp->type );
1845 return ulp;
1846}
static struct interface_descriptor fc_ulp_prli_desc
Fibre Channel upper-layer protocol PRLI interface descriptor.
Definition fc.c:1814
static void fc_ulp_examine(struct fc_link_state *link)
Examine Fibre Channel upper-layer protocol link state.
Definition fc.c:1778
static void fc_ulp_free(struct refcnt *refcnt)
Free Fibre Channel upper-layer protocol.
Definition fc.c:1569
struct refcnt refcnt
Reference count.
Definition fc.h:416

References DBGC, fc_link_init(), fc_link_start(), fc_ntoa(), fc_peer_get(), fc_ulp_examine(), fc_ulp_free(), fc_ulp_prli_desc, INIT_LIST_HEAD, intf_init(), fc_ulp::link, fc_ulp::list, list_add_tail, NULL, fc_ulp::peer, peer, fc_peer::port_wwn, fc_ulp::prli, ref_init, fc_ulp::refcnt, fc_ulp::type, type, fc_ulp::users, and zalloc().

Referenced by fc_ulp_get_type().

◆ fc_ulp_get_type()

struct fc_ulp * fc_ulp_get_type ( struct fc_peer * peer,
unsigned int type )
static

Get Fibre Channel upper-layer protocol by peer and type.

Parameters
peerFibre Channel peer
typeType
Return values
ulpFibre Channel upper-layer protocol, or NULL

Definition at line 1855 of file fc.c.

1856 {
1857 struct fc_ulp *ulp;
1858
1859 /* Look for an existing ULP */
1860 list_for_each_entry ( ulp, &peer->ulps, list ) {
1861 if ( ulp->type == type )
1862 return fc_ulp_get ( ulp );
1863 }
1864
1865 /* Create a new ULP */
1866 ulp = fc_ulp_create ( peer, type );
1867 if ( ! ulp )
1868 return NULL;
1869
1870 return ulp;
1871}
static struct fc_ulp * fc_ulp_create(struct fc_peer *peer, unsigned int type)
Create Fibre Channel upper-layer protocl.
Definition fc.c:1824

References fc_ulp_create(), fc_ulp_get(), fc_ulp::list, list_for_each_entry, NULL, peer, fc_ulp::type, and type.

Referenced by fc_ulp_get_port_id_type(), and fc_ulp_get_wwn_type().

◆ fc_ulp_get_wwn_type()

struct fc_ulp * fc_ulp_get_wwn_type ( const struct fc_name * port_wwn,
unsigned int type )

Get Fibre Channel upper-layer protocol by port name and type.

Parameters
port_wwnPort name
typeType
Return values
ulpFibre Channel upper-layer protocol, or NULL

Definition at line 1880 of file fc.c.

1881 {
1882 struct fc_ulp *ulp;
1883 struct fc_peer *peer;
1884
1885 /* Get peer */
1887 if ( ! peer )
1888 goto err_peer_get_wwn;
1889
1890 /* Get ULP */
1891 ulp = fc_ulp_get_type ( peer, type );
1892 if ( ! ulp )
1893 goto err_ulp_get_type;
1894
1895 /* Drop temporary reference to peer */
1896 fc_peer_put ( peer );
1897
1898 return ulp;
1899
1900 fc_ulp_put ( ulp );
1901 err_ulp_get_type:
1902 fc_peer_put ( peer );
1903 err_peer_get_wwn:
1904 return NULL;
1905}
struct fc_peer * fc_peer_get_wwn(const struct fc_name *port_wwn)
Get Fibre Channel peer by node name.
Definition fc.c:1516
static struct fc_ulp * fc_ulp_get_type(struct fc_peer *peer, unsigned int type)
Get Fibre Channel upper-layer protocol by peer and type.
Definition fc.c:1855

References fc_peer_get_wwn(), fc_peer_put(), fc_ulp_get_type(), fc_ulp_put(), NULL, peer, fc_peer::port_wwn, and type.

Referenced by fcpdev_open().

◆ fc_ulp_get_port_id_type()

struct fc_ulp * fc_ulp_get_port_id_type ( struct fc_port * port,
const struct fc_port_id * peer_port_id,
unsigned int type )

Get Fibre Channel upper-layer protocol by port ID and type.

Parameters
portFibre Channel port
peer_port_idPeer port ID
typeType
Return values
ulpFibre Channel upper-layer protocol, or NULL

Definition at line 1915 of file fc.c.

1917 {
1918 struct fc_ulp *ulp;
1919 struct fc_peer *peer;
1920
1921 /* Get peer */
1922 peer = fc_peer_get_port_id ( port, peer_port_id );
1923 if ( ! peer )
1924 goto err_peer_get_wwn;
1925
1926 /* Get ULP */
1927 ulp = fc_ulp_get_type ( peer, type );
1928 if ( ! ulp )
1929 goto err_ulp_get_type;
1930
1931 /* Drop temporary reference to peer */
1932 fc_peer_put ( peer );
1933
1934 return ulp;
1935
1936 fc_ulp_put ( ulp );
1937 err_ulp_get_type:
1938 fc_peer_put ( peer );
1939 err_peer_get_wwn:
1940 return NULL;
1941}
struct fc_peer * fc_peer_get_port_id(struct fc_port *port, const struct fc_port_id *peer_port_id)
Get Fibre Channel peer by port ID.
Definition fc.c:1541

References fc_peer_get_port_id(), fc_peer_put(), fc_ulp_get_type(), fc_ulp_put(), NULL, peer, port, and type.

Referenced by fc_els_prli_rx(), and fc_els_prli_tx().

◆ REQUIRING_SYMBOL()

REQUIRING_SYMBOL ( fc_ports )

References fc_ports.

◆ REQUIRE_OBJECT()

REQUIRE_OBJECT ( config_fc )

Variable Documentation

◆ fc_empty_port_id

struct fc_port_id fc_empty_port_id = { .bytes = { 0x00, 0x00, 0x00 } }

Unassigned port ID.

Definition at line 65 of file fc.c.

65{ .bytes = { 0x00, 0x00, 0x00 } };

Referenced by fc_port_deliver(), and fcels_exec().

◆ fc_f_port_id

struct fc_port_id fc_f_port_id = { .bytes = { 0xff, 0xff, 0xfe } }

F_Port contoller port ID.

Definition at line 68 of file fc.c.

68{ .bytes = { 0xff, 0xff, 0xfe } };

Referenced by fc_els_flogi(), fc_els_logo_logout(), fc_port_deliver(), and fcels_exec().

◆ fc_gs_port_id

struct fc_port_id fc_gs_port_id = { .bytes = { 0xff, 0xff, 0xfc } }

Generic services port ID.

Definition at line 71 of file fc.c.

71{ .bytes = { 0xff, 0xff, 0xfc } };

Referenced by fc_ns_query_step(), and fc_port_login().

◆ fc_ptp_low_port_id

struct fc_port_id fc_ptp_low_port_id = { .bytes = { 0x01, 0x01, 0x01 } }

Point-to-point low port ID.

Definition at line 74 of file fc.c.

74{ .bytes = { 0x01, 0x01, 0x01 } };

Referenced by fc_port_login().

◆ fc_ptp_high_port_id

struct fc_port_id fc_ptp_high_port_id = { .bytes = { 0x01, 0x01, 0x02 } }

Point-to-point high port ID.

Definition at line 77 of file fc.c.

77{ .bytes = { 0x01, 0x01, 0x02 } };

Referenced by fc_port_login().

◆ fc_r_ctl_info_meta_flags

const uint8_t fc_r_ctl_info_meta_flags[FC_R_CTL_INFO_MASK+1]
static
Initial value:

Mapping from Fibre Channel routing control information to xfer metadata.

Definition at line 568 of file fc.c.

Referenced by fc_xchg_rx().

◆ fc_xchg_ulp_op

struct interface_operation fc_xchg_ulp_op[]
static
Initial value:
= {
}
static size_t fc_xchg_window(struct fc_exchange *xchg __unused)
Check Fibre Channel exchange window.
Definition fc.c:423
static int fc_xchg_tx(struct fc_exchange *xchg, struct io_buffer *iobuf, struct xfer_metadata *meta)
Transmit data as part of a Fibre Channel exchange.
Definition fc.c:457
static struct io_buffer * fc_xchg_alloc_iob(struct fc_exchange *xchg, size_t len)
Allocate Fibre Channel I/O buffer.
Definition fc.c:436
void intf_close(struct interface *intf, int rc)
Close an object interface.
Definition interface.c:250
#define INTF_OP(op_type, object_type, op_func)
Define an object interface operation.
Definition interface.h:33

Fibre Channel exchange ULP interface operations.

Definition at line 677 of file fc.c.

◆ fc_xchg_ulp_desc

struct interface_descriptor fc_xchg_ulp_desc
static
Initial value:
=
static struct interface_operation fc_xchg_ulp_op[]
Fibre Channel exchange ULP interface operations.
Definition fc.c:677
#define INTF_DESC(object_type, intf, operations)
Define an object interface descriptor.
Definition interface.h:81

Fibre Channel exchange ULP interface descriptor.

Definition at line 685 of file fc.c.

Referenced by fc_xchg_create().

◆ fc_port_transport_op

struct interface_operation fc_port_transport_op[]
static
Initial value:
= {
}
static int fc_port_deliver(struct fc_port *port, struct io_buffer *iobuf, struct xfer_metadata *meta)
Handle received frame from Fibre Channel port.
Definition fc.c:859
static void fc_port_window_changed(struct fc_port *port)
Handle change of flow control window.
Definition fc.c:1126
static void fc_port_close(struct fc_port *port, int rc)
Close Fibre Channel port.
Definition fc.c:806
void xfer_window_changed(struct interface *intf)
Report change of flow control window.
Definition xfer.c:147

Fibre Channel port transport interface operations.

Definition at line 1151 of file fc.c.

1151 {
1155 INTF_OP ( intf_close, struct fc_port *, fc_port_close ),
1156};

◆ fc_port_transport_desc

struct interface_descriptor fc_port_transport_desc
static
Initial value:
=
INTF_DESC ( struct fc_port, transport, fc_port_transport_op )
static struct interface_operation fc_port_transport_op[]
Fibre Channel port transport interface operations.
Definition fc.c:1151

Fibre Channel port transport interface descriptor.

Definition at line 1159 of file fc.c.

Referenced by fc_port_open().

◆ fc_port_flogi_op

struct interface_operation fc_port_flogi_op[]
static
Initial value:
= {
}
static void fc_port_flogi_done(struct fc_port *port, int rc)
Handle FLOGI completion.
Definition fc.c:1067

Fibre Channel port FLOGI interface operations.

Definition at line 1163 of file fc.c.

1163 {
1165};

◆ fc_port_flogi_desc

struct interface_descriptor fc_port_flogi_desc
static
Initial value:
=
INTF_DESC ( struct fc_port, flogi, fc_port_flogi_op )
static struct interface_operation fc_port_flogi_op[]
Fibre Channel port FLOGI interface operations.
Definition fc.c:1163

Fibre Channel port FLOGI interface descriptor.

Definition at line 1168 of file fc.c.

Referenced by fc_port_open().

◆ fc_port_ns_plogi_op

struct interface_operation fc_port_ns_plogi_op[]
static
Initial value:
= {
}
static void fc_port_ns_plogi_done(struct fc_port *port, int rc)
Handle name server PLOGI completion.
Definition fc.c:1081

Fibre Channel port name server PLOGI interface operations.

Definition at line 1172 of file fc.c.

1172 {
1174};

◆ fc_port_ns_plogi_desc

struct interface_descriptor fc_port_ns_plogi_desc
static
Initial value:
=
INTF_DESC ( struct fc_port, ns_plogi, fc_port_ns_plogi_op )
static struct interface_operation fc_port_ns_plogi_op[]
Fibre Channel port name server PLOGI interface operations.
Definition fc.c:1172

Fibre Channel port name server PLOGI interface descriptor.

Definition at line 1177 of file fc.c.

Referenced by fc_port_open().

◆ fc_peer_plogi_op

struct interface_operation fc_peer_plogi_op[]
static
Initial value:
= {
}
static void fc_peer_plogi_done(struct fc_peer *peer, int rc)
Handle PLOGI completion.
Definition fc.c:1383

Fibre Channel peer PLOGI interface operations.

Definition at line 1475 of file fc.c.

1475 {
1477};

◆ fc_peer_plogi_desc

struct interface_descriptor fc_peer_plogi_desc
static
Initial value:
=
INTF_DESC ( struct fc_peer, plogi, fc_peer_plogi_op )
static struct interface_operation fc_peer_plogi_op[]
Fibre Channel peer PLOGI interface operations.
Definition fc.c:1475

Fibre Channel peer PLOGI interface descriptor.

Definition at line 1480 of file fc.c.

Referenced by fc_peer_create().

◆ fc_ulp_prli_op

struct interface_operation fc_ulp_prli_op[]
static
Initial value:
= {
}
static void fc_ulp_prli_done(struct fc_ulp *ulp, int rc)
Handle PRLI completion.
Definition fc.c:1765

Fibre Channel upper-layer protocol PRLI interface operations.

Definition at line 1809 of file fc.c.

1809 {
1811};

◆ fc_ulp_prli_desc

struct interface_descriptor fc_ulp_prli_desc
static
Initial value:
=
INTF_DESC ( struct fc_ulp, prli, fc_ulp_prli_op )
static struct interface_operation fc_ulp_prli_op[]
Fibre Channel upper-layer protocol PRLI interface operations.
Definition fc.c:1809

Fibre Channel upper-layer protocol PRLI interface descriptor.

Definition at line 1814 of file fc.c.

Referenced by fc_ulp_create().