Browse Source

[iscsi] Send any padding inline with the data segment

Some iSCSI targets respond to a PDU before receiving the padding
bytes.  If the target responds quickly enough, this can cause iPXE to
start processing a new TX PDU before the padding bytes have been sent,
which results in a protocol violation.

Fix by always transmitting the padding bytes along with the data
segment.

Originally-fixed-by: Shyam Iyer <shyam_iyer@dell.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 12 years ago
parent
commit
1d293776ea
2 changed files with 9 additions and 30 deletions
  1. 0
    2
      src/include/ipxe/iscsi.h
  2. 9
    28
      src/net/tcp/iscsi.c

+ 0
- 2
src/include/ipxe/iscsi.h View File

@@ -515,8 +515,6 @@ enum iscsi_tx_state {
515 515
 	ISCSI_TX_AHS,
516 516
 	/** Sending the data segment */
517 517
 	ISCSI_TX_DATA,
518
-	/** Sending the data segment padding */
519
-	ISCSI_TX_DATA_PADDING,
520 518
 };
521 519
 
522 520
 /** State of an iSCSI RX engine */

+ 9
- 28
src/net/tcp/iscsi.c View File

@@ -570,20 +570,23 @@ static int iscsi_tx_data_out ( struct iscsi_session *iscsi ) {
570 570
 	struct io_buffer *iobuf;
571 571
 	unsigned long offset;
572 572
 	size_t len;
573
+	size_t pad_len;
573 574
 
574 575
 	offset = ntohl ( data_out->offset );
575 576
 	len = ISCSI_DATA_LEN ( data_out->lengths );
577
+	pad_len = ISCSI_DATA_PAD_LEN ( data_out->lengths );
576 578
 
577 579
 	assert ( iscsi->command != NULL );
578 580
 	assert ( iscsi->command->data_out );
579 581
 	assert ( ( offset + len ) <= iscsi->command->data_out_len );
580 582
 
581
-	iobuf = xfer_alloc_iob ( &iscsi->socket, len );
583
+	iobuf = xfer_alloc_iob ( &iscsi->socket, ( len + pad_len ) );
582 584
 	if ( ! iobuf )
583 585
 		return -ENOMEM;
584 586
 	
585 587
 	copy_from_user ( iob_put ( iobuf, len ),
586 588
 			 iscsi->command->data_out, offset, len );
589
+	memset ( iob_put ( iobuf, pad_len ), 0, pad_len );
587 590
 
588 591
 	return xfer_deliver_iob ( &iscsi->socket, iobuf );
589 592
 }
@@ -801,13 +804,17 @@ static int iscsi_tx_login_request ( struct iscsi_session *iscsi ) {
801 804
 	struct iscsi_bhs_login_request *request = &iscsi->tx_bhs.login_request;
802 805
 	struct io_buffer *iobuf;
803 806
 	size_t len;
807
+	size_t pad_len;
804 808
 
805 809
 	len = ISCSI_DATA_LEN ( request->lengths );
806
-	iobuf = xfer_alloc_iob ( &iscsi->socket, len );
810
+	pad_len = ISCSI_DATA_PAD_LEN ( request->lengths );
811
+	iobuf = xfer_alloc_iob ( &iscsi->socket, ( len + pad_len ) );
807 812
 	if ( ! iobuf )
808 813
 		return -ENOMEM;
809 814
 	iob_put ( iobuf, len );
810 815
 	iscsi_build_login_request_strings ( iscsi, iobuf->data, len );
816
+	memset ( iob_put ( iobuf, pad_len ), 0, pad_len );
817
+
811 818
 	return xfer_deliver_iob ( &iscsi->socket, iobuf );
812 819
 }
813 820
 
@@ -1415,27 +1422,6 @@ static int iscsi_tx_data ( struct iscsi_session *iscsi ) {
1415 1422
 	}
1416 1423
 }
1417 1424
 
1418
-/**
1419
- * Transmit data padding of an iSCSI PDU
1420
- *
1421
- * @v iscsi		iSCSI session
1422
- * @ret rc		Return status code
1423
- * 
1424
- * Handle transmission of any data padding in a PDU data segment.
1425
- * iscsi::tx_bhs will be valid when this is called.
1426
- */
1427
-static int iscsi_tx_data_padding ( struct iscsi_session *iscsi ) {
1428
-	static const char pad[] = { '\0', '\0', '\0' };
1429
-	struct iscsi_bhs_common *common = &iscsi->tx_bhs.common;
1430
-	size_t pad_len;
1431
-	
1432
-	pad_len = ISCSI_DATA_PAD_LEN ( common->lengths );
1433
-	if ( ! pad_len )
1434
-		return 0;
1435
-
1436
-	return xfer_deliver_raw ( &iscsi->socket, pad, pad_len );
1437
-}
1438
-
1439 1425
 /**
1440 1426
  * Complete iSCSI PDU transmission
1441 1427
  *
@@ -1494,11 +1480,6 @@ static void iscsi_tx_step ( struct iscsi_session *iscsi ) {
1494 1480
 		case ISCSI_TX_DATA:
1495 1481
 			tx = iscsi_tx_data;
1496 1482
 			tx_len = ISCSI_DATA_LEN ( common->lengths );
1497
-			next_state = ISCSI_TX_DATA_PADDING;
1498
-			break;
1499
-		case ISCSI_TX_DATA_PADDING:
1500
-			tx = iscsi_tx_data_padding;
1501
-			tx_len = ISCSI_DATA_PAD_LEN ( common->lengths );
1502 1483
 			next_state = ISCSI_TX_IDLE;
1503 1484
 			break;
1504 1485
 		case ISCSI_TX_IDLE:

Loading…
Cancel
Save