david/ipxe
david
/
ipxe
Archived
1
0
Fork 0

Limit xmit window to one MTU. (Path MTU discovery not yet

implemented; should be done at some point.)
This commit is contained in:
Michael Brown 2007-07-08 14:33:53 +01:00
parent 3e1dd0772a
commit edded7546e
2 changed files with 42 additions and 16 deletions

View File

@ -237,6 +237,14 @@ struct tcp_mss_option {
*/ */
#define TCP_MAX_WINDOW_SIZE ( 65536 - 4 ) #define TCP_MAX_WINDOW_SIZE ( 65536 - 4 )
/**
* Path MTU
*
* We really ought to implement Path MTU discovery. Until we do,
* anything with a path MTU greater than this may fail.
*/
#define TCP_PATH_MTU 1460
/** /**
* Advertised TCP MSS * Advertised TCP MSS
* *

View File

@ -301,6 +301,27 @@ static void tcp_close ( struct tcp_connection *tcp, int rc ) {
*************************************************************************** ***************************************************************************
*/ */
/**
* Calculate transmission window
*
* @v tcp TCP connection
* @ret len Maximum length that can be sent in a single packet
*/
static size_t tcp_xmit_win ( struct tcp_connection *tcp ) {
size_t len;
/* Not ready if we're not in a suitable connection state */
if ( ! TCP_CAN_SEND_DATA ( tcp->tcp_state ) )
return 0;
/* Length is the minimum of the receiver's window and the path MTU */
len = tcp->snd_win;
if ( len > TCP_PATH_MTU )
len = TCP_PATH_MTU;
return len;
}
/** /**
* Process TCP transmit queue * Process TCP transmit queue
* *
@ -363,8 +384,8 @@ static int tcp_xmit ( struct tcp_connection *tcp, int force_send ) {
unsigned int flags; unsigned int flags;
size_t len = 0; size_t len = 0;
size_t seq_len; size_t seq_len;
size_t app_window; size_t app_win;
size_t window; size_t rcv_win;
int rc; int rc;
/* If retransmission timer is already running, do nothing */ /* If retransmission timer is already running, do nothing */
@ -375,7 +396,8 @@ static int tcp_xmit ( struct tcp_connection *tcp, int force_send ) {
* lengths that we wish to transmit. * lengths that we wish to transmit.
*/ */
if ( TCP_CAN_SEND_DATA ( tcp->tcp_state ) ) { if ( TCP_CAN_SEND_DATA ( tcp->tcp_state ) ) {
len = tcp_process_queue ( tcp, tcp->snd_win, NULL, 0 ); len = tcp_process_queue ( tcp, tcp_xmit_win ( tcp ),
NULL, 0 );
} }
seq_len = len; seq_len = len;
flags = TCP_FLAGS_SENDING ( tcp->tcp_state ); flags = TCP_FLAGS_SENDING ( tcp->tcp_state );
@ -410,13 +432,13 @@ static int tcp_xmit ( struct tcp_connection *tcp, int force_send ) {
tcp_process_queue ( tcp, len, iobuf, 0 ); tcp_process_queue ( tcp, len, iobuf, 0 );
/* Estimate window size */ /* Estimate window size */
window = ( ( freemem * 3 ) / 4 ); rcv_win = ( ( freemem * 3 ) / 4 );
if ( window > TCP_MAX_WINDOW_SIZE ) if ( rcv_win > TCP_MAX_WINDOW_SIZE )
window = TCP_MAX_WINDOW_SIZE; rcv_win = TCP_MAX_WINDOW_SIZE;
app_window = xfer_window ( &tcp->xfer ); app_win = xfer_window ( &tcp->xfer );
if ( window > app_window ) if ( rcv_win > app_win )
window = app_window; rcv_win = app_win;
window &= ~0x03; /* Keep everything dword-aligned */ rcv_win &= ~0x03; /* Keep everything dword-aligned */
/* Fill up the TCP header */ /* Fill up the TCP header */
payload = iobuf->data; payload = iobuf->data;
@ -434,7 +456,7 @@ static int tcp_xmit ( struct tcp_connection *tcp, int force_send ) {
tcphdr->ack = htonl ( tcp->rcv_ack ); tcphdr->ack = htonl ( tcp->rcv_ack );
tcphdr->hlen = ( ( payload - iobuf->data ) << 2 ); tcphdr->hlen = ( ( payload - iobuf->data ) << 2 );
tcphdr->flags = flags; tcphdr->flags = flags;
tcphdr->win = htons ( window ); tcphdr->win = htons ( rcv_win );
tcphdr->csum = tcpip_chksum ( iobuf->data, iob_len ( iobuf ) ); tcphdr->csum = tcpip_chksum ( iobuf->data, iob_len ( iobuf ) );
/* Dump header */ /* Dump header */
@ -910,10 +932,6 @@ static size_t tcp_xfer_window ( struct xfer_interface *xfer ) {
struct tcp_connection *tcp = struct tcp_connection *tcp =
container_of ( xfer, struct tcp_connection, xfer ); container_of ( xfer, struct tcp_connection, xfer );
/* Not ready if we're not in a suitable connection state */
if ( ! TCP_CAN_SEND_DATA ( tcp->tcp_state ) )
return 0;
/* Not ready if data queue is non-empty. This imposes a limit /* Not ready if data queue is non-empty. This imposes a limit
* of only one unACKed packet in the TX queue at any time; we * of only one unACKed packet in the TX queue at any time; we
* do this to conserve memory usage. * do this to conserve memory usage.
@ -922,7 +940,7 @@ static size_t tcp_xfer_window ( struct xfer_interface *xfer ) {
return 0; return 0;
/* Return TCP window length */ /* Return TCP window length */
return tcp->snd_win; return tcp_xmit_win ( tcp );
} }
/** /**