summaryrefslogtreecommitdiffstats
path: root/src/net/tcp.c
diff options
context:
space:
mode:
authorMichael Brown2009-06-23 15:28:00 +0200
committerMichael Brown2009-06-23 15:28:00 +0200
commit99e64f5806524a60386ccbb928227af7511c3b16 (patch)
tree358c4b2efa20ef1e71a53dcf3bdab33c2380dcab /src/net/tcp.c
parent[tcp] Include current sequence numbers in "timer expired" messages (diff)
downloadipxe-99e64f5806524a60386ccbb928227af7511c3b16.tar.gz
ipxe-99e64f5806524a60386ccbb928227af7511c3b16.tar.xz
ipxe-99e64f5806524a60386ccbb928227af7511c3b16.zip
[tcp] Attempt to catch all possible error cases with debug messages
All TCP errors or unusual events should now generate a debugging message at DBGLVL_LOG, with enough information (SEQ and ACK numbers) to be able to identify the corresponding packet (or missing packet) in a network trace from the remote end.
Diffstat (limited to 'src/net/tcp.c')
-rw-r--r--src/net/tcp.c47
1 files changed, 36 insertions, 11 deletions
diff --git a/src/net/tcp.c b/src/net/tcp.c
index d9f6c2d1..5a64c83f 100644
--- a/src/net/tcp.c
+++ b/src/net/tcp.c
@@ -402,6 +402,7 @@ static int tcp_xmit ( struct tcp_connection *tcp, int force_send ) {
size_t seq_len;
size_t app_win;
size_t max_rcv_win;
+ int rc;
/* If retransmission timer is already running, do nothing */
if ( timer_running ( &tcp->timer ) )
@@ -438,7 +439,9 @@ static int tcp_xmit ( struct tcp_connection *tcp, int force_send ) {
/* Allocate I/O buffer */
iobuf = alloc_iob ( len + MAX_HDR_LEN );
if ( ! iobuf ) {
- DBGC ( tcp, "TCP %p could not allocate data buffer\n", tcp );
+ DBGC ( tcp, "TCP %p could not allocate iobuf for %08x..%08x "
+ "%08x\n", tcp, tcp->snd_seq, ( tcp->snd_seq + seq_len ),
+ tcp->rcv_ack );
return -ENOMEM;
}
iob_reserve ( iobuf, MAX_HDR_LEN );
@@ -495,8 +498,15 @@ static int tcp_xmit ( struct tcp_connection *tcp, int force_send ) {
DBGC2 ( tcp, "\n" );
/* Transmit packet */
- return tcpip_tx ( iobuf, &tcp_protocol, NULL, &tcp->peer, NULL,
- &tcphdr->csum );
+ if ( ( rc = tcpip_tx ( iobuf, &tcp_protocol, NULL, &tcp->peer, NULL,
+ &tcphdr->csum ) ) != 0 ) {
+ DBGC ( tcp, "TCP %p could not transmit %08x..%08x %08x: %s\n",
+ tcp, tcp->snd_seq, ( tcp->snd_seq + tcp->snd_sent ),
+ tcp->rcv_ack, strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
}
/**
@@ -510,9 +520,9 @@ static void tcp_expired ( struct retry_timer *timer, int over ) {
container_of ( timer, struct tcp_connection, timer );
int graceful_close = TCP_CLOSED_GRACEFULLY ( tcp->tcp_state );
- DBGC ( tcp, "TCP %p timer %s in %s for [%08x,%08x)\n", tcp,
+ DBGC ( tcp, "TCP %p timer %s in %s for %08x..%08x %08x\n", tcp,
( over ? "expired" : "fired" ), tcp_state ( tcp->tcp_state ),
- tcp->snd_seq, ( tcp->snd_seq + tcp->snd_sent ) );
+ tcp->snd_seq, ( tcp->snd_seq + tcp->snd_sent ), tcp->rcv_ack );
assert ( ( tcp->tcp_state == TCP_SYN_SENT ) ||
( tcp->tcp_state == TCP_SYN_RCVD ) ||
@@ -547,11 +557,14 @@ static int tcp_xmit_reset ( struct tcp_connection *tcp,
struct tcp_header *in_tcphdr ) {
struct io_buffer *iobuf;
struct tcp_header *tcphdr;
+ int rc;
/* Allocate space for dataless TX buffer */
iobuf = alloc_iob ( MAX_HDR_LEN );
if ( ! iobuf ) {
- DBGC ( tcp, "TCP %p could not allocate data buffer\n", tcp );
+ DBGC ( tcp, "TCP %p could not allocate iobuf for RST "
+ "%08x..%08x %08x\n", tcp, ntohl ( in_tcphdr->ack ),
+ ntohl ( in_tcphdr->ack ), ntohl ( in_tcphdr->seq ) );
return -ENOMEM;
}
iob_reserve ( iobuf, MAX_HDR_LEN );
@@ -577,8 +590,16 @@ static int tcp_xmit_reset ( struct tcp_connection *tcp,
DBGC2 ( tcp, "\n" );
/* Transmit packet */
- return tcpip_tx ( iobuf, &tcp_protocol, NULL, st_dest,
- NULL, &tcphdr->csum );
+ if ( ( rc = tcpip_tx ( iobuf, &tcp_protocol, NULL, st_dest,
+ NULL, &tcphdr->csum ) ) != 0 ) {
+ DBGC ( tcp, "TCP %p could not transmit RST %08x..%08x %08x: "
+ "%s\n", tcp, ntohl ( in_tcphdr->ack ),
+ ntohl ( in_tcphdr->ack ), ntohl ( in_tcphdr->seq ),
+ strerror ( rc ) );
+ return rc;
+ }
+
+ return 0;
}
/***************************************************************************
@@ -728,8 +749,8 @@ static int tcp_rx_ack ( struct tcp_connection *tcp, uint32_t ack,
* timer running, as for the ack_len==0 case, to
* handle old duplicate ACKs.
*/
- DBGC ( tcp, "TCP %p received ACK for [%08x,%08zx), "
- "sent only [%08x,%08x)\n", tcp, tcp->snd_seq,
+ DBGC ( tcp, "TCP %p received ACK for %08x..%08zx, "
+ "sent only %08x..%08x\n", tcp, tcp->snd_seq,
( tcp->snd_seq + ack_len ), tcp->snd_seq,
( tcp->snd_seq + tcp->snd_sent ) );
/* Send RST if an out-of-range ACK is received on a
@@ -785,8 +806,11 @@ static int tcp_rx_data ( struct tcp_connection *tcp, uint32_t seq,
len -= already_rcvd;
/* Deliver data to application */
- if ( ( rc = xfer_deliver_iob ( &tcp->xfer, iobuf ) ) != 0 )
+ if ( ( rc = xfer_deliver_iob ( &tcp->xfer, iobuf ) ) != 0 ) {
+ DBGC ( tcp, "TCP %p could not deliver %08x..%08x: %s\n",
+ tcp, seq, ( seq + len ), strerror ( rc ) );
return rc;
+ }
/* Acknowledge new data */
tcp_rx_seq ( tcp, len );
@@ -844,6 +868,7 @@ static int tcp_rx_rst ( struct tcp_connection *tcp, uint32_t seq ) {
tcp_dump_state ( tcp );
tcp_close ( tcp, -ECONNRESET );
+ DBGC ( tcp, "TCP %p connection reset by peer\n", tcp );
return -ECONNRESET;
}