"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "src/bwping.c" between
bwping-1.16.tar.gz and bwping-1.17.tar.gz

About: BWPing is a tool to measure bandwidth and response times between two hosts using Internet Control Message Protocol (ICMP) echo request/echo reply mechanism.

bwping.c  (bwping-1.16):bwping.c  (bwping-1.17)
skipping to change at line 40 skipping to change at line 40
#ifdef HAVE_NETINET_ICMP6_H #ifdef HAVE_NETINET_ICMP6_H
#include <netinet/icmp6.h> #include <netinet/icmp6.h>
#endif #endif
#ifdef __CYGWIN__ #ifdef __CYGWIN__
#include "../include/cygwin.h" #include "../include/cygwin.h"
#endif #endif
#include <netdb.h> #include <netdb.h>
const size_t MAX_IPV4_HDR_SIZE = 60; static const size_t MAX_IPV4_HDR_SIZE = 60;
const uint32_t CALIBRATION_CYCLES = 100, static const uint32_t CALIBRATION_CYCLES = 100,
PKT_BURST_PRECISION = 1000, PKT_BURST_PRECISION = 1000,
BUF_SIZE_RESERVE_FACTOR = 10; BUF_SIZE_RESERVE_FACTOR = 10;
int64_t min_rtt, max_rtt, average_rtt; static char *prog_name;
char *prog_name;
static void get_time(struct timespec *ts) static void get_time(struct timespec *ts)
{ {
#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_REALTIME) #if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_REALTIME)
#if defined(CLOCK_HIGHRES) #if defined(CLOCK_HIGHRES)
const clockid_t id = CLOCK_HIGHRES; const clockid_t id = CLOCK_HIGHRES;
#elif defined(CLOCK_MONOTONIC_RAW) #elif defined(CLOCK_MONOTONIC_RAW)
const clockid_t id = CLOCK_MONOTONIC_RAW; const clockid_t id = CLOCK_MONOTONIC_RAW;
#elif defined(CLOCK_MONOTONIC) #elif defined(CLOCK_MONOTONIC)
const clockid_t id = CLOCK_MONOTONIC; const clockid_t id = CLOCK_MONOTONIC;
#else #else
const clockid_t id = CLOCK_REALTIME; const clockid_t id = CLOCK_REALTIME;
#endif /* CLOCK_XXX */ #endif
if (clock_gettime(id, ts) < 0) { if (clock_gettime(id, ts) < 0) {
fprintf(stderr, "%s: clock_gettime() failed: %s\n", prog_name, strerror( errno)); fprintf(stderr, "%s: clock_gettime() failed: %s\n", prog_name, strerror( errno));
ts->tv_sec = 0; ts->tv_sec = 0;
ts->tv_nsec = 0; ts->tv_nsec = 0;
} }
#else #else /* HAVE_CLOCK_GETTIME */
struct timeval tv; struct timeval tv;
if (gettimeofday(&tv, NULL) < 0) { if (gettimeofday(&tv, NULL) < 0) {
fprintf(stderr, "%s: gettimeofday() failed: %s\n", prog_name, strerror(e rrno)); fprintf(stderr, "%s: gettimeofday() failed: %s\n", prog_name, strerror(e rrno));
ts->tv_sec = 0; ts->tv_sec = 0;
ts->tv_nsec = 0; ts->tv_nsec = 0;
} else { } else {
ts->tv_sec = tv.tv_sec; ts->tv_sec = tv.tv_sec;
ts->tv_nsec = tv.tv_usec * 1000; ts->tv_nsec = tv.tv_usec * 1000;
} }
#endif /* HAVE_CLOCK_GETTIME */ #endif /* HAVE_CLOCK_GETTIME */
} }
static int64_t ts_sub(struct timespec *ts1, struct timespec *ts2) static int64_t ts_sub(const struct timespec *ts1, const struct timespec *ts2)
{ {
return ((int64_t)ts1->tv_sec - (int64_t)ts2->tv_sec) * 1000000 + (ts1->tv_ns ec - ts2->tv_nsec) / 1000; return ((int64_t)ts1->tv_sec - (int64_t)ts2->tv_sec) * 1000000 + (ts1->tv_ns ec - ts2->tv_nsec) / 1000;
} }
static uint16_t cksum(void *packet, size_t pkt_size) static uint16_t cksum(const void *packet, size_t pkt_size)
{ {
uint16_t buf[IP_MAXPACKET]; uint16_t buf[IP_MAXPACKET] = {0};
memset(buf, 0, sizeof(buf));
memcpy(buf, packet, pkt_size); memcpy(buf, packet, pkt_size);
uint32_t sum = 0; uint32_t sum = 0;
for (size_t i = 0; i < pkt_size / 2 + pkt_size % 2; i++) { for (size_t i = 0; i < pkt_size / 2 + pkt_size % 2; i++) {
sum += buf[i]; sum += buf[i];
} }
sum = (sum >> 16) + (sum & 0xFFFF); sum = (sum >> 16) + (sum & 0xFFFF);
sum += (sum >> 16); sum += (sum >> 16);
skipping to change at line 134 skipping to change at line 132
} }
get_time(&end); get_time(&end);
sum += ts_sub(&end, &begin); sum += ts_sub(&end, &begin);
} }
return sum / CALIBRATION_CYCLES; return sum / CALIBRATION_CYCLES;
} }
static void send_ping4(int sock, struct addrinfo *to_ai, size_t pkt_size, uint16 _t ident, bool first_in_burst, uint32_t *transmitted_number, uint64_t *transmitt ed_volume) static void send_ping4(int sock, const struct addrinfo *to_ai, size_t pkt_size, uint16_t ident, bool first_in_burst, uint32_t *transmitted_number, uint64_t *tra nsmitted_volume)
{ {
char packet[IP_MAXPACKET]; char packet[IP_MAXPACKET] = {0};
struct icmp icmp4;
memset(&icmp4, 0, sizeof(icmp4)); struct icmp icmp4 = {.icmp_type = ICMP_ECHO, .icmp_code = 0, .icmp_cksum = 0
, .icmp_id = ident, .icmp_seq = htons(*transmitted_number)};
icmp4.icmp_type = ICMP_ECHO;
icmp4.icmp_code = 0;
icmp4.icmp_cksum = 0;
icmp4.icmp_id = ident;
icmp4.icmp_seq = htons(*transmitted_number);
memcpy(packet, &icmp4, sizeof(icmp4)); memcpy(packet, &icmp4, sizeof(icmp4));
struct timespec pkt_time;
if (first_in_burst) { if (first_in_burst) {
struct timespec now; struct timespec pkt_time;
get_time(&now); get_time(&pkt_time);
pkt_time.tv_sec = now.tv_sec; memcpy(&packet[sizeof(icmp4)], &pkt_time, sizeof(pkt_time));
pkt_time.tv_nsec = now.tv_nsec;
} else {
memset(&pkt_time, 0, sizeof(pkt_time));
} }
memcpy(&packet[sizeof(icmp4)], &pkt_time, sizeof(pkt_time));
icmp4.icmp_cksum = cksum(packet, pkt_size); icmp4.icmp_cksum = cksum(packet, pkt_size);
memcpy(&packet[offsetof(struct icmp, icmp_cksum)], &icmp4.icmp_cksum, sizeof (icmp4.icmp_cksum)); memcpy(&packet[offsetof(struct icmp, icmp_cksum)], &icmp4.icmp_cksum, sizeof (icmp4.icmp_cksum));
ssize_t res = sendto(sock, packet, pkt_size, 0, to_ai->ai_addr, to_ai->ai_ad drlen); ssize_t res = sendto(sock, packet, pkt_size, 0, to_ai->ai_addr, to_ai->ai_ad drlen);
if (res < 0) { if (res < 0) {
fprintf(stderr, "%s: sendto() failed: %s\n", prog_name, strerror(errno)) ; fprintf(stderr, "%s: sendto() failed: %s\n", prog_name, strerror(errno)) ;
} else if (res != (ssize_t)pkt_size) { } else if (res != (ssize_t)pkt_size) {
fprintf(stderr, "%s: partial write: packet size: %zu, sent: %zd\n", prog _name, pkt_size, res); fprintf(stderr, "%s: partial write: packet size: %zu, sent: %zd\n", prog _name, pkt_size, res);
} }
(*transmitted_number)++; (*transmitted_number)++;
(*transmitted_volume) += pkt_size; (*transmitted_volume) += pkt_size;
} }
static void send_ping6(int sock, struct addrinfo *to_ai, size_t pkt_size, uint16 _t ident, bool first_in_burst, uint32_t *transmitted_number, uint64_t *transmitt ed_volume) static void send_ping6(int sock, const struct addrinfo *to_ai, size_t pkt_size, uint16_t ident, bool first_in_burst, uint32_t *transmitted_number, uint64_t *tra nsmitted_volume)
{ {
char packet[IP_MAXPACKET]; char packet[IP_MAXPACKET] = {0};
struct icmp6_hdr icmp6;
memset(&icmp6, 0, sizeof(icmp6)); struct icmp6_hdr icmp6 = {.icmp6_type = ICMP6_ECHO_REQUEST, .icmp6_code = 0,
.icmp6_cksum = 0, .icmp6_id = ident, .icmp6_seq = htons(*transmitted_number)};
icmp6.icmp6_type = ICMP6_ECHO_REQUEST;
icmp6.icmp6_code = 0;
icmp6.icmp6_cksum = 0;
icmp6.icmp6_id = ident;
icmp6.icmp6_seq = htons(*transmitted_number);
memcpy(packet, &icmp6, sizeof(icmp6)); memcpy(packet, &icmp6, sizeof(icmp6));
struct timespec pkt_time;
if (first_in_burst) { if (first_in_burst) {
struct timespec now; struct timespec pkt_time;
get_time(&now); get_time(&pkt_time);
pkt_time.tv_sec = now.tv_sec; memcpy(&packet[sizeof(icmp6)], &pkt_time, sizeof(pkt_time));
pkt_time.tv_nsec = now.tv_nsec;
} else {
memset(&pkt_time, 0, sizeof(pkt_time));
} }
memcpy(&packet[sizeof(icmp6)], &pkt_time, sizeof(pkt_time));
ssize_t res = sendto(sock, packet, pkt_size, 0, to_ai->ai_addr, to_ai->ai_ad drlen); ssize_t res = sendto(sock, packet, pkt_size, 0, to_ai->ai_addr, to_ai->ai_ad drlen);
if (res < 0) { if (res < 0) {
fprintf(stderr, "%s: sendto() failed: %s\n", prog_name, strerror(errno)) ; fprintf(stderr, "%s: sendto() failed: %s\n", prog_name, strerror(errno)) ;
} else if (res != (ssize_t)pkt_size) { } else if (res != (ssize_t)pkt_size) {
fprintf(stderr, "%s: partial write: packet size: %zu, sent: %zd\n", prog _name, pkt_size, res); fprintf(stderr, "%s: partial write: packet size: %zu, sent: %zd\n", prog _name, pkt_size, res);
} }
(*transmitted_number)++; (*transmitted_number)++;
(*transmitted_volume) += pkt_size; (*transmitted_volume) += pkt_size;
} }
static bool recv_ping4(int sock, uint16_t ident, uint32_t *received_number, uint 64_t *received_volume) static bool recv_ping4(int sock, uint16_t ident, uint32_t *received_number, uint 64_t *received_volume, int64_t *min_rtt, int64_t *max_rtt, int64_t *average_rtt)
{ {
char packet[IP_MAXPACKET]; char packet[IP_MAXPACKET];
struct iovec iov; struct iovec iov = {.iov_base = packet, .iov_len = sizeof(packet)};
struct msghdr msg = {.msg_iov = &iov, .msg_iovlen = 1};
memset(&iov, 0, sizeof(iov));
iov.iov_base = packet;
iov.iov_len = sizeof(packet);
struct msghdr msg;
memset(&msg, 0, sizeof(msg));
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
ssize_t res = recvmsg(sock, &msg, MSG_DONTWAIT); ssize_t res = recvmsg(sock, &msg, MSG_DONTWAIT);
struct ip ip4; struct ip ip4;
if (res >= (ssize_t)sizeof(ip4)) { if (res >= (ssize_t)sizeof(ip4)) {
memcpy(&ip4, packet, sizeof(ip4)); memcpy(&ip4, packet, sizeof(ip4));
size_t hdr_len = ip4.ip_hl << 2; size_t hdr_len = ip4.ip_hl << 2;
skipping to change at line 273 skipping to change at line 230
if (res >= (ssize_t)(hdr_len + sizeof(icmp4) + sizeof(pkt_time)) ) { if (res >= (ssize_t)(hdr_len + sizeof(icmp4) + sizeof(pkt_time)) ) {
memcpy(&pkt_time, &packet[hdr_len + sizeof(icmp4)], sizeof(p kt_time)); memcpy(&pkt_time, &packet[hdr_len + sizeof(icmp4)], sizeof(p kt_time));
if (pkt_time.tv_sec != 0 || pkt_time.tv_nsec != 0) { if (pkt_time.tv_sec != 0 || pkt_time.tv_nsec != 0) {
struct timespec now; struct timespec now;
get_time(&now); get_time(&now);
int64_t rtt = ts_sub(&now, &pkt_time) / 1000; int64_t rtt = ts_sub(&now, &pkt_time) / 1000;
if (min_rtt > rtt) { if (*min_rtt > rtt) {
min_rtt = rtt; *min_rtt = rtt;
} }
if (max_rtt < rtt) { if (*max_rtt < rtt) {
max_rtt = rtt; *max_rtt = rtt;
} }
average_rtt = *received_number ? ((average_rtt * (*recei ved_number - 1)) + rtt) / *received_number : average_rtt; *average_rtt = *received_number ? ((*average_rtt * (*rec eived_number - 1)) + rtt) / *received_number : *average_rtt;
} }
} }
} }
} }
return true; return true;
} else { } else {
return false; return false;
} }
} }
static bool recv_ping6(int sock, uint16_t ident, uint32_t *received_number, uint 64_t *received_volume) static bool recv_ping6(int sock, uint16_t ident, uint32_t *received_number, uint 64_t *received_volume, int64_t *min_rtt, int64_t *max_rtt, int64_t *average_rtt)
{ {
char packet[IP_MAXPACKET]; char packet[IP_MAXPACKET];
struct iovec iov; struct iovec iov = {.iov_base = packet, .iov_len = sizeof(packet)};
struct msghdr msg = {.msg_iov = &iov, .msg_iovlen = 1};
memset(&iov, 0, sizeof(iov));
iov.iov_base = packet;
iov.iov_len = sizeof(packet);
struct msghdr msg;
memset(&msg, 0, sizeof(msg));
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
ssize_t res = recvmsg(sock, &msg, MSG_DONTWAIT); ssize_t res = recvmsg(sock, &msg, MSG_DONTWAIT);
struct icmp6_hdr icmp6; struct icmp6_hdr icmp6;
if (res >= (ssize_t)sizeof(icmp6)) { if (res >= (ssize_t)sizeof(icmp6)) {
memcpy(&icmp6, packet, sizeof(icmp6)); memcpy(&icmp6, packet, sizeof(icmp6));
if (icmp6.icmp6_type == ICMP6_ECHO_REPLY && if (icmp6.icmp6_type == ICMP6_ECHO_REPLY &&
icmp6.icmp6_id == ident) { icmp6.icmp6_id == ident) {
skipping to change at line 334 skipping to change at line 280
if (res >= (ssize_t)(sizeof(icmp6) + sizeof(pkt_time))) { if (res >= (ssize_t)(sizeof(icmp6) + sizeof(pkt_time))) {
memcpy(&pkt_time, &packet[sizeof(icmp6)], sizeof(pkt_time)); memcpy(&pkt_time, &packet[sizeof(icmp6)], sizeof(pkt_time));
if (pkt_time.tv_sec != 0 || pkt_time.tv_nsec != 0) { if (pkt_time.tv_sec != 0 || pkt_time.tv_nsec != 0) {
struct timespec now; struct timespec now;
get_time(&now); get_time(&now);
int64_t rtt = ts_sub(&now, &pkt_time) / 1000; int64_t rtt = ts_sub(&now, &pkt_time) / 1000;
if (min_rtt > rtt) { if (*min_rtt > rtt) {
min_rtt = rtt; *min_rtt = rtt;
} }
if (max_rtt < rtt) { if (*max_rtt < rtt) {
max_rtt = rtt; *max_rtt = rtt;
} }
average_rtt = *received_number ? ((average_rtt * (*received_ number - 1)) + rtt) / *received_number : average_rtt; *average_rtt = *received_number ? ((*average_rtt * (*receive d_number - 1)) + rtt) / *received_number : *average_rtt;
} }
} }
} }
return true; return true;
} else { } else {
return false; return false;
} }
} }
static bool resolve_name(bool ipv4_mode, char *name, struct addrinfo **addr_info ) static bool resolve_name(bool ipv4_mode, const char *name, struct addrinfo **add r_info)
{ {
struct addrinfo hints; struct addrinfo hints = {.ai_flags = AI_CANONNAME, .ai_socktype = SOCK_RAW};
memset(&hints, 0, sizeof(hints));
hints.ai_flags = AI_CANONNAME;
hints.ai_socktype = SOCK_RAW;
if (ipv4_mode) { if (ipv4_mode) {
hints.ai_family = AF_INET; hints.ai_family = AF_INET;
hints.ai_protocol = IPPROTO_ICMP; hints.ai_protocol = IPPROTO_ICMP;
} else { } else {
hints.ai_family = AF_INET6; hints.ai_family = AF_INET6;
hints.ai_protocol = IPPROTO_ICMPV6; hints.ai_protocol = IPPROTO_ICMPV6;
} }
int res = getaddrinfo(name, NULL, &hints, addr_info); int res = getaddrinfo(name, NULL, &hints, addr_info);
if (res != 0) { if (res != 0) {
fprintf(stderr, "%s: cannot resolve %s: %s\n", prog_name, name, gai_stre rror(res)); fprintf(stderr, "%s: cannot resolve %s: %s\n", prog_name, name, gai_stre rror(res));
return false; return false;
} else { } else {
return true; return true;
} }
} }
int main(int argc, char **argv) int main(int argc, char *argv[])
{ {
prog_name = basename(argv[0]); prog_name = basename(argv[0]);
bool ipv4_mode = (strcmp(prog_name, "bwping") == 0); bool ipv4_mode = (strcmp(prog_name, "bwping") == 0);
int exit_val = EX_OK; int exit_val = EX_OK;
unsigned int buf_size = 0, unsigned int buf_size = 0,
tos_or_traf_class = 0; tos_or_traf_class = 0;
size_t pkt_size = 0; size_t pkt_size = 0;
int32_t reporting_period = 0; int32_t reporting_period = 0;
skipping to change at line 554 skipping to change at line 495
char addr_buf[ipv4_mode ? INET_ADDRSTRLEN : INET6_ADDRSTRLEN]; char addr_buf[ipv4_mode ? INET_ADDRSTRLEN : INET6_ADDRSTRLEN];
if (getnameinfo(to_ai->ai_addr, to_ai->ai_addrlen, addr_buf, siz eof(addr_buf), NULL, 0, NI_NUMERICHOST) != 0) { if (getnameinfo(to_ai->ai_addr, to_ai->ai_addrlen, addr_buf, siz eof(addr_buf), NULL, 0, NI_NUMERICHOST) != 0) {
addr_buf[0] = '?'; addr_buf[0] = '?';
addr_buf[1] = 0; addr_buf[1] = 0;
} }
printf("Target: %s (%s), transfer speed: %" PRIu32 " kbps, packe t size: %zu bytes, traffic volume: %" PRIu64 " bytes\n", printf("Target: %s (%s), transfer speed: %" PRIu32 " kbps, packe t size: %zu bytes, traffic volume: %" PRIu64 " bytes\n",
target, addr_buf, kbps, pkt_size, volume); target, addr_buf, kbps, pkt_size, volume);
min_rtt = INT64_MAX;
max_rtt = 0;
average_rtt = 0;
bool finish = false; bool finish = false;
uint32_t transmitted_number = 0, uint32_t transmitted_number = 0,
received_number = 0; received_number = 0;
int64_t min_rtt = INT64_MAX,
max_rtt = 0,
average_rtt = 0;
uint64_t transmitted_volume = 0, uint64_t transmitted_volume = 0,
received_volume = 0; received_volume = 0;
int64_t interval = (int64_t)pkt_size * 8000 / kbps, int64_t interval = (int64_t)pkt_size * 8000 / kbps,
min_interval = calibrate_timer(); min_interval = calibrate_timer();
uint32_t pkt_burst; uint32_t pkt_burst;
if (interval >= min_interval) { if (interval >= min_interval) {
pkt_burst = PKT_BURST_PRECISION * 1; pkt_burst = PKT_BURST_PRECISION * 1;
skipping to change at line 644 skipping to change at line 584
FD_SET(sock, &fds); FD_SET(sock, &fds);
struct timeval timeout; struct timeval timeout;
timeout.tv_sec = select_timeout / 1000000; timeout.tv_sec = select_timeout / 1000000;
timeout.tv_usec = select_timeout % 1000000; timeout.tv_usec = select_timeout % 1000000;
int n = select(sock + 1, &fds, NULL, NULL, &timeout); int n = select(sock + 1, &fds, NULL, NULL, &timeout);
if (n > 0) { if (n > 0) {
while (ipv4_mode ? recv_ping4(sock, ident, &received while (ipv4_mode ? recv_ping4(sock, ident, &received
_number, &received_volume) : _number, &received_volume, &min_rtt, &max_rtt, &average_rtt) :
recv_ping6(sock, ident, &received recv_ping6(sock, ident, &received
_number, &received_volume)) { _number, &received_volume, &min_rtt, &max_rtt, &average_rtt)) {
if (received_number >= transmitted_number) { if (received_number >= transmitted_number) {
break; break;
} }
} }
} }
struct timespec now; struct timespec now;
get_time(&now); get_time(&now);
 End of changes. 40 change blocks. 
108 lines changed or deleted 50 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)