Skip to content

Commit

Permalink
[tcp] Do not shrink window when discarding received packets
Browse files Browse the repository at this point in the history
We currently shrink the TCP window permanently if we are ever forced
(by a low-memory condition) to discard a previously received TCP
packet.  This behaviour was intended to reduce the number of
retransmissions in a lossy network, since lost packets might
potentially result in the entire window contents being retransmitted.

Since commit e0fc8fe ("[tcp] Implement support for TCP Selective
Acknowledgements (SACK)") the cost of lost packets has been reduced by
around one order of magnitude, and the reduction in the window size
(which affects the maximum throughput) is now the more significant
cost.

Remove the code which reduces the TCP maximum window size when a
received packet is discarded.

Reported-by: Wissam Shoukair <wissams@mellanox.com>
Tested-by: Wissam Shoukair <wissams@mellanox.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
  • Loading branch information
mcb30 committed Jun 25, 2015
1 parent e46154f commit c117b25
Showing 1 changed file with 3 additions and 20 deletions.
23 changes: 3 additions & 20 deletions src/net/tcp.c
Expand Up @@ -101,8 +101,6 @@ struct tcp_connection {
* Equivalent to Rcv.Wind.Scale in RFC 1323 terminology
*/
uint8_t rcv_win_scale;
/** Maximum receive window */
uint32_t max_rcv_win;

/** Selective acknowledgement list (in host-endian order) */
struct tcp_sack_block sack[TCP_SACK_MAX];
Expand Down Expand Up @@ -291,7 +289,6 @@ static int tcp_open ( struct interface *xfer, struct sockaddr *peer,
tcp->tcp_state = TCP_STATE_SENT ( TCP_SYN );
tcp_dump_state ( tcp );
tcp->snd_seq = random();
tcp->max_rcv_win = TCP_MAX_WINDOW_SIZE;
INIT_LIST_HEAD ( &tcp->tx_queue );
INIT_LIST_HEAD ( &tcp->rx_queue );
memcpy ( &tcp->peer, st_peer, sizeof ( tcp->peer ) );
Expand Down Expand Up @@ -615,7 +612,6 @@ static void tcp_xmit_sack ( struct tcp_connection *tcp, uint32_t sack_seq ) {
size_t len = 0;
size_t sack_len;
uint32_t seq_len;
uint32_t app_win;
uint32_t max_rcv_win;
uint32_t max_representable_win;
int rc;
Expand Down Expand Up @@ -669,10 +665,9 @@ static void tcp_xmit_sack ( struct tcp_connection *tcp, uint32_t sack_seq ) {
tcp_process_tx_queue ( tcp, len, iobuf, 0 );

/* Expand receive window if possible */
max_rcv_win = tcp->max_rcv_win;
app_win = xfer_window ( &tcp->xfer );
if ( max_rcv_win > app_win )
max_rcv_win = app_win;
max_rcv_win = xfer_window ( &tcp->xfer );
if ( max_rcv_win > TCP_MAX_WINDOW_SIZE )
max_rcv_win = TCP_MAX_WINDOW_SIZE;
max_representable_win = ( 0xffff << tcp->rcv_win_scale );
if ( max_rcv_win > max_representable_win )
max_rcv_win = max_representable_win;
Expand Down Expand Up @@ -1482,24 +1477,12 @@ struct tcpip_protocol tcp_protocol __tcpip_protocol = {
static unsigned int tcp_discard ( void ) {
struct tcp_connection *tcp;
struct io_buffer *iobuf;
struct tcp_rx_queued_header *tcpqhdr;
uint32_t max_win;
unsigned int discarded = 0;

/* Try to drop one queued RX packet from each connection */
list_for_each_entry ( tcp, &tcp_conns, list ) {
list_for_each_entry_reverse ( iobuf, &tcp->rx_queue, list ) {

/* Limit window to prevent future discards */
tcpqhdr = iobuf->data;
max_win = ( tcpqhdr->seq - tcp->rcv_ack );
if ( max_win < tcp->max_rcv_win ) {
DBGC ( tcp, "TCP %p reducing maximum window "
"from %d to %d\n",
tcp, tcp->max_rcv_win, max_win );
tcp->max_rcv_win = max_win;
}

/* Remove packet from queue */
list_del ( &iobuf->list );
free_iob ( iobuf );
Expand Down

0 comments on commit c117b25

Please sign in to comment.