Browse Source

Redefine TCP state to include "flags that have been sent" rather than

"flags that are currently being sent".  This allows at least one special
case (checking that we haven't already sent a FIN in tcp_rx_fin()) to be
collapsed.
tags/v0.9.3
Michael Brown 18 years ago
parent
commit
ce9819af27
2 changed files with 46 additions and 47 deletions
  1. 31
    28
      src/include/gpxe/tcp.h
  2. 15
    19
      src/net/tcp.c

+ 31
- 28
src/include/gpxe/tcp.h View File

@@ -42,17 +42,16 @@ struct tcp_header {
42 42
 /**
43 43
 * @defgroup tcpstates TCP states
44 44
 *
45
-* The TCP state is defined by a combination of the flags that are
46
-* currently being sent in outgoing packets, the flags that have been
47
-* sent and acknowledged by the peer, and the flags that have been
48
-* received from the peer.
45
+* The TCP state is defined by a combination of the flags that have
46
+* been sent to the peer, the flags that have been acknowledged by the
47
+* peer, and the flags that have been received from the peer.
49 48
 *
50 49
 * @{
51 50
 */
52 51
 
53
-/** TCP flags that are currently being sent in outgoing packets */
54
-#define TCP_STATE_SENDING(flags) ( (flags) << 0 )
55
-#define TCP_FLAGS_SENDING(state) ( ( (state) >> 0 ) & 0xff )
52
+/** TCP flags that have been sent in outgoing packets */
53
+#define TCP_STATE_SENT(flags) ( (flags) << 0 )
54
+#define TCP_FLAGS_SENT(state) ( ( (state) >> 0 ) & 0xff )
56 55
 
57 56
 /** TCP flags that have been acknowledged by the peer
58 57
  *
@@ -69,6 +68,10 @@ struct tcp_header {
69 68
 #define TCP_STATE_RCVD(flags) ( (flags) << 12 )
70 69
 #define TCP_FLAGS_RCVD(state) ( ( (state) >> 12 ) & 0x03 )
71 70
 
71
+/** TCP flags that are currently being sent in outgoing packets */
72
+#define TCP_FLAGS_SENDING(state) \
73
+	( TCP_FLAGS_SENT ( state ) & ~TCP_FLAGS_ACKED ( state ) )
74
+
72 75
 /** CLOSED
73 76
  *
74 77
  * The connection has not yet been used for anything.
@@ -86,21 +89,21 @@ struct tcp_header {
86 89
  *
87 90
  * SYN has been sent, nothing has yet been received or acknowledged.
88 91
  */
89
-#define TCP_SYN_SENT	( TCP_STATE_SENDING ( TCP_SYN ) )
92
+#define TCP_SYN_SENT	( TCP_STATE_SENT ( TCP_SYN ) )
90 93
 
91 94
 /** SYN_RCVD
92 95
  *
93 96
  * SYN has been sent but not acknowledged, SYN has been received.
94 97
  */
95
-#define TCP_SYN_RCVD	( TCP_STATE_SENDING ( TCP_SYN | TCP_ACK ) |	\
98
+#define TCP_SYN_RCVD	( TCP_STATE_SENT ( TCP_SYN | TCP_ACK ) |	    \
96 99
 			  TCP_STATE_RCVD ( TCP_SYN ) )
97 100
 
98 101
 /** ESTABLISHED
99 102
  *
100 103
  * SYN has been sent and acknowledged, SYN has been received.
101 104
  */
102
-#define TCP_ESTABLISHED	( TCP_STATE_SENDING ( TCP_ACK ) |		\
103
-			  TCP_STATE_ACKED ( TCP_SYN ) |			\
105
+#define TCP_ESTABLISHED	( TCP_STATE_SENT ( TCP_SYN | TCP_ACK ) |	    \
106
+			  TCP_STATE_ACKED ( TCP_SYN ) |			    \
104 107
 			  TCP_STATE_RCVD ( TCP_SYN ) )
105 108
 
