12UINT8 mTcpOutFlag[] = {
16 TCP_FLG_SYN | TCP_FLG_ACK,
43 if (TCP_SEQ_GT (Tcb->RcvWl2 + Tcb->RcvWnd, Tcb->RcvNxt)) {
44 OldWin = TCP_SUB_SEQ (
45 Tcb->RcvWl2 + Tcb->RcvWnd,
80 Increase = Win - OldWin;
124 Wnd =
MIN (Wnd >> Tcb->RcvWndScale, 0xffff);
125 return NTOHS ((UINT16)Wnd);
148 Entry = Tcb->SndQue.BackLink;
149 Nbuf = NET_LIST_USER_STRUCT (Entry,
NET_BUF, List);
151 ASSERT (TCP_SEQ_GEQ (TCPSEG_NETBUF (Nbuf)->End, Tcb->SndNxt));
152 return TCPSEG_NETBUF (Nbuf)->End;
188 Limit = Tcb->SndWl2 + Tcb->SndWnd;
190 if (TCP_SEQ_GT (Limit, Tcb->SndUna + Tcb->CWnd)) {
191 Limit = Tcb->SndUna + Tcb->CWnd;
194 if (TCP_SEQ_GT (Limit, Tcb->SndNxt)) {
195 Win = TCP_SUB_SEQ (Limit, Tcb->SndNxt);
206 Len =
MIN (Win, Left);
208 if (Len > Tcb->SndMss) {
212 if ((Force != 0) || ((Len == 0) && (Left == 0))) {
216 if ((Len == 0) && (Left != 0)) {
217 goto SetPersistTimer;
228 if ((Len == Tcb->SndMss) || (2 * Len >= Tcb->SndWndMax)) {
247 "TcpDataToSend: enter persistent state for TCB %p\n",
251 if (!Tcb->ProbeTimerOn) {
282 ASSERT ((Nbuf !=
NULL) && (Nbuf->Tcp ==
NULL));
288 DataLen = Nbuf->TotalSize;
290 Seg = TCPSEG_NETBUF (Nbuf);
291 Syn = TCP_FLG_ON (Seg->
Flag, TCP_FLG_SYN);
299 ASSERT ((Len % 4 == 0) && (Len <= 40));
309 ASSERT (Head !=
NULL);
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);
325 TCP_CLEAR_FLG (Seg->
Flag, TCP_FLG_PSH);
329 TCP_SEQ_BETWEEN (Seg->
Seq, Tcb->SndPsh, Seg->
End)
332 TCP_SET_FLG (Seg->
Flag, TCP_FLG_PSH);
335 TCP_SET_FLG (Seg->
Flag, TCP_FLG_PSH);
342 TCP_CLEAR_FLG (Seg->
Flag, TCP_FLG_URG);
345 TCP_SET_FLG (Seg->
Flag, TCP_FLG_URG);
347 if (TCP_SEQ_LT (Tcb->SndUp, Seg->
End)) {
348 Seg->
Urg = (UINT16)TCP_SUB_SEQ (Tcb->SndUp, Seg->
Seq);
360 Head->Flag = Seg->
Flag;
361 Head->Urg = NTOHS (Seg->
Urg);
367 Tcb->RcvWl2 = Tcb->RcvNxt;
369 Tcb->RcvWnd = NTOHS (Head->Wnd);
377 return TcpSendIpPacket (Tcb, Nbuf, &Tcb->LocalEnd.Ip, &Tcb->RemoteEnd.Ip, Tcb->Sk->IpVersion);
408 ASSERT ((Tcb !=
NULL) && TCP_SEQ_LEQ (Seq, Tcb->SndNxt) && (Len > 0));
418 NET_LIST_FOR_EACH (Cur, Head) {
419 Node = NET_LIST_USER_STRUCT (Cur,
NET_BUF, List);
420 Seg = TCPSEG_NETBUF (Node);
422 if (TCP_SEQ_LT (Seq, Seg->
End) && TCP_SEQ_LEQ (Seg->
Seq, Seq)) {
427 if ((Cur == Head) || (Seg ==
NULL) || (Node ==
NULL)) {
435 if ((Seg->
Seq == Seq) &&
436 TCP_SEQ_LEQ (Seg->
End, Seg->
Seq + Len) &&
437 !NET_BUF_SHARED (Node)
458 if (TCP_SEQ_LT (Seq + Len, Seg->
End)) {
462 CopyLen = TCP_SUB_SEQ (End, Seq);
463 Offset = TCP_SUB_SEQ (Seq, Seg->
Seq);
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);
485 if (Seg->
End == End) {
492 ASSERT (CopyLen >= 0);
499 ASSERT (Data !=
NULL);
501 if ((INT32)
NetbufCopy (Node, Offset, CopyLen, Data) != CopyLen) {
508 TCPSEG_NETBUF (Nbuf)->Seq = Seq;
509 TCPSEG_NETBUF (Nbuf)->End = End;
510 TCPSEG_NETBUF (Nbuf)->Flag = Flag;
540 ASSERT ((Tcb !=
NULL) && (Tcb->Sk !=
NULL));
547 "TcpGetSegmentSock: failed to allocate a netbuf for TCB %p\n",
563 ASSERT (Data !=
NULL);
570 TCPSEG_NETBUF (Nbuf)->Seq = Seq;
571 TCPSEG_NETBUF (Nbuf)->End = Seq + Len;
602 ASSERT (Tcb !=
NULL);
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))))
658 Len = TCP_SUB_SEQ (Tcb->SndNxt, Seq);
661 "TcpRetransmit: retransmission without regard to the receiver window for TCB %p\n",
664 }
else if (TCP_SEQ_GEQ (Tcb->SndWl2 + Tcb->SndWnd, Seq)) {
665 Len = TCP_SUB_SEQ (Tcb->SndWl2 + Tcb->SndWnd, Seq);
669 "TcpRetransmit: retransmission cancelled because send window too small for TCB %p\n",
676 Len =
MIN (Len, Tcb->SndMss);
691 if (TCP_SEQ_GT (Seq, Tcb->RetxmitSeqMax)) {
692 Tcb->RetxmitSeqMax = Seq;
700 ASSERT (Nbuf->Tcp !=
NULL);
701 NetbufTrim (Nbuf, (Nbuf->Tcp->HeadLen << 2), NET_BUF_HEAD);
740 Entry = Head->ForwardLink;
741 Nbuf = NET_LIST_USER_STRUCT (Entry,
NET_BUF, List);
742 Seq = TCPSEG_NETBUF (Nbuf)->Seq;
744 NET_LIST_FOR_EACH (Entry, Head) {
745 Nbuf = NET_LIST_USER_STRUCT (Entry,
NET_BUF, List);
755 if (Seq != TCPSEG_NETBUF (Nbuf)->Seq) {
759 Seq = TCPSEG_NETBUF (Nbuf)->End;
789 ASSERT ((Tcb !=
NULL) && (Tcb->Sk !=
NULL) && (Tcb->State != TCP_LISTEN));
804 ASSERT ((Tcb->State) < (
ARRAY_SIZE (mTcpOutFlag)));
805 Flag = mTcpOutFlag[Tcb->State];
807 if ((Flag & TCP_FLG_SYN) != 0) {
816 if ((Len == 0) && ((Flag & (TCP_FLG_SYN |
TCP_FLG_FIN)) == 0)) {
825 "TcpToSendData: failed to get a segment for TCB %p\n",
832 Seg = TCPSEG_NETBUF (Nbuf);
837 Len = Nbuf->TotalSize;
839 if (TCP_FLG_ON (Flag, TCP_FLG_SYN)) {
850 TCP_SEQ_LT (End + 1, Tcb->SndWnd + Tcb->SndWl2)
855 "TcpToSendData: send FIN to peer for TCB %p in state %s\n",
857 mTcpStateName[Tcb->State])
873 "TcpToSendData: discard a broken segment for TCB %p\n",
882 if (Seg->
End == Seg->
Seq) {
885 "TcpToSendData: created a empty segment for TCB %p, free it now\n",
893 NetbufTrim (Nbuf, (Nbuf->Tcp->HeadLen << 2), NET_BUF_HEAD);
903 Sent += TCP_SUB_SEQ (End, Seq);
908 ASSERT (Nbuf->Tcp !=
NULL);
910 NetbufTrim (Nbuf, (Nbuf->Tcp->HeadLen << 2), NET_BUF_HEAD);
924 if (TCP_SEQ_GT (End, Tcb->SndNxt)) {
939 "TcpToSendData: set RTT measure sequence %d for TCB %p\n",
948 }
while (Len == Tcb->SndMss);
982 Seg = TCPSEG_NETBUF (Nbuf);
983 Seg->
Seq = Tcb->SndNxt;
984 Seg->
End = Tcb->SndNxt;
985 Seg->
Flag = TCP_FLG_ACK;
1025 Seg = TCPSEG_NETBUF (Nbuf);
1026 Seg->
Seq = Tcb->SndNxt - 1;
1027 Seg->
End = Tcb->SndNxt - 1;
1028 Seg->
Flag = TCP_FLG_ACK;
1055 if (TCP_FLG_ON (Tcb->CtrlFlag,
TCP_CTRL_ACK_NOW) || (Tcb->DelayedAck >= 1)) {
1069 "TcpToSendAck: scheduled a delayed ACK for TCB %p\n",
1111 if ((Head->Flag & TCP_FLG_RST) != 0) {
1127 ASSERT (Nhead !=
NULL);
1130 Nhead->Flag = TCP_FLG_RST;
1137 if (TCP_FLG_ON (Head->Flag, TCP_FLG_ACK)) {
1138 Nhead->Seq = Head->Ack;
1142 TCP_SET_FLG (Nhead->Flag, TCP_FLG_ACK);
1143 Nhead->Ack = HTONL (NTOHL (Head->Seq) + Len);
1146 Nhead->Seq = HTONL (Tcb->SndNxt);
1147 Nhead->Ack = HTONL (Tcb->RcvNxt);
1148 TCP_SET_FLG (Nhead->Flag, TCP_FLG_ACK);
1151 Nhead->SrcPort = Head->DstPort;
1152 Nhead->DstPort = Head->SrcPort;
1153 Nhead->HeadLen = (UINT8)(
sizeof (
TCP_HEAD) >> 2);
1155 Nhead->Wnd = HTONS (0xFFFF);
1156 Nhead->Checksum = 0;
1159 if (Version == IP_VERSION_4) {
1196 NET_CHECK_SIGNATURE (Nbuf, NET_BUF_SIGNATURE);
1198 Seg = TCPSEG_NETBUF (Nbuf);
1199 Len = Nbuf->TotalSize;
1203 if (Head->Flag != Seg->
Flag) {
1207 Len -= (Head->HeadLen << 2);
1210 if (TCP_FLG_ON (Seg->
Flag, TCP_FLG_SYN)) {
1218 if (Seg->
Seq + Len != Seg->
End) {
BOOLEAN EFIAPI IsListEmpty(IN CONST LIST_ENTRY *ListHead)
LIST_ENTRY *EFIAPI InsertTailList(IN OUT LIST_ENTRY *ListHead, IN OUT LIST_ENTRY *Entry)
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
#define ARRAY_SIZE(Array)
#define DEBUG(Expression)
VOID EFIAPI NetbufFree(IN NET_BUF *Nbuf)
VOID EFIAPI NetbufReserve(IN OUT NET_BUF *Nbuf, IN UINT32 Len)
UINT16 EFIAPI NetIp6PseudoHeadChecksum(IN EFI_IPv6_ADDRESS *Src, IN EFI_IPv6_ADDRESS *Dst, IN UINT8 NextHeader, IN UINT32 Len)
UINT32 EFIAPI NetbufTrim(IN OUT NET_BUF *Nbuf, IN UINT32 Len, IN BOOLEAN FromHead)
UINT32 EFIAPI NetbufCopy(IN NET_BUF *Nbuf, IN UINT32 Offset, IN UINT32 Len, IN UINT8 *Dest)
NET_BUF *EFIAPI NetbufAlloc(IN UINT32 Len)
UINT8 *EFIAPI NetbufAllocSpace(IN OUT NET_BUF *Nbuf, IN UINT32 Len, IN BOOLEAN FromHead)
UINT16 EFIAPI NetPseudoHeadChecksum(IN IP4_ADDR Src, IN IP4_ADDR Dst, IN UINT8 Proto, IN UINT16 Len)
UINT32 SockGetFreeSpace(IN SOCKET *Sock, IN UINT32 Which)
#define GET_SND_DATASIZE(Sock)
UINT32 SockGetDataToSend(IN SOCKET *Sock, IN UINT32 Offset, IN UINT32 Len, OUT UINT8 *Dest)
#define GET_RCV_BUFFSIZE(Sock)
VOID SockDataSent(IN OUT SOCKET *Sock, IN UINT32 Count)
VOID TcpSetProbeTimer(IN OUT TCP_CB *Tcb)
VOID TcpSetTimer(IN OUT TCP_CB *Tcb, IN UINT16 Timer, IN UINT32 TimeOut)
INTN TcpSendIpPacket(IN TCP_CB *Tcb, IN NET_BUF *Nbuf, IN EFI_IP_ADDRESS *Src, IN EFI_IP_ADDRESS *Dest, IN UINT8 Version)
UINT16 TcpChecksum(IN NET_BUF *Nbuf, IN UINT16 HeadSum)
UINT16 TcpBuildOption(IN TCP_CB *Tcb, IN NET_BUF *Nbuf)
UINT16 TcpSynBuildOption(IN TCP_CB *Tcb, IN NET_BUF *Nbuf)
INTN TcpRetransmit(IN TCP_CB *Tcb, IN TCP_SEQNO Seq)
INTN TcpVerifySegment(IN NET_BUF *Nbuf)
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)
INTN TcpToSendData(IN OUT TCP_CB *Tcb, IN INTN Force)
UINT32 TcpRcvWinNow(IN TCP_CB *Tcb)
INTN TcpCheckSndQue(IN LIST_ENTRY *Head)
UINT32 TcpRcvWinOld(IN TCP_CB *Tcb)
NET_BUF * TcpGetSegment(IN TCP_CB *Tcb, IN TCP_SEQNO Seq, IN UINT32 Len)
NET_BUF * TcpGetSegmentSndQue(IN TCP_CB *Tcb, IN TCP_SEQNO Seq, IN UINT32 Len)
NET_BUF * TcpGetSegmentSock(IN TCP_CB *Tcb, IN TCP_SEQNO Seq, IN UINT32 Len)
INTN TcpSendZeroProbe(IN OUT TCP_CB *Tcb)
INTN TcpTransmitSegment(IN OUT TCP_CB *Tcb, IN NET_BUF *Nbuf)
VOID TcpSendAck(IN OUT TCP_CB *Tcb)
UINT16 TcpComputeWnd(IN OUT TCP_CB *Tcb, IN BOOLEAN Syn)
UINT32 TcpDataToSend(IN TCP_CB *Tcb, IN INTN Force)
TCP_SEQNO TcpGetMaxSndNxt(IN TCP_CB *Tcb)
VOID TcpToSendAck(IN OUT TCP_CB *Tcb)
#define TCP_CTRL_NO_NAGLE
Disable Nagle algorithm.
#define TCP_TIMER_REXMIT
Retransmit timer.
#define TCP_CTRL_FIN_SENT
FIN is sent.
#define TCP_CTRL_SND_PSH
In PUSH send mode.
#define TCP_CTRL_RTT_ON
The RTT measurement is on.
#define TCP_CTRL_SND_URG
In urgent send mode.
#define TCP_CTRL_ACK_NOW
Send the ACK now, don't delay.
#define TCP_CONGEST_OPEN
TCP is opening its congestion window.
TCP_SEQNO Seq
Starting sequence number.
TCP_SEQNO End
The sequence of the last byte + 1, include SYN/FIN. End-Seq = SEG.LEN.
UINT8 Flag
TCP header flags.
UINT16 Urg
Valid if URG flag is set.