|
@@ -16,6 +16,7 @@
|
16
|
16
|
#include <ipxe/uri.h>
|
17
|
17
|
#include <ipxe/netdevice.h>
|
18
|
18
|
#include <ipxe/profile.h>
|
|
19
|
+#include <ipxe/process.h>
|
19
|
20
|
#include <ipxe/tcpip.h>
|
20
|
21
|
#include <ipxe/tcp.h>
|
21
|
22
|
|
|
@@ -107,6 +108,8 @@ struct tcp_connection {
|
107
|
108
|
struct list_head tx_queue;
|
108
|
109
|
/** Receive queue */
|
109
|
110
|
struct list_head rx_queue;
|
|
111
|
+ /** Transmission process */
|
|
112
|
+ struct process process;
|
110
|
113
|
/** Retransmission timer */
|
111
|
114
|
struct retry_timer timer;
|
112
|
115
|
/** Shutdown (TIME_WAIT) timer */
|
|
@@ -166,6 +169,7 @@ static struct profiler tcp_rx_profiler __profiler = { .name = "tcp.rx" };
|
166
|
169
|
static struct profiler tcp_xfer_profiler __profiler = { .name = "tcp.xfer" };
|
167
|
170
|
|
168
|
171
|
/* Forward declarations */
|
|
172
|
+static struct process_descriptor tcp_process_desc;
|
169
|
173
|
static struct interface_descriptor tcp_xfer_desc;
|
170
|
174
|
static void tcp_expired ( struct retry_timer *timer, int over );
|
171
|
175
|
static void tcp_wait_expired ( struct retry_timer *timer, int over );
|
|
@@ -273,6 +277,7 @@ static int tcp_open ( struct interface *xfer, struct sockaddr *peer,
|
273
|
277
|
DBGC ( tcp, "TCP %p allocated\n", tcp );
|
274
|
278
|
ref_init ( &tcp->refcnt, NULL );
|
275
|
279
|
intf_init ( &tcp->xfer, &tcp_xfer_desc, &tcp->refcnt );
|
|
280
|
+ process_init_stopped ( &tcp->process, &tcp_process_desc, &tcp->refcnt );
|
276
|
281
|
timer_init ( &tcp->timer, tcp_expired, &tcp->refcnt );
|
277
|
282
|
timer_init ( &tcp->wait, tcp_wait_expired, &tcp->refcnt );
|
278
|
283
|
tcp->prev_tcp_state = TCP_CLOSED;
|
|
@@ -369,6 +374,7 @@ static void tcp_close ( struct tcp_connection *tcp, int rc ) {
|
369
|
374
|
pending_put ( &tcp->pending_flags );
|
370
|
375
|
|
371
|
376
|
/* Remove from list and drop reference */
|
|
377
|
+ process_del ( &tcp->process );
|
372
|
378
|
stop_timer ( &tcp->timer );
|
373
|
379
|
stop_timer ( &tcp->wait );
|
374
|
380
|
list_del ( &tcp->list );
|
|
@@ -497,7 +503,7 @@ static size_t tcp_process_tx_queue ( struct tcp_connection *tcp, size_t max_len,
|
497
|
503
|
* will have been started if necessary, and so the stack will
|
498
|
504
|
* eventually attempt to retransmit the failed packet.
|
499
|
505
|
*/
|
500
|
|
-static int tcp_xmit ( struct tcp_connection *tcp ) {
|
|
506
|
+static void tcp_xmit ( struct tcp_connection *tcp ) {
|
501
|
507
|
struct io_buffer *iobuf;
|
502
|
508
|
struct tcp_header *tcphdr;
|
503
|
509
|
struct tcp_mss_option *mssopt;
|
|
@@ -517,7 +523,7 @@ static int tcp_xmit ( struct tcp_connection *tcp ) {
|
517
|
523
|
|
518
|
524
|
/* If retransmission timer is already running, do nothing */
|
519
|
525
|
if ( timer_running ( &tcp->timer ) )
|
520
|
|
- return 0;
|
|
526
|
+ return;
|
521
|
527
|
|
522
|
528
|
/* Calculate both the actual (payload) and sequence space
|
523
|
529
|
* lengths that we wish to transmit.
|
|
@@ -537,7 +543,7 @@ static int tcp_xmit ( struct tcp_connection *tcp ) {
|
537
|
543
|
|
538
|
544
|
/* If we have nothing to transmit, stop now */
|
539
|
545
|
if ( ( seq_len == 0 ) && ! ( tcp->flags & TCP_ACK_PENDING ) )
|
540
|
|
- return 0;
|
|
546
|
+ return;
|
541
|
547
|
|
542
|
548
|
/* If we are transmitting anything that requires
|
543
|
549
|
* acknowledgement (i.e. consumes sequence space), start the
|
|
@@ -553,7 +559,7 @@ static int tcp_xmit ( struct tcp_connection *tcp ) {
|
553
|
559
|
DBGC ( tcp, "TCP %p could not allocate iobuf for %08x..%08x "
|
554
|
560
|
"%08x\n", tcp, tcp->snd_seq, ( tcp->snd_seq + seq_len ),
|
555
|
561
|
tcp->rcv_ack );
|
556
|
|
- return -ENOMEM;
|
|
562
|
+ return;
|
557
|
563
|
}
|
558
|
564
|
iob_reserve ( iobuf, TCP_MAX_HEADER_LEN );
|
559
|
565
|
|
|
@@ -620,16 +626,19 @@ static int tcp_xmit ( struct tcp_connection *tcp ) {
|
620
|
626
|
DBGC ( tcp, "TCP %p could not transmit %08x..%08x %08x: %s\n",
|
621
|
627
|
tcp, tcp->snd_seq, ( tcp->snd_seq + tcp->snd_sent ),
|
622
|
628
|
tcp->rcv_ack, strerror ( rc ) );
|
623
|
|
- return rc;
|
|
629
|
+ return;
|
624
|
630
|
}
|
625
|
631
|
|
626
|
632
|
/* Clear ACK-pending flag */
|
627
|
633
|
tcp->flags &= ~TCP_ACK_PENDING;
|
628
|
634
|
|
629
|
635
|
profile_stop ( &tcp_tx_profiler );
|
630
|
|
- return 0;
|
631
|
636
|
}
|
632
|
637
|
|
|
638
|
+/** TCP process descriptor */
|
|
639
|
+static struct process_descriptor tcp_process_desc =
|
|
640
|
+ PROC_DESC_ONCE ( struct tcp_connection, process, tcp_xmit );
|
|
641
|
+
|
633
|
642
|
/**
|
634
|
643
|
* Retransmission timer expired
|
635
|
644
|
*
|
|
@@ -1272,8 +1281,16 @@ static int tcp_rx ( struct io_buffer *iobuf,
|
1272
|
1281
|
/* Dump out any state change as a result of the received packet */
|
1273
|
1282
|
tcp_dump_state ( tcp );
|
1274
|
1283
|
|
1275
|
|
- /* Send out any pending data */
|
1276
|
|
- tcp_xmit ( tcp );
|
|
1284
|
+ /* Schedule transmission of ACK (and any pending data). If we
|
|
1285
|
+ * have received any out-of-order packets (i.e. if the receive
|
|
1286
|
+ * queue remains non-empty after processing) then send the ACK
|
|
1287
|
+ * immediately in order to trigger Fast Retransmission.
|
|
1288
|
+ */
|
|
1289
|
+ if ( list_empty ( &tcp->rx_queue ) ) {
|
|
1290
|
+ process_add ( &tcp->process );
|
|
1291
|
+ } else {
|
|
1292
|
+ tcp_xmit ( tcp );
|
|
1293
|
+ }
|
1277
|
1294
|
|
1278
|
1295
|
/* If this packet was the last we expect to receive, set up
|
1279
|
1296
|
* timer to expire and cause the connection to be freed.
|