示例#1
0
/*
 * Allocate a default DCE and a hash table for per-IP address DCEs
 */
void
dce_stack_init(ip_stack_t *ipst)
{
	int	i;

	ipst->ips_dce_default = kmem_cache_alloc(dce_cache, KM_SLEEP);
	bzero(ipst->ips_dce_default, sizeof (dce_t));
	ipst->ips_dce_default->dce_flags = DCEF_DEFAULT;
	ipst->ips_dce_default->dce_generation = DCE_GENERATION_INITIAL;
	ipst->ips_dce_default->dce_last_change_time =
	    TICK_TO_SEC(ddi_get_lbolt64());
	ipst->ips_dce_default->dce_refcnt = 1;	/* Should never go away */
	ipst->ips_dce_default->dce_ipst = ipst;

	/* This must be a power of two since we are using IRE_ADDR_HASH macro */
	ipst->ips_dce_hashsize = 256;
	ipst->ips_dce_hash_v4 = kmem_zalloc(ipst->ips_dce_hashsize *
	    sizeof (dcb_t), KM_SLEEP);
	ipst->ips_dce_hash_v6 = kmem_zalloc(ipst->ips_dce_hashsize *
	    sizeof (dcb_t), KM_SLEEP);
	for (i = 0; i < ipst->ips_dce_hashsize; i++) {
		rw_init(&ipst->ips_dce_hash_v4[i].dcb_lock, NULL, RW_DEFAULT,
		    NULL);
		rw_init(&ipst->ips_dce_hash_v6[i].dcb_lock, NULL, RW_DEFAULT,
		    NULL);
	}
}
示例#2
0
int
getrusage(int who, struct rusage * rusage)
{
#ifdef WIN32
	if (rusage)
		memset(rusage, 0, sizeof(rusage));
#else
	struct tms	tms;
	int			tick_rate = CLK_TCK;	/* ticks per second */
	clock_t		u,
				s;

	if (rusage == (struct rusage *) NULL)
	{
		errno = EFAULT;
		return -1;
	}
	if (times(&tms) < 0)
	{
		/* errno set by times */
		return -1;
	}
	switch (who)
	{
		case RUSAGE_SELF:
			u = tms.tms_utime;
			s = tms.tms_stime;
			break;
		case RUSAGE_CHILDREN:
			u = tms.tms_cutime;
			s = tms.tms_cstime;
			break;
		default:
			errno = EINVAL;
			return -1;
	}
#define TICK_TO_SEC(T, RATE)	((T)/(RATE))
#define TICK_TO_USEC(T,RATE)	(((T)%(RATE)*1000000)/RATE)
	rusage->ru_utime.tv_sec = TICK_TO_SEC(u, tick_rate);
	rusage->ru_utime.tv_usec = TICK_TO_USEC(u, tick_rate);
	rusage->ru_stime.tv_sec = TICK_TO_SEC(s, tick_rate);
	rusage->ru_stime.tv_usec = TICK_TO_USEC(u, tick_rate);
#endif
	return 0;
}
示例#3
0
/*
 * Atomically looks for a non-default DCE, and if not found tries to create one.
 * If there is no memory it returns NULL.
 * When an entry is created we increase the generation number on
 * the default DCE so that conn_ip_output will detect there is a new DCE.
 * ifindex should only be used with link-local addresses.
 */
