]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[fc] Allow FLOGI response to be sent to newly-assigned peer port ID
authorMichael Brown <mcb30@ipxe.org>
Mon, 20 Sep 2010 23:55:14 +0000 (00:55 +0100)
committerMichael Brown <mcb30@ipxe.org>
Tue, 21 Sep 2010 01:06:06 +0000 (02:06 +0100)
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>
src/include/ipxe/fc.h
src/include/ipxe/socket.h
src/net/fc.c
src/net/fcels.c

index 5d73068f2dcd5424eb314451423ff91fd527506d..00571f1fdf998b1c8380805f2a8dd54eb064dc12 100644 (file)
@@ -16,6 +16,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
 #include <ipxe/tables.h>
 #include <ipxe/interface.h>
 #include <ipxe/retry.h>
+#include <ipxe/socket.h>
 
 /******************************************************************************
  *
@@ -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;
index ea2972a8934c4ed706f1c5a2ddbd1285c1f4d8f6..320dae4f18c84316d992568c66229642b2e9e667 100644 (file)
@@ -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 */
 /** @} */
 
 /**
index 63df3dadae94c0c639db6828358d3bac4f64c27b..33e13bdaf7ffb0b2de85440ebcfde680a4c30fe6 100644 (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,
                        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;
index 63063ca35694ceb4987d420deacca4cb1bac1d99..fe2f5c224da623d80165070b228ec432b6f8e4f3 100644 (file)
@@ -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;
 }