iPXE
fcels.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2010 Michael Brown <mbrown@fensystems.co.uk>.
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., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301, USA.
18 *
19 * You can also choose to distribute this program under the terms of
20 * the Unmodified Binary Distribution Licence (as given in the file
21 * COPYING.UBDL), provided that you have satisfied its requirements.
22 */
23
24FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25
26#include <stdint.h>
27#include <stdlib.h>
28#include <string.h>
29#include <errno.h>
30#include <assert.h>
31#include <byteswap.h>
32#include <ipxe/interface.h>
33#include <ipxe/xfer.h>
34#include <ipxe/iobuf.h>
35#include <ipxe/process.h>
36#include <ipxe/fc.h>
37#include <ipxe/fcels.h>
38
39/** @file
40 *
41 * Fibre Channel Extended Link Services
42 *
43 */
44
45/** Fibre Channel ELS transaction debug message format */
46#define FCELS_FMT "FCELS %s %s %s %s"
47
48/** Fibre Channel ELS transaction debug message arguments */
49#define FCELS_ARGS( els ) \
50 (els)->port->name, \
51 ( (els)->handler ? (els)->handler->name : "unknown ELS" ), \
52 ( fc_els_is_request ( els ) ? "to" : "from" ), \
53 fc_id_ntoa ( &(els)->peer_port_id )
54
55struct fc_els_handler fc_els_unknown_handler __fc_els_handler;
56
57/**
58 * Free Fibre Channel ELS transaction
59 *
60 * @v refcnt Reference count
61 */
62static void fc_els_free ( struct refcnt *refcnt ) {
63 struct fc_els *els = container_of ( refcnt, struct fc_els, refcnt );
64
65 assert ( ! process_running ( &els->process ) );
66 fc_port_put ( els->port );
67 free ( els );
68}
69
70/**
71 * Close Fibre Channel ELS transaction
72 *
73 * @v els Fibre Channel ELS transaction
74 * @v rc Reason for close
75 */
76static void fc_els_close ( struct fc_els *els, int rc ) {
77
78 if ( rc != 0 ) {
79 DBGC ( els, FCELS_FMT " complete (%s)\n",
80 FCELS_ARGS ( els ), strerror ( rc ) );
81 }
82
83 /* Stop process */
84 process_del ( &els->process );
85
86 /* Shut down interfaces */
87 intf_shutdown ( &els->xchg, rc );
88 intf_shutdown ( &els->job, rc );
89}
90
91/**
92 * Detect Fibre Channel ELS frame handler
93 *
94 * @v els Fibre Channel ELS transaction
95 * @v command ELS command code
96 * @ret handler ELS handler, or NULL
97 */
98static struct fc_els_handler * fc_els_detect ( struct fc_els *els,
99 const void *data,
100 size_t len ) {
101 const struct fc_els_frame_common *frame = data;
102 struct fc_els_handler *handler;
103 int rc;
104
105 /* Sanity check */
106 if ( len < sizeof ( *frame ) )
107 return NULL;
108
109 /* Try each handler in turn */
111 if ( ( rc = handler->detect ( els, data, len ) ) == 0 )
112 return handler;
113 }
114
115 return NULL;
116}
117
118/**
119 * Transmit Fibre Channel ELS frame
120 *
121 * @v els Fibre Channel ELS transaction
122 * @v data Data to transmit
123 * @v len Length of data
124 * @ret rc Return status code
125 */
126int fc_els_tx ( struct fc_els *els, const void *data, size_t len ) {
127 struct xfer_metadata meta;
128 struct sockaddr_fc dest;
129 int rc;
130
131 DBGC2 ( els, FCELS_FMT " transmitting:\n", FCELS_ARGS ( els ) );
132 DBGC2_HDA ( els, 0, data, len );
133
134 /* Construct metadata */
135 memset ( &meta, 0, sizeof ( meta ) );
136 meta.flags = ( fc_els_is_request ( els ) ?
138 meta.dest = fc_fill_sockaddr ( &dest, &els->peer_port_id );
139
140 /* Transmit frame */
141 if ( ( rc = xfer_deliver_raw_meta ( &els->xchg, data, len,
142 &meta ) ) != 0 ) {
143 DBGC ( els, FCELS_FMT " could not deliver frame: %s\n",
144 FCELS_ARGS ( els ), strerror ( rc ) );
145 return rc;
146 }
147
148 return 0;
149}
150
151/**
152 * Receive Fibre Channel ELS frame
153 *
154 * @v els Fibre Channel ELS transaction
155 * @v iobuf I/O buffer
156 * @v meta Data transfer metadata
157 * @ret rc Return status code
158 */
159static int fc_els_rx ( struct fc_els *els,
160 struct io_buffer *iobuf,
161 struct xfer_metadata *meta ) {
162 struct fc_els_frame_common *frame = iobuf->data;
163 struct sockaddr_fc *src = ( ( struct sockaddr_fc * ) meta->src );
164 struct sockaddr_fc *dest = ( ( struct sockaddr_fc * ) meta->dest );
165 size_t len = iob_len ( iobuf );
166 int rc;
167
168 /* Sanity check */
169 if ( len < sizeof ( *frame ) ) {
170 DBGC ( els, FCELS_FMT " received underlength frame:\n",
171 FCELS_ARGS ( els ) );
172 DBGC_HDA ( els, 0, frame, len );
173 rc = -EINVAL;
174 goto done;
175 }
176 if ( ! src ) {
177 DBGC ( els, FCELS_FMT " received frame missing source "
178 "address:\n", FCELS_ARGS ( els ) );
179 rc = -EINVAL;
180 goto done;
181 }
182 if ( ! dest ) {
183 DBGC ( els, FCELS_FMT " received frame missing destination "
184 "address:\n", FCELS_ARGS ( els ) );
185 rc = -EINVAL;
186 goto done;
187 }
188
189 /* Check for rejection responses */
190 if ( fc_els_is_request ( els ) &&
191 ( frame->command != FC_ELS_LS_ACC ) ) {
192 DBGC ( els, FCELS_FMT " rejected:\n", FCELS_ARGS ( els ) );
193 DBGC_HDA ( els, 0, frame, len );
194 rc = -EACCES;
195 goto done;
196 }
197
198 /* Update port IDs */
199 memcpy ( &els->port_id, &dest->sfc_port_id, sizeof ( els->port_id ) );
200 memcpy ( &els->peer_port_id, &src->sfc_port_id,
201 sizeof ( els->peer_port_id ) );
202
203 /* Determine handler, if necessary */
204 if ( ! els->handler )
205 els->handler = fc_els_detect ( els, frame, len );
206 if ( ! els->handler )
207 els->handler = &fc_els_unknown_handler;
208
209 DBGC2 ( els, FCELS_FMT " received:\n", FCELS_ARGS ( els ) );
210 DBGC2_HDA ( els, 0, frame, len );
211
212 /* Handle received frame */
213 if ( ( rc = els->handler->rx ( els, frame, len ) ) != 0 ) {
214 DBGC ( els, FCELS_FMT " could not handle received frame: "
215 "%s\n", FCELS_ARGS ( els ), strerror ( rc ) );
216 DBGC_HDA ( els, 0, frame, len );
217 goto done;
218 }
219
220 done:
221 /* Free I/O buffer */
222 free_iob ( iobuf );
223
224 /* Close transaction */
225 fc_els_close ( els, rc );
226
227 return rc;
228}
229
230/** Fibre Channel ELS exchange interface operations */
232 INTF_OP ( xfer_deliver, struct fc_els *, fc_els_rx ),
233 INTF_OP ( intf_close, struct fc_els *, fc_els_close ),
234};
235
236/** Fibre Channel ELS exchange interface descriptor */
238 INTF_DESC ( struct fc_els, xchg, fc_els_xchg_op );
239
240/** Fibre Channel ELS job control interface operations */
242 INTF_OP ( intf_close, struct fc_els *, fc_els_close ),
243};
244
245/** Fibre Channel ELS job control interface descriptor */
247 INTF_DESC ( struct fc_els, job, fc_els_job_op );
248
249/**
250 * Fibre Channel ELS process
251 *
252 * @v els Fibre Channel ELS transaction
253 */
254static void fc_els_step ( struct fc_els *els ) {
255 int xchg_id;
256 int rc;
257
258 /* Sanity check */
259 assert ( fc_els_is_request ( els ) );
260
261 /* Create exchange */
262 if ( ( xchg_id = fc_xchg_originate ( &els->xchg, els->port,
263 &els->peer_port_id,
264 FC_TYPE_ELS ) ) < 0 ) {
265 rc = xchg_id;
266 DBGC ( els, FCELS_FMT " could not create exchange: %s\n",
267 FCELS_ARGS ( els ), strerror ( rc ) );
268 fc_els_close ( els, rc );
269 return;
270 }
271
272 /* Transmit request */
273 if ( ( rc = els->handler->tx ( els ) ) != 0 ) {
274 DBGC ( els, FCELS_FMT " could not transmit request: %s\n",
275 FCELS_ARGS ( els ), strerror ( rc ) );
276 fc_els_close ( els, rc );
277 return;
278 }
279}
280
281/** Fibre Channel ELS process descriptor */
284
285/**
286 * Create ELS transaction
287 *
288 * @v port Fibre Channel port
289 * @v port_id Local port ID
290 * @v peer_port_id Peer port ID
291 * @ret els Fibre Channel ELS transaction, or NULL
292 */
293static struct fc_els * fc_els_create ( struct fc_port *port,
294 struct fc_port_id *port_id,
295 struct fc_port_id *peer_port_id ) {
296 struct fc_els *els;
297
298 /* Allocate and initialise structure */
299 els = zalloc ( sizeof ( *els ) );
300 if ( ! els )
301 return NULL;
302 ref_init ( &els->refcnt, fc_els_free );
303 intf_init ( &els->job, &fc_els_job_desc, &els->refcnt );
304 intf_init ( &els->xchg, &fc_els_xchg_desc, &els->refcnt );
306 &els->refcnt );
307 els->port = fc_port_get ( port );
308 memcpy ( &els->port_id, port_id, sizeof ( els->port_id ) );
310 sizeof ( els->peer_port_id ) );
311 return els;
312}
313
314/**
315 * Create ELS request
316 *
317 * @v job Parent job-control interface
318 * @v port Fibre Channel port
319 * @v peer_port_id Peer port ID
320 * @v handler ELS handler
321 * @ret rc Return status code
322 */
323int fc_els_request ( struct interface *job, struct fc_port *port,
324 struct fc_port_id *peer_port_id,
325 struct fc_els_handler *handler ) {
326 struct fc_els *els;
327
328 /* Allocate and initialise structure */
329 els = fc_els_create ( port, &port->port_id, peer_port_id );
330 if ( ! els )
331 return -ENOMEM;
332 els->handler = handler;
333 els->flags = FC_ELS_REQUEST;
334 process_add ( &els->process );
335
336 /* Attach to parent job interface, mortalise self, and return */
337 intf_plug_plug ( &els->job, job );
338 ref_put ( &els->refcnt );
339 return 0;
340}
341
342/**
343 * Create ELS response
344 *
345 * @v xchg Exchange interface
346 * @v port Fibre Channel port
347 * @v port_id Local port ID
348 * @v peer_port_id Peer port ID
349 * @ret rc Return status code
350 */
351static int fc_els_respond ( struct interface *xchg, struct fc_port *port,
352 struct fc_port_id *port_id,
353 struct fc_port_id *peer_port_id ) {
354 struct fc_els *els;
355
356 /* Allocate and initialise structure */
358 if ( ! els )
359 return -ENOMEM;
360
361 /* Attach to exchange interface, mortalise self, and return */
362 intf_plug_plug ( &els->xchg, xchg );
363 ref_put ( &els->refcnt );
364 return 0;
365}
366
367/** Fibre Channel ELS responder */
368struct fc_responder fc_els_responder __fc_responder = {
369 .type = FC_TYPE_ELS,
370 .respond = fc_els_respond,
371};
372
373/******************************************************************************
374 *
375 * Unknown ELS handler
376 *
377 ******************************************************************************
378 */
379
380/**
381 * Transmit unknown ELS request
382 *
383 * @v els Fibre Channel ELS transaction
384 * @ret rc Return status code
385 */
386static int fc_els_unknown_tx ( struct fc_els *els __unused ) {
387 return -ENOTSUP;
388}
389
390/**
391 * Transmit unknown ELS response
392 *
393 * @v els Fibre Channel ELS transaction
394 * @ret rc Return status code
395 */
396static int fc_els_unknown_tx_response ( struct fc_els *els ) {
397 struct fc_ls_rjt_frame ls_rjt;
398
399 /* Construct LS_RJT */
400 memset ( &ls_rjt, 0, sizeof ( ls_rjt ) );
401 ls_rjt.command = FC_ELS_LS_RJT;
403
404 /* Transmit LS_RJT */
405 return fc_els_tx ( els, &ls_rjt, sizeof ( ls_rjt ) );
406}
407
408/**
409 * Receive unknown ELS
410 *
411 * @v els Fibre Channel ELS transaction
412 * @v data ELS frame
413 * @v len Length of ELS frame
414 * @ret rc Return status code
415 */
416static int fc_els_unknown_rx ( struct fc_els *els, void *data, size_t len ) {
417 int rc;
418
419 DBGC ( els, FCELS_FMT ":\n", FCELS_ARGS ( els ) );
420 DBGC_HDA ( els, 0, data, len );
421
422 /* Transmit response, if applicable */
423 if ( ! fc_els_is_request ( els ) ) {
424 if ( ( rc = fc_els_unknown_tx_response ( els ) ) != 0 )
425 return rc;
426 }
427
428 return 0;
429}
430
431/**
432 * Detect unknown ELS
433 *
434 * @v els Fibre Channel ELS transaction
435 * @v data ELS frame
436 * @v len Length of ELS frame
437 * @ret rc Return status code
438 */
439static int fc_els_unknown_detect ( struct fc_els *els __unused,
440 const void *data __unused,
441 size_t len __unused ) {
442 return -ENOTSUP;
443}
444
445/** Unknown ELS handler */
446struct fc_els_handler fc_els_unknown_handler __fc_els_handler = {
447 .name = "UNKNOWN",
448 .tx = fc_els_unknown_tx,
449 .rx = fc_els_unknown_rx,
450 .detect = fc_els_unknown_detect,
451};
452
453/******************************************************************************
454 *
455 * FLOGI
456 *
457 ******************************************************************************
458 */
459
460/**
461 * Transmit FLOGI
462 *
463 * @v els Fibre Channel ELS transaction
464 * @ret rc Return status code
465 */
466static int fc_els_flogi_tx ( struct fc_els *els ) {
467 struct fc_login_frame flogi;
468
469 /* Construct FLOGI */
470 memset ( &flogi, 0, sizeof ( flogi ) );
471 flogi.command = fc_els_tx_command ( els, FC_ELS_FLOGI );
476 memcpy ( &flogi.port_wwn, &els->port->port_wwn,
477 sizeof ( flogi.port_wwn ) );
478 memcpy ( &flogi.node_wwn, &els->port->node_wwn,
479 sizeof ( flogi.node_wwn ) );
482
483 /* Transmit FLOGI */
484 return fc_els_tx ( els, &flogi, sizeof ( flogi ) );
485}
486
487/**
488 * Receive FLOGI
489 *
490 * @v els Fibre Channel ELS transaction
491 * @v data ELS frame
492 * @v len Length of ELS frame
493 * @ret rc Return status code
494 */
495static int fc_els_flogi_rx ( struct fc_els *els, void *data, size_t len ) {
496 struct fc_login_frame *flogi = data;
497 int has_fabric;
498 int rc;
499
500 /* Sanity check */
501 if ( len < sizeof ( *flogi ) ) {
502 DBGC ( els, FCELS_FMT " received underlength frame:\n",
503 FCELS_ARGS ( els ) );
504 DBGC_HDA ( els, 0, data, len );
505 return -EINVAL;
506 }
507
508 /* Extract parameters */
509 has_fabric = ( flogi->common.flags & htons ( FC_LOGIN_F_PORT ) );
510 DBGC ( els, FCELS_FMT " has node %s\n", FCELS_ARGS ( els ),
511 fc_ntoa ( &flogi->node_wwn ) );
512 DBGC ( els, FCELS_FMT " has port %s\n", FCELS_ARGS ( els ),
513 fc_ntoa ( &flogi->port_wwn ) );
514 if ( has_fabric ) {
515 DBGC ( els, FCELS_FMT " has fabric with", FCELS_ARGS ( els ) );
516 DBGC ( els, " local ID %s\n", fc_id_ntoa ( &els->port_id ) );
517 } else {
518 DBGC ( els, FCELS_FMT " has point-to-point link\n",
519 FCELS_ARGS ( els ) );
520 }
521
522 /* Log in port */
523 if ( ( rc = fc_port_login ( els->port, &els->port_id, &flogi->node_wwn,
524 &flogi->port_wwn, has_fabric ) ) != 0 ) {
525 DBGC ( els, FCELS_FMT " could not log in port: %s\n",
526 FCELS_ARGS ( els ), strerror ( rc ) );
527 return rc;
528 }
529
530 /* Send any responses to the newly-assigned peer port ID, if
531 * applicable.
532 */
533 if ( ! has_fabric ) {
535 sizeof ( els->peer_port_id ) );
536 }
537
538 /* Transmit response, if applicable */
539 if ( ! fc_els_is_request ( els ) ) {
540 if ( ( rc = fc_els_flogi_tx ( els ) ) != 0 )
541 return rc;
542 }
543
544 return 0;
545}
546
547/**
548 * Detect FLOGI
549 *
550 * @v els Fibre Channel ELS transaction
551 * @v data ELS frame
552 * @v len Length of ELS frame
553 * @ret rc Return status code
554 */
555static int fc_els_flogi_detect ( struct fc_els *els __unused, const void *data,
556 size_t len __unused ) {
557 const struct fc_login_frame *flogi = data;
558
559 /* Check for FLOGI */
560 if ( flogi->command != FC_ELS_FLOGI )
561 return -EINVAL;
562
563 return 0;
564}
565
566/** FLOGI ELS handler */
567struct fc_els_handler fc_els_flogi_handler __fc_els_handler = {
568 .name = "FLOGI",
569 .tx = fc_els_flogi_tx,
570 .rx = fc_els_flogi_rx,
571 .detect = fc_els_flogi_detect,
572};
573
574/**
575 * Create FLOGI request
576 *
577 * @v parent Parent interface
578 * @v port Fibre Channel port
579 * @ret rc Return status code
580 */
581int fc_els_flogi ( struct interface *parent, struct fc_port *port ) {
582
583 return fc_els_request ( parent, port, &fc_f_port_id,
584 &fc_els_flogi_handler );
585}
586
587/******************************************************************************
588 *
589 * PLOGI
590 *
591 ******************************************************************************
592 */
593
594/**
595 * Transmit PLOGI
596 *
597 * @v els Fibre Channel ELS transaction
598 * @ret rc Return status code
599 */
600static int fc_els_plogi_tx ( struct fc_els *els ) {
601 struct fc_login_frame plogi;
602
603 /* Construct PLOGI */
604 memset ( &plogi, 0, sizeof ( plogi ) );
605 plogi.command = fc_els_tx_command ( els, FC_ELS_PLOGI );
613 memcpy ( &plogi.port_wwn, &els->port->port_wwn,
614 sizeof ( plogi.port_wwn ) );
615 memcpy ( &plogi.node_wwn, &els->port->node_wwn,
616 sizeof ( plogi.node_wwn ) );
621 plogi.class3.max_seq_per_xchg = 1;
622
623 /* Transmit PLOGI */
624 return fc_els_tx ( els, &plogi, sizeof ( plogi ) );
625}
626
627/**
628 * Receive PLOGI
629 *
630 * @v els Fibre Channel ELS transaction
631 * @v data ELS frame
632 * @v len Length of ELS frame
633 * @ret rc Return status code
634 */
635static int fc_els_plogi_rx ( struct fc_els *els, void *data, size_t len ) {
636 struct fc_login_frame *plogi = data;
637 struct fc_peer *peer;
638 int rc;
639
640 /* Sanity checks */
641 if ( len < sizeof ( *plogi ) ) {
642 DBGC ( els, FCELS_FMT " received underlength frame:\n",
643 FCELS_ARGS ( els ) );
644 DBGC_HDA ( els, 0, data, len );
645 rc = -EINVAL;
646 goto err_sanity;
647 }
648 if ( ! fc_link_ok ( &els->port->link ) ) {
649 DBGC ( els, FCELS_FMT " received while port link is down\n",
650 FCELS_ARGS ( els ) );
651 rc = -EINVAL;
652 goto err_sanity;
653 }
654
655 /* Extract parameters */
656 DBGC ( els, FCELS_FMT " has node %s\n", FCELS_ARGS ( els ),
657 fc_ntoa ( &plogi->node_wwn ) );
658 DBGC ( els, FCELS_FMT " has port %s as %s\n",
659 FCELS_ARGS ( els ), fc_ntoa ( &plogi->port_wwn ),
660 fc_id_ntoa ( &els->peer_port_id ) );
661
662 /* Get peer */
663 peer = fc_peer_get_wwn ( &plogi->port_wwn );
664 if ( ! peer ) {
665 DBGC ( els, FCELS_FMT " could not create peer\n",
666 FCELS_ARGS ( els ) );
667 rc = -ENOMEM;
668 goto err_peer_get_wwn;
669 }
670
671 /* Record login */
672 if ( ( rc = fc_peer_login ( peer, els->port,
673 &els->peer_port_id ) ) != 0 ) {
674 DBGC ( els, FCELS_FMT " could not log in peer: %s\n",
675 FCELS_ARGS ( els ), strerror ( rc ) );
676 goto err_login;
677 }
678
679 /* Transmit response, if applicable */
680 if ( ! fc_els_is_request ( els ) ) {
681 if ( ( rc = fc_els_plogi_tx ( els ) ) != 0 )
682 goto err_plogi_tx;
683 }
684
685 /* Drop temporary reference to peer */
686 fc_peer_put ( peer );
687
688 return 0;
689
690 err_plogi_tx:
691 err_login:
692 fc_peer_put ( peer );
693 err_peer_get_wwn:
694 err_sanity:
695 return rc;
696}
697
698/**
699 * Detect PLOGI
700 *
701 * @v els Fibre Channel ELS transaction
702 * @v data ELS frame
703 * @v len Length of ELS frame
704 * @ret rc Return status code
705 */
706static int fc_els_plogi_detect ( struct fc_els *els __unused, const void *data,
707 size_t len __unused ) {
708 const struct fc_login_frame *plogi = data;
709
710 /* Check for PLOGI */
711 if ( plogi->command != FC_ELS_PLOGI )
712 return -EINVAL;
713
714 return 0;
715}
716
717/** PLOGI ELS handler */
718struct fc_els_handler fc_els_plogi_handler __fc_els_handler = {
719 .name = "PLOGI",
720 .tx = fc_els_plogi_tx,
721 .rx = fc_els_plogi_rx,
722 .detect = fc_els_plogi_detect,
723};
724
725/**
726 * Create PLOGI request
727 *
728 * @v parent Parent interface
729 * @v port Fibre Channel port
730 * @v peer_port_id Peer port ID
731 * @ret rc Return status code
732 */
733int fc_els_plogi ( struct interface *parent, struct fc_port *port,
734 struct fc_port_id *peer_port_id ) {
735
736 return fc_els_request ( parent, port, peer_port_id,
737 &fc_els_plogi_handler );
738}
739
740/******************************************************************************
741 *
742 * LOGO
743 *
744 ******************************************************************************
745 */
746
747/**
748 * Transmit LOGO request
749 *
750 * @v els Fibre Channel ELS transaction
751 * @ret rc Return status code
752 */
753static int fc_els_logo_tx ( struct fc_els *els ) {
754 struct fc_logout_request_frame logo;
755
756 /* Construct LOGO */
757 memset ( &logo, 0, sizeof ( logo ) );
758 logo.command = FC_ELS_LOGO;
759 memcpy ( &logo.port_id, &els->port->port_id, sizeof ( logo.port_id ) );
760 memcpy ( &logo.port_wwn, &els->port->port_wwn,
761 sizeof ( logo.port_wwn ) );
762
763 /* Transmit LOGO */
764 return fc_els_tx ( els, &logo, sizeof ( logo ) );
765}
766
767/**
768 * Transmit LOGO response
769 *
770 * @v els Fibre Channel ELS transaction
771 * @ret rc Return status code
772 */
773static int fc_els_logo_tx_response ( struct fc_els *els ) {
774 struct fc_logout_response_frame logo;
775
776 /* Construct LOGO */
777 memset ( &logo, 0, sizeof ( logo ) );
778 logo.command = FC_ELS_LS_ACC;
779
780 /* Transmit LOGO */
781 return fc_els_tx ( els, &logo, sizeof ( logo ) );
782}
783
784/**
785 * Log out individual peer or whole port as applicable
786 *
787 * @v els Fibre Channel ELS transaction
788 * @v port_id Peer port ID
789 */
790static void fc_els_logo_logout ( struct fc_els *els,
791 struct fc_port_id *peer_port_id ) {
792 struct fc_peer *peer;
793
794 if ( ( memcmp ( peer_port_id, &fc_f_port_id,
795 sizeof ( *peer_port_id ) ) == 0 ) ||
796 ( memcmp ( peer_port_id, &els->port->port_id,
797 sizeof ( *peer_port_id ) ) == 0 ) ) {
798 fc_port_logout ( els->port, 0 );
799 } else {
800 peer = fc_peer_get_port_id ( els->port, peer_port_id );
801 if ( peer ) {
802 fc_peer_logout ( peer, 0 );
803 fc_peer_put ( peer );
804 }
805 }
806}
807
808/**
809 * Receive LOGO request
810 *
811 * @v els Fibre Channel ELS transaction
812 * @v data ELS frame
813 * @v len Length of ELS frame
814 * @ret rc Return status code
815 */
816static int fc_els_logo_rx_request ( struct fc_els *els, void *data,
817 size_t len ) {
818 struct fc_logout_request_frame *logo = data;
819 int rc;
820
821 /* Sanity check */
822 if ( len < sizeof ( *logo ) ) {
823 DBGC ( els, FCELS_FMT " received underlength frame:\n",
824 FCELS_ARGS ( els ) );
825 DBGC_HDA ( els, 0, data, len );
826 return -EINVAL;
827 }
828
829 DBGC ( els, FCELS_FMT " has port %s as %s\n", FCELS_ARGS ( els ),
830 fc_ntoa ( &logo->port_wwn ), fc_id_ntoa ( &logo->port_id ) );
831
832 /* Log out individual peer or whole port as applicable */
833 fc_els_logo_logout ( els, &logo->port_id );
834
835 /* Transmit repsonse */
836 if ( ( rc = fc_els_logo_tx_response ( els ) ) != 0 )
837 return rc;
838
839 return 0;
840}
841
842/**
843 * Receive LOGO response
844 *
845 * @v els Fibre Channel ELS transaction
846 * @v data ELS frame
847 * @v len Length of ELS frame
848 * @ret rc Return status code
849 */
850static int fc_els_logo_rx_response ( struct fc_els *els, void *data __unused,
851 size_t len __unused ) {
852
853 /* Log out individual peer or whole port as applicable */
854 fc_els_logo_logout ( els, &els->peer_port_id );
855
856 return 0;
857}
858
859/**
860 * Receive LOGO
861 *
862 * @v els Fibre Channel ELS transaction
863 * @v data ELS frame
864 * @v len Length of ELS frame
865 * @ret rc Return status code
866 */
867static int fc_els_logo_rx ( struct fc_els *els, void *data, size_t len ) {
868
869 if ( fc_els_is_request ( els ) ) {
870 return fc_els_logo_rx_response ( els, data, len );
871 } else {
872 return fc_els_logo_rx_request ( els, data, len );
873 }
874}
875
876/**
877 * Detect LOGO
878 *
879 * @v els Fibre Channel ELS transaction
880 * @v data ELS frame
881 * @v len Length of ELS frame
882 * @ret rc Return status code
883 */
884static int fc_els_logo_detect ( struct fc_els *els __unused, const void *data,
885 size_t len __unused ) {
886 const struct fc_logout_request_frame *logo = data;
887
888 /* Check for LOGO */
889 if ( logo->command != FC_ELS_LOGO )
890 return -EINVAL;
891
892 return 0;
893}
894
895/** LOGO ELS handler */
896struct fc_els_handler fc_els_logo_handler __fc_els_handler = {
897 .name = "LOGO",
898 .tx = fc_els_logo_tx,
899 .rx = fc_els_logo_rx,
900 .detect = fc_els_logo_detect,
901};
902
903/**
904 * Create LOGO request
905 *
906 * @v parent Parent interface
907 * @v port Fibre Channel port
908 * @v peer_port_id Peer port ID
909 * @ret rc Return status code
910 */
911int fc_els_logo ( struct interface *parent, struct fc_port *port,
912 struct fc_port_id *peer_port_id ) {
913
914 return fc_els_request ( parent, port, peer_port_id,
915 &fc_els_logo_handler );
916}
917
918/******************************************************************************
919 *
920 * PRLI
921 *
922 ******************************************************************************
923 */
924
925/**
926 * Find PRLI descriptor
927 *
928 * @v type Upper-layer protocol type
929 * @ret descriptor PRLI descriptor, or NULL
930 */
931static struct fc_els_prli_descriptor *
932fc_els_prli_descriptor ( unsigned int type ) {
933 struct fc_els_prli_descriptor *descriptor;
934
936 if ( descriptor->type == type )
937 return descriptor;
938 }
939 return NULL;
940}
941
942/**
943 * Transmit PRLI
944 *
945 * @v els Fibre Channel ELS transaction
946 * @v descriptor ELS PRLI descriptor
947 * @v param Service parameters
948 * @ret rc Return status code
949 */
950int fc_els_prli_tx ( struct fc_els *els,
951 struct fc_els_prli_descriptor *descriptor, void *param ) {
952 struct {
953 struct fc_prli_frame frame;
954 uint8_t param[descriptor->param_len];
955 } __attribute__ (( packed )) prli;
956 struct fc_ulp *ulp;
957 int rc;
958
959 /* Get ULP */
960 ulp = fc_ulp_get_port_id_type ( els->port, &els->peer_port_id,
961 descriptor->type );
962 if ( ! ulp ) {
963 rc = -ENOMEM;
964 goto err_get_port_id_type;
965 }
966
967 /* Build frame for transmission */
968 memset ( &prli, 0, sizeof ( prli ) );
969 prli.frame.command = fc_els_tx_command ( els, FC_ELS_PRLI );
970 prli.frame.page_len =
971 ( sizeof ( prli.frame.page ) + sizeof ( prli.param ) );
972 prli.frame.len = htons ( sizeof ( prli ) );
973 prli.frame.page.type = descriptor->type;
974 if ( fc_els_is_request ( els ) ) {
975 prli.frame.page.flags |= htons ( FC_PRLI_ESTABLISH );
976 } else if ( fc_link_ok ( &ulp->link ) ) {
977 prli.frame.page.flags |= htons ( FC_PRLI_ESTABLISH |
979 }
980 memcpy ( &prli.param, param, sizeof ( prli.param ) );
981
982 /* Transmit frame */
983 if ( ( rc = fc_els_tx ( els, &prli, sizeof ( prli ) ) ) != 0 )
984 goto err_tx;
985
986 /* Drop temporary reference to ULP */
987 fc_ulp_put ( ulp );
988
989 return 0;
990
991 err_tx:
992 fc_ulp_put ( ulp );
993 err_get_port_id_type:
994 return rc;
995}
996
997/**
998 * Receive PRLI
999 *
1000 * @v els Fibre Channel ELS transaction
1001 * @v descriptor ELS PRLI descriptor
1002 * @v frame ELS frame
1003 * @v len Length of ELS frame
1004 * @ret rc Return status code
1005 */
1006int fc_els_prli_rx ( struct fc_els *els,
1007 struct fc_els_prli_descriptor *descriptor,
1008 void *data, size_t len ) {
1009 struct {
1010 struct fc_prli_frame frame;
1011 uint8_t param[descriptor->param_len];
1012 } __attribute__ (( packed )) *prli = data;
1013 struct fc_ulp *ulp;
1014 int rc;
1015
1016 /* Sanity check */
1017 if ( len < sizeof ( *prli ) ) {
1018 DBGC ( els, FCELS_FMT " received underlength frame:\n",
1019 FCELS_ARGS ( els ) );
1020 DBGC_HDA ( els, 0, data, len );
1021 rc = -EINVAL;
1022 goto err_sanity;
1023 }
1024
1025 DBGC ( els, FCELS_FMT " has parameters:\n", FCELS_ARGS ( els ) );
1026 DBGC_HDA ( els, 0, prli->param, sizeof ( prli->param ) );
1027
1028 /* Get ULP */
1029 ulp = fc_ulp_get_port_id_type ( els->port, &els->peer_port_id,
1030 descriptor->type );
1031 if ( ! ulp ) {
1032 rc = -ENOMEM;
1033 goto err_get_port_id_type;
1034 }
1035
1036 /* Sanity check */
1037 if ( ! fc_link_ok ( &ulp->peer->link ) ) {
1038 DBGC ( els, FCELS_FMT " received while peer link is down\n",
1039 FCELS_ARGS ( els ) );
1040 rc = -EINVAL;
1041 goto err_link;
1042 }
1043
1044 /* Log in ULP, if applicable */
1045 if ( prli->frame.page.flags & htons ( FC_PRLI_ESTABLISH ) ) {
1046 if ( ( rc = fc_ulp_login ( ulp, prli->param,
1047 sizeof ( prli->param ),
1048 fc_els_is_request ( els ) ) ) != 0 ){
1049 DBGC ( els, FCELS_FMT " could not log in ULP: %s\n",
1050 FCELS_ARGS ( els ), strerror ( rc ) );
1051 goto err_login;
1052 }
1053 } else {
1054 if ( fc_els_is_request ( els ) ) {
1055 fc_ulp_logout ( ulp, -EACCES );
1056 } else {
1057 /* This is just an information-gathering PRLI; do not
1058 * log in or out
1059 */
1060 }
1061 }
1062
1063 /* Transmit response, if applicable */
1064 if ( ! fc_els_is_request ( els ) ) {
1065 if ( ( rc = els->handler->tx ( els ) ) != 0 )
1066 goto err_tx;
1067 }
1068
1069 /* Drop temporary reference to ULP */
1070 fc_ulp_put ( ulp );
1071
1072 return 0;
1073
1074 err_tx:
1075 err_login:
1076 err_link:
1077 fc_ulp_put ( ulp );
1078 err_get_port_id_type:
1079 err_sanity:
1080 return rc;
1081}
1082
1083/**
1084 * Detect PRLI
1085 *
1086 * @v els Fibre Channel ELS transaction
1087 * @v descriptor ELS PRLI descriptor
1088 * @v data ELS frame
1089 * @v len Length of ELS frame
1090 * @ret rc Return status code
1091 */
1093 struct fc_els_prli_descriptor *descriptor,
1094 const void *data, size_t len ) {
1095 const struct {
1096 struct fc_prli_frame frame;
1097 uint8_t param[descriptor->param_len];
1098 } __attribute__ (( packed )) *prli = data;
1099
1100 /* Check for PRLI */
1101 if ( prli->frame.command != FC_ELS_PRLI )
1102 return -EINVAL;
1103
1104 /* Check for sufficient length to contain service parameter page */
1105 if ( len < sizeof ( *prli ) )
1106 return -EINVAL;
1107
1108 /* Check for upper-layer protocol type */
1109 if ( prli->frame.page.type != descriptor->type )
1110 return -EINVAL;
1111
1112 return 0;
1113}
1114
1115/**
1116 * Create PRLI request
1117 *
1118 * @v parent Parent interface
1119 * @v port Fibre Channel port
1120 * @v peer_port_id Peer port ID
1121 * @v type Upper-layer protocol type
1122 * @ret rc Return status code
1123 */
1124int fc_els_prli ( struct interface *parent, struct fc_port *port,
1125 struct fc_port_id *peer_port_id, unsigned int type ) {
1126 struct fc_els_prli_descriptor *descriptor;
1127
1128 /* Find a PRLI descriptor */
1129 descriptor = fc_els_prli_descriptor ( type );
1130 if ( ! descriptor )
1131 return -ENOTSUP;
1132
1133 return fc_els_request ( parent, port, peer_port_id,
1134 descriptor->handler );
1135}
1136
1137/******************************************************************************
1138 *
1139 * RTV
1140 *
1141 ******************************************************************************
1142 */
1143
1144/**
1145 * Transmit RTV response
1146 *
1147 * @v els Fibre Channel ELS transaction
1148 * @ret rc Return status code
1149 */
1150static int fc_els_rtv_tx_response ( struct fc_els *els ) {
1151 struct fc_rtv_response_frame rtv;
1152
1153 /* Construct RTV */
1154 memset ( &rtv, 0, sizeof ( rtv ) );
1155 rtv.command = FC_ELS_LS_ACC;
1157
1158 /* Transmit RTV */
1159 return fc_els_tx ( els, &rtv, sizeof ( rtv ) );
1160}
1161
1162/**
1163 * Receive RTV
1164 *
1165 * @v els Fibre Channel ELS transaction
1166 * @v data ELS frame
1167 * @v len Length of ELS frame
1168 * @ret rc Return status code
1169 */
1170static int fc_els_rtv_rx ( struct fc_els *els, void *data __unused,
1171 size_t len __unused ) {
1172 int rc;
1173
1174 DBGC ( els, FCELS_FMT "\n", FCELS_ARGS ( els ) );
1175
1176 /* Transmit response */
1177 if ( ! fc_els_is_request ( els ) ) {
1178 if ( ( rc = fc_els_rtv_tx_response ( els ) ) != 0 )
1179 return rc;
1180 }
1181
1182 return 0;
1183}
1184
1185/**
1186 * Detect RTV
1187 *
1188 * @v els Fibre Channel ELS transaction
1189 * @v data ELS frame
1190 * @v len Length of ELS frame
1191 * @ret rc Return status code
1192 */
1193static int fc_els_rtv_detect ( struct fc_els *els __unused, const void *data,
1194 size_t len __unused ) {
1195 const struct fc_rtv_request_frame *rtv = data;
1196
1197 /* Check for RTV */
1198 if ( rtv->command != FC_ELS_RTV )
1199 return -EINVAL;
1200
1201 return 0;
1202}
1203
1204/** RTV ELS handler */
1205struct fc_els_handler fc_els_rtv_handler __fc_els_handler = {
1206 .name = "RTV",
1207 .tx = fc_els_unknown_tx,
1208 .rx = fc_els_rtv_rx,
1209 .detect = fc_els_rtv_detect,
1210};
1211
1212/******************************************************************************
1213 *
1214 * ECHO
1215 *
1216 ******************************************************************************
1217 */
1218
1219/** ECHO request data */
1221 /** ECHO frame header */
1223 /** Magic marker */
1225} __attribute__ (( packed ));
1226
1227/** ECHO magic marker */
1228#define FC_ECHO_MAGIC 0x69505845
1229
1230/**
1231 * Transmit ECHO
1232 *
1233 * @v els Fibre Channel ELS transaction
1234 * @ret rc Return status code
1235 */
1236static int fc_els_echo_tx ( struct fc_els *els ) {
1238
1239 /* Construct ECHO */
1240 memset ( &echo, 0, sizeof ( echo ) );
1241 echo.echo.command = FC_ELS_ECHO;
1242 echo.magic = htonl ( FC_ECHO_MAGIC );
1243
1244 /* Transmit ECHO */
1245 return fc_els_tx ( els, &echo, sizeof ( echo ) );
1246}
1247
1248/**
1249 * Receive ECHO request
1250 *
1251 * @v els Fibre Channel ELS transaction
1252 * @v data ELS frame
1253 * @v len Length of ELS frame
1254 * @ret rc Return status code
1255 */
1256static int fc_els_echo_rx_request ( struct fc_els *els, void *data,
1257 size_t len ) {
1258 struct {
1260 char payload[ len - sizeof ( struct fc_echo_frame_header ) ];
1261 } *echo = data;
1262 int rc;
1263
1264 DBGC ( els, FCELS_FMT "\n", FCELS_ARGS ( els ) );
1265
1266 /* Transmit response */
1267 echo->echo.command = FC_ELS_LS_ACC;
1268 if ( ( rc = fc_els_tx ( els, echo, sizeof ( *echo ) ) ) != 0 )
1269 return rc;
1270
1271 /* Nothing to do */
1272 return 0;
1273}
1274
1275/**
1276 * Receive ECHO response
1277 *
1278 * @v els Fibre Channel ELS transaction
1279 * @v data ELS frame
1280 * @v len Length of ELS frame
1281 * @ret rc Return status code
1282 */
1283static int fc_els_echo_rx_response ( struct fc_els *els, void *data,
1284 size_t len ) {
1286
1287 DBGC ( els, FCELS_FMT "\n", FCELS_ARGS ( els ) );
1288
1289 /* Check response is correct */
1290 if ( ( len != sizeof ( *echo ) ) ||
1291 ( echo->magic != htonl ( FC_ECHO_MAGIC ) ) ) {
1292 DBGC ( els, FCELS_FMT " received bad echo response\n",
1293 FCELS_ARGS ( els ) );
1294 DBGC_HDA ( els, 0, data, len );
1295 return -EIO;
1296 }
1297
1298 return 0;
1299}
1300
1301/**
1302 * Receive ECHO
1303 *
1304 * @v els Fibre Channel ELS transaction
1305 * @v data ELS frame
1306 * @v len Length of ELS frame
1307 * @ret rc Return status code
1308 */
1309static int fc_els_echo_rx ( struct fc_els *els, void *data, size_t len ) {
1310
1311 if ( fc_els_is_request ( els ) ) {
1312 return fc_els_echo_rx_response ( els, data, len );
1313 } else {
1314 return fc_els_echo_rx_request ( els, data, len );
1315 }
1316}
1317
1318/**
1319 * Detect ECHO
1320 *
1321 * @v els Fibre Channel ELS transaction
1322 * @v data ELS frame
1323 * @v len Length of ELS frame
1324 * @ret rc Return status code
1325 */
1326static int fc_els_echo_detect ( struct fc_els *els __unused, const void *data,
1327 size_t len __unused ) {
1328 const struct fc_echo_frame_header *echo = data;
1329
1330 /* Check for ECHO */
1331 if ( echo->command != FC_ELS_ECHO )
1332 return -EINVAL;
1333
1334 return 0;
1335}
1336
1337/** ECHO ELS handler */
1338struct fc_els_handler fc_els_echo_handler __fc_els_handler = {
1339 .name = "ECHO",
1340 .tx = fc_els_echo_tx,
1341 .rx = fc_els_echo_rx,
1342 .detect = fc_els_echo_detect,
1343};
#define NULL
NULL pointer (VOID *)
Definition Base.h:322
u8 port
Port number.
Definition CIB_PRM.h:3
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
unsigned int uint32_t
Definition stdint.h:12
unsigned char uint8_t
Definition stdint.h:10
if(len >=6 *4) __asm__ __volatile__("movsl" if(len >=5 *4) __asm__ __volatile__("movsl" if(len >=4 *4) __asm__ __volatile__("movsl" if(len >=3 *4) __asm__ __volatile__("movsl" if(len >=2 *4) __asm__ __volatile__("movsl" if(len >=1 *4) __asm__ __volatile__("movsl" if((len % 4) >=2) __asm__ __volatile__("movsw" if((len % 2) >=1) __asm__ __volatile__("movsb" retur dest)
Definition string.h:151
static const void * src
Definition string.h:48
Assertions.
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:50
struct bofm_section_header done
Definition bofm_test.c:46
ring len
Length.
Definition dwmac.h:226
uint32_t type
Operating system type.
Definition ena.h:1
uint8_t data[48]
Additional event data.
Definition ena.h:11
uint8_t meta
Metadata flags.
Definition ena.h:3
Error codes.
struct sockaddr * fc_fill_sockaddr(struct sockaddr_fc *sa_fc, struct fc_port_id *id)
Fill Fibre Channel socket address.
Definition fc.c:165
struct fc_peer * fc_peer_get_wwn(const struct fc_name *port_wwn)
Get Fibre Channel peer by node name.
Definition fc.c:1516
struct fc_peer * fc_peer_get_port_id(struct fc_port *port, const struct fc_port_id *peer_port_id)
Get Fibre Channel peer by port ID.
Definition fc.c:1541
struct fc_port_id fc_f_port_id
F_Port contoller port ID.
Definition fc.c:68
const char * fc_ntoa(const struct fc_name *wwn)
Format Fibre Channel WWN.
Definition fc.c:127
void fc_peer_logout(struct fc_peer *peer, int rc)
Log out Fibre Channel peer.
Definition fc.c:1347
int fc_port_login(struct fc_port *port, struct fc_port_id *port_id, const struct fc_name *link_node_wwn, const struct fc_name *link_port_wwn, int has_fabric)
Log in Fibre Channel port.
Definition fc.c:941
int fc_xchg_originate(struct interface *parent, struct fc_port *port, struct fc_port_id *peer_port_id, unsigned int type)
Originate a new Fibre Channel exchange.
Definition fc.c:728
const char * fc_id_ntoa(const struct fc_port_id *id)
Format Fibre Channel port ID.
Definition fc.c:92
void fc_ulp_logout(struct fc_ulp *ulp, int rc)
Log out Fibre Channel upper-layer protocol.
Definition fc.c:1727
int fc_peer_login(struct fc_peer *peer, struct fc_port *port, struct fc_port_id *port_id)
Log in Fibre Channel peer.
Definition fc.c:1300
struct fc_ulp * fc_ulp_get_port_id_type(struct fc_port *port, const struct fc_port_id *peer_port_id, unsigned int type)
Get Fibre Channel upper-layer protocol by port ID and type.
Definition fc.c:1915
void fc_port_logout(struct fc_port *port, int rc)
Log out Fibre Channel port.
Definition fc.c:1039
int fc_ulp_login(struct fc_ulp *ulp, const void *param, size_t param_len, int originated)
Log in Fibre Channel upper-layer protocol.
Definition fc.c:1657
Fibre Channel.
static void fc_peer_put(struct fc_peer *peer)
Drop reference to Fibre Channel peer.
Definition fc.h:391
@ FC_TYPE_ELS
Extended Link Service.
Definition fc.h:193
static void fc_ulp_put(struct fc_ulp *ulp)
Drop reference to Fibre Channel upper-layer protocol.
Definition fc.h:486
static void fc_port_put(struct fc_port *port)
Drop reference to Fibre Channel port.
Definition fc.h:316
static int fc_link_ok(struct fc_link_state *link)
Check Fibre Channel link state.
Definition fc.h:109
static struct fc_port * fc_port_get(struct fc_port *port)
Get reference to Fibre Channel port.
Definition fc.h:305
#define __fc_responder
Declare a Fibre Channel responder.
Definition fc.h:243
static void fc_els_step(struct fc_els *els)
Fibre Channel ELS process.
Definition fcels.c:254
#define FC_ECHO_MAGIC
ECHO magic marker.
Definition fcels.c:1228
static void fc_els_free(struct refcnt *refcnt)
Free Fibre Channel ELS transaction.
Definition fcels.c:62
static struct fc_els_prli_descriptor * fc_els_prli_descriptor(unsigned int type)
Find PRLI descriptor.
Definition fcels.c:932
static struct interface_operation fc_els_xchg_op[]
Fibre Channel ELS exchange interface operations.
Definition fcels.c:231
static int fc_els_echo_rx_response(struct fc_els *els, void *data, size_t len)
Receive ECHO response.
Definition fcels.c:1283
static int fc_els_respond(struct interface *xchg, struct fc_port *port, struct fc_port_id *port_id, struct fc_port_id *peer_port_id)
Create ELS response.
Definition fcels.c:351
static int fc_els_logo_tx(struct fc_els *els)
Transmit LOGO request.
Definition fcels.c:753
int fc_els_tx(struct fc_els *els, const void *data, size_t len)
Transmit Fibre Channel ELS frame.
Definition fcels.c:126
int fc_els_request(struct interface *job, struct fc_port *port, struct fc_port_id *peer_port_id, struct fc_els_handler *handler)
Create ELS request.
Definition fcels.c:323
static int fc_els_unknown_rx(struct fc_els *els, void *data, size_t len)
Receive unknown ELS.
Definition fcels.c:416
static int fc_els_logo_detect(struct fc_els *els __unused, const void *data, size_t len __unused)
Detect LOGO.
Definition fcels.c:884
static int fc_els_flogi_rx(struct fc_els *els, void *data, size_t len)
Receive FLOGI.
Definition fcels.c:495
static struct fc_els_handler * fc_els_detect(struct fc_els *els, const void *data, size_t len)
Detect Fibre Channel ELS frame handler.
Definition fcels.c:98
static int fc_els_logo_tx_response(struct fc_els *els)
Transmit LOGO response.
Definition fcels.c:773
static int fc_els_echo_detect(struct fc_els *els __unused, const void *data, size_t len __unused)
Detect ECHO.
Definition fcels.c:1326
#define FCELS_FMT
Fibre Channel ELS transaction debug message format.
Definition fcels.c:46
static int fc_els_plogi_detect(struct fc_els *els __unused, const void *data, size_t len __unused)
Detect PLOGI.
Definition fcels.c:706
static struct interface_descriptor fc_els_xchg_desc
Fibre Channel ELS exchange interface descriptor.
Definition fcels.c:237
static int fc_els_plogi_tx(struct fc_els *els)
Transmit PLOGI.
Definition fcels.c:600
static int fc_els_flogi_tx(struct fc_els *els)
Transmit FLOGI.
Definition fcels.c:466
static int fc_els_echo_rx_request(struct fc_els *els, void *data, size_t len)
Receive ECHO request.
Definition fcels.c:1256
static struct interface_operation fc_els_job_op[]
Fibre Channel ELS job control interface operations.
Definition fcels.c:241
static int fc_els_rx(struct fc_els *els, struct io_buffer *iobuf, struct xfer_metadata *meta)
Receive Fibre Channel ELS frame.
Definition fcels.c:159
static int fc_els_rtv_tx_response(struct fc_els *els)
Transmit RTV response.
Definition fcels.c:1150
static int fc_els_unknown_tx(struct fc_els *els __unused)
Transmit unknown ELS request.
Definition fcels.c:386
static int fc_els_logo_rx_request(struct fc_els *els, void *data, size_t len)
Receive LOGO request.
Definition fcels.c:816
#define FCELS_ARGS(els)
Fibre Channel ELS transaction debug message arguments.
Definition fcels.c:49
static int fc_els_rtv_rx(struct fc_els *els, void *data __unused, size_t len __unused)
Receive RTV.
Definition fcels.c:1170
static int fc_els_rtv_detect(struct fc_els *els __unused, const void *data, size_t len __unused)
Detect RTV.
Definition fcels.c:1193
int fc_els_prli(struct interface *parent, struct fc_port *port, struct fc_port_id *peer_port_id, unsigned int type)
Create PRLI request.
Definition fcels.c:1124
static struct process_descriptor fc_els_process_desc
Fibre Channel ELS process descriptor.
Definition fcels.c:282
int fc_els_flogi(struct interface *parent, struct fc_port *port)
Create FLOGI request.
Definition fcels.c:581
static void fc_els_logo_logout(struct fc_els *els, struct fc_port_id *peer_port_id)
Log out individual peer or whole port as applicable.
Definition fcels.c:790
static int fc_els_plogi_rx(struct fc_els *els, void *data, size_t len)
Receive PLOGI.
Definition fcels.c:635
int fc_els_plogi(struct interface *parent, struct fc_port *port, struct fc_port_id *peer_port_id)
Create PLOGI request.
Definition fcels.c:733
int fc_els_prli_tx(struct fc_els *els, struct fc_els_prli_descriptor *descriptor, void *param)
Transmit PRLI.
Definition fcels.c:950
static int fc_els_logo_rx(struct fc_els *els, void *data, size_t len)
Receive LOGO.
Definition fcels.c:867
static struct interface_descriptor fc_els_job_desc
Fibre Channel ELS job control interface descriptor.
Definition fcels.c:246
static int fc_els_unknown_tx_response(struct fc_els *els)
Transmit unknown ELS response.
Definition fcels.c:396
static struct fc_els * fc_els_create(struct fc_port *port, struct fc_port_id *port_id, struct fc_port_id *peer_port_id)
Create ELS transaction.
Definition fcels.c:293
static int fc_els_unknown_detect(struct fc_els *els __unused, const void *data __unused, size_t len __unused)
Detect unknown ELS.
Definition fcels.c:439
int fc_els_logo(struct interface *parent, struct fc_port *port, struct fc_port_id *peer_port_id)
Create LOGO request.
Definition fcels.c:911
static int fc_els_echo_rx(struct fc_els *els, void *data, size_t len)
Receive ECHO.
Definition fcels.c:1309
static int fc_els_logo_rx_response(struct fc_els *els, void *data __unused, size_t len __unused)
Receive LOGO response.
Definition fcels.c:850
static int fc_els_echo_tx(struct fc_els *els)
Transmit ECHO.
Definition fcels.c:1236
static int fc_els_flogi_detect(struct fc_els *els __unused, const void *data, size_t len __unused)
Detect FLOGI.
Definition fcels.c:555
static void fc_els_close(struct fc_els *els, int rc)
Close Fibre Channel ELS transaction.
Definition fcels.c:76
int fc_els_prli_detect(struct fc_els *els __unused, struct fc_els_prli_descriptor *descriptor, const void *data, size_t len)
Detect PRLI.
Definition fcels.c:1092
int fc_els_prli_rx(struct fc_els *els, struct fc_els_prli_descriptor *descriptor, void *data, size_t len)
Receive PRLI.
Definition fcels.c:1006
Fibre Channel Extended Link Services.
@ FC_ELS_FLOGI
Fabric Login.
Definition fcels.h:35
@ FC_ELS_RTV
Read Timeout Value.
Definition fcels.h:37
@ FC_ELS_LS_ACC
Link Service Accept.
Definition fcels.h:33
@ FC_ELS_PLOGI
Port Login.
Definition fcels.h:34
@ FC_ELS_PRLI
Process Login.
Definition fcels.h:39
@ FC_ELS_LOGO
Logout.
Definition fcels.h:36
@ FC_ELS_LS_RJT
Link Service Reject.
Definition fcels.h:32
@ FC_ELS_ECHO
Echo.
Definition fcels.h:38
#define FC_LOGIN_CONTINUOUS_OFFSET
Continuously increasing relative offset.
Definition fcels.h:109
#define FC_LOGIN_CLASS_SEQUENTIAL
Sequential delivery requested.
Definition fcels.h:206
#define FC_LOGIN_DEFAULT_REL_OFFS
Default relative offset by info category.
Definition fcels.h:175
#define FC_LOGIN_DEFAULT_E_D_TOV
Default E_D timeout value.
Definition fcels.h:178
#define FC_LOGIN_VERSION
Fibre Channel default login version.
Definition fcels.h:103
#define FC_LOGIN_DEFAULT_MAX_SEQ
Default maximum number of concurrent sequences.
Definition fcels.h:172
#define FC_LOGIN_DEFAULT_MTU
Fibre Channel default MTU.
Definition fcels.h:169
#define __fc_els_handler
Declare a Fibre Channel ELS handler.
Definition fcels.h:384
#define FC_PRLI_RESPONSE_SUCCESS
Request was executed successfully.
Definition fcels.h:271
#define FC_ELS_HANDLERS
Fibre Channel ELS handler table.
Definition fcels.h:381
#define FC_LOGIN_CLASS_VALID
Class valid.
Definition fcels.h:203
#define FC_ELS_PRLI_DESCRIPTORS
Fibre Channel ELS PRLI descriptor table.
Definition fcels.h:397
static unsigned int fc_els_tx_command(struct fc_els *els, unsigned int request_command)
Calculate ELS command to transmit.
Definition fcels.h:420
static int fc_els_is_request(struct fc_els *els)
Check if Fibre Channel ELS transaction is a request.
Definition fcels.h:409
#define FC_PRLI_ESTABLISH
Establish image pair.
Definition fcels.h:265
#define FC_LOGIN_DEFAULT_B2B
Fibre Channel default buffer-to-buffer credit.
Definition fcels.h:106
@ FC_ELS_REQUEST
ELS transaction is a request.
Definition fcels.h:349
@ FC_ELS_RJT_UNSUPPORTED
Command not supported.
Definition fcels.h:70
#define FC_LOGIN_F_PORT
Forwarder port.
Definition fcels.h:130
#define __unused
Declare a variable or data structure as unused.
Definition compiler.h:573
#define DBGC2(...)
Definition compiler.h:522
#define DBGC2_HDA(...)
Definition compiler.h:523
#define DBGC(...)
Definition compiler.h:505
#define DBGC_HDA(...)
Definition compiler.h:506
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:896
#define EINVAL
Invalid argument.
Definition errno.h:429
#define ENOMEM
Not enough space.
Definition errno.h:535
#define EIO
Input/output error.
Definition errno.h:434
#define ENOTSUP
Operation not supported.
Definition errno.h:590
#define EACCES
Permission denied.
Definition errno.h:299
#define htonl(value)
Definition byteswap.h:134
#define htons(value)
Definition byteswap.h:136
#define __attribute__(x)
Definition compiler.h:10
struct hv_monitor_parameter param[4][32]
Parameters.
Definition hyperv.h:13
String functions.
void * memcpy(void *dest, const void *src, size_t len) __nonnull
void * memset(void *dest, int character, size_t len) __nonnull
void intf_close(struct interface *intf, int rc)
Close an object interface.
Definition interface.c:250
void intf_plug_plug(struct interface *a, struct interface *b)
Plug two object interfaces together.
Definition interface.c:108
void intf_shutdown(struct interface *intf, int rc)
Shut down an object interface.
Definition interface.c:279
Object interfaces.
#define INTF_DESC(object_type, intf, operations)
Define an object interface descriptor.
Definition interface.h:81
static void intf_init(struct interface *intf, struct interface_descriptor *desc, struct refcnt *refcnt)
Initialise an object interface.
Definition interface.h:204
#define INTF_OP(op_type, object_type, op_func)
Define an object interface operation.
Definition interface.h:33
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition iobuf.c:153
I/O buffers.
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition iobuf.h:160
int echo(void)
Definition kb.c:133
void * zalloc(size_t size)
Allocate cleared memory.
Definition malloc.c:662
struct mschapv2_challenge peer
Peer challenge.
Definition mschapv2.h:1
void process_del(struct process *process)
Remove process from process list.
Definition process.c:80
void process_add(struct process *process)
Add process to process list.
Definition process.c:60
Processes.
#define PROC_DESC_ONCE(object_type, process, _step)
Define a process descriptor for a process that runs only once.
Definition process.h:98
static int process_running(struct process *process)
Check if process is running.
Definition process.h:176
static void process_init_stopped(struct process *process, struct process_descriptor *desc, struct refcnt *refcnt)
Initialise process without adding to process list.
Definition process.h:146
static void(* free)(struct refcnt *refcnt))
Definition refcnt.h:55
#define ref_put(refcnt)
Drop reference to object.
Definition refcnt.h:107
#define ref_init(refcnt, free)
Initialise a reference counter.
Definition refcnt.h:65
#define container_of(ptr, type, field)
Get containing structure.
Definition stddef.h:36
char * strerror(int errno)
Retrieve string representation of error number.
Definition strerror.c:79
int memcmp(const void *first, const void *second, size_t len)
Compare memory regions.
Definition string.c:115
A Fibre Channel ECHO frame.
Definition fcels.h:316
ECHO request data.
Definition fcels.c:1220
uint32_t magic
Magic marker.
Definition fcels.c:1224
struct fc_echo_frame_header echo
ECHO frame header.
Definition fcels.c:1222
Fibre Channel ELS frame common parameters.
Definition fcels.h:23
A Fibre Channel extended link services handler.
Definition fcels.h:353
int(* rx)(struct fc_els *els, void *data, size_t len)
Receive ELS frame.
Definition fcels.h:369
int(* tx)(struct fc_els *els)
Transmit ELS frame.
Definition fcels.h:361
int(* detect)(struct fc_els *els, const void *data, size_t len)
Detect ELS frame.
Definition fcels.h:377
A Fibre Channel ELS PRLI descriptor.
Definition fcels.h:387
struct fc_els_handler * handler
Fibre Channel ELS handler.
Definition fcels.h:393
size_t param_len
Service parameter length.
Definition fcels.h:391
unsigned int type
Upper-layer protocol type.
Definition fcels.h:389
A Fibre Channel extended link services transaction.
Definition fcels.h:324
struct fc_port * port
Fibre Channel port.
Definition fcels.h:335
struct fc_port_id port_id
Local port ID.
Definition fcels.h:337
struct fc_els_handler * handler
ELS handler, if known.
Definition fcels.h:341
struct interface xchg
Fibre Channel exchange.
Definition fcels.h:330
struct interface job
Job control interface.
Definition fcels.h:328
struct refcnt refcnt
Reference count.
Definition fcels.h:326
struct fc_port_id peer_port_id
Peer port ID.
Definition fcels.h:339
unsigned int flags
Flags.
Definition fcels.h:343
struct process process
Request sending process.
Definition fcels.h:332
uint16_t mtu
Receive data field size.
Definition fcels.h:189
uint16_t max_seq
Maximum number of concurrent sequences.
Definition fcels.h:191
uint16_t flags
Flags.
Definition fcels.h:183
uint8_t max_seq_per_xchg
Maximum number of open sequences per exchange.
Definition fcels.h:197
uint16_t credit
Buffer-to-buffer credit.
Definition fcels.h:80
uint16_t rel_offs
Relative offset by info category.
Definition fcels.h:91
uint16_t mtu
Receive size.
Definition fcels.h:84
uint16_t flags
Flags.
Definition fcels.h:82
uint32_t e_d_tov
Error detection timeout value.
Definition fcels.h:99
uint16_t version
Login version.
Definition fcels.h:78
struct fc_login_common::@057055275144204264201027124204260000332106235341::@014376230376306047030265062056353210336054307263 plogi
union fc_login_common::@057055275144204264201027124204260000332106235341 u
"Common"?
uint16_t max_seq
Maximum number of concurrent sequences.
Definition fcels.h:89
A Fibre Channel FLOGI/PLOGI frame.
Definition fcels.h:209
struct fc_login_common common
Common service parameters.
Definition fcels.h:215
struct fc_login_class class3
Class 3 service parameters.
Definition fcels.h:225
uint8_t command
ELS command code.
Definition fcels.h:211
struct fc_name port_wwn
Port name.
Definition fcels.h:217
struct fc_name node_wwn
Node name.
Definition fcels.h:219
A Fibre Channel LOGO request frame.
Definition fcels.h:233
uint8_t command
ELS command code.
Definition fcels.h:235
struct fc_name port_wwn
Port name.
Definition fcels.h:241
struct fc_port_id port_id
Port ID.
Definition fcels.h:239
A Fibre Channel LOGO response frame.
Definition fcels.h:245
uint8_t command
ELS command code.
Definition fcels.h:247
A Fibre Channel LS_RJT frame.
Definition fcels.h:44
uint8_t command
ELS command code.
Definition fcels.h:46
uint8_t reason
Reason code.
Definition fcels.h:50
A Fibre Channel peer.
Definition fc.h:341
struct fc_link_state link
Link state monitor.
Definition fc.h:351
struct interface plogi
PLOGI interface.
Definition fc.h:353
A Fibre Channel port identifier.
Definition fc.h:38
A Fibre Channel port.
Definition fc.h:253
struct fc_name node_wwn
Node name.
Definition fc.h:264
struct fc_name port_wwn
Port name.
Definition fc.h:266
struct fc_link_state link
Link state monitor.
Definition fc.h:273
struct fc_port_id port_id
Local port ID.
Definition fc.h:268
struct fc_port_id ptp_link_port_id
Link port ID (for point-to-point links only)
Definition fc.h:281
A Fibre Channel PRLI frame.
Definition fcels.h:274
A Fibre Channel responder.
Definition fc.h:223
A Fibre Channel RTV request frame.
Definition fcels.h:286
uint8_t command
ELS command code.
Definition fcels.h:288
A Fibre Channel RTV response frame.
Definition fcels.h:294
uint8_t command
ELS command code.
Definition fcels.h:296
uint32_t e_d_tov
Error detection timeout value.
Definition fcels.h:302
A Fibre Channel upper-layer protocol.
Definition fc.h:414
struct fc_peer * peer
Fibre Channel peer.
Definition fc.h:418
struct interface prli
PRLI interface.
Definition fc.h:430
struct fc_link_state link
Link state monitor.
Definition fc.h:428
An object interface descriptor.
Definition interface.h:56
An object interface operation.
Definition interface.h:18
An object interface.
Definition interface.h:125
A persistent I/O buffer.
Definition iobuf.h:38
void * data
Start of data.
Definition iobuf.h:53
A process descriptor.
Definition process.h:32
A process.
Definition process.h:18
A reference counter.
Definition refcnt.h:27
Fibre Channel socket address.
Definition fc.h:48
Data transfer metadata.
Definition xfer.h:23
#define for_each_table_entry(pointer, table)
Iterate through all entries within a linker table.
Definition tables.h:386
unsigned long frame
Definition xengrant.h:180
int xfer_deliver(struct interface *intf, struct io_buffer *iobuf, struct xfer_metadata *meta)
Deliver datagram.
Definition xfer.c:195
int xfer_deliver_raw_meta(struct interface *intf, const void *data, size_t len, struct xfer_metadata *meta)
Deliver datagram as raw data.
Definition xfer.c:269
Data transfer interfaces.
#define XFER_FL_OVER
Sender is relinquishing use of half-duplex channel.
Definition xfer.h:51
#define XFER_FL_RESPONSE
Data content is a response.
Definition xfer.h:64
#define XFER_FL_OUT
This is the final data transfer.
Definition xfer.h:54