dce_t *
dce_lookup_and_add_v6(const in6_addr_t *dst, uint_t ifindex, ip_stack_t *ipst)
{
	uint_t		hash;
	dcb_t		*dcb;
	dce_t		*dce;

	/* We should not create entries for link-locals w/o an ifindex */
	ASSERT(!(IN6_IS_ADDR_LINKSCOPE(dst)) || ifindex != 0);

	hash = IRE_ADDR_HASH_V6(*dst, ipst->ips_dce_hashsize);
	dcb = &ipst->ips_dce_hash_v6[hash];
	rw_enter(&dcb->dcb_lock, RW_WRITER);
	for (dce = dcb->dcb_dce; dce != NULL; dce = dce->dce_next) {
		if (IN6_ARE_ADDR_EQUAL(&dce->dce_v6addr, dst) &&
		    dce->dce_ifindex == ifindex) {
			mutex_enter(&dce->dce_lock);
			if (!DCE_IS_CONDEMNED(dce)) {
				dce_refhold(dce);
				mutex_exit(&dce->dce_lock);
				rw_exit(&dcb->dcb_lock);
				return (dce);
			}
			mutex_exit(&dce->dce_lock);
		}
	}

	dce = kmem_cache_alloc(dce_cache, KM_NOSLEEP);
	if (dce == NULL) {
		rw_exit(&dcb->dcb_lock);
		return (NULL);
	}
	bzero(dce, sizeof (dce_t));
	dce->dce_ipst = ipst;	/* No netstack_hold */
	dce->dce_v6addr = *dst;
	dce->dce_ifindex = ifindex;
	dce->dce_generation = DCE_GENERATION_INITIAL;
	dce->dce_ipversion = IPV6_VERSION;
	dce->dce_last_change_time = TICK_TO_SEC(ddi_get_lbolt64());
	dce_refhold(dce);	/* For the hash list */

	/* Link into list */
	if (dcb->dcb_dce != NULL)
		dcb->dcb_dce->dce_ptpn = &dce->dce_next;
	dce->dce_next = dcb->dcb_dce;
	dce->dce_ptpn = &dcb->dcb_dce;
	dcb->dcb_dce = dce;
	dce->dce_bucket = dcb;
	atomic_add_32(&dcb->dcb_cnt, 1);
	dce_refhold(dce);	/* For the caller */
	rw_exit(&dcb->dcb_lock);

	/* Initialize dce_ident to be different than for the last packet */
	dce->dce_ident = ipst->ips_dce_default->dce_ident + 1;
	dce_increment_generation(ipst->ips_dce_default);
	return (dce);
}
示例#4
0
/*
 * Atomically looks for a non-default DCE, and if not found tries to create one.
 * If there is no memory it returns NULL.
 * When an entry is created we increase the generation number on
 * the default DCE so that conn_ip_output will detect there is a new DCE.
 */
