Parcourir la source

[fc] Support Fibre Channel ECHO

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown il y a 13 ans
Parent
révision
90930be8fe
3 fichiers modifiés avec 237 ajouts et 103 suppressions
  1. 15
    22
      src/include/ipxe/fcels.h
  2. 219
    76
      src/net/fcels.c
  3. 3
    5
      src/net/fcp.c

+ 15
- 22
src/include/ipxe/fcels.h Voir le fichier

34
 	FC_ELS_FLOGI = 0x04,		/**< Fabric Login */
34
 	FC_ELS_FLOGI = 0x04,		/**< Fabric Login */
35
 	FC_ELS_LOGO = 0x05,		/**< Logout */
35
 	FC_ELS_LOGO = 0x05,		/**< Logout */
36
 	FC_ELS_RTV = 0x0e,		/**< Read Timeout Value */
36
 	FC_ELS_RTV = 0x0e,		/**< Read Timeout Value */
37
+	FC_ELS_ECHO = 0x10,		/**< Echo */
37
 	FC_ELS_PRLI = 0x20,		/**< Process Login */
38
 	FC_ELS_PRLI = 0x20,		/**< Process Login */
38
 	FC_ELS_PRLO = 0x21,		/**< Process Logout */
39
 	FC_ELS_PRLO = 0x21,		/**< Process Logout */
39
 };
40
 };
310
 /** Short R_T timeout */
311
 /** Short R_T timeout */
311
 #define FC_RTV_SHORT_R_T_TOV 0x0008
312
 #define FC_RTV_SHORT_R_T_TOV 0x0008
312
 
313
 
314
+/** A Fibre Channel ECHO frame */
315
+struct fc_echo_frame_header {
316
+	/** ELS command code */
317
+	uint8_t command;
318
+	/** Reserved */
319
+	uint8_t reserved[3];
320
+} __attribute__ (( packed ));
321
+
313
 /** A Fibre Channel extended link services transaction */
322
 /** A Fibre Channel extended link services transaction */
