[gPXE-devel] [PATCH 2/2] [tcp] Cleanup TCP closing actions
Guo-Fu Tseng
cooldavid at cooldavid.org
Sun Jul 18 22:21:13 EDT 2010
From: Guo-Fu Tseng <cooldavid at cooldavid.org>
Separate tcp_terminate() from tcp_close().
Use tcp_terminate to immediately free all tcp resources.
And use tcp_close() to bing TCP connection to closing state.
Signed-off-by: Guo-Fu Tseng <cooldavid at cooldavid.org>
---
src/net/tcp.c | 124 +++++++++++++++++++++++++++++----------------------------
1 files changed, 63 insertions(+), 61 deletions(-)
diff --git a/src/net/tcp.c b/src/net/tcp.c
index 3e6543c..4e69f70 100644
--- a/src/net/tcp.c
+++ b/src/net/tcp.c
@@ -265,6 +265,12 @@ static int tcp_open ( struct xfer_interface *xfer, struct sockaddr *peer,
if ( ! tcp )
return -ENOMEM;
DBGC ( tcp, "TCP %p allocated\n", tcp );
+ /**
+ * refcnt is the first object of struct tcp_connection
+ * In other word, &tcp->refcnt == tcp.
+ * So that we can use default free(&tcp->refcnt) in ref_put()
+ * to free this tcp_connection structure.
+ */
ref_init ( &tcp->refcnt, NULL );
xfer_init ( &tcp->xfer, &tcp_xfer_operations, &tcp->refcnt );
timer_init ( &tcp->timer, tcp_expired );
@@ -297,42 +303,65 @@ static int tcp_open ( struct xfer_interface *xfer, struct sockaddr *peer,
}
/**
- * Close TCP connection
+ * Shutdown TCP xfer interface
*
* @v tcp TCP connection
* @v rc Reason for close
*
- * If the TCP state machine is in a suitable state, the
- * connection will be deleted.
+ * Closes the data transfer interface.
*/
-static void tcp_close ( struct tcp_connection *tcp ) {
+static void tcp_xfer_shutdown ( struct tcp_connection *tcp, int rc ) {
+ if ( tcp->flags & TCP_XFER_CLOSED )
+ return;
+
+ /* Close data transfer interface */
+ xfer_nullify ( &tcp->xfer );
+ xfer_close ( &tcp->xfer, rc );
+ tcp->flags |= TCP_XFER_CLOSED;
+}
+
+/**
+ * TCP connection final cleanup
+ *
+ * @v tcp TCP connection
+ * @v rc Reason for close
+ *
+ * Terminate TCP connection and free all resources
+ */
+static void tcp_terminate ( struct tcp_connection *tcp, int rc ) {
struct io_buffer *iobuf;
struct io_buffer *tmp;
- /* If we are in CLOSED, or have otherwise not yet received a
- * SYN (i.e. we are in LISTEN or SYN_SENT), just delete the
- * connection.
- */
- if ( ! ( tcp->tcp_state & TCP_STATE_RCVD ( TCP_SYN ) ) ) {
-
- /* Transition to CLOSED for the sake of debugging messages */
- tcp->tcp_state = TCP_CLOSED;
- tcp_dump_state ( tcp );
+ /* Shutdown TCP xfer interface */
+ tcp_xfer_shutdown ( tcp, rc );
- /* Free any unsent I/O buffers */
- list_for_each_entry_safe ( iobuf, tmp, &tcp->queue, list ) {
- list_del ( &iobuf->list );
- free_iob ( iobuf );
- }
+ /* Transition to CLOSED for the sake of debugging messages */
+ tcp->tcp_state = TCP_CLOSED;
+ tcp_dump_state ( tcp );
- /* Remove from list and drop reference */
- stop_timer ( &tcp->timer );
- list_del ( &tcp->list );
- ref_put ( &tcp->refcnt );
- DBGC ( tcp, "TCP %p connection deleted\n", tcp );
- return;
+ /* Free any unsent I/O buffers */
+ list_for_each_entry_safe ( iobuf, tmp, &tcp->queue, list ) {
+ list_del ( &iobuf->list );
+ free_iob ( iobuf );
}
+ /* Remove from list and drop reference */
+ stop_timer ( &tcp->timer );
+ stop_timer ( &tcp->wait );
+ list_del ( &tcp->list );
+ ref_put ( &tcp->refcnt );
+ DBGC ( tcp, "TCP %p connection deleted\n", tcp );
+}
+
+/**
+ * Start to close TCP connection
+ *
+ * @v tcp TCP connection
+ * @v rc Reason for close
+ *
+ * Bring TCP connection to closing state
+ */
+static void tcp_close ( struct tcp_connection *tcp ) {
/* If we have not had our SYN acknowledged (i.e. we are in
* SYN_RCVD), pretend that it has been acknowledged so that we
* can send a FIN without breaking things.
@@ -347,24 +376,6 @@ static void tcp_close ( struct tcp_connection *tcp ) {
}
}
-/**
- * Shutdown TCP xfer interface
- *
- * @v tcp TCP connection
- * @v rc Reason for close
- *
- * Closes the data transfer interface.
- */
-static void tcp_xfer_shutdown ( struct tcp_connection *tcp, int rc ) {
- if ( tcp->flags & TCP_XFER_CLOSED )
- return;
-
- /* Close data transfer interface */
- xfer_nullify ( &tcp->xfer );
- xfer_close ( &tcp->xfer, rc );
- tcp->flags |= TCP_XFER_CLOSED;
-}
-
/***************************************************************************
*
* Transmit data path
@@ -601,10 +612,7 @@ static void tcp_expired ( struct retry_timer *timer, int over ) {
/* If we have finally timed out and given up,
* terminate the connection
*/
- tcp->tcp_state = TCP_CLOSED;
- tcp_dump_state ( tcp );
- tcp_close ( tcp );
- tcp_xfer_shutdown ( tcp, -ETIMEDOUT );
+ tcp_terminate ( tcp, -ETIMEDOUT );
} else {
/* Otherwise, retransmit the packet */
tcp_xmit ( tcp );
@@ -627,10 +635,7 @@ static void tcp_wait_expired ( struct retry_timer *timer, int over __unused ) {
tcp_state ( tcp->tcp_state ), tcp->snd_seq,
( tcp->snd_seq + tcp->snd_sent ), tcp->rcv_ack );
- tcp->tcp_state = TCP_CLOSED;
- tcp_dump_state ( tcp );
- tcp_close ( tcp );
- tcp_xfer_shutdown ( tcp, 0 );
+ tcp_terminate ( tcp, 0 );
}
/**
@@ -930,7 +935,7 @@ static int tcp_rx_fin ( struct tcp_connection *tcp, uint32_t seq ) {
DBGC ( tcp, "TCP %p passive closing.\n", tcp );
}
- /* Close connection */
+ /* Start to close connection */
tcp_close ( tcp );
return 0;
@@ -959,10 +964,7 @@ static int tcp_rx_rst ( struct tcp_connection *tcp, uint32_t seq ) {
}
/* Abort connection */
- tcp->tcp_state = TCP_CLOSED;
- tcp_dump_state ( tcp );
- tcp_close ( tcp );
- tcp_xfer_shutdown ( tcp, -ECONNRESET );
+ tcp_terminate ( tcp, -ECONNRESET );
DBGC ( tcp, "TCP %p connection reset by peer\n", tcp );
return -ECONNRESET;
@@ -1111,10 +1113,7 @@ static int tcp_rx ( struct io_buffer *iobuf,
* Set up timer to expire and cause the connection to be freed.
*/
if ( tcp->tcp_state == TCP_PASV_CLOSED ) {
- tcp->tcp_state = TCP_CLOSED;
- tcp_dump_state ( tcp );
- tcp_close ( tcp );
- tcp_xfer_shutdown ( tcp, 0 );
+ tcp_terminate ( tcp, 0 );
} else if ( TCP_CLOSED_GRACEFULLY ( tcp->tcp_state ) ) {
stop_timer ( &tcp->wait );
start_timer_fixed ( &tcp->wait, ( 2 * TCP_MSL ) );
@@ -1152,10 +1151,13 @@ static void tcp_xfer_close ( struct xfer_interface *xfer, int rc ) {
struct tcp_connection *tcp =
container_of ( xfer, struct tcp_connection, xfer );
- /* Close TCP Connection */
+ /* Start to close TCP Connection */
tcp_close ( tcp );
- /* Shutdown xfer interface */
+ /**
+ * Shutdown xfer interface
+ * Upper layer stopped transmitting data after calling this
+ */
tcp_xfer_shutdown ( tcp, rc );
/* Transmit FIN, if possible */
--
1.7.1
More information about the gPXE-devel
mailing list