diff options
author | Nikhil Chandru Rao | 2006-08-07 20:52:26 +0200 |
---|---|---|
committer | Nikhil Chandru Rao | 2006-08-07 20:52:26 +0200 |
commit | cb42e573a08694b31a1c6fed41cfb14607ae175b (patch) | |
tree | b125d0087a1c141d6e4a49af069898ff3206f176 /src/net/tcp.c | |
parent | Add very, very quick and dirty hello world test (diff) | |
download | ipxe-cb42e573a08694b31a1c6fed41cfb14607ae175b.tar.gz ipxe-cb42e573a08694b31a1c6fed41cfb14607ae175b.tar.xz ipxe-cb42e573a08694b31a1c6fed41cfb14607ae175b.zip |
Added retransmissions to TCP
Diffstat (limited to 'src/net/tcp.c')
-rw-r--r-- | src/net/tcp.c | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/src/net/tcp.c b/src/net/tcp.c index c9b4c433..2450f45a 100644 --- a/src/net/tcp.c +++ b/src/net/tcp.c @@ -11,6 +11,7 @@ #include <gpxe/ip.h> #include <gpxe/tcp.h> #include <gpxe/tcpip.h> +#include <gpxe/retry.h> #include "uip/uip.h" /** @file @@ -369,6 +370,58 @@ void tcp_init_conn ( struct tcp_connection *conn ) { conn->tcp_op = NULL; } +/** Retry timer + * + * @v timer Retry timer + * @v over Failure indicator + */ +void tcp_expired ( struct retry_timer *timer, int over ) { + struct tcp_connection *conn; + if ( over ) { + conn = ( struct tcp_connection * ) container_of ( timer, + struct tcp_connection, timer ); + switch ( conn->tcp_state ) { + case TCP_SYN_SENT: + if ( conn->retransmits > MAX_RETRANSMITS ) { + tcp_trans ( conn, TCP_CLOSED ); + return; + } + if ( conn->tcp_lstate == TCP_CLOSED || + conn->tcp_lstate == TCP_LISTEN ) { + goto send_tcp_nomsg; + } + return; + case TCP_SYN_RCVD: + tcp_trans ( conn, TCP_CLOSED ); + if ( conn->tcp_lstate == TCP_LISTEN || + conn->tcp_lstate == TCP_SYN_SENT ) { + goto send_tcp_nomsg; + } + return; + case TCP_ESTABLISHED: + break; + case TCP_FIN_WAIT_1: + case TCP_FIN_WAIT_2: + case TCP_CLOSE_WAIT: + goto send_tcp_nomsg; + case TCP_CLOSING: + case TCP_LAST_ACK: + return; + case TCP_TIME_WAIT: + tcp_trans ( conn, TCP_CLOSED ); + return; + } + /* Retransmit the data */ + tcp_senddata ( conn ); + conn->retransmits++; + return; + + send_tcp_nomsg: + tcp_send ( conn, TCP_NOMSG, TCP_NOMSG_LEN ); + return; + } +} + /** * Connect to a remote server * @@ -396,6 +449,9 @@ int tcp_connectto ( struct tcp_connection *conn, } memcpy ( &conn->peer, peer, sizeof ( conn->peer ) ); + /* Initialize the TCP timer */ + conn->timer.expired = tcp_expired; + /* Send a SYN packet and transition to TCP_SYN_SENT */ conn->snd_una = ( ( ( uint32_t ) random() ) << 16 ) & random(); tcp_trans ( conn, TCP_SYN_SENT ); @@ -577,6 +633,9 @@ int tcp_send ( struct tcp_connection *conn, const void *data, size_t len ) { /* Dump the TCP header */ tcp_dump ( tcphdr ); + /* Start the timer */ + start_timer ( &conn->timer ); + /* Transmit packet */ return tcpip_tx ( pkb, &tcp_protocol, peer ); } @@ -624,6 +683,10 @@ static int tcp_rx ( struct pk_buff *pkb, return 0; found_conn: + /* Stop the timer */ + stop_timer ( &conn->timer ); + conn->retransmits = 0; + /* Set the advertised window */ conn->snd_win = tcphdr->win; |