Browse Source

Clean up connection closing and permanent failure logic.

tags/v0.9.3
Michael Brown 18 years ago
parent
commit
76525294ee
2 changed files with 69 additions and 32 deletions
  1. 7
    0
      src/include/gpxe/iscsi.h
  2. 62
    32
      src/net/tcp/iscsi.c

+ 7
- 0
src/include/gpxe/iscsi.h View File

592
 	struct scsi_command *command;
592
 	struct scsi_command *command;
593
 	/** Asynchronous operation for the current iSCSI operation */
593
 	/** Asynchronous operation for the current iSCSI operation */
594
 	struct async_operation aop;
594
 	struct async_operation aop;
595
+	/** Instant return code
596
+	 *
597
+	 * Set to a non-zero value if all requests should return
598
+	 * immediately.  This can be used to e.g. avoid retrying
599
+	 * logins that are doomed to fail authentication.
600
+	 */
601
+	int instant_rc;
595
 };
602
 };
596
 
603
 
597
 /** iSCSI session is currently in the security negotiation phase */
604
 /** iSCSI session is currently in the security negotiation phase */

+ 62
- 32
src/net/tcp/iscsi.c View File

78
 	iscsi->rx_buffer = NULL;
78
 	iscsi->rx_buffer = NULL;
79
 }
79
 }
80
 
80
 
81
+/**
82
+ * Close iSCSI connection
83
+ *
84
+ * @v iscsi		iSCSI session
85
+ */
86
+static void iscsi_close ( struct iscsi_session *iscsi ) {
87
+
88
+	/* Close TCP connection */
89
+	tcp_close ( &iscsi->tcp );
90
+
91
+	/* Clear connection status */
92
+	iscsi->status = 0;
93
+
94
+	/* Reset TX and RX state machines */
95
+	iscsi->tx_state = ISCSI_TX_IDLE;
96
+	iscsi->rx_state = ISCSI_RX_BHS;
97
+
98
+	/* Free any dynamically allocated memory */
99
+	chap_finish ( &iscsi->chap );
100
+	iscsi_rx_buffered_data_done ( iscsi );
101
+}
102
+
81
 /**
103
 /**
82
  * Mark iSCSI operation as complete
104
  * Mark iSCSI operation as complete
83
  *
105
  *
93
  */
115
  */
94
 static void iscsi_done ( struct iscsi_session *iscsi, int rc ) {
116
 static void iscsi_done ( struct iscsi_session *iscsi, int rc ) {
95
 
117
 
118
+	assert ( iscsi->tx_state == ISCSI_TX_IDLE );
119
+	assert ( iscsi->rx_state == ISCSI_RX_BHS );
120
+	assert ( iscsi->rx_offset == 0 );
121
+
96
 	/* Clear current SCSI command */
122
 	/* Clear current SCSI command */
97
 	iscsi->command = NULL;
123
 	iscsi->command = NULL;
98
 
124
 
99
-	/* Free any dynamically allocated memory */
100
-	chap_finish ( &iscsi->chap );
101
-	iscsi_rx_buffered_data_done ( iscsi );
102
-
103
 	/* Mark asynchronous operation as complete */
125
 	/* Mark asynchronous operation as complete */
104
 	async_done ( &iscsi->aop, rc );
126
 	async_done ( &iscsi->aop, rc );
105
 }
127
 }
470
 
492
 
471
 	/* Clear any "strings to send" flags */
493
 	/* Clear any "strings to send" flags */
472
 	iscsi->status &= ~ISCSI_STATUS_STRINGS_MASK;
494
 	iscsi->status &= ~ISCSI_STATUS_STRINGS_MASK;
495
+
496
+	/* Free any dynamically allocated storage used for login */
497
+	chap_finish ( &iscsi->chap );
473
 }
498
 }
474
 
499
 
475
 /**
500
 /**
547
 	/* Prepare for CHAP with MD5 */
572
 	/* Prepare for CHAP with MD5 */
548
 	if ( ( rc = chap_init ( &iscsi->chap, &md5_algorithm ) ) != 0 ) {
573
 	if ( ( rc = chap_init ( &iscsi->chap, &md5_algorithm ) ) != 0 ) {
549
 		DBG ( "iSCSI %p could not initialise CHAP\n", iscsi );
574
 		DBG ( "iSCSI %p could not initialise CHAP\n", iscsi );
575
+		iscsi_close ( iscsi );
550
 		iscsi_done ( iscsi, rc );
576
 		iscsi_done ( iscsi, rc );
551
 	}
577
 	}
552
 }
578
 }
707
 	/* Buffer up the PDU data */
733
 	/* Buffer up the PDU data */
