|
@@ -11,6 +11,7 @@
|
11
|
11
|
#include <gpxe/ip.h>
|
12
|
12
|
#include <gpxe/tcp.h>
|
13
|
13
|
#include <gpxe/tcpip.h>
|
|
14
|
+#include <gpxe/retry.h>
|
14
|
15
|
#include "uip/uip.h"
|
15
|
16
|
|
16
|
17
|
/** @file
|
|
@@ -369,6 +370,58 @@ void tcp_init_conn ( struct tcp_connection *conn ) {
|
369
|
370
|
conn->tcp_op = NULL;
|
370
|
371
|
}
|
371
|
372
|
|
|
373
|
+/** Retry timer
|
|
374
|
+ *
|
|
375
|
+ * @v timer Retry timer
|
|
376
|
+ * @v over Failure indicator
|
|
377
|
+ */
|
|
378
|
+void tcp_expired ( struct retry_timer *timer, int over ) {
|
|
379
|
+ 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:
|
|
395
|
+ 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:
|
|
409
|
+ return;
|
|
410
|
+ case TCP_TIME_WAIT:
|
|
411
|
+ tcp_trans ( conn, TCP_CLOSED );
|
|
412
|
+ return;
|
|
413
|
+ }
|
|
414
|
+ /* Retransmit the data */
|
|
415
|
+ tcp_senddata ( conn );
|
|
416
|
+ conn->retransmits++;
|
|
417
|
+ return;
|
|
418
|
+
|
|
419
|
+ send_tcp_nomsg:
|
|
420
|
+ tcp_send ( conn, TCP_NOMSG, TCP_NOMSG_LEN );
|
|
421
|
+ return;
|
|
422
|
+ }
|
|
423
|
+}
|
|
424
|
+
|
372
|
425
|
/**
|
373
|
426
|
* Connect to a remote server
|
374
|
427
|
*
|
|
@@ -396,6 +449,9 @@ int tcp_connectto ( struct tcp_connection *conn,
|
396
|
449
|
}
|
397
|
450
|
memcpy ( &conn->peer, peer, sizeof ( conn->peer ) );
|
398
|
451
|
|
|
452
|
+ /* Initialize the TCP timer */
|
|
453
|
+ conn->timer.expired = tcp_expired;
|
|
454
|
+
|
399
|
455
|
/* Send a SYN packet and transition to TCP_SYN_SENT */
|
400
|
456
|
conn->snd_una = ( ( ( uint32_t ) random() ) << 16 ) & random();
|
401
|
457
|
tcp_trans ( conn, TCP_SYN_SENT );
|
|
@@ -577,6 +633,9 @@ int tcp_send ( struct tcp_connection *conn, const void *data, size_t len ) {
|
577
|
633
|
/* Dump the TCP header */
|
578
|
634
|
tcp_dump ( tcphdr );
|
579
|
635
|
|
|
636
|
+ /* Start the timer */
|
|
637
|
+ start_timer ( &conn->timer );
|
|
638
|
+
|
580
|
639
|
/* Transmit packet */
|
581
|
640
|
return tcpip_tx ( pkb, &tcp_protocol, peer );
|
582
|
641
|
}
|
|
@@ -624,6 +683,10 @@ static int tcp_rx ( struct pk_buff *pkb,
|
624
|
683
|
return 0;
|
625
|
684
|
|
626
|
685
|
found_conn:
|
|
686
|
+ /* Stop the timer */
|
|
687
|
+ stop_timer ( &conn->timer );
|
|
688
|
+ conn->retransmits = 0;
|
|
689
|
+
|
627
|
690
|
/* Set the advertised window */
|
628
|
691
|
conn->snd_win = tcphdr->win;
|
629
|
692
|
|