X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=MdeModulePkg%2FUniversal%2FNetwork%2FTcp4Dxe%2FTcp4Output.c;h=760b09a1eda1fe58fe4aebb0d29c58a04066790e;hb=d1102dba7210b95e41d06c2338a22ba6af248645;hp=f12b2c5b4ca001ec88c95f20b1e22e510d24e414;hpb=dfc1f033eadc0110006698797925f7060a251f10;p=mirror_edk2.git diff --git a/MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Output.c b/MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Output.c index f12b2c5b4c..760b09a1ed 100644 --- a/MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Output.c +++ b/MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Output.c @@ -1,8 +1,8 @@ /** @file TCP output process routines. - -Copyright (c) 2005 - 2006, Intel Corporation
-All rights reserved. This program and the accompanying materials + +Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.
+This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License which accompanies this distribution. The full text of the license may be found at http://opensource.org/licenses/bsd-license.php
@@ -115,8 +115,8 @@ TcpRcvWinNow ( **/ UINT16 TcpComputeWnd ( - IN TCP_CB *Tcb, - IN BOOLEAN Syn + IN OUT TCP_CB *Tcb, + IN BOOLEAN Syn ) { UINT32 Wnd; @@ -267,7 +267,9 @@ SetPersistTimer: Tcb) ); - TcpSetProbeTimer (Tcb); + if (!Tcb->ProbeTimerOn) { + TcpSetProbeTimer (Tcb); + } } return 0; @@ -286,8 +288,8 @@ SetPersistTimer: **/ INTN TcpTransmitSegment ( - IN TCP_CB *Tcb, - IN NET_BUF *Nbuf + IN OUT TCP_CB *Tcb, + IN NET_BUF *Nbuf ) { UINT16 Len; @@ -445,7 +447,9 @@ TcpGetSegmentSndQue ( } } - ASSERT (Cur != Head); + ASSERT (Cur != Head); + ASSERT (Node != NULL); + ASSERT (Seg != NULL); // // Return the buffer if it can be returned without @@ -482,7 +486,7 @@ TcpGetSegmentSndQue ( // // If SYN is set and out of the range, clear the flag. - // Becuase the sequence of the first byte is SEG.SEQ+1, + // Because the sequence of the first byte is SEG.SEQ+1, // adjust Offset by -1. If SYN is in the range, copy // one byte less. // @@ -667,17 +671,39 @@ TcpRetransmit ( // 2. must in the current send window // 3. will not change the boundaries of queued segments. // - if (TCP_SEQ_LT (Tcb->SndWl2 + Tcb->SndWnd, Seq)) { - DEBUG ((EFI_D_WARN, "TcpRetransmit: retransmission cancelled " - "because send window too small for TCB %p\n", Tcb)); + + // + // Handle the Window Retraction if TCP window scale is enabled according to RFC7323: + // On first retransmission, or if the sequence number is out of + // window by less than 2^Rcv.Wind.Shift, then do normal + // retransmission(s) without regard to the receiver window as long + // as the original segment was in window when it was sent. + // + if ((Tcb->SndWndScale != 0) && + (TCP_SEQ_GT (Seq, Tcb->RetxmitSeqMax) || TCP_SEQ_BETWEEN (Tcb->SndWl2 + Tcb->SndWnd, Seq, Tcb->SndWl2 + Tcb->SndWnd + (1 << Tcb->SndWndScale)))) { + Len = TCP_SUB_SEQ (Tcb->SndNxt, Seq); + DEBUG ( + (EFI_D_WARN, + "TcpRetransmit: retransmission without regard to the receiver window for TCB %p\n", + Tcb) + ); + + } else if (TCP_SEQ_GEQ (Tcb->SndWl2 + Tcb->SndWnd, Seq)) { + Len = TCP_SUB_SEQ (Tcb->SndWl2 + Tcb->SndWnd, Seq); + + } else { + DEBUG ( + (EFI_D_WARN, + "TcpRetransmit: retransmission cancelled because send window too small for TCB %p\n", + Tcb) + ); return 0; } - Len = TCP_SUB_SEQ (Tcb->SndWl2 + Tcb->SndWnd, Seq); - Len = MIN (Len, Tcb->SndMss); + Len = MIN (Len, Tcb->SndMss); - Nbuf = TcpGetSegmentSndQue (Tcb, Seq, Len); + Nbuf = TcpGetSegmentSndQue (Tcb, Seq, Len); if (Nbuf == NULL) { return -1; } @@ -688,6 +714,10 @@ TcpRetransmit ( goto OnError; } + if (TCP_SEQ_GT (Seq, Tcb->RetxmitSeqMax)) { + Tcb->RetxmitSeqMax = Seq; + } + // // The retransmitted buffer may be on the SndQue, // trim TCP head because all the buffer on SndQue @@ -721,8 +751,8 @@ OnError: **/ INTN TcpToSendData ( - IN TCP_CB *Tcb, - IN INTN Force + IN OUT TCP_CB *Tcb, + IN INTN Force ) { UINT32 Len; @@ -750,6 +780,7 @@ SEND_AGAIN: Len = TcpDataToSend (Tcb, Force); Seq = Tcb->SndNxt; + ASSERT ((Tcb->State) < (ARRAY_SIZE (mTcpOutFlag))); Flag = mTcpOutFlag[Tcb->State]; if ((Flag & TCP_FLG_SYN) != 0) { @@ -762,7 +793,7 @@ SEND_AGAIN: // only send a segment without data if SYN or // FIN is set. // - if ((Len == 0) && + if ((Len == 0) && ((Flag & (TCP_FLG_SYN | TCP_FLG_FIN)) == 0)) { return Sent; } @@ -800,10 +831,10 @@ SEND_AGAIN: TCP_SEQ_LT (End + 1, Tcb->SndWnd + Tcb->SndWl2)) { DEBUG ( - (EFI_D_INFO, - "TcpToSendData: send FIN " - "to peer for TCB %p in state %s\n", - Tcb, + (EFI_D_NET, + "TcpToSendData: send FIN " + "to peer for TCB %p in state %s\n", + Tcb, mTcpStateName[Tcb->State]) ); @@ -832,9 +863,6 @@ SEND_AGAIN: } if (TcpTransmitSegment (Tcb, Nbuf) != 0) { - // - // TODO: double check this - // NetbufTrim (Nbuf, (Nbuf->Tcp->HeadLen << 2), NET_BUF_HEAD); Nbuf->Tcp = NULL; @@ -881,7 +909,7 @@ SEND_AGAIN: if ((Tcb->CongestState == TCP_CONGEST_OPEN) && !TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_RTT_ON)) { - DEBUG ((EFI_D_INFO, "TcpToSendData: set RTT measure " + DEBUG ((EFI_D_NET, "TcpToSendData: set RTT measure " "sequence %d for TCB %p\n", Seq, Tcb)); TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_RTT_ON); @@ -912,7 +940,7 @@ OnError: **/ VOID TcpSendAck ( - IN TCP_CB *Tcb + IN OUT TCP_CB *Tcb ) { NET_BUF *Nbuf; @@ -951,7 +979,7 @@ TcpSendAck ( **/ INTN TcpSendZeroProbe ( - IN TCP_CB *Tcb + IN OUT TCP_CB *Tcb ) { NET_BUF *Nbuf; @@ -990,7 +1018,7 @@ TcpSendZeroProbe ( **/ VOID TcpToSendAck ( - IN TCP_CB *Tcb + IN OUT TCP_CB *Tcb ) { UINT32 TcpNow; @@ -1009,7 +1037,7 @@ TcpToSendAck ( return; } - DEBUG ((EFI_D_INFO, "TcpToSendAck: scheduled a delayed" + DEBUG ((EFI_D_NET, "TcpToSendAck: scheduled a delayed" " ACK for TCB %p\n", Tcb)); // @@ -1092,7 +1120,7 @@ TcpSendReset ( Nhead->SrcPort = Head->DstPort; Nhead->DstPort = Head->SrcPort; - Nhead->HeadLen = (sizeof (TCP_HEAD) >> 2); + Nhead->HeadLen = (UINT8) (sizeof (TCP_HEAD) >> 2); Nhead->Res = 0; Nhead->Wnd = HTONS (0xFFFF); Nhead->Checksum = 0;