]>
git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Output.c
2 TCP output process routines.
4 Copyright (c) 2005 - 2016, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php<BR>
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 UINT8 mTcpOutFlag
[] = {
20 TCP_FLG_SYN
, // TCP_SYN_SENT
21 TCP_FLG_SYN
| TCP_FLG_ACK
, // TCP_SYN_RCVD
22 TCP_FLG_ACK
, // TCP_ESTABLISHED
23 TCP_FLG_FIN
| TCP_FLG_ACK
, // TCP_FIN_WAIT_1
24 TCP_FLG_ACK
, // TCP_FIN_WAIT_2
25 TCP_FLG_ACK
| TCP_FLG_FIN
, // TCP_CLOSING
26 TCP_FLG_ACK
, // TCP_TIME_WAIT
27 TCP_FLG_ACK
, // TCP_CLOSE_WAIT
28 TCP_FLG_FIN
| TCP_FLG_ACK
// TCP_LAST_ACK
33 Compute the sequence space left in the old receive window.
35 @param Tcb Pointer to the TCP_CB of this TCP instance.
37 @return The sequence space left in the old receive window.
49 if (TCP_SEQ_GT (Tcb
->RcvWl2
+ Tcb
->RcvWnd
, Tcb
->RcvNxt
)) {
51 OldWin
= TCP_SUB_SEQ (
52 Tcb
->RcvWl2
+ Tcb
->RcvWnd
,
62 Compute the current receive window.
64 @param Tcb Pointer to the TCP_CB of this TCP instance.
66 @return The size of the current receive window, in bytes.
82 OldWin
= TcpRcvWinOld (Tcb
);
84 Win
= SockGetFreeSpace (Sk
, SOCK_RCV_BUF
);
88 Increase
= Win
- OldWin
;
92 // Receiver's SWS: don't advertise a bigger window
93 // unless it can be increased by at least one Mss or
94 // half of the receive buffer.
96 if ((Increase
> Tcb
->SndMss
) ||
97 (2 * Increase
>= GET_RCV_BUFFSIZE (Sk
))) {
107 Compute the value to fill in the window size field of the outgoing segment.
109 @param Tcb Pointer to the TCP_CB of this TCP instance.
110 @param Syn The flag to indicate whether the outgoing segment is a SYN
113 @return The value of the local receive window size used to fill the outing segment.
125 // RFC requires that initial window not be scaled
129 Wnd
= GET_RCV_BUFFSIZE (Tcb
->Sk
);
132 Wnd
= TcpRcvWinNow (Tcb
);
137 Wnd
= MIN (Wnd
>> Tcb
->RcvWndScale
, 0xffff);
138 return NTOHS ((UINT16
) Wnd
);
143 Get the maximum SndNxt.
145 @param Tcb Pointer to the TCP_CB of this TCP instance.
147 @return The sequence number of the maximum SndNxt.
158 if (IsListEmpty (&Tcb
->SndQue
)) {
162 Entry
= Tcb
->SndQue
.BackLink
;
163 Nbuf
= NET_LIST_USER_STRUCT (Entry
, NET_BUF
, List
);
165 ASSERT (TCP_SEQ_GEQ (TCPSEG_NETBUF (Nbuf
)->End
, Tcb
->SndNxt
));
166 return TCPSEG_NETBUF (Nbuf
)->End
;
171 Compute how much data to send.
173 @param Tcb Pointer to the TCP_CB of this TCP instance.
174 @param Force Whether to ignore the sender's SWS avoidance algorithm and send
177 @return The length of the data can be sent, if 0, no data can be sent.
196 // TCP should NOT send data beyond the send window
197 // and congestion window. The right edge of send
198 // window is defined as SND.WL2 + SND.WND. The right
199 // edge of congestion window is defined as SND.UNA +
203 Limit
= Tcb
->SndWl2
+ Tcb
->SndWnd
;
205 if (TCP_SEQ_GT (Limit
, Tcb
->SndUna
+ Tcb
->CWnd
)) {
207 Limit
= Tcb
->SndUna
+ Tcb
->CWnd
;
210 if (TCP_SEQ_GT (Limit
, Tcb
->SndNxt
)) {
211 Win
= TCP_SUB_SEQ (Limit
, Tcb
->SndNxt
);
215 // The data to send contains two parts: the data on the
216 // socket send queue, and the data on the TCB's send
217 // buffer. The later can be non-zero if the peer shrinks
218 // its advertised window.
220 Left
= GET_SND_DATASIZE (Sk
) +
221 TCP_SUB_SEQ (TcpGetMaxSndNxt (Tcb
), Tcb
->SndNxt
);
223 Len
= MIN (Win
, Left
);
225 if (Len
> Tcb
->SndMss
) {
229 if ((Force
!= 0)|| (Len
== 0 && Left
== 0)) {
233 if (Len
== 0 && Left
!= 0) {
234 goto SetPersistTimer
;
238 // Sender's SWS avoidance: Don't send a small segment unless
239 // a)A full-sized segment can be sent,
240 // b)at least one-half of the maximum sized windows that
241 // the other end has ever advertised.
242 // c)It can send everything it has and either it isn't
243 // expecting an ACK or the Nagle algorithm is disabled.
245 if ((Len
== Tcb
->SndMss
) || (2 * Len
>= Tcb
->SndWndMax
)) {
251 ((Tcb
->SndNxt
== Tcb
->SndUna
) ||
252 TCP_FLG_ON (Tcb
->CtrlFlag
, TCP_CTRL_NO_NAGLE
))) {
258 // RFC1122 suggests to set a timer when SWSA forbids TCP
259 // sending more data, and combine it with probe timer.
262 if (!TCP_TIMER_ON (Tcb
->EnabledTimer
, TCP_TIMER_REXMIT
)) {
266 "TcpDataToSend: enter persistent state for TCB %p\n",
270 if (!Tcb
->ProbeTimerOn
) {
271 TcpSetProbeTimer (Tcb
);
280 Build the TCP header of the TCP segment and transmit the segment by IP.
282 @param Tcb Pointer to the TCP_CB of this TCP instance.
283 @param Nbuf Pointer to the buffer containing the segment to be sent out.
285 @retval 0 The segment is sent out successfully.
286 @retval other Error condition occurred.
301 ASSERT ((Nbuf
!= NULL
) && (Nbuf
->Tcp
== NULL
) && (TcpVerifySegment (Nbuf
) != 0));
303 DataLen
= Nbuf
->TotalSize
;
305 Seg
= TCPSEG_NETBUF (Nbuf
);
306 Syn
= TCP_FLG_ON (Seg
->Flag
, TCP_FLG_SYN
);
310 Len
= TcpSynBuildOption (Tcb
, Nbuf
);
313 Len
= TcpBuildOption (Tcb
, Nbuf
);
316 ASSERT ((Len
% 4 == 0) && (Len
<= 40));
318 Len
+= sizeof (TCP_HEAD
);
320 Head
= (TCP_HEAD
*) NetbufAllocSpace (
326 ASSERT (Head
!= NULL
);
330 Head
->SrcPort
= Tcb
->LocalEnd
.Port
;
331 Head
->DstPort
= Tcb
->RemoteEnd
.Port
;
332 Head
->Seq
= NTOHL (Seg
->Seq
);
333 Head
->Ack
= NTOHL (Tcb
->RcvNxt
);
334 Head
->HeadLen
= (UINT8
) (Len
>> 2);
336 Head
->Wnd
= TcpComputeWnd (Tcb
, Syn
);
340 // Check whether to set the PSH flag.
342 TCP_CLEAR_FLG (Seg
->Flag
, TCP_FLG_PSH
);
345 if (TCP_FLG_ON (Tcb
->CtrlFlag
, TCP_CTRL_SND_PSH
) &&
346 TCP_SEQ_BETWEEN (Seg
->Seq
, Tcb
->SndPsh
, Seg
->End
)) {
348 TCP_SET_FLG (Seg
->Flag
, TCP_FLG_PSH
);
349 TCP_CLEAR_FLG (Tcb
->CtrlFlag
, TCP_CTRL_SND_PSH
);
351 } else if ((Seg
->End
== Tcb
->SndNxt
) &&
352 (GET_SND_DATASIZE (Tcb
->Sk
) == 0)) {
354 TCP_SET_FLG (Seg
->Flag
, TCP_FLG_PSH
);
359 // Check whether to set the URG flag and the urgent pointer.
361 TCP_CLEAR_FLG (Seg
->Flag
, TCP_FLG_URG
);
363 if (TCP_FLG_ON (Tcb
->CtrlFlag
, TCP_CTRL_SND_URG
) &&
364 TCP_SEQ_LEQ (Seg
->Seq
, Tcb
->SndUp
)) {
366 TCP_SET_FLG (Seg
->Flag
, TCP_FLG_URG
);
368 if (TCP_SEQ_LT (Tcb
->SndUp
, Seg
->End
)) {
370 Seg
->Urg
= (UINT16
) TCP_SUB_SEQ (Tcb
->SndUp
, Seg
->Seq
);
373 Seg
->Urg
= (UINT16
) MIN (
374 TCP_SUB_SEQ (Tcb
->SndUp
,
381 Head
->Flag
= Seg
->Flag
;
382 Head
->Urg
= NTOHS (Seg
->Urg
);
383 Head
->Checksum
= TcpChecksum (Nbuf
, Tcb
->HeadSum
);
386 // update the TCP session's control information
388 Tcb
->RcvWl2
= Tcb
->RcvNxt
;
390 Tcb
->RcvWnd
= NTOHS (Head
->Wnd
);
394 // clear delayedack flag
398 return TcpSendIpPacket (Tcb
, Nbuf
, Tcb
->LocalEnd
.Ip
, Tcb
->RemoteEnd
.Ip
);
403 Get a segment from the Tcb's SndQue.
405 @param Tcb Pointer to the TCP_CB of this TCP instance.
406 @param Seq The sequence number of the segment.
407 @param Len The maximum length of the segment.
409 @return Pointer to the segment, if NULL some error occurred.
413 TcpGetSegmentSndQue (
430 ASSERT ((Tcb
!= NULL
) && TCP_SEQ_LEQ (Seq
, Tcb
->SndNxt
) && (Len
> 0));
433 // Find the segment that contains the Seq.
440 NET_LIST_FOR_EACH (Cur
, Head
) {
441 Node
= NET_LIST_USER_STRUCT (Cur
, NET_BUF
, List
);
442 Seg
= TCPSEG_NETBUF (Node
);
444 if (TCP_SEQ_LT (Seq
, Seg
->End
) && TCP_SEQ_LEQ (Seg
->Seq
, Seq
)) {
450 ASSERT (Cur
!= Head
);
451 ASSERT (Node
!= NULL
);
452 ASSERT (Seg
!= NULL
);
455 // Return the buffer if it can be returned without
458 if ((Seg
->Seq
== Seq
) &&
459 TCP_SEQ_LEQ (Seg
->End
, Seg
->Seq
+ Len
) &&
460 !NET_BUF_SHARED (Node
)) {
467 // Create a new buffer and copy data there.
469 Nbuf
= NetbufAlloc (Len
+ TCP_MAX_HEAD
);
475 NetbufReserve (Nbuf
, TCP_MAX_HEAD
);
480 if (TCP_SEQ_LT (Seq
+ Len
, Seg
->End
)) {
484 CopyLen
= TCP_SUB_SEQ (End
, Seq
);
485 Offset
= TCP_SUB_SEQ (Seq
, Seg
->Seq
);
488 // If SYN is set and out of the range, clear the flag.
489 // Because the sequence of the first byte is SEG.SEQ+1,
490 // adjust Offset by -1. If SYN is in the range, copy
493 if (TCP_FLG_ON (Seg
->Flag
, TCP_FLG_SYN
)) {
495 if (TCP_SEQ_LT (Seg
->Seq
, Seq
)) {
497 TCP_CLEAR_FLG (Flag
, TCP_FLG_SYN
);
506 // If FIN is set and in the range, copy one byte less,
507 // and if it is out of the range, clear the flag.
509 if (TCP_FLG_ON (Seg
->Flag
, TCP_FLG_FIN
)) {
511 if (Seg
->End
== End
) {
516 TCP_CLEAR_FLG (Flag
, TCP_FLG_FIN
);
520 ASSERT (CopyLen
>= 0);
523 // copy data to the segment
526 Data
= NetbufAllocSpace (Nbuf
, CopyLen
, NET_BUF_TAIL
);
527 ASSERT (Data
!= NULL
);
529 if ((INT32
) NetbufCopy (Node
, Offset
, CopyLen
, Data
) != CopyLen
) {
534 CopyMem (TCPSEG_NETBUF (Nbuf
), Seg
, sizeof (TCP_SEG
));
536 TCPSEG_NETBUF (Nbuf
)->Seq
= Seq
;
537 TCPSEG_NETBUF (Nbuf
)->End
= End
;
538 TCPSEG_NETBUF (Nbuf
)->Flag
= Flag
;
549 Get a segment from the Tcb's socket buffer.
551 @param Tcb Pointer to the TCP_CB of this TCP instance.
552 @param Seq The sequence number of the segment.
553 @param Len The maximum length of the segment.
555 @return Pointer to the segment, if NULL some error occurred.
569 ASSERT ((Tcb
!= NULL
) && (Tcb
->Sk
!= NULL
));
571 Nbuf
= NetbufAlloc (Len
+ TCP_MAX_HEAD
);
574 DEBUG ((EFI_D_ERROR
, "TcpGetSegmentSock: failed to allocate "
575 "a netbuf for TCB %p\n",Tcb
));
580 NetbufReserve (Nbuf
, TCP_MAX_HEAD
);
586 // copy data to the segment.
588 Data
= NetbufAllocSpace (Nbuf
, Len
, NET_BUF_TAIL
);
589 ASSERT (Data
!= NULL
);
591 DataGet
= SockGetDataToSend (Tcb
->Sk
, 0, Len
, Data
);
596 TCPSEG_NETBUF (Nbuf
)->Seq
= Seq
;
597 TCPSEG_NETBUF (Nbuf
)->End
= Seq
+ Len
;
599 InsertTailList (&(Tcb
->SndQue
), &(Nbuf
->List
));
603 SockDataSent (Tcb
->Sk
, DataGet
);
611 Get a segment starting from sequence Seq of a maximum
614 @param Tcb Pointer to the TCP_CB of this TCP instance.
615 @param Seq The sequence number of the segment.
616 @param Len The maximum length of the segment.
618 @return Pointer to the segment, if NULL some error occurred.
630 ASSERT (Tcb
!= NULL
);
633 // Compare the SndNxt with the max sequence number sent.
635 if ((Len
!= 0) && TCP_SEQ_LT (Seq
, TcpGetMaxSndNxt (Tcb
))) {
637 Nbuf
= TcpGetSegmentSndQue (Tcb
, Seq
, Len
);
640 Nbuf
= TcpGetSegmentSock (Tcb
, Seq
, Len
);
643 ASSERT (TcpVerifySegment (Nbuf
) != 0);
649 Retransmit the segment from sequence Seq.
651 @param Tcb Pointer to the TCP_CB of this TCP instance.
652 @param Seq The sequence number of the segment to be retransmitted.
654 @retval 0 Retransmission succeeded.
655 @retval -1 Error condition occurred.
668 // Compute the maxium length of retransmission. It is
669 // limited by three factors:
670 // 1. Less than SndMss
671 // 2. must in the current send window
672 // 3. will not change the boundaries of queued segments.
674 if (TCP_SEQ_LT (Tcb
->SndWl2
+ Tcb
->SndWnd
, Seq
)) {
675 DEBUG ((EFI_D_WARN
, "TcpRetransmit: retransmission cancelled "
676 "because send window too small for TCB %p\n", Tcb
));
681 Len
= TCP_SUB_SEQ (Tcb
->SndWl2
+ Tcb
->SndWnd
, Seq
);
682 Len
= MIN (Len
, Tcb
->SndMss
);
684 Nbuf
= TcpGetSegmentSndQue (Tcb
, Seq
, Len
);
689 ASSERT (TcpVerifySegment (Nbuf
) != 0);
691 if (TcpTransmitSegment (Tcb
, Nbuf
) != 0) {
696 // The retransmitted buffer may be on the SndQue,
697 // trim TCP head because all the buffer on SndQue
700 ASSERT (Nbuf
->Tcp
!= NULL
);
701 NetbufTrim (Nbuf
, (Nbuf
->Tcp
->HeadLen
<< 2), NET_BUF_HEAD
);
717 Check whether to send data/SYN/FIN and piggy back an ACK.
719 @param Tcb Pointer to the TCP_CB of this TCP instance.
720 @param Force Whether to ignore the sender's SWS avoidance algorithm and send
723 @return The number of bytes sent.
740 ASSERT ((Tcb
!= NULL
) && (Tcb
->Sk
!= NULL
) && (Tcb
->State
!= TCP_LISTEN
));
744 if ((Tcb
->State
== TCP_CLOSED
) ||
745 TCP_FLG_ON (Tcb
->CtrlFlag
, TCP_CTRL_FIN_SENT
)) {
752 // compute how much data can be sent
754 Len
= TcpDataToSend (Tcb
, Force
);
757 ASSERT ((Tcb
->State
) < (sizeof (mTcpOutFlag
) / sizeof (mTcpOutFlag
[0])));
758 Flag
= mTcpOutFlag
[Tcb
->State
];
760 if ((Flag
& TCP_FLG_SYN
) != 0) {
767 // only send a segment without data if SYN or
771 ((Flag
& (TCP_FLG_SYN
| TCP_FLG_FIN
)) == 0)) {
775 Nbuf
= TcpGetSegment (Tcb
, Seq
, Len
);
780 "TcpToSendData: failed to get a segment for TCB %p\n",
787 Seg
= TCPSEG_NETBUF (Nbuf
);
790 // Set the TcpSeg in Nbuf.
792 Len
= Nbuf
->TotalSize
;
794 if (TCP_FLG_ON (Flag
, TCP_FLG_SYN
)) {
798 if ((Flag
& TCP_FLG_FIN
) != 0) {
800 // Send FIN if all data is sent, and FIN is
803 if ((TcpGetMaxSndNxt (Tcb
) == Tcb
->SndNxt
) &&
804 (GET_SND_DATASIZE (Tcb
->Sk
) == 0) &&
805 TCP_SEQ_LT (End
+ 1, Tcb
->SndWnd
+ Tcb
->SndWl2
)) {
809 "TcpToSendData: send FIN "
810 "to peer for TCB %p in state %s\n",
812 mTcpStateName
[Tcb
->State
])
817 TCP_CLEAR_FLG (Flag
, TCP_FLG_FIN
);
825 ASSERT (TcpVerifySegment (Nbuf
) != 0);
826 ASSERT (TcpCheckSndQue (&Tcb
->SndQue
) != 0);
829 // don't send an empty segment here.
831 if (Seg
->End
== Seg
->Seq
) {
832 DEBUG ((EFI_D_WARN
, "TcpToSendData: created a empty"
833 " segment for TCB %p, free it now\n", Tcb
));
839 if (TcpTransmitSegment (Tcb
, Nbuf
) != 0) {
840 NetbufTrim (Nbuf
, (Nbuf
->Tcp
->HeadLen
<< 2), NET_BUF_HEAD
);
843 if ((Flag
& TCP_FLG_FIN
) != 0) {
844 TCP_SET_FLG (Tcb
->CtrlFlag
, TCP_CTRL_FIN_SENT
);
850 Sent
+= TCP_SUB_SEQ (End
, Seq
);
853 // All the buffer in the SndQue is headless
855 ASSERT (Nbuf
->Tcp
!= NULL
);
857 NetbufTrim (Nbuf
, (Nbuf
->Tcp
->HeadLen
<< 2), NET_BUF_HEAD
);
863 // update status in TCB
867 if ((Flag
& TCP_FLG_FIN
) != 0) {
868 TCP_SET_FLG (Tcb
->CtrlFlag
, TCP_CTRL_FIN_SENT
);
871 if (TCP_SEQ_GT (End
, Tcb
->SndNxt
)) {
875 if (!TCP_TIMER_ON (Tcb
->EnabledTimer
, TCP_TIMER_REXMIT
)) {
876 TcpSetTimer (Tcb
, TCP_TIMER_REXMIT
, Tcb
->Rto
);
880 // Enable RTT measurement only if not in retransmit.
881 // Karn's algorithm reqires not to update RTT when in loss.
883 if ((Tcb
->CongestState
== TCP_CONGEST_OPEN
) &&
884 !TCP_FLG_ON (Tcb
->CtrlFlag
, TCP_CTRL_RTT_ON
)) {
886 DEBUG ((EFI_D_INFO
, "TcpToSendData: set RTT measure "
887 "sequence %d for TCB %p\n", Seq
, Tcb
));
889 TCP_SET_FLG (Tcb
->CtrlFlag
, TCP_CTRL_RTT_ON
);
894 if (Len
== Tcb
->SndMss
) {
910 Send an ACK immediately.
912 @param Tcb Pointer to the TCP_CB of this TCP instance.
923 Nbuf
= NetbufAlloc (TCP_MAX_HEAD
);
929 NetbufReserve (Nbuf
, TCP_MAX_HEAD
);
931 Seg
= TCPSEG_NETBUF (Nbuf
);
932 Seg
->Seq
= Tcb
->SndNxt
;
933 Seg
->End
= Tcb
->SndNxt
;
934 Seg
->Flag
= TCP_FLG_ACK
;
936 if (TcpTransmitSegment (Tcb
, Nbuf
) == 0) {
937 TCP_CLEAR_FLG (Tcb
->CtrlFlag
, TCP_CTRL_ACK_NOW
);
946 Send a zero probe segment. It can be used by keepalive and zero window probe.
948 @param Tcb Pointer to the TCP_CB of this TCP instance.
950 @retval 0 The zero probe segment was sent out successfully.
951 @retval other Error condition occurred.
963 Nbuf
= NetbufAlloc (TCP_MAX_HEAD
);
969 NetbufReserve (Nbuf
, TCP_MAX_HEAD
);
972 // SndNxt-1 is out of window. The peer should respond
975 Seg
= TCPSEG_NETBUF (Nbuf
);
976 Seg
->Seq
= Tcb
->SndNxt
- 1;
977 Seg
->End
= Tcb
->SndNxt
- 1;
978 Seg
->Flag
= TCP_FLG_ACK
;
980 Result
= TcpTransmitSegment (Tcb
, Nbuf
);
988 Check whether to send an ACK or delayed ACK.
990 @param Tcb Pointer to the TCP_CB of this TCP instance.
1000 TcpNow
= TcpRcvWinNow (Tcb
);
1002 // Generally, TCP should send a delayed ACK unless:
1003 // 1. ACK at least every other FULL sized segment received,
1004 // 2. Packets received out of order
1005 // 3. Receiving window is open
1007 if (TCP_FLG_ON (Tcb
->CtrlFlag
, TCP_CTRL_ACK_NOW
) ||
1008 (Tcb
->DelayedAck
>= 1) ||
1009 (TcpNow
> TcpRcvWinOld (Tcb
))) {
1014 DEBUG ((EFI_D_INFO
, "TcpToSendAck: scheduled a delayed"
1015 " ACK for TCB %p\n", Tcb
));
1018 // schedule a delayed ACK
1025 Send a RESET segment in response to the segment received.
1027 @param Tcb Pointer to the TCP_CB of this TCP instance, may be NULL.
1028 @param Head TCP header of the segment that triggers the reset.
1029 @param Len Length of the segment that triggers the reset.
1030 @param Local Local IP address.
1031 @param Remote Remote peer's IP address.
1033 @retval 0 A reset is sent or no need to send it.
1034 @retval -1 No reset is sent.
1051 // Don't respond to a Reset with reset
1053 if ((Head
->Flag
& TCP_FLG_RST
) != 0) {
1057 Nbuf
= NetbufAlloc (TCP_MAX_HEAD
);
1063 Nhead
= (TCP_HEAD
*) NetbufAllocSpace (
1069 ASSERT (Nhead
!= NULL
);
1072 Nhead
->Flag
= TCP_FLG_RST
;
1075 // Derive Seq/ACK from the segment if no TCB
1076 // associated with it, otherwise from the Tcb
1080 if (TCP_FLG_ON (Head
->Flag
, TCP_FLG_ACK
)) {
1081 Nhead
->Seq
= Head
->Ack
;
1085 TCP_SET_FLG (Nhead
->Flag
, TCP_FLG_ACK
);
1086 Nhead
->Ack
= HTONL (NTOHL (Head
->Seq
) + Len
);
1090 Nhead
->Seq
= HTONL (Tcb
->SndNxt
);
1091 Nhead
->Ack
= HTONL (Tcb
->RcvNxt
);
1092 TCP_SET_FLG (Nhead
->Flag
, TCP_FLG_ACK
);
1095 Nhead
->SrcPort
= Head
->DstPort
;
1096 Nhead
->DstPort
= Head
->SrcPort
;
1097 Nhead
->HeadLen
= (UINT8
) (sizeof (TCP_HEAD
) >> 2);
1099 Nhead
->Wnd
= HTONS (0xFFFF);
1100 Nhead
->Checksum
= 0;
1103 HeadSum
= NetPseudoHeadChecksum (Local
, Remote
, 6, 0);
1104 Nhead
->Checksum
= TcpChecksum (Nbuf
, HeadSum
);
1106 TcpSendIpPacket (Tcb
, Nbuf
, Local
, Remote
);
1114 Verify that the segment is in good shape.
1116 @param Nbuf Buffer that contains the segment to be checked.
1118 @retval 0 The segment is broken.
1119 @retval 1 The segment is in good shape.
1135 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
1137 Seg
= TCPSEG_NETBUF (Nbuf
);
1138 Len
= Nbuf
->TotalSize
;
1142 if (Head
->Flag
!= Seg
->Flag
) {
1146 Len
-= (Head
->HeadLen
<< 2);
1149 if (TCP_FLG_ON (Seg
->Flag
, TCP_FLG_SYN
)) {
1153 if (TCP_FLG_ON (Seg
->Flag
, TCP_FLG_FIN
)) {
1157 if (Seg
->Seq
+ Len
!= Seg
->End
) {
1166 Verify that all the segments in SndQue are in good shape.
1168 @param Head Pointer to the head node of the SndQue.
1170 @retval 0 At least one segment is broken.
1171 @retval 1 All segments in the specific queue are in good shape.
1183 if (IsListEmpty (Head
)) {
1187 // Initialize the Seq
1189 Entry
= Head
->ForwardLink
;
1190 Nbuf
= NET_LIST_USER_STRUCT (Entry
, NET_BUF
, List
);
1191 Seq
= TCPSEG_NETBUF (Nbuf
)->Seq
;
1193 NET_LIST_FOR_EACH (Entry
, Head
) {
1194 Nbuf
= NET_LIST_USER_STRUCT (Entry
, NET_BUF
, List
);
1196 if (TcpVerifySegment (Nbuf
) == 0) {
1201 // All the node in the SndQue should has:
1202 // SEG.SEQ = LAST_SEG.END
1204 if (Seq
!= TCPSEG_NETBUF (Nbuf
)->Seq
) {
1208 Seq
= TCPSEG_NETBUF (Nbuf
)->End
;