[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.
This commit is contained in:
parent
f4605970f4
commit
99e64f5806
|
@ -402,6 +402,7 @@ static int tcp_xmit ( struct tcp_connection *tcp, int force_send ) {
|
||||||
size_t seq_len;
|
size_t seq_len;
|
||||||
size_t app_win;
|
size_t app_win;
|
||||||
size_t max_rcv_win;
|
size_t max_rcv_win;
|
||||||
|
int rc;
|
||||||
|
|
||||||
/* If retransmission timer is already running, do nothing */
|
/* If retransmission timer is already running, do nothing */
|
||||||
if ( timer_running ( &tcp->timer ) )
|
if ( timer_running ( &tcp->timer ) )
|
||||||
|
@ -438,7 +439,9 @@ static int tcp_xmit ( struct tcp_connection *tcp, int force_send ) {
|
||||||
/* Allocate I/O buffer */
|
/* Allocate I/O buffer */
|
||||||
iobuf = alloc_iob ( len + MAX_HDR_LEN );
|
iobuf = alloc_iob ( len + MAX_HDR_LEN );
|
||||||
if ( ! iobuf ) {
|
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;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
iob_reserve ( iobuf, MAX_HDR_LEN );
|
iob_reserve ( iobuf, MAX_HDR_LEN );
|
||||||
|
@ -495,8 +498,15 @@ static int tcp_xmit ( struct tcp_connection *tcp, int force_send ) {
|
||||||
DBGC2 ( tcp, "\n" );
|
DBGC2 ( tcp, "\n" );
|
||||||
|
|
||||||
/* Transmit packet */
|
/* Transmit packet */
|
||||||
return tcpip_tx ( iobuf, &tcp_protocol, NULL, &tcp->peer, NULL,
|
if ( ( rc = tcpip_tx ( iobuf, &tcp_protocol, NULL, &tcp->peer, NULL,
|
||||||
&tcphdr->csum );
|
&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 );
|
container_of ( timer, struct tcp_connection, timer );
|
||||||
int graceful_close = TCP_CLOSED_GRACEFULLY ( tcp->tcp_state );
|
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 ),
|
( 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 ) ||
|
assert ( ( tcp->tcp_state == TCP_SYN_SENT ) ||
|
||||||
( tcp->tcp_state == TCP_SYN_RCVD ) ||
|
( 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 tcp_header *in_tcphdr ) {
|
||||||
struct io_buffer *iobuf;
|
struct io_buffer *iobuf;
|
||||||
struct tcp_header *tcphdr;
|
struct tcp_header *tcphdr;
|
||||||
|
int rc;
|
||||||
|
|
||||||
/* Allocate space for dataless TX buffer */
|
/* Allocate space for dataless TX buffer */
|
||||||
iobuf = alloc_iob ( MAX_HDR_LEN );
|
iobuf = alloc_iob ( MAX_HDR_LEN );
|
||||||
if ( ! iobuf ) {
|
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;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
iob_reserve ( iobuf, MAX_HDR_LEN );
|
iob_reserve ( iobuf, MAX_HDR_LEN );
|
||||||
|
@ -577,8 +590,16 @@ static int tcp_xmit_reset ( struct tcp_connection *tcp,
|
||||||
DBGC2 ( tcp, "\n" );
|
DBGC2 ( tcp, "\n" );
|
||||||
|
|
||||||
/* Transmit packet */
|
/* Transmit packet */
|
||||||
return tcpip_tx ( iobuf, &tcp_protocol, NULL, st_dest,
|
if ( ( rc = tcpip_tx ( iobuf, &tcp_protocol, NULL, st_dest,
|
||||||
NULL, &tcphdr->csum );
|
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
|
* timer running, as for the ack_len==0 case, to
|
||||||
* handle old duplicate ACKs.
|
* handle old duplicate ACKs.
|
||||||
*/
|
*/
|
||||||
DBGC ( tcp, "TCP %p received ACK for [%08x,%08zx), "
|
DBGC ( tcp, "TCP %p received ACK for %08x..%08zx, "
|
||||||
"sent only [%08x,%08x)\n", tcp, tcp->snd_seq,
|
"sent only %08x..%08x\n", tcp, tcp->snd_seq,
|
||||||
( tcp->snd_seq + ack_len ), tcp->snd_seq,
|
( tcp->snd_seq + ack_len ), tcp->snd_seq,
|
||||||
( tcp->snd_seq + tcp->snd_sent ) );
|
( tcp->snd_seq + tcp->snd_sent ) );
|
||||||
/* Send RST if an out-of-range ACK is received on a
|
/* 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;
|
len -= already_rcvd;
|
||||||
|
|
||||||
/* Deliver data to application */
|
/* 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;
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
/* Acknowledge new data */
|
/* Acknowledge new data */
|
||||||
tcp_rx_seq ( tcp, len );
|
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_dump_state ( tcp );
|
||||||
tcp_close ( tcp, -ECONNRESET );
|
tcp_close ( tcp, -ECONNRESET );
|
||||||
|
|
||||||
|
DBGC ( tcp, "TCP %p connection reset by peer\n", tcp );
|
||||||
return -ECONNRESET;
|
return -ECONNRESET;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Reference in New Issue