iPXE
fcmgmt_cmd.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2010 Michael Brown <mbrown@fensystems.co.uk>.
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License as
00006  * published by the Free Software Foundation; either version 2 of the
00007  * License, or any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful, but
00010  * WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software
00016  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00017  * 02110-1301, USA.
00018  *
00019  * You can also choose to distribute this program under the terms of
00020  * the Unmodified Binary Distribution Licence (as given in the file
00021  * COPYING.UBDL), provided that you have satisfied its requirements.
00022  */
00023 
00024 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
00025 
00026 #include <stdio.h>
00027 #include <errno.h>
00028 #include <getopt.h>
00029 #include <strings.h>
00030 #include <ipxe/fc.h>
00031 #include <ipxe/fcels.h>
00032 #include <ipxe/command.h>
00033 #include <ipxe/parseopt.h>
00034 #include <ipxe/tables.h>
00035 #include <usr/fcmgmt.h>
00036 
00037 /** @file
00038  *
00039  * Fibre Channel management commands
00040  *
00041  */
00042 
00043 /**
00044  * Parse Fibre Channel port name
00045  *
00046  * @v text              Text
00047  * @ret port            Fibre Channel port
00048  * @ret rc              Return status code
00049  */
00050 static int parse_fc_port ( char *text, struct fc_port **port ) {
00051 
00052         /* Sanity check */
00053         assert ( text != NULL );
00054 
00055         /* Find Fibre Channel port */
00056         *port = fc_port_find ( text );
00057         if ( ! *port ) {
00058                 printf ( "\"%s\": no such port\n", text );
00059                 return -ENODEV;
00060         }
00061 
00062         return 0;
00063 }
00064 
00065 /**
00066  * Parse Fibre Channel port ID
00067  *
00068  * @v text              Text
00069  * @ret port_id         Fibre Channel port ID
00070  * @ret rc              Return status code
00071  */
00072 static int parse_fc_port_id ( char *text, struct fc_port_id *port_id ) {
00073         int rc;
00074 
00075         /* Sanity check */
00076         assert ( text != NULL );
00077 
00078         /* Parse port ID */
00079         if ( ( rc = fc_id_aton ( text, port_id ) ) != 0 ) {
00080                 printf ( "\"%s\": invalid port ID\n", text );
00081                 return -EINVAL;
00082         }
00083 
00084         return 0;
00085 }
00086 
00087 /**
00088  * Parse Fibre Channel ELS handler name
00089  *
00090  * @v text              Text
00091  * @ret handler         Fibre Channel ELS handler
00092  * @ret rc              Return status code
00093  */
00094 static int parse_fc_els_handler ( char *text, struct fc_els_handler **handler ){
00095 
00096         for_each_table_entry ( (*handler), FC_ELS_HANDLERS ) {
00097                 if ( strcasecmp ( (*handler)->name, text ) == 0 )
00098                         return 0;
00099         }
00100 
00101         printf ( "\"%s\": unrecognised ELS\n", text );
00102         return -ENOENT;
00103 }
00104 
00105 /** "fcstat" options */
00106 struct fcstat_options {};
00107 
00108 /** "fcstat" option list */
00109 static struct option_descriptor fcstat_opts[] = {};
00110 
00111 /** "fcstat" command descriptor */
00112 static struct command_descriptor fcstat_cmd =
00113         COMMAND_DESC ( struct fcstat_options, fcstat_opts, 0, 0, NULL );
00114 
00115 /**
00116  * The "fcstat" command
00117  *
00118  * @v argc              Argument count
00119  * @v argv              Argument list
00120  * @ret rc              Return status code
00121  */
00122 static int fcstat_exec ( int argc, char **argv ) {
00123         struct fcstat_options opts;
00124         struct fc_port *port;
00125         struct fc_peer *peer;
00126         int rc;
00127 
00128         /* Parse options */
00129         if ( ( rc = parse_options ( argc, argv, &fcstat_cmd, &opts ) ) != 0 )
00130                 return rc;
00131 
00132         list_for_each_entry ( port, &fc_ports, list )
00133                 fcportstat ( port );
00134         list_for_each_entry ( peer, &fc_peers, list )
00135                 fcpeerstat ( peer );
00136 
00137         return 0;
00138 }
00139 
00140 /** "fcels" options */
00141 struct fcels_options {
00142         /** Fibre Channel port */
00143         struct fc_port *port;
00144         /** Fibre Channel peer port ID */
00145         struct fc_port_id peer_port_id;
00146 };
00147 
00148 /** "fcels" option list */
00149 static struct option_descriptor fcels_opts[] = {
00150         OPTION_DESC ( "port", 'p', required_argument,
00151                       struct fcels_options, port, parse_fc_port ),
00152         OPTION_DESC ( "id", 'i', required_argument,
00153                       struct fcels_options, peer_port_id, parse_fc_port_id ),
00154 };
00155 
00156 /** "fcels" command descriptor */
00157 static struct command_descriptor fcels_cmd =
00158         COMMAND_DESC ( struct fcels_options, fcels_opts, 1, 1, "<request>" );
00159 
00160 /**
00161  * The "fcels" command
00162  *
00163  * @v argc              Argument count
00164  * @v argv              Argument list
00165  * @ret rc              Return status code
00166  */
00167 static int fcels_exec ( int argc, char **argv ) {
00168         struct fcels_options opts;
00169         struct fc_els_handler *handler;
00170         struct fc_port_id *id;
00171         int rc;
00172 
00173         /* Parse options */
00174         if ( ( rc = parse_options ( argc, argv, &fcels_cmd, &opts ) ) != 0 )
00175                 return rc;
00176 
00177         /* Parse ELS handler */
00178         if ( ( rc = parse_fc_els_handler ( argv[optind], &handler ) ) != 0 )
00179                 return rc;
00180 
00181         /* Use first port if no port specified */
00182         if ( ! opts.port ) {
00183                 opts.port = list_first_entry ( &fc_ports, struct fc_port,
00184                                                list );
00185                 if ( ! opts.port ) {
00186                         printf ( "No ports\n" );
00187                         return -ENODEV;
00188                 }
00189         }
00190 
00191         /* Use link peer port ID if no peer port ID specified */
00192         id = &opts.peer_port_id;
00193         if ( memcmp ( id, &fc_empty_port_id, sizeof ( *id ) ) == 0 ) {
00194                 if ( fc_link_ok ( &opts.port->link ) &&
00195                      ! ( opts.port->flags & FC_PORT_HAS_FABRIC ) ) {
00196                         id = &opts.port->ptp_link_port_id;
00197                 } else {
00198                         id = &fc_f_port_id;
00199                 }
00200         }
00201 
00202         /** Issue ELS */
00203         if ( ( rc = fcels ( opts.port, id, handler ) ) != 0 )
00204                 return rc;
00205 
00206         return 0;
00207 }
00208 
00209 /** Fibre Channel management commands */
00210 struct command fcmgmt_commands[] __command = {
00211         {
00212                 .name = "fcstat",
00213                 .exec = fcstat_exec,
00214         },
00215         {
00216                 .name = "fcels",
00217                 .exec = fcels_exec,
00218         },
00219 };