106 109
 /** FIN_WAIT_1
@@ -117,8 +120,8 @@ struct tcp_header {
117 120
  * to FIN_WAIT_1, we have to remember to set TCP_STATE_ACKED(TCP_SYN)
118 121
  * and increment our sequence number.
119 122
  */
120
-#define TCP_FIN_WAIT_1	( TCP_STATE_SENDING ( TCP_ACK | TCP_FIN ) |	\
121
-			  TCP_STATE_ACKED ( TCP_SYN ) |			\
123
+#define TCP_FIN_WAIT_1	( TCP_STATE_SENT ( TCP_SYN | TCP_ACK | TCP_FIN ) |  \
124
+			  TCP_STATE_ACKED ( TCP_SYN ) |			    \
122 125
 			  TCP_STATE_RCVD ( TCP_SYN ) )
123 126
 
124 127
 /** FIN_WAIT_2
@@ -126,8 +129,8 @@ struct tcp_header {
126 129
  * SYN has been sent and acknowledged, SYN has been received, FIN has
127 130
  * been sent and acknowledged, FIN ha not been received.
128 131
  */
129
-#define TCP_FIN_WAIT_2	( TCP_STATE_SENDING ( TCP_ACK ) |		\
130
-			  TCP_STATE_ACKED ( TCP_SYN | TCP_FIN ) |	\
132
+#define TCP_FIN_WAIT_2	( TCP_STATE_SENT ( TCP_SYN | TCP_ACK | TCP_FIN ) |  \
133
+			  TCP_STATE_ACKED ( TCP_SYN | TCP_FIN ) |	    \
131 134
 			  TCP_STATE_RCVD ( TCP_SYN ) )
132 135
 
133 136
 /** CLOSING / LAST_ACK
@@ -139,9 +142,9 @@ struct tcp_header {
139 142
  * identical with the definition of state that we use.  I don't
140 143
  * *believe* that they need to be distinguished.
141 144
  */
142
-#define TCP_CLOSING_OR_LAST_ACK					\
143
-			( TCP_STATE_SENDING ( TCP_ACK | TCP_FIN ) |	\
144
-			  TCP_STATE_ACKED ( TCP_SYN ) |			\
145
+#define TCP_CLOSING_OR_LAST_ACK						    \
146
+			( TCP_STATE_SENT ( TCP_SYN | TCP_ACK | TCP_FIN ) |  \
147
+			  TCP_STATE_ACKED ( TCP_SYN ) |			    \
145 148
 			  TCP_STATE_RCVD ( TCP_SYN | TCP_FIN ) )
146 149
 
147 150
 /** TIME_WAIT
@@ -149,8 +152,8 @@ struct tcp_header {
149 152
  * SYN has been sent and acknowledged, SYN has been received, FIN has
150 153
  * been sent and acknowledged, FIN has been received.
151 154
  */
152
-#define TCP_TIME_WAIT	( TCP_STATE_SENDING ( TCP_ACK ) |		\
153
-			  TCP_STATE_ACKED ( TCP_SYN | TCP_FIN ) |	\
155
+#define TCP_TIME_WAIT	( TCP_STATE_SENT ( TCP_SYN | TCP_ACK | TCP_FIN ) |  \
156
+			  TCP_STATE_ACKED ( TCP_SYN | TCP_FIN ) |	    \
154 157
 			  TCP_STATE_RCVD ( TCP_SYN | TCP_FIN ) )
155 158
 
156 159
 /** CLOSE_WAIT
@@ -158,8 +161,8 @@ struct tcp_header {
158 161
  * SYN has been sent and acknowledged, SYN has been received, FIN has
159 162
  * been received.
160 163
  */
161
-#define TCP_CLOSE_WAIT	( TCP_STATE_SENDING ( TCP_ACK ) |		\
162
-			  TCP_STATE_ACKED ( TCP_SYN ) |			\
164
+#define TCP_CLOSE_WAIT	( TCP_STATE_SENT ( TCP_SYN | TCP_ACK ) |	    \
165
+			  TCP_STATE_ACKED ( TCP_SYN ) |			    \
163 166
 			  TCP_STATE_RCVD ( TCP_SYN | TCP_FIN ) )
