1
0
mirror of https://github.com/nmap/nmap.git synced 2026-01-10 00:19:02 +00:00

Change RateMeter to be more general, measuring just one quantity. Add a

PacketRateMeter specialized for measuring packet and byte rates, and use that
in scan_engine.cc.
This commit is contained in:
david
2008-08-16 01:05:11 +00:00
parent 0644d84fca
commit debfc5f683
3 changed files with 124 additions and 98 deletions

View File

@@ -643,7 +643,7 @@ public:
list<HostScanStats *> completedHosts;
ScanProgressMeter *SPM;
RateMeter send_rate_meter;
PacketRateMeter send_rate_meter;
struct scan_lists *ports;
int rawsd; /* raw socket descriptor */
pcap_t *pd;
@@ -2693,7 +2693,7 @@ static UltraProbe *sendConnectScanProbe(UltraScanInfo *USI, HostScanStats *hss,
PacketTrace::traceConnect(IPPROTO_TCP, (sockaddr *) &sock, socklen, rc,
connect_errno, &USI->now);
/* We don't record a byte count for connect probes. */
USI->send_rate_meter.record(0, &USI->now);
USI->send_rate_meter.update(0, &USI->now);
/* This counts as probe being sent, so update structures */
hss->probes_outstanding.push_back(probe);
probeI = hss->probes_outstanding.end();
@@ -2791,7 +2791,7 @@ static UltraProbe *sendArpScanProbe(UltraScanInfo *USI, HostScanStats *hss,
error("WARNING: eth_send of ARP packet returned %i rather than expected %d (errno=%i: %s)", rc, (int) sizeof(frame), err, strerror(err));
}
PacketTrace::traceArp(PacketTrace::SENT, (u8 *) frame, sizeof(frame), &USI->now);
USI->send_rate_meter.record(sizeof(frame), &USI->now);
USI->send_rate_meter.update(sizeof(frame), &USI->now);
probe->tryno = tryno;
probe->pingseq = pingseq;
/* First build the probe */
@@ -2969,7 +2969,7 @@ static UltraProbe *sendIPScanProbe(UltraScanInfo *USI, HostScanStats *hss,
free(packet);
}
} else assert(0); /* TODO: Maybe RPC scan and the like */
USI->send_rate_meter.record(packetlen, &USI->now);
USI->send_rate_meter.update(packetlen, &USI->now);
/* Now that the probe has been sent, add it to the Queue for this host */
hss->probes_outstanding.push_back(probe);
USI->gstats->num_probes_active++;

167
timing.cc
View File