dce_t *
dce_lookup_and_add_v4(ipaddr_t dst, ip_stack_t *ipst)
{
	uint_t		hash;
	dcb_t		*dcb;
	dce_t		*dce;

	hash = IRE_ADDR_HASH(dst, ipst->ips_dce_hashsize);
	dcb = &ipst->ips_dce_hash_v4[hash];
	rw_enter(&dcb->dcb_lock, RW_WRITER);
	for (dce = dcb->dcb_dce; dce != NULL; dce = dce->dce_next) {
		if (dce->dce_v4addr == dst) {
			mutex_enter(&dce->dce_lock);
			if (!DCE_IS_CONDEMNED(dce)) {
				dce_refhold(dce);
				mutex_exit(&dce->dce_lock);
				rw_exit(&dcb->dcb_lock);
				return (dce);
			}
			mutex_exit(&dce->dce_lock);
		}
	}
	dce = kmem_cache_alloc(dce_cache, KM_NOSLEEP);
	if (dce == NULL) {
		rw_exit(&dcb->dcb_lock);
		return (NULL);
	}
	bzero(dce, sizeof (dce_t));
	dce->dce_ipst = ipst;	/* No netstack_hold */
	dce->dce_v4addr = dst;
	dce->dce_generation = DCE_GENERATION_INITIAL;
	dce->dce_ipversion = IPV4_VERSION;
	dce->dce_last_change_time = TICK_TO_SEC(ddi_get_lbolt64());
	dce_refhold(dce);	/* For the hash list */

	/* Link into list */
	if (dcb->dcb_dce != NULL)
		dcb->dcb_dce->dce_ptpn = &dce->dce_next;
	dce->dce_next = dcb->dcb_dce;
	dce->dce_ptpn = &dcb->dcb_dce;
	dcb->dcb_dce = dce;
	dce->dce_bucket = dcb;
	dce_refhold(dce);	/* For the caller */
	rw_exit(&dcb->dcb_lock);

	/* Initialize dce_ident to be different than for the last packet */
	dce->dce_ident = ipst->ips_dce_default->dce_ident + 1;

	dce_increment_generation(ipst->ips_dce_default);
	return (dce);
}
示例#5
0
static void* flush_thread_main(void *in) {
    hlld_config *config;
    hlld_setmgr *mgr;
    int *should_run;
    UNPACK_ARGS();

    // Perform the initial checkpoint with the manager
    setmgr_client_checkpoint(mgr);

    syslog(LOG_INFO, "Flush thread started. Interval: %d seconds.", config->flush_interval);
    unsigned int ticks = 0;
    while (*should_run) {
        usleep(PERIODIC_TIME_USEC);
        setmgr_client_checkpoint(mgr);
        if ((TICK_TO_SEC(++ticks) % config->flush_interval) == 0 && *should_run) {
            // Time how long this takes
            struct timeval start, end;
            gettimeofday(&start, NULL);

            // List all the sets
            syslog(LOG_INFO, "Scheduled flush started.");
            hlld_set_list_head *head;
            int res = setmgr_list_sets(mgr, NULL, &head);
            if (res != 0) {
                syslog(LOG_WARNING, "Failed to list sets for flushing!");
                continue;
            }

            // Flush all, ignore errors since
            // sets might get deleted in the process
            hlld_set_list *node = head->head;
            unsigned int cmds = 0;
            while (node) {
                setmgr_flush_set(mgr, node->set_name);
                if (!(++cmds % PERIODIC_CHECKPOINT)) setmgr_client_checkpoint(mgr);
                node = node->next;
            }

            // Compute the elapsed time
            gettimeofday(&end, NULL);
            syslog(LOG_INFO, "Flushed %d sets in %d msecs", head->size, timediff_msec(&start, &end));

            // Cleanup
            setmgr_cleanup_list(head);
        }
    }
    return NULL;
}
示例#6
0
static void* unmap_thread_main(void *in) {
    hlld_config *config;
    hlld_setmgr *mgr;
    int *should_run;
    UNPACK_ARGS();

    // Perform the initial checkpoint with the manager
    setmgr_client_checkpoint(mgr);

    syslog(LOG_INFO, "Cold unmap thread started. Interval: %d seconds.", config->cold_interval);
    unsigned int ticks = 0;
    while (*should_run) {
        usleep(PERIODIC_TIME_USEC);
        setmgr_client_checkpoint(mgr);
        if ((TICK_TO_SEC(++ticks) % config->cold_interval) == 0 && *should_run) {
            // Time how long this takes
            struct timeval start, end;
            gettimeofday(&start, NULL);

            // List the cold sets
            syslog(LOG_INFO, "Cold unmap started.");
            hlld_set_list_head *head;
            int res = setmgr_list_cold_sets(mgr, &head);
            if (res != 0) {
                continue;
            }

            // Close the sets, save memory
            hlld_set_list *node = head->head;
            unsigned int cmds = 0;
            while (node) {
                syslog(LOG_DEBUG, "Unmapping set '%s' for being cold.", node->set_name);
                setmgr_unmap_set(mgr, node->set_name);
                if (!(++cmds % PERIODIC_CHECKPOINT)) setmgr_client_checkpoint(mgr);
                node = node->next;
            }

            // Compute the elapsed time
            gettimeofday(&end, NULL);
            syslog(LOG_INFO, "Unmapped %d sets in %d msecs", head->size, timediff_msec(&start, &end));

            // Cleanup
            setmgr_cleanup_list(head);
        }
    }
    return NULL;
}
示例#7
0
/*
 * Reclaim a fraction of dce's in the dcb.
 * For now we have a higher probability to delete DCEs without DCE_PMTU.
 */
