Browse Source

[tcp] Truncate TCP window to prevent future packet discards

Whenever memory pressure causes a queued packet to be discarded (and
so retransmitted), reduce the maximum TCP window to a size that would
have prevented the discard.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 12 years ago
parent
commit
a5d16a91af
1 changed files with 20 additions and 3 deletions
  1. 20
    3
      src/net/tcp.c

+ 20
- 3
src/net/tcp.c View File

97
 	 * Equivalent to Rcv.Wind.Scale in RFC 1323 terminology
97
 	 * Equivalent to Rcv.Wind.Scale in RFC 1323 terminology
98
 	 */
98
 	 */
99
 	uint8_t rcv_win_scale;
99
 	uint8_t rcv_win_scale;
100
+	/** Maximum receive window */
101
+	uint32_t max_rcv_win;
100
 
102
 
101
 	/** Transmit queue */
103
 	/** Transmit queue */
102
 	struct list_head tx_queue;
104
 	struct list_head tx_queue;
295
 	tcp->tcp_state = TCP_STATE_SENT ( TCP_SYN );
297
 	tcp->tcp_state = TCP_STATE_SENT ( TCP_SYN );
296
 	tcp_dump_state ( tcp );
298
 	tcp_dump_state ( tcp );
297
 	tcp->snd_seq = random();
299
 	tcp->snd_seq = random();
300
+	tcp->max_rcv_win = TCP_MAX_WINDOW_SIZE;
298
 	INIT_LIST_HEAD ( &tcp->tx_queue );
301
 	INIT_LIST_HEAD ( &tcp->tx_queue );
299
 	INIT_LIST_HEAD ( &tcp->rx_queue );
302
 	INIT_LIST_HEAD ( &tcp->rx_queue );
300
 	memcpy ( &tcp->peer, st_peer, sizeof ( tcp->peer ) );
303
 	memcpy ( &tcp->peer, st_peer, sizeof ( tcp->peer ) );
557
 	tcp_process_tx_queue ( tcp, len, iobuf, 0 );
560
 	tcp_process_tx_queue ( tcp, len, iobuf, 0 );
558
 
561
 
559
 	/* Expand receive window if possible */
562
 	/* Expand receive window if possible */
560
-	max_rcv_win = ( ( freemem * 3 ) / 4 );
561
-	if ( max_rcv_win > TCP_MAX_WINDOW_SIZE )
562
-		max_rcv_win = TCP_MAX_WINDOW_SIZE;
563
+	max_rcv_win = tcp->max_rcv_win;
563
 	app_win = xfer_window ( &tcp->xfer );
564
 	app_win = xfer_window ( &tcp->xfer );
564
 	if ( max_rcv_win > app_win )
565
 	if ( max_rcv_win > app_win )
565
 		max_rcv_win = app_win;
566
 		max_rcv_win = app_win;
1299
 static unsigned int tcp_discard ( void ) {
1300
 static unsigned int tcp_discard ( void ) {
1300
 	struct tcp_connection *tcp;
1301
 	struct tcp_connection *tcp;
1301
 	struct io_buffer *iobuf;
1302
 	struct io_buffer *iobuf;
1303
+	struct tcp_rx_queued_header *tcpqhdr;
1304
+	uint32_t max_win;
1302
 	unsigned int discarded = 0;
1305
 	unsigned int discarded = 0;
1303
 
1306
 
1304
 	/* Try to drop one queued RX packet from each connection */
1307
 	/* Try to drop one queued RX packet from each connection */
1305
 	list_for_each_entry ( tcp, &tcp_conns, list ) {
1308
 	list_for_each_entry ( tcp, &tcp_conns, list ) {
1306
 		list_for_each_entry_reverse ( iobuf, &tcp->rx_queue, list ) {
1309
 		list_for_each_entry_reverse ( iobuf, &tcp->rx_queue, list ) {
1310
+
1311
+			/* Limit window to prevent future discards */
1312
+			tcpqhdr = iobuf->data;
1313
+			max_win = ( tcpqhdr->seq - tcp->rcv_ack );
1314
+			if ( max_win < tcp->max_rcv_win ) {
1315
+				DBGC ( tcp, "TCP %p reducing maximum window "
1316
+				       "from %d to %d\n",
1317
+				       tcp, tcp->max_rcv_win, max_win );
1318
+				tcp->max_rcv_win = max_win;
1319
+			}
1320
+
1321
+			/* Remove packet from queue */
1307
 			list_del ( &iobuf->list );
1322
 			list_del ( &iobuf->list );
1308
 			free_iob ( iobuf );
1323
 			free_iob ( iobuf );
1324
+
1325
+			/* Report discard */
1309
 			discarded++;
1326
 			discarded++;
1310
 			break;
1327
 			break;
1311
 		}
1328
 		}

Loading…
Cancel
Save