164 167
 
165 168
 /** Can send data in current state
@@ -167,9 +170,9 @@ struct tcp_header {
167 170
  * We can send data if and only if we have had our SYN acked and we
168 171
  * have not yet sent our FIN.
169 172
  */
170
-#define TCP_CAN_SEND_DATA(state)					\
171
-	( ( (state) & ( TCP_STATE_ACKED ( TCP_SYN | TCP_FIN ) |		\
172
-		      TCP_STATE_SENDING ( TCP_FIN ) ) )			\
173
+#define TCP_CAN_SEND_DATA(state)					    \
174
+	( ( (state) & ( TCP_STATE_ACKED ( TCP_SYN ) |			    \
175
+			TCP_STATE_SENT ( TCP_FIN ) ) )			    \
173 176
 	  == TCP_STATE_ACKED ( TCP_SYN ) )
174 177
 
175 178
 /** Have closed gracefully
@@ -177,9 +180,9 @@ struct tcp_header {
177 180
  * We have closed gracefully if we have both received a FIN and had
178 181
  * our own FIN acked.
179 182
  */
180
-#define TCP_CLOSED_GRACEFULLY(state)					\
181
-	( ( (state) & ( TCP_STATE_ACKED ( TCP_FIN ) |			\
182
-			TCP_STATE_RCVD ( TCP_FIN ) ) )			\
183
+#define TCP_CLOSED_GRACEFULLY(state)					    \
184
+	( ( (state) & ( TCP_STATE_ACKED ( TCP_FIN ) |			    \
185
+			TCP_STATE_RCVD ( TCP_FIN ) ) )			    \
183 186
 	  == ( TCP_STATE_ACKED ( TCP_FIN ) | TCP_STATE_RCVD ( TCP_FIN ) ) )
184 187
 
185 188
 /** @} */

+ 15
- 19
src/net/tcp.c View File

@@ -229,6 +229,7 @@ static int tcp_senddata_conn ( struct tcp_connection *conn, int force_send ) {
229 229
 	struct tcp_application *app = conn->app;
230 230
 	struct pk_buff *pkb;
231 231
 	struct tcp_header *tcphdr;
232
+	unsigned int flags;
232 233
 	size_t len;
233 234
 	size_t seq_len;
234 235
 
@@ -264,9 +265,9 @@ static int tcp_senddata_conn ( struct tcp_connection *conn, int force_send ) {
264 265
 	 */
265 266
 	len = pkb_len ( pkb );
266 267
 	seq_len = len;
267
-	assert ( ! ( ( conn->tcp_state & TCP_STATE_SENDING ( TCP_SYN ) ) &&
268
-		     ( conn->tcp_state & TCP_STATE_SENDING ( TCP_FIN ) ) ) );
269
-	if ( conn->tcp_state & TCP_STATE_SENDING ( TCP_SYN | TCP_FIN ) )
268
+	flags = TCP_FLAGS_SENDING ( conn->tcp_state );
269
+	assert ( ! ( ( flags & TCP_SYN ) && ( flags & TCP_FIN ) ) );
270
+	if ( flags & ( TCP_SYN | TCP_FIN ) )
270 271
 		seq_len++;
271 272
 	conn->snd_sent = seq_len;
272 273
 
@@ -291,7 +292,7 @@ static int tcp_senddata_conn ( struct tcp_connection *conn, int force_send ) {
291 292
 	tcphdr->seq = htonl ( conn->snd_seq );
292 293
 	tcphdr->ack = htonl ( conn->rcv_ack );
293 294
 	tcphdr->hlen = ( ( sizeof ( *tcphdr ) / 4 ) << 4 );
294
-	tcphdr->flags = TCP_FLAGS_SENDING ( conn->tcp_state );
295
+	tcphdr->flags = flags;
295 296
 	tcphdr->win = htons ( TCP_WINDOW_SIZE );
296 297
 	tcphdr->csum = tcpip_chksum ( pkb->data, pkb_len ( pkb ) );
297 298
 
@@ -458,7 +459,7 @@ static int tcp_rx_syn ( struct tcp_connection *conn, uint32_t seq ) {
458 459
 		return 0;
459 460
 
460 461
 	/* Mark SYN as received and start sending ACKs with each packet */
461
-	conn->tcp_state |= ( TCP_STATE_SENDING ( TCP_ACK ) |
462
+	conn->tcp_state |= ( TCP_STATE_SENT ( TCP_ACK ) |
462 463
 			     TCP_STATE_RCVD ( TCP_SYN ) );
463 464
 
464 465
 	/* Acknowledge SYN */
@@ -517,10 +518,8 @@ static int tcp_rx_ack ( struct tcp_connection *conn, uint32_t ack,
517 518
 		app->tcp_op->acked ( app, len );
518 519
 
519 520
 	/* Mark SYN/FIN as acknowledged if applicable. */
520
-	if ( acked_flags ) {
521
-		conn->tcp_state &= ~TCP_STATE_SENDING ( TCP_SYN | TCP_FIN );
521
+	if ( acked_flags )
522 522
 		conn->tcp_state |= TCP_STATE_ACKED ( acked_flags );
523
-	}
524 523
 
525 524
 	/* Notify application of established connection, if applicable */
526 525
 	if ( ( acked_flags & TCP_SYN ) && app && app->tcp_op->connected )
@@ -573,14 +572,11 @@ static int tcp_rx_fin ( struct tcp_connection *conn, uint32_t seq ) {
573 572
 	if ( ( conn->rcv_ack - seq ) > 0 )
574 573
 		return 0;
575 574
 
576
-	/* Mark FIN as received and acknowledge it */
577
-	conn->tcp_state |= TCP_STATE_RCVD ( TCP_FIN );
575
+	/* Mark FIN as received, acknowledge it, and send our own FIN */
576
+	conn->tcp_state |= ( TCP_STATE_RCVD ( TCP_FIN ) |
577
+			     TCP_STATE_SENT ( TCP_FIN ) );
578 578
 	conn->rcv_ack++;
579 579
 
580
-	/* If we haven't already sent our FIN, send a FIN */
581
-	if ( ! ( conn->tcp_state & TCP_STATE_ACKED ( TCP_FIN ) ) )
582
-		conn->tcp_state |= TCP_STATE_SENDING ( TCP_FIN );
583
-
584 580
 	/* Break association with application */
585 581
 	tcp_disassociate ( conn );
586 582
 
@@ -832,15 +828,15 @@ void tcp_close ( struct tcp_application *app ) {
832 828
 		return;
833 829
 	}
834 830
 
835
-	/* If we have sent a SYN but not had it acknowledged (i.e. we
836
-	 * are in SYN_RCVD), pretend that it has been acknowledged so
837
-	 * that we can send a FIN without breaking things.
831
+	/* If we have not had our SYN acknowledged (i.e. we are in
832
+	 * SYN_RCVD), pretend that it has been acknowledged so that we
833
+	 * can send a FIN without breaking things.
838 834
 	 */
839
-	if ( conn->tcp_state & TCP_STATE_SENDING ( TCP_SYN ) )
835
+	if ( ! ( conn->tcp_state & TCP_STATE_ACKED ( TCP_SYN ) ) )
840 836
 		tcp_rx_ack ( conn, ( conn->snd_seq + 1 ), 0 );
841 837
 
842 838
 	/* Send a FIN to initiate the close */
843
-	conn->tcp_state |= TCP_STATE_SENDING ( TCP_FIN );
839
+	conn->tcp_state |= TCP_STATE_SENT ( TCP_FIN );
844 840
 	tcp_dump_state ( conn );
845 841
 	tcp_senddata_conn ( conn, 0 );
846 842
 }

Loading…
Cancel
Save