4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/** @file
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP output process routines.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync This program and the accompanying materials
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync are licensed and made available under the terms and conditions of the BSD License
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync which accompanies this distribution. The full text of the license may be found at
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync http://opensource.org/licenses/bsd-license.php.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include "TcpMain.h"
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncUINT8 mTcpOutFlag[] = {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 0, // TCP_CLOSED
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 0, // TCP_LISTEN
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_FLG_SYN, // TCP_SYN_SENT
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_FLG_SYN | TCP_FLG_ACK, // TCP_SYN_RCVD
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_FLG_ACK, // TCP_ESTABLISHED
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_FLG_FIN | TCP_FLG_ACK, // TCP_FIN_WAIT_1
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_FLG_ACK, // TCP_FIN_WAIT_2
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_FLG_ACK | TCP_FLG_FIN, // TCP_CLOSING
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_FLG_ACK, // TCP_TIME_WAIT
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_FLG_ACK, // TCP_CLOSE_WAIT
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_FLG_FIN | TCP_FLG_ACK // TCP_LAST_ACK
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync};
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Compute the sequence space left in the old receive window.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Tcb Pointer to the TCP_CB of this TCP instance.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @return The sequence space left in the old receive window.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncUINT32
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncTcpRcvWinOld (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN TCP_CB *Tcb
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 OldWin;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync OldWin = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TCP_SEQ_GT (Tcb->RcvWl2 + Tcb->RcvWnd, Tcb->RcvNxt)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync OldWin = TCP_SUB_SEQ (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb->RcvWl2 + Tcb->RcvWnd,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb->RcvNxt
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return OldWin;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Compute the current receive window.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Tcb Pointer to the TCP_CB of this TCP instance.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @return The size of the current receive window, in bytes.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncUINT32
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncTcpRcvWinNow (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN TCP_CB *Tcb
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SOCKET *Sk;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 Win;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 Increase;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 OldWin;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Sk = Tcb->Sk;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (Sk != NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync OldWin = TcpRcvWinOld (Tcb);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Win = SockGetFreeSpace (Sk, SOCK_RCV_BUF);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Increase = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Win > OldWin) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Increase = Win - OldWin;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Receiver's SWS: don't advertise a bigger window
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // unless it can be increased by at least one Mss or
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // half of the receive buffer.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((Increase > Tcb->SndMss) || (2 * Increase >= GET_RCV_BUFFSIZE (Sk))) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Win;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return OldWin;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Compute the value to fill in the window size field of the outgoing segment.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Syn The flag to indicate whether the outgoing segment
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync is a SYN segment.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @return The value of the local receive window size used to fill the outgoing segment.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncUINT16
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncTcpComputeWnd (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN OUT TCP_CB *Tcb,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN BOOLEAN Syn
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 Wnd;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // RFC requires that initial window not be scaled
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Syn) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Wnd = GET_RCV_BUFFSIZE (Tcb->Sk);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Wnd = TcpRcvWinNow (Tcb);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb->RcvWnd = Wnd;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Wnd = MIN (Wnd >> Tcb->RcvWndScale, 0xffff);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return NTOHS ((UINT16) Wnd);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Get the maximum SndNxt.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Tcb Pointer to the TCP_CB of this TCP instance.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @return The sequence number of the maximum SndNxt.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncTCP_SEQNO
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncTcpGetMaxSndNxt (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN TCP_CB *Tcb
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LIST_ENTRY *Entry;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_BUF *Nbuf;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (IsListEmpty (&Tcb->SndQue)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Tcb->SndNxt;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Entry = Tcb->SndQue.BackLink;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Nbuf = NET_LIST_USER_STRUCT (Entry, NET_BUF, List);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (TCP_SEQ_GEQ (TCPSEG_NETBUF (Nbuf)->End, Tcb->SndNxt));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return TCPSEG_NETBUF (Nbuf)->End;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Compute how much data to send.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Tcb Pointer to the TCP_CB of this TCP instance.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Force If TRUE, to ignore the sender's SWS avoidance algorithm and send
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync out data by force.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @return The length of the data can be sent. If 0, no data can be sent.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncUINT32
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncTcpDataToSend (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN TCP_CB *Tcb,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN INTN Force
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SOCKET *Sk;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 Win;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 Len;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 Left;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 Limit;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Sk = Tcb->Sk;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (Sk != NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // TCP should NOT send data beyond the send window
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // and congestion window. The right edge of send
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // window is defined as SND.WL2 + SND.WND. The right
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // edge of congestion window is defined as SND.UNA +
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // CWND.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Win = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Limit = Tcb->SndWl2 + Tcb->SndWnd;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TCP_SEQ_GT (Limit, Tcb->SndUna + Tcb->CWnd)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Limit = Tcb->SndUna + Tcb->CWnd;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TCP_SEQ_GT (Limit, Tcb->SndNxt)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Win = TCP_SUB_SEQ (Limit, Tcb->SndNxt);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // The data to send contains two parts: the data on the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // socket send queue, and the data on the TCB's send
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // buffer. The later can be non-zero if the peer shrinks
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // its advertised window.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Left = GET_SND_DATASIZE (Sk) + TCP_SUB_SEQ (TcpGetMaxSndNxt (Tcb), Tcb->SndNxt);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Len = MIN (Win, Left);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Len > Tcb->SndMss) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Len = Tcb->SndMss;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((Force != 0)|| (Len == 0 && Left == 0)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Len;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Len == 0 && Left != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto SetPersistTimer;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Sender's SWS avoidance: Don't send a small segment unless
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // a)A full-sized segment can be sent,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // b)At least one-half of the maximum sized windows that
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // the other end has ever advertised.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // c)It can send everything it has, and either it isn't
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // expecting an ACK, or the Nagle algorithm is disabled.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((Len == Tcb->SndMss) || (2 * Len >= Tcb->SndWndMax)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Len;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((Len == Left) &&
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ((Tcb->SndNxt == Tcb->SndUna) || TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_NAGLE))
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Len;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // RFC1122 suggests to set a timer when SWSA forbids TCP
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // sending more data, and combines it with a probe timer.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncSetPersistTimer:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!TCP_TIMER_ON (Tcb->EnabledTimer, TCP_TIMER_REXMIT)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DEBUG (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (EFI_D_WARN,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "TcpDataToSend: enter persistent state for TCB %p\n",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!Tcb->ProbeTimerOn) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TcpSetProbeTimer (Tcb);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Build the TCP header of the TCP segment and transmit the segment by IP.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Nbuf Pointer to the buffer containing the segment to be
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sent out.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval 0 The segment was sent out successfully.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval -1 An error condition occurred.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncINTN
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncTcpTransmitSegment (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN OUT TCP_CB *Tcb,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN NET_BUF *Nbuf
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT16 Len;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_HEAD *Head;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_SEG *Seg;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BOOLEAN Syn;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 DataLen;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT ((Nbuf != NULL) && (Nbuf->Tcp == NULL) && (TcpVerifySegment (Nbuf) != 0));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DataLen = Nbuf->TotalSize;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Seg = TCPSEG_NETBUF (Nbuf);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Syn = TCP_FLG_ON (Seg->Flag, TCP_FLG_SYN);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Syn) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Len = TcpSynBuildOption (Tcb, Nbuf);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Len = TcpBuildOption (Tcb, Nbuf);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT ((Len % 4 == 0) && (Len <= 40));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Len += sizeof (TCP_HEAD);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Head = (TCP_HEAD *) NetbufAllocSpace (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Nbuf,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sizeof (TCP_HEAD),
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_BUF_HEAD
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (Head != NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Nbuf->Tcp = Head;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Head->SrcPort = Tcb->LocalEnd.Port;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Head->DstPort = Tcb->RemoteEnd.Port;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Head->Seq = NTOHL (Seg->Seq);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Head->Ack = NTOHL (Tcb->RcvNxt);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Head->HeadLen = (UINT8) (Len >> 2);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Head->Res = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Head->Wnd = TcpComputeWnd (Tcb, Syn);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Head->Checksum = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Check whether to set the PSH flag.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_CLEAR_FLG (Seg->Flag, TCP_FLG_PSH);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (DataLen != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_SND_PSH) &&
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_SEQ_BETWEEN (Seg->Seq, Tcb->SndPsh, Seg->End)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_SET_FLG (Seg->Flag, TCP_FLG_PSH);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_CLEAR_FLG (Tcb->CtrlFlag, TCP_CTRL_SND_PSH);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else if ((Seg->End == Tcb->SndNxt) && (GET_SND_DATASIZE (Tcb->Sk) == 0)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_SET_FLG (Seg->Flag, TCP_FLG_PSH);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Check whether to set the URG flag and the urgent pointer.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_CLEAR_FLG (Seg->Flag, TCP_FLG_URG);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_SND_URG) && TCP_SEQ_LEQ (Seg->Seq, Tcb->SndUp)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_SET_FLG (Seg->Flag, TCP_FLG_URG);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TCP_SEQ_LT (Tcb->SndUp, Seg->End)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Seg->Urg = (UINT16) TCP_SUB_SEQ (Tcb->SndUp, Seg->Seq);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Seg->Urg = (UINT16) MIN (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_SUB_SEQ (Tcb->SndUp,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Seg->Seq),
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 0xffff
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Head->Flag = Seg->Flag;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Head->Urg = NTOHS (Seg->Urg);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Head->Checksum = TcpChecksum (Nbuf, Tcb->HeadSum);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Update the TCP session's control information.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb->RcvWl2 = Tcb->RcvNxt;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Syn) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb->RcvWnd = NTOHS (Head->Wnd);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Clear the delayedack flag.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb->DelayedAck = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return TcpSendIpPacket (Tcb, Nbuf, &Tcb->LocalEnd.Ip, &Tcb->RemoteEnd.Ip, Tcb->Sk->IpVersion);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Get a segment from the Tcb's SndQue.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Tcb Pointer to the TCP_CB of this TCP instance.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Seq The sequence number of the segment.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Len The maximum length of the segment.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @return Pointer to the segment. If NULL, some error occurred.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncNET_BUF *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncTcpGetSegmentSndQue (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN TCP_CB *Tcb,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN TCP_SEQNO Seq,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT32 Len
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LIST_ENTRY *Head;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LIST_ENTRY *Cur;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_BUF *Node;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_SEG *Seg;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_BUF *Nbuf;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_SEQNO End;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT8 *Data;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT8 Flag;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync INT32 Offset;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync INT32 CopyLen;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT ((Tcb != NULL) && TCP_SEQ_LEQ (Seq, Tcb->SndNxt) && (Len > 0));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Find the segment that contains the Seq.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Head = &Tcb->SndQue;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Node = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Seg = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_LIST_FOR_EACH (Cur, Head) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Node = NET_LIST_USER_STRUCT (Cur, NET_BUF, List);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Seg = TCPSEG_NETBUF (Node);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TCP_SEQ_LT (Seq, Seg->End) && TCP_SEQ_LEQ (Seg->Seq, Seq)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((Cur == Head) || (Seg == NULL) || (Node == NULL)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Return the buffer if it can be returned without
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // adjustment:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((Seg->Seq == Seq) &&
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_SEQ_LEQ (Seg->End, Seg->Seq + Len) &&
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync !NET_BUF_SHARED (Node)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_GET_REF (Node);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Node;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Create a new buffer and copy data there.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Nbuf = NetbufAlloc (Len + TCP_MAX_HEAD);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Nbuf == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufReserve (Nbuf, TCP_MAX_HEAD);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Flag = Seg->Flag;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync End = Seg->End;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TCP_SEQ_LT (Seq + Len, Seg->End)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync End = Seq + Len;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CopyLen = TCP_SUB_SEQ (End, Seq);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Offset = TCP_SUB_SEQ (Seq, Seg->Seq);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // If SYN is set and out of the range, clear the flag.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Becuase the sequence of the first byte is SEG.SEQ+1,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // adjust Offset by -1. If SYN is in the range, copy
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // one byte less.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TCP_FLG_ON (Seg->Flag, TCP_FLG_SYN)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TCP_SEQ_LT (Seg->Seq, Seq)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_CLEAR_FLG (Flag, TCP_FLG_SYN);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Offset--;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CopyLen--;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // If FIN is set and in the range, copy one byte less,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // and if it is out of the range, clear the flag.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TCP_FLG_ON (Seg->Flag, TCP_FLG_FIN)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Seg->End == End) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CopyLen--;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_CLEAR_FLG (Flag, TCP_FLG_FIN);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (CopyLen >= 0);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Copy data to the segment
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (CopyLen != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Data = NetbufAllocSpace (Nbuf, CopyLen, NET_BUF_TAIL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (Data != NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((INT32) NetbufCopy (Node, Offset, CopyLen, Data) != CopyLen) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto OnError;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CopyMem (TCPSEG_NETBUF (Nbuf), Seg, sizeof (TCP_SEG));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCPSEG_NETBUF (Nbuf)->Seq = Seq;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCPSEG_NETBUF (Nbuf)->End = End;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCPSEG_NETBUF (Nbuf)->Flag = Flag;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Nbuf;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncOnError:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufFree (Nbuf);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Get a segment from the Tcb's socket buffer.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Tcb Pointer to the TCP_CB of this TCP instance.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Seq The sequence number of the segment.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Len The maximum length of the segment.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @return Pointer to the segment. If NULL, some error occurred.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncNET_BUF *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncTcpGetSegmentSock (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN TCP_CB *Tcb,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN TCP_SEQNO Seq,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT32 Len
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_BUF *Nbuf;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT8 *Data;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 DataGet;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT ((Tcb != NULL) && (Tcb->Sk != NULL));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Nbuf = NetbufAlloc (Len + TCP_MAX_HEAD);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Nbuf == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DEBUG (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (EFI_D_ERROR,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "TcpGetSegmentSock: failed to allocate a netbuf for TCB %p\n",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufReserve (Nbuf, TCP_MAX_HEAD);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DataGet = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Len != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // copy data to the segment.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Data = NetbufAllocSpace (Nbuf, Len, NET_BUF_TAIL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (Data != NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DataGet = SockGetDataToSend (Tcb->Sk, 0, Len, Data);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_GET_REF (Nbuf);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCPSEG_NETBUF (Nbuf)->Seq = Seq;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCPSEG_NETBUF (Nbuf)->End = Seq + Len;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync InsertTailList (&(Tcb->SndQue), &(Nbuf->List));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (DataGet != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SockDataSent (Tcb->Sk, DataGet);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Nbuf;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Get a segment starting from sequence Seq of a maximum
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync length of Len.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Tcb Pointer to the TCP_CB of this TCP instance.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Seq The sequence number of the segment.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Len The maximum length of the segment.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @return Pointer to the segment. If NULL, some error occurred.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncNET_BUF *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncTcpGetSegment (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN TCP_CB *Tcb,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN TCP_SEQNO Seq,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT32 Len
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_BUF *Nbuf;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (Tcb != NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Compare the SndNxt with the max sequence number sent.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((Len != 0) && TCP_SEQ_LT (Seq, TcpGetMaxSndNxt (Tcb))) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Nbuf = TcpGetSegmentSndQue (Tcb, Seq, Len);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Nbuf = TcpGetSegmentSock (Tcb, Seq, Len);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (TcpVerifySegment (Nbuf) != 0);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Nbuf;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Retransmit the segment from sequence Seq.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Tcb Pointer to the TCP_CB of this TCP instance.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Seq The sequence number of the segment to be retransmitted.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval 0 Retransmission succeeded.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval -1 Error condition occurred.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncINTN
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncTcpRetransmit (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN TCP_CB *Tcb,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN TCP_SEQNO Seq
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_BUF *Nbuf;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 Len;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Compute the maxium length of retransmission. It is
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // limited by three factors:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // 1. Less than SndMss
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // 2. Must in the current send window
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // 3. Will not change the boundaries of queued segments.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TCP_SEQ_LT (Tcb->SndWl2 + Tcb->SndWnd, Seq)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DEBUG (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (EFI_D_WARN,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "TcpRetransmit: retransmission cancelled because send window too small for TCB %p\n",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Len = TCP_SUB_SEQ (Tcb->SndWl2 + Tcb->SndWnd, Seq);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Len = MIN (Len, Tcb->SndMss);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Nbuf = TcpGetSegmentSndQue (Tcb, Seq, Len);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Nbuf == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return -1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (TcpVerifySegment (Nbuf) != 0);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TcpTransmitSegment (Tcb, Nbuf) != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto OnError;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // The retransmitted buffer may be on the SndQue,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // trim TCP head because all the buffers on SndQue
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // are headless.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (Nbuf->Tcp != NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufTrim (Nbuf, (Nbuf->Tcp->HeadLen << 2), NET_BUF_HEAD);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Nbuf->Tcp = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufFree (Nbuf);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncOnError:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Nbuf != NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufFree (Nbuf);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return -1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Verify that all the segments in SndQue are in good shape.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Head Pointer to the head node of the SndQue.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval 0 At least one segment is broken.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval 1 All segments in the specific queue are in good shape.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncINTN
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncTcpCheckSndQue (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN LIST_ENTRY *Head
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LIST_ENTRY *Entry;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_BUF *Nbuf;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_SEQNO Seq;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (IsListEmpty (Head)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Initialize the Seq.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Entry = Head->ForwardLink;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Nbuf = NET_LIST_USER_STRUCT (Entry, NET_BUF, List);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Seq = TCPSEG_NETBUF (Nbuf)->Seq;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_LIST_FOR_EACH (Entry, Head) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Nbuf = NET_LIST_USER_STRUCT (Entry, NET_BUF, List);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TcpVerifySegment (Nbuf) == 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // All the node in the SndQue should has:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // SEG.SEQ = LAST_SEG.END
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Seq != TCPSEG_NETBUF (Nbuf)->Seq) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Seq = TCPSEG_NETBUF (Nbuf)->End;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Check whether to send data/SYN/FIN and piggyback an ACK.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Force If TRUE, ignore the sender's SWS avoidance algorithm
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync and send out data by force.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @return The number of bytes sent.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncINTN
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncTcpToSendData (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN OUT TCP_CB *Tcb,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN INTN Force
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 Len;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync INTN Sent;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT8 Flag;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_BUF *Nbuf;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_SEG *Seg;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_SEQNO Seq;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_SEQNO End;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT ((Tcb != NULL) && (Tcb->Sk != NULL) && (Tcb->State != TCP_LISTEN));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Sent = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((Tcb->State == TCP_CLOSED) || TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_FIN_SENT)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync do {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Compute how much data can be sent
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Len = TcpDataToSend (Tcb, Force);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Seq = Tcb->SndNxt;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT ((Tcb->State) < (sizeof (mTcpOutFlag) / sizeof (mTcpOutFlag[0])));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Flag = mTcpOutFlag[Tcb->State];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((Flag & TCP_FLG_SYN) != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Seq = Tcb->Iss;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Len = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Only send a segment without data if SYN or
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // FIN is set.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((Len == 0) && ((Flag & (TCP_FLG_SYN | TCP_FLG_FIN)) == 0)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Sent;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Nbuf = TcpGetSegment (Tcb, Seq, Len);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Nbuf == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DEBUG (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (EFI_D_ERROR,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "TcpToSendData: failed to get a segment for TCB %p\n",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto OnError;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Seg = TCPSEG_NETBUF (Nbuf);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Set the TcpSeg in Nbuf.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Len = Nbuf->TotalSize;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync End = Seq + Len;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TCP_FLG_ON (Flag, TCP_FLG_SYN)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync End++;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((Flag & TCP_FLG_FIN) != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Send FIN if all data is sent, and FIN is
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // in the window
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((TcpGetMaxSndNxt (Tcb) == Tcb->SndNxt) &&
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (GET_SND_DATASIZE (Tcb->Sk) == 0) &&
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_SEQ_LT (End + 1, Tcb->SndWnd + Tcb->SndWl2)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DEBUG (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (EFI_D_INFO,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "TcpToSendData: send FIN to peer for TCB %p in state %s\n",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync mTcpStateName[Tcb->State])
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync End++;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_CLEAR_FLG (Flag, TCP_FLG_FIN);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Seg->Seq = Seq;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Seg->End = End;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Seg->Flag = Flag;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (TcpVerifySegment (Nbuf) != 0);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (TcpCheckSndQue (&Tcb->SndQue) != 0);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Don't send an empty segment here.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Seg->End == Seg->Seq) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DEBUG (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (EFI_D_WARN,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "TcpToSendData: created a empty segment for TCB %p, free it now\n",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufFree (Nbuf);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Sent;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TcpTransmitSegment (Tcb, Nbuf) != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufTrim (Nbuf, (Nbuf->Tcp->HeadLen << 2), NET_BUF_HEAD);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Nbuf->Tcp = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((Flag & TCP_FLG_FIN) != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_FIN_SENT);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto OnError;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Sent += TCP_SUB_SEQ (End, Seq);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // All the buffers in the SndQue are headless.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (Nbuf->Tcp != NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufTrim (Nbuf, (Nbuf->Tcp->HeadLen << 2), NET_BUF_HEAD);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Nbuf->Tcp = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufFree (Nbuf);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Update the status in TCB.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb->DelayedAck = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((Flag & TCP_FLG_FIN) != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_FIN_SENT);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TCP_SEQ_GT (End, Tcb->SndNxt)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb->SndNxt = End;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!TCP_TIMER_ON (Tcb->EnabledTimer, TCP_TIMER_REXMIT)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TcpSetTimer (Tcb, TCP_TIMER_REXMIT, Tcb->Rto);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Enable RTT measurement only if not in retransmit.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Karn's algorithm requires not to update RTT when in loss.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((Tcb->CongestState == TCP_CONGEST_OPEN) && !TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_RTT_ON)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DEBUG (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (EFI_D_INFO,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "TcpToSendData: set RTT measure sequence %d for TCB %p\n",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Seq,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_RTT_ON);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb->RttSeq = Seq;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb->RttMeasure = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } while (Len == Tcb->SndMss);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Sent;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncOnError:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Nbuf != NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufFree (Nbuf);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Sent;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Send an ACK immediately.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncTcpSendAck (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN OUT TCP_CB *Tcb
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_BUF *Nbuf;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_SEG *Seg;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Nbuf = NetbufAlloc (TCP_MAX_HEAD);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Nbuf == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufReserve (Nbuf, TCP_MAX_HEAD);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Seg = TCPSEG_NETBUF (Nbuf);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Seg->Seq = Tcb->SndNxt;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Seg->End = Tcb->SndNxt;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Seg->Flag = TCP_FLG_ACK;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TcpTransmitSegment (Tcb, Nbuf) == 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_CLEAR_FLG (Tcb->CtrlFlag, TCP_CTRL_ACK_NOW);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb->DelayedAck = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufFree (Nbuf);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Send a zero probe segment. It can be used by keepalive and zero window probe.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval 0 The zero probe segment was sent out successfully.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval other An error condition occurred.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncINTN
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncTcpSendZeroProbe (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN OUT TCP_CB *Tcb
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_BUF *Nbuf;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_SEG *Seg;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync INTN Result;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Nbuf = NetbufAlloc (TCP_MAX_HEAD);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Nbuf == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return -1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufReserve (Nbuf, TCP_MAX_HEAD);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // SndNxt-1 is out of window. The peer should respond
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // with an ACK.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Seg = TCPSEG_NETBUF (Nbuf);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Seg->Seq = Tcb->SndNxt - 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Seg->End = Tcb->SndNxt - 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Seg->Flag = TCP_FLG_ACK;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Result = TcpTransmitSegment (Tcb, Nbuf);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufFree (Nbuf);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Result;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Check whether to send an ACK or delayed ACK.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncTcpToSendAck (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN OUT TCP_CB *Tcb
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 TcpNow;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Generally, TCP should send a delayed ACK unless:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // 1. ACK at least every other FULL sized segment received.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // 2. Packets received out of order.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // 3. Receiving window is open.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_ACK_NOW) || (Tcb->DelayedAck >= 1)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TcpSendAck (Tcb);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TcpNow = TcpRcvWinNow (Tcb);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TcpNow > TcpRcvWinOld (Tcb)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TcpSendAck (Tcb);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DEBUG (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (EFI_D_INFO,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "TcpToSendAck: scheduled a delayed ACK for TCB %p\n",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Schedule a delayed ACK.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb->DelayedAck++;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Send a RESET segment in response to the segment received.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Tcb Pointer to the TCP_CB of this TCP instance. May be NULL.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Head TCP header of the segment that triggers the reset.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Len Length of the segment that triggers the reset.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Local Local IP address.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Remote Remote peer's IP address.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Version IP_VERSION_4 indicates TCP is running on IP4 stack,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IP_VERSION_6 indicates TCP is running on IP6 stack.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval 0 A reset was sent or there is no need to send it.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval -1 No reset is sent.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncINTN
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncTcpSendReset (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN TCP_CB *Tcb,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN TCP_HEAD *Head,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN INT32 Len,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_IP_ADDRESS *Local,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_IP_ADDRESS *Remote,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT8 Version
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_BUF *Nbuf;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_HEAD *Nhead;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT16 HeadSum;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Don't respond to a Reset with reset.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((Head->Flag & TCP_FLG_RST) != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Nbuf = NetbufAlloc (TCP_MAX_HEAD);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Nbuf == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return -1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Nhead = (TCP_HEAD *) NetbufAllocSpace (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Nbuf,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sizeof (TCP_HEAD),
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_BUF_TAIL
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (Nhead != NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Nbuf->Tcp = Nhead;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Nhead->Flag = TCP_FLG_RST;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Derive Seq/ACK from the segment if no TCB
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // is associated with it, otherwise derive from the Tcb.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Tcb == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TCP_FLG_ON (Head->Flag, TCP_FLG_ACK)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Nhead->Seq = Head->Ack;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Nhead->Ack = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Nhead->Seq = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_SET_FLG (Nhead->Flag, TCP_FLG_ACK);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Nhead->Ack = HTONL (NTOHL (Head->Seq) + Len);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Nhead->Seq = HTONL (Tcb->SndNxt);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Nhead->Ack = HTONL (Tcb->RcvNxt);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_SET_FLG (Nhead->Flag, TCP_FLG_ACK);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Nhead->SrcPort = Head->DstPort;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Nhead->DstPort = Head->SrcPort;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Nhead->HeadLen = (UINT8) (sizeof (TCP_HEAD) >> 2);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Nhead->Res = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Nhead->Wnd = HTONS (0xFFFF);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Nhead->Checksum = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Nhead->Urg = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Version == IP_VERSION_4) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync HeadSum = NetPseudoHeadChecksum (Local->Addr[0], Remote->Addr[0], 6, 0);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync HeadSum = NetIp6PseudoHeadChecksum (&Local->v6, &Remote->v6, 6, 0);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Nhead->Checksum = TcpChecksum (Nbuf, HeadSum);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TcpSendIpPacket (Tcb, Nbuf, Local, Remote, Version);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufFree (Nbuf);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Verify that the segment is in good shape.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Nbuf The buffer that contains the segment to be checked.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval 0 The segment is broken.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval 1 The segment is in good shape.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncINTN
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncTcpVerifySegment (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN NET_BUF *Nbuf
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_HEAD *Head;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_SEG *Seg;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 Len;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Nbuf == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_CHECK_SIGNATURE (Nbuf, NET_BUF_SIGNATURE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Seg = TCPSEG_NETBUF (Nbuf);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Len = Nbuf->TotalSize;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Head = Nbuf->Tcp;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Head != NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Head->Flag != Seg->Flag) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Len -= (Head->HeadLen << 2);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TCP_FLG_ON (Seg->Flag, TCP_FLG_SYN)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Len++;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TCP_FLG_ON (Seg->Flag, TCP_FLG_FIN)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Len++;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Seg->Seq + Len != Seg->End) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync