static int camd_recv_cw(struct ts *ts) { struct camd *c = &ts->camd; struct timeval tv1, tv2, last_ts_keyset; uint16_t ca_id = 0; uint16_t idx = 0; int ret; gettimeofday(&tv1, NULL); ret = c->ops.get_cw(c, &ca_id, &idx, c->key->cw); gettimeofday(&tv2, NULL); if (ret <= 0) { if (ret == -1) { // Fatal error it is better to reconnect to server. ts_LOGf("ERR | No code word has been received (ret = %d)\n", ret); c->ops.reconnect(c); } c->ecm_recv_errors++; if (c->ecm_recv_errors >= ECM_RECV_ERRORS_LIMIT) { c->key->is_valid_cw = 0; memset(c->key->cw, 0, 16); // Invalid CW } usleep(10000); return 0; } char cw_dump[16 * 6]; ts_hex_dump_buf(cw_dump, 16 * 6, c->key->cw, 16, 0); int valid_cw = memcmp(c->key->cw, invalid_cw, 16) != 0; if (!c->key->is_valid_cw && valid_cw) { ts_LOGf("CW | OK: Valid code word was received.\n"); notify(ts, "CODE_WORD_OK", "Valid code word was received."); } c->key->is_valid_cw = valid_cw; // At first ts_keyset is not initialized last_ts_keyset = c->key->ts_keyset; if (c->key->is_valid_cw) camd_set_cw(ts, c->key->cw, 1); if (ts->ecm_cw_log) { ts_LOGf("CW | SID 0x%04x CAID: 0x%04x CW_recv: %5llu ms LastKey: %5llu ms Data: %s\n", ts->service_id, ca_id, timeval_diff_msec(&tv1, &tv2), timeval_diff_msec(&last_ts_keyset, &tv2), cw_dump ); } return 1; }
/* * get_timeout * returns the amount of time that select should block for before returning * whether some packets have arrived or not */ static int get_timeout(struct timeval *tv) { struct timeval temp; int64_t min_diff = 1000, temp_diff; if(tv == NULL) { return 0; } bzero(&temp, sizeof(temp)); bzero(&tz, sizeof(tz)); if(gettimeofday(&temp, &tz) != 0) { printerror(errno, strerror, "could not gettimeofday"); return 0; } if(wait_between > 0) { temp_diff = timeval_diff_msec(&wait_between_tv, &temp); if(temp_diff >= 0 && temp_diff < min_diff) min_diff = temp_diff; } tv->tv_sec = 0; tv->tv_usec = 0; timeval_add(tv, min_diff); return 1; }
void process_packets(struct ts *ts, uint8_t *ts_packet, ssize_t readen) { struct timeval now; struct packet *packet = ts->current_packet; if (packet->data_len + readen < PACKET_MAX_LENGTH) { // Add data to buffer memcpy(packet->data + packet->data_len, ts_packet, readen); packet->data_len += readen; } else { // Too much data, add to queue p_dbg1("*** Reached buffer end (%zd + %zd > %d)\n", packet->data_len + readen, readen, PACKET_MAX_LENGTH); packet = add_to_queue(ts); } if (!packet->ts.tv_sec) gettimeofday(&packet->ts, NULL); gettimeofday(&now, NULL); unsigned long long diff = timeval_diff_msec(&packet->ts, &now); if (diff > PACKET_MAX_TIME) { // Too much time have passed, add to queue p_dbg1("+++ Reached time limit (%llu > %d)\n", diff, PACKET_MAX_TIME); add_to_queue(ts); } }
void poll_process_rss (struct poll_state *ps) { struct task_basic_info ti; int ret; ++ps->num_polls; ret = get_task_info(ps, &ti); if (ret != 0) { if ((ret == 2) && (ps->num_polls >= 2)) { // Then guess that this is not because of lack of // permissions, because we have successfully made the call // before. Guess that this is because the child process // has exited already. Unfortunately I do not see a good // way to determine that this has happened other than by // guessing, but there is probably a Mach way to do it // with some API call. // Record the time this has happened, so we can later tell // if it is close to the time the child process exits. // Also indicate that we should disable the timer now. ps->task_info_errored = 1; ret = gettimeofday(&(ps->task_info_error_time), NULL); // TBD: check ret? return; } run_as_superuser_msg(global_prog_name); exit(1); } natural_t rss_bytes = ti.resident_size; if (ps->verbose_poll) { double rss_mbytes = (double) rss_bytes / (1024.0 * 1024.0); printf("rss (mb)=%.1f\n", rss_mbytes); } struct timeval this_poll_time; ret = gettimeofday(&this_poll_time, NULL); if (ps->first_poll || (rss_bytes > ps->max_rss_bytes)) { ps->max_rss_bytes = rss_bytes; memcpy(&(ps->poll_time_when_maxrss_first_seen), &this_poll_time, sizeof(struct timeval)); } if (!ps->first_poll) { int64 delta = timeval_diff_msec(&(ps->prev_poll_time), &this_poll_time); if (delta < ps->consecutive_poll_separation_min_msec) { ps->consecutive_poll_separation_min_msec = delta; } if (delta > ps->consecutive_poll_separation_max_msec) { ps->consecutive_poll_separation_max_msec = delta; } } ps->first_poll = 0; memcpy(&(ps->prev_poll_time), &this_poll_time, sizeof(struct timeval)); }
static void log_poll_interval(long long int last_wakeup) { long long int interval = time_msec() - last_wakeup; if (interval >= 1000 && !is_warped(&monotonic_clock)) { const struct rusage *last_rusage = get_recent_rusage(); struct rusage rusage; getrusage(RUSAGE_SELF, &rusage); VLOG_WARN("Unreasonably long %lldms poll interval" " (%lldms user, %lldms system)", interval, timeval_diff_msec(&rusage.ru_utime, &last_rusage->ru_utime), timeval_diff_msec(&rusage.ru_stime, &last_rusage->ru_stime)); if (rusage.ru_minflt > last_rusage->ru_minflt || rusage.ru_majflt > last_rusage->ru_majflt) { VLOG_WARN("faults: %ld minor, %ld major", rusage.ru_minflt - last_rusage->ru_minflt, rusage.ru_majflt - last_rusage->ru_majflt); } if (rusage.ru_inblock > last_rusage->ru_inblock || rusage.ru_oublock > last_rusage->ru_oublock) { VLOG_WARN("disk: %ld reads, %ld writes", rusage.ru_inblock - last_rusage->ru_inblock, rusage.ru_oublock - last_rusage->ru_oublock); } if (rusage.ru_nvcsw > last_rusage->ru_nvcsw || rusage.ru_nivcsw > last_rusage->ru_nivcsw) { VLOG_WARN("context switches: %ld voluntary, %ld involuntary", rusage.ru_nvcsw - last_rusage->ru_nvcsw, rusage.ru_nivcsw - last_rusage->ru_nivcsw); } coverage_log(); } }
static int time_to_send_request() { struct timeval tv; gettimeofday(&tv, &tz); if(sent_all_requests == 1) { return 0; } if(wait_between == 0) { return 1; } if(timeval_diff_msec(&wait_between_tv, &tv) > 0) { return 0; } return 1; }
void hostmon(time_t facilitytime, char *ifptr) { int logging = options.logging; struct ethtab table; struct ethtabent *entry; char scratch_saddr[ETH_ALEN]; char scratch_daddr[ETH_ALEN]; unsigned int idx = 1; int is_ip; int ch; char *ifname = ifptr; struct timeval tv; struct timeval tv_rate; time_t now = 0; time_t statbegin = 0; time_t startlog = 0; struct timeval updtime; struct eth_desc *list = NULL; FILE *logfile = NULL; int pkt_result; WINDOW *sortwin; PANEL *sortpanel; int keymode = 0; int fd; if (ifptr && !dev_up(ifptr)) { err_iface_down(); return; } LIST_HEAD(promisc); if (options.promisc) { promisc_init(&promisc, ifptr); promisc_set_list(&promisc); } hostmonhelp(); initethtab(&table); /* Ethernet description list */ struct eth_desc *elist = load_eth_desc(ARPHRD_ETHER); /* FDDI description list */ struct eth_desc *flist = load_eth_desc(ARPHRD_FDDI); if (logging) { if (strcmp(current_logfile, "") == 0) { strncpy(current_logfile, gen_instance_logname(LANLOG, getpid()), 80); if (!daemonized) input_logfile(current_logfile, &logging); } } if (logging) { opentlog(&logfile, current_logfile); if (logfile == NULL) logging = 0; } if (logging) { signal(SIGUSR1, rotate_lanlog); rotate_flag = 0; writelog(logging, logfile, "******** LAN traffic monitor started ********"); } leaveok(table.tabwin, TRUE); fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); if(fd == -1) { write_error("Unable to obtain monitoring socket"); goto err; } if(ifptr && dev_bind_ifname(fd, ifptr) == -1) { write_error("Unable to bind interface on the socket"); goto err_close; } exitloop = 0; gettimeofday(&tv, NULL); tv_rate = tv; updtime = tv; statbegin = startlog = tv.tv_sec; PACKET_INIT(pkt); do { gettimeofday(&tv, NULL); now = tv.tv_sec; unsigned long msecs = timeval_diff_msec(&tv, &tv_rate); if (msecs >= 1000) { printelapsedtime(statbegin, now, LINES - 3, 15, table.borderwin); updateethrates(&table, msecs, idx); tv_rate = tv; } if (logging) { check_rotate_flag(&logfile); if ((now - startlog) >= options.logspan) { writeethlog(table.head, now - statbegin, logfile); startlog = now; } } if (screen_update_needed(&tv, &updtime)) { update_panels(); doupdate(); updtime = tv; } if ((facilitytime != 0) && (((now - statbegin) / 60) >= facilitytime)) exitloop = 1; if (packet_get(fd, &pkt, &ch, table.tabwin) == -1) { write_error("Packet receive failed"); exitloop = 1; break; } if (ch != ERR) { if (keymode == 0) { switch (ch) { case KEY_UP: scrollethwin(&table, SCROLLDOWN, &idx); break; case KEY_DOWN: scrollethwin(&table, SCROLLUP, &idx); break; case KEY_PPAGE: case '-': pageethwin(&table, SCROLLDOWN, &idx); break; case KEY_NPAGE: case ' ': pageethwin(&table, SCROLLUP, &idx); break; case 12: case 'l': case 'L': tx_refresh_screen(); break; case 's': case 'S': show_hostsort_keywin(&sortwin, &sortpanel); keymode = 1; break; case 'q': case 'Q': case 'x': case 'X': case 27: case 24: exitloop = 1; } } else if (keymode == 1) { del_panel(sortpanel); delwin(sortwin); sort_hosttab(&table, &idx, ch); keymode = 0; } } if (pkt.pkt_len <= 0) continue; char ifnamebuf[IFNAMSIZ]; pkt_result = packet_process(&pkt, NULL, NULL, NULL, MATCH_OPPOSITE_USECONFIG, 0); if (pkt_result != PACKET_OK) continue; if (!ifptr) { /* we're capturing on "All interfaces", */ /* so get the name of the interface */ /* of this packet */ int r = dev_get_ifname(pkt.pkt_ifindex, ifnamebuf); if (r != 0) { write_error("Unable to get interface name"); break; /* can't get interface name, get out! */ } ifname = ifnamebuf; } /* get HW addresses */ switch (pkt.pkt_hatype) { case ARPHRD_ETHER: { memcpy(scratch_saddr, pkt.ethhdr->h_source, ETH_ALEN); memcpy(scratch_daddr, pkt.ethhdr->h_dest, ETH_ALEN); list = elist; break; } case ARPHRD_FDDI: { memcpy(scratch_saddr, pkt.fddihdr->saddr, FDDI_K_ALEN); memcpy(scratch_daddr, pkt.fddihdr->daddr, FDDI_K_ALEN); list = flist; break; } default: /* unknown link protocol */ continue; } switch(pkt.pkt_protocol) { case ETH_P_IP: case ETH_P_IPV6: is_ip = 1; break; default: is_ip = 0; break; } /* Check source address entry */ entry = in_ethtable(&table, pkt.pkt_hatype, scratch_saddr); if (!entry) entry = addethentry(&table, pkt.pkt_hatype, ifname, scratch_saddr, list); if (entry != NULL) { updateethent(entry, pkt.pkt_len, is_ip, 1); if (!entry->prev_entry->un.desc.printed) printethent(&table, entry->prev_entry, idx); printethent(&table, entry, idx); } /* Check destination address entry */ entry = in_ethtable(&table, pkt.pkt_hatype, scratch_daddr); if (!entry) entry = addethentry(&table, pkt.pkt_hatype, ifname, scratch_daddr, list); if (entry != NULL) { updateethent(entry, pkt.pkt_len, is_ip, 0); if (!entry->prev_entry->un.desc.printed) printethent(&table, entry->prev_entry, idx); printethent(&table, entry, idx); } } while (!exitloop); err_close: close(fd); err: if (options.promisc) { promisc_restore_list(&promisc); promisc_destroy(&promisc); } if (logging) { signal(SIGUSR1, SIG_DFL); writeethlog(table.head, time(NULL) - statbegin, logfile); writelog(logging, logfile, "******** LAN traffic monitor stopped ********"); fclose(logfile); } del_panel(table.tabpanel); delwin(table.tabwin); del_panel(table.borderpanel); delwin(table.borderwin); update_panels(); doupdate(); destroyethtab(&table); free_eth_desc(elist); free_eth_desc(flist); strcpy(current_logfile, ""); }
/* * The detailed interface statistics function */ void detstats(char *iface, time_t facilitytime) { int logging = options.logging; WINDOW *statwin; PANEL *statpanel; int pkt_result = 0; FILE *logfile = NULL; unsigned int iplen = 0; struct ifcounts ifcounts; int ch; struct timeval tv; struct timeval start_tv; struct timeval updtime; time_t starttime; time_t now; time_t statbegin; time_t startlog; struct proto_counter span; struct rate rate; struct rate rate_in; struct rate rate_out; unsigned long peakactivity = 0; unsigned long peakactivity_in = 0; unsigned long peakactivity_out = 0; struct rate pps_rate; struct rate pps_rate_in; struct rate pps_rate_out; unsigned long peakpps = 0; unsigned long peakpps_in = 0; unsigned long peakpps_out = 0; int fd; if (!dev_up(iface)) { err_iface_down(); return; } LIST_HEAD(promisc); if (options.promisc) { promisc_init(&promisc, iface); promisc_set_list(&promisc); } move(LINES - 1, 1); stdexitkeyhelp(); statwin = newwin(LINES - 2, COLS, 1, 0); statpanel = new_panel(statwin); tx_stdwinset(statwin); wtimeout(statwin, -1); wattrset(statwin, BOXATTR); tx_colorwin(statwin); tx_box(statwin, ACS_VLINE, ACS_HLINE); wmove(statwin, 0, 1); wprintw(statwin, " Statistics for %s ", iface); wattrset(statwin, STDATTR); update_panels(); doupdate(); memset(&ifcounts, 0, sizeof(struct ifcounts)); if (logging) { if (strcmp(current_logfile, "") == 0) { snprintf(current_logfile, 64, "%s-%s.log", DSTATLOG, iface); if (!daemonized) input_logfile(current_logfile, &logging); } } if (logging) { opentlog(&logfile, current_logfile); if (logfile == NULL) logging = 0; } if (logging) { signal(SIGUSR1, rotate_dstat_log); rotate_flag = 0; writelog(logging, logfile, "******** Detailed interface statistics started ********"); } printdetlabels(statwin); printdetails(&ifcounts, statwin); update_panels(); doupdate(); memset(&span, 0, sizeof(span)); rate_alloc(&rate, 5); rate_alloc(&rate_in, 5); rate_alloc(&rate_out, 5); rate_alloc(&pps_rate, 5); rate_alloc(&pps_rate_in, 5); rate_alloc(&pps_rate_out, 5); gettimeofday(&tv, NULL); start_tv = tv; updtime = tv; starttime = startlog = statbegin = tv.tv_sec; leaveok(statwin, TRUE); fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); if(fd == -1) { write_error("Unable to obtain monitoring socket"); goto err; } if(dev_bind_ifname(fd, iface) == -1) { write_error("Unable to bind interface on the socket"); goto err_close; } exitloop = 0; PACKET_INIT(pkt); /* * Data-gathering loop */ while (!exitloop) { gettimeofday(&tv, NULL); now = tv.tv_sec; if ((now - starttime) >= 1) { char buf[64]; unsigned long activity, activity_in, activity_out; unsigned long pps, pps_in, pps_out; unsigned long msecs; wattrset(statwin, BOXATTR); printelapsedtime(statbegin, now, LINES - 3, 1, statwin); msecs = timeval_diff_msec(&tv, &start_tv); rate_add_rate(&rate, span.proto_total.pc_bytes, msecs); activity = rate_get_average(&rate); rate_add_rate(&rate_in, span.proto_in.pc_bytes, msecs); activity_in = rate_get_average(&rate_in); rate_add_rate(&rate_out, span.proto_out.pc_bytes, msecs); activity_out = rate_get_average(&rate_out); rate_add_rate(&pps_rate, span.proto_total.pc_packets, msecs); pps = rate_get_average(&pps_rate); rate_add_rate(&pps_rate_in, span.proto_in.pc_packets, msecs); pps_in = rate_get_average(&pps_rate_in); rate_add_rate(&pps_rate_out, span.proto_out.pc_packets, msecs); pps_out = rate_get_average(&pps_rate_out); memset(&span, 0, sizeof(span)); starttime = now; start_tv = tv; wattrset(statwin, HIGHATTR); rate_print(activity, buf, sizeof(buf)); mvwprintw(statwin, 14, 19, "%s", buf); rate_print_pps(pps, buf, sizeof(buf)); mvwprintw(statwin, 15, 19, "%s", buf); rate_print(activity_in, buf, sizeof(buf)); mvwprintw(statwin, 17, 19, "%s", buf); rate_print_pps(pps_in, buf, sizeof(buf)); mvwprintw(statwin, 18, 19, "%s", buf); rate_print(activity_out, buf, sizeof(buf)); mvwprintw(statwin, 20, 19, "%s", buf); rate_print_pps(pps_out, buf, sizeof(buf)); mvwprintw(statwin, 21, 19, "%s", buf); if (activity > peakactivity) peakactivity = activity; if (activity_in > peakactivity_in) peakactivity_in = activity_in; if (activity_out > peakactivity_out) peakactivity_out = activity_out; if (pps > peakpps) peakpps = pps; if (pps_in > peakpps_in) peakpps_in = pps_in; if (pps_out > peakpps_out) peakpps_out = pps_out; } if (logging) { check_rotate_flag(&logfile); if ((now - startlog) >= options.logspan) { writedstatlog(iface, peakactivity, peakpps, peakactivity_in, peakpps_in, peakactivity_out, peakpps_out, &ifcounts, time(NULL) - statbegin, logfile); startlog = now; } } if (screen_update_needed(&tv, &updtime)) { printdetails(&ifcounts, statwin); update_panels(); doupdate(); updtime = tv; } if ((facilitytime != 0) && (((now - statbegin) / 60) >= facilitytime)) exitloop = 1; if (packet_get(fd, &pkt, &ch, statwin) == -1) { write_error("Packet receive failed"); exitloop = 1; break; } switch (ch) { case ERR: /* no key ready, do nothing */ break; case 12: case 'l': case 'L': tx_refresh_screen(); break; case 'Q': case 'q': case 'X': case 'x': case 24: case 27: exitloop = 1; break; } if (pkt.pkt_len <= 0) continue; int outgoing; pkt_result = packet_process(&pkt, NULL, NULL, NULL, MATCH_OPPOSITE_USECONFIG, options.v6inv4asv6); if (pkt_result != PACKET_OK && pkt_result != MORE_FRAGMENTS) continue; outgoing = (pkt.pkt_pkttype == PACKET_OUTGOING); update_proto_counter(&ifcounts.total, outgoing, pkt.pkt_len); if (pkt.pkt_pkttype == PACKET_BROADCAST) { update_pkt_counter(&ifcounts.bcast, pkt.pkt_len); } update_proto_counter(&span, outgoing, pkt.pkt_len); /* account network layer protocol */ switch(pkt.pkt_protocol) { case ETH_P_IP: if (pkt_result == CHECKSUM_ERROR) { update_pkt_counter(&ifcounts.bad, pkt.pkt_len); continue; } iplen = ntohs(pkt.iphdr->tot_len); update_proto_counter(&ifcounts.ipv4, outgoing, iplen); break; case ETH_P_IPV6: iplen = ntohs(pkt.ip6_hdr->ip6_plen) + 40; update_proto_counter(&ifcounts.ipv6, outgoing, iplen); break; default: update_proto_counter(&ifcounts.nonip, outgoing, iplen); continue; } __u8 ip_protocol = pkt_ip_protocol(&pkt); /* account transport layer protocol */ switch (ip_protocol) { case IPPROTO_TCP: update_proto_counter(&ifcounts.tcp, outgoing, iplen); break; case IPPROTO_UDP: update_proto_counter(&ifcounts.udp, outgoing, iplen); break; case IPPROTO_ICMP: case IPPROTO_ICMPV6: update_proto_counter(&ifcounts.icmp, outgoing, iplen); break; default: update_proto_counter(&ifcounts.other, outgoing, iplen); break; } } err_close: close(fd); err: rate_destroy(&pps_rate_out); rate_destroy(&pps_rate_in); rate_destroy(&pps_rate); rate_destroy(&rate_out); rate_destroy(&rate_in); rate_destroy(&rate); if (options.promisc) { promisc_restore_list(&promisc); promisc_destroy(&promisc); } if (logging) { signal(SIGUSR1, SIG_DFL); writedstatlog(iface, peakactivity, peakpps, peakactivity_in, peakpps_in, peakactivity_out, peakpps_out, &ifcounts, time(NULL) - statbegin, logfile); writelog(logging, logfile, "******** Detailed interface statistics stopped ********"); fclose(logfile); } del_panel(statpanel); delwin(statwin); strcpy(current_logfile, ""); pkt_cleanup(); update_panels(); doupdate(); }
int main (int argc, char **argv, char **envp) { global_prog_name = argv[0]; if (argc == 1) { usage(global_prog_name); exit(1); } // Determine which version of OS X we are running on. int major_version_num; int minor_version_num; int subminor_version_num; get_macosx_version(&major_version_num, &minor_version_num, &subminor_version_num); struct poll_state ps; ps.use_polling = 0; if (major_version_num >= 10) { // Mac OS X 10.5.* and earlier return a number that appears // correct from the ru_maxrss field of getrusage(), also // filled in by wait4(). // Mac OS X 10.6.* always returns 0 for ru_maxrss, so we must // use a different method to measure it. ps.use_polling = 1; } char **child_argv = (char **) malloc((unsigned) argc * sizeof(char *)); int i; for (i = 1; i < argc; i++) { child_argv[i-1] = argv[i]; } child_argv[argc-1] = NULL; // char **p; // for (p = child_argv; *p != NULL; p++) { // fprintf(stderr, " p[%d]='%s'", p-child_argv, *p); // } // fprintf(stderr, "\n"); struct timeval start_time; struct timeval end_time; unsigned int num_cpus = get_num_cpus(); cpu_usage *total_cpu_stats_start = malloc_cpu_stats(1); cpu_usage *per_cpu_stats_start = malloc_cpu_stats(num_cpus); cpu_usage *total_cpu_stats_end = malloc_cpu_stats(1); cpu_usage *per_cpu_stats_end = malloc_cpu_stats(num_cpus); get_cpu_usage(num_cpus, per_cpu_stats_start, total_cpu_stats_start); int ret = gettimeofday(&start_time, NULL); // tbd: check ret pid_t pid = fork(); if (pid == -1) { fprintf(stderr, "Error return status -1 while attempting" " to call fork(). errno=%d\n", errno); perror(global_prog_name); exit(3); } else if (pid == 0) { // We are the child process // Set the uid to the original uid of the process that invoked // the timemem-darwin process, so that the command being // measured is run with that user's priviliges, not with root // privileges. int original_uid = getuid(); int ret = setuid(original_uid); if (ret != 0) { fprintf(stderr, "Error return status %d while attempting" " to set uid to %d. errno=%d\n", ret, original_uid, errno); perror(global_prog_name); exit(4); } ret = execvp(child_argv[0], child_argv); // Normally the call above will not return. fprintf(stderr, "Error return status %d while attempting" " to call execvp(). errno=%d\n", ret, errno); perror(global_prog_name); exit(2); } // We are the parent process. // We want to wait until the child process finishes, but we also // want to periodically poll the child process's resident set size // (memory usage). On OS X 10.5.8 and earlier, simply using // wait4() for the child to finish would fill in the rusage struct // with the maximum resident set size, but this value is always // filled in with 0 in OS X 10.6, hence the use of polling. // We implement the polling by calling setitimer() so that we are // sent a SIGALRM signal every 100 msec. This should cause // wait4() to return early. We handle the signal, and then call // wait4() again. // Read the current maximum resident set size once before starting // the timer, because the most likely reason for it to fail is // that we are not running with root privileges. if (ps.use_polling) { if (init_polling_process_rss(pid, &ps) != 0) { run_as_superuser_msg(global_prog_name); exit(1); } poll_process_rss(&ps); // Set up the SIGALRM signal handler. global_sigalrm_handled = 0; enable_handling_sigalrm(); // Set timer to send us a SIGALRM signal every 100 msec. int timer_period_msec = 100; enable_timer(timer_period_msec); } //int wait_opts = WNOHANG; int wait_opts = 0; int wait_status; int wait4_ret; struct rusage r; while (1) { wait4_ret = wait4(pid, &wait_status, wait_opts, &r); if (wait4_ret != -1) { break; } if ((errno == EINTR) && ps.use_polling) { // Most likely the SIGALRM timer signal was handled. If // so, poll the child process's memory use once. The // timer should automatically signal again periodically // without having to reset it. if (global_sigalrm_handled) { poll_process_rss(&ps); global_sigalrm_handled = 0; if (ps.task_info_errored) { disable_timer(); ignore_sigalrm(); } } // Go around and call wait4() again. } else { fprintf(stderr, "wait4() returned %d. errno=%d\n", wait4_ret, errno); perror(global_prog_name); exit(5); } } // We may not use end_time if there are errors we haven't checked // for yet from wait4(), but it is more accurate to call this as // soon after wait4() returns as we can. It is out of the loop // above to avoid the overhead of calling it on every poll time. if (debug) { fprintf(stderr, "About to call gettimeofday()\n"); } ret = gettimeofday(&end_time, NULL); // tbd: check ret get_cpu_usage(num_cpus, per_cpu_stats_end, total_cpu_stats_end); if (wait4_ret != pid) { fprintf(stderr, "wait4() returned pid=%d. Expected pid" " %d of child process. Try again.\n", wait4_ret, pid); fprintf(stderr, "wait4 r.ru_maxrss=%ld\n", r.ru_maxrss); exit(7); } ps.wait4_returned_normally = 1; if (debug) { fprintf(stderr, "wait4() returned pid=%d of child process." " Done!\n", pid); } if (ps.use_polling) { // Disable the timer. Ignore SIGALRM, too, just in case one // more happens. if (debug) { fprintf(stderr, "About to disable the timer\n"); } disable_timer(); if (debug) { fprintf(stderr, "About to ignore SIGALRM\n"); } ignore_sigalrm(); } // Elapsed time int elapsed_msec = timeval_diff_msec(&start_time, &end_time); fprintf(stderr, "real %9d.%03d\n", (elapsed_msec / 1000), (elapsed_msec % 1000)); // User, sys times fprintf(stderr, "user %9ld.%03d\n", r.ru_utime.tv_sec, r.ru_utime.tv_usec / 1000); fprintf(stderr, "sys %9ld.%03d\n", r.ru_stime.tv_sec, r.ru_stime.tv_usec / 1000); // Maximum resident set size if (! ps.use_polling) { // At least on the Intel Core 2 Duo Mac OS X 10.5.8 machine on // which I first tested this code, it seemed to give a value // of up to 2^31-4096 bytes correctly, but if it went a little // bit over that, the fprintf statement showed it as 0, not // 2^31 bytes. For now, I'll do a special check for 0 and // print out what I believe to be the correct value. // One way to test this on that machine is as follows. The // first command below prints 2^31-4096 bytes as the maximum // resident set size. Without the "if" condition below, the // second command below prints 0 as the maximum resident set // size. // ./timemem-darwin ../../memuse/test-memuse 2096863 // ./timemem-darwin ../../memuse/test-memuse 2096864 // Reference: // http://lists.apple.com/archives/darwin-kernel/2009/Mar/msg00005.html if (r.ru_maxrss == 0L) { // Print 2^31 bytes exactly fprintf(stderr, "2147483648 maximum resident set size from getrusage\n"); } else { fprintf(stderr, "%10lu maximum resident set size from getrusage\n", (unsigned long) r.ru_maxrss); } } if (ps.use_polling) { long delta = (long) ps.max_rss_bytes - (long) r.ru_maxrss; fprintf(stderr, "%10lu maximum resident set size from polling (%.1f MB, delta %ld bytes = %.1f MB)\n", (unsigned long) ps.max_rss_bytes, (double) ps.max_rss_bytes / (1024.0 * 1024.0), delta, (double) delta / (1024.0 * 1024.0)); double elapsed_time_sec = (double) elapsed_msec / 1000.0; fprintf(stderr, "number of times rss polled=%ld, avg of %.1f times per second\n", ps.num_polls, (double) ps.num_polls / elapsed_time_sec); fprintf(stderr, "time between consecutive polls (msec): min=%.1f max=%.1f\n", (double) ps.consecutive_poll_separation_min_msec, (double) ps.consecutive_poll_separation_max_msec); int64 max_rss_first_seen_msec = timeval_diff_msec(&start_time, &(ps.poll_time_when_maxrss_first_seen)); fprintf(stderr, "Max RSS observed %.1f sec after start time\n", (double) max_rss_first_seen_msec / 1000.0); if (ps.task_info_errored) { int64 diff_msec = timeval_diff_msec(&end_time, &(ps.task_info_error_time)); if (diff_msec <= 0 && diff_msec >= -100) { // Then the error most likely occurred because the // child process had already exited. Ignore it. } else { fprintf(stderr, "A call to task_info() returned an error. error_time - end_time = %.3f sec. This may mean the maximum resident set size measurement above is too low.\n", (double) diff_msec / 1000.0); } } } // Show separate busy percentage for each CPU core fprintf(stderr, "Per core CPU utilization (%d cores):", num_cpus); for (i = 0; i < num_cpus; i++) { uint64 total = (per_cpu_stats_end[i].total - per_cpu_stats_start[i].total); int cpu_busy_percent = 0; if (total != 0) { uint64 idle = (per_cpu_stats_end[i].idle - per_cpu_stats_start[i].idle); cpu_busy_percent = (int) round(100.0 * (1.0 - ((float) idle)/total)); } fprintf(stderr, " %d%%", cpu_busy_percent); } fprintf(stderr, "\n"); if (WIFEXITED(wait_status)) { // Exit with the same status that the child process did. exit(WEXITSTATUS(wait_status)); } else if (WIFSIGNALED(wait_status)) { fprintf(stderr, "Command stopped due to signal %d without calling exit().\n", WTERMSIG(wait_status)); exit(1); } else { fprintf(stderr, "Command is stopped due to signal %d, and can be restarted.\n", WSTOPSIG(wait_status)); exit(2); } return 0; }
void ifstats(const struct OPTIONS *options, struct filterstate *ofilter, time_t facilitytime) { int logging = options->logging; struct iftab table; int pkt_result = 0; struct iflist *ptmp = NULL; unsigned int idx = 1; FILE *logfile = NULL; int ch; int fd; struct timeval tv; time_t starttime = 0; time_t statbegin = 0; time_t now = 0; struct timeval start_tv; unsigned long long unow = 0; time_t startlog = 0; time_t updtime = 0; unsigned long long updtime_usec = 0; struct promisc_states *promisc_list; if (!facility_active(GSTATIDFILE, "")) mark_facility(GSTATIDFILE, "general interface statistics", ""); else { write_error("General interface stats already active in another process"); return; } initiflist(&(table.head)); if (table.head == NULL) { no_ifaces_error(); unmark_facility(GSTATIDFILE, ""); return; } initiftab(&table); if ((first_active_facility()) && (options->promisc)) { init_promisc_list(&promisc_list); save_promisc_list(promisc_list); srpromisc(1, promisc_list); destroy_promisc_list(&promisc_list); } adjust_instance_count(PROCCOUNTFILE, 1); if (logging) { if (strcmp(current_logfile, "") == 0) { strcpy(current_logfile, GSTATLOG); if (!daemonized) input_logfile(current_logfile, &logging); } } if (logging) { opentlog(&logfile, GSTATLOG); if (logfile == NULL) logging = 0; } if (logging) { signal(SIGUSR1, rotate_gstat_log); rotate_flag = 0; writelog(logging, logfile, "******** General interface statistics started ********"); } preparescreen(&table); update_panels(); doupdate(); fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); if(fd == -1) { write_error("Unable to obtain monitoring socket"); goto err; } //isdnfd = -1; exitloop = 0; gettimeofday(&tv, NULL); start_tv = tv; starttime = startlog = statbegin = tv.tv_sec; PACKET_INIT(pkt); while (!exitloop) { gettimeofday(&tv, NULL); now = tv.tv_sec; unow = tv.tv_sec * 1000000ULL + tv.tv_usec; if ((now - starttime) >= 1) { unsigned long msecs; msecs = timeval_diff_msec(&tv, &start_tv); updaterates(&table, options->actmode, msecs, idx); printelapsedtime(statbegin, now, LINES - 3, 1, table.borderwin); starttime = now; start_tv = tv; } if (logging) { check_rotate_flag(&logfile); if ((now - startlog) >= options->logspan) { writegstatlog(&table, options->actmode, time(NULL) - statbegin, logfile); startlog = now; } } if (((options->updrate != 0) && (now - updtime >= options->updrate)) || ((options->updrate == 0) && (unow - updtime_usec >= DEFAULT_UPDATE_DELAY))) { update_panels(); doupdate(); updtime = now; updtime_usec = unow; } if ((facilitytime != 0) && (((now - statbegin) / 60) >= facilitytime)) exitloop = 1; if (packet_get(fd, &pkt, &ch, table.statwin) == -1) { write_error("Packet receive failed"); exitloop = 1; break; } switch (ch) { case ERR: /* no key ready, do nothing */ break; case KEY_UP: scrollgstatwin(&table, SCROLLDOWN, &idx); break; case KEY_DOWN: scrollgstatwin(&table, SCROLLUP, &idx); break; case KEY_PPAGE: case '-': pagegstatwin(&table, SCROLLDOWN, &idx); break; case KEY_NPAGE: case ' ': pagegstatwin(&table, SCROLLUP, &idx); break; case 12: case 'l': case 'L': tx_refresh_screen(); break; case 'Q': case 'q': case 'X': case 'x': case 27: case 24: exitloop = 1; break; } if (pkt.pkt_len <= 0) continue; pkt_result = packet_process(&pkt, NULL, NULL, NULL, ofilter, MATCH_OPPOSITE_USECONFIG, options->v6inv4asv6); if (pkt_result != PACKET_OK && pkt_result != MORE_FRAGMENTS) continue; ptmp = positionptr(table.head, pkt.pkt_ifindex); if (!ptmp) continue; ptmp->total++; ptmp->spanbr += pkt.pkt_len; ptmp->br += pkt.pkt_len; if (pkt.pkt_protocol == ETH_P_IP) { ptmp->iptotal++; if (pkt_result == CHECKSUM_ERROR) { (ptmp->badtotal)++; continue; } } else if (pkt.pkt_protocol == ETH_P_IPV6) { ptmp->ip6total++; } else { (ptmp->noniptotal)++; } printifentry(ptmp, table.statwin, idx); } close(fd); err: if ((options->promisc) && (is_last_instance())) { load_promisc_list(&promisc_list); srpromisc(0, promisc_list); destroy_promisc_list(&promisc_list); } adjust_instance_count(PROCCOUNTFILE, -1); del_panel(table.statpanel); delwin(table.statwin); del_panel(table.borderpanel); delwin(table.borderwin); update_panels(); doupdate(); if (logging) { signal(SIGUSR1, SIG_DFL); writegstatlog(&table, options->actmode, time(NULL) - statbegin, logfile); writelog(logging, logfile, "******** General interface statistics stopped ********"); fclose(logfile); } destroyiflist(table.head); pkt_cleanup(); unmark_facility(GSTATIDFILE, ""); strcpy(current_logfile, ""); }