static void
dcb_reclaim(dcb_t *dcb, ip_stack_t *ipst, uint_t fraction)
{
	uint_t	fraction_pmtu = fraction*4;
	uint_t	hash;
	dce_t	*dce, *nextdce;

	rw_enter(&dcb->dcb_lock, RW_WRITER);
	for (dce = dcb->dcb_dce; dce != NULL; dce = nextdce) {
		nextdce = dce->dce_next;
		/* Clear DCEF_PMTU if the pmtu is too old */
		mutex_enter(&dce->dce_lock);
		if ((dce->dce_flags & DCEF_PMTU) &&
		    TICK_TO_SEC(ddi_get_lbolt64()) - dce->dce_last_change_time >
		    ipst->ips_ip_pathmtu_interval) {
			dce->dce_flags &= ~DCEF_PMTU;
			mutex_exit(&dce->dce_lock);
			dce_increment_generation(dce);
		} else {
			mutex_exit(&dce->dce_lock);
		}
		hash = RANDOM_HASH((uint64_t)(uintptr_t)dce);
		if (dce->dce_flags & DCEF_PMTU) {
			if (hash % fraction_pmtu != 0)
				continue;
		} else {
			if (hash % fraction != 0)
				continue;
		}

		IP_STAT(ipst, ip_dce_reclaim_deleted);
		dce_delete_locked(dcb, dce);
		dce_refrele(dce);
	}
	rw_exit(&dcb->dcb_lock);
}
示例#8
0
/* This code works on:
 *              univel
 *              solaris_i386
 *              sco
 *              solaris_sparc
 *              svr4
 *              hpux 9.*
 *              win32
 * which currently is all the supported platforms that don't have a
 * native version of getrusage().  So, if configure decides to compile
 * this file at all, we just use this version unconditionally.
 */
int
getrusage(int who, struct rusage * rusage)
{
#ifdef __WIN32__

  FILETIME        starttime;
  FILETIME        exittime;
  FILETIME        kerneltime;
  FILETIME        usertime;
  ULARGE_INTEGER  li;

  if (who != RUSAGE_SELF)
  {
    /* Only RUSAGE_SELF is supported in this implementation for now */
    errno = EINVAL;
    return -1;
  }

  if (rusage == (struct rusage *) NULL)
  {
    errno = EFAULT;
    return -1;
  }
  memset(rusage, 0, sizeof(struct rusage));
  if (GetProcessTimes(GetCurrentProcess(),
      &starttime, &exittime, &kerneltime, &usertime) == 0)
  {
    _dosmaperr(GetLastError());
    return -1;
  }

  /* Convert FILETIMEs (0.1 us) to struct timeval */
  memcpy(&li, &kerneltime, sizeof(FILETIME));
  li.QuadPart /= 10L;                     /* Convert to microseconds */
  rusage->ru_stime.tv_sec = li.QuadPart / 1000000L;
  rusage->ru_stime.tv_usec = li.QuadPart % 1000000L;

  memcpy(&li, &usertime, sizeof(FILETIME));
  li.QuadPart /= 10L;                     /* Convert to microseconds */
  rusage->ru_utime.tv_sec = li.QuadPart / 1000000L;
  rusage->ru_utime.tv_usec = li.QuadPart % 1000000L;
#else                                                   /* all but __WIN32__ */

  struct tms      tms;
  int             tick_rate = CLK_TCK;    /* ticks per second */
  clock_t         u, s;

  if (rusage == (struct rusage *) NULL)
  {
    errno = EFAULT;
    return -1;
  }
  if (times(&tms) < 0)
  {
    /* errno set by times */
    return -1;
  }
  switch (who)
  {
    case RUSAGE_SELF:
      u = tms.tms_utime;
      s = tms.tms_stime;
      break;
    case RUSAGE_CHILDREN:
      u = tms.tms_cutime;
      s = tms.tms_cstime;
      break;
    default:
      errno = EINVAL;
      return -1;
  }
#define TICK_TO_SEC(T, RATE)    ((T)/(RATE))
#define TICK_TO_USEC(T,RATE)    (((T)%(RATE)*1000000)/RATE)
  rusage->ru_utime.tv_sec = TICK_TO_SEC(u, tick_rate);
  rusage->ru_utime.tv_usec = TICK_TO_USEC(u, tick_rate);
  rusage->ru_stime.tv_sec = TICK_TO_SEC(s, tick_rate);
  rusage->ru_stime.tv_usec = TICK_TO_USEC(u, tick_rate);
#endif   /* __WIN32__ */

  return 0;
}
示例#9
0
/*
 * Get current zone maximum burst time.
 */
rctl_qty_t
cpucaps_zone_get_burst_time(zone_t *zone)
{
	return (zone->zone_cpucap != NULL ?
	    (rctl_qty_t)(TICK_TO_SEC(zone->zone_cpucap->cap_burst_limit)) : 0);
}