/** @file\r
TCP output process routines.\r
\r
- Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>\r
+ Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>\r
\r
- This program and the accompanying materials\r
- are licensed and made available under the terms and conditions of the BSD License\r
- which accompanies this distribution. The full text of the license may be found at\r
- http://opensource.org/licenses/bsd-license.php.\r
-\r
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
BOOLEAN Syn;\r
UINT32 DataLen;\r
\r
- ASSERT ((Nbuf != NULL) && (Nbuf->Tcp == NULL) && (TcpVerifySegment (Nbuf) != 0));\r
+ ASSERT ((Nbuf != NULL) && (Nbuf->Tcp == NULL));\r
+\r
+ if (TcpVerifySegment (Nbuf) == 0) {\r
+ return -1;\r
+ }\r
\r
DataLen = Nbuf->TotalSize;\r
\r
Nbuf = TcpGetSegmentSock (Tcb, Seq, Len);\r
}\r
\r
- ASSERT (TcpVerifySegment (Nbuf) != 0);\r
+ if (TcpVerifySegment (Nbuf) == 0) {\r
+ NetbufFree (Nbuf);\r
+ return NULL;\r
+ }\r
+\r
return Nbuf;\r
}\r
\r
// 2. Must in the current send window\r
// 3. Will not change the boundaries of queued segments.\r
//\r
- if (TCP_SEQ_LT (Tcb->SndWl2 + Tcb->SndWnd, Seq)) {\r
+\r
+ //\r
+ // Handle the Window Retraction if TCP window scale is enabled according to RFC7323:\r
+ // On first retransmission, or if the sequence number is out of\r
+ // window by less than 2^Rcv.Wind.Shift, then do normal\r
+ // retransmission(s) without regard to the receiver window as long\r
+ // as the original segment was in window when it was sent.\r
+ //\r
+ if ((Tcb->SndWndScale != 0) &&\r
+ (TCP_SEQ_GT (Seq, Tcb->RetxmitSeqMax) || TCP_SEQ_BETWEEN (Tcb->SndWl2 + Tcb->SndWnd, Seq, Tcb->SndWl2 + Tcb->SndWnd + (1 << Tcb->SndWndScale)))) {\r
+ Len = TCP_SUB_SEQ (Tcb->SndNxt, Seq);\r
+ DEBUG (\r
+ (EFI_D_WARN,\r
+ "TcpRetransmit: retransmission without regard to the receiver window for TCB %p\n",\r
+ Tcb)\r
+ );\r
+\r
+ } else if (TCP_SEQ_GEQ (Tcb->SndWl2 + Tcb->SndWnd, Seq)) {\r
+ Len = TCP_SUB_SEQ (Tcb->SndWl2 + Tcb->SndWnd, Seq);\r
+\r
+ } else {\r
DEBUG (\r
(EFI_D_WARN,\r
"TcpRetransmit: retransmission cancelled because send window too small for TCB %p\n",\r
return 0;\r
}\r
\r
- Len = TCP_SUB_SEQ (Tcb->SndWl2 + Tcb->SndWnd, Seq);\r
- Len = MIN (Len, Tcb->SndMss);\r
+ Len = MIN (Len, Tcb->SndMss);\r
\r
- Nbuf = TcpGetSegmentSndQue (Tcb, Seq, Len);\r
+ Nbuf = TcpGetSegmentSndQue (Tcb, Seq, Len);\r
if (Nbuf == NULL) {\r
return -1;\r
}\r
\r
- ASSERT (TcpVerifySegment (Nbuf) != 0);\r
+ if (TcpVerifySegment (Nbuf) == 0) {\r
+ goto OnError;\r
+ }\r
\r
if (TcpTransmitSegment (Tcb, Nbuf) != 0) {\r
goto OnError;\r
}\r
\r
+ if (TCP_SEQ_GT (Seq, Tcb->RetxmitSeqMax)) {\r
+ Tcb->RetxmitSeqMax = Seq;\r
+ }\r
+\r
//\r
// The retransmitted buffer may be on the SndQue,\r
// trim TCP head because all the buffers on SndQue\r
Seg->End = End;\r
Seg->Flag = Flag;\r
\r
- ASSERT (TcpVerifySegment (Nbuf) != 0);\r
- ASSERT (TcpCheckSndQue (&Tcb->SndQue) != 0);\r
+ if (TcpVerifySegment (Nbuf) == 0 || TcpCheckSndQue (&Tcb->SndQue) == 0) {\r
+ DEBUG (\r
+ (EFI_D_ERROR,\r
+ "TcpToSendData: discard a broken segment for TCB %p\n",\r
+ Tcb)\r
+ );\r
+ goto OnError;\r
+ }\r
\r
//\r
// Don't send an empty segment here.\r
Tcb)\r
);\r
\r
- NetbufFree (Nbuf);\r
- return Sent;\r
+ goto OnError;\r
}\r
\r
if (TcpTransmitSegment (Tcb, Nbuf) != 0) {\r