314
 struct fc_els {
323
 struct fc_els {
315
 	/** Reference count */
324
 	/** Reference count */
343
 struct fc_els_handler {
352
 struct fc_els_handler {
344
 	/** Name */
353
 	/** Name */
345
 	const char *name;
354
 	const char *name;
346
-	/** Transmit ELS request frame
347
-	 *
348
-	 * @v els		Fibre Channel ELS transaction
349
-	 * @ret rc		Return status code
350
-	 */
351
-	int ( * tx_request ) ( struct fc_els *els );
352
-	/** Transmit ELS response frame
353
-	 *
354
-	 * @v els		Fibre Channel ELS transaction
355
-	 * @ret rc		Return status code
356
-	 */
357
-	int ( * tx_response ) ( struct fc_els *els );
358
-	/** Receive ELS request frame
355
+	/** Transmit ELS frame
359
 	 *
356
 	 *
360
 	 * @v els		Fibre Channel ELS transaction
357
 	 * @v els		Fibre Channel ELS transaction
361
-	 * @v data		ELS frame
362
-	 * @v len		Length of ELS frame
363
 	 * @ret rc		Return status code
358
 	 * @ret rc		Return status code
364
 	 */
359
 	 */
365
-	int ( * rx_request ) ( struct fc_els *els, const void *data,
366
-			       size_t len );
367
-	/** Receive ELS response frame
360
+	int ( * tx ) ( struct fc_els *els );
361
+	/** Receive ELS frame
368
 	 *
362
 	 *
369
 	 * @v els		Fibre Channel ELS transaction
363
 	 * @v els		Fibre Channel ELS transaction
370
 	 * @v data		ELS frame
364
 	 * @v data		ELS frame
371
 	 * @v len		Length of ELS frame
365
 	 * @v len		Length of ELS frame
372
 	 * @ret rc		Return status code
366
 	 * @ret rc		Return status code
373
 	 */
367
 	 */
374
-	int ( * rx_response ) ( struct fc_els *els, const void *data,
375
-				size_t len );
376
-	/** Detect ELS request frame
368
+	int ( * rx ) ( struct fc_els *els, void *data, size_t len );
369
+	/** Detect ELS frame
377
 	 *
370
 	 *
378
 	 * @v els		Fibre Channel ELS transaction
371
 	 * @v els		Fibre Channel ELS transaction
379
 	 * @v data		ELS frame
372
 	 * @v data		ELS frame
444
 			    void *param );
437
 			    void *param );
445
 extern int fc_els_prli_rx ( struct fc_els *els,
438
 extern int fc_els_prli_rx ( struct fc_els *els,
446
 			    struct fc_els_prli_descriptor *descriptor,
439
 			    struct fc_els_prli_descriptor *descriptor,
447
-			    const void *data, size_t len );
440
+			    void *data, size_t len );
448
 extern int fc_els_prli_detect ( struct fc_els *els __unused,
441
 extern int fc_els_prli_detect ( struct fc_els *els __unused,
449
 				struct fc_els_prli_descriptor *descriptor,
442
 				struct fc_els_prli_descriptor *descriptor,
450
 				const void *data, size_t len );
443
 				const void *data, size_t len );

+ 219
- 76
src/net/fcels.c Voir le fichier

158
 	struct sockaddr_fc *src = ( ( struct sockaddr_fc * ) meta->src );
158
 	struct sockaddr_fc *src = ( ( struct sockaddr_fc * ) meta->src );
159
 	struct sockaddr_fc *dest = ( ( struct sockaddr_fc * ) meta->dest );
159
 	struct sockaddr_fc *dest = ( ( struct sockaddr_fc * ) meta->dest );
160
 	size_t len = iob_len ( iobuf );
160
 	size_t len = iob_len ( iobuf );
161
-	int ( * rx ) ( struct fc_els *els, const void *data, size_t len );
162
 	int rc;
161
 	int rc;
163
 
162
 
164
 	/* Sanity check */
163
 	/* Sanity check */
206
 	DBGC2_HDA ( els, 0, frame, len );
205
 	DBGC2_HDA ( els, 0, frame, len );
207
 
206
 
208
 	/* Handle received frame */
207
 	/* Handle received frame */
209
-	rx = ( fc_els_is_request ( els ) ?
210
-	       els->handler->rx_response : els->handler->rx_request );
211
-	if ( ( rc = rx ( els, frame, len ) ) != 0 ) {
208
+	if ( ( rc = els->handler->rx ( els, frame, len ) ) != 0 ) {
212
 		DBGC ( els, FCELS_FMT " could not handle received frame: "
209
 		DBGC ( els, FCELS_FMT " could not handle received frame: "
213
 		       "%s\n", FCELS_ARGS ( els ), strerror ( rc ) );
210
 		       "%s\n", FCELS_ARGS ( els ), strerror ( rc ) );
214
 		DBGC_HDA ( els, 0, frame, len );
211
 		DBGC_HDA ( els, 0, frame, len );
215
 		goto done;
212
 		goto done;
216
 	}
213
 	}
217
 
214
 
218
-	/* Free I/O buffer.  Do this before transmitting response to
219
-	 * minimise memory consumption.
220
-	 */
221
-	free_iob ( iob_disown ( iobuf ) );
222
-
223
-	/* Transmit response if applicable */
224
-	if ( ( ! fc_els_is_request ( els ) ) &&
225
-	     ( ( rc = els->handler->tx_response ( els ) ) != 0 ) ) {
226
-		DBGC ( els, FCELS_FMT " could not transmit response: %s\n",
227
-		       FCELS_ARGS ( els ), strerror ( rc ) );
228
-		goto done;
229
-	}
230
-
231
  done:
215
  done:
232
 	/* Free I/O buffer */
216
 	/* Free I/O buffer */
233
 	free_iob ( iobuf );
217
 	free_iob ( iobuf );
286
 	}
270
 	}
287
 
271
 
288
 	/* Transmit request */
272
 	/* Transmit request */
289
-	if ( ( rc = els->handler->tx_request ( els ) ) != 0 ) {
273
+	if ( ( rc = els->handler->tx ( els ) ) != 0 ) {
290
 		DBGC ( els, FCELS_FMT " could not transmit request: %s\n",
274
 		DBGC ( els, FCELS_FMT " could not transmit request: %s\n",
291
 		       FCELS_ARGS ( els ), strerror ( rc ) );
275
 		       FCELS_ARGS ( els ), strerror ( rc ) );
292
 		fc_els_close ( els, rc );
276
 		fc_els_close ( els, rc );
394
  * @v els		Fibre Channel ELS transaction
378
  * @v els		Fibre Channel ELS transaction
395
  * @ret rc		Return status code
379
  * @ret rc		Return status code
396
  */
380
  */
397
-static int fc_els_unknown_tx_request ( struct fc_els *els __unused ) {
381
+static int fc_els_unknown_tx ( struct fc_els *els __unused ) {
398
 	return -ENOTSUP;
382
 	return -ENOTSUP;
399
 }
383
 }
400
 
384
 
417
 }
401
 }
418
 
402
 
419
 /**
403
 /**
420
- * Receive unknown ELS request
404
+ * Receive unknown ELS
421
  *
405
  *
422
  * @v els		Fibre Channel ELS transaction
406
  * @v els		Fibre Channel ELS transaction
423
  * @v data		ELS frame
407
  * @v data		ELS frame
424
  * @v len		Length of ELS frame
408
  * @v len		Length of ELS frame
425
  * @ret rc		Return status code
409
  * @ret rc		Return status code
426
  */
410
  */
427
-static int fc_els_unknown_rx_request ( struct fc_els *els, const void *data,
428
-				       size_t len ) {
411
+static int fc_els_unknown_rx ( struct fc_els *els, void *data, size_t len ) {
412
+	int rc;
429
 
413
 
430
 	DBGC ( els, FCELS_FMT ":\n", FCELS_ARGS ( els ) );
414
 	DBGC ( els, FCELS_FMT ":\n", FCELS_ARGS ( els ) );
431
 	DBGC_HDA ( els, 0, data, len );
415
 	DBGC_HDA ( els, 0, data, len );
432
-	return 0;
433
-}
434
 
416
 
435
-/**
436
- * Receive unknown ELS response
437
- *
438
- * @v els		Fibre Channel ELS transaction
439
- * @v data		ELS frame
440
- * @v len		Length of ELS frame
441
- * @ret rc		Return status code
442
- */
443
-static int fc_els_unknown_rx_response ( struct fc_els *els __unused,
444
-					const void *data __unused,
445
-					size_t len __unused ) {
446
-	assert ( 0 );
447
-	return -EINVAL;
417
+	/* Transmit response, if applicable */
418
+	if ( ! fc_els_is_request ( els ) ) {
419
+		if ( ( rc = fc_els_unknown_tx_response ( els ) ) != 0 )
420
+			return rc;
421
+	}
422
+
423
+	return 0;
448
 }
424
 }
449
 
425
 
450
 /**
426
 /**
464
 /** Unknown ELS handler */
440
 /** Unknown ELS handler */
465
 struct fc_els_handler fc_els_unknown_handler __fc_els_handler = {
441
 struct fc_els_handler fc_els_unknown_handler __fc_els_handler = {
466
 	.name		= "UNKNOWN",
442
 	.name		= "UNKNOWN",
467
-	.tx_request	= fc_els_unknown_tx_request,
468
-	.tx_response	= fc_els_unknown_tx_response,
469
-	.rx_request	= fc_els_unknown_rx_request,
470
-	.rx_response	= fc_els_unknown_rx_response,
443
+	.tx		= fc_els_unknown_tx,
444
+	.rx		= fc_els_unknown_rx,
471
 	.detect		= fc_els_unknown_detect,
445
 	.detect		= fc_els_unknown_detect,
472
 };
446
 };
473
 
447
 
513
  * @v len		Length of ELS frame
487
  * @v len		Length of ELS frame
514
  * @ret rc		Return status code
488
  * @ret rc		Return status code
515
  */
489
  */
516
-static int fc_els_flogi_rx ( struct fc_els *els, const void *data,
517
-			     size_t len ) {
518
-	const struct fc_login_frame *flogi = data;
490
+static int fc_els_flogi_rx ( struct fc_els *els, void *data, size_t len ) {
491
+	struct fc_login_frame *flogi = data;
519
 	int has_fabric;
492
 	int has_fabric;
520
 	int rc;
493
 	int rc;
521
 
494
 
557
 			 sizeof ( els->peer_port_id ) );
530
 			 sizeof ( els->peer_port_id ) );
558
 	}
531
 	}
