[gPXE-devel] [PATCH 4/6] [tcp] Waiting for TCP to fully close

cooldavid at cooldavid.org cooldavid at cooldavid.org
Tue Jul 13 11:15:42 EDT 2010


From: Guo-Fu Tseng <cooldavid at cooldavid.org>

While using scripts, if the downloaded image is not bootable, the gPXE
exits faster than it have the opportunity to gracefully closing the TCP
connection. Which might lead the TCP state of remote server not closed.

This commit waits for TCP to fully close by polling remaining ACKs from
remote server and let the gPXE reply the correct response before
shutdown the xfer interface.

It is somehow hacky, hoping we can find better solution.

Signed-off-by: Guo-Fu Tseng <cooldavid at cooldavid.org>
---
 src/include/gpxe/netdevice.h |    1 +
 src/net/netdevice.c          |    9 +++++++++
 src/net/tcp.c                |    9 +++++++++
 3 files changed, 19 insertions(+), 0 deletions(-)

diff --git a/src/include/gpxe/netdevice.h b/src/include/gpxe/netdevice.h
index 97bf168..f5227df 100644
--- a/src/include/gpxe/netdevice.h
+++ b/src/include/gpxe/netdevice.h
@@ -529,6 +529,7 @@ extern int net_tx ( struct io_buffer *iobuf, struct net_device *netdev,
 		    struct net_protocol *net_protocol, const void *ll_dest );
 extern int net_rx ( struct io_buffer *iobuf, struct net_device *netdev,
 		    uint16_t net_proto, const void *ll_source );
+extern void net_poll ( void );
 
 /**
  * Complete network transmission
diff --git a/src/net/netdevice.c b/src/net/netdevice.c
index 00b4478..f08c326 100644
--- a/src/net/netdevice.c
+++ b/src/net/netdevice.c
@@ -631,6 +631,15 @@ static void net_step ( struct process *process __unused ) {
 	}
 }
 
+/**
+ * Single-step the network stack
+ *
+ * This is the extern wrapper for upper-layer to explicitly poll RX packets.
+ */
+void net_poll ( void ) {
+	net_step ( NULL );
+}
+
 /** Networking stack process */
 struct process net_process __permanent_process = {
 	.list = LIST_HEAD_INIT ( net_process.list ),
diff --git a/src/net/tcp.c b/src/net/tcp.c
index 9241572..22f3936 100644
--- a/src/net/tcp.c
+++ b/src/net/tcp.c
@@ -14,6 +14,7 @@
 #include <gpxe/uri.h>
 #include <gpxe/tcpip.h>
 #include <gpxe/tcp.h>
+#include <gpxe/netdevice.h>
 
 /** @file
  *
@@ -1084,6 +1085,7 @@ struct tcpip_protocol tcp_protocol __tcpip_protocol = {
 static void tcp_xfer_close ( struct xfer_interface *xfer, int rc ) {
 	struct tcp_connection *tcp =
 		container_of ( xfer, struct tcp_connection, xfer );
+	unsigned int max_wait_ticks;
 
 	/* Close TCP Connection */
 	tcp_close ( tcp );
@@ -1093,6 +1095,13 @@ static void tcp_xfer_close ( struct xfer_interface *xfer, int rc ) {
 
 	/* Transmit FIN, if possible */
 	tcp_xmit ( tcp, 0 );
+
+	/* polling incoming packet until TCP are safe to leave */
+	max_wait_ticks = currticks() + 50;
+	while ( tcp->tcp_state != TCP_CLOSED &&
+		tcp->tcp_state != TCP_TIME_WAIT &&
+		currticks() < max_wait_ticks )
+		net_poll();
 }
 
 /**
-- 
1.7.1



More information about the gPXE-devel mailing list