version 1.57, 2018/08/08 14:35:38 |
version 1.58, 2018/09/28 18:21:26 |
|
|
static void saddr_ntop(const struct sockaddr *, socklen_t, char *, size_t); |
static void saddr_ntop(const struct sockaddr *, socklen_t, char *, size_t); |
static void drop_gid(void); |
static void drop_gid(void); |
static void set_slice_timer(int); |
static void set_slice_timer(int); |
static void print_tcp_header(void); |
static void print_tcp_header(void); |
static void kget(u_long, void *, size_t); |
static void kget(u_long, void *, size_t); |
static u_long kfind_tcb(int); |
static u_long kfind_tcb(int); |
static void kupdate_stats(u_long, struct inpcb *, struct tcpcb *, |
static void kupdate_stats(u_long, struct inpcb *, struct tcpcb *, |
|
|
static struct { |
static struct { |
unsigned long long slice_bytes; /* bytes for last slice */ |
unsigned long long slice_bytes; /* bytes for last slice */ |
long double peak_mbps; /* peak mbps so far */ |
long double peak_mbps; /* peak mbps so far */ |
int nconns; /* connected clients */ |
int nconns; /* connected clients */ |
struct event timer; /* process timer */ |
struct event timer; /* process timer */ |
} mainstats; |
} mainstats; |
|
|
|
|
/* XXX Is there a better way to do this ? */ |
/* XXX Is there a better way to do this ? */ |
tv.tv_sec = ptb->rflag / 1000; |
tv.tv_sec = ptb->rflag / 1000; |
tv.tv_usec = (ptb->rflag % 1000) * 1000; |
tv.tv_usec = (ptb->rflag % 1000) * 1000; |
|
|
evtimer_add(&mainstats.timer, &tv); |
evtimer_add(&mainstats.timer, &tv); |
} else if (evtimer_pending(&mainstats.timer, NULL)) |
} else if (evtimer_pending(&mainstats.timer, NULL)) |
evtimer_del(&mainstats.timer); |
evtimer_del(&mainstats.timer); |
} |
} |
|
|
static int |
static int |
clock_gettime_tv(clockid_t clock_id, struct timeval *tv) |
clock_gettime_tv(clockid_t clock_id, struct timeval *tv) |
{ |
{ |
|
|
|
|
if (clock_gettime(clock_id, &ts) == -1) |
if (clock_gettime(clock_id, &ts) == -1) |
return (-1); |
return (-1); |
|
|
TIMESPEC_TO_TIMEVAL(tv, &ts); |
TIMESPEC_TO_TIMEVAL(tv, &ts); |
|
|
return (0); |
return (0); |
} |
} |
|
|
|
|
|
|
printf("%12s %14s %12s %8s ", "elapsed_ms", "bytes", "mbps", |
printf("%12s %14s %12s %8s ", "elapsed_ms", "bytes", "mbps", |
"bwidth"); |
"bwidth"); |
for (kv = ptb->kvars; ptb->kvars != NULL && *kv != NULL; kv++) |
for (kv = ptb->kvars; ptb->kvars != NULL && *kv != NULL; kv++) |
printf("%s%s", kv != ptb->kvars ? "," : "", *kv); |
printf("%s%s", kv != ptb->kvars ? "," : "", *kv); |
printf("\n"); |
printf("\n"); |
} |
} |
|
|
struct tcpcb *tcpcb, struct socket *sockb) |
struct tcpcb *tcpcb, struct socket *sockb) |
{ |
{ |
int j; |
int j; |
|
|
printf("%12llu %14llu %12.3Lf %7.2f%% ", total_elapsed, sc->bytes, |
printf("%12llu %14llu %12.3Lf %7.2f%% ", total_elapsed, sc->bytes, |
mbps, bwperc); |
mbps, bwperc); |
|
|
if (ptb->kvars != NULL) { |
if (ptb->kvars != NULL) { |
kupdate_stats(sc->tcp_tcbaddr, inpcb, tcpcb, |
kupdate_stats(sc->tcp_tcbaddr, inpcb, tcpcb, |
sockb); |
sockb); |
|
|
P(tcpcb, t_srtt, "%hu") |
P(tcpcb, t_srtt, "%hu") |
P(tcpcb, ts_recent, "%u") |
P(tcpcb, ts_recent, "%u") |
P(tcpcb, ts_recent_age, "%u") |
P(tcpcb, ts_recent_age, "%u") |
#undef S |
#undef S |
#undef P |
#undef P |
} |
} |
} |
} |
|
|
struct inpcb inpcb; |
struct inpcb inpcb; |
struct tcpcb tcpcb; |
struct tcpcb tcpcb; |
struct socket sockb; |
struct socket sockb; |
|
|
TAILQ_FOREACH(sc, &sc_queue, entry) { |
TAILQ_FOREACH(sc, &sc_queue, entry) { |
if (clock_gettime_tv(CLOCK_MONOTONIC, &t_cur) == -1) |
if (clock_gettime_tv(CLOCK_MONOTONIC, &t_cur) == -1) |
err(1, "clock_gettime_tv"); |
err(1, "clock_gettime_tv"); |
if (ptb->kvars != NULL) /* process kernel stats */ |
if (ptb->kvars != NULL) /* process kernel stats */ |
kupdate_stats(sc->tcp_tcbaddr, &inpcb, &tcpcb, |
kupdate_stats(sc->tcp_tcbaddr, &inpcb, &tcpcb, |
&sockb); |
&sockb); |
|
|
timersub(&t_cur, &sc->t_start, &t_diff); |
timersub(&t_cur, &sc->t_start, &t_diff); |
total_elapsed = t_diff.tv_sec * 1000 + t_diff.tv_usec / 1000; |
total_elapsed = t_diff.tv_sec * 1000 + t_diff.tv_usec / 1000; |
timersub(&t_cur, &sc->t_last, &t_diff); |
timersub(&t_cur, &sc->t_last, &t_diff); |
|
|
bwperc = (sc->bytes * 100.0) / mainstats.slice_bytes; |
bwperc = (sc->bytes * 100.0) / mainstats.slice_bytes; |
mbps = (sc->bytes * 8) / (since_last * 1000.0); |
mbps = (sc->bytes * 8) / (since_last * 1000.0); |
slice_mbps += mbps; |
slice_mbps += mbps; |
|
|
tcp_stats_display(total_elapsed, mbps, bwperc, sc, |
tcp_stats_display(total_elapsed, mbps, bwperc, sc, |
&inpcb, &tcpcb, &sockb); |
&inpcb, &tcpcb, &sockb); |
|
|
sc->t_last = t_cur; |
sc->t_last = t_cur; |
sc->bytes = 0; |
sc->bytes = 0; |
} |
} |
|
|
mainstats.peak_mbps = slice_mbps; |
mainstats.peak_mbps = slice_mbps; |
printf("Conn: %3d Mbps: %12.3Lf Peak Mbps: %12.3Lf Avg Mbps: %12.3Lf\n", |
printf("Conn: %3d Mbps: %12.3Lf Peak Mbps: %12.3Lf Avg Mbps: %12.3Lf\n", |
mainstats.nconns, slice_mbps, mainstats.peak_mbps, |
mainstats.nconns, slice_mbps, mainstats.peak_mbps, |
mainstats.nconns ? slice_mbps / mainstats.nconns : 0); |
mainstats.nconns ? slice_mbps / mainstats.nconns : 0); |
mainstats.slice_bytes = 0; |
mainstats.slice_bytes = 0; |
|
|
set_slice_timer(mainstats.nconns > 0); |
set_slice_timer(mainstats.nconns > 0); |
|
|
warn("fd %d read error", fd); |
warn("fd %d read error", fd); |
return; |
return; |
} |
} |
|
|
if (ptb->vflag >= 3) |
if (ptb->vflag >= 3) |
fprintf(stderr, "read: %zd bytes\n", n); |
fprintf(stderr, "read: %zd bytes\n", n); |
/* If this was our first packet, start slice timer */ |
/* If this was our first packet, start slice timer */ |
|
|
sc->bytes += n; |
sc->bytes += n; |
mainstats.slice_bytes += n; |
mainstats.slice_bytes += n; |
} |
} |
|
|
static void |
static void |
tcp_server_accept(int fd, short event, void *arg) |
tcp_server_accept(int fd, short event, void *arg) |
{ |
{ |
|
|
struct sockaddr_storage ss; |
struct sockaddr_storage ss; |
socklen_t sslen; |
socklen_t sslen; |
char tmp[128]; |
char tmp[128]; |
|
|
sslen = sizeof(ss); |
sslen = sizeof(ss); |
|
|
event_add(&ts->ev, NULL); |
event_add(&ts->ev, NULL); |
|
|
freeaddrinfo(aitop); |
freeaddrinfo(aitop); |
if (lnfds == 0) |
if (lnfds == 0) |
errx(1, "No working listen addresses found"); |
errx(1, "No working listen addresses found"); |
} |
} |
|
|
static void |
static void |
client_handle_sc(int fd, short event, void *v_sc) |
client_handle_sc(int fd, short event, void *v_sc) |
|
|
return; |
return; |
err(1, "write"); |
err(1, "write"); |
} |
} |
if (TCP_MODE && n == 0) { |
if (TCP_MODE && n == 0) { |
fprintf(stderr, "Remote end closed connection"); |
fprintf(stderr, "Remote end closed connection"); |
exit(1); |
exit(1); |
} |
} |
|
|
{ "netcontrol", IPTOS_PREC_NETCONTROL }, |
{ "netcontrol", IPTOS_PREC_NETCONTROL }, |
{ "reliability", IPTOS_RELIABILITY }, |
{ "reliability", IPTOS_RELIABILITY }, |
{ "throughput", IPTOS_THROUGHPUT }, |
{ "throughput", IPTOS_THROUGHPUT }, |
{ NULL, -1 }, |
{ NULL, -1 }, |
}; |
}; |
|
|
for (t = toskeywords; t->keyword != NULL; t++) { |
for (t = toskeywords; t->keyword != NULL; t++) { |
if (strcmp(s, t->keyword) == 0) { |
if (strcmp(s, t->keyword) == 0) { |
*val = t->val; |
*val = t->val; |
return (1); |
return (1); |
} |
} |
} |
} |
|
|
return (0); |
return (0); |
} |
} |
|
|
|
|
* ethernet packet. |
* ethernet packet. |
*/ |
*/ |
if (!ptb->dummybuf_len) { |
if (!ptb->dummybuf_len) { |
if (ptb->sflag || TCP_MODE) |
if (ptb->sflag || TCP_MODE) |
ptb->dummybuf_len = DEFAULT_BUF; |
ptb->dummybuf_len = DEFAULT_BUF; |
else |
else |
ptb->dummybuf_len = DEFAULT_UDP_PKT; |
ptb->dummybuf_len = DEFAULT_UDP_PKT; |
|
|
signal_add(&ev_sigterm, NULL); |
signal_add(&ev_sigterm, NULL); |
signal_add(&ev_sighup, NULL); |
signal_add(&ev_sighup, NULL); |
signal(SIGPIPE, SIG_IGN); |
signal(SIGPIPE, SIG_IGN); |
|
|
if (UDP_MODE) { |
if (UDP_MODE) { |
if ((udp_sc = calloc(1, sizeof(*udp_sc))) == NULL) |
if ((udp_sc = calloc(1, sizeof(*udp_sc))) == NULL) |
err(1, "calloc"); |
err(1, "calloc"); |