Пример #1
0
/**
 * Called every 500 ms and implements the retransmission timer and the timer that
 * removes PCBs that have been in TIME-WAIT for enough time. It also increments
 * various timers such as the inactivity timer in each PCB.
 *
 * Automatically called from tcp_tmr().
 */
void
tcp_slowtmr(void)
{
  struct tcp_pcb *pcb, *pcb2, *prev;
  u16_t eff_wnd;
  u8_t pcb_remove;      /* flag if a PCB should be removed */
  u8_t pcb_reset;       /* flag if a RST should be sent when removing */
  err_t err;

  err = ERR_OK;

  ++tcp_ticks;

  /* Steps through all of the active PCBs. */
  prev = NULL;
  pcb = tcp_active_pcbs;
  if (pcb == NULL) {
    LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: no active pcbs\n"));
  }
  while (pcb != NULL) {
    LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: processing active pcb\n"));
    LWIP_ASSERT("tcp_slowtmr: active pcb->state != CLOSED\n", pcb->state != CLOSED);
    LWIP_ASSERT("tcp_slowtmr: active pcb->state != LISTEN\n", pcb->state != LISTEN);
    LWIP_ASSERT("tcp_slowtmr: active pcb->state != TIME-WAIT\n", pcb->state != TIME_WAIT);

    pcb_remove = 0;
    pcb_reset = 0;
    if (pcb->state == SYN_SENT && pcb->nrtx == TCP_SYNMAXRTX) {
      ++pcb_remove;
      LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: max SYN retries reached\n"));
    }
    else if (pcb->nrtx == TCP_MAXRTX) {
      ++pcb_remove;
      LWIP_DEBUGF(TCP_DEBUG, ("tcp_slowtmr: max DATA retries reached\n"));
    } else {
      if (pcb->persist_backoff > 0) {
        /* If snd_wnd is zero, use persist timer to send 1 byte probes
         * instead of using the standard retransmission mechanism. */
        pcb->persist_cnt++;
        if (pcb->persist_cnt >= tcp_persist_backoff[pcb->persist_backoff-1]) {
          pcb->persist_cnt = 0;
          if (pcb->persist_backoff < sizeof(tcp_persist_backoff)) {
            pcb->persist_backoff++;
          }
          tcp_zero_window_probe(pcb);
        }
      } else {
        /* Increase the retransmission timer if it is running */
        if(pcb->rtime >= 0)
          ++pcb->rtime;

        if (pcb->unacked != NULL && pcb->rtime >= pcb->rto) {
          /* Time for a retransmission. */
          LWIP_DEBUGF(TCP_RTO_DEBUG, ("tcp_slowtmr: rtime %"S16_F
                                      " pcb->rto %"S16_F"\n",
                                      pcb->rtime, pcb->rto));

          /* Double retransmission time-out unless we are trying to
           * connect to somebody (i.e., we are in SYN_SENT). */
          if (pcb->state != SYN_SENT) {
            pcb->rto = ((pcb->sa >> 3) + pcb->sv) << tcp_backoff[pcb->nrtx];
          }

          /* Reset the retransmission timer. */
          pcb->rtime = 0;

          /* Reduce congestion window and ssthresh. */
          eff_wnd = LWIP_MIN(pcb->cwnd, pcb->snd_wnd);
          pcb->ssthresh = eff_wnd >> 1;
          if (pcb->ssthresh < pcb->mss) {
            pcb->ssthresh = pcb->mss * 2;
          }
          pcb->cwnd = pcb->mss;
          LWIP_DEBUGF(TCP_CWND_DEBUG, ("tcp_slowtmr: cwnd %"U16_F
                                       " ssthresh %"U16_F"\n",
                                       pcb->cwnd, pcb->ssthresh));
 
          /* The following needs to be called AFTER cwnd is set to one
             mss - STJ */
          tcp_rexmit_rto(pcb);
        }
      }
    }
Пример #2
0
/**
 * Called every 500 ms and implements the retransmission timer and the timer that
 * removes PCBs that have been in TIME-WAIT for enough time. It also increments
 * various timers such as the inactivity timer in each PCB.
 *
 * Automatically called from tcp_tmr().
 */
void tcp_slowtmr(void)
{
    TCP_PCB *pcb, *pcb2, *prev;
    uint16 eff_wnd;
    uint8 err= ERR_OK;

    ++tcp_ticks;

    /* Steps through all of the active PCBs. */
    prev = NULL;
    pcb = &stTcpPcb;

    if (pcb->state == SYN_SENT && pcb->nrtx == TCP_SYNMAXRTX)
    {
        printf("SYN SENT CLOSED\n");
        pcb->state = CLOSED;
        tcp_pcb_purge(pcb);
	    tcp_close(pcb);
        return;
    }
    else if (pcb->nrtx == TCP_MAXRTX)
    {
        printf("TCP MAXRTX CLOSED\n");
        pcb->state = CLOSED;
        tcp_pcb_purge(pcb);
	    tcp_close(pcb);
        return;
    }
    else
    {
        if (pcb->persist_backoff > 0)
        {
            /* If snd_wnd is zero, use persist timer to send 1 byte probes
             * instead of using the standard retransmission mechanism. */
            pcb->persist_cnt++;
            if (pcb->persist_cnt >= tcp_persist_backoff[pcb->persist_backoff-1])
            {
                pcb->persist_cnt = 0;
                if (pcb->persist_backoff < sizeof(tcp_persist_backoff))
                {
                    pcb->persist_backoff++;
                }
                tcp_zero_window_probe(pcb);
            }
        }
        else
        {
            /* Increase the retransmission timer if it is running */
            if (pcb->rtime >= 0)
                ++pcb->rtime;

            if (pcb->unacked != NULL && pcb->rtime >= pcb->rto)
            {
                /* Double retransmission time-out unless we are trying to
                 * connect to somebody (i.e., we are in SYN_SENT). */
                if (pcb->state != SYN_SENT)
                {
                    pcb->rto = ((pcb->sa >> 3) + pcb->sv) << tcp_backoff[pcb->nrtx];
                }

                /* Reset the retransmission timer. */
                pcb->rtime = 0;

                /* Reduce congestion window and ssthresh. */
                eff_wnd = LWIP_MIN(pcb->cwnd, pcb->snd_wnd);
                pcb->ssthresh = eff_wnd >> 1;
                if (pcb->ssthresh < pcb->mss)
                {
                    pcb->ssthresh = pcb->mss * 2;
                }
                pcb->cwnd = pcb->mss;

                /* The following needs to be called AFTER cwnd is set to one
                   mss - STJ */
                tcp_rexmit_rto(pcb);
            }
        }
    }