Browse Source

Removed some bugs in TCP

tags/v0.9.3
Nikhil Chandru Rao 18 years ago
parent
commit
d2bdf81505
4 changed files with 106 additions and 57 deletions
  1. 2
    1
      src/include/gpxe/ip6.h
  2. 2
    3
      src/include/gpxe/tcp.h
  3. 6
    0
      src/net/ipv4.c
  4. 96
    53
      src/net/tcp.c

+ 2
- 1
src/include/gpxe/ip6.h View File

@@ -11,7 +11,8 @@
11 11
 
12 12
 /* IP6 constants */
13 13
 
14
-#define IP6_VER		6
14
+#define IP6_VERSION	0x6
15
+#define IP6_HOP_LIMIT	64
15 16
 
16 17
 /* IP6 header */
17 18
 

+ 2
- 3
src/include/gpxe/tcp.h View File

@@ -159,7 +159,6 @@ struct tcp_connection {
159 159
 	struct list_head list;		/* List of TCP connections */
160 160
 	struct pk_buff *tx_pkb;		/* Transmit packet buffer */
161 161
 	struct retry_timer timer;	/* Retransmission timer */
162
-	int retransmits;		/* Number of retransmits */
163 162
 	struct tcp_operations *tcp_op;	/* Operations table for connection */
164 163
 };
165 164
 
