int sigar_cpu_get(sigar_t *sigar, sigar_cpu_t *cpu) { int status, i; status = sigar_cpu_list_get(sigar, &sigar->cpulist); if (status != SIGAR_OK) { return status; } SIGAR_ZERO(cpu); for (i=0; i<sigar->cpulist.number; i++) { sigar_cpu_t *xcpu = &sigar->cpulist.data[i]; cpu->user += xcpu->user; cpu->sys += xcpu->sys; cpu->idle += xcpu->idle; cpu->nice += xcpu->nice; cpu->wait += xcpu->wait; cpu->total += xcpu->total; } return SIGAR_OK; }
/* XXX: check for stale-ness using start_time */ SIGAR_DECLARE(int) sigar_proc_cpu_get(sigar_t *sigar, sigar_pid_t pid, sigar_proc_cpu_t *proccpu) { sigar_cache_entry_t *entry; sigar_proc_cpu_t *prev; sigar_uint64_t otime, time_now = sigar_time_now_millis(); sigar_uint64_t time_diff, total_diff; int status; if (!sigar->proc_cpu) { sigar->proc_cpu = sigar_cache_new(128); } entry = sigar_cache_get(sigar->proc_cpu, pid); if (entry->value) { prev = (sigar_proc_cpu_t *)entry->value; } else { prev = entry->value = malloc(sizeof(*prev)); SIGAR_ZERO(prev); } time_diff = time_now - prev->last_time; proccpu->last_time = prev->last_time = time_now; if (time_diff == 0) { /* we were just called within < 1 second ago. */ memcpy(proccpu, prev, sizeof(*proccpu)); return SIGAR_OK; } otime = prev->total; status = sigar_proc_time_get(sigar, pid, (sigar_proc_time_t *)proccpu); if (status != SIGAR_OK) { return status; } memcpy(prev, proccpu, sizeof(*prev)); if (proccpu->total < otime) { /* XXX this should not happen */ otime = 0; } if (otime == 0) { proccpu->percent = 0.0; /* first time called */ return SIGAR_OK; } total_diff = proccpu->total - otime; proccpu->percent = total_diff / (double)time_diff; return SIGAR_OK; }
static int net_conn_get_udp_listen(sigar_net_connection_walker_t *walker) { sigar_t *sigar = walker->sigar; int flags = walker->flags; int status, count, i; unsigned int len; mib_udpLsnEnt *entries; struct nmparms parms; len = sizeof(count); parms.objid = ID_udpLsnNumEnt; parms.buffer = &count; parms.len = &len; if ((status = sigar_get_mib_info(sigar, &parms)) != SIGAR_OK) { return status; } if (count <= 0) { return ENOENT; } len = count * sizeof(*entries); entries = malloc(len); parms.objid = ID_udpLsnTable; parms.buffer = entries; parms.len = &len; if ((status = sigar_get_mib_info(sigar, &parms)) != SIGAR_OK) { free(entries); return status; } for (i=0; i<count; i++) { sigar_net_connection_t conn; mib_udpLsnEnt *entry = &entries[i]; SIGAR_ZERO(&conn); conn.type = SIGAR_NETCONN_UDP; conn.local_port = (unsigned short)entry->LocalPort; conn.remote_port = 0; sigar_net_address_set(conn.local_address, entry->LocalAddress); sigar_net_address_set(conn.remote_address, 0); conn.send_queue = conn.receive_queue = SIGAR_FIELD_NOTIMPL; if (walker->add_connection(walker, &conn) != SIGAR_OK) { break; } } free(entries); return SIGAR_OK; }
int sigar_mem_get(sigar_t *sigar, sigar_mem_t *mem) { kstat_ctl_t *kc = sigar->kc; kstat_t *ksp; sigar_uint64_t kern = 0; SIGAR_ZERO(mem); /* XXX: is mem hot swappable or can we just do this during open ? */ mem->total = sysconf(_SC_PHYS_PAGES); mem->total <<= sigar->pagesize; if (sigar_kstat_update(sigar) == -1) { return errno; } if ((ksp = sigar->ks.syspages) && kstat_read(kc, ksp, NULL) >= 0) { sigar_koffsets_init_syspages(sigar, ksp); mem->free = kSYSPAGES(KSTAT_SYSPAGES_FREE); mem->free <<= sigar->pagesize; mem->used = mem->total - mem->free; } if ((ksp = sigar->ks.mempages) && kstat_read(kc, ksp, NULL) >= 0) { sigar_koffsets_init_mempages(sigar, ksp); } /* XXX mdb ::memstat cachelist/freelist not available to kstat, see: */ /* http://bugs.opensolaris.org/bugdatabase/view_bug.do?bug_id=6821980 */ /* ZFS ARC cache. see: http://opensolaris.org/jive/thread.jspa?messageID=393695 */ if ((ksp = kstat_lookup(sigar->kc, "zfs", 0, "arcstats")) && (kstat_read(sigar->kc, ksp, NULL) != -1)) { kstat_named_t *kn; if ((kn = (kstat_named_t *)kstat_data_lookup(ksp, "size"))) { kern = kn->value.i64; } if ((kn = (kstat_named_t *)kstat_data_lookup(ksp, "c_min"))) { /* c_min cannot be reclaimed they say */ if (kern > kn->value.i64) { kern -= kn->value.i64; } } } mem->actual_free = mem->free + kern; mem->actual_used = mem->used - kern; sigar_mem_calc_ram(sigar, mem); return SIGAR_OK; }
static int udp_connection_get(sigar_net_connection_walker_t *walker, struct mib2_udpEntry *entry, int len) { int flags = walker->flags; int status; char *end = (char *)entry + len; while ((char *)entry < end) { int state = entry->udpEntryInfo.ue_state; /* XXX dunno if this state check is right */ if (((flags & SIGAR_NETCONN_SERVER) && (state == MIB2_UDP_idle)) || ((flags & SIGAR_NETCONN_CLIENT) && (state != MIB2_UDP_idle))) { sigar_net_connection_t conn; SIGAR_ZERO(&conn); sigar_net_address_set(conn.local_address, entry->udpLocalAddress); sigar_net_address_set(conn.remote_address, 0); conn.local_port = entry->udpLocalPort; conn.remote_port = 0; conn.type = SIGAR_NETCONN_UDP; status = walker->add_connection(walker, &conn); if (status != SIGAR_OK) { return status; } } entry++; } return SIGAR_OK; }
static int sigar_pbi_get(sigar_t *sigar, HANDLE proc, PEB *peb) { int status; PROCESS_BASIC_INFORMATION pbi; DWORD size=sizeof(pbi); dllmod_init_ntdll(sigar); if (!sigar_NtQueryInformationProcess) { return SIGAR_ENOTIMPL; } SIGAR_ZERO(&pbi); status = sigar_NtQueryInformationProcess(proc, ProcessBasicInformation, &pbi, size, NULL); if (status != ERROR_SUCCESS) { return status; } if (!pbi.PebBaseAddress) { /* likely we are 32-bit, pid process is 64-bit */ return ERROR_DATATYPE_MISMATCH; } size = sizeof(*peb); if (ReadProcessMemory(proc, pbi.PebBaseAddress, peb, size, NULL)) { return SIGAR_OK; } else { return GetLastError(); } }
static int tcp_connection_get(sigar_net_connection_walker_t *walker, struct mib2_tcpConnEntry *entry, int len) { int flags = walker->flags; int status; char *end = (char *)entry + len; while ((char *)entry < end) { int state = entry->tcpConnEntryInfo.ce_state; if (((flags & SIGAR_NETCONN_SERVER) && (state == TCPS_LISTEN)) || ((flags & SIGAR_NETCONN_CLIENT) && (state != TCPS_LISTEN))) { sigar_net_connection_t conn; SIGAR_ZERO(&conn); sigar_net_address_set(conn.local_address, entry->tcpConnLocalAddress); sigar_net_address_set(conn.remote_address, entry->tcpConnRemAddress); conn.local_port = entry->tcpConnLocalPort; conn.remote_port = entry->tcpConnRemPort; conn.type = SIGAR_NETCONN_TCP; conn.send_queue = TCPQ_SIZE(entry->tcpConnEntryInfo.ce_snxt - entry->tcpConnEntryInfo.ce_suna - 1); conn.receive_queue = TCPQ_SIZE(entry->tcpConnEntryInfo.ce_rnxt - entry->tcpConnEntryInfo.ce_rack); switch (state) { case TCPS_CLOSED: conn.state = SIGAR_TCP_CLOSE; break; case TCPS_IDLE: conn.state = SIGAR_TCP_IDLE; break; case TCPS_BOUND: conn.state = SIGAR_TCP_BOUND; break; case TCPS_LISTEN: conn.state = SIGAR_TCP_LISTEN; break; case TCPS_SYN_SENT: conn.state = SIGAR_TCP_SYN_SENT; break; case TCPS_SYN_RCVD: conn.state = SIGAR_TCP_SYN_RECV; break; case TCPS_ESTABLISHED: conn.state = SIGAR_TCP_ESTABLISHED; break; case TCPS_CLOSE_WAIT: conn.state = SIGAR_TCP_CLOSE_WAIT; break; case TCPS_FIN_WAIT_1: conn.state = SIGAR_TCP_FIN_WAIT1; break; case TCPS_CLOSING: conn.state = SIGAR_TCP_CLOSING; break; case TCPS_LAST_ACK: conn.state = SIGAR_TCP_LAST_ACK; break; case TCPS_FIN_WAIT_2: conn.state = SIGAR_TCP_FIN_WAIT2; break; case TCPS_TIME_WAIT: conn.state = SIGAR_TCP_TIME_WAIT; break; default: conn.state = SIGAR_TCP_UNKNOWN; break; } status = walker->add_connection(walker, &conn); if (status != SIGAR_OK) { return status; } } entry++; } return SIGAR_OK; }
static int sigar_cpu_list_get(sigar_t *sigar, sigar_cpu_list_t *cpulist) { kstat_ctl_t *kc = sigar->kc; kstat_t *ksp; uint_t cpuinfo[CPU_STATES]; unsigned int i; int is_debug = SIGAR_LOG_IS_DEBUG(sigar); sigar_cache_t *chips; if (sigar_kstat_update(sigar) == -1) { return errno; } if (cpulist == &sigar->cpulist) { if (sigar->cpulist.size == 0) { /* create once */ sigar_cpu_list_create(cpulist); } else { /* reset, re-using cpulist.data */ sigar->cpulist.number = 0; } } else { sigar_cpu_list_create(cpulist); } if (is_debug) { sigar_log_printf(sigar, SIGAR_LOG_DEBUG, "[cpu_list] OS reports %d CPUs", sigar->ncpu); } chips = sigar_cache_new(16); chips->free_value = free_chip_id; for (i=0; i<sigar->ncpu; i++) { sigar_cpu_t *cpu; char *buf; int chip_id; sigar_cache_entry_t *ent; if (!CPU_ONLINE(sigar->ks.cpuid[i])) { sigar_log_printf(sigar, SIGAR_LOG_INFO, "cpu %d (id=%d) is offline", i, sigar->ks.cpuid[i]); continue; } if (!(ksp = sigar->ks.cpu[i])) { sigar_log_printf(sigar, SIGAR_LOG_ERROR, "NULL ksp for cpu %d (id=%d)", i, sigar->ks.cpuid[i]); continue; /* shouldnot happen */ } if (kstat_read(kc, ksp, NULL) < 0) { sigar_log_printf(sigar, SIGAR_LOG_ERROR, "kstat_read failed for cpu %d (id=%d): %s", i, sigar->ks.cpuid[i], sigar_strerror(sigar, errno)); continue; /* shouldnot happen */ } /* * cpu_stat_t is not binary compatible between solaris versions. * since cpu_stat is a 'raw' kstat and not 'named' we cannot * use name based lookups as we do for others. * the start of the cpu_stat_t structure is binary compatible, * which looks like so: * typedef struct cpu_stat { * kmutex_t cpu_stat_lock; * cpu_sysinfo_t cpu_sysinfo; * ... * typedef struct cpu_sysinfo { * ulong cpu[CPU_STATES]; * ... * we just copy the piece we need below: */ buf = ksp->ks_data; buf += sizeof(kmutex_t); memcpy(&cpuinfo[0], buf, sizeof(cpuinfo)); chip_id = sigar->cpu_list_cores ? -1 : get_chip_id(sigar, i); if (chip_id == -1) { SIGAR_CPU_LIST_GROW(cpulist); cpu = &cpulist->data[cpulist->number++]; SIGAR_ZERO(cpu); } else { /* merge times of logical processors */ ent = sigar_cache_get(chips, chip_id); if (ent->value) { cpu = &cpulist->data[(long)ent->value-1]; } else { SIGAR_CPU_LIST_GROW(cpulist); cpu = &cpulist->data[cpulist->number++]; ent->value = (void *)(long)cpulist->number; SIGAR_ZERO(cpu); if (is_debug) { sigar_log_printf(sigar, SIGAR_LOG_DEBUG, "[cpu_list] Merging times of" " logical processors for chip_id=%d", chip_id); } } } cpu->user += SIGAR_TICK2MSEC(cpuinfo[CPU_USER]); cpu->sys += SIGAR_TICK2MSEC(cpuinfo[CPU_KERNEL]); cpu->idle += SIGAR_TICK2MSEC(cpuinfo[CPU_IDLE]); cpu->wait += SIGAR_TICK2MSEC(cpuinfo[CPU_WAIT]); cpu->nice += 0; /* no cpu->nice */ cpu->total = cpu->user + cpu->sys + cpu->idle + cpu->wait; } sigar_cache_destroy(chips); return SIGAR_OK; }
int sigar_net_interface_config_get(sigar_t *sigar, const char *name, sigar_net_interface_config_t *ifconfig) { int sock; struct ifreq ifr; if (!name) { return sigar_net_interface_config_primary_get(sigar, ifconfig); } SIGAR_ZERO(ifconfig); if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { return errno; } SIGAR_SSTRCPY(ifconfig->name, name); SIGAR_SSTRCPY(ifr.ifr_name, name); #define ifr_s_addr(ifr) \ ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr if (!ioctl(sock, SIOCGIFADDR, &ifr)) { sigar_net_address_set(ifconfig->address, ifr_s_addr(ifr)); } if (!ioctl(sock, SIOCGIFNETMASK, &ifr)) { sigar_net_address_set(ifconfig->netmask, ifr_s_addr(ifr)); } if (!ioctl(sock, SIOCGIFFLAGS, &ifr)) { sigar_uint64_t flags = ifr.ifr_flags; #ifdef __linux__ # ifndef IFF_DYNAMIC # define IFF_DYNAMIC 0x8000 /* not in 2.2 kernel */ # endif /* IFF_DYNAMIC */ int is_mcast = flags & IFF_MULTICAST; int is_slave = flags & IFF_SLAVE; int is_master = flags & IFF_MASTER; int is_dynamic = flags & IFF_DYNAMIC; /* * XXX: should just define SIGAR_IFF_* * and test IFF_* bits on given platform. * this is the only diff between solaris/hpux/linux * for the flags we care about. * */ flags &= ~(IFF_MULTICAST|IFF_SLAVE|IFF_MASTER); if (is_mcast) { flags |= SIGAR_IFF_MULTICAST; } if (is_slave) { flags |= SIGAR_IFF_SLAVE; } if (is_master) { flags |= SIGAR_IFF_MASTER; } if (is_dynamic) { flags |= SIGAR_IFF_DYNAMIC; } #endif ifconfig->flags = flags; } else { /* should always be able to get flags for existing device */ /* other ioctls may fail if device is not enabled: ok */ close(sock); return errno; } if (ifconfig->flags & IFF_LOOPBACK) { sigar_net_address_set(ifconfig->destination, ifconfig->address.addr.in); sigar_net_address_set(ifconfig->broadcast, 0); sigar_hwaddr_set_null(ifconfig); SIGAR_SSTRCPY(ifconfig->type, SIGAR_NIC_LOOPBACK); } else { if (!ioctl(sock, SIOCGIFDSTADDR, &ifr)) { sigar_net_address_set(ifconfig->destination, ifr_s_addr(ifr)); } if (!ioctl(sock, SIOCGIFBRDADDR, &ifr)) { sigar_net_address_set(ifconfig->broadcast, ifr_s_addr(ifr)); } #if defined(HAVE_LIBDLPI_H) hwaddr_libdlpi_lookup(sigar, ifconfig); #elif defined(SIOCGIFHWADDR) if (!ioctl(sock, SIOCGIFHWADDR, &ifr)) { get_interface_type(ifconfig, ifr.ifr_hwaddr.sa_family); sigar_net_address_mac_set(ifconfig->hwaddr, ifr.ifr_hwaddr.sa_data, IFHWADDRLEN); } #elif defined(_AIX) || defined(__osf__) hwaddr_aix_lookup(sigar, ifconfig); SIGAR_SSTRCPY(ifconfig->type, SIGAR_NIC_ETHERNET); #else hwaddr_arp_lookup(ifconfig, sock); SIGAR_SSTRCPY(ifconfig->type, SIGAR_NIC_ETHERNET); #endif } #if defined(SIOCGLIFMTU) && !defined(__hpux) { struct lifreq lifr; SIGAR_SSTRCPY(lifr.lifr_name, name); if(!ioctl(sock, SIOCGLIFMTU, &lifr)) { ifconfig->mtu = lifr.lifr_mtu; } } #elif defined(SIOCGIFMTU) if (!ioctl(sock, SIOCGIFMTU, &ifr)) { # if defined(__hpux) ifconfig->mtu = ifr.ifr_metric; # else ifconfig->mtu = ifr.ifr_mtu; #endif } #else ifconfig->mtu = 0; /*XXX*/ #endif if (!ioctl(sock, SIOCGIFMETRIC, &ifr)) { ifconfig->metric = ifr.ifr_metric ? ifr.ifr_metric : 1; } #if defined(SIOCGIFTXQLEN) if (!ioctl(sock, SIOCGIFTXQLEN, &ifr)) { ifconfig->tx_queue_len = ifr.ifr_qlen; } else { ifconfig->tx_queue_len = -1; /* net-tools behaviour */ } #else ifconfig->tx_queue_len = -1; #endif close(sock); /* XXX can we get a better description like win32? */ SIGAR_SSTRCPY(ifconfig->description, ifconfig->name); sigar_net_interface_ipv6_config_init(ifconfig); sigar_net_interface_ipv6_config_get(sigar, name, ifconfig); return SIGAR_OK; }
static int net_conn_get_tcp(sigar_net_connection_walker_t *walker) { sigar_t *sigar = walker->sigar; int flags = walker->flags; int status, count, i; unsigned int len; mib_tcpConnEnt *entries; struct nmparms parms; len = sizeof(count); parms.objid = ID_tcpConnNumEnt; parms.buffer = &count; parms.len = &len; if ((status = sigar_get_mib_info(sigar, &parms)) != SIGAR_OK) { return status; } if (count <= 0) { return ENOENT; } len = count * sizeof(*entries); entries = malloc(len); parms.objid = ID_tcpConnTable; parms.buffer = entries; parms.len = &len; if ((status = sigar_get_mib_info(sigar, &parms)) != SIGAR_OK) { free(entries); return status; } for (i=0; i<count; i++) { sigar_net_connection_t conn; mib_tcpConnEnt *entry = &entries[i]; int state = entry->State; if (!(IS_TCP_SERVER(state, flags) || IS_TCP_CLIENT(state, flags))) { continue; } SIGAR_ZERO(&conn); switch (state) { case TCCLOSED: conn.state = SIGAR_TCP_CLOSE; break; case TCLISTEN: conn.state = SIGAR_TCP_LISTEN; break; case TCSYNSENT: conn.state = SIGAR_TCP_SYN_SENT; break; case TCSYNRECEIVE: conn.state = SIGAR_TCP_SYN_RECV; break; case TCESTABLISED: conn.state = SIGAR_TCP_ESTABLISHED; break; case TCFINWAIT1: conn.state = SIGAR_TCP_FIN_WAIT1; break; case TCFINWAIT2: conn.state = SIGAR_TCP_FIN_WAIT2; break; case TCCLOSEWAIT: conn.state = SIGAR_TCP_CLOSE_WAIT; break; case TCCLOSING: conn.state = SIGAR_TCP_CLOSING; break; case TCLASTACK: conn.state = SIGAR_TCP_LAST_ACK; break; case TCTIMEWAIT: conn.state = SIGAR_TCP_TIME_WAIT; break; case TCDELETETCB: default: conn.state = SIGAR_TCP_UNKNOWN; break; } conn.local_port = (unsigned short)entry->LocalPort; conn.remote_port = (unsigned short)entry->RemPort; conn.type = SIGAR_NETCONN_TCP; sigar_net_address_set(conn.local_address, entry->LocalAddress); sigar_net_address_set(conn.remote_address, entry->RemAddress); conn.send_queue = conn.receive_queue = SIGAR_FIELD_NOTIMPL; if (walker->add_connection(walker, &conn) != SIGAR_OK) { break; } } free(entries); return SIGAR_OK; }
int sigar_net_route_list_get(sigar_t *sigar, sigar_net_route_list_t *routelist) { int status, count, i; unsigned int len; struct nmparms parms; mib_ipRouteEnt *routes; sigar_net_route_t *route; len = sizeof(count); parms.objid = ID_ipRouteNumEnt; parms.buffer = &count; parms.len = &len; if ((status = sigar_get_mib_info(sigar, &parms)) != SIGAR_OK) { return status; } len = count * sizeof(*routes); routes = malloc(len); parms.objid = ID_ipRouteTable; parms.buffer = routes; parms.len = &len; if ((status = sigar_get_mib_info(sigar, &parms)) != SIGAR_OK) { free(routes); return status; } routelist->size = routelist->number = 0; sigar_net_route_list_create(routelist); for (i=0; i<count; i++) { mib_ipRouteEnt *ent = &routes[i]; SIGAR_NET_ROUTE_LIST_GROW(routelist); route = &routelist->data[routelist->number++]; SIGAR_ZERO(route); /* XXX: other fields */ sigar_net_address_set(route->destination, ent->Dest); sigar_net_address_set(route->mask, ent->Mask); sigar_net_address_set(route->gateway, ent->NextHop); route->flags = SIGAR_RTF_UP; if ((ent->Dest == 0) && (ent->Mask == 0)) { route->flags |= SIGAR_RTF_GATEWAY; } } free(routes); return SIGAR_OK; }