559
 
532
 
533
+	/* Transmit response, if applicable */
534
+	if ( ! fc_els_is_request ( els ) ) {
535
+		if ( ( rc = fc_els_flogi_tx ( els ) ) != 0 )
536
+			return rc;
537
+	}
538
+
560
 	return 0;
539
 	return 0;
561
 }
540
 }
562
 
541
 
582
 /** FLOGI ELS handler */
561
 /** FLOGI ELS handler */
583
 struct fc_els_handler fc_els_flogi_handler __fc_els_handler = {
562
 struct fc_els_handler fc_els_flogi_handler __fc_els_handler = {
584
 	.name		= "FLOGI",
563
 	.name		= "FLOGI",
585
-	.tx_request	= fc_els_flogi_tx,
586
-	.tx_response	= fc_els_flogi_tx,
587
-	.rx_request	= fc_els_flogi_rx,
588
-	.rx_response	= fc_els_flogi_rx,
564
+	.tx		= fc_els_flogi_tx,
565
+	.rx		= fc_els_flogi_rx,
589
 	.detect		= fc_els_flogi_detect,
566
 	.detect		= fc_els_flogi_detect,
590
 };
567
 };
591
 
568
 
650
  * @v len		Length of ELS frame
627
  * @v len		Length of ELS frame
651
  * @ret rc		Return status code
628
  * @ret rc		Return status code
652
  */
629
  */
653
-static int fc_els_plogi_rx ( struct fc_els *els, const void *data,
654
-			     size_t len ) {
655
-	const struct fc_login_frame *plogi = data;
630
+static int fc_els_plogi_rx ( struct fc_els *els, void *data, size_t len ) {
631
+	struct fc_login_frame *plogi = data;
656
 	struct fc_peer *peer;
632
 	struct fc_peer *peer;
657
 	int rc;
633
 	int rc;
658
 
634
 
695
 		goto err_login;
671
 		goto err_login;
696
 	}
672
 	}
697
 
673
 
674
+	/* Transmit response, if applicable */
675
+	if ( ! fc_els_is_request ( els ) ) {
676
+		if ( ( rc = fc_els_plogi_tx ( els ) ) != 0 )
677
+			goto err_plogi_tx;
678
+	}
679
+
698
 	/* Drop temporary reference to peer */
680
 	/* Drop temporary reference to peer */
699
 	fc_peer_put ( peer );
681
 	fc_peer_put ( peer );
700
 
682
 
701
 	return 0;
683
 	return 0;
702
 
684
 
685
+ err_plogi_tx:
703
  err_login:
686
  err_login:
704
 	fc_peer_put ( peer );
687
 	fc_peer_put ( peer );
705
  err_peer_get_wwn:
688
  err_peer_get_wwn:
729
 /** PLOGI ELS handler */
712
 /** PLOGI ELS handler */
730
 struct fc_els_handler fc_els_plogi_handler __fc_els_handler = {
713
 struct fc_els_handler fc_els_plogi_handler __fc_els_handler = {
731
 	.name		= "PLOGI",
714
 	.name		= "PLOGI",
732
-	.tx_request	= fc_els_plogi_tx,
733
-	.tx_response	= fc_els_plogi_tx,
734
-	.rx_request	= fc_els_plogi_rx,
735
-	.rx_response	= fc_els_plogi_rx,
715
+	.tx		= fc_els_plogi_tx,
716
+	.rx		= fc_els_plogi_rx,
736
 	.detect		= fc_els_plogi_detect,
717
 	.detect		= fc_els_plogi_detect,
737
 };
718
 };
