Annotation of qemu/roms/ipxe/src/net/fcns.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (C) 2010 Michael Brown <[email protected]>.
                      3:  *
                      4:  * This program is free software; you can redistribute it and/or
                      5:  * modify it under the terms of the GNU General Public License as
                      6:  * published by the Free Software Foundation; either version 2 of the
                      7:  * License, or any later version.
                      8:  *
                      9:  * This program is distributed in the hope that it will be useful, but
                     10:  * WITHOUT ANY WARRANTY; without even the implied warranty of
                     11:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
                     12:  * General Public License for more details.
                     13:  *
                     14:  * You should have received a copy of the GNU General Public License
                     15:  * along with this program; if not, write to the Free Software
                     16:  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
                     17:  */
                     18: 
                     19: FILE_LICENCE ( GPL2_OR_LATER );
                     20: 
                     21: #include <stddef.h>
                     22: #include <stdlib.h>
                     23: #include <string.h>
                     24: #include <errno.h>
                     25: #include <byteswap.h>
                     26: #include <ipxe/interface.h>
                     27: #include <ipxe/iobuf.h>
                     28: #include <ipxe/process.h>
                     29: #include <ipxe/xfer.h>
                     30: #include <ipxe/fc.h>
                     31: #include <ipxe/fcns.h>
                     32: 
                     33: /** @file
                     34:  *
                     35:  * Fibre Channel name server lookups
                     36:  *
                     37:  */
                     38: 
                     39: /** A Fibre Channel name server query */
                     40: struct fc_ns_query {
                     41:        /** Reference count */
                     42:        struct refcnt refcnt;
                     43:        /** Fibre Channel exchange */
                     44:        struct interface xchg;
                     45: 
                     46:        /** Fibre Channel peer */
                     47:        struct fc_peer *peer;
                     48:        /** Fibre Channel port */
                     49:        struct fc_port *port;
                     50: 
                     51:        /** Process */
                     52:        struct process process;
                     53:        /** Success handler
                     54:         *
                     55:         * @v peer              Fibre Channel peer
                     56:         * @v port              Fibre Channel port
                     57:         * @v peer_port_id      Peer port ID
                     58:         * @ret rc              Return status code
                     59:         */
                     60:        int ( * done ) ( struct fc_peer *peer, struct fc_port *port,
                     61:                         struct fc_port_id *peer_port_id );
                     62: };
                     63: 
                     64: /**
                     65:  * Free name server query
                     66:  *
                     67:  * @v refcnt           Reference count
                     68:  */
                     69: static void fc_ns_query_free ( struct refcnt *refcnt ) {
                     70:        struct fc_ns_query *query =
                     71:                container_of ( refcnt, struct fc_ns_query, refcnt );
                     72: 
                     73:        fc_peer_put ( query->peer );
                     74:        fc_port_put ( query->port );
                     75:        free ( query );
                     76: }
                     77: 
                     78: /**
                     79:  * Close name server query
                     80:  *
                     81:  * @v query            Name server query
                     82:  * @v rc               Reason for close
                     83:  */
                     84: static void fc_ns_query_close ( struct fc_ns_query *query, int rc ) {
                     85: 
                     86:        /* Stop process */
                     87:        process_del ( &query->process );
                     88: 
                     89:        /* Shut down interfaces */
                     90:        intf_shutdown ( &query->xchg, rc );
                     91: }
                     92: 
                     93: /**
                     94:  * Receive name server query response
                     95:  *
                     96:  * @v query            Name server query
                     97:  * @v iobuf            I/O buffer
                     98:  * @v meta             Data transfer metadata
                     99:  * @ret rc             Return status code
                    100:  */
                    101: static int fc_ns_query_deliver ( struct fc_ns_query *query,
                    102:                                 struct io_buffer *iobuf,
                    103:                                 struct xfer_metadata *meta __unused ) {
                    104:        union fc_ns_response *resp = iobuf->data;
                    105:        struct fc_port_id *peer_port_id;
                    106:        int rc;
                    107: 
                    108:        /* Sanity check */
                    109:        if ( iob_len ( iobuf ) < sizeof ( resp->ct ) ) {
                    110:                DBGC ( query, "FCNS %p received underlength response (%zd "
                    111:                       "bytes)\n", query, iob_len ( iobuf ) );
                    112:                rc = -EINVAL;
                    113:                goto done;
                    114:        }
                    115: 
                    116:        /* Handle response */
                    117:        switch ( ntohs ( resp->ct.code ) ) {
                    118:        case FC_GS_ACCEPT:
                    119:                if ( iob_len ( iobuf ) < sizeof ( resp->gid_pn ) ) {
                    120:                        DBGC ( query, "FCNS %p received underlength accept "
                    121:                               "response (%zd bytes)\n",
                    122:                               query, iob_len ( iobuf ) );
                    123:                        rc = -EINVAL;
                    124:                        goto done;
                    125:                }
                    126:                peer_port_id = &resp->gid_pn.port_id.port_id;
                    127:                DBGC ( query, "FCNS %p resolved %s to %s via %s\n",
                    128:                       query, fc_ntoa ( &query->peer->port_wwn ),
                    129:                       fc_id_ntoa ( peer_port_id ), query->port->name );
                    130:                if ( ( rc = query->done ( query->peer, query->port,
                    131:                                          peer_port_id ) ) != 0 )
                    132:                        goto done;
                    133:                break;
                    134:        case FC_GS_REJECT:
                    135:                DBGC ( query, "FCNS %p rejected (reason %02x explanation "
                    136:                       "%02x)\n", query, resp->reject.ct.reason,
                    137:                       resp->reject.ct.explanation );
                    138:                break;
                    139:        default:
                    140:                DBGC ( query, "FCNS %p received invalid response code %04x\n",
                    141:                       query, ntohs ( resp->ct.code ) );
                    142:                rc = -ENOTSUP;
                    143:                goto done;
                    144:        }
                    145: 
                    146:        rc = 0;
                    147:  done:
                    148:        free_iob ( iobuf );
                    149:        fc_ns_query_close ( query, rc );
                    150:        return rc;
                    151: }
                    152: 
                    153: /**
                    154:  * Name server query process
                    155:  *
                    156:  * @v process          Process
                    157:  */
                    158: static void fc_ns_query_step ( struct process *process ) {
                    159:        struct fc_ns_query *query =
                    160:                container_of ( process, struct fc_ns_query, process );
                    161:        struct xfer_metadata meta;
                    162:        struct fc_ns_gid_pn_request gid_pn;
                    163:        int xchg_id;
                    164:        int rc;
                    165: 
                    166:        /* Stop process */
                    167:        process_del ( &query->process );
                    168: 
                    169:        /* Create exchange */
                    170:        if ( ( xchg_id = fc_xchg_originate ( &query->xchg, query->port,
                    171:                                             &fc_gs_port_id,
                    172:                                             FC_TYPE_CT ) ) < 0 ) {
                    173:                rc = xchg_id;
                    174:                DBGC ( query, "FCNS %p could not create exchange: %s\n",
                    175:                       query, strerror ( rc ) );
                    176:                fc_ns_query_close ( query, rc );
                    177:                return;
                    178:        }
                    179: 
                    180:        /* Construct query request */
                    181:        memset ( &gid_pn, 0, sizeof ( gid_pn ) );
                    182:        gid_pn.ct.revision = FC_CT_REVISION;
                    183:        gid_pn.ct.type = FC_GS_TYPE_DS;
                    184:        gid_pn.ct.subtype = FC_DS_SUBTYPE_NAME;
                    185:        gid_pn.ct.code = htons ( FC_NS_GET ( FC_NS_PORT_NAME, FC_NS_PORT_ID ));
                    186:        memcpy ( &gid_pn.port_wwn, &query->peer->port_wwn,
                    187:                 sizeof ( gid_pn.port_wwn ) );
                    188:        memset ( &meta, 0, sizeof ( meta ) );
                    189:        meta.flags = XFER_FL_OVER;
                    190: 
                    191:        /* Send query */
                    192:        if ( ( rc = xfer_deliver_raw_meta ( &query->xchg, &gid_pn,
                    193:                                            sizeof ( gid_pn ), &meta ) ) != 0){
                    194:                DBGC ( query, "FCNS %p could not deliver query: %s\n",
                    195:                       query, strerror ( rc ) );
                    196:                fc_ns_query_close ( query, rc );
                    197:                return;
                    198:        }
                    199: }
                    200: 
                    201: /** Name server exchange interface operations */
                    202: static struct interface_operation fc_ns_query_xchg_op[] = {
                    203:        INTF_OP ( xfer_deliver, struct fc_ns_query *, fc_ns_query_deliver ),
                    204:        INTF_OP ( intf_close, struct fc_ns_query *, fc_ns_query_close ),
                    205: };
                    206: 
                    207: /** Name server exchange interface descriptor */
                    208: static struct interface_descriptor fc_ns_query_xchg_desc =
                    209:        INTF_DESC ( struct fc_ns_query, xchg, fc_ns_query_xchg_op );
                    210: 
                    211: /**
                    212:  * Issue Fibre Channel name server query
                    213:  *
                    214:  * @v peer             Fibre Channel peer
                    215:  * @v port             Fibre Channel port
                    216:  * @ret rc             Return status code
                    217:  */
                    218: int fc_ns_query ( struct fc_peer *peer, struct fc_port *port,
                    219:                  int ( * done ) ( struct fc_peer *peer, struct fc_port *port,
                    220:                                   struct fc_port_id *peer_port_id ) ) {
                    221:        struct fc_ns_query *query;
                    222: 
                    223:        /* Allocate and initialise structure */
                    224:        query = zalloc ( sizeof ( *query ) );
                    225:        if ( ! query )
                    226:                return -ENOMEM;
                    227:        ref_init ( &query->refcnt, fc_ns_query_free );
                    228:        intf_init ( &query->xchg, &fc_ns_query_xchg_desc, &query->refcnt );
                    229:        process_init ( &query->process, fc_ns_query_step, &query->refcnt );
                    230:        query->peer = fc_peer_get ( peer );
                    231:        query->port = fc_port_get ( port );
                    232:        query->done = done;
                    233: 
                    234:        DBGC ( query, "FCNS %p querying %s via %s\n",
                    235:               query, fc_ntoa ( &query->peer->port_wwn ), port->name );
                    236: 
                    237:        /* Mortalise self and return */
                    238:        ref_put ( &query->refcnt );
                    239:        return 0;
                    240: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.