708
 	if ( ( rc = iscsi_rx_buffered_data ( iscsi, data, len ) ) != 0 ) {
734
 	if ( ( rc = iscsi_rx_buffered_data ( iscsi, data, len ) ) != 0 ) {
709
 		DBG ( "iSCSI %p could not buffer login response\n", iscsi );
735
 		DBG ( "iSCSI %p could not buffer login response\n", iscsi );
736
+		iscsi_close ( iscsi );
710
 		iscsi_done ( iscsi, rc );
737
 		iscsi_done ( iscsi, rc );
711
 		return;
738
 		return;
712
 	}
739
 	}
720
 	/* Check for login redirection */
747
 	/* Check for login redirection */
721
 	if ( response->status_class == ISCSI_STATUS_REDIRECT ) {
748
 	if ( response->status_class == ISCSI_STATUS_REDIRECT ) {
722
 		DBG ( "iSCSI %p redirecting to new server\n", iscsi );
749
 		DBG ( "iSCSI %p redirecting to new server\n", iscsi );
723
-		tcp_close ( &iscsi->tcp );
724
-		iscsi->status = 0;
750
+		iscsi_close ( iscsi );
725
 		if ( ( rc = tcp_connect ( &iscsi->tcp, &iscsi->target,
751
 		if ( ( rc = tcp_connect ( &iscsi->tcp, &iscsi->target,
726
 					  0 ) ) != 0 ) {
752
 					  0 ) ) != 0 ) {
727
 			DBG ( "iSCSI %p could not open TCP connection\n",
753
 			DBG ( "iSCSI %p could not open TCP connection\n",
735
 	if ( response->status_class != 0 ) {
761
 	if ( response->status_class != 0 ) {
736
 		DBG ( "iSCSI login failure: class %02x detail %02x\n",
762
 		DBG ( "iSCSI login failure: class %02x detail %02x\n",
737
 		      response->status_class, response->status_detail );
763
 		      response->status_class, response->status_detail );
764
+		iscsi->instant_rc = -EPERM;
765
+		iscsi_close ( iscsi );
738
 		iscsi_done ( iscsi, -EPERM );
766
 		iscsi_done ( iscsi, -EPERM );
739
 		return;
767
 		return;
740
 	}
768
 	}
753
 		default:
781
 		default:
754
 			DBG ( "iSCSI %p got invalid response flags %02x\n",
782
 			DBG ( "iSCSI %p got invalid response flags %02x\n",
755
 			      iscsi, response->flags );
783
 			      iscsi, response->flags );
784
+			iscsi_close ( iscsi );
756
 			iscsi_done ( iscsi, -EIO );
785
 			iscsi_done ( iscsi, -EIO );
757
 			return;
786
 			return;
758
 		}
787
 		}
767
 		return;
796
 		return;
768
 	}
797
 	}
769
 
798
 
799
+	/* Reset retry count */
800
+	iscsi->retry_count = 0;
801
+
770
 	/* Record TSIH for future reference */
802
 	/* Record TSIH for future reference */
771
 	iscsi->tsih = ntohl ( response->tsih );
803
 	iscsi->tsih = ntohl ( response->tsih );
772
 	
804
 	
986
 	default:
1018
 	default:
987
 		if ( remaining )
1019
 		if ( remaining )
988
 			return;
1020
 			return;
989
-		printf ( "Unknown iSCSI opcode %02x\n", response->opcode );
1021
+		DBG ( "Unknown iSCSI opcode %02x\n", response->opcode );
1022
+		iscsi_close ( iscsi );
990
 		iscsi_done ( iscsi, -EOPNOTSUPP );
1023
 		iscsi_done ( iscsi, -EOPNOTSUPP );
991
 		break;
1024
 		break;
992
 	}
1025
 	}
1112
 	struct iscsi_session *iscsi = tcp_to_iscsi ( app );
1145
 	struct iscsi_session *iscsi = tcp_to_iscsi ( app );
1113
 	int rc;
1146
 	int rc;
1114
 
1147
 
1115
-	/* Clear session status */
1116
-	iscsi->status = 0;
1148
+	/* Even a graceful close counts as an error for iSCSI */
1149
+	if ( ! status )
1150
+		status = -ECONNRESET;
1151
+
1152
+	/* Close session cleanly */
1153
+	iscsi_close ( iscsi );
1117
 
1154
 
1118
 	/* Retry connection if within the retry limit, otherwise fail */
1155
 	/* Retry connection if within the retry limit, otherwise fail */
1119
 	if ( ++iscsi->retry_count <= ISCSI_MAX_RETRIES ) {
1156
 	if ( ++iscsi->retry_count <= ISCSI_MAX_RETRIES ) {
1120
-		DBG ( "iSCSI %p retrying connection\n", iscsi );
1157
+		DBG ( "iSCSI %p retrying connection (retry #%d)\n",
1158
+		      iscsi, iscsi->retry_count );
1121
 		if ( ( rc = tcp_connect ( app, &iscsi->target, 0 ) ) != 0 ) {
1159
 		if ( ( rc = tcp_connect ( app, &iscsi->target, 0 ) ) != 0 ) {
1122
 			DBG ( "iSCSI %p could not open TCP connection\n",
1160
 			DBG ( "iSCSI %p could not open TCP connection\n",
1123
 			      iscsi );
1161
 			      iscsi );
1124
 			iscsi_done ( iscsi, rc );
1162
 			iscsi_done ( iscsi, rc );
1125
 		}
1163
 		}
1126
 	} else {
1164
 	} else {
1127
-		printf ( "iSCSI %p retry count exceeded\n", iscsi );
1165
+		DBG ( "iSCSI %p retry count exceeded\n", iscsi );
1166
+		iscsi->instant_rc = status;
1128
 		iscsi_done ( iscsi, status );
1167
 		iscsi_done ( iscsi, status );
1129
 	}
1168
 	}
1130
 }
1169
 }
1138
 static void iscsi_connected ( struct tcp_application *app ) {
1177
 static void iscsi_connected ( struct tcp_application *app ) {
1139
 	struct iscsi_session *iscsi = tcp_to_iscsi ( app );
1178
 	struct iscsi_session *iscsi = tcp_to_iscsi ( app );
1140
 
1179
 
1141
-	/* Set connected flag and reset retry count */
1180
+	assert ( iscsi->rx_state == ISCSI_RX_BHS );
1181
+	assert ( iscsi->rx_offset == 0 );
1182
+
1183
+	/* Enter security negotiation phase */
1142
 	iscsi->status = ( ISCSI_STATUS_SECURITY_NEGOTIATION_PHASE |
1184
 	iscsi->status = ( ISCSI_STATUS_SECURITY_NEGOTIATION_PHASE |
1143
 			  ISCSI_STATUS_STRINGS_SECURITY );
1185
 			  ISCSI_STATUS_STRINGS_SECURITY );
1144
-	iscsi->retry_count = 0;
1145
-
1146
-	/* Prepare to receive PDUs. */
1147
-	iscsi->rx_state = ISCSI_RX_BHS;
1148
-	iscsi->rx_offset = 0;
1149
 
1186
 
1150
 	/* Assign fresh initiator task tag */
1187
 	/* Assign fresh initiator task tag */
1151
 	iscsi->itt++;
1188
 	iscsi->itt++;
1177
 	assert ( iscsi->command == NULL );
1214
 	assert ( iscsi->command == NULL );
1178
 	iscsi->command = command;
1215
 	iscsi->command = command;
1179
 
1216
 
1180
-	if ( iscsi->status ) {
1181
-		if ( ( iscsi->status & ISCSI_STATUS_PHASE_MASK ) ==
1182
-		     ISCSI_STATUS_FULL_FEATURE_PHASE ) {
1183
-			/* Session already open: issue command */
1184
-			iscsi_start_command ( iscsi );
1185
-			tcp_senddata ( &iscsi->tcp );
1186
-		} else {
1187
-			/* Session failed to reach full feature phase:
1188
-			 * abort immediately rather than retrying the
1189
-			 * login.
1190
-			 */
1191
-			iscsi_done ( iscsi, -EPERM );
1192
-		}
1217
+	if ( iscsi->instant_rc ) {
1218
+		/* Abort immediately rather than retrying */
1219
+		iscsi_done ( iscsi, iscsi->instant_rc );
1220
+	} else if ( iscsi->status ) {
1221
+		/* Session already open: issue command */
1222
+		iscsi_start_command ( iscsi );
1223
+		tcp_senddata ( &iscsi->tcp );
1193
 	} else {
1224
 	} else {
1194
 		/* Session not open: initiate login */
1225
 		/* Session not open: initiate login */
1195
 		iscsi->tcp.tcp_op = &iscsi_tcp_operations;
1226
 		iscsi->tcp.tcp_op = &iscsi_tcp_operations;
1211
  * @ret aop		Asynchronous operation
1242
  * @ret aop		Asynchronous operation
1212
  */
1243
  */
1213
 void iscsi_shutdown ( struct iscsi_session *iscsi ) {
1244
 void iscsi_shutdown ( struct iscsi_session *iscsi ) {
1214
-	iscsi->status = 0;
1215
-	tcp_close ( &iscsi->tcp );
1245
+	iscsi_close ( iscsi );
1216
 }
1246
 }

Loading…
Cancel
Save