TianoCore EDK2 master
Loading...
Searching...
No Matches
TcpOutput.c
Go to the documentation of this file.
1
10#include "TcpMain.h"
11
12UINT8 mTcpOutFlag[] = {
13 0, // TCP_CLOSED
14 0, // TCP_LISTEN
15 TCP_FLG_SYN, // TCP_SYN_SENT
16 TCP_FLG_SYN | TCP_FLG_ACK, // TCP_SYN_RCVD
17 TCP_FLG_ACK, // TCP_ESTABLISHED
18 TCP_FLG_FIN | TCP_FLG_ACK, // TCP_FIN_WAIT_1
19 TCP_FLG_ACK, // TCP_FIN_WAIT_2
20 TCP_FLG_ACK | TCP_FLG_FIN, // TCP_CLOSING
21 TCP_FLG_ACK, // TCP_TIME_WAIT
22 TCP_FLG_ACK, // TCP_CLOSE_WAIT
23 TCP_FLG_FIN | TCP_FLG_ACK // TCP_LAST_ACK
24};
25
34UINT32
36 IN TCP_CB *Tcb
37 )
38{
39 UINT32 OldWin;
40
41 OldWin = 0;
42
43 if (TCP_SEQ_GT (Tcb->RcvWl2 + Tcb->RcvWnd, Tcb->RcvNxt)) {
44 OldWin = TCP_SUB_SEQ (
45 Tcb->RcvWl2 + Tcb->RcvWnd,
46 Tcb->RcvNxt
47 );
48 }
49
50 return OldWin;
51}
52
61UINT32
63 IN TCP_CB *Tcb
64 )
65{
66 SOCKET *Sk;
67 UINT32 Win;
68 UINT32 Increase;
69 UINT32 OldWin;
70
71 Sk = Tcb->Sk;
72 ASSERT (Sk != NULL);
73
74 OldWin = TcpRcvWinOld (Tcb);
75
76 Win = SockGetFreeSpace (Sk, SOCK_RCV_BUF);
77
78 Increase = 0;
79 if (Win > OldWin) {
80 Increase = Win - OldWin;
81 }
82
83 //
84 // Receiver's SWS: don't advertise a bigger window
85 // unless it can be increased by at least one Mss or
86 // half of the receive buffer.
87 //
88 if ((Increase > Tcb->SndMss) || (2 * Increase >= GET_RCV_BUFFSIZE (Sk))) {
89 return Win;
90 }
91
92 return OldWin;
93}
94
105UINT16
107 IN OUT TCP_CB *Tcb,
108 IN BOOLEAN Syn
109 )
110{
111 UINT32 Wnd;
112
113 //
114 // RFC requires that initial window not be scaled
115 //
116 if (Syn) {
117 Wnd = GET_RCV_BUFFSIZE (Tcb->Sk);
118 } else {
119 Wnd = TcpRcvWinNow (Tcb);
120
121 Tcb->RcvWnd = Wnd;
122 }
123
124 Wnd = MIN (Wnd >> Tcb->RcvWndScale, 0xffff);
125 return NTOHS ((UINT16)Wnd);
126}
127
136TCP_SEQNO
138 IN TCP_CB *Tcb
139 )
140{
141 LIST_ENTRY *Entry;
142 NET_BUF *Nbuf;
143
144 if (IsListEmpty (&Tcb->SndQue)) {
145 return Tcb->SndNxt;
146 }
147
148 Entry = Tcb->SndQue.BackLink;
149 Nbuf = NET_LIST_USER_STRUCT (Entry, NET_BUF, List);
150
151 ASSERT (TCP_SEQ_GEQ (TCPSEG_NETBUF (Nbuf)->End, Tcb->SndNxt));
152 return TCPSEG_NETBUF (Nbuf)->End;
153}
154
165UINT32
167 IN TCP_CB *Tcb,
168 IN INTN Force
169 )
170{
171 SOCKET *Sk;
172 UINT32 Win;
173 UINT32 Len;
174 UINT32 Left;
175 UINT32 Limit;
176
177 Sk = Tcb->Sk;
178 ASSERT (Sk != NULL);
179
180 //
181 // TCP should NOT send data beyond the send window
182 // and congestion window. The right edge of send
183 // window is defined as SND.WL2 + SND.WND. The right
184 // edge of congestion window is defined as SND.UNA +
185 // CWND.
186 //
187 Win = 0;
188 Limit = Tcb->SndWl2 + Tcb->SndWnd;
189
190 if (TCP_SEQ_GT (Limit, Tcb->SndUna + Tcb->CWnd)) {
191 Limit = Tcb->SndUna + Tcb->CWnd;
192 }
193
194 if (TCP_SEQ_GT (Limit, Tcb->SndNxt)) {
195 Win = TCP_SUB_SEQ (Limit, Tcb->SndNxt);
196 }
197
198 //
199 // The data to send contains two parts: the data on the
200 // socket send queue, and the data on the TCB's send
201 // buffer. The later can be non-zero if the peer shrinks
202 // its advertised window.
203 //
204 Left = GET_SND_DATASIZE (Sk) + TCP_SUB_SEQ (TcpGetMaxSndNxt (Tcb), Tcb->SndNxt);
205
206 Len = MIN (Win, Left);
207
208 if (Len > Tcb->SndMss) {
209 Len = Tcb->SndMss;
210 }
211
212 if ((Force != 0) || ((Len == 0) && (Left == 0))) {
213 return Len;
214 }
215
216 if ((Len == 0) && (Left != 0)) {
217 goto SetPersistTimer;
218 }
219
220 //
221 // Sender's SWS avoidance: Don't send a small segment unless
222 // a)A full-sized segment can be sent,
223 // b)At least one-half of the maximum sized windows that
224 // the other end has ever advertised.
225 // c)It can send everything it has, and either it isn't
226 // expecting an ACK, or the Nagle algorithm is disabled.
227 //
228 if ((Len == Tcb->SndMss) || (2 * Len >= Tcb->SndWndMax)) {
229 return Len;
230 }
231
232 if ((Len == Left) &&
233 ((Tcb->SndNxt == Tcb->SndUna) || TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_NAGLE))
234 )
235 {
236 return Len;
237 }
238
239 //
240 // RFC1122 suggests to set a timer when SWSA forbids TCP
241 // sending more data, and combines it with a probe timer.
242 //
243SetPersistTimer:
244 if (!TCP_TIMER_ON (Tcb->EnabledTimer, TCP_TIMER_REXMIT)) {
245 DEBUG (
246 (DEBUG_WARN,
247 "TcpDataToSend: enter persistent state for TCB %p\n",
248 Tcb)
249 );
250
251 if (!Tcb->ProbeTimerOn) {
252 TcpSetProbeTimer (Tcb);
253 }
254 }
255
256 return 0;
257}
258
270INTN
272 IN OUT TCP_CB *Tcb,
273 IN NET_BUF *Nbuf
274 )
275{
276 UINT16 Len;
277 TCP_HEAD *Head;
278 TCP_SEG *Seg;
279 BOOLEAN Syn;
280 UINT32 DataLen;
281
282 ASSERT ((Nbuf != NULL) && (Nbuf->Tcp == NULL));
283
284 if (TcpVerifySegment (Nbuf) == 0) {
285 return -1;
286 }
287
288 DataLen = Nbuf->TotalSize;
289
290 Seg = TCPSEG_NETBUF (Nbuf);
291 Syn = TCP_FLG_ON (Seg->Flag, TCP_FLG_SYN);
292
293 if (Syn) {
294 Len = TcpSynBuildOption (Tcb, Nbuf);
295 } else {
296 Len = TcpBuildOption (Tcb, Nbuf);
297 }
298
299 ASSERT ((Len % 4 == 0) && (Len <= 40));
300
301 Len += sizeof (TCP_HEAD);
302
303 Head = (TCP_HEAD *)NetbufAllocSpace (
304 Nbuf,
305 sizeof (TCP_HEAD),
306 NET_BUF_HEAD
307 );
308
309 ASSERT (Head != NULL);
310
311 Nbuf->Tcp = Head;
312
313 Head->SrcPort = Tcb->LocalEnd.Port;
314 Head->DstPort = Tcb->RemoteEnd.Port;
315 Head->Seq = NTOHL (Seg->Seq);
316 Head->Ack = NTOHL (Tcb->RcvNxt);
317 Head->HeadLen = (UINT8)(Len >> 2);
318 Head->Res = 0;
319 Head->Wnd = TcpComputeWnd (Tcb, Syn);
320 Head->Checksum = 0;
321
322 //
323 // Check whether to set the PSH flag.
324 //
325 TCP_CLEAR_FLG (Seg->Flag, TCP_FLG_PSH);
326
327 if (DataLen != 0) {
328 if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_SND_PSH) &&
329 TCP_SEQ_BETWEEN (Seg->Seq, Tcb->SndPsh, Seg->End)
330 )
331 {
332 TCP_SET_FLG (Seg->Flag, TCP_FLG_PSH);
333 TCP_CLEAR_FLG (Tcb->CtrlFlag, TCP_CTRL_SND_PSH);
334 } else if ((Seg->End == Tcb->SndNxt) && (GET_SND_DATASIZE (Tcb->Sk) == 0)) {
335 TCP_SET_FLG (Seg->Flag, TCP_FLG_PSH);
336 }
337 }
338
339 //
340 // Check whether to set the URG flag and the urgent pointer.
341 //
342 TCP_CLEAR_FLG (Seg->Flag, TCP_FLG_URG);
343
344 if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_SND_URG) && TCP_SEQ_LEQ (Seg->Seq, Tcb->SndUp)) {
345 TCP_SET_FLG (Seg->Flag, TCP_FLG_URG);
346
347 if (TCP_SEQ_LT (Tcb->SndUp, Seg->End)) {
348 Seg->Urg = (UINT16)TCP_SUB_SEQ (Tcb->SndUp, Seg->Seq);
349 } else {
350 Seg->Urg = (UINT16)MIN (
351 TCP_SUB_SEQ (
352 Tcb->SndUp,
353 Seg->Seq
354 ),
355 0xffff
356 );
357 }
358 }
359
360 Head->Flag = Seg->Flag;
361 Head->Urg = NTOHS (Seg->Urg);
362 Head->Checksum = TcpChecksum (Nbuf, Tcb->HeadSum);
363
364 //
365 // Update the TCP session's control information.
366 //
367 Tcb->RcvWl2 = Tcb->RcvNxt;
368 if (Syn) {
369 Tcb->RcvWnd = NTOHS (Head->Wnd);
370 }
371
372 //
373 // Clear the delayedack flag.
374 //
375 Tcb->DelayedAck = 0;
376
377 return TcpSendIpPacket (Tcb, Nbuf, &Tcb->LocalEnd.Ip, &Tcb->RemoteEnd.Ip, Tcb->Sk->IpVersion);
378}
379
390NET_BUF *
392 IN TCP_CB *Tcb,
393 IN TCP_SEQNO Seq,
394 IN UINT32 Len
395 )
396{
397 LIST_ENTRY *Head;
398 LIST_ENTRY *Cur;
399 NET_BUF *Node;
400 TCP_SEG *Seg;
401 NET_BUF *Nbuf;
402 TCP_SEQNO End;
403 UINT8 *Data;
404 UINT8 Flag;
405 INT32 Offset;
406 INT32 CopyLen;
407
408 ASSERT ((Tcb != NULL) && TCP_SEQ_LEQ (Seq, Tcb->SndNxt) && (Len > 0));
409
410 //
411 // Find the segment that contains the Seq.
412 //
413 Head = &Tcb->SndQue;
414
415 Node = NULL;
416 Seg = NULL;
417
418 NET_LIST_FOR_EACH (Cur, Head) {
419 Node = NET_LIST_USER_STRUCT (Cur, NET_BUF, List);
420 Seg = TCPSEG_NETBUF (Node);
421
422 if (TCP_SEQ_LT (Seq, Seg->End) && TCP_SEQ_LEQ (Seg->Seq, Seq)) {
423 break;
424 }
425 }
426
427 if ((Cur == Head) || (Seg == NULL) || (Node == NULL)) {
428 return NULL;
429 }
430
431 //
432 // Return the buffer if it can be returned without
433 // adjustment:
434 //
435 if ((Seg->Seq == Seq) &&
436 TCP_SEQ_LEQ (Seg->End, Seg->Seq + Len) &&
437 !NET_BUF_SHARED (Node)
438 )
439 {
440 NET_GET_REF (Node);
441 return Node;
442 }
443
444 //
445 // Create a new buffer and copy data there.
446 //
447 Nbuf = NetbufAlloc (Len + TCP_MAX_HEAD);
448
449 if (Nbuf == NULL) {
450 return NULL;
451 }
452
453 NetbufReserve (Nbuf, TCP_MAX_HEAD);
454
455 Flag = Seg->Flag;
456 End = Seg->End;
457
458 if (TCP_SEQ_LT (Seq + Len, Seg->End)) {
459 End = Seq + Len;
460 }
461
462 CopyLen = TCP_SUB_SEQ (End, Seq);
463 Offset = TCP_SUB_SEQ (Seq, Seg->Seq);
464
465 //
466 // If SYN is set and out of the range, clear the flag.
467 // Because the sequence of the first byte is SEG.SEQ+1,
468 // adjust Offset by -1. If SYN is in the range, copy
469 // one byte less.
470 //
471 if (TCP_FLG_ON (Seg->Flag, TCP_FLG_SYN)) {
472 if (TCP_SEQ_LT (Seg->Seq, Seq)) {
473 TCP_CLEAR_FLG (Flag, TCP_FLG_SYN);
474 Offset--;
475 } else {
476 CopyLen--;
477 }
478 }
479
480 //
481 // If FIN is set and in the range, copy one byte less,
482 // and if it is out of the range, clear the flag.
483 //
484 if (TCP_FLG_ON (Seg->Flag, TCP_FLG_FIN)) {
485 if (Seg->End == End) {
486 CopyLen--;
487 } else {
488 TCP_CLEAR_FLG (Flag, TCP_FLG_FIN);
489 }
490 }
491
492 ASSERT (CopyLen >= 0);
493
494 //
495 // Copy data to the segment
496 //
497 if (CopyLen != 0) {
498 Data = NetbufAllocSpace (Nbuf, CopyLen, NET_BUF_TAIL);
499 ASSERT (Data != NULL);
500
501 if ((INT32)NetbufCopy (Node, Offset, CopyLen, Data) != CopyLen) {
502 goto OnError;
503 }
504 }
505
506 CopyMem (TCPSEG_NETBUF (Nbuf), Seg, sizeof (TCP_SEG));
507
508 TCPSEG_NETBUF (Nbuf)->Seq = Seq;
509 TCPSEG_NETBUF (Nbuf)->End = End;
510 TCPSEG_NETBUF (Nbuf)->Flag = Flag;
511
512 return Nbuf;
513
514OnError:
515 NetbufFree (Nbuf);
516 return NULL;
517}
518
529NET_BUF *
531 IN TCP_CB *Tcb,
532 IN TCP_SEQNO Seq,
533 IN UINT32 Len
534 )
535{
536 NET_BUF *Nbuf;
537 UINT8 *Data;
538 UINT32 DataGet;
539
540 ASSERT ((Tcb != NULL) && (Tcb->Sk != NULL));
541
542 Nbuf = NetbufAlloc (Len + TCP_MAX_HEAD);
543
544 if (Nbuf == NULL) {
545 DEBUG (
546 (DEBUG_ERROR,
547 "TcpGetSegmentSock: failed to allocate a netbuf for TCB %p\n",
548 Tcb)
549 );
550
551 return NULL;
552 }
553
554 NetbufReserve (Nbuf, TCP_MAX_HEAD);
555
556 DataGet = 0;
557
558 if (Len != 0) {
559 //
560 // copy data to the segment.
561 //
562 Data = NetbufAllocSpace (Nbuf, Len, NET_BUF_TAIL);
563 ASSERT (Data != NULL);
564
565 DataGet = SockGetDataToSend (Tcb->Sk, 0, Len, Data);
566 }
567
568 NET_GET_REF (Nbuf);
569
570 TCPSEG_NETBUF (Nbuf)->Seq = Seq;
571 TCPSEG_NETBUF (Nbuf)->End = Seq + Len;
572
573 InsertTailList (&(Tcb->SndQue), &(Nbuf->List));
574
575 if (DataGet != 0) {
576 SockDataSent (Tcb->Sk, DataGet);
577 }
578
579 return Nbuf;
580}
581
593NET_BUF *
595 IN TCP_CB *Tcb,
596 IN TCP_SEQNO Seq,
597 IN UINT32 Len
598 )
599{
600 NET_BUF *Nbuf;
601
602 ASSERT (Tcb != NULL);
603
604 //
605 // Compare the SndNxt with the max sequence number sent.
606 //
607 if ((Len != 0) && TCP_SEQ_LT (Seq, TcpGetMaxSndNxt (Tcb))) {
608 Nbuf = TcpGetSegmentSndQue (Tcb, Seq, Len);
609 } else {
610 Nbuf = TcpGetSegmentSock (Tcb, Seq, Len);
611 }
612
613 if (TcpVerifySegment (Nbuf) == 0) {
614 NetbufFree (Nbuf);
615 return NULL;
616 }
617
618 return Nbuf;
619}
620
631INTN
633 IN TCP_CB *Tcb,
634 IN TCP_SEQNO Seq
635 )
636{
637 NET_BUF *Nbuf;
638 UINT32 Len;
639
640 //
641 // Compute the maximum length of retransmission. It is
642 // limited by three factors:
643 // 1. Less than SndMss
644 // 2. Must in the current send window
645 // 3. Will not change the boundaries of queued segments.
646 //
647
648 //
649 // Handle the Window Retraction if TCP window scale is enabled according to RFC7323:
650 // On first retransmission, or if the sequence number is out of
651 // window by less than 2^Rcv.Wind.Shift, then do normal
652 // retransmission(s) without regard to the receiver window as long
653 // as the original segment was in window when it was sent.
654 //
655 if ((Tcb->SndWndScale != 0) &&
656 (TCP_SEQ_GT (Seq, Tcb->RetxmitSeqMax) || TCP_SEQ_BETWEEN (Tcb->SndWl2 + Tcb->SndWnd, Seq, Tcb->SndWl2 + Tcb->SndWnd + (1 << Tcb->SndWndScale))))
657 {
658 Len = TCP_SUB_SEQ (Tcb->SndNxt, Seq);
659 DEBUG (
660 (DEBUG_WARN,
661 "TcpRetransmit: retransmission without regard to the receiver window for TCB %p\n",
662 Tcb)
663 );
664 } else if (TCP_SEQ_GEQ (Tcb->SndWl2 + Tcb->SndWnd, Seq)) {
665 Len = TCP_SUB_SEQ (Tcb->SndWl2 + Tcb->SndWnd, Seq);
666 } else {
667 DEBUG (
668 (DEBUG_WARN,
669 "TcpRetransmit: retransmission cancelled because send window too small for TCB %p\n",
670 Tcb)
671 );
672
673 return 0;
674 }
675
676 Len = MIN (Len, Tcb->SndMss);
677
678 Nbuf = TcpGetSegmentSndQue (Tcb, Seq, Len);
679 if (Nbuf == NULL) {
680 return -1;
681 }
682
683 if (TcpVerifySegment (Nbuf) == 0) {
684 goto OnError;
685 }
686
687 if (TcpTransmitSegment (Tcb, Nbuf) != 0) {
688 goto OnError;
689 }
690
691 if (TCP_SEQ_GT (Seq, Tcb->RetxmitSeqMax)) {
692 Tcb->RetxmitSeqMax = Seq;
693 }
694
695 //
696 // The retransmitted buffer may be on the SndQue,
697 // trim TCP head because all the buffers on SndQue
698 // are headless.
699 //
700 ASSERT (Nbuf->Tcp != NULL);
701 NetbufTrim (Nbuf, (Nbuf->Tcp->HeadLen << 2), NET_BUF_HEAD);
702 Nbuf->Tcp = NULL;
703
704 NetbufFree (Nbuf);
705 return 0;
706
707OnError:
708 if (Nbuf != NULL) {
709 NetbufFree (Nbuf);
710 }
711
712 return -1;
713}
714
724INTN
726 IN LIST_ENTRY *Head
727 )
728{
729 LIST_ENTRY *Entry;
730 NET_BUF *Nbuf;
731 TCP_SEQNO Seq;
732
733 if (IsListEmpty (Head)) {
734 return 1;
735 }
736
737 //
738 // Initialize the Seq.
739 //
740 Entry = Head->ForwardLink;
741 Nbuf = NET_LIST_USER_STRUCT (Entry, NET_BUF, List);
742 Seq = TCPSEG_NETBUF (Nbuf)->Seq;
743
744 NET_LIST_FOR_EACH (Entry, Head) {
745 Nbuf = NET_LIST_USER_STRUCT (Entry, NET_BUF, List);
746
747 if (TcpVerifySegment (Nbuf) == 0) {
748 return 0;
749 }
750
751 //
752 // All the node in the SndQue should has:
753 // SEG.SEQ = LAST_SEG.END
754 //
755 if (Seq != TCPSEG_NETBUF (Nbuf)->Seq) {
756 return 0;
757 }
758
759 Seq = TCPSEG_NETBUF (Nbuf)->End;
760 }
761
762 return 1;
763}
764
775INTN
777 IN OUT TCP_CB *Tcb,
778 IN INTN Force
779 )
780{
781 UINT32 Len;
782 INTN Sent;
783 UINT8 Flag;
784 NET_BUF *Nbuf;
785 TCP_SEG *Seg;
786 TCP_SEQNO Seq;
787 TCP_SEQNO End;
788
789 ASSERT ((Tcb != NULL) && (Tcb->Sk != NULL) && (Tcb->State != TCP_LISTEN));
790
791 Sent = 0;
792
793 if ((Tcb->State == TCP_CLOSED) || TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_FIN_SENT)) {
794 return 0;
795 }
796
797 do {
798 //
799 // Compute how much data can be sent
800 //
801 Len = TcpDataToSend (Tcb, Force);
802 Seq = Tcb->SndNxt;
803
804 ASSERT ((Tcb->State) < (ARRAY_SIZE (mTcpOutFlag)));
805 Flag = mTcpOutFlag[Tcb->State];
806
807 if ((Flag & TCP_FLG_SYN) != 0) {
808 Seq = Tcb->Iss;
809 Len = 0;
810 }
811
812 //
813 // Only send a segment without data if SYN or
814 // FIN is set.
815 //
816 if ((Len == 0) && ((Flag & (TCP_FLG_SYN | TCP_FLG_FIN)) == 0)) {
817 return Sent;
818 }
819
820 Nbuf = TcpGetSegment (Tcb, Seq, Len);
821
822 if (Nbuf == NULL) {
823 DEBUG (
824 (DEBUG_ERROR,
825 "TcpToSendData: failed to get a segment for TCB %p\n",
826 Tcb)
827 );
828
829 goto OnError;
830 }
831
832 Seg = TCPSEG_NETBUF (Nbuf);
833
834 //
835 // Set the TcpSeg in Nbuf.
836 //
837 Len = Nbuf->TotalSize;
838 End = Seq + Len;
839 if (TCP_FLG_ON (Flag, TCP_FLG_SYN)) {
840 End++;
841 }
842
843 if ((Flag & TCP_FLG_FIN) != 0) {
844 //
845 // Send FIN if all data is sent, and FIN is
846 // in the window
847 //
848 if ((TcpGetMaxSndNxt (Tcb) == Tcb->SndNxt) &&
849 (GET_SND_DATASIZE (Tcb->Sk) == 0) &&
850 TCP_SEQ_LT (End + 1, Tcb->SndWnd + Tcb->SndWl2)
851 )
852 {
853 DEBUG (
854 (DEBUG_NET,
855 "TcpToSendData: send FIN to peer for TCB %p in state %s\n",
856 Tcb,
857 mTcpStateName[Tcb->State])
858 );
859
860 End++;
861 } else {
862 TCP_CLEAR_FLG (Flag, TCP_FLG_FIN);
863 }
864 }
865
866 Seg->Seq = Seq;
867 Seg->End = End;
868 Seg->Flag = Flag;
869
870 if ((TcpVerifySegment (Nbuf) == 0) || (TcpCheckSndQue (&Tcb->SndQue) == 0)) {
871 DEBUG (
872 (DEBUG_ERROR,
873 "TcpToSendData: discard a broken segment for TCB %p\n",
874 Tcb)
875 );
876 goto OnError;
877 }
878
879 //
880 // Don't send an empty segment here.
881 //
882 if (Seg->End == Seg->Seq) {
883 DEBUG (
884 (DEBUG_WARN,
885 "TcpToSendData: created a empty segment for TCB %p, free it now\n",
886 Tcb)
887 );
888
889 goto OnError;
890 }
891
892 if (TcpTransmitSegment (Tcb, Nbuf) != 0) {
893 NetbufTrim (Nbuf, (Nbuf->Tcp->HeadLen << 2), NET_BUF_HEAD);
894 Nbuf->Tcp = NULL;
895
896 if ((Flag & TCP_FLG_FIN) != 0) {
897 TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_FIN_SENT);
898 }
899
900 goto OnError;
901 }
902
903 Sent += TCP_SUB_SEQ (End, Seq);
904
905 //
906 // All the buffers in the SndQue are headless.
907 //
908 ASSERT (Nbuf->Tcp != NULL);
909
910 NetbufTrim (Nbuf, (Nbuf->Tcp->HeadLen << 2), NET_BUF_HEAD);
911 Nbuf->Tcp = NULL;
912
913 NetbufFree (Nbuf);
914
915 //
916 // Update the status in TCB.
917 //
918 Tcb->DelayedAck = 0;
919
920 if ((Flag & TCP_FLG_FIN) != 0) {
921 TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_FIN_SENT);
922 }
923
924 if (TCP_SEQ_GT (End, Tcb->SndNxt)) {
925 Tcb->SndNxt = End;
926 }
927
928 if (!TCP_TIMER_ON (Tcb->EnabledTimer, TCP_TIMER_REXMIT)) {
929 TcpSetTimer (Tcb, TCP_TIMER_REXMIT, Tcb->Rto);
930 }
931
932 //
933 // Enable RTT measurement only if not in retransmit.
934 // Karn's algorithm requires not to update RTT when in loss.
935 //
936 if ((Tcb->CongestState == TCP_CONGEST_OPEN) && !TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_RTT_ON)) {
937 DEBUG (
938 (DEBUG_NET,
939 "TcpToSendData: set RTT measure sequence %d for TCB %p\n",
940 Seq,
941 Tcb)
942 );
943
944 TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_RTT_ON);
945 Tcb->RttSeq = Seq;
946 Tcb->RttMeasure = 0;
947 }
948 } while (Len == Tcb->SndMss);
949
950 return Sent;
951
952OnError:
953 if (Nbuf != NULL) {
954 NetbufFree (Nbuf);
955 }
956
957 return Sent;
958}
959
966VOID
968 IN OUT TCP_CB *Tcb
969 )
970{
971 NET_BUF *Nbuf;
972 TCP_SEG *Seg;
973
974 Nbuf = NetbufAlloc (TCP_MAX_HEAD);
975
976 if (Nbuf == NULL) {
977 return;
978 }
979
980 NetbufReserve (Nbuf, TCP_MAX_HEAD);
981
982 Seg = TCPSEG_NETBUF (Nbuf);
983 Seg->Seq = Tcb->SndNxt;
984 Seg->End = Tcb->SndNxt;
985 Seg->Flag = TCP_FLG_ACK;
986
987 if (TcpTransmitSegment (Tcb, Nbuf) == 0) {
988 TCP_CLEAR_FLG (Tcb->CtrlFlag, TCP_CTRL_ACK_NOW);
989 Tcb->DelayedAck = 0;
990 }
991
992 NetbufFree (Nbuf);
993}
994
1004INTN
1006 IN OUT TCP_CB *Tcb
1007 )
1008{
1009 NET_BUF *Nbuf;
1010 TCP_SEG *Seg;
1011 INTN Result;
1012
1013 Nbuf = NetbufAlloc (TCP_MAX_HEAD);
1014
1015 if (Nbuf == NULL) {
1016 return -1;
1017 }
1018
1019 NetbufReserve (Nbuf, TCP_MAX_HEAD);
1020
1021 //
1022 // SndNxt-1 is out of window. The peer should respond
1023 // with an ACK.
1024 //
1025 Seg = TCPSEG_NETBUF (Nbuf);
1026 Seg->Seq = Tcb->SndNxt - 1;
1027 Seg->End = Tcb->SndNxt - 1;
1028 Seg->Flag = TCP_FLG_ACK;
1029
1030 Result = TcpTransmitSegment (Tcb, Nbuf);
1031 NetbufFree (Nbuf);
1032
1033 return Result;
1034}
1035
1042VOID
1044 IN OUT TCP_CB *Tcb
1045 )
1046{
1047 UINT32 TcpNow;
1048
1049 //
1050 // Generally, TCP should send a delayed ACK unless:
1051 // 1. ACK at least every other FULL sized segment received.
1052 // 2. Packets received out of order.
1053 // 3. Receiving window is open.
1054 //
1055 if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_ACK_NOW) || (Tcb->DelayedAck >= 1)) {
1056 TcpSendAck (Tcb);
1057 return;
1058 }
1059
1060 TcpNow = TcpRcvWinNow (Tcb);
1061
1062 if (TcpNow > TcpRcvWinOld (Tcb)) {
1063 TcpSendAck (Tcb);
1064 return;
1065 }
1066
1067 DEBUG (
1068 (DEBUG_NET,
1069 "TcpToSendAck: scheduled a delayed ACK for TCB %p\n",
1070 Tcb)
1071 );
1072
1073 //
1074 // Schedule a delayed ACK.
1075 //
1076 Tcb->DelayedAck++;
1077}
1078
1094INTN
1096 IN TCP_CB *Tcb,
1097 IN TCP_HEAD *Head,
1098 IN INT32 Len,
1099 IN EFI_IP_ADDRESS *Local,
1100 IN EFI_IP_ADDRESS *Remote,
1101 IN UINT8 Version
1102 )
1103{
1104 NET_BUF *Nbuf;
1105 TCP_HEAD *Nhead;
1106 UINT16 HeadSum;
1107
1108 //
1109 // Don't respond to a Reset with reset.
1110 //
1111 if ((Head->Flag & TCP_FLG_RST) != 0) {
1112 return 0;
1113 }
1114
1115 Nbuf = NetbufAlloc (TCP_MAX_HEAD);
1116
1117 if (Nbuf == NULL) {
1118 return -1;
1119 }
1120
1121 Nhead = (TCP_HEAD *)NetbufAllocSpace (
1122 Nbuf,
1123 sizeof (TCP_HEAD),
1124 NET_BUF_TAIL
1125 );
1126
1127 ASSERT (Nhead != NULL);
1128
1129 Nbuf->Tcp = Nhead;
1130 Nhead->Flag = TCP_FLG_RST;
1131
1132 //
1133 // Derive Seq/ACK from the segment if no TCB
1134 // is associated with it, otherwise derive from the Tcb.
1135 //
1136 if (Tcb == NULL) {
1137 if (TCP_FLG_ON (Head->Flag, TCP_FLG_ACK)) {
1138 Nhead->Seq = Head->Ack;
1139 Nhead->Ack = 0;
1140 } else {
1141 Nhead->Seq = 0;
1142 TCP_SET_FLG (Nhead->Flag, TCP_FLG_ACK);
1143 Nhead->Ack = HTONL (NTOHL (Head->Seq) + Len);
1144 }
1145 } else {
1146 Nhead->Seq = HTONL (Tcb->SndNxt);
1147 Nhead->Ack = HTONL (Tcb->RcvNxt);
1148 TCP_SET_FLG (Nhead->Flag, TCP_FLG_ACK);
1149 }
1150
1151 Nhead->SrcPort = Head->DstPort;
1152 Nhead->DstPort = Head->SrcPort;
1153 Nhead->HeadLen = (UINT8)(sizeof (TCP_HEAD) >> 2);
1154 Nhead->Res = 0;
1155 Nhead->Wnd = HTONS (0xFFFF);
1156 Nhead->Checksum = 0;
1157 Nhead->Urg = 0;
1158
1159 if (Version == IP_VERSION_4) {
1160 HeadSum = NetPseudoHeadChecksum (Local->Addr[0], Remote->Addr[0], 6, 0);
1161 } else {
1162 HeadSum = NetIp6PseudoHeadChecksum (&Local->v6, &Remote->v6, 6, 0);
1163 }
1164
1165 Nhead->Checksum = TcpChecksum (Nbuf, HeadSum);
1166
1167 TcpSendIpPacket (Tcb, Nbuf, Local, Remote, Version);
1168
1169 NetbufFree (Nbuf);
1170
1171 return 0;
1172}
1173
1183INTN
1185 IN NET_BUF *Nbuf
1186 )
1187{
1188 TCP_HEAD *Head;
1189 TCP_SEG *Seg;
1190 UINT32 Len;
1191
1192 if (Nbuf == NULL) {
1193 return 1;
1194 }
1195
1196 NET_CHECK_SIGNATURE (Nbuf, NET_BUF_SIGNATURE);
1197
1198 Seg = TCPSEG_NETBUF (Nbuf);
1199 Len = Nbuf->TotalSize;
1200 Head = Nbuf->Tcp;
1201
1202 if (Head != NULL) {
1203 if (Head->Flag != Seg->Flag) {
1204 return 0;
1205 }
1206
1207 Len -= (Head->HeadLen << 2);
1208 }
1209
1210 if (TCP_FLG_ON (Seg->Flag, TCP_FLG_SYN)) {
1211 Len++;
1212 }
1213
1214 if (TCP_FLG_ON (Seg->Flag, TCP_FLG_FIN)) {
1215 Len++;
1216 }
1217
1218 if (Seg->Seq + Len != Seg->End) {
1219 return 0;
1220 }
1221
1222 return 1;
1223}
INT64 INTN
BOOLEAN EFIAPI IsListEmpty(IN CONST LIST_ENTRY *ListHead)
Definition: LinkedList.c:403
LIST_ENTRY *EFIAPI InsertTailList(IN OUT LIST_ENTRY *ListHead, IN OUT LIST_ENTRY *Entry)
Definition: LinkedList.c:259
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
#define NULL
Definition: Base.h:319
#define MIN(a, b)
Definition: Base.h:1007
#define ARRAY_SIZE(Array)
Definition: Base.h:1393
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define DEBUG(Expression)
Definition: DebugLib.h:434
VOID EFIAPI NetbufFree(IN NET_BUF *Nbuf)
Definition: NetBuffer.c:195
VOID EFIAPI NetbufReserve(IN OUT NET_BUF *Nbuf, IN UINT32 Len)
Definition: NetBuffer.c:984
UINT16 EFIAPI NetIp6PseudoHeadChecksum(IN EFI_IPv6_ADDRESS *Src, IN EFI_IPv6_ADDRESS *Dst, IN UINT8 NextHeader, IN UINT32 Len)
Definition: NetBuffer.c:1777
UINT32 EFIAPI NetbufTrim(IN OUT NET_BUF *Nbuf, IN UINT32 Len, IN BOOLEAN FromHead)
Definition: NetBuffer.c:1134
UINT32 EFIAPI NetbufCopy(IN NET_BUF *Nbuf, IN UINT32 Offset, IN UINT32 Len, IN UINT8 *Dest)
Definition: NetBuffer.c:1206
NET_BUF *EFIAPI NetbufAlloc(IN UINT32 Len)
Definition: NetBuffer.c:89
UINT8 *EFIAPI NetbufAllocSpace(IN OUT NET_BUF *Nbuf, IN UINT32 Len, IN BOOLEAN FromHead)
Definition: NetBuffer.c:1015
UINT16 EFIAPI NetPseudoHeadChecksum(IN IP4_ADDR Src, IN IP4_ADDR Dst, IN UINT8 Proto, IN UINT16 Len)
Definition: NetBuffer.c:1740
UINT32 SockGetFreeSpace(IN SOCKET *Sock, IN UINT32 Which)
Definition: SockImpl.c:1156
#define GET_SND_DATASIZE(Sock)
Definition: Socket.h:284
UINT32 SockGetDataToSend(IN SOCKET *Sock, IN UINT32 Offset, IN UINT32 Len, OUT UINT8 *Dest)
Definition: SockImpl.c:1096
#define GET_RCV_BUFFSIZE(Sock)
Definition: Socket.h:245
VOID SockDataSent(IN OUT SOCKET *Sock, IN UINT32 Count)
Definition: SockImpl.c:1039
VOID TcpSetProbeTimer(IN OUT TCP_CB *Tcb)
Definition: TcpTimer.c:415
VOID TcpSetTimer(IN OUT TCP_CB *Tcb, IN UINT16 Timer, IN UINT32 TimeOut)
Definition: TcpTimer.c:364
INTN TcpSendIpPacket(IN TCP_CB *Tcb, IN NET_BUF *Nbuf, IN EFI_IP_ADDRESS *Src, IN EFI_IP_ADDRESS *Dest, IN UINT8 Version)
Definition: TcpIo.c:62
UINT16 TcpChecksum(IN NET_BUF *Nbuf, IN UINT16 HeadSum)
Definition: TcpMisc.c:854
UINT16 TcpBuildOption(IN TCP_CB *Tcb, IN NET_BUF *Nbuf)
Definition: TcpOption.c:185
UINT16 TcpSynBuildOption(IN TCP_CB *Tcb, IN NET_BUF *Nbuf)
Definition: TcpOption.c:105
INTN TcpRetransmit(IN TCP_CB *Tcb, IN TCP_SEQNO Seq)
Definition: TcpOutput.c:632
INTN TcpVerifySegment(IN NET_BUF *Nbuf)
Definition: TcpOutput.c:1184
INTN TcpSendReset(IN TCP_CB *Tcb, IN TCP_HEAD *Head, IN INT32 Len, IN EFI_IP_ADDRESS *Local, IN EFI_IP_ADDRESS *Remote, IN UINT8 Version)
Definition: TcpOutput.c:1095
INTN TcpToSendData(IN OUT TCP_CB *Tcb, IN INTN Force)
Definition: TcpOutput.c:776
UINT32 TcpRcvWinNow(IN TCP_CB *Tcb)
Definition: TcpOutput.c:62
INTN TcpCheckSndQue(IN LIST_ENTRY *Head)
Definition: TcpOutput.c:725
UINT32 TcpRcvWinOld(IN TCP_CB *Tcb)
Definition: TcpOutput.c:35
NET_BUF * TcpGetSegment(IN TCP_CB *Tcb, IN TCP_SEQNO Seq, IN UINT32 Len)
Definition: TcpOutput.c:594
NET_BUF * TcpGetSegmentSndQue(IN TCP_CB *Tcb, IN TCP_SEQNO Seq, IN UINT32 Len)
Definition: TcpOutput.c:391
NET_BUF * TcpGetSegmentSock(IN TCP_CB *Tcb, IN TCP_SEQNO Seq, IN UINT32 Len)
Definition: TcpOutput.c:530
INTN TcpSendZeroProbe(IN OUT TCP_CB *Tcb)
Definition: TcpOutput.c:1005
INTN TcpTransmitSegment(IN OUT TCP_CB *Tcb, IN NET_BUF *Nbuf)
Definition: TcpOutput.c:271
VOID TcpSendAck(IN OUT TCP_CB *Tcb)
Definition: TcpOutput.c:967
UINT16 TcpComputeWnd(IN OUT TCP_CB *Tcb, IN BOOLEAN Syn)
Definition: TcpOutput.c:106
UINT32 TcpDataToSend(IN TCP_CB *Tcb, IN INTN Force)
Definition: TcpOutput.c:166
TCP_SEQNO TcpGetMaxSndNxt(IN TCP_CB *Tcb)
Definition: TcpOutput.c:137
VOID TcpToSendAck(IN OUT TCP_CB *Tcb)
Definition: TcpOutput.c:1043
#define TCP_CTRL_NO_NAGLE
Disable Nagle algorithm.
Definition: TcpProto.h:58
#define TCP_TIMER_REXMIT
Retransmit timer.
Definition: TcpProto.h:78
#define TCP_CTRL_FIN_SENT
FIN is sent.
Definition: TcpProto.h:68
#define TCP_CLOSED
Definition: TcpProto.h:17
#define TCP_CTRL_SND_PSH
In PUSH send mode.
Definition: TcpProto.h:67
#define TCP_CTRL_RTT_ON
The RTT measurement is on.
Definition: TcpProto.h:71
#define TCP_CTRL_SND_URG
In urgent send mode.
Definition: TcpProto.h:65
#define TCP_CTRL_ACK_NOW
Send the ACK now, don't delay.
Definition: TcpProto.h:72
#define TCP_FLG_FIN
Definition: TcpProto.h:32
#define TCP_CONGEST_OPEN
TCP is opening its congestion window.
Definition: TcpProto.h:53
TCP_SEQNO Seq
Starting sequence number.
Definition: TcpProto.h:211
TCP_SEQNO End
The sequence of the last byte + 1, include SYN/FIN. End-Seq = SEG.LEN.
Definition: TcpProto.h:212
UINT8 Flag
TCP header flags.
Definition: TcpProto.h:214
UINT16 Urg
Valid if URG flag is set.
Definition: TcpProto.h:215