Beispiel #1
0
void tcpcb_expire_timeouts(void)
{
    struct tcpcb_list_s *n = tcpcbs, *next;

    while (n) {
	next = n->next;
	switch (n->tcpcb.state) {
	    case TS_TIME_WAIT:
		if (TIME_GT(Now, n->tcpcb.time_wait_exp)) {
		    LEAVE_TIME_WAIT(&n->tcpcb);
		    tcpcb_remove(n);
		}
		break;
	    case TS_FIN_WAIT_1:
	    case TS_FIN_WAIT_2:
	    case TS_LAST_ACK:
	    case TS_CLOSING:
		if (TIME_GT(Now - (240 << 4), n->tcpcb.time_wait_exp)) {
		    cbs_in_user_timeout--;
		    tcpcb_remove(n);
		}
		break;
	}
	n = next;
    }
}
Beispiel #2
0
/* insert a non-pending timer into the scheduler */
void __ci_ip_timer_set(ci_netif *netif, ci_ip_timer *ts, ci_iptime_t t)
{
  ci_ni_dllist_t* bucket;
  int w;
  ci_iptime_t stime = IPTIMER_STATE(netif)->sched_ticks;

  ci_assert(TIME_GT(t, stime));
  /* this is absolute time */
  ts->time = t;

  if( TIME_LT(t, IPTIMER_STATE(netif)->closest_timer) )
    IPTIMER_STATE(netif)->closest_timer = t;

  /* Previous error in this code was to choose wheel based on time delta 
   * before timer fires (ts->time - stime). This is bogus as the timer wheels
   * work like a clock and we need to find wheel based on the absolute time
   */

  /* insert in wheel 0 if the top 3 wheels have the same time */
  if ((stime & WHEEL0_MASK) == (t & WHEEL0_MASK))
    w = 0;
  /* else, insert in wheel 1 if the top 2 wheels have the same time */
  else if ((stime & WHEEL1_MASK) == (t & WHEEL1_MASK))
    w = 1;
  /* else, insert in wheel 2 if the top wheel has the same time */
  else if ((stime & WHEEL2_MASK) == (t & WHEEL2_MASK))
    w = 2;
  else
    w = 3;

  bucket = BUCKET(netif, w, t);

  LOG_ITV(log("%s: delta=0x%x (t=0x%x-s=0x%x), w=0x%x, b=0x%x", 
         __FUNCTION__, 
         ts->time-stime, ts->time, stime, 
         w, BUCKETNO(w, ts->time)));

  /* append onto the correct bucket 
  **
  ** NB this might not be stable because a later insert with a
  ** smaller relative time will be before an earlier insert with a
  ** larger relative time. Oh well doesn't really matter
  */
  ci_ni_dllist_push_tail(netif, bucket, &ts->link);

  ci_assert(ci_ip_timer_is_link_valid(netif, ts));
  DETAILED_CHECK_TIMERS(netif);
}
Beispiel #3
0
void ci_ip_timer_state_assert_valid(ci_netif* ni, const char* file, int line)
{
  ci_ip_timer_state* ipts;
  ci_ip_timer* ts;
  ci_ni_dllist_t* bucket;
  ci_ni_dllist_link* l;
  ci_iptime_t stime, wheel_base, max_time, min_time;
  int a1, a2, a3, w, b, bit_shift;

  /* shifting a 32 bit integer left or right 32 bits has undefined results 
   * (i.e. not 0 which is required). Therefore I now use an array of mask 
   * values 
   */
  unsigned wheel_mask[CI_IPTIME_WHEELS] = 
                { WHEEL0_MASK, WHEEL1_MASK, WHEEL2_MASK, 0 };

  ipts = IPTIMER_STATE(ni);
  stime = ipts->sched_ticks;
  
  /* for each wheel */
  for(w=0; w < CI_IPTIME_WHEELS; w++) {

    /* base time of wheel */
    wheel_base = stime & wheel_mask[w];
    /* for each bucket in wheel */
    for (b=0; b < CI_IPTIME_BUCKETS; b++) {

      /* max and min relative times for this bucket */
      bit_shift = CI_IPTIME_BUCKETBITS*w;
      min_time = wheel_base + (b << bit_shift);
      max_time = min_time   + (1 << bit_shift);

      bucket = &ipts->warray[w*CI_IPTIME_BUCKETS + b];

      /* check list looks valid */
      if ( ci_ni_dllist_start(ni, bucket) == ci_ni_dllist_end(ni, bucket) ) {
        ci_assert( ci_ni_dllist_is_empty(ni, bucket) );
      }

      /* check buckets that should be empty are! */
      a3 = TIME_GT(min_time, stime) || ci_ni_dllist_is_empty(ni, bucket);

      /* run through timers in bucket */
      for (l = ci_ni_dllist_start(ni, bucket);
           l != ci_ni_dllist_end(ni, bucket);
           ci_ni_dllist_iter(ni, l) ) {

        ci_ni_dllist_link_assert_valid(ni, l);

        /* get timer */  
        ts = LINK2TIMER(l);

        /* must be in the future */
        a1 = TIME_GT(ts->time, stime);
        /* must be within time range of bucket */
        a2 = TIME_LT(ts->time, max_time) && TIME_GE(ts->time, min_time);

        /* if any of the checks fail then print out timer details */
        if (!a1 || !a2 || !a3) {
          ci_log("%s: [w=0x%x/b=0x%x] stime=0x%x", __FUNCTION__, w, b, stime);
          ci_log("    --> t=0x%x, min=0x%x, max=0x%x", ts->time, min_time, max_time);
          ci_log("    [%s line=%d]", file, line);
        }
        /* stop if assertion failed */
        ci_assert(a1 && a2 && a3);
      }
    }
  }
}