-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Maybe this can be reused for other things. Signed-off-by: Casper Andersson <[email protected]>
- Loading branch information
Showing
4 changed files
with
213 additions
and
118 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
// SPDX-License-Identifier: GPL-2.0-only | ||
// SPDX-FileCopyrightText: 2024 Casper Andersson <[email protected]> | ||
|
||
#ifndef __STATS_H__ | ||
#define __STATS_H__ | ||
|
||
#include <inttypes.h> | ||
|
||
typedef struct { | ||
int64_t mean; | ||
int64_t max; | ||
int64_t min; | ||
} Result; | ||
|
||
/* Ingress/egress latency of host should be accounted for in these timestamps */ | ||
struct tsinfo { | ||
uint16_t seqid; | ||
int64_t tx_ts; | ||
int64_t rx_ts; | ||
int64_t correction; | ||
}; | ||
|
||
typedef struct { | ||
int count; | ||
int size; | ||
struct tsinfo *tsinfo; | ||
} Stats; | ||
|
||
int init_stats(Stats *s, int size); | ||
void free_stats(Stats *s); | ||
int add_stats(Stats *s, int64_t tx_ts, int64_t rx_ts, int64_t correction, uint16_t seqid); | ||
Result stats_get_time_error(Stats *s); | ||
Result stats_get_latency(Stats *s); | ||
Result stats_get_pdv(Stats *s); | ||
void show_stats(Stats *s, char *p1, char *p2, int count_left); | ||
|
||
#endif /* __STATS_H__ */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,174 @@ | ||
// SPDX-License-Identifier: GPL-2.0-only | ||
// SPDX-FileCopyrightText: 2024 Casper Andersson <[email protected]> | ||
|
||
#include <inttypes.h> | ||
#include <errno.h> | ||
#include <stdlib.h> | ||
#include <stdio.h> | ||
#include <linux/if_ether.h> | ||
|
||
#include "liblink.h" | ||
#include "stats.h" | ||
|
||
/* TODO: | ||
* - If performance becomes slow, aggregate all calculations into one | ||
loop and return a struct with all results. | ||
*/ | ||
|
||
int init_stats(Stats *s, int size) | ||
{ | ||
if (size == 0) | ||
s->size = 100; | ||
else | ||
s->size = size; | ||
s->count = 0; | ||
s->tsinfo = malloc(sizeof(struct tsinfo) * s->size); | ||
if (!s->tsinfo) { | ||
ERR("failed to allocate stats array"); | ||
return ENOMEM; | ||
} | ||
return 0; | ||
} | ||
|
||
void free_stats(Stats *s) | ||
{ | ||
free(s->tsinfo); | ||
s->tsinfo = NULL; | ||
} | ||
|
||
int add_stats(Stats *s, int64_t tx_ts, int64_t rx_ts, int64_t correction, uint16_t seqid) | ||
{ | ||
if (s->count == s->size) { | ||
s->size = s->size * 2; | ||
s->tsinfo = realloc(s->tsinfo, sizeof(struct tsinfo) * s->size); | ||
if (!s->tsinfo) { | ||
ERR("failed to reallocate stats array"); | ||
return ENOMEM; | ||
} | ||
} | ||
|
||
s->tsinfo[s->count].seqid = seqid; | ||
s->tsinfo[s->count].tx_ts = tx_ts; | ||
s->tsinfo[s->count].rx_ts = rx_ts; | ||
s->tsinfo[s->count].correction = correction; | ||
s->count++; | ||
return 0; | ||
} | ||
|
||
static int64_t tsinfo_get_error(struct tsinfo tsinfo) | ||
{ | ||
return tsinfo.rx_ts - tsinfo.tx_ts - tsinfo.correction; | ||
} | ||
|
||
static int64_t tsinfo_get_latency(struct tsinfo tsinfo) | ||
{ | ||
return tsinfo.rx_ts - tsinfo.tx_ts; | ||
} | ||
|
||
Result stats_get_time_error(Stats *s) | ||
{ | ||
int64_t sum_err = 0; | ||
int64_t timeerror; | ||
Result r; | ||
|
||
timeerror = tsinfo_get_error(s->tsinfo[0]); | ||
r.max = timeerror; | ||
r.min = timeerror; | ||
for (int i = 0; i < s->count; i++) { | ||
timeerror = tsinfo_get_error(s->tsinfo[i]); | ||
if (timeerror > r.max) | ||
r.max = timeerror; | ||
if (timeerror < r.min) | ||
r.min = timeerror; | ||
sum_err += timeerror; | ||
} | ||
r.mean = sum_err / s->count; | ||
return r; | ||
} | ||
|
||
Result stats_get_latency(Stats *s) | ||
{ | ||
int64_t sum_lat = 0; | ||
int64_t latency; | ||
Result r; | ||
|
||
latency = tsinfo_get_latency(s->tsinfo[0]); | ||
r.max = latency; | ||
r.min = latency; | ||
for (int i = 0; i < s->count; i++) { | ||
latency = tsinfo_get_latency(s->tsinfo[i]); | ||
if (latency > r.max) | ||
r.max = latency; | ||
if (latency < r.min) | ||
r.min = latency; | ||
sum_lat += latency; | ||
} | ||
|
||
r.mean = sum_lat / s->count; | ||
return r; | ||
} | ||
|
||
static int64_t pdv_get_lucky_packet(Stats *s) | ||
{ | ||
int64_t lucky_packet, tmp; | ||
|
||
lucky_packet = s->tsinfo[0].rx_ts - s->tsinfo[0].tx_ts; | ||
for (int i = 1; i < s->count; i++) { | ||
tmp = s->tsinfo[i].rx_ts - s->tsinfo[i].tx_ts; | ||
if (tmp < lucky_packet) | ||
lucky_packet = tmp; | ||
} | ||
return lucky_packet; | ||
} | ||
|
||
Result stats_get_pdv(Stats *s) | ||
{ | ||
int64_t lucky_packet, tmp, sum = 0; | ||
Result r = { 0 }; | ||
|
||
lucky_packet = pdv_get_lucky_packet(s); | ||
r.max = 0; | ||
r.min = 0; | ||
for (int i = 0; i < s->count; i++) { | ||
tmp = (s->tsinfo[i].rx_ts - s->tsinfo[i].tx_ts) - lucky_packet; | ||
sum += tmp; | ||
if (tmp > r.max) | ||
r.max = tmp; | ||
} | ||
r.mean = sum / s->count; | ||
return r; | ||
} | ||
|
||
void show_stats(Stats *s, char *p1, char *p2, int count_left) | ||
{ | ||
if (s->count == 0) { | ||
printf("No measurements\n"); | ||
return; | ||
} | ||
|
||
printf("===============\n"); | ||
if (count_left) | ||
printf("%d measurements (exited early, expected %d)\n", s->count, | ||
s->count + count_left); | ||
else | ||
printf("%d measurements\n", s->count); | ||
printf("%s -> %s\n", p1, p2); | ||
|
||
Result time_error = stats_get_time_error(s); | ||
Result latency = stats_get_latency(s); | ||
Result pdv = stats_get_pdv(s); | ||
|
||
printf("--- TIME ERROR ---\n"); | ||
printf("Mean: %" PRId64 "\n", time_error.mean); | ||
printf("Max : %" PRId64 "\n", time_error.max); | ||
printf("Min : %" PRId64 "\n", time_error.min); | ||
printf("--- LATENCY ---\n"); | ||
printf("Mean: %" PRId64 "\n", latency.mean); | ||
printf("Max : %" PRId64 "\n", latency.max); | ||
printf("Min : %" PRId64 "\n", latency.min); | ||
printf("--- PDV ---\n"); | ||
printf("Mean: %" PRId64 "\n", pdv.mean); | ||
printf("Max : %" PRId64 "\n", pdv.max); | ||
printf("Min : %" PRId64 " (lucky packet)\n", pdv.min); | ||
printf("===============\n"); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters