|
@@ -19,11 +19,13 @@
|
19
|
19
|
FILE_LICENCE ( GPL2_OR_LATER );
|
20
|
20
|
|
21
|
21
|
#include <stdio.h>
|
|
22
|
+#include <errno.h>
|
22
|
23
|
#include <getopt.h>
|
23
|
24
|
#include <strings.h>
|
24
|
25
|
#include <ipxe/fc.h>
|
25
|
26
|
#include <ipxe/fcels.h>
|
26
|
27
|
#include <ipxe/command.h>
|
|
28
|
+#include <ipxe/parseopt.h>
|
27
|
29
|
#include <ipxe/tables.h>
|
28
|
30
|
#include <usr/fcmgmt.h>
|
29
|
31
|
|
|
@@ -33,36 +35,96 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
33
|
35
|
*
|
34
|
36
|
*/
|
35
|
37
|
|
36
|
|
-static void fcstat_syntax ( char **argv ) {
|
37
|
|
- printf ( "Usage:\n %s\n", argv[0] );
|
|
38
|
+/**
|
|
39
|
+ * Parse Fibre Channel port name
|
|
40
|
+ *
|
|
41
|
+ * @v text Text
|
|
42
|
+ * @ret port Fibre Channel port
|
|
43
|
+ * @ret rc Return status code
|
|
44
|
+ */
|
|
45
|
+static int parse_fc_port ( const char *text, struct fc_port **port ) {
|
|
46
|
+
|
|
47
|
+ /* Sanity check */
|
|
48
|
+ assert ( text != NULL );
|
|
49
|
+
|
|
50
|
+ /* Find Fibre Channel port */
|
|
51
|
+ *port = fc_port_find ( text );
|
|
52
|
+ if ( ! *port ) {
|
|
53
|
+ printf ( "\"%s\": no such port\n", text );
|
|
54
|
+ return -ENODEV;
|
|
55
|
+ }
|
|
56
|
+
|
|
57
|
+ return 0;
|
38
|
58
|
}
|
39
|
59
|
|
|
60
|
+/**
|
|
61
|
+ * Parse Fibre Channel port ID
|
|
62
|
+ *
|
|
63
|
+ * @v text Text
|
|
64
|
+ * @ret port_id Fibre Channel port ID
|
|
65
|
+ * @ret rc Return status code
|
|
66
|
+ */
|
|
67
|
+static int parse_fc_port_id ( const char *text, struct fc_port_id *port_id ) {
|
|
68
|
+ int rc;
|
|
69
|
+
|
|
70
|
+ /* Sanity check */
|
|
71
|
+ assert ( text != NULL );
|
|
72
|
+
|
|
73
|
+ /* Parse port ID */
|
|
74
|
+ if ( ( rc = fc_id_aton ( text, port_id ) ) != 0 ) {
|
|
75
|
+ printf ( "\"%s\": invalid port ID\n", text );
|
|
76
|
+ return -EINVAL;
|
|
77
|
+ }
|
|
78
|
+
|
|
79
|
+ return 0;
|
|
80
|
+}
|
|
81
|
+
|
|
82
|
+/**
|
|
83
|
+ * Parse Fibre Channel ELS handler name
|
|
84
|
+ *
|
|
85
|
+ * @v text Text
|
|
86
|
+ * @ret handler Fibre Channel ELS handler
|
|
87
|
+ * @ret rc Return status code
|
|
88
|
+ */
|
|
89
|
+static int parse_fc_els_handler ( const char *text,
|
|
90
|
+ struct fc_els_handler **handler ) {
|
|
91
|
+
|
|
92
|
+ for_each_table_entry ( (*handler), FC_ELS_HANDLERS ) {
|
|
93
|
+ if ( strcasecmp ( (*handler)->name, text ) == 0 )
|
|
94
|
+ return 0;
|
|
95
|
+ }
|
|
96
|
+
|
|
97
|
+ printf ( "\"%s\": unrecognised ELS\n", text );
|
|
98
|
+ return -ENOENT;
|
|
99
|
+}
|
|
100
|
+
|
|
101
|
+/** "fcstat" options */
|
|
102
|
+struct fcstat_options {};
|
|
103
|
+
|
|
104
|
+/** "fcstat" option list */
|
|
105
|
+static struct option_descriptor fcstat_opts[] = {};
|
|
106
|
+
|
|
107
|
+/** "fcstat" command descriptor */
|
|
108
|
+static struct command_descriptor fcstat_cmd =
|
|
109
|
+ COMMAND_DESC ( struct fcstat_options, fcstat_opts, 0, 0,
|
|
110
|
+ "", "" );
|
|
111
|
+
|
|
112
|
+/**
|
|
113
|
+ * The "fcstat" command
|
|
114
|
+ *
|
|
115
|
+ * @v argc Argument count
|
|
116
|
+ * @v argv Argument list
|
|
117
|
+ * @ret rc Return status code
|
|
118
|
+ */
|
40
|
119
|
static int fcstat_exec ( int argc, char **argv ) {
|
41
|
|
- static struct option fcstat_opts[] = {
|
42
|
|
- { "help", 0, NULL, 'h' },
|
43
|
|
- { NULL, 0, NULL, 0 },
|
44
|
|
- };
|
|
120
|
+ struct fcstat_options opts;
|
45
|
121
|
struct fc_port *port;
|
46
|
122
|
struct fc_peer *peer;
|
47
|
|
- int c;
|
|
123
|
+ int rc;
|
48
|
124
|
|
49
|
125
|
/* Parse options */
|
50
|
|
- while ( ( c = getopt_long ( argc, argv, "h", fcstat_opts,
|
51
|
|
- NULL ) ) >= 0 ) {
|
52
|
|
- switch ( c ) {
|
53
|
|
- case 'h':
|
54
|
|
- /* Display help text */
|
55
|
|
- default:
|
56
|
|
- /* Unrecognised/invalid option */
|
57
|
|
- fcstat_syntax ( argv );
|
58
|
|
- return 1;
|
59
|
|
- }
|
60
|
|
- }
|
61
|
|
-
|
62
|
|
- if ( optind != argc ) {
|
63
|
|
- fcstat_syntax ( argv );
|
64
|
|
- return 1;
|
65
|
|
- }
|
|
126
|
+ if ( ( rc = parse_options ( argc, argv, &fcstat_cmd, &opts ) ) != 0 )
|
|
127
|
+ return rc;
|
66
|
128
|
|
67
|
129
|
list_for_each_entry ( port, &fc_ports, list )
|
68
|
130
|
fcportstat ( port );
|
|
@@ -72,105 +134,72 @@ static int fcstat_exec ( int argc, char **argv ) {
|
72
|
134
|
return 0;
|
73
|
135
|
}
|
74
|
136
|
|
75
|
|
-static void fcels_syntax ( char **argv ) {
|
76
|
|
- printf ( "Usage:\n %s [--port <port>] [--id <peer port id>]"
|
77
|
|
- " <command>\n", argv[0] );
|
78
|
|
-}
|
|
137
|
+/** "fcels" options */
|
|
138
|
+struct fcels_options {
|
|
139
|
+ /** Fibre Channel port */
|
|
140
|
+ struct fc_port *port;
|
|
141
|
+ /** Fibre Channel peer port ID */
|
|
142
|
+ struct fc_port_id peer_port_id;
|
|
143
|
+};
|
79
|
144
|
|
80
|
|
-static struct fc_els_handler * fcels_find_handler ( const char *name ) {
|
81
|
|
- struct fc_els_handler *handler;
|
|
145
|
+/** "fcels" option list */
|
|
146
|
+static struct option_descriptor fcels_opts[] = {
|
|
147
|
+ OPTION_DESC ( "port", 'p', required_argument,
|
|
148
|
+ struct fcels_options, port, parse_fc_port ),
|
|
149
|
+ OPTION_DESC ( "id", 'i', required_argument,
|
|
150
|
+ struct fcels_options, peer_port_id, parse_fc_port_id ),
|
|
151
|
+};
|
82
|
152
|
|
83
|
|
- for_each_table_entry ( handler, FC_ELS_HANDLERS ) {
|
84
|
|
- if ( strcasecmp ( handler->name, name ) == 0 )
|
85
|
|
- return handler;
|
86
|
|
- }
|
87
|
|
- return NULL;
|
88
|
|
-}
|
|
153
|
+/** "fcels" command descriptor */
|
|
154
|
+static struct command_descriptor fcels_cmd =
|
|
155
|
+ COMMAND_DESC ( struct fcels_options, fcels_opts, 1, 1,
|
|
156
|
+ "[--port <port>] [--id <peer_port_id>] <command>", "" );
|
89
|
157
|
|
|
158
|
+/**
|
|
159
|
+ * The "fcels" command
|
|
160
|
+ *
|
|
161
|
+ * @v argc Argument count
|
|
162
|
+ * @v argv Argument list
|
|
163
|
+ * @ret rc Return status code
|
|
164
|
+ */
|
90
|
165
|
static int fcels_exec ( int argc, char **argv ) {
|
91
|
|
- static struct option fcels_opts[] = {
|
92
|
|
- { "help", 0, NULL, 'h' },
|
93
|
|
- { "port", required_argument, NULL, 'p' },
|
94
|
|
- { "id", required_argument, NULL, 'i' },
|
95
|
|
- { NULL, 0, NULL, 0 },
|
96
|
|
- };
|
97
|
|
- const char *handler_text;
|
98
|
|
- const char *port_text = NULL;
|
99
|
|
- const char *id_text = NULL;
|
|
166
|
+ struct fcels_options opts;
|
100
|
167
|
struct fc_els_handler *handler;
|
101
|
|
- struct fc_port *port;
|
102
|
|
- struct fc_port_id id_buf;
|
103
|
168
|
struct fc_port_id *id;
|
104
|
|
- int c;
|
|
169
|
+ int rc;
|
105
|
170
|
|
106
|
171
|
/* Parse options */
|
107
|
|
- while ( ( c = getopt_long ( argc, argv, "hp:i:", fcels_opts,
|
108
|
|
- NULL ) ) >= 0 ) {
|
109
|
|
- switch ( c ) {
|
110
|
|
- case 'p':
|
111
|
|
- port_text = optarg;
|
112
|
|
- break;
|
113
|
|
- case 'i':
|
114
|
|
- id_text = optarg;
|
115
|
|
- break;
|
116
|
|
- case 'h':
|
117
|
|
- /* Display help text */
|
118
|
|
- default:
|
119
|
|
- /* Unrecognised/invalid option */
|
120
|
|
- fcels_syntax ( argv );
|
121
|
|
- return 1;
|
122
|
|
- }
|
123
|
|
- }
|
124
|
|
-
|
125
|
|
- /* Identify ELS */
|
126
|
|
- if ( optind != ( argc - 1 ) ) {
|
127
|
|
- fcels_syntax ( argv );
|
128
|
|
- return 1;
|
129
|
|
- }
|
130
|
|
- handler_text = argv[optind];
|
131
|
|
- handler = fcels_find_handler ( handler_text );
|
132
|
|
- if ( ! handler ) {
|
133
|
|
- printf ( "%s: unrecognised ELS\n", handler_text );
|
134
|
|
- return 1;
|
135
|
|
- }
|
136
|
|
-
|
137
|
|
- /* Identify port */
|
138
|
|
- if ( port_text ) {
|
139
|
|
- /* Use specified port */
|
140
|
|
- port = fc_port_find ( port_text );
|
141
|
|
- if ( ! port ) {
|
142
|
|
- printf ( "%s: no such port\n", port_text );
|
143
|
|
- return 1;
|
144
|
|
- }
|
145
|
|
- } else {
|
146
|
|
- /* Use first port */
|
147
|
|
- port = list_first_entry ( &fc_ports, struct fc_port, list );
|
148
|
|
- if ( ! port ) {
|
|
172
|
+ if ( ( rc = parse_options ( argc, argv, &fcels_cmd, &opts ) ) != 0 )
|
|
173
|
+ return rc;
|
|
174
|
+
|
|
175
|
+ /* Parse ELS handler */
|
|
176
|
+ if ( ( rc = parse_fc_els_handler ( argv[optind], &handler ) ) != 0 )
|
|
177
|
+ return rc;
|
|
178
|
+
|
|
179
|
+ /* Use first port if no port specified */
|
|
180
|
+ if ( ! opts.port ) {
|
|
181
|
+ opts.port = list_first_entry ( &fc_ports, struct fc_port,
|
|
182
|
+ list );
|
|
183
|
+ if ( ! opts.port ) {
|
149
|
184
|
printf ( "No ports\n" );
|
150
|
|
- return 1;
|
|
185
|
+ return -ENODEV;
|
151
|
186
|
}
|
152
|
187
|
}
|
153
|
|
- assert ( port != NULL );
|
154
|
188
|
|
155
|
|
- /* Identify port ID */
|
156
|
|
- if ( id_text ) {
|
157
|
|
- if ( fc_id_aton ( id_text, &id_buf ) != 0 ) {
|
158
|
|
- printf ( "%s: invalid port ID\n", id_text );
|
159
|
|
- return 1;
|
160
|
|
- }
|
161
|
|
- id = &id_buf;
|
162
|
|
- } else {
|
163
|
|
- if ( fc_link_ok ( &port->link ) &&
|
164
|
|
- ! ( port->flags & FC_PORT_HAS_FABRIC ) ) {
|
165
|
|
- id = &port->ptp_link_port_id;
|
|
189
|
+ /* Use link peer port ID if no peer port ID specified */
|
|
190
|
+ id = &opts.peer_port_id;
|
|
191
|
+ if ( memcmp ( id, &fc_empty_port_id, sizeof ( *id ) ) == 0 ) {
|
|
192
|
+ if ( fc_link_ok ( &opts.port->link ) &&
|
|
193
|
+ ! ( opts.port->flags & FC_PORT_HAS_FABRIC ) ) {
|
|
194
|
+ id = &opts.port->ptp_link_port_id;
|
166
|
195
|
} else {
|
167
|
196
|
id = &fc_f_port_id;
|
168
|
197
|
}
|
169
|
198
|
}
|
170
|
|
- assert ( id != NULL );
|
171
|
199
|
|
172
|
|
- if ( fcels ( port, id, handler ) != 0 )
|
173
|
|
- return 1;
|
|
200
|
+ /** Issue ELS */
|
|
201
|
+ if ( ( rc = fcels ( opts.port, id, handler ) ) != 0 )
|
|
202
|
+ return rc;
|
174
|
203
|
|
175
|
204
|
return 0;
|
176
|
205
|
}
|