]>
git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Output.c
f1bc83e20bd89eb6518e99623809f17485231bf0
3 Copyright (c) 2005 - 2006, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 TCP output process routines.
25 STATIC UINT8 mTcpOutFlag
[] = {
28 TCP_FLG_SYN
, // TCP_SYN_SENT
29 TCP_FLG_SYN
| TCP_FLG_ACK
, // TCP_SYN_RCVD
30 TCP_FLG_ACK
, // TCP_ESTABLISHED
31 TCP_FLG_FIN
| TCP_FLG_ACK
, // TCP_FIN_WAIT_1
32 TCP_FLG_ACK
, // TCP_FIN_WAIT_2
33 TCP_FLG_ACK
| TCP_FLG_FIN
, // TCP_CLOSING
34 TCP_FLG_ACK
, // TCP_TIME_WAIT
35 TCP_FLG_ACK
, // TCP_CLOSE_WAIT
36 TCP_FLG_FIN
| TCP_FLG_ACK
// TCP_LAST_ACK
41 Compute the sequence space left in the old receive window.
43 @param Tcb Pointer to the TCP_CB of this TCP instance.
45 @return The sequence space left in the old receive window.
57 if (TCP_SEQ_GT (Tcb
->RcvWl2
+ Tcb
->RcvWnd
, Tcb
->RcvNxt
)) {
59 OldWin
= TCP_SUB_SEQ (
60 Tcb
->RcvWl2
+ Tcb
->RcvWnd
,
70 Compute the current receive window.
72 @param Tcb Pointer to the TCP_CB of this TCP instance.
74 @return The size of the current receive window, in bytes.
90 OldWin
= TcpRcvWinOld (Tcb
);
92 Win
= SockGetFreeSpace (Sk
, SOCK_RCV_BUF
);
96 Increase
= Win
- OldWin
;
100 // Receiver's SWS: don't advertise a bigger window
101 // unless it can be increased by at least one Mss or
102 // half of the receive buffer.
104 if ((Increase
> Tcb
->SndMss
) ||
105 (2 * Increase
>= GET_RCV_BUFFSIZE (Sk
))) {
115 Compute the value to fill in the window size field
116 of the outgoing segment.
118 @param Tcb Pointer to the TCP_CB of this TCP instance.
119 @param Syn The flag to indicate whether the outgoing segment is a SYN
122 @return The value of the local receive window size used to fill the outing segment.
135 // RFC requires that initial window not be scaled
139 Wnd
= GET_RCV_BUFFSIZE (Tcb
->Sk
);
142 Wnd
= TcpRcvWinNow (Tcb
);
147 Wnd
= MIN (Wnd
>> Tcb
->RcvWndScale
, 0xffff);
148 return NTOHS ((UINT16
) Wnd
);
153 Get the maximum SndNxt.
155 @param Tcb Pointer to the TCP_CB of this TCP instance.
157 @return The sequence number of the maximum SndNxt.
168 if (IsListEmpty (&Tcb
->SndQue
)) {
172 Entry
= Tcb
->SndQue
.BackLink
;
173 Nbuf
= NET_LIST_USER_STRUCT (Entry
, NET_BUF
, List
);
175 ASSERT (TCP_SEQ_GEQ (TCPSEG_NETBUF (Nbuf
)->End
, Tcb
->SndNxt
));
176 return TCPSEG_NETBUF (Nbuf
)->End
;
181 Compute how much data to send.
183 @param Tcb Pointer to the TCP_CB of this TCP instance.
184 @param Force Whether to ignore the sender's SWS avoidance algorithm and send
187 @return The length of the data can be sent, if 0, no data can be sent.
206 // TCP should NOT send data beyond the send window
207 // and congestion window. The right edge of send
208 // window is defined as SND.WL2 + SND.WND. The right
209 // edge of congestion window is defined as SND.UNA +
213 Limit
= Tcb
->SndWl2
+ Tcb
->SndWnd
;
215 if (TCP_SEQ_GT (Limit
, Tcb
->SndUna
+ Tcb
->CWnd
)) {
217 Limit
= Tcb
->SndUna
+ Tcb
->CWnd
;
220 if (TCP_SEQ_GT (Limit
, Tcb
->SndNxt
)) {
221 Win
= TCP_SUB_SEQ (Limit
, Tcb
->SndNxt
);
225 // The data to send contains two parts: the data on the
226 // socket send queue, and the data on the TCB's send
227 // buffer. The later can be non-zero if the peer shrinks
228 // its advertised window.
230 Left
= GET_SND_DATASIZE (Sk
) +
231 TCP_SUB_SEQ (TcpGetMaxSndNxt (Tcb
), Tcb
->SndNxt
);
233 Len
= MIN (Win
, Left
);
235 if (Len
> Tcb
->SndMss
) {
239 if (Force
|| (Len
== 0 && Left
== 0)) {
243 if (Len
== 0 && Left
!= 0) {
244 goto SetPersistTimer
;
248 // Sender's SWS avoidance: Don't send a small segment unless
249 // a)A full-sized segment can be sent,
250 // b)at least one-half of the maximum sized windows that
251 // the other end has ever advertised.
252 // c)It can send everything it has and either it isn't
253 // expecting an ACK or the Nagle algorithm is disabled.
255 if ((Len
== Tcb
->SndMss
) || (2 * Len
>= Tcb
->SndWndMax
)) {
261 ((Tcb
->SndNxt
== Tcb
->SndUna
) ||
262 TCP_FLG_ON (Tcb
->CtrlFlag
, TCP_CTRL_NO_NAGLE
))) {
268 // RFC1122 suggests to set a timer when SWSA forbids TCP
269 // sending more data, and combine it with probe timer.
272 if (!TCP_TIMER_ON (Tcb
->EnabledTimer
, TCP_TIMER_REXMIT
)) {
276 "TcpDataToSend: enter persistent state for TCB %p\n",
280 TcpSetProbeTimer (Tcb
);
288 Build the TCP header of the TCP segment and transmit the
291 @param Tcb Pointer to the TCP_CB of this TCP instance.
292 @param Nbuf Pointer to the buffer containing the segment to be sent out.
294 @retval 0 The segment is sent out successfully.
295 @retval other Error condition occurred.
311 ASSERT (Nbuf
&& (Nbuf
->Tcp
== NULL
) && TcpVerifySegment (Nbuf
));
313 DataLen
= Nbuf
->TotalSize
;
315 Seg
= TCPSEG_NETBUF (Nbuf
);
316 Syn
= TCP_FLG_ON (Seg
->Flag
, TCP_FLG_SYN
);
320 Len
= TcpSynBuildOption (Tcb
, Nbuf
);
323 Len
= TcpBuildOption (Tcb
, Nbuf
);
326 ASSERT ((Len
% 4 == 0) && (Len
<= 40));
328 Len
+= sizeof (TCP_HEAD
);
330 Head
= (TCP_HEAD
*) NetbufAllocSpace (
336 ASSERT (Head
!= NULL
);
340 Head
->SrcPort
= Tcb
->LocalEnd
.Port
;
341 Head
->DstPort
= Tcb
->RemoteEnd
.Port
;
342 Head
->Seq
= NTOHL (Seg
->Seq
);
343 Head
->Ack
= NTOHL (Tcb
->RcvNxt
);
344 Head
->HeadLen
= (UINT8
) (Len
>> 2);
346 Head
->Wnd
= TcpComputeWnd (Tcb
, Syn
);
350 // Check whether to set the PSH flag.
352 TCP_CLEAR_FLG (Seg
->Flag
, TCP_FLG_PSH
);
355 if (TCP_FLG_ON (Tcb
->CtrlFlag
, TCP_CTRL_SND_PSH
) &&
356 TCP_SEQ_BETWEEN (Seg
->Seq
, Tcb
->SndPsh
, Seg
->End
)) {
358 TCP_SET_FLG (Seg
->Flag
, TCP_FLG_PSH
);
359 TCP_CLEAR_FLG (Tcb
->CtrlFlag
, TCP_CTRL_SND_PSH
);
361 } else if ((Seg
->End
== Tcb
->SndNxt
) &&
362 (GET_SND_DATASIZE (Tcb
->Sk
) == 0)) {
364 TCP_SET_FLG (Seg
->Flag
, TCP_FLG_PSH
);
369 // Check whether to set the URG flag and the urgent pointer.
371 TCP_CLEAR_FLG (Seg
->Flag
, TCP_FLG_URG
);
373 if (TCP_FLG_ON (Tcb
->CtrlFlag
, TCP_CTRL_SND_URG
) &&
374 TCP_SEQ_LEQ (Seg
->Seq
, Tcb
->SndUp
)) {
376 TCP_SET_FLG (Seg
->Flag
, TCP_FLG_URG
);
378 if (TCP_SEQ_LT (Tcb
->SndUp
, Seg
->End
)) {
380 Seg
->Urg
= (UINT16
) TCP_SUB_SEQ (Tcb
->SndUp
, Seg
->Seq
);
383 Seg
->Urg
= (UINT16
) MIN (
384 TCP_SUB_SEQ (Tcb
->SndUp
,
391 Head
->Flag
= Seg
->Flag
;
392 Head
->Urg
= NTOHS (Seg
->Urg
);
393 Head
->Checksum
= TcpChecksum (Nbuf
, Tcb
->HeadSum
);
396 // update the TCP session's control information
398 Tcb
->RcvWl2
= Tcb
->RcvNxt
;
400 Tcb
->RcvWnd
= NTOHS (Head
->Wnd
);
404 // clear delayedack flag
408 return TcpSendIpPacket (Tcb
, Nbuf
, Tcb
->LocalEnd
.Ip
, Tcb
->RemoteEnd
.Ip
);
413 Get a segment from the Tcb's SndQue.
415 @param Tcb Pointer to the TCP_CB of this TCP instance.
416 @param Seq The sequence number of the segment.
417 @param Len The maximum length of the segment.
419 @return Pointer to the segment, if NULL some error occurred.
423 TcpGetSegmentSndQue (
440 ASSERT (Tcb
&& TCP_SEQ_LEQ (Seq
, Tcb
->SndNxt
) && (Len
> 0));
443 // Find the segment that contains the Seq.
450 NET_LIST_FOR_EACH (Cur
, Head
) {
451 Node
= NET_LIST_USER_STRUCT (Cur
, NET_BUF
, List
);
452 Seg
= TCPSEG_NETBUF (Node
);
454 if (TCP_SEQ_LT (Seq
, Seg
->End
) && TCP_SEQ_LEQ (Seg
->Seq
, Seq
)) {
460 ASSERT (Cur
!= Head
);
463 // Return the buffer if it can be returned without
466 if ((Seg
->Seq
== Seq
) &&
467 TCP_SEQ_LEQ (Seg
->End
, Seg
->Seq
+ Len
) &&
468 !NET_BUF_SHARED (Node
)) {
475 // Create a new buffer and copy data there.
477 Nbuf
= NetbufAlloc (Len
+ TCP_MAX_HEAD
);
483 NetbufReserve (Nbuf
, TCP_MAX_HEAD
);
488 if (TCP_SEQ_LT (Seq
+ Len
, Seg
->End
)) {
492 CopyLen
= TCP_SUB_SEQ (End
, Seq
);
493 Offset
= TCP_SUB_SEQ (Seq
, Seg
->Seq
);
496 // If SYN is set and out of the range, clear the flag.
497 // Becuase the sequence of the first byte is SEG.SEQ+1,
498 // adjust Offset by -1. If SYN is in the range, copy
501 if (TCP_FLG_ON (Seg
->Flag
, TCP_FLG_SYN
)) {
503 if (TCP_SEQ_LT (Seg
->Seq
, Seq
)) {
505 TCP_CLEAR_FLG (Flag
, TCP_FLG_SYN
);
514 // If FIN is set and in the range, copy one byte less,
515 // and if it is out of the range, clear the flag.
517 if (TCP_FLG_ON (Seg
->Flag
, TCP_FLG_FIN
)) {
519 if (Seg
->End
== End
) {
524 TCP_CLEAR_FLG (Flag
, TCP_FLG_FIN
);
528 ASSERT (CopyLen
>= 0);
531 // copy data to the segment
534 Data
= NetbufAllocSpace (Nbuf
, CopyLen
, NET_BUF_TAIL
);
537 if ((INT32
) NetbufCopy (Node
, Offset
, CopyLen
, Data
) != CopyLen
) {
542 CopyMem (TCPSEG_NETBUF (Nbuf
), Seg
, sizeof (TCP_SEG
));
544 TCPSEG_NETBUF (Nbuf
)->Seq
= Seq
;
545 TCPSEG_NETBUF (Nbuf
)->End
= End
;
546 TCPSEG_NETBUF (Nbuf
)->Flag
= Flag
;
557 Get a segment from the Tcb's socket buffer.
559 @param Tcb Pointer to the TCP_CB of this TCP instance.
560 @param Seq The sequence number of the segment.
561 @param Len The maximum length of the segment.
563 @return Pointer to the segment, if NULL some error occurred.
577 ASSERT (Tcb
&& Tcb
->Sk
);
579 Nbuf
= NetbufAlloc (Len
+ TCP_MAX_HEAD
);
582 DEBUG ((EFI_D_ERROR
, "TcpGetSegmentSock: failed to allocate "
583 "a netbuf for TCB %p\n",Tcb
));
588 NetbufReserve (Nbuf
, TCP_MAX_HEAD
);
594 // copy data to the segment.
596 Data
= NetbufAllocSpace (Nbuf
, Len
, NET_BUF_TAIL
);
599 DataGet
= SockGetDataToSend (Tcb
->Sk
, 0, Len
, Data
);
604 TCPSEG_NETBUF (Nbuf
)->Seq
= Seq
;
605 TCPSEG_NETBUF (Nbuf
)->End
= Seq
+ Len
;
607 InsertTailList (&(Tcb
->SndQue
), &(Nbuf
->List
));
611 SockDataSent (Tcb
->Sk
, DataGet
);
619 Get a segment starting from sequence Seq of a maximum
622 @param Tcb Pointer to the TCP_CB of this TCP instance.
623 @param Seq The sequence number of the segment.
624 @param Len The maximum length of the segment.
626 @return Pointer to the segment, if NULL some error occurred.
641 // Compare the SndNxt with the max sequence number sent.
643 if ((Len
!= 0) && TCP_SEQ_LT (Seq
, TcpGetMaxSndNxt (Tcb
))) {
645 Nbuf
= TcpGetSegmentSndQue (Tcb
, Seq
, Len
);
648 Nbuf
= TcpGetSegmentSock (Tcb
, Seq
, Len
);
651 ASSERT (TcpVerifySegment (Nbuf
));
657 Retransmit the segment from sequence Seq.
659 @param Tcb Pointer to the TCP_CB of this TCP instance.
660 @param Seq The sequence number of the segment to be retransmitted.
662 @retval 0 Retransmission succeeded.
663 @retval -1 Error condition occurred.
676 // Compute the maxium length of retransmission. It is
677 // limited by three factors:
678 // 1. Less than SndMss
679 // 2. must in the current send window
680 // 3. will not change the boundaries of queued segments.
682 if (TCP_SEQ_LT (Tcb
->SndWl2
+ Tcb
->SndWnd
, Seq
)) {
683 DEBUG ((EFI_D_WARN
, "TcpRetransmit: retransmission cancelled "
684 "because send window too small for TCB %p\n", Tcb
));
689 Len
= TCP_SUB_SEQ (Tcb
->SndWl2
+ Tcb
->SndWnd
, Seq
);
690 Len
= MIN (Len
, Tcb
->SndMss
);
692 Nbuf
= TcpGetSegmentSndQue (Tcb
, Seq
, Len
);
697 ASSERT (TcpVerifySegment (Nbuf
));
699 if (TcpTransmitSegment (Tcb
, Nbuf
) != 0) {
704 // The retransmitted buffer may be on the SndQue,
705 // trim TCP head because all the buffer on SndQue
709 NetbufTrim (Nbuf
, (Nbuf
->Tcp
->HeadLen
<< 2), NET_BUF_HEAD
);
725 Check whether to send data/SYN/FIN and piggy back an ACK.
727 @param Tcb Pointer to the TCP_CB of this TCP instance.
728 @param Force Whether to ignore the sender's SWS avoidance algorithm and send
731 @return The number of bytes sent.
748 ASSERT (Tcb
&& Tcb
->Sk
&& (Tcb
->State
!= TCP_LISTEN
));
752 if ((Tcb
->State
== TCP_CLOSED
) ||
753 TCP_FLG_ON (Tcb
->CtrlFlag
, TCP_CTRL_FIN_SENT
)) {
760 // compute how much data can be sent
762 Len
= TcpDataToSend (Tcb
, Force
);
765 Flag
= mTcpOutFlag
[Tcb
->State
];
767 if (Flag
& TCP_FLG_SYN
) {
774 // only send a segment without data if SYN or
777 if ((Len
== 0) && !(Flag
& (TCP_FLG_SYN
| TCP_FLG_FIN
))) {
781 Nbuf
= TcpGetSegment (Tcb
, Seq
, Len
);
786 "TcpToSendData: failed to get a segment for TCB %p\n",
793 Seg
= TCPSEG_NETBUF (Nbuf
);
796 // Set the TcpSeg in Nbuf.
798 Len
= Nbuf
->TotalSize
;
800 if (TCP_FLG_ON (Flag
, TCP_FLG_SYN
)) {
804 if (Flag
& TCP_FLG_FIN
) {
806 // Send FIN if all data is sent, and FIN is
809 if ((TcpGetMaxSndNxt (Tcb
) == Tcb
->SndNxt
) &&
810 (GET_SND_DATASIZE (Tcb
->Sk
) == 0) &&
811 TCP_SEQ_LT (End
+ 1, Tcb
->SndWnd
+ Tcb
->SndWl2
)
814 DEBUG ((EFI_D_INFO
, "TcpToSendData: send FIN "
815 "to peer for TCB %p in state %d\n", Tcb
, Tcb
->State
));
819 TCP_CLEAR_FLG (Flag
, TCP_FLG_FIN
);
827 ASSERT (TcpVerifySegment (Nbuf
));
828 ASSERT (TcpCheckSndQue (&Tcb
->SndQue
));
831 // don't send an empty segment here.
833 if (Seg
->End
== Seg
->Seq
) {
834 DEBUG ((EFI_D_WARN
, "TcpToSendData: created a empty"
835 " segment for TCB %p, free it now\n", Tcb
));
841 if (TcpTransmitSegment (Tcb
, Nbuf
) != 0) {
843 // TODO: double check this
845 NetbufTrim (Nbuf
, (Nbuf
->Tcp
->HeadLen
<< 2), NET_BUF_HEAD
);
848 if (Flag
& TCP_FLG_FIN
) {
849 TCP_SET_FLG (Tcb
->CtrlFlag
, TCP_CTRL_FIN_SENT
);
855 Sent
+= TCP_SUB_SEQ (End
, Seq
);
858 // All the buffer in the SndQue is headless
862 NetbufTrim (Nbuf
, (Nbuf
->Tcp
->HeadLen
<< 2), NET_BUF_HEAD
);
868 // update status in TCB
872 if (Flag
& TCP_FLG_FIN
) {
873 TCP_SET_FLG (Tcb
->CtrlFlag
, TCP_CTRL_FIN_SENT
);
876 if (TCP_SEQ_GT (End
, Tcb
->SndNxt
)) {
880 if (!TCP_TIMER_ON (Tcb
->EnabledTimer
, TCP_TIMER_REXMIT
)) {
881 TcpSetTimer (Tcb
, TCP_TIMER_REXMIT
, Tcb
->Rto
);
885 // Enable RTT measurement only if not in retransmit.
886 // Karn's algorithm reqires not to update RTT when in loss.
888 if ((Tcb
->CongestState
== TCP_CONGEST_OPEN
) &&
889 !TCP_FLG_ON (Tcb
->CtrlFlag
, TCP_CTRL_RTT_ON
)) {
891 DEBUG ((EFI_D_INFO
, "TcpToSendData: set RTT measure "
892 "sequence %d for TCB %p\n", Seq
, Tcb
));
894 TCP_SET_FLG (Tcb
->CtrlFlag
, TCP_CTRL_RTT_ON
);
899 if (Len
== Tcb
->SndMss
) {
915 Send an ACK immediately.
917 @param Tcb Pointer to the TCP_CB of this TCP instance.
930 Nbuf
= NetbufAlloc (TCP_MAX_HEAD
);
936 NetbufReserve (Nbuf
, TCP_MAX_HEAD
);
938 Seg
= TCPSEG_NETBUF (Nbuf
);
939 Seg
->Seq
= Tcb
->SndNxt
;
940 Seg
->End
= Tcb
->SndNxt
;
941 Seg
->Flag
= TCP_FLG_ACK
;
943 if (TcpTransmitSegment (Tcb
, Nbuf
) == 0) {
944 TCP_CLEAR_FLG (Tcb
->CtrlFlag
, TCP_CTRL_ACK_NOW
);
953 Send a zero probe segment. It can be used by keepalive
954 and zero window probe.
956 @param Tcb Pointer to the TCP_CB of this TCP instance.
958 @retval 0 The zero probe segment was sent out successfully.
959 @retval other Error condition occurred.
971 Nbuf
= NetbufAlloc (TCP_MAX_HEAD
);
977 NetbufReserve (Nbuf
, TCP_MAX_HEAD
);
980 // SndNxt-1 is out of window. The peer should respond
983 Seg
= TCPSEG_NETBUF (Nbuf
);
984 Seg
->Seq
= Tcb
->SndNxt
- 1;
985 Seg
->End
= Tcb
->SndNxt
- 1;
986 Seg
->Flag
= TCP_FLG_ACK
;
988 Result
= TcpTransmitSegment (Tcb
, Nbuf
);
996 Check whether to send an ACK or delayed ACK.
998 @param Tcb Pointer to the TCP_CB of this TCP instance.
1010 TcpNow
= TcpRcvWinNow (Tcb
);
1012 // Generally, TCP should send a delayed ACK unless:
1013 // 1. ACK at least every other FULL sized segment received,
1014 // 2. Packets received out of order
1015 // 3. Receiving window is open
1017 if (TCP_FLG_ON (Tcb
->CtrlFlag
, TCP_CTRL_ACK_NOW
) ||
1018 (Tcb
->DelayedAck
>= 1) ||
1019 (TcpNow
> TcpRcvWinOld (Tcb
))
1025 DEBUG ((EFI_D_INFO
, "TcpToSendAck: scheduled a delayed"
1026 " ACK for TCB %p\n", Tcb
));
1029 // schedule a delayed ACK
1036 Send a RESET segment in response to the segment received.
1038 @param Tcb Pointer to the TCP_CB of this TCP instance, may be NULL.
1039 @param Head TCP header of the segment that triggers the reset.
1040 @param Len Length of the segment that triggers the reset.
1041 @param Local Local IP address.
1042 @param Remote Remote peer's IP address.
1044 @retval 0 A reset is sent or no need to send it.
1045 @retval -1 No reset is sent.
1062 // Don't respond to a Reset with reset
1064 if (Head
->Flag
& TCP_FLG_RST
) {
1068 Nbuf
= NetbufAlloc (TCP_MAX_HEAD
);
1074 Nhead
= (TCP_HEAD
*) NetbufAllocSpace (
1080 ASSERT (Nhead
!= NULL
);
1083 Nhead
->Flag
= TCP_FLG_RST
;
1086 // Derive Seq/ACK from the segment if no TCB
1087 // associated with it, otherwise from the Tcb
1091 if (TCP_FLG_ON (Head
->Flag
, TCP_FLG_ACK
)) {
1092 Nhead
->Seq
= Head
->Ack
;
1096 TCP_SET_FLG (Nhead
->Flag
, TCP_FLG_ACK
);
1097 Nhead
->Ack
= HTONL (NTOHL (Head
->Seq
) + Len
);
1101 Nhead
->Seq
= HTONL (Tcb
->SndNxt
);
1102 Nhead
->Ack
= HTONL (Tcb
->RcvNxt
);
1103 TCP_SET_FLG (Nhead
->Flag
, TCP_FLG_ACK
);
1106 Nhead
->SrcPort
= Head
->DstPort
;
1107 Nhead
->DstPort
= Head
->SrcPort
;
1108 Nhead
->HeadLen
= (sizeof (TCP_HEAD
) >> 2);
1110 Nhead
->Wnd
= HTONS (0xFFFF);
1111 Nhead
->Checksum
= 0;
1114 HeadSum
= NetPseudoHeadChecksum (Local
, Remote
, 6, 0);
1115 Nhead
->Checksum
= TcpChecksum (Nbuf
, HeadSum
);
1117 TcpSendIpPacket (Tcb
, Nbuf
, Local
, Remote
);
1125 Verify that the segment is in good shape.
1127 @param Nbuf Buffer that contains the segment to be checked.
1129 @retval 0 The segment is broken.
1130 @retval 1 The segment is in good shape.
1146 NET_CHECK_SIGNATURE (Nbuf
, NET_BUF_SIGNATURE
);
1148 Seg
= TCPSEG_NETBUF (Nbuf
);
1149 Len
= Nbuf
->TotalSize
;
1153 if (Head
->Flag
!= Seg
->Flag
) {
1157 Len
-= (Head
->HeadLen
<< 2);
1160 if (TCP_FLG_ON (Seg
->Flag
, TCP_FLG_SYN
)) {
1164 if (TCP_FLG_ON (Seg
->Flag
, TCP_FLG_FIN
)) {
1168 if (Seg
->Seq
+ Len
!= Seg
->End
) {
1177 Verify that all the segments in SndQue are in good shape.
1179 @param Head Pointer to the head node of the SndQue.
1181 @retval 0 At least one segment is broken.
1182 @retval 1 All segments in the specific queue are in good shape.
1194 if (IsListEmpty (Head
)) {
1198 // Initialize the Seq
1200 Entry
= Head
->ForwardLink
;
1201 Nbuf
= NET_LIST_USER_STRUCT (Entry
, NET_BUF
, List
);
1202 Seq
= TCPSEG_NETBUF (Nbuf
)->Seq
;
1204 NET_LIST_FOR_EACH (Entry
, Head
) {
1205 Nbuf
= NET_LIST_USER_STRUCT (Entry
, NET_BUF
, List
);
1207 if (TcpVerifySegment (Nbuf
) == 0) {
1212 // All the node in the SndQue should has:
1213 // SEG.SEQ = LAST_SEG.END
1215 if (Seq
!= TCPSEG_NETBUF (Nbuf
)->Seq
) {
1219 Seq
= TCPSEG_NETBUF (Nbuf
)->End
;