From 654da534ada4624d20bd1e2835f86ee9c95ca165 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Tue, 21 Sep 2010 00:55:14 +0100 Subject: [PATCH] [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 --- src/include/ipxe/fc.h | 22 ++++++++++++++++++++++ src/include/ipxe/socket.h | 1 + src/net/fc.c | 5 ++++- src/net/fcels.c | 27 +++++++++++++++++++++++---- 4 files changed, 50 insertions(+), 5 deletions(-) diff --git a/src/include/ipxe/fc.h b/src/include/ipxe/fc.h index 5d73068f..00571f1f 100644 --- a/src/include/ipxe/fc.h +++ b/src/include/ipxe/fc.h @@ -16,6 +16,7 @@ FILE_LICENCE ( GPL2_OR_LATER ); #include #include #include +#include /****************************************************************************** * @@ -40,6 +41,27 @@ struct fc_port_id { /** Length of Fibre Channel port identifier next */ #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_f_port_id; extern struct fc_port_id fc_ptp_low_port_id; diff --git a/src/include/ipxe/socket.h b/src/include/ipxe/socket.h index ea2972a8..320dae4f 100644 --- a/src/include/ipxe/socket.h +++ b/src/include/ipxe/socket.h @@ -54,6 +54,7 @@ socket_semantics_name ( int semantics ) { */ #define AF_INET 1 /**< IPv4 Internet addresses */ #define AF_INET6 2 /**< IPv6 Internet addresses */ +#define AF_FC 3 /**< Fibre Channel addresses */ /** @} */ /** diff --git a/src/net/fc.c b/src/net/fc.c index 63df3dad..33e13bda 100644 --- a/src/net/fc.c +++ b/src/net/fc.c @@ -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, struct xfer_metadata *meta ) { struct fc_port *port = xchg->port; + struct sockaddr_fc *dest = ( ( struct sockaddr_fc * ) meta->dest ); struct fc_frame_header *fchdr; unsigned int r_ctl; 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 ) ); memset ( fchdr, 0, sizeof ( *fchdr ) ); 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 ) ); fchdr->type = xchg->type; fchdr->f_ctl_es = f_ctl_es; diff --git a/src/net/fcels.c b/src/net/fcels.c index 63063ca3..fe2f5c22 100644 --- a/src/net/fcels.c +++ b/src/net/fcels.c @@ -119,15 +119,26 @@ static struct fc_els_handler * fc_els_detect ( struct fc_els *els, * @ret rc Return status code */ int fc_els_tx ( struct fc_els *els, const void *data, size_t len ) { - struct xfer_metadata meta = { - .flags = ( fc_els_is_request ( els ) ? - XFER_FL_OVER : ( XFER_FL_RESPONSE | XFER_FL_OUT ) ), - }; + union { + struct sockaddr sa; + struct sockaddr_fc fc; + } dest; + struct xfer_metadata meta; int rc; DBGC2 ( els, FCELS_FMT " transmitting:\n", FCELS_ARGS ( els ) ); 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 */ if ( ( rc = xfer_deliver_raw_meta ( &els->xchg, data, len, &meta ) ) != 0 ) { @@ -524,6 +535,14 @@ static int fc_els_flogi_rx ( struct fc_els *els, const void *data, 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; }