Skip to content

Commit

Permalink
stats: Break out from tc.c
Browse files Browse the repository at this point in the history
Maybe this can be reused for other things.

Signed-off-by: Casper Andersson <[email protected]>
  • Loading branch information
cappe987 committed Dec 31, 2024
1 parent ed74530 commit 70aaf42
Show file tree
Hide file tree
Showing 4 changed files with 213 additions and 118 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ project(tstest VERSION 1.0)

# ---- BUILD ----
add_executable(tstest)
target_sources(tstest PRIVATE src/liblink.c src/timestamping.c src/ptp_message.c src/extts.c src/pkt.c src/tstest.c src/delay.c src/check.c src/tc.c)
target_sources(tstest PRIVATE src/liblink.c src/timestamping.c src/ptp_message.c src/extts.c src/pkt.c src/tstest.c src/delay.c src/check.c src/tc.c src/stats.c)

target_include_directories(tstest PUBLIC ${PROJECT_INCLUDES})
target_link_libraries(tstest PUBLIC)
Expand Down
37 changes: 37 additions & 0 deletions include/stats.h
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__ */
174 changes: 174 additions & 0 deletions src/stats.c
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");
}
118 changes: 1 addition & 117 deletions src/tc.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
#include <pthread.h>
#include <inttypes.h>

#include "net_tstamp_cpy.h"
Expand All @@ -20,6 +19,7 @@
#include "liblink.h"
#include "tstest.h"
#include "pkt.h"
#include "stats.h"

/* Measure the one-way inaccuracy through a TC. Runs on two ports that
* are either synchronized or use the same PHC. The inaccuracies will
Expand Down Expand Up @@ -138,122 +138,6 @@ static void send_pkt(struct pkt_cfg *cfg, int sock, int64_t *tx_ts)
}
}

/* 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;

static 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;
}

static void free_stats(Stats *s)
{
free(s->tsinfo);
}

static 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;
}

static void show_stats(Stats *s, char *p1, char *p2, int count_left)
{
int64_t max_err, min_err, sum_err = 0;
int64_t max_lat, min_lat, sum_lat = 0;
int64_t timeerror, latency;

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);

timeerror = tsinfo_get_error(s->tsinfo[0]);
latency = tsinfo_get_latency(s->tsinfo[0]);
max_err = timeerror;
min_err = timeerror;
max_lat = latency;
min_lat = latency;

for (int i = 0; i < s->count; i++) {
timeerror = tsinfo_get_error(s->tsinfo[i]);
latency = tsinfo_get_latency(s->tsinfo[i]);
if (timeerror > max_err)
max_err = timeerror;
if (timeerror < min_err)
min_err = timeerror;
sum_err += timeerror;

if (latency > max_lat)
max_lat = latency;
if (latency < min_lat)
min_lat = latency;
sum_lat += latency;
}

printf("--- TIME ERROR ---\n");
printf("Mean: %" PRId64 "\n", sum_err / s->count);
printf("Max : %" PRId64 "\n", max_err);
printf("Min : %" PRId64 "\n", min_err);
printf("--- LATENCY ---\n");
printf("Mean: %" PRId64 "\n", sum_lat / s->count);
printf("Max : %" PRId64 "\n", max_lat);
printf("Min : %" PRId64 "\n", min_lat);
printf("===============\n");
}

static void run(struct pkt_cfg *cfg, char *p1, char *p2, int p1_sock, int p2_sock)
{
int64_t rx_ts, tx_ts, correction, total_err;
Expand Down

0 comments on commit 70aaf42

Please sign in to comment.