738
 
719
 
764
  * @v els		Fibre Channel ELS transaction
745
  * @v els		Fibre Channel ELS transaction
765
  * @ret rc		Return status code
746
  * @ret rc		Return status code
766
  */
747
  */
767
-static int fc_els_logo_tx_request ( struct fc_els *els ) {
748
+static int fc_els_logo_tx ( struct fc_els *els ) {
768
 	struct fc_logout_request_frame logo;
749
 	struct fc_logout_request_frame logo;
769
 
750
 
770
 	/* Construct LOGO */
751
 	/* Construct LOGO */
802
  * @v port_id		Peer port ID
783
  * @v port_id		Peer port ID
803
  */
784
  */
804
 static void fc_els_logo_logout ( struct fc_els *els,
785
 static void fc_els_logo_logout ( struct fc_els *els,
805
-				 const struct fc_port_id *peer_port_id ) {
786
+				 struct fc_port_id *peer_port_id ) {
806
 	struct fc_peer *peer;
787
 	struct fc_peer *peer;
807
 
788
 
808
 	if ( ( memcmp ( peer_port_id, &fc_f_port_id,
789
 	if ( ( memcmp ( peer_port_id, &fc_f_port_id,
827
  * @v len		Length of ELS frame
808
  * @v len		Length of ELS frame
828
  * @ret rc		Return status code
809
  * @ret rc		Return status code
829
  */
810
  */
830
-static int fc_els_logo_rx_request ( struct fc_els *els, const void *data,
811
+static int fc_els_logo_rx_request ( struct fc_els *els, void *data,
831
 				    size_t len ) {
812
 				    size_t len ) {
832
-	const struct fc_logout_request_frame *logo = data;
813
+	struct fc_logout_request_frame *logo = data;
814
+	int rc;
833
 
815
 
834
 	/* Sanity check */
816
 	/* Sanity check */
835
 	if ( len < sizeof ( *logo ) ) {
817
 	if ( len < sizeof ( *logo ) ) {
845
 	/* Log out individual peer or whole port as applicable */
827
 	/* Log out individual peer or whole port as applicable */
846
 	fc_els_logo_logout ( els, &logo->port_id );
828
 	fc_els_logo_logout ( els, &logo->port_id );
847
 
829
 
830
+	/* Transmit repsonse */
831
+	if ( ( rc = fc_els_logo_tx_response ( els ) ) != 0 )
832
+		return rc;
833
+
848
 	return 0;
834
 	return 0;
849
 }
835
 }
850
 
836
 
856
  * @v len		Length of ELS frame
842
  * @v len		Length of ELS frame
857
  * @ret rc		Return status code
843
  * @ret rc		Return status code
858
  */
844
  */
859
-static int fc_els_logo_rx_response ( struct fc_els *els,
860
-				     const void *data __unused,
845
+static int fc_els_logo_rx_response ( struct fc_els *els, void *data __unused,
861
 				     size_t len __unused ) {
846
 				     size_t len __unused ) {
862
 
847
 
863
 	/* Log out individual peer or whole port as applicable */
848
 	/* Log out individual peer or whole port as applicable */
866
 	return 0;
851
 	return 0;
867
 }
852
 }
868
 
853
 
854
+/**
855
+ * Receive LOGO
856
+ *
857
+ * @v els		Fibre Channel ELS transaction
858
+ * @v data		ELS frame
859
+ * @v len		Length of ELS frame
860
+ * @ret rc		Return status code
861
+ */
862
+static int fc_els_logo_rx ( struct fc_els *els, void *data, size_t len ) {
863
+
864
+	if ( fc_els_is_request ( els ) ) {
865
+		return fc_els_logo_rx_response ( els, data, len );
866
+	} else {
867
+		return fc_els_logo_rx_request ( els, data, len );
868
+	}
869
+}
870
+
869
 /**
871
 /**
870
  * Detect LOGO
872
  * Detect LOGO
871
  *
873
  *
888
 /** LOGO ELS handler */
890
 /** LOGO ELS handler */
889
 struct fc_els_handler fc_els_logo_handler __fc_els_handler = {
891
 struct fc_els_handler fc_els_logo_handler __fc_els_handler = {
890
 	.name		= "LOGO",
892
 	.name		= "LOGO",
891
-	.tx_request	= fc_els_logo_tx_request,
892
-	.tx_response	= fc_els_logo_tx_response,
893
-	.rx_request	= fc_els_logo_rx_request,
894
-	.rx_response	= fc_els_logo_rx_response,
893
+	.tx		= fc_els_logo_tx,
894
+	.rx		= fc_els_logo_rx,
895
 	.detect		= fc_els_logo_detect,
895
 	.detect		= fc_els_logo_detect,
896
 };
896
 };
897
 
897
 
1000
  */
1000
  */
1001
 int fc_els_prli_rx ( struct fc_els *els,
1001
 int fc_els_prli_rx ( struct fc_els *els,
1002
 		     struct fc_els_prli_descriptor *descriptor,
1002
 		     struct fc_els_prli_descriptor *descriptor,
1003
-		     const void *data, size_t len ) {
1004
-	const struct {
1003
+		     void *data, size_t len ) {
1004
+	struct {
1005
 		struct fc_prli_frame frame;
1005
 		struct fc_prli_frame frame;
1006
 		uint8_t param[descriptor->param_len];
1006
 		uint8_t param[descriptor->param_len];
1007
 	} __attribute__ (( packed )) *prli = data;
1007
 	} __attribute__ (( packed )) *prli = data;
1055
 		}
1055
 		}
1056
 	}
1056
 	}
1057
 
1057
 
1058
+	/* Transmit response, if applicable */
1059
+	if ( ! fc_els_is_request ( els ) ) {
1060
+		if ( ( rc = els->handler->tx ( els ) ) != 0 )
1061
+			goto err_tx;
1062
+	}
1063
+
1058
 	/* Drop temporary reference to ULP */
1064
 	/* Drop temporary reference to ULP */
1059
 	fc_ulp_put ( ulp );
1065
 	fc_ulp_put ( ulp );
1060
 
1066
 
1061
 	return 0;
1067
 	return 0;
1062
 
1068
 
1069
+ err_tx:
1063
  err_login:
1070
  err_login:
1064
  err_link:
1071
  err_link:
1065
 	fc_ulp_put ( ulp );
1072
 	fc_ulp_put ( ulp );
1148
 }
1155
 }
1149
 
1156
 
1150
 /**
1157
 /**
1151
- * Receive RTV request
1158
+ * Receive RTV
1152
  *
1159
  *
1153
  * @v els		Fibre Channel ELS transaction
1160
  * @v els		Fibre Channel ELS transaction
1154
  * @v data		ELS frame
1161
  * @v data		ELS frame
1155
  * @v len		Length of ELS frame
1162
  * @v len		Length of ELS frame
1156
  * @ret rc		Return status code
1163
  * @ret rc		Return status code
1157
  */
1164
  */
1158
-static int fc_els_rtv_rx_request ( struct fc_els *els,
1159
-				   const void *data __unused,
1160
-				   size_t len __unused ) {
1165
+static int fc_els_rtv_rx ( struct fc_els *els, void *data __unused,
1166
+			   size_t len __unused ) {
1167
+	int rc;
1161
 
1168
 
1162
 	DBGC ( els, FCELS_FMT "\n", FCELS_ARGS ( els ) );
1169
 	DBGC ( els, FCELS_FMT "\n", FCELS_ARGS ( els ) );
1163
 
1170
 
1164
-	/* Nothing to do */
1171
+	/* Transmit response */
1172
+	if ( ! fc_els_is_request ( els ) ) {
1173
+		if ( ( rc = fc_els_rtv_tx_response ( els ) ) != 0 )
1174
+			return rc;
1175
+	}
1176
+
1165
 	return 0;
1177
 	return 0;
1166
 }
1178
 }
1167
 
1179
 
1187
 /** RTV ELS handler */
1199
 /** RTV ELS handler */
1188
 struct fc_els_handler fc_els_rtv_handler __fc_els_handler = {
1200
 struct fc_els_handler fc_els_rtv_handler __fc_els_handler = {
1189
 	.name		= "RTV",
1201
 	.name		= "RTV",
1190
-	.tx_request	= fc_els_unknown_tx_request,
1191
-	.tx_response	= fc_els_rtv_tx_response,
1192
-	.rx_request	= fc_els_rtv_rx_request,
1193
-	.rx_response	= fc_els_unknown_rx_response,
1202
+	.tx		= fc_els_unknown_tx,
1203
+	.rx		= fc_els_rtv_rx,
1194
 	.detect		= fc_els_rtv_detect,
1204
 	.detect		= fc_els_rtv_detect,
1195
 };
1205
 };
1206
+
1207
+/******************************************************************************
1208
+ *
1209
+ * ECHO
1210
+ *
1211
+ ******************************************************************************
1212
+ */
1213
+
1214
+/** ECHO request data */
1215
+struct fc_echo_request_frame {
1216
+	/** ECHO frame header */
1217
+	struct fc_echo_frame_header echo;
1218
+	/** Magic marker */
1219
+	uint32_t magic;
1220
+} __attribute__ (( packed ));
1221
+
1222
+/** ECHO magic marker */
1223
+#define FC_ECHO_MAGIC 0x69505845
1224
+
1225
+/**
1226
+ * Transmit ECHO
1227
+ *
1228
+ * @v els		Fibre Channel ELS transaction
1229
+ * @ret rc		Return status code
1230
+ */
1231
+static int fc_els_echo_tx ( struct fc_els *els ) {
1232
+	struct fc_echo_request_frame echo;
1233
+
1234
+	/* Construct ECHO */
1235
+	memset ( &echo, 0, sizeof ( echo ) );
1236
+	echo.echo.command = FC_ELS_ECHO;
1237
+	echo.magic = htonl ( FC_ECHO_MAGIC );
1238
+
1239
+	/* Transmit ECHO */
1240
+	return fc_els_tx ( els, &echo, sizeof ( echo ) );
1241
+}
1242
+
1243
+/**
1244
+ * Receive ECHO request
1245
+ *
1246
+ * @v els		Fibre Channel ELS transaction
1247
+ * @v data		ELS frame
1248
+ * @v len		Length of ELS frame
1249
+ * @ret rc		Return status code
1250
+ */
1251
+static int fc_els_echo_rx_request ( struct fc_els *els, void *data,
1252
+				    size_t len ) {
1253
+	struct {
1254
+		struct fc_echo_frame_header echo;
1255
+		char payload[ len - sizeof ( struct fc_echo_frame_header ) ];
1256
+	} *echo = data;
1257
+	int rc;
1258
+
1259
+	DBGC ( els, FCELS_FMT "\n", FCELS_ARGS ( els ) );
1260
+
1261
+	/* Transmit response */
1262
+	echo->echo.command = FC_ELS_LS_ACC;
1263
+	if ( ( rc = fc_els_tx ( els, echo, sizeof ( *echo ) ) ) != 0 )
1264
+		return rc;
1265
+
1266
+	/* Nothing to do */
1267
+	return 0;
1268
+}
1269
+
1270
+/**
1271
+ * Receive ECHO response
1272
+ *
1273
+ * @v els		Fibre Channel ELS transaction
1274
+ * @v data		ELS frame
1275
+ * @v len		Length of ELS frame
1276
+ * @ret rc		Return status code
1277
+ */
1278
+static int fc_els_echo_rx_response ( struct fc_els *els, void *data,
1279
+				     size_t len ) {
1280
+	struct fc_echo_request_frame *echo = data;
1281
+
1282
+	DBGC ( els, FCELS_FMT "\n", FCELS_ARGS ( els ) );
1283
+
1284
+	/* Check response is correct */
1285
+	if ( ( len != sizeof ( *echo ) ) ||
1286
+	     ( echo->magic != htonl ( FC_ECHO_MAGIC ) ) ) {
1287
+		DBGC ( els, FCELS_FMT " received bad echo response\n",
1288
+		       FCELS_ARGS ( els ) );
1289
+		DBGC_HDA ( els, 0, data, len );
1290
+		return -EIO;
1291
+	}
1292
+
1293
+	return 0;
1294
+}
1295
+
1296
+/**
1297
+ * Receive ECHO
1298
+ *
1299
+ * @v els		Fibre Channel ELS transaction
1300
+ * @v data		ELS frame
1301
+ * @v len		Length of ELS frame
1302
+ * @ret rc		Return status code
1303
+ */
1304
+static int fc_els_echo_rx ( struct fc_els *els, void *data, size_t len ) {
1305
+
1306
+	if ( fc_els_is_request ( els ) ) {
1307
+		return fc_els_echo_rx_response ( els, data, len );
1308
+	} else {
1309
+		return fc_els_echo_rx_request ( els, data, len );
1310
+	}
1311
+}
1312
+
1313
+/**
1314
+ * Detect ECHO
1315
+ *
1316
+ * @v els		Fibre Channel ELS transaction
1317
+ * @v data		ELS frame
1318
+ * @v len		Length of ELS frame
1319
+ * @ret rc		Return status code
1320
+ */
1321
+static int fc_els_echo_detect ( struct fc_els *els __unused, const void *data,
1322
+				size_t len __unused ) {
1323
+	const struct fc_echo_frame_header *echo = data;
1324
+
1325
+	/* Check for ECHO */
1326
+	if ( echo->command != FC_ELS_ECHO )
1327
+		return -EINVAL;
1328
+
1329
+	return 0;
1330
+}
1331
+
1332
+/** ECHO ELS handler */
1333
+struct fc_els_handler fc_els_echo_handler __fc_els_handler = {
1334
+	.name		= "ECHO",
1335
+	.tx		= fc_els_echo_tx,
1336
+	.rx		= fc_els_echo_rx,
1337
+	.detect		= fc_els_echo_detect,
1338
+};

+ 3
- 5
src/net/fcp.c Voir le fichier

103
  * @v len		Length of ELS frame
103
  * @v len		Length of ELS frame
104
  * @ret rc		Return status code
104
  * @ret rc		Return status code
105
  */
105
  */
106
-static int fcp_prli_rx ( struct fc_els *els, const void *data, size_t len ) {
106
+static int fcp_prli_rx ( struct fc_els *els, void *data, size_t len ) {
107
 	return fc_els_prli_rx ( els, &fcp_prli_descriptor, data, len );
107
 	return fc_els_prli_rx ( els, &fcp_prli_descriptor, data, len );
108
 }
108
 }
109
 
109
 
123
 /** FCP PRLI ELS handler */
123
 /** FCP PRLI ELS handler */
124
 struct fc_els_handler fcp_prli_handler __fc_els_handler = {
124
 struct fc_els_handler fcp_prli_handler __fc_els_handler = {
125
 	.name		= "PRLI-FCP",
125
 	.name		= "PRLI-FCP",
126
-	.tx_request	= fcp_prli_tx,
127
-	.tx_response	= fcp_prli_tx,
128
-	.rx_request	= fcp_prli_rx,
129
-	.rx_response	= fcp_prli_rx,
126
+	.tx		= fcp_prli_tx,
127
+	.rx		= fcp_prli_rx,
130
 	.detect		= fcp_prli_detect,
128
 	.detect		= fcp_prli_detect,
131
 };
129
 };
132
 
130
 

Chargement…
Annuler
Enregistrer