@@ -198,10 +197,10 @@ struct tcp_header {
198 197
 /**
199 198
  * TCP flags
200 199
  */
201
-#define TCP_RST		0x20
200
+#define TCP_URG		0x20
202 201
 #define TCP_ACK		0x10
203 202
 #define TCP_PSH		0x08
204
-#define TCP_URG		0x04
203
+#define TCP_RST		0x04
205 204
 #define TCP_SYN		0x02
206 205
 #define TCP_FIN		0x01
207 206
 

+ 6
- 0
src/net/ipv4.c View File

@@ -107,6 +107,7 @@ void del_ipv4_address ( struct net_device *netdev ) {
107 107
  */
108 108
 static void ipv4_dump ( struct iphdr *iphdr __unused ) {
109 109
 
110
+/*
110 111
 	DBG ( "IP4 header at %p+%#zx\n", iphdr, sizeof ( *iphdr ) );
111 112
 	DBG ( "\tVersion = %d\n", ( iphdr->verhdrlen & IP_MASK_VER ) / 16 );
112 113
 	DBG ( "\tHeader length = %d\n", iphdr->verhdrlen & IP_MASK_HLEN );
@@ -120,6 +121,11 @@ static void ipv4_dump ( struct iphdr *iphdr __unused ) {
120 121
 				ntohs ( iphdr->chksum ) );
121 122
 	DBG ( "\tSource = %s\n", inet_ntoa ( iphdr->src ) );
122 123
 	DBG ( "\tDestination = %s\n", inet_ntoa ( iphdr->dest ) );
124
+*/
125
+	DBG ( "IP4 %p transmitting %p+%d ident %d protocol %d header-csum %x\n",
126
+		&ipv4_protocol, iphdr, ntohs ( iphdr->len ), ntohs ( iphdr->ident ),
127
+		iphdr->protocol, ntohs ( iphdr->chksum ) );
128
+	DBG ( "src %s, dest %s\n", inet_ntoa ( iphdr->src ), inet_ntoa ( iphdr->dest ) );
123 129
 }
124 130
 
125 131
 /**

+ 96
- 53
src/net/tcp.c View File

@@ -258,17 +258,7 @@ static const char *tcp_states[] = {
258 258
  * @v conn	TCP connection
259 259
  * @v nxt_state Next TCP state
260 260
  */
261
-void tcp_trans ( struct tcp_connection *conn, int nxt_state ) {
262
-	/* Remember the last state */
263
-	conn->tcp_lstate = conn->tcp_state;
264
-	conn->tcp_state = nxt_state;
265
-
266
-	/* TODO: Check if this check is required */
267
-	if ( conn->tcp_lstate == conn->tcp_state || 
268
-	     conn->tcp_state == TCP_INVALID ) {
269
-		conn->tcp_flags = 0;
270
-		return;
271
-	}
261
+void tcp_set_flags ( struct tcp_connection *conn ) {
272 262
 
273 263
 	/* Set the TCP flags */
274 264
 	switch ( conn->tcp_state ) {
@@ -331,12 +321,29 @@ void tcp_trans ( struct tcp_connection *conn, int nxt_state ) {
331 321
 	}
332 322
 }
333 323
 
324
+void tcp_trans ( struct tcp_connection *conn, int nxt_state ) {
325
+	/* Remember the last state */
326
+	conn->tcp_lstate = conn->tcp_state;
327
+	conn->tcp_state = nxt_state;
328
+
329
+	printf ( "Transition from %s to %s\n", tcp_states[conn->tcp_lstate], tcp_states[conn->tcp_state] );
330
+
331
+	/* TODO: Check if this check is required */
332
+	if ( conn->tcp_lstate == conn->tcp_state || 
333
+	     conn->tcp_state == TCP_INVALID ) {
334
+		conn->tcp_flags = 0;
335
+		return;
336
+	}
337
+	tcp_set_flags ( conn );
338
+}
339
+
334 340
 /**
335 341
  * Dump TCP header
336 342
  *
337 343
  * @v tcphdr	TCP header
338 344
  */
339 345
 void tcp_dump ( struct tcp_header *tcphdr ) {
346
+/*
340 347
 	DBG ( "TCP header at %p+%d\n", tcphdr, sizeof ( *tcphdr ) );
341 348
 	DBG ( "\tSource port = %d, Destination port = %d\n",
342 349
 		ntohs ( tcphdr->src ), ntohs ( tcphdr->dest ) );
@@ -347,6 +354,10 @@ void tcp_dump ( struct tcp_header *tcphdr ) {
347 354
 		( tcphdr->flags & TCP_MASK_FLAGS ) );
348 355
 	DBG ( "\tAdvertised window = %ld, Checksum = %x, Urgent Pointer = %d\n",
349 356
 		ntohs ( tcphdr->win ), tcphdr->csum, ntohs ( tcphdr->urg ) );
357
+*/
358
+	DBG ( "TCP %p at %p src:%d dest:%d seq:%lld ack:%lld hlen:%hd flags:%#hx\n",
359
+		&tcp_protocol, tcphdr, ntohs ( tcphdr->src ), ntohs ( tcphdr->dest ), ntohl ( tcphdr->seq ),
360
+		ntohl ( tcphdr->ack ), ( ( tcphdr->hlen & TCP_MASK_HLEN ) / 16 ), ( tcphdr->flags & TCP_MASK_FLAGS ) );
350 361
 }
351 362
 
352 363
 /**
@@ -377,49 +388,64 @@ void tcp_init_conn ( struct tcp_connection *conn ) {
377 388
  */
378 389
 void tcp_expired ( struct retry_timer *timer, int over ) {
379 390
 	struct tcp_connection *conn;
380
-	if ( over ) {
381
-		conn = ( struct tcp_connection * ) container_of ( timer, 
382
-						struct tcp_connection, timer );
383
-		switch ( conn->tcp_state ) {
384
-		case TCP_SYN_SENT:
385
-			if ( conn->retransmits > MAX_RETRANSMITS ) {
386
-				tcp_trans ( conn, TCP_CLOSED );
387
-				return;
388
-			}
389
-			if ( conn->tcp_lstate == TCP_CLOSED ||
390
-			     conn->tcp_lstate == TCP_LISTEN ) {
391
-				goto send_tcp_nomsg;
392
-			}
393
-			return;
394
-		case TCP_SYN_RCVD:
391
+	conn = ( struct tcp_connection * ) container_of ( timer, 
392
+					struct tcp_connection, timer );
393
+	DBG ( "Timer expired in %s\n", tcp_states[conn->tcp_state] );
394
+	switch ( conn->tcp_state ) {
395
+	case TCP_SYN_SENT:
396
+		if ( over ) {
395 397
 			tcp_trans ( conn, TCP_CLOSED );
396
-			if ( conn->tcp_lstate == TCP_LISTEN ||
397
-			     conn->tcp_lstate == TCP_SYN_SENT ) {
398
-				goto send_tcp_nomsg;
399
-			}
400
-			return;
401
-		case TCP_ESTABLISHED:
402
-			break;
403
-		case TCP_FIN_WAIT_1:
404
-		case TCP_FIN_WAIT_2:
405
-		case TCP_CLOSE_WAIT:
406
-			goto send_tcp_nomsg;
407
-		case TCP_CLOSING:
408
-		case TCP_LAST_ACK:
398
+			stop_timer ( &conn->timer );
399
+			DBG ( "Timeout! Connection closed\n" );
409 400
 			return;
410
-		case TCP_TIME_WAIT:
401
+		}
402
+		goto send_tcp_nomsg;
403
+	case TCP_SYN_RCVD:
404
+		if ( over ) {
411 405
 			tcp_trans ( conn, TCP_CLOSED );
412
-			return;
406
+			stop_timer ( &conn->timer );
407
+			goto send_tcp_nomsg;
408
+		}
409
+		goto send_tcp_nomsg;
410
+	case TCP_ESTABLISHED:
411
+		if ( conn->tcp_lstate == TCP_SYN_SENT ) {
412
+			goto send_tcp_nomsg;
413
+		}
414
+		break;
415
+	case TCP_CLOSE_WAIT:
416
+		if ( conn->tcp_lstate == TCP_ESTABLISHED ) {
417
+			goto send_tcp_nomsg;
418
+		}
419
+		break;
420
+	case TCP_FIN_WAIT_1:
421
+	case TCP_FIN_WAIT_2:
422
+		goto send_tcp_nomsg;
423
+	case TCP_CLOSING:
424
+	case TCP_LAST_ACK:
425
+		if ( conn->tcp_lstate == TCP_CLOSE_WAIT ) {
426
+			goto send_tcp_nomsg;
413 427
 		}
414
-		/* Retransmit the data */
415
-		tcp_senddata ( conn );
416
-		conn->retransmits++;
417 428
 		return;
429
+	case TCP_TIME_WAIT:
430
+		tcp_trans ( conn, TCP_CLOSED );
431
+		stop_timer ( &conn->timer );
432
+		return;
433
+	}
434
+	/* Retransmit the data */
435
+	tcp_set_flags ( conn );
436
+	tcp_senddata ( conn );
437
+	return;
418 438
 
419 439
   send_tcp_nomsg:
420
-		tcp_send ( conn, TCP_NOMSG, TCP_NOMSG_LEN );
421
-		return;
440
+//	free_pkb ( conn->tx_pkb );
441
+	conn->tx_pkb = alloc_pkb ( MIN_PKB_LEN );
442
+	pkb_reserve ( conn->tx_pkb, MAX_HDR_LEN );
443
+	tcp_set_flags ( conn );
444
+	int rc;
445
+	if ( ( rc = tcp_send ( conn, TCP_NOMSG, TCP_NOMSG_LEN ) ) != 0 ) {
446
+		DBG ( "Error sending TCP message (rc = %d)\n", rc );
422 447
 	}
448
+	return;
423 449
 }
424 450
 
425 451
 /**
@@ -634,7 +660,13 @@ int tcp_send ( struct tcp_connection *conn, const void *data, size_t len ) {
634 660
 	tcp_dump ( tcphdr );
635 661
 
636 662
 	/* Start the timer */
637
-	start_timer ( &conn->timer );
663
+	if ( ( conn->tcp_state == TCP_ESTABLISHED && conn->tcp_lstate == TCP_SYN_SENT ) ||
664
+	     ( conn->tcp_state == TCP_LISTEN && conn->tcp_lstate == TCP_SYN_RCVD ) ||
665
+	     ( conn->tcp_state == TCP_CLOSED && conn->tcp_lstate == TCP_SYN_RCVD ) ) {
666
+		// Don't start the timer
667
+	} else {
668
+		start_timer ( &conn->timer );
669
+	}
638 670
 
639 671
 	/* Transmit packet */
640 672
 	return tcpip_tx ( pkb, &tcp_protocol, peer );
@@ -653,6 +685,7 @@ static int tcp_rx ( struct pk_buff *pkb,
653 685
 	struct tcp_header *tcphdr;
654 686
 	uint32_t acked, toack;
655 687
 	int hlen;
688
+	int add = 0;
656 689
 
657 690
 	/* Sanity check */
658 691
 	if ( pkb_len ( pkb ) < sizeof ( *tcphdr ) ) {
@@ -660,14 +693,21 @@ static int tcp_rx ( struct pk_buff *pkb,
660 693
 		return -EINVAL;
661 694
 	}
662 695
 
696
+
663 697
 	/* Process TCP header */
664 698
 	tcphdr = pkb->data;
699
+	tcp_dump ( tcphdr );
665 700
 
666 701
 	/* Verify header length */
667 702
 	hlen = ( ( tcphdr->hlen & TCP_MASK_HLEN ) / 16 ) * 4;
668 703
 	if ( hlen != sizeof ( *tcphdr ) ) {
669
-		DBG ( "Bad header length (%d bytes)\n", hlen );
670
-		return -EINVAL;
704
+		if ( hlen == sizeof ( *tcphdr ) + 4 ) {
705
+			DBG ( "TCP options sent\n" );
706
+			add = 4;
707
+		} else {
708
+			DBG ( "Bad header length (%d bytes)\n", hlen );
709
+			return -EINVAL;
710
+		}
671 711
 	}
672 712
 	
673 713
 	/* TODO: Verify checksum */
@@ -685,7 +725,6 @@ static int tcp_rx ( struct pk_buff *pkb,
685 725
   found_conn:
686 726
 	/* Stop the timer */
687 727
 	stop_timer ( &conn->timer );
688
-	conn->retransmits = 0;
689 728
 
690 729
 	/* Set the advertised window */
691 730
 	conn->snd_win = tcphdr->win;
@@ -729,6 +768,7 @@ static int tcp_rx ( struct pk_buff *pkb,
729 768
 				 */
730 769
 				conn->snd_una = ntohl ( tcphdr->ack );
731 770
 				conn->tcp_op->connected ( conn );
771
+				tcp_senddata ( conn );
732 772
 			} else {
733 773
 				tcp_trans ( conn, TCP_SYN_RCVD );
734 774
 				out_flags |= TCP_SYN;
@@ -752,6 +792,7 @@ static int tcp_rx ( struct pk_buff *pkb,
752 792
 			 */
753 793
 			conn->snd_una = tcphdr->ack - 1;
754 794
 			conn->tcp_op->connected ( conn );
795
+			tcp_senddata ( conn );
755 796
 			return 0;
756 797
 		}
757 798
 		/* Unexpected packet */
@@ -799,6 +840,7 @@ static int tcp_rx ( struct pk_buff *pkb,
799 840
 	case TCP_CLOSING:
800 841
 		if ( tcphdr->flags & TCP_ACK ) {
801 842
 			tcp_trans ( conn, TCP_TIME_WAIT );
843
+			start_timer ( &conn->timer );
802 844
 			return 0;
803 845
 		}
804 846
 		/* Unexpected packet */
@@ -831,7 +873,7 @@ static int tcp_rx ( struct pk_buff *pkb,
831 873
 		/* Check if expected sequence number */
832 874
 		if ( conn->rcv_nxt == ntohl ( tcphdr->seq ) ) {
833 875
 			conn->rcv_nxt += toack;
834
-			conn->tcp_op->newdata ( conn, pkb->data + sizeof ( *tcphdr ), toack );
876
+			conn->tcp_op->newdata ( conn, pkb->data + sizeof ( *tcphdr ) + add, toack );
835 877
 		}
836 878
 
837 879
 		/* Acknowledge new data */
@@ -870,8 +912,9 @@ static int tcp_rx ( struct pk_buff *pkb,
870 912
 	return 0;
871 913
 
872 914
   unexpected:
873
-	DBG ( "Unexpected packet received in %d state with flags = %hd\n",
874
-			conn->tcp_state, tcphdr->flags & TCP_MASK_FLAGS );
915
+	DBG ( "Unexpected packet received in %s with flags = %#hx\n",
916
+			tcp_states[conn->tcp_state], tcphdr->flags & TCP_MASK_FLAGS );
917
+	tcp_close ( conn );
875 918
 	free_pkb ( conn->tx_pkb );
876 919
 	return -EINVAL;
877 920
 }

Loading…
Cancel
Save