예제 #1
0
int main(int argc, char **argv)
{
	struct thread thread;

	master = thread_master_create(NULL);

	openzlog("grammar_sandbox", "NONE", 0, LOG_CONS | LOG_NDELAY | LOG_PID,
		 LOG_DAEMON);
	zlog_set_level(ZLOG_DEST_SYSLOG, ZLOG_DISABLED);
	zlog_set_level(ZLOG_DEST_STDOUT, LOG_DEBUG);
	zlog_set_level(ZLOG_DEST_MONITOR, ZLOG_DISABLED);

	/* Library inits. */
	cmd_init(1);
	host.name = strdup("test");
	host.domainname = strdup("testdomainname");

	vty_init(master, true);
	memory_init();
	yang_init();
	nb_init(master, NULL, 0);

	vty_stdio(vty_do_exit);

	/* Fetch next active thread. */
	while (thread_fetch(master, &thread))
		thread_call(&thread);

	/* Not reached. */
	exit(0);
}
예제 #2
0
void
ospf6_log_init ()
{
  int flag = 0;

  if (!daemon_mode)
    flag |= ZLOG_STDOUT;

  zlog_default = openzlog (progname, flag, ZLOG_OSPF6,
                 LOG_CONS|LOG_NDELAY|LOG_PERROR|LOG_PID,
                 LOG_DAEMON);
}
예제 #3
0
파일: test-sig.c 프로젝트: AsherBond/quagga
int
main (void)
{
  master = thread_master_create ();
  signal_init (master, array_size(sigs), sigs);
  
  zlog_default = openzlog("testsig", ZLOG_NONE,
                          LOG_CONS|LOG_NDELAY|LOG_PID, LOG_DAEMON);
  zlog_set_level (NULL, ZLOG_DEST_SYSLOG, ZLOG_DISABLED);
  zlog_set_level (NULL, ZLOG_DEST_STDOUT, LOG_DEBUG);
  zlog_set_level (NULL, ZLOG_DEST_MONITOR, ZLOG_DISABLED);
  
  while (thread_fetch (master, &t))
    thread_call (&t);

  exit (0);
}
예제 #4
0
int main ()
{
  struct ospf6_list *list;
  struct ospf6_list_node *node;
 
  int flag;
  flag |= ZLOG_STDOUT;
  zlog_default = openzlog ("test", flag, ZLOG_OSPF6,
                 LOG_CONS|LOG_NDELAY|LOG_PERROR|LOG_PID,
                 LOG_DAEMON);

  cmd_init (1);
  memory_init ();

  list = ospf6_list_create ();

  ospf6_list_add_index ("This", list, 0);
  ospf6_list_add_index ("is", list, 1);
  ospf6_list_add_index ("a", list, 2);
  ospf6_list_add_index ("test", list, 3);
  ospf6_list_add_index ("for", list, 4);
  ospf6_list_add_index ("list", list, 5);
  ospf6_list_add_index ("of", list, 6);
  ospf6_list_add_index ("ospf6", list, 7);
  ospf6_list_add_index ("!!", list, 8);
  ospf6_list_add_index ("!!", list, 0);

  ospf6_list_debug (list);
  for (node = ospf6_list_head (list); node; node = ospf6_list_next (node))
    {
      printf ("%s ", (char *)node->data);
    }
  printf ("\n");
  printf ("LIST: %ld LISTNODE: %ld\n",
          mstat[MTYPE_LINK_LIST].alloc, mstat[MTYPE_LINK_NODE].alloc);

  for (node = ospf6_list_head (list); node; node = ospf6_list_next (node))
    {
      if (strcmp ((char *)node->data, "test") == 0)
        ospf6_list_remove (node->data, list);
    }

  for (node = ospf6_list_head (list); node; node = ospf6_list_next (node))
    {
      printf ("%s ", (char *)node->data);
    }
  printf ("\n");
  printf ("LIST: %ld LISTNODE: %ld\n",
          mstat[MTYPE_LINK_LIST].alloc, mstat[MTYPE_LINK_NODE].alloc);

  ospf6_list_add_index ("test", list, 3);
  for (node = ospf6_list_head (list); node; node = ospf6_list_next (node))
    {
      printf ("%s ", (char *)node->data);
    }
  printf ("\n");
  printf ("LIST: %ld LISTNODE: %ld\n",
          mstat[MTYPE_LINK_LIST].alloc, mstat[MTYPE_LINK_NODE].alloc);

  ospf6_list_remove_index (list, 3);
  for (node = ospf6_list_head (list); node; node = ospf6_list_next (node))
    {
      printf ("%s ", (char *)node->data);
    }
  printf ("\n");
  printf ("LIST: %ld LISTNODE: %ld\n",
          mstat[MTYPE_LINK_LIST].alloc, mstat[MTYPE_LINK_NODE].alloc);

  ospf6_list_delete (list);

  printf ("LIST: %ld LISTNODE: %ld\n",
          mstat[MTYPE_LINK_LIST].alloc, mstat[MTYPE_LINK_NODE].alloc);

  return 0;
}
예제 #5
0
/* Main startup routine. */
int
main (int argc, char **argv)
{
  char *p;
  char *vty_addr = NULL;
  int vty_port = ZEBRA_VTY_PORT;
  int dryrun = 0;
  int batch_mode = 0;
  int daemon_mode = 0;
  char *config_file = NULL;
  char *progname;
  struct thread thread;
  char *zserv_path = NULL;

  /* Set umask before anything for security */
  umask (0027);

  /* preserve my name */
  progname = ((p = strrchr (argv[0], '/')) ? ++p : argv[0]);

  zlog_default = openzlog (progname, ZLOG_ZEBRA,
			   LOG_CONS|LOG_NDELAY|LOG_PID, LOG_DAEMON);

  while (1) 
    {
      int opt;
  
#ifdef HAVE_NETLINK  
      opt = getopt_long (argc, argv, "bdkf:i:z:hA:P:ru:g:vs:C", longopts, 0);
#else
      opt = getopt_long (argc, argv, "bdkf:i:z:hA:P:ru:g:vC", longopts, 0);
#endif /* HAVE_NETLINK */

      if (opt == EOF)
	break;

      switch (opt) 
	{
	case 0:
	  break;
	case 'b':
	  batch_mode = 1;
	case 'd':
	  daemon_mode = 1;
	  break;
	case 'k':
	  keep_kernel_mode = 1;
	  break;
	case 'C':
	  dryrun = 1;
	  break;
	case 'f':
	  config_file = optarg;
	  break;
	case 'A':
	  vty_addr = optarg;
	  break;
        case 'i':
          pid_file = optarg;
          break;
	case 'z':
	  zserv_path = optarg;
	  break;
	case 'P':
	  /* Deal with atoi() returning 0 on failure, and zebra not
	     listening on zebra port... */
	  if (strcmp(optarg, "0") == 0) 
	    {
	      vty_port = 0;
	      break;
	    } 
	  vty_port = atoi (optarg);
	  if (vty_port <= 0 || vty_port > 0xffff)
	    vty_port = ZEBRA_VTY_PORT;
	  break;
	case 'r':
	  retain_mode = 1;
	  break;
#ifdef HAVE_NETLINK
	case 's':
	  nl_rcvbufsize = atoi (optarg);
	  break;
#endif /* HAVE_NETLINK */
	case 'u':
	  zserv_privs.user = optarg;
	  break;
	case 'g':
	  zserv_privs.group = optarg;
	  break;
	case 'v':
	  print_version (progname);
	  exit (0);
	  break;
	case 'h':
	  usage (progname, 0);
	  break;
	default:
	  usage (progname, 1);
	  break;
	}
    }

  /* Make master thread emulator. */
  zebrad.master = thread_master_create ();

  /* privs initialise */
  zprivs_init (&zserv_privs);

  /* Vty related initialize. */
  signal_init (zebrad.master, Q_SIGC(zebra_signals), zebra_signals);
  cmd_init (1);
  vty_init (zebrad.master);
  memory_init ();

  /* Zebra related initialize. */
  zebra_init ();
  rib_init ();
  zebra_if_init ();
  zebra_debug_init ();
  router_id_init();
  zebra_vty_init ();
  access_list_init ();
  prefix_list_init ();
  rtadv_init ();
#ifdef HAVE_IRDP
  irdp_init();
#endif

  /* For debug purpose. */
  /* SET_FLAG (zebra_debug_event, ZEBRA_DEBUG_EVENT); */

  /* Make kernel routing socket. */
  kernel_init ();
  interface_list ();
  route_read ();

  /* Sort VTY commands. */
  sort_node ();

#ifdef HAVE_SNMP
  zebra_snmp_init ();
#endif /* HAVE_SNMP */

  /* Process the configuration file. Among other configuration
  *  directives we can meet those installing static routes. Such
  *  requests will not be executed immediately, but queued in
  *  zebra->ribq structure until we enter the main execution loop.
  *  The notifications from kernel will show originating PID equal
  *  to that after daemon() completes (if ever called).
  */
  vty_read_config (config_file, config_default);

  /* Don't start execution if we are in dry-run mode */
  if (dryrun)
    return(0);
  
  /* Clean up rib. */
  rib_weed_tables ();

  /* Exit when zebra is working in batch mode. */
  if (batch_mode)
    exit (0);

  /* Daemonize. */
  if (daemon_mode && daemon (0, 0) < 0)
    {
      zlog_err("Zebra daemon failed: %s", strerror(errno));
      exit (1);
    }

  /* Output pid of zebra. */
  pid_output (pid_file);

  /* After we have successfully acquired the pidfile, we can be sure
  *  about being the only copy of zebra process, which is submitting
  *  changes to the FIB.
  *  Clean up zebra-originated routes. The requests will be sent to OS
  *  immediately, so originating PID in notifications from kernel
  *  will be equal to the current getpid(). To know about such routes,
  * we have to have route_read() called before.
  */
  if (! keep_kernel_mode)
    rib_sweep_route ();

  /* Needed for BSD routing socket. */
  pid = getpid ();

  /* This must be done only after locking pidfile (bug #403). */
  zebra_zserv_socket_init (zserv_path);

  /* Make vty server socket. */
  vty_serv_sock (vty_addr, vty_port, ZEBRA_VTYSH_PATH);

  /* Print banner. */
  zlog_notice ("Zebra %s starting: vty@%d", QUAGGA_VERSION, vty_port);

  while (thread_fetch (zebrad.master, &thread))
    thread_call (&thread);

  /* Not reached... */
  return 0;
}
예제 #6
0
/* Main startup routine. */
int
rtm_init (int argc, char **argv)
{
  char *p;
  char *vty_addr = NULL;
  int vty_port = ZEBRA_VTY_PORT;
  int dryrun = 0;
  int batch_mode = 0;
  int daemon_mode = 0;
  char *config_file = NULL;
  char *progname;
  struct thread thread;
  char *zserv_path = NULL;

  /* Set umask before anything for security */
  umask (0027);

  /* preserve my name */
  progname = ((p = strrchr (argv[0], '/')) ? ++p : argv[0]);

  zlog_default = openzlog (progname, ZLOG_ZEBRA,
			   LOG_CONS|LOG_NDELAY|LOG_PID, LOG_DAEMON);

  /* Make master thread emulator. */
  zebrad.master = thread_master_create ();

  /* privs initialise */
  zprivs_init (&zserv_privs);

  /* Vty related initialize. */
  signal_init (zebrad.master, Q_SIGC(zebra_signals), zebra_signals);
#if 0
  /*
   * All CLI command registrations commented out 
   */
  cmd_init (1);
  vty_init (zebrad.master);
  memory_init ();
  zebra_init ();
  zebra_if_init ();
  zebra_vty_init ();
  /* Sort VTY commands. */
  sort_node ();
#endif

  /* Zebra related initialize. */
  rib_init ();
  zebra_debug_init ();
  router_id_init();
  access_list_init ();
  prefix_list_init ();
  rtadv_init ();
#ifdef HAVE_IRDP
  irdp_init();
#endif

  /* For debug purpose. */
  /* SET_FLAG (zebra_debug_event, ZEBRA_DEBUG_EVENT); */

#if 0
  /*
   * The Kernel FIB Interface is no longer needed
   */
  /* Make kernel routing socket. */
  kernel_init ();
  interface_list ();
  route_read ();
#endif


#ifdef HAVE_SNMP
  zebra_snmp_init ();
#endif /* HAVE_SNMP */

  /* Process the configuration file. Among other configuration
  *  directives we can meet those installing static routes. Such
  *  requests will not be executed immediately, but queued in
  *  zebra->ribq structure until we enter the main execution loop.
  *  The notifications from kernel will show originating PID equal
  *  to that after daemon() completes (if ever called).
  */
  vty_read_config (config_file, config_default);

  /* Don't start execution if we are in dry-run mode */
  if (dryrun)
    return(0);
  
  /* Clean up rib. */
  rib_weed_tables ();

  /* Exit when zebra is working in batch mode. */
  if (batch_mode)
    exit (0);

#if 0
  /* Daemonize. */
  if (daemon_mode && daemon (0, 0) < 0)
    {
      zlog_err("Zebra daemon failed: %s", strerror(errno));
      exit (1);
    }

  /* Output pid of zebra. */
  pid_output (pid_file);
#endif

  /* After we have successfully acquired the pidfile, we can be sure
  *  about being the only copy of zebra process, which is submitting
  *  changes to the FIB.
  *  Clean up zebra-originated routes. The requests will be sent to OS
  *  immediately, so originating PID in notifications from kernel
  *  will be equal to the current getpid(). To know about such routes,
  * we have to have route_read() called before.
  */
  if (! keep_kernel_mode)
    rib_sweep_route ();

#if 0
  /* Needed for BSD routing socket. */
  pid = getpid ();

  /* This must be done only after locking pidfile (bug #403). */
  zebra_zserv_socket_init (zserv_path);

  /* Make vty server socket. */
  vty_serv_sock (vty_addr, vty_port, ZEBRA_VTYSH_PATH);
#endif

  /* Print banner. */
  zlog_notice ("Zebra %s starting: vty@%d", QUAGGA_VERSION, vty_port);

  while (thread_fetch (zebrad.master, &thread))
    thread_call (&thread);

  /* Not reached... */
  return 0;
}
예제 #7
0
파일: ospf6-sibling.c 프로젝트: ecks/harry
int main(int argc, char *argv[])
{
  int opt;
  char * config_file = "/etc/zebralite/ospf6_sibling.conf";
  char * sisis_addr;
  struct in6_addr * sibling_addr;
  struct list * replicas;
  struct vconn * vconn;
  int retval;
  struct rfpbuf * buffer;
  struct thread thread;
  struct in6_addr * ctrl_addr;

  int sisis_fd;
  uint64_t host_num = 1;

  bool restart_mode = false;

  struct sigaction sa;

  /* Command line argument treatment. */
  while(1)
  {
    opt = getopt_long(argc, argv, "rf:", longopts, 0);

    if(opt == EOF)
      break;

    switch(opt)
    {
      case 'f':
        config_file = optarg;
        break;

      case 'r':
        restart_mode = true;
        break;
    }
  }

  zlog_default = openzlog(argv[0], ZLOG_OSPF6_SIBLING, LOG_CONS|LOG_NDELAY|LOG_PID, LOG_DAEMON);
  
  cmd_init(1);
  vty_init(master);

  ospf6_sibling_debug_init();

  // signal_init - use sigaction
  
  sa.sa_handler = terminate;
  sa.sa_flags = 0;
  sigemptyset(&sa.sa_mask);

  sigaction(SIGABRT, &sa, NULL);
  sigaction(SIGTERM, &sa, NULL);
  sigaction(SIGINT, &sa, NULL);

  /* thread master */
  master = thread_master_create();

  /* initialize ospf6 */
  ospf6_top_init(restart_mode);
  ospf6_area_init();

  sisis_addr = calloc(INET6_ADDRSTRLEN, sizeof(char));
  if((sisis_fd = sisis_init(sisis_addr, host_num, SISIS_PTYPE_OSPF6_SBLING) < 0))
  {
    printf("sisis_init error\n");
    exit(1);
  }

  sibling_addr = calloc(1, sizeof(struct in6_addr));

  inet_pton(AF_INET6, sisis_addr, sibling_addr);

  replicas = get_ospf6_sibling_addrs();

  ospf6_replicas_init(sibling_addr, replicas);

  // init ctrl clients and restart msg queue
  sibling_ctrl_init();

  // this is where the command actually gets executed
  vty_read_config(config_file, config_default);

  if(restart_mode)
  {
    zlog_notice("<---- OSPF6 Sibling starting in restart mode: %d ---->", getpid());
  }
  else
  {
    zlog_notice("<---- OSPF6 Sibling starting in normal mode: %d ---->", getpid());
  }

  zlog_debug("sibling sisis addr: %s", sisis_addr);

  free(sisis_addr);

  unsigned int num_of_controllers = number_of_sisis_addrs_for_process_type(SISIS_PTYPE_CTRL);

  if(IS_OSPF6_SIBLING_DEBUG_SISIS)
  {
    zlog_debug("num of controllers: %d", num_of_controllers);
  }
 
  sibling_ctrl_set_addresses(sibling_addr);

  // Monitor rib changes in the case that we need to restart it
  struct subscribe_to_rib_changes_info info;
  info.rib_add_ipv4_route = rib_monitor_add_ipv4_route;
  info.rib_remove_ipv4_route = rib_monitor_remove_ipv4_route;
  info.rib_add_ipv6_route = rib_monitor_add_ipv6_route;
  info.rib_remove_ipv6_route = rib_monitor_remove_ipv6_route;
  subscribe_to_rib_changes(&info);

  /* Start finite state machine, here we go! */
  while(thread_fetch(master, &thread))
    thread_call(&thread);

}
예제 #8
0
파일: main.c 프로젝트: OPSF/uClinux
/* Main startup routine. */
int
main (int argc, char **argv)
{
  char *p;
  char *vty_addr = NULL;
  int vty_port = ZEBRA_VTY_PORT;
  int batch_mode = 0;
  int daemon_mode = 0;
  char *config_file = NULL;
  char *progname;
  struct thread thread;
  void rib_weed_tables ();
  void zebra_vty_init ();

  /* Set umask before anything for security */
  umask (0027);

  /* preserve my name */
  progname = ((p = strrchr (argv[0], '/')) ? ++p : argv[0]);

  zlog_default = openzlog (progname, ZLOG_ZEBRA,
			   LOG_CONS|LOG_NDELAY|LOG_PID, LOG_DAEMON);

  while (1) 
    {
      int opt;
  
#ifdef HAVE_NETLINK  
      opt = getopt_long (argc, argv, "bdklf:i:hA:P:ru:g:vs:", longopts, 0);
#else
      opt = getopt_long (argc, argv, "bdklf:i:hA:P:ru:g:v", longopts, 0);
#endif /* HAVE_NETLINK */

      if (opt == EOF)
	break;

      switch (opt) 
	{
	case 0:
	  break;
	case 'b':
	  batch_mode = 1;
	case 'd':
	  daemon_mode = 1;
	  break;
	case 'k':
	  keep_kernel_mode = 1;
	  break;
	case 'l':
	  /* log_mode = 1; */
	  break;
	case 'f':
	  config_file = optarg;
	  break;
	case 'A':
	  vty_addr = optarg;
	  break;
        case 'i':
          pid_file = optarg;
          break;
	case 'P':
	  /* Deal with atoi() returning 0 on failure, and zebra not
	     listening on zebra port... */
	  if (strcmp(optarg, "0") == 0) 
	    {
	      vty_port = 0;
	      break;
	    } 
	  vty_port = atoi (optarg);
	  vty_port = (vty_port ? vty_port : ZEBRA_VTY_PORT);
	  break;
	case 'r':
	  retain_mode = 1;
	  break;
#ifdef HAVE_NETLINK
	case 's':
	  nl_rcvbufsize = atoi (optarg);
	  break;
#endif /* HAVE_NETLINK */
	case 'u':
	  zserv_privs.user = optarg;
	  break;
	case 'g':
	  zserv_privs.group = optarg;
	  break;
	case 'v':
	  print_version (progname);
	  exit (0);
	  break;
	case 'h':
	  usage (progname, 0);
	  break;
	default:
	  usage (progname, 1);
	  break;
	}
    }

  /* Make master thread emulator. */
  zebrad.master = thread_master_create ();

  /* privs initialise */
  zprivs_init (&zserv_privs);

  /* Vty related initialize. */
  signal_init (zebrad.master, Q_SIGC(zebra_signals), zebra_signals);
  cmd_init (1);
  vty_init (zebrad.master);
  memory_init ();

  /* Zebra related initialize. */
  zebra_init ();
  rib_init ();
  zebra_if_init ();
  zebra_debug_init ();
  router_id_init();
  zebra_vty_init ();
  access_list_init ();
  rtadv_init ();
#ifdef HAVE_IRDP
  irdp_init();
#endif

  /* For debug purpose. */
  /* SET_FLAG (zebra_debug_event, ZEBRA_DEBUG_EVENT); */

  /* Make kernel routing socket. */
  kernel_init ();
  interface_list ();
  route_read ();

  /* Sort VTY commands. */
  sort_node ();

#ifdef HAVE_SNMP
  zebra_snmp_init ();
#endif /* HAVE_SNMP */

  /* Clean up self inserted route. */
  if (! keep_kernel_mode)
    rib_sweep_route ();

  /* Configuration file read*/
  vty_read_config (config_file, config_default);

  /* Clean up rib. */
  rib_weed_tables ();

  /* Exit when zebra is working in batch mode. */
  if (batch_mode)
    exit (0);

  /* Needed for BSD routing socket. */
  old_pid = getpid ();

  /* Daemonize. */
  if (daemon_mode)
    daemon (0, 0);

  /* Output pid of zebra. */
  pid_output (pid_file);

  /* Needed for BSD routing socket. */
  pid = getpid ();

  /* Make vty server socket. */
  vty_serv_sock (vty_addr, vty_port, ZEBRA_VTYSH_PATH);

  /* Print banner. */
  zlog_notice ("Zebra %s starting: vty@%d", QUAGGA_VERSION, vty_port);

  while (thread_fetch (zebrad.master, &thread))
    thread_call (&thread);

  /* Not reached... */
  exit (0);
}
예제 #9
0
int main (int argc, char *argv[])
{
	/*
	  1. acquire all simulation parameters or use the default values
	  2. generate the simulation begin event @time = 0
	  3. add this event to the timer queue
	  4. while (simulatio not finished) {
	        advance the simu time by 1 time unit (ms)
	     }
	 */
	/* 1. */
	simu_paras_t spt;
	spt.t.packet_size = PKT_SIZE; /* bytes */
	spt.rl.link_distance = 0;
	spt.rl.prop_delay = MS2US(270);	   /* 270 ms */
	spt.rl.link_bandwidth = BANDWIDTH; /* bps */
	spt.rl.per = PER;					/* x/10000 */

	/* this should be set when the mac pdu is build (at the tx_begin_event) */
	/*
	spt.tx_delay = ( (1e3 * OCTET *
						   (spt.t.packet_size +
							MAC_HEADER_SIZE +
							PHY_HEADER_SIZE))
						  / spt.rl.link_bandwidth );
	*/					 

						  
	/* rlc params */
	spt.rlc_paras.ump.t_Reordering = MS2US(T_REORDERING); /* ms */
	spt.rlc_paras.ump.UM_Window_Size = UWSize;	   /* window size */
	spt.rlc_paras.ump.sn_FieldLength = SN_LEN;	   /* sn length */

#define PTIMER_MEM_MAX 4096*16
	spt.g_mem_ptimer_t = fastalloc_create(sizeof(ptimer_t), PTIMER_MEM_MAX, 0, 100);
	assert(spt.g_mem_ptimer_t);

/* #define PACKET_MEM_MAX (4096*16*16*8) */
/* 	spt.g_mem_packet_t = fastalloc_create(sizeof(packet_t), PACKET_MEM_MAX, 0, 100); */
/* 	assert(spt.g_mem_packet_t); */
	
	/* @transmitter */
	/* @receiver */
	/* leave these to be done at the simulatioin begin event */

	/* init log */
	zlog_default = openzlog(ZLOG_STDOUT);
	zlog_set_pri(zlog_default, LOG_INFO);
	zlog_reset_flag(zlog_default, ZLOG_LOGTIME); /* no time display */

	ZLOG_DEBUG("pkt size = %d, prop delay = %d, link bandwidth = %d\n",
			   spt.t.packet_size, spt.rl.prop_delay, spt.rl.link_bandwidth);

	/* 2. */
	/* FIXME: simu time unit: 1us! */
	ptimer_t simu_begin_timer = {
		.duration = 0,
		.onexpired_func = simu_begin_event,
		.param[0] = (void*) &spt,
		.param[1] = (void*) SIMU_BEGIN,
	};

	time_t t;
	
	srand((unsigned) time(&t));
	
	/* 3. */
	rlc_init();
	rlc_timer_start(&simu_begin_timer);

	/* 4. */
	int step_in_us = 1;
	while (g_is_finished == NOT_FINISHED && g_time_elasped_in_us <= MS2US(S2MS(SIMU_TIME)) ) {
		rlc_timer_push(step_in_us);		/* us */
		g_time_elasped_in_us += step_in_us;

		if ( g_time_elasped_in_us % (int)MS2US(S2MS(1)) == 0 ) {
			ZLOG_INFO("simu time = %f\n", g_time_elasped_in_us/MS2US(S2MS(1)));
		}
	}

	/* output the simu result */
	ZLOG_DEBUG("time_elasped_in_us = %d\n", g_time_elasped_in_us);

	int cnt = 0;
	int output_e2e_delay = 1;

	int n_rxok = 0, n_rxerr = 0;
	while (!DLLIST_EMPTY(&g_sink_packet_list)) {
		packet_t *pktt = (packet_t*) DLLIST_HEAD(&g_sink_packet_list);

		/* 1. tx throughput */
		// output_tx_throughput(pktt);
		// output_rx_throughput(pktt);

		/* 2. e2e delay */
		switch (pktt->ptt) {
		case RX_OK:
			n_rxok++;
			break;
		case RX_ERR:
			n_rxerr++;
			break;
			
		default:
			assert(0);
			break;
		}

		if( output_e2e_delay ) {
			if (pktt->ptt == RX_OK )
				ZLOG_INFO("SN, buffering: %u, %u\n", pktt->sequence_no, pktt->rx_deliver_timestamp - pktt->rx_end_timestamp);
		}
		
		dllist_remove(&g_sink_packet_list, &(pktt->node));
		cnt++;

		// FASTFREE(spt.g_mem_packet_t, pktt);
		free(pktt); pktt = NULL;
	}

	output_tx_throughput(NULL);
	output_rx_throughput(NULL);

	ZLOG_INFO("n_txed = %d, n_rxok = %d, n_rxerr = %d\n", cnt, n_rxok, n_rxerr);

	return 0;
}