⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tcpstate.c

📁 用于嵌入式系统的TCP/IP协议栈
💻 C
📖 第 1 页 / 共 3 页
字号:
  /*-------------------------------------------------------------------*/  /* Return -1 if segment does not have acknowledgment flag set.       */  /*-------------------------------------------------------------------*/  if ((Net.Tcp->flags & TCPF_ACK) == 0)    return -1;  /*-------------------------------------------------------------------*/  /* Check for absurdly high acknowledgment number.                    */  /*-------------------------------------------------------------------*/  if (SEQ_GT(Net.Tcp->ack_num, Sock->max_snt))  {    if (Sock->state == SS_SYNRCVD)      TcpReset();    else      TcpJustAck(Sock);    return -1;  }  /*-------------------------------------------------------------------*/  /* Compute number of new octets acknowledged. Return if old ack.     */  /*-------------------------------------------------------------------*/  if (SEQ_LT(Net.Tcp->ack_num, Sock->snt_una))    return 0;  /*-------------------------------------------------------------------*/  /* Update window if any of three conditions are met.                 */  /*-------------------------------------------------------------------*/  acked = Net.Tcp->ack_num - Sock->snt_una;  if (SEQ_LT(Sock->lw_seq, Net.Tcp->seq_num) || acked ||      (Sock->snd_window < Net.Tcp->window))  {    /*-----------------------------------------------------------------*/    /* Remember increased sequence number and record peer's window.    */    /*-----------------------------------------------------------------*/    if (SEQ_LT(Sock->lw_seq, Net.Tcp->seq_num))      Sock->lw_seq = Net.Tcp->seq_num;    Sock->snd_window = Net.Tcp->window;    win_update = TRUE;    /*-----------------------------------------------------------------*/    /* Check if window is open.                                        */    /*-----------------------------------------------------------------*/    if (Sock->snd_window)    {      /*---------------------------------------------------------------*/      /* If window edge has advanced while in "transmit", try output.  */      /*---------------------------------------------------------------*/      if (Sock->out_state == TCPO_XMIT)      {        tcpseq old_end = Sock->snt_una + Sock->snd_window;        tcpseq new_end = Net.Tcp->ack_num + Net.Tcp->window;        if (SEQ_GT(new_end, old_end))          Net.TryOut = TRUE;      }      /*---------------------------------------------------------------*/      /* Else change to "transmit" if window has opened in "persist".  */      /*---------------------------------------------------------------*/      else if (Sock->out_state == TCPO_PERSIST)      {        Sock->out_state = TCPO_XMIT;        Sock->flags &= ~SF_TIMING_RTT;        Sock->retrans_count = 0;        NetTimerStop(&Sock->out_tmr);        Net.TryOut = TRUE;      }    }  }  /*-------------------------------------------------------------------*/  /* Check if state is "transmit".                                     */  /*-------------------------------------------------------------------*/  if (Sock->out_state == TCPO_XMIT)  {    /*-----------------------------------------------------------------*/    /* Check if nothing was acknowledged.                              */    /*-----------------------------------------------------------------*/    if (acked == 0)    {      /*---------------------------------------------------------------*/      /* Check if ack is not a complete duplicate.                     */      /*---------------------------------------------------------------*/      if (RxBuf->length || win_update)      {        Sock->dup_acks = 0;      }      /*---------------------------------------------------------------*/      /* Else perform fast retransmission after three duplicate acks.  */      /*---------------------------------------------------------------*/      else if (++Sock->dup_acks == FAST_RXMIT_THRES)      {        tcpseq snd_nxt;        /*-------------------------------------------------------------*/        /* Set slow start threshold to max(half flight size, two MSS). */        /*-------------------------------------------------------------*/        Sock->ssthresh = max(((Sock->snd_nxt - Sock->snt_una) >> 1),                             (Sock->snd_mss << 1));        /*-------------------------------------------------------------*/        /* Resend the indicated missing segment.                       */        /*-------------------------------------------------------------*/        snd_nxt = Sock->snd_nxt;        Sock->snd_nxt = Sock->snt_una;        TcpSendSeg(Sock, Sock->snd_mss);        Sock->snd_nxt = snd_nxt;        /*-------------------------------------------------------------*/        /* Cancel round trip timing and restart output timer.          */        /*-------------------------------------------------------------*/        Sock->flags &= ~SF_TIMING_RTT;        NetTimerStart(&Sock->out_tmr, Sock->retrans_timeo);        /*-------------------------------------------------------------*/        /* Set congestion window to slow-start threshold plus segments */        /* which triggered the duplicate acknowledgments.              */        /*-------------------------------------------------------------*/        Sock->snd_cwnd = Sock->ssthresh +                         FAST_RXMIT_THRES * Sock->snd_mss;      }      /*---------------------------------------------------------------*/      /* Follow with fast recovery until ack of new data arrives.      */      /*---------------------------------------------------------------*/      else if (Sock->dup_acks > FAST_RXMIT_THRES)      {        Sock->snd_cwnd += Sock->snd_mss;        Net.TryOut = TRUE;      }      return 0;    }    /*-----------------------------------------------------------------*/    /* Data was acknowledged. Stop timer and schedule next output.     */    /*-----------------------------------------------------------------*/    NetTimerStop(&Sock->out_tmr);    Net.TryOut = TRUE;    /*-----------------------------------------------------------------*/    /* Update timeout if acknowledged transmission was measured.       */    /*-----------------------------------------------------------------*/    if ((Sock->flags & SF_TIMING_RTT) &&         SEQ_GT(Net.Tcp->ack_num, Sock->rtt_seq))    {      uint rrt;   /* raw round trip */      int error;  /* deviation from smoothed round trip estimate */      /*---------------------------------------------------------------*/      /* Calculate round trip time.                                    */      /*---------------------------------------------------------------*/      rrt = NetTickCount + Sock->retrans_timeo - Sock->out_tmr.time_due;      /*---------------------------------------------------------------*/      /* Initialization after first acknowledgment.                    */      /*---------------------------------------------------------------*/      if (Sock->srtt == 0)      {        Sock->srtt = (rrt + TICKS_PER_SEC / 2) << 3; /* scaling by 8 */        Sock->rttvar = Sock->srtt >> 2;              /* scaling by 4 */      }      /*---------------------------------------------------------------*/      /* "srtt" is scaled by 8, so this is really error = rrt - srtt.  */      /*---------------------------------------------------------------*/      error = rrt - (Sock->srtt >> 3);      /*---------------------------------------------------------------*/      /* "srtt" is scaled by 8, so this is srtt = srtt + error/8.      */      /*---------------------------------------------------------------*/      Sock->srtt += error;      /*---------------------------------------------------------------*/      /* Convert error to absolute value.                              */      /*---------------------------------------------------------------*/      if (error < 0)        error = -error;      /*---------------------------------------------------------------*/      /* "rttvar" is scaled by 4, so this is really                    */      /*  rttvar = rttvar + (|error| - rttvar)/4                       */      /*---------------------------------------------------------------*/      Sock->rttvar += error - (Sock->rttvar >> 2);      /*---------------------------------------------------------------*/      /* "srtt" is scaled by 8 and rttvar scaled by 4, so this is      */      /*  rto = srtt + 4 * rttvar                                      */      /*---------------------------------------------------------------*/      Sock->retrans_timeo = (Sock->srtt >> 3) + Sock->rttvar;      /*---------------------------------------------------------------*/      /* Ensure retransmit period not reduced below lower bound.       */      /*---------------------------------------------------------------*/      if (Sock->retrans_timeo < MIN_RXT)        Sock->retrans_timeo = MIN_RXT;      /*---------------------------------------------------------------*/      /* Record that round trip timing is no longer active.            */      /*---------------------------------------------------------------*/      Sock->flags &= ~SF_TIMING_RTT;    }  }  /*-------------------------------------------------------------------*/  /* Else processing for other output states.                          */  /*-------------------------------------------------------------------*/  else  {    /*-----------------------------------------------------------------*/    /* If state is "persist", any ack resets retransmission count.     */    /*-----------------------------------------------------------------*/    if (Sock->out_state == TCPO_PERSIST)      Sock->retrans_count = 0;    /*-----------------------------------------------------------------*/    /* Finished if no data was acknowledged.                           */    /*-----------------------------------------------------------------*/    if (acked == 0)      return 0;    /*-----------------------------------------------------------------*/    /* If state is "retransmit", ack moves state to "transmit".        */    /*-----------------------------------------------------------------*/    if (Sock->out_state == TCPO_REXMT)    {      Sock->out_state = TCPO_XMIT;      Sock->flags &= ~SF_TIMING_RTT;      Sock->retrans_count = 0;      NetTimerStop(&Sock->out_tmr);      Net.TryOut = TRUE;    }  }  /*-------------------------------------------------------------------*/  /* Update unacknowledged send start and next sequence number sent.   */  /*-------------------------------------------------------------------*/  Sock->snt_una = Net.Tcp->ack_num;  if (SEQ_GT(Net.Tcp->ack_num, Sock->snd_nxt))    Sock->snd_nxt = Net.Tcp->ack_num;  /*-------------------------------------------------------------------*/  /* Clear send urgent flag if urgent data has been acknowledged.      */  /*-------------------------------------------------------------------*/  if ((Sock->flags & SF_SUPOK) &&      SEQ_GE(Net.Tcp->ack_num, Sock->surg_seq))    Sock->flags &= ~SF_SUPOK;  /*-------------------------------------------------------------------*/  /* Clear send SYN flag if SYN has been acknowledged.                 */  /*-------------------------------------------------------------------*/  if (Sock->flags & TCPF_SYN)  {    --acked;    Sock->flags &= ~TCPF_SYN;  }  /*-------------------------------------------------------------------*/  /* Clear send FIN flag if FIN has been acknowledged.                 */  /*-------------------------------------------------------------------*/  if ((Sock->flags & SF_SNDFIN) &&      SEQ_GT(Net.Tcp->ack_num, Sock->fin_seq))  {    --acked;    Sock->flags &= ~SF_SNDFIN;  }  /*-------------------------------------------------------------------*/  /* Check if any data was acknowledged.                               */  /*-------------------------------------------------------------------*/  if (acked)  {    /*-----------------------------------------------------------------*/    /* First ack after fast recovery deflates the congestion window.   */    /*-----------------------------------------------------------------*/    if (Sock->dup_acks >= FAST_RXMIT_THRES)    {      Sock->snd_cwnd = Sock->ssthresh;    }    /*-----------------------------------------------------------------*/    /* Else acknowledgment increases congestion window.                */    /*-----------------------------------------------------------------*/    else    {      int incr;      /*---------------------------------------------------------------*/      /* If congestion window <= slow-start threshold, use slow-start. */      /*---------------------------------------------------------------*/      if (Sock->snd_cwnd <= Sock->ssthresh)        incr = Sock->snd_mss;    /* exponential increase */      /*---------------------------------------------------------------*/      /* Else use congestion avoidance algorithm (additive increase).  */      /*---------------------------------------------------------------*/      else      {        incr = (Sock->snd_mss * Sock->snd_mss) / Sock->snd_cwnd;        incr = max(incr, 1);      }      /*---------------------------------------------------------------*/      /* Increase congestion window until bigger than send buffer.     */      /*---------------------------------------------------------------*/      if (Sock->snd_cwnd < Sock->sb_size)        Sock->snd_cwnd += incr;    }    /*-----------------------------------------------------------------*/    /* Any data acknowledgment resets duplicate ack counting.          */    /*-----------------------------------------------------------------*/    Sock->dup_acks = 0;    /*-----------------------------------------------------------------*/    /* Update send buffer and post event.                              */    /*-----------------------------------------------------------------*/    Sock->sb_start = (Sock->sb_start + acked) % Sock->sb_size;    TcpAssert(Sock->sb_count >= acked);    Sock->sb_count -= acked;    NetPostEvent(Sock, SE_DATA_ACKED);  }  return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -