28 return (TCP_SEQ_LEQ (Tcb->RcvNxt, Seg->End) &&
29 TCP_SEQ_LT (Seg->Seq, Tcb->RcvWl2 + Tcb->RcvWnd));
55 FlightSize = TCP_SUB_SEQ (Tcb->SndNxt, Tcb->SndUna);
57 Tcb->Ssthresh =
MAX (FlightSize >> 1, (UINT32)(2 * Tcb->SndMss));
58 Tcb->Recover = Tcb->SndNxt;
67 Tcb->CWnd = Tcb->Ssthresh + 3 * Tcb->SndMss;
71 "TcpFastRecover: enter fast retransmission for TCB %p, recover point is %d\n",
81 if (Seg->Ack == Tcb->SndUna) {
90 Tcb->CWnd += Tcb->SndMss;
93 "TcpFastRecover: received another duplicated ACK (%d) for TCB %p\n",
102 if (TCP_SEQ_GEQ (Seg->Ack, Tcb->Recover)) {
107 FlightSize = TCP_SUB_SEQ (Tcb->SndNxt, Tcb->SndUna);
109 Tcb->CWnd =
MIN (Tcb->Ssthresh, FlightSize + Tcb->SndMss);
114 "TcpFastRecover: received a full ACK(%d) for TCB %p, exit fast recovery\n",
125 Acked = TCP_SUB_SEQ (Seg->Ack, Tcb->SndUna);
132 if (Acked >= Tcb->SndMss) {
133 Acked -= Tcb->SndMss;
140 "TcpFastRecover: received a partial ACK(%d) for TCB %p\n",
161 if (TCP_SEQ_GT (Seg->Ack, Tcb->SndUna)) {
166 if (TCP_SEQ_GEQ (Seg->Ack, Tcb->LossRecover)) {
175 "TcpFastLossRecover: received a full ACK(%d) for TCB %p\n",
187 "TcpFastLossRecover: received a partial ACK(%d) for TCB %p\n",
213 if (Tcb->SRtt != 0) {
220 Tcb->RttVar = (3 * Tcb->RttVar + Var) >> 2;
221 Tcb->SRtt = 7 * (Tcb->SRtt >> 3) + Measure;
245 "TcpComputeRtt: new RTT for TCB %p computed SRTT: %d RTTVAR: %d RTO: %d\n",
275 Seg = TCPSEG_NETBUF (Nbuf);
281 if (TCP_SEQ_LEQ (Seg->
End, Left) || TCP_SEQ_LEQ (Right, Seg->
Seq)) {
282 TCP_CLEAR_FLG (Seg->
Flag, TCP_FLG_SYN);
286 NetbufTrim (Nbuf, Nbuf->TotalSize, NET_BUF_HEAD);
293 if (TCP_SEQ_LT (Seg->
Seq, Left)) {
294 Drop = TCP_SUB_SEQ (Left, Seg->
Seq);
295 Urg = Seg->
Seq + Seg->
Urg;
298 if (TCP_FLG_ON (Seg->
Flag, TCP_FLG_SYN)) {
299 TCP_CLEAR_FLG (Seg->
Flag, TCP_FLG_SYN);
306 if (TCP_FLG_ON (Seg->
Flag, TCP_FLG_URG)) {
307 if (TCP_SEQ_LT (Urg, Seg->
Seq)) {
308 TCP_CLEAR_FLG (Seg->
Flag, TCP_FLG_URG);
310 Seg->
Urg = (UINT16)TCP_SUB_SEQ (Urg, Seg->
Seq);
322 if (TCP_SEQ_GT (Seg->
End, Right)) {
323 Drop = TCP_SUB_SEQ (Seg->
End, Right);
355 return TcpTrimSegment (Nbuf, Tcb->RcvNxt, Tcb->RcvWl2 + Tcb->RcvWnd);
380 ASSERT ((Tcb !=
NULL) && (Tcb->Sk !=
NULL));
393 Entry = Tcb->RcvQue.ForwardLink;
396 while (Entry != &Tcb->RcvQue) {
397 Nbuf = NET_LIST_USER_STRUCT (Entry,
NET_BUF, List);
398 Seg = TCPSEG_NETBUF (Nbuf);
403 "TcpToSendData: discard a broken segment for TCB %p\n",
410 ASSERT (Nbuf->Tcp ==
NULL);
412 if (TCP_SEQ_GT (Seg->
Seq, Seq)) {
416 Entry = Entry->ForwardLink;
433 "TcpDeliverData: data received after FIN from peer of TCB %p, reset connection\n",
443 "TcpDeliverData: processing FIN from peer of TCB %p\n",
447 switch (Tcb->State) {
449 case TCP_ESTABLISHED:
469 if (Tcb->TimeWaitTimeout != 0) {
474 "Connection closed immediately because app disables TIME_WAIT timer for %p\n",
507 if (TCP_FLG_ON (Seg->
Flag, TCP_FLG_PSH)) {
511 if (Nbuf->TotalSize != 0) {
515 TCP_SEQ_LEQ (Seg->
Seq, Tcb->RcvUp))
517 if (TCP_SEQ_LEQ (Seg->
End, Tcb->RcvUp)) {
518 Urgent = Nbuf->TotalSize;
520 Urgent = TCP_SUB_SEQ (Tcb->RcvUp, Seg->
Seq) + 1;
527 if (TCP_FIN_RCVD (Tcb->State)) {
559 ASSERT ((Tcb !=
NULL) && (Nbuf !=
NULL) && (Nbuf->Tcp ==
NULL));
563 Seg = TCPSEG_NETBUF (Nbuf);
578 for (Prev = Head, Cur = Head->ForwardLink;
580 Prev = Cur, Cur = Cur->ForwardLink)
582 Node = NET_LIST_USER_STRUCT (Cur,
NET_BUF, List);
584 if (TCP_SEQ_LT (Seg->
Seq, TCPSEG_NETBUF (Node)->Seq)) {
594 Node = NET_LIST_USER_STRUCT (Prev,
NET_BUF, List);
596 if (TCP_SEQ_LT (Seg->
Seq, TCPSEG_NETBUF (Node)->End)) {
597 if (TCP_SEQ_LEQ (Seg->
End, TCPSEG_NETBUF (Node)->End)) {
614 while (Cur != Head) {
615 Node = NET_LIST_USER_STRUCT (Cur,
NET_BUF, List);
617 if (TCP_SEQ_LEQ (TCPSEG_NETBUF (Node)->End, Seg->
End)) {
618 Cur = Cur->ForwardLink;
625 if (TCP_SEQ_LT (TCPSEG_NETBUF (Node)->Seq, Seg->
End)) {
626 if (TCP_SEQ_LEQ (TCPSEG_NETBUF (Node)->Seq, Seg->
Seq)) {
639 Cur = Cur->ForwardLink;
667 Cur = Head->ForwardLink;
669 while (Cur != Head) {
670 Node = NET_LIST_USER_STRUCT (Cur,
NET_BUF, List);
671 Seg = TCPSEG_NETBUF (Node);
673 if (TCP_SEQ_GEQ (Seg->
Seq, Ack)) {
680 if (TCP_SEQ_LEQ (Seg->
End, Ack)) {
681 Cur = Cur->ForwardLink;
729 ASSERT ((Version == IP_VERSION_4) || (Version == IP_VERSION_6));
731 NET_CHECK_SIGNATURE (Nbuf, NET_BUF_SIGNATURE);
737 ASSERT (Head !=
NULL);
739 if (Nbuf->TotalSize < sizeof (
TCP_HEAD)) {
740 DEBUG ((DEBUG_NET,
"TcpInput: received a malformed packet\n"));
744 Len = Nbuf->TotalSize - (Head->HeadLen << 2);
746 if ((Head->HeadLen < 5) || (Len < 0)) {
747 DEBUG ((DEBUG_NET,
"TcpInput: received a malformed packet\n"));
752 if (Version == IP_VERSION_4) {
761 DEBUG ((DEBUG_ERROR,
"TcpInput: received a checksum error packet\n"));
765 if (TCP_FLG_ON (Head->Flag, TCP_FLG_SYN)) {
779 (BOOLEAN)TCP_FLG_ON (Head->Flag, TCP_FLG_SYN)
783 DEBUG ((DEBUG_NET,
"TcpInput: send reset because no TCB found\n"));
798 "TcpInput: reset the peer because of malformed option for TCB %p\n",
808 NetbufTrim (Nbuf, (Head->HeadLen << 2), NET_BUF_HEAD);
814 if (Tcb->
State == TCP_LISTEN) {
818 if (TCP_FLG_ON (Seg->
Flag, TCP_FLG_RST)) {
821 "TcpInput: discard a reset segment for TCB %p in listening\n",
832 if (TCP_FLG_ON (Seg->
Flag, TCP_FLG_ACK)) {
835 "TcpInput: send reset because of segment with ACK for TCB %p in listening\n",
845 if (TCP_FLG_ON (Seg->
Flag, TCP_FLG_SYN)) {
855 "TcpInput: discard a segment because failed to clone a child for TCB %p\n",
864 "TcpInput: create a child for TCB %p in listening\n",
877 if (EFI_ERROR (Status)) {
880 "TcpInput: discard a segment because failed to init local end for TCB %p\n",
894 "TcpInput: discard a broken segment for TCB %p\n",
905 }
else if (Tcb->
State == TCP_SYN_SENT) {
909 if (TCP_FLG_ON (Seg->
Flag, TCP_FLG_ACK) && (Seg->
Ack != Tcb->
Iss + 1)) {
912 "TcpInput: send reset because of wrong ACK received for TCB %p in SYN_SENT\n",
922 if (TCP_FLG_ON (Seg->
Flag, TCP_FLG_RST)) {
923 if (TCP_FLG_ON (Seg->
Flag, TCP_FLG_ACK)) {
926 "TcpInput: connection reset by peer for TCB %p in SYN_SENT\n",
931 goto DROP_CONNECTION;
935 "TcpInput: discard a reset segment because of no ACK for TCB %p in SYN_SENT\n",
950 if (TCP_FLG_ON (Seg->
Flag, TCP_FLG_SYN)) {
953 if (TCP_FLG_ON (Seg->
Flag, TCP_FLG_ACK)) {
959 if (TCP_SEQ_GT (Tcb->
SndUna, Tcb->
Iss)) {
975 "TcpInput: discard a broken segment for TCB %p\n",
986 "TcpInput: connection established for TCB %p in SYN_SENT\n",
1002 "TcpInput: discard a broken segment for TCB %p\n",
1011 "TcpInput: simultaneous open for TCB %p in SYN_SENT\n",
1040 "TcpInput: sequence acceptance test failed for segment of TCB %p\n",
1044 if (!TCP_FLG_ON (Seg->
Flag, TCP_FLG_RST)) {
1051 if ((TCP_SEQ_LT (Seg->
Seq, Tcb->
RcvWl2)) &&
1061 if (TCP_FLG_ON (Seg->
Flag, TCP_FLG_RST)) {
1062 DEBUG ((DEBUG_WARN,
"TcpInput: connection reset for TCB %p\n", Tcb));
1064 if (Tcb->
State == TCP_SYN_RCVD) {
1073 }
else if ((Tcb->
State == TCP_ESTABLISHED) ||
1074 (Tcb->
State == TCP_FIN_WAIT_1) ||
1075 (Tcb->
State == TCP_FIN_WAIT_2) ||
1076 (Tcb->
State == TCP_CLOSE_WAIT))
1082 goto DROP_CONNECTION;
1091 "TcpInput: discard a broken segment for TCB %p\n",
1105 if (TCP_FLG_ON (Seg->
Flag, TCP_FLG_SYN)) {
1108 "TcpInput: connection reset because received extra SYN for TCB %p\n",
1113 goto RESET_THEN_DROP;
1119 if (!TCP_FLG_ON (Seg->
Flag, TCP_FLG_ACK)) {
1122 "TcpInput: segment discard because of no ACK for connected TCB %p\n",
1128 if ((Tcb->
IpInfo->IpVersion == IP_VERSION_6) && (Tcb->
Tick == 0)) {
1134 if (Tcb->
State == TCP_SYN_RCVD) {
1135 if (TCP_SEQ_LT (Tcb->
SndUna, Seg->
Ack) &&
1149 "TcpInput: connection established for TCB %p in SYN_RCVD\n",
1159 "TcpInput: send reset because of wrong ACK for TCB %p in SYN_RCVD\n",
1167 if (TCP_SEQ_LT (Seg->
Ack, Tcb->
SndUna)) {
1170 "TcpInput: ignore the out-of-data ACK for connected TCB %p\n",
1175 }
else if (TCP_SEQ_GT (Seg->
Ack, Tcb->
SndNxt)) {
1178 "TcpInput: discard segment for future ACK for connected TCB %p\n",
1189 if (TCP_FLG_ON (Option.
Flag, TCP_OPTION_RCVD_TS)) {
1195 if (TCP_SEQ_LEQ (Seg->
Seq, Tcb->
RcvWl2) &&
1235 if (TCP_SEQ_GT (Seg->
Ack, Tcb->
SndUna)) {
1252 if (TCP_SEQ_GT (Seg->
Ack, Tcb->
SndUna)) {
1256 "TcpInput: discard a broken segment for TCB %p\n",
1275 if (TCP_SEQ_LT (Tcb->
SndWl1, Seg->
Seq) ||
1278 Right = Seg->
Ack + Seg->
Wnd;
1290 "TcpInput: peer shrinks the window for connected TCB %p\n",
1295 (TCP_SEQ_LT (Right, Tcb->
Recover)))
1306 if (TCP_SEQ_LT (Right, Tcb->
SndNxt)) {
1316 "TcpInput: peer advise negative useable window for connected TCB %p\n",
1319 Usable = TCP_SUB_SEQ (Tcb->
SndNxt, Right);
1323 "TcpInput: SndNxt is out of window by more than window scale for TCB %p\n",
1329 if (Right == Tcb->
SndUna) {
1349 "TcpInput: local FIN is ACKed by peer for connected TCB %p\n",
1359 switch (Tcb->
State) {
1360 case TCP_FIN_WAIT_1:
1369 case TCP_FIN_WAIT_2:
1373 case TCP_CLOSE_WAIT:
1388 "Connection closed immediately because app disables TIME_WAIT timer for %p\n",
1415 "Connection closed immediately because app disables TIME_WAIT timer for %p\n",
1437 if (TCP_FLG_ON (Seg->
Flag, TCP_FLG_URG) && !TCP_FIN_RCVD (Tcb->
State)) {
1440 "TcpInput: received urgent data from peer for connected TCB %p\n",
1444 Urg = Seg->
Seq + Seg->
Urg;
1447 TCP_SEQ_GT (Urg, Tcb->
RcvUp))
1459 if (Seg->
End != Seg->
Seq) {
1460 if (TCP_FIN_RCVD (Tcb->
State)) {
1463 "TcpInput: connection reset because data is lost for connected TCB %p\n",
1467 goto RESET_THEN_DROP;
1470 if (TCP_LOCAL_CLOSED (Tcb->
State) && (Nbuf->TotalSize != 0)) {
1473 "TcpInput: connection reset because data is lost for connected TCB %p\n",
1477 goto RESET_THEN_DROP;
1483 "TcpInput: discard a broken segment for TCB %p\n",
1491 goto RESET_THEN_DROP;
1510 if (Parent !=
NULL) {
1545 DEBUG ((DEBUG_WARN,
"TcpInput: Discard a packet\n"));
1548 if ((Parent !=
NULL) && (Tcb !=
NULL)) {
1549 ASSERT (Tcb->
Sk !=
NULL);
1581 BOOLEAN IcmpErrIsHard;
1582 BOOLEAN IcmpErrNotify;
1584 IcmpErrIsHard =
FALSE;
1585 IcmpErrNotify =
FALSE;
1587 if (Nbuf->TotalSize < sizeof (
TCP_HEAD)) {
1592 ASSERT (Head !=
NULL);
1609 Seq = NTOHL (Head->Seq);
1610 if (!(TCP_SEQ_LEQ (Tcb->
SndUna, Seq) && TCP_SEQ_LT (Seq, Tcb->
SndNxt))) {
1621 if (IcmpErrNotify) {
1625 if (IcmpErrIsHard) {
BOOLEAN EFIAPI IsListEmpty(IN CONST LIST_ENTRY *ListHead)
LIST_ENTRY *EFIAPI InsertHeadList(IN OUT LIST_ENTRY *ListHead, IN OUT LIST_ENTRY *Entry)
LIST_ENTRY *EFIAPI RemoveEntryList(IN CONST LIST_ENTRY *Entry)
LIST_ENTRY *EFIAPI InsertTailList(IN OUT LIST_ENTRY *ListHead, IN OUT LIST_ENTRY *Entry)
EFI_STATUS EFIAPI IpIoGetIcmpErrStatus(IN UINT8 IcmpError, IN UINT8 IpVersion, OUT BOOLEAN *IsHard OPTIONAL, OUT BOOLEAN *Notify OPTIONAL)
#define DEBUG(Expression)
VOID EFIAPI NetbufFree(IN NET_BUF *Nbuf)
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)
UINT16 EFIAPI NetPseudoHeadChecksum(IN IP4_ADDR Src, IN IP4_ADDR Dst, IN UINT8 Proto, IN UINT16 Len)
UINT8 *EFIAPI NetbufGetByte(IN NET_BUF *Nbuf, IN UINT32 Offset, OUT UINT32 *Index OPTIONAL)
VOID SockDataRcvd(IN OUT SOCKET *Sock, IN OUT NET_BUF *NetBuffer, IN UINT32 UrgLen)
VOID SockNoMoreData(IN OUT SOCKET *Sock)
#define SOCK_ERROR(Sock, Error)
EFI_STATUS Tcp6RefreshNeighbor(IN TCP_CB *Tcb, IN EFI_IP_ADDRESS *Neighbor, IN UINT32 Timeout)
VOID TcpClose(IN OUT TCP_CB *Tcb)
EFI_STATUS TcpInitTcbLocal(IN OUT TCP_CB *Tcb)
INTN TcpRetransmit(IN TCP_CB *Tcb, IN TCP_SEQNO Seq)
VOID TcpClearTimer(IN OUT TCP_CB *Tcb, IN UINT16 Timer)
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)
VOID TcpSetProbeTimer(IN OUT TCP_CB *Tcb)
INTN TcpInsertTcb(IN TCP_CB *Tcb)
VOID TcpSetTimer(IN OUT TCP_CB *Tcb, IN UINT16 Timer, IN UINT32 TimeOut)
VOID TcpSetState(IN TCP_CB *Tcb, IN UINT8 State)
TCP_CB * TcpLocateTcb(IN TCP_PORTNO LocalPort, IN EFI_IP_ADDRESS *LocalIp, IN TCP_PORTNO RemotePort, IN EFI_IP_ADDRESS *RemoteIp, IN UINT8 Version, IN BOOLEAN Syn)
TCP_CB * TcpCloneTcb(IN TCP_CB *Tcb)
TCP_SEG * TcpFormatNetbuf(IN TCP_CB *Tcb, IN OUT NET_BUF *Nbuf)
VOID TcpInitTcbPeer(IN OUT TCP_CB *Tcb, IN TCP_SEG *Seg, IN TCP_OPTION *Opt)
VOID TcpSendAck(IN OUT TCP_CB *Tcb)
VOID TcpClearAllTimer(IN OUT TCP_CB *Tcb)
VOID TcpSetKeepaliveTimer(IN OUT TCP_CB *Tcb)
VOID TcpToSendAck(IN OUT TCP_CB *Tcb)
UINT16 TcpChecksum(IN NET_BUF *Nbuf, IN UINT16 HeadSum)
#define TCP6_REFRESH_NEIGHBOR_TICK
#define TCP6_KEEP_NEIGHBOR_TIME
INTN TcpParseOption(IN TCP_HEAD *Tcp, IN OUT TCP_OPTION *Option)
#define TCP_TIMER_PROBE
Window probe timer.
#define TCP_TIMER_2MSL
TIME_WAIT timer.
#define TCP_TIMER_CONNECT
Connection establishment timer.
#define TCP_CONNECTED(state)
#define TCP_RTO_MIN
The minimum value of RTO.
#define TCP_CTRL_FIN_ACKED
FIN is ACKed.
#define TCP_RTO_MAX
The maximum value of RTO.
#define TCP_TIMER_REXMIT
Retransmit timer.
#define TCP_CTRL_FIN_SENT
FIN is sent.
#define TCP_TIMER_FINWAIT2
FIN_WAIT_2 timer.
#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_RECOVER
During the NewReno fast recovery.
#define TCP_CONGEST_LOSS
Retxmit because of retxmit time out.
#define TCP_CONGEST_OPEN
TCP is opening its congestion window.
#define TCP_CTRL_RCVD_URG
In urgent receive mode.
#define TCP_RTT_SHIFT
SRTT & RTTVAR scaled by 8.
TCP_SEQNO SndUna
First unacknowledged data.
UINT32 Tick
1 tick = 200ms
UINT8 SndWndScale
Wndscale received from the peer.
TCP_PEER RemoteEnd
Remote endpoint.
TCP_SEQNO LossRecover
Recover point for retxmit.
UINT32 RttMeasure
Currently measured RTT in heartbeats.
UINT32 Ssthresh
Slow start threshold.
TCP_CB * Parent
The parent TCP_CB structure.
UINT32 Idle
How long the connection is in idle.
TCP_SEQNO SndWl2
Ack no of last window update.
UINT8 CongestState
The current congestion state(RFC3782).
UINT32 TimeWaitTimeout
The TIME_WAIT timeout.
TCP_SEQNO SndUp
Send urgent point.
BOOLEAN ProbeTimerOn
If TRUE, the probe time is on.
TCP_SEQNO Recover
Recover point for NewReno.
UINT32 Rto
Current RTO, not scaled.
TCP_SEQNO Iss
Initial Sending Sequence.
UINT32 SndWndMax
Max send window advertised by the peer.
UINT8 State
TCP state, such as SYN_SENT, LISTEN.
LIST_ENTRY RcvQue
Reassemble queue.
UINT16 SndMss
Max send segment size.
TCP_SEQNO SndWl1
Seq number used for last window update.
UINT32 FinWait2Timeout
The FIN_WAIT_2 timeout.
UINT16 DupAck
Number of duplicate ACKs.
UINT32 ConnectTimeout
The connect establishment timeout.
SOCKET * Sk
The socket it controlled.
TCP_PEER LocalEnd
Local endpoint.
IP_IO_IP_INFO * IpInfo
Pointer reference to Ip used to send pkt.
TCP_SEQNO RcvUp
Urgent point;.
UINT32 TsRecentAge
When this TsRecent is updated.
UINT32 CtrlFlag
Control flags, such as NO_NAGLE.
TCP_SEQNO SndNxt
Next data sequence to send.
UINT32 TsRecent
TsRecent to echo to the remote peer.
UINT32 CWnd
Sender's congestion window.
UINT32 SndWnd
Window advertised by the remote peer.
UINT32 TSEcr
The TSEcr field in a timestamp option.
UINT8 Flag
Flag such as TCP_OPTION_RCVD_MSS.
UINT32 TSVal
The TSVal field in a timestamp option.
EFI_IP_ADDRESS Ip
IP address, in network byte order.
TCP_PORTNO Port
Port number, in network byte order.
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.
TCP_SEQNO Ack
ACK field in the segment.
UINT32 Wnd
TCP window size field.