@@ -238,19 +238,18 @@ void enforce_scan_delay(struct timeval *tv) {
return;
}
/* Initialize the constant CURRENT_RATE_HISTORY that defines how far back we
look when calculating the current rates. */
RateMeter::RateMeter() : CURRENT_RATE_HISTORY(5.0) {
/* current_rate_history defines how far back (in seconds) we look when
calculating the current rate. */
RateMeter::RateMeter(double current_rate_history) {
this->current_rate_history = current_rate_history;
start_tv.tv_sec = 0;
start_tv.tv_usec = 0;
stop_tv.tv_sec = 0;
stop_tv.tv_usec = 0;
last_update_tv.tv_sec = 0;
last_update_tv.tv_usec = 0;
num_packets = 0;
num_bytes = 0;
current_packet_rate = 0.0;
current_byte_rate = 0.0;
total = 0.0;
current_rate = 0.0;
assert(!isSet(&start_tv));
assert(!isSet(&stop_tv));
}
@@ -273,52 +272,9 @@ void RateMeter::stop(const struct timeval *now) {
stop_tv = *now;
}
/* Record a packet of length len. If now is not NULL, use it as the time the
packet was received rather than calling gettimeofday. */
void RateMeter::record(u32 len, const struct timeval *now) {
update(1, len, now);
}
double RateMeter::getOverallPacketRate(const struct timeval *now) const {
return num_packets / elapsedTime(now);
}
/* Get the "current" packet rate (actually a moving average of the last few
seconds). If update is true (its default value), lower the rate to account
for the time since the last packet was received. */
double RateMeter::getCurrentPacketRate(const struct timeval *now, bool update) {
if (update)
this->update(0, 0, now);
return current_packet_rate;
}
double RateMeter::getOverallByteRate(const struct timeval *now) const {
return num_bytes / elapsedTime(now);
}
/* Get the "current" byte rate (actually a moving average of the last few
seconds). If update is true (its default value), lower the rate to account
for the time since the last bytes were received. */
double RateMeter::getCurrentByteRate(const struct timeval *now, bool update) {
if (update)
this->update(0, 0, now);
return current_byte_rate;
}
unsigned long long RateMeter::getNumPackets(void) const {
return num_packets;
}
unsigned long long RateMeter::getNumBytes(void) const {
return num_bytes;
}
/* Update the rates to include packets additional packets and bytes additional
bytes. If now is not NULL, use it as the time the packets and bytes were
received rather than calling gettimeofday. */
void RateMeter::update(u32 packets, u32 bytes, const struct timeval *now) {
/* Update the rates to reflect the given amount added to the total at the time
now. If now is NULL, get the current time with gettimeofday. */
void RateMeter::update(double amount, const struct timeval *now) {
struct timeval tv;
static int clockwarn = 0;
double diff;
@@ -328,9 +284,8 @@ void RateMeter::update(u32 packets, u32 bytes, const struct timeval *now) {
assert(isSet(&start_tv));
assert(!isSet(&stop_tv));
/* Update the overall counters. */
num_packets += packets;
num_bytes += bytes;
/* Update the total. */
total += amount;
if (now == NULL) {
gettimeofday(&tv, NULL);
@@ -339,9 +294,9 @@ void RateMeter::update(u32 packets, u32 bytes, const struct timeval *now) {
if (!isSet(&last_update_tv))
last_update_tv = start_tv;
/* Calculate approximate moving averages of how many packets and bytes were
recorded in the last CURRENT_RATE_HISTORY seconds. These averages are what
are returned as the "current" rates. */
/* Calculate the approximate moving average of how much was recorded in the
last current_rate_history seconds. This average is what is returned as the
"current" rate. */
/* How long since the last update? */
diff = TIMEVAL_SUBTRACT(*now, last_update_tv) / 1000000.0;
@@ -365,40 +320,53 @@ void RateMeter::update(u32 packets, u32 bytes, const struct timeval *now) {
fatal("RateMeter::update: negative time delta; now=%lu.%lu; last_update_tv=%lu.%lu", (unsigned long) now->tv_sec, (unsigned long) now->tv_usec, (unsigned long) last_update_tv.tv_sec, (unsigned long) last_update_tv.tv_usec);
/* Find out how far back in time to look. We want to look back
CURRENT_RATE_HISTORY seconds, or to when the last update occurred,
current_rate_history seconds, or to when the last update occurred,
whichever is longer. However, we never look past the start. */
struct timeval tmp;
/* Find the time CURRENT_RATE_HISTORY seconds after the start. That's our
/* Find the time current_rate_history seconds after the start. That's our
threshold for deciding how far back to look. */
TIMEVAL_ADD(tmp, start_tv, (time_t) (CURRENT_RATE_HISTORY * 1000000.0));
TIMEVAL_ADD(tmp, start_tv, (time_t) (current_rate_history * 1000000.0));
if (TIMEVAL_AFTER(*now, tmp))
interval = MAX(CURRENT_RATE_HISTORY, diff);
interval = MAX(current_rate_history, diff);
else
interval = TIMEVAL_SUBTRACT(*now, start_tv) / 1000000.0;
assert(diff <= interval);
/* If we get packets in the very same instant that the timer is started,
/* If we record an amount in the very same instant that the timer is started,
there's no way to calculate meaningful rates. Ignore it. */
if (interval == 0.0)
return;
/* To calculate the approximate average of the packet rate over the last
/* To calculate the approximate average of the rate over the last
interval seconds, we assume that the rate was constant over that interval.
We calculate how many packets would have been received in that interval,
ignoring the first diff seconds' worth:
(interval - diff) * current_packet_rate.
Then we add how many packets were received in the most recent diff seconds.
Divide by the width of the interval to get the average. */
count = (interval - diff) * current_packet_rate + packets;
current_packet_rate = count / interval;
assert(current_packet_rate >= 0.0);
/* Likewise with the byte rate. */
count = (interval - diff) * current_byte_rate + bytes;
current_byte_rate = count / interval;
assert(current_byte_rate >= 0.0);
We calculate how much would have been received in that interval, ignoring
the first diff seconds' worth:
(interval - diff) * current_rate.
Then we add how much was received in the most recent diff seconds. Divide
by the width of the interval to get the average. */
count = (interval - diff) * current_rate + amount;
current_rate = count / interval;
last_update_tv = *now;
}
double RateMeter::getOverallRate(const struct timeval *now) const {
return total / elapsedTime(now);
}
/* Get the "current" rate (actually a moving average of the last
current_rate_history seconds). If update is true (its default value), lower
the rate to account for the time since the last record. */
double RateMeter::getCurrentRate(const struct timeval *now, bool update) {
if (update)
this->update(0.0, now);
return current_rate;
}
double RateMeter::getTotal(void) const {
return total;
}
/* Get the number of seconds the meter has been running: if it has been stopped,
the amount of time between start and stop, or if it is still running, the
amount of time between start and now. */
@@ -426,6 +394,51 @@ bool RateMeter::isSet(const struct timeval *tv) {
return tv->tv_sec != 0 || tv->tv_usec != 0;
}
PacketRateMeter::PacketRateMeter(double current_rate_history) {
packet_rate_meter = RateMeter(current_rate_history);
byte_rate_meter = RateMeter(current_rate_history);
}
void PacketRateMeter::start(const struct timeval *now) {
packet_rate_meter.start(now);
byte_rate_meter.start(now);
}
void PacketRateMeter::stop(const struct timeval *now) {
packet_rate_meter.stop(now);
byte_rate_meter.stop(now);
}
/* Record one packet of length len. */
void PacketRateMeter::update(u32 len, const struct timeval *now) {
packet_rate_meter.update(1, now);
byte_rate_meter.update(len, now);
}
double PacketRateMeter::getOverallPacketRate(const struct timeval *now) const {
return packet_rate_meter.getOverallRate(now);
}
double PacketRateMeter::getCurrentPacketRate(const struct timeval *now, bool update) {
return packet_rate_meter.getCurrentRate(now, update);
}
double PacketRateMeter::getOverallByteRate(const struct timeval *now) const {
return byte_rate_meter.getOverallRate(now);
}
double PacketRateMeter::getCurrentByteRate(const struct timeval *now, bool update) {
return byte_rate_meter.getCurrentRate(now, update);
}
unsigned long long PacketRateMeter::getNumPackets(void) const {
return (unsigned long long) packet_rate_meter.getTotal();
}
unsigned long long PacketRateMeter::getNumBytes(void) const {
return (unsigned long long) byte_rate_meter.getTotal();
}
ScanProgressMeter::ScanProgressMeter(const char *stypestr) {
scantypestr = strdup(stypestr);
gettimeofday(&begin, NULL);

View File

@@ -123,31 +123,28 @@ void adjust_timeouts2(const struct timeval *sent,
response. We update our RTT averages, etc. */
void adjust_timeouts(struct timeval sent, struct timeout_info *to);
#define DEFAULT_CURRENT_RATE_HISTORY 5.0
/* Sleeps if necessary to ensure that it isn't called twice within less
time than o.send_delay. If it is passed a non-null tv, the POST-SLEEP
time is recorded in it */
void enforce_scan_delay(struct timeval *tv);
/* This class implements current and lifetime average data rates for packets and
bytes. */
/* This class measures current and lifetime average rates for some quantity. */
class RateMeter {
public:
RateMeter();
RateMeter(double current_rate_history = DEFAULT_CURRENT_RATE_HISTORY);
void start(const struct timeval *now = NULL);
void stop(const struct timeval *now = NULL);
void record(u32 len, const struct timeval *now = NULL);
double getOverallPacketRate(const struct timeval *now = NULL) const;
double getCurrentPacketRate(const struct timeval *now = NULL, bool update =true);
double getOverallByteRate(const struct timeval *now = NULL) const;
double getCurrentByteRate(const struct timeval *now = NULL, bool update =true);
unsigned long long getNumPackets(void) const;
unsigned long long getNumBytes(void) const;
void update(double amount, const struct timeval *now = NULL);
double getOverallRate(const struct timeval *now = NULL) const;
double getCurrentRate(const struct timeval *now = NULL, bool update = true);
double getTotal(void) const;
private:
/* How many seconds to look back when calculating the "current" rates. */
const double CURRENT_RATE_HISTORY;
double current_rate_history;
/* When this meter started recording. */
struct timeval start_tv;
@@ -156,17 +153,33 @@ class RateMeter {
/* The last time the current sample rates were updated. */
struct timeval last_update_tv;
unsigned long long num_packets;
unsigned long long num_bytes;
double total;
double current_rate;
double current_packet_rate;
double current_byte_rate;
void update(u32 packets, u32 bytes, const struct timeval *now);
double elapsedTime(const struct timeval *now = NULL) const;
static bool isSet(const struct timeval *tv);
};
/* A specialization of RateMeter that measures packet and byte rates. */
class PacketRateMeter {
public:
PacketRateMeter(double current_rate_history = DEFAULT_CURRENT_RATE_HISTORY);
void start(const struct timeval *now = NULL);
void stop(const struct timeval *now = NULL);
void update(u32 len, const struct timeval *now = NULL);
double getOverallPacketRate(const struct timeval *now = NULL) const;
double getCurrentPacketRate(const struct timeval *now = NULL, bool update = true);
double getOverallByteRate(const struct timeval *now = NULL) const;
double getCurrentByteRate(const struct timeval *now = NULL, bool update =true);
unsigned long long getNumPackets(void) const;
unsigned long long getNumBytes(void) const;
private:
RateMeter packet_rate_meter;
RateMeter byte_rate_meter;
};
class ScanProgressMeter {
public:
/* A COPY of stypestr is made and saved for when stats are printed */