david/ipxe
david
/
ipxe
Archived
1
0
Fork 0

[fc] Allow FLOGI response to be sent to newly-assigned peer port ID

The response to a received FLOGI should probably be sent to the peer
port ID assigned as a result of the WWPN comparison.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
Michael Brown 2010-09-21 00:55:14 +01:00
parent 1c7f47895c
commit 654da534ad
4 changed files with 50 additions and 5 deletions

View File

@ -16,6 +16,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
#include <ipxe/tables.h> #include <ipxe/tables.h>
#include <ipxe/interface.h> #include <ipxe/interface.h>
#include <ipxe/retry.h> #include <ipxe/retry.h>
#include <ipxe/socket.h>
/****************************************************************************** /******************************************************************************
* *
@ -40,6 +41,27 @@ struct fc_port_id {
/** Length of Fibre Channel port identifier next */ /** Length of Fibre Channel port identifier next */
#define FC_PORT_ID_STRLEN 9 /* "xx.xx.xx" */ #define FC_PORT_ID_STRLEN 9 /* "xx.xx.xx" */
/**
* Fibre Channel socket address
*/
struct sockaddr_fc {
/** Socket address family (part of struct @c sockaddr)
*
* Always set to @c AF_FC for Fibre Channel addresses
*/
sa_family_t sfc_family;
/** Port ID */
struct fc_port_id sfc_port_id;
/** Padding
*
* This ensures that a struct @c sockaddr_tcpip is large
* enough to hold a socket address for any TCP/IP address
* family.
*/
char pad[ sizeof ( struct sockaddr ) - sizeof ( sa_family_t )
- sizeof ( struct fc_port_id ) ];
} __attribute__ (( may_alias ));
extern struct fc_port_id fc_empty_port_id; extern struct fc_port_id fc_empty_port_id;
extern struct fc_port_id fc_f_port_id; extern struct fc_port_id fc_f_port_id;
extern struct fc_port_id fc_ptp_low_port_id; extern struct fc_port_id fc_ptp_low_port_id;

View File

@ -54,6 +54,7 @@ socket_semantics_name ( int semantics ) {
*/ */
#define AF_INET 1 /**< IPv4 Internet addresses */ #define AF_INET 1 /**< IPv4 Internet addresses */
#define AF_INET6 2 /**< IPv6 Internet addresses */ #define AF_INET6 2 /**< IPv6 Internet addresses */
#define AF_FC 3 /**< Fibre Channel addresses */
/** @} */ /** @} */
/** /**

View File

@ -428,6 +428,7 @@ static struct io_buffer * fc_xchg_alloc_iob ( struct fc_exchange *xchg,
static int fc_xchg_tx ( struct fc_exchange *xchg, struct io_buffer *iobuf, static int fc_xchg_tx ( struct fc_exchange *xchg, struct io_buffer *iobuf,
struct xfer_metadata *meta ) { struct xfer_metadata *meta ) {
struct fc_port *port = xchg->port; struct fc_port *port = xchg->port;
struct sockaddr_fc *dest = ( ( struct sockaddr_fc * ) meta->dest );
struct fc_frame_header *fchdr; struct fc_frame_header *fchdr;
unsigned int r_ctl; unsigned int r_ctl;
unsigned int f_ctl_es; unsigned int f_ctl_es;
@ -484,7 +485,9 @@ static int fc_xchg_tx ( struct fc_exchange *xchg, struct io_buffer *iobuf,
fchdr = iob_push ( iobuf, sizeof ( *fchdr ) ); fchdr = iob_push ( iobuf, sizeof ( *fchdr ) );
memset ( fchdr, 0, sizeof ( *fchdr ) ); memset ( fchdr, 0, sizeof ( *fchdr ) );
fchdr->r_ctl = r_ctl; fchdr->r_ctl = r_ctl;
memcpy ( &fchdr->d_id, &xchg->peer_port_id, sizeof ( fchdr->d_id ) ); memcpy ( &fchdr->d_id,
( dest ? &dest->sfc_port_id : &xchg->peer_port_id ),
sizeof ( fchdr->d_id ) );
memcpy ( &fchdr->s_id, &port->port_id, sizeof ( fchdr->s_id ) ); memcpy ( &fchdr->s_id, &port->port_id, sizeof ( fchdr->s_id ) );
fchdr->type = xchg->type; fchdr->type = xchg->type;
fchdr->f_ctl_es = f_ctl_es; fchdr->f_ctl_es = f_ctl_es;

View File

@ -119,15 +119,26 @@ static struct fc_els_handler * fc_els_detect ( struct fc_els *els,
* @ret rc Return status code * @ret rc Return status code
*/ */
int fc_els_tx ( struct fc_els *els, const void *data, size_t len ) { int fc_els_tx ( struct fc_els *els, const void *data, size_t len ) {
struct xfer_metadata meta = { union {
.flags = ( fc_els_is_request ( els ) ? struct sockaddr sa;
XFER_FL_OVER : ( XFER_FL_RESPONSE | XFER_FL_OUT ) ), struct sockaddr_fc fc;
}; } dest;
struct xfer_metadata meta;
int rc; int rc;
DBGC2 ( els, FCELS_FMT " transmitting:\n", FCELS_ARGS ( els ) ); DBGC2 ( els, FCELS_FMT " transmitting:\n", FCELS_ARGS ( els ) );
DBGC2_HDA ( els, 0, data, len ); DBGC2_HDA ( els, 0, data, len );
/* Construct metadata */
memset ( &dest, 0, sizeof ( dest ) );
dest.fc.sfc_family = AF_FC;
memcpy ( &dest.fc.sfc_port_id, &els->peer_port_id,
sizeof ( dest.fc.sfc_port_id ) );
memset ( &meta, 0, sizeof ( meta ) );
meta.flags = ( fc_els_is_request ( els ) ?
XFER_FL_OVER : ( XFER_FL_RESPONSE | XFER_FL_OUT ) );
meta.dest = &dest.sa;
/* Transmit frame */ /* Transmit frame */
if ( ( rc = xfer_deliver_raw_meta ( &els->xchg, data, len, if ( ( rc = xfer_deliver_raw_meta ( &els->xchg, data, len,
&meta ) ) != 0 ) { &meta ) ) != 0 ) {
@ -524,6 +535,14 @@ static int fc_els_flogi_rx ( struct fc_els *els, const void *data,
return rc; return rc;
} }
/* Send any responses to the newly-assigned peer port ID, if
* applicable.
*/
if ( ! has_fabric ) {
memcpy ( &els->peer_port_id, &els->port->ptp_link_port_id,
sizeof ( els->peer_port_id ) );
}
return 0; return 0;
} }