示例#1
0
static int
babel_create_routing_process (void)
{
    assert (babel_routing_process == NULL);

    /* Allocaste Babel instance. */
    babel_routing_process = XCALLOC (MTYPE_BABEL, sizeof (struct babel));

    /* Initialize timeouts */
    gettime(&babel_now);
    expiry_time = babel_now.tv_sec + roughly(30);
    source_expiry_time = babel_now.tv_sec + roughly(300);

    /* Make socket for Babel protocol. */
    protocol_socket = babel_socket(protocol_port);
    if (protocol_socket < 0) {
        zlog_err("Couldn't create link local socket: %s", safe_strerror(errno));
        goto fail;
    }

    /* Threads. */
    babel_routing_process->t_read =
    thread_add_read(master, &babel_read_protocol, NULL, protocol_socket);
    /* wait a little: zebra will announce interfaces, addresses, routes... */
    babel_routing_process->t_update =
    thread_add_timer_msec(master, babel_init_routing_process, NULL, 200L);
    schedule_auth_housekeeping();
    return 0;

fail:
    XFREE(MTYPE_BABEL, babel_routing_process);
    babel_routing_process = NULL;
    return -1;
}
示例#2
0
/**
 * @fn eigrp_update_send_GR_thread
 *
 * @param[in]		thread		contains neighbor who would receive Graceful restart
 *
 * @return int      always 0
 *
 * @par
 * Function used for sending Graceful restart Update packet
 * in thread, it is prepared for multiple chunks of packet.
 *
 * Uses nbr_gr_packet_type and t_nbr_send_gr from neighbor.
 */
int
eigrp_update_send_GR_thread(struct thread *thread)
{
	struct eigrp_neighbor *nbr;

	/* get argument from thread */
	nbr = THREAD_ARG(thread);
	/* remove this thread pointer */
	nbr->t_nbr_send_gr = NULL;

	/* if there is packet waiting in queue,
	 * schedule this thread again with small delay */
	if(nbr->retrans_queue->count > 0)
	{
		nbr->t_nbr_send_gr = thread_add_timer_msec(master, eigrp_update_send_GR_thread, nbr, 10);
		return 0;
	}

	/* send GR EIGRP packet chunk */
	eigrp_update_send_GR_part(nbr);

	/* if it wasn't last chunk, schedule this thread again */
	if(nbr->nbr_gr_packet_type != EIGRP_PACKET_PART_LAST)
		nbr->t_nbr_send_gr = thread_execute(master, eigrp_update_send_GR_thread, nbr, 0);

	return 0;
}
示例#3
0
long spf_backoff_schedule(struct spf_backoff *backoff)
{
	long rv = 0;
	struct timeval now;

	gettimeofday(&now, NULL);

	backoff_debug("SPF Back-off(%s) schedule called in state %s",
		      backoff->name, spf_backoff_state2str(backoff->state));

	backoff->last_event_time = now;

	switch (backoff->state) {
	case SPF_BACKOFF_QUIET:
		backoff->state = SPF_BACKOFF_SHORT_WAIT;
		thread_add_timer_msec(
			backoff->m, spf_backoff_timetolearn_elapsed, backoff,
			backoff->timetolearn, &backoff->t_timetolearn);
		thread_add_timer_msec(backoff->m, spf_backoff_holddown_elapsed,
				      backoff, backoff->holddown,
				      &backoff->t_holddown);
		backoff->first_event_time = now;
		rv = backoff->init_delay;
		break;
	case SPF_BACKOFF_SHORT_WAIT:
	case SPF_BACKOFF_LONG_WAIT:
		THREAD_TIMER_OFF(backoff->t_holddown);
		thread_add_timer_msec(backoff->m, spf_backoff_holddown_elapsed,
				      backoff, backoff->holddown,
				      &backoff->t_holddown);
		if (backoff->state == SPF_BACKOFF_SHORT_WAIT)
			rv = backoff->short_delay;
		else
			rv = backoff->long_delay;
		break;
	}

	backoff_debug(
		"SPF Back-off(%s) changed state to %s and returned %ld delay",
		backoff->name, spf_backoff_state2str(backoff->state), rv);
	return rv;
}
示例#4
0
int main(int argc, char **argv)
{
  int i, j;
  struct thread t;
  struct timeval **alarms;

  master = thread_master_create();

  log_buf_len = SCHEDULE_TIMERS * (TIMESTR_LEN + 1) + 1;
  log_buf_pos = 0;
  log_buf = XMALLOC(MTYPE_TMP, log_buf_len);

  expected_buf_len = SCHEDULE_TIMERS * (TIMESTR_LEN + 1) + 1;
  expected_buf_pos = 0;
  expected_buf = XMALLOC(MTYPE_TMP, expected_buf_len);

  prng = prng_new(0);

  timers = XMALLOC(MTYPE_TMP, SCHEDULE_TIMERS * sizeof(*timers));

  for (i = 0; i < SCHEDULE_TIMERS; i++)
    {
      long interval_msec;
      int ret;
      char *arg;

      /* Schedule timers to expire in 0..5 seconds */
      interval_msec = prng_rand(prng) % 5000;
      arg = XMALLOC(MTYPE_TMP, TIMESTR_LEN + 1);
      timers[i] = thread_add_timer_msec(master, timer_func, arg, interval_msec);
      ret = snprintf(arg, TIMESTR_LEN + 1, "%ld.%06ld",
                     timers[i]->u.sands.tv_sec, timers[i]->u.sands.tv_usec);
      assert(ret > 0);
      assert((size_t)ret < TIMESTR_LEN + 1);
      timers_pending++;
    }

  for (i = 0; i < REMOVE_TIMERS; i++)
    {
      int index;

      index = prng_rand(prng) % SCHEDULE_TIMERS;
      if (!timers[index])
        continue;

      XFREE(MTYPE_TMP, timers[index]->arg);
      thread_cancel(timers[index]);
      timers[index] = NULL;
      timers_pending--;
    }

  /* We create an array of pointers to the alarm times and sort
   * that array. That sorted array is used to generate a string
   * representing the expected "output" of the timers when they
   * are run. */
  j = 0;
  alarms = XMALLOC(MTYPE_TMP, timers_pending * sizeof(*alarms));
  for (i = 0; i < SCHEDULE_TIMERS; i++)
    {
      if (!timers[i])
        continue;
      alarms[j++] = &timers[i]->u.sands;
    }
  qsort(alarms, j, sizeof(*alarms), cmp_timeval);
  for (i = 0; i < j; i++)
    {
      int ret;

      ret = snprintf(expected_buf + expected_buf_pos,
                     expected_buf_len - expected_buf_pos,
                     "%ld.%06ld\n", alarms[i]->tv_sec, alarms[i]->tv_usec);
      assert(ret > 0);
      expected_buf_pos += ret;
      assert(expected_buf_pos < expected_buf_len);
    }
  XFREE(MTYPE_TMP, alarms);

  while (thread_fetch(master, &t))
    thread_call(&t);

  return 0;
}
int main(int argc, char **argv)
{
  struct prng *prng;
  int i;
  struct thread **timers;
  struct timeval tv_start, tv_lap, tv_stop;
  unsigned long t_schedule, t_remove;

  master = thread_master_create();
  prng = prng_new(0);
  timers = calloc(SCHEDULE_TIMERS, sizeof(*timers));

  /* create thread structures so they won't be allocated during the
   * time measurement */
  for (i = 0; i < SCHEDULE_TIMERS; i++)
    timers[i] = thread_add_timer_msec(master, dummy_func, NULL, 0);
  for (i = 0; i < SCHEDULE_TIMERS; i++)
    thread_cancel(timers[i]);

  quagga_gettime(QUAGGA_CLK_MONOTONIC, &tv_start);

  for (i = 0; i < SCHEDULE_TIMERS; i++)
    {
      long interval_msec;

      interval_msec = prng_rand(prng) % (100 * SCHEDULE_TIMERS);
      timers[i] = thread_add_timer_msec(master, dummy_func,
                                        NULL, interval_msec);
    }

  quagga_gettime(QUAGGA_CLK_MONOTONIC, &tv_lap);

  for (i = 0; i < REMOVE_TIMERS; i++)
    {
      int index;

      index = prng_rand(prng) % SCHEDULE_TIMERS;
      if (timers[index])
        thread_cancel(timers[index]);
      timers[index] = NULL;
    }

  quagga_gettime(QUAGGA_CLK_MONOTONIC, &tv_stop);

  t_schedule = 1000 * (tv_lap.tv_sec - tv_start.tv_sec);
  t_schedule += (tv_lap.tv_usec - tv_start.tv_usec) / 1000;

  t_remove = 1000 * (tv_stop.tv_sec - tv_lap.tv_sec);
  t_remove += (tv_stop.tv_usec - tv_lap.tv_usec) / 1000;

  printf("Scheduling %d random timers took %ld.%03ld seconds.\n",
         SCHEDULE_TIMERS, t_schedule/1000, t_schedule%1000);
  printf("Removing %d random timers took %ld.%03ld seconds.\n",
         REMOVE_TIMERS, t_remove/1000, t_remove%1000);
  fflush(stdout);

  free(timers);
  thread_master_free(master);
  prng_free(prng);
  return 0;
}
示例#6
0
/* Add schedule for SPF calculation.  To avoid frequenst SPF calc, we
   set timer for SPF calc. */
void
ospf6_spf_schedule (struct ospf6 *ospf6, unsigned int reason)
{
  unsigned long delay, elapsed, ht;
  struct timeval now, result;

  ospf6_set_spf_reason(ospf6, reason);

  if (IS_OSPF6_DEBUG_SPF(PROCESS) || IS_OSPF6_DEBUG_SPF (TIME))
    {
      char rbuf[32];
      ospf6_spf_reason_string(reason, rbuf, sizeof(rbuf));
      zlog_debug ("SPF: calculation timer scheduled (reason %s)", rbuf);
    }

  /* OSPF instance does not exist. */
  if (ospf6 == NULL)
    return;

  /* SPF calculation timer is already scheduled. */
  if (ospf6->t_spf_calc)
    {
      if (IS_OSPF6_DEBUG_SPF(PROCESS) || IS_OSPF6_DEBUG_SPF (TIME))
        zlog_debug ("SPF: calculation timer is already scheduled: %p",
                    (void *)ospf6->t_spf_calc);
      return;
    }

  /* XXX Monotic timers: we only care about relative time here. */
  now = recent_relative_time ();
  timersub (&now, &ospf6->ts_spf, &result);

  elapsed = (result.tv_sec * 1000) + (result.tv_usec / 1000);
  ht = ospf6->spf_holdtime * ospf6->spf_hold_multiplier;

  if (ht > ospf6->spf_max_holdtime)
    ht = ospf6->spf_max_holdtime;

  /* Get SPF calculation delay time. */
  if (elapsed < ht)
    {
      /* Got an event within the hold time of last SPF. We need to
       * increase the hold_multiplier, if it's not already at/past
       * maximum value, and wasn't already increased..
       */
      if (ht < ospf6->spf_max_holdtime)
        ospf6->spf_hold_multiplier++;

      /* always honour the SPF initial delay */
      if ( (ht - elapsed) < ospf6->spf_delay)
        delay = ospf6->spf_delay;
      else
        delay = ht - elapsed;
    }
  else
    {
      /* Event is past required hold-time of last SPF */
      delay = ospf6->spf_delay;
      ospf6->spf_hold_multiplier = 1;
    }

  if (IS_OSPF6_DEBUG_SPF(PROCESS) || IS_OSPF6_DEBUG_SPF (TIME))
    zlog_debug ("SPF: calculation timer delay = %ld", delay);

  zlog_info ("SPF: Scheduled in %ld msec", delay);

  ospf6->t_spf_calc =
    thread_add_timer_msec (master, ospf6_spf_calculation_thread, ospf6, delay);
}
示例#7
0
文件: svz_sisis.c 项目: ecks/sis-is
int
shim_sisis_read(struct thread * thread)
{
  struct sisis_listener *listener;
  int sisis_sock;
  uint16_t length, checksum;
  int already;
  u_int ifindex;
  struct shim_interface * si;
  struct in6_addr src;
  char src_buf[INET6_ADDRSTRLEN];
  struct in6_addr dst;
  char dst_buf[INET6_ADDRSTRLEN];

  zlog_notice("Reading packet from SISIS connection!");

  /* first of all get listener pointer. */
  listener = THREAD_ARG (thread);
  sisis_sock = THREAD_FD (thread);

  stream_reset(listener->ibuf);

  if ((already = stream_get_endp(listener->ibuf)) < SVZ_OUT_HEADER_SIZE)
  {
    ssize_t nbytes;
    if (((nbytes = stream_read_try (listener->ibuf, sisis_sock, SVZ_OUT_HEADER_SIZE-already)) == 0) || (nbytes == -1))
    {
      return -1;
    }

    if(nbytes != (SVZ_OUT_HEADER_SIZE - already))
    {
      listener->read_thread = thread_add_read (master, shim_sisis_read, listener, sisis_sock);
      return 0;
    }

    already = SVZ_OUT_HEADER_SIZE;
  }

  stream_set_getp(listener->ibuf, 0);

  length = stream_getw(listener->ibuf);
  checksum = stream_getw(listener->ibuf);

  if(length > STREAM_SIZE(listener->ibuf))
  {
    struct stream * ns; 
    zlog_warn("message size exceeds buffer size");
    ns = stream_new(length);
    stream_copy(ns, listener->ibuf);
    stream_free(listener->ibuf);
    listener->ibuf = ns; 
  }

  if(already < length)
  {
    ssize_t nbytes;
    if(((nbytes = stream_read_try(listener->ibuf, sisis_sock, length-already)) == 0) || nbytes == -1) 
    {   
      return -1; 
    }   
    if(nbytes != (length-already))
    {   
      listener->read_thread = thread_add_read (master, shim_sisis_read, listener, sisis_sock);
      return 0;
    }   
  } 

  unsigned int num_of_addrs = number_of_sisis_addrs_for_process_type(SISIS_PTYPE_RIBCOMP_OSPF6);
  unsigned int num_of_listeners = number_of_listeners();
 
  zlog_notice("Number of addr: %d", num_of_addrs);
  zlog_notice("Number of listeners: %d", num_of_listeners);

  pthread_mutex_lock(&bmap_mutex);
  struct bmap * bmap = bmap_set(checksum);

  // if we added initially
  // set timer at which to recycle bmap 
  // if there are no more processes sending data
  if(bmap->count == 0)
  {
    uint16_t * chcksum_ptr = malloc(sizeof(uint16_t));
    *chcksum_ptr = checksum;
  
    listener->bmap_thread = thread_add_timer_msec (master, svz_sisis_clean_bmap, chcksum_ptr, 100);
  }

  bmap->count++;
  zlog_notice("# of streams %d for checksum %d with length %d", bmap->count, checksum, length);
 
  float received_ratio = (float)bmap->count/(float)num_of_addrs;
  stream_putw(listener->chksum_stream, checksum);
  if((received_ratio > 1.0/2.0) && !bmap->sent)
  {
    if(are_checksums_same())
    {
      zlog_notice("Checksums are all the same");

    if(primary_listener == NULL)
      primary_listener = listener;

    reset_checksum_streams();
    svz_send(listener->ibuf);
    bmap->sent = 1;
    }
    else
    {
      zlog_notice("Checksums are not all the same");
      stream_fifo_push(listener->dif, listener->ibuf);
      listener->dif_size++;
    }
  }
  else if(!bmap->sent)
  {
    zlog_notice("Not enough processes have sent their data; buffering...");
  }
  else
  {
    zlog_notice("Data has already been sent...");
  }

  if((bmap->count == num_of_addrs) && (bmap->sent))
  {
    zlog_notice("Bmap no longer needed, freeing...");

    bmap->count = 0;
    bmap->sent = 0;

    clear_checksum_streams(checksum);
    bmap_unset(checksum);
  } 
  pthread_mutex_unlock(&bmap_mutex);

  if (sisis_sock < 0) 
    /* Connection was closed during packet processing. */
    return -1; 

  /* Register read thread. */
//  stream_reset(listener->ibuf);

  /* prepare for next packet. */
  listener->read_thread = thread_add_read (master, shim_sisis_read, listener, sisis_sock);

  return 0;
}