From: Guo-Fu Tseng <[email protected]>

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 <[email protected]>
---
 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

_______________________________________________
gPXE-devel mailing list
[email protected]
http://etherboot.org/mailman/listinfo/gpxe-devel

Reply via email to