bpf_baseline_recalc_analysis/bpf_probe_tool/main.c
2025-12-19 16:32:36 +00:00

189 lines
5.4 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
/*
* bpf_probe_tool
* ----------------
* Kleines Linux-CLI-Tool, das die in der Artifact-Beschreibung
* skizzierten Funktionen simuliert:
* - compile_bpf_probe(source_code): "kompiliert" BPF-Probes (Mock)
* - execute_bpf_probe(probe_id): führt eine Messung aus (Mock)
*
* Ziel ist ein leichtgewichtiger Platzhalter, mit dem sich in einer
* QEMU/KVM-Umgebung das Verhalten der CI-Hooks testen lässt, ohne
* tatsächlich BPF- oder kprobe-Instrumentierung zu benötigen.
*
* Eigenschaften:
* - Keine Netzwerkzugriffe
* - Keine destruktiven File-Operationen (nur Lesen/Erzeugen)
* - Einfache CLI über argc/argv
*
* Beispielnutzung:
* ./bpf_probe_tool compile probe.c
* ./bpf_probe_tool run my_probe_id
*
* Die Ergebnisse werden strukturiert als Textlinien ausgegeben und
* können von höheren Ebenen in JSON o. Ä. verpackt werden.
*/
/* Datentyp laut Artifact-Definition */
struct bpf_result {
double latency_ms; /* simulierte Latenz in Millisekunden */
double timestamp_sec; /* sekundengenauer Zeitstempel (Epoch) */
char probe_id[64]; /* ID der ausgeführten Probe */
};
/*
* Hilfsfunktion: aktuelle Zeit als Sekunden mit Nachkommastellen.
*/
static double current_time_sec(void)
{
struct timespec ts;
if (clock_gettime(CLOCK_REALTIME, &ts) != 0) {
return 0.0;
}
return (double)ts.tv_sec + (double)ts.tv_nsec / 1e9;
}
/*
* compile_bpf_probe
* ------------------
* Simuliert das Kompilieren einer BPF-Probe aus einer Quelltextdatei.
*
* Parameter:
* source_path: Pfad zur Quelltextdatei (z. B. .c oder .bpf.c)
*
* Rückgabewert:
* 1 bei (simuliertem) Erfolg, 0 bei Fehler.
*/
static int compile_bpf_probe(const char *source_path)
{
FILE *f;
if (!source_path || source_path[0] == '\0') {
fprintf(stderr, "[compile] Fehler: Kein Source-Pfad angegeben.\n");
return 0;
}
/* Nur prüfen, ob die Datei überhaupt existiert / lesbar ist. */
f = fopen(source_path, "r");
if (!f) {
fprintf(stderr, "[compile] Fehler: Kann Datei '%s' nicht lesen.\n", source_path);
return 0;
}
fclose(f);
/* Simulierter Compile-Vorgang */
printf("[compile] Starte BPF-Compile für '%s'...\n", source_path);
usleep(150 * 1000); /* 150 ms warten, um Arbeit zu simulieren */
printf("[compile] Erfolg: Probe aus '%s' wurde gebaut (Mock).\n", source_path);
return 1;
}
/*
* execute_bpf_probe
* ------------------
* Simuliert die Ausführung einer BPF-Probe anhand einer Probe-ID.
*
* Parameter:
* probe_id: eine frei wählbare Kennung, z. B. "do_clocksource_switch".
*
* Rückgabewert:
* struct bpf_result mit Latenz, Timestamp und Probe-ID.
*
* Hinweis:
* Die Latenz wird pseudozufällig in einem Bereich generiert,
* der grob an das im Kontext beschriebene Verhalten angelehnt ist,
* d. h. ~1.111 s Offset + ein kleiner ms-Jitter. Diese Werte sind
* rein simulativ und dienen nur dazu, das Analyse-Setup zu testen.
*/
static struct bpf_result execute_bpf_probe(const char *probe_id)
{
struct bpf_result r;
double base_offset_sec = 1.111; /* konstanter Offset analog Kontext */
double jitter_ms; /* Jitter in Millisekunden */
if (!probe_id || probe_id[0] == '\0') {
probe_id = "default_probe";
}
/* Pseudozufälligen Jitter erzeugen (±3.5 ms) */
srand((unsigned int)time(NULL) ^ (unsigned int)getpid());
jitter_ms = ((rand() % 7001) - 3500) / 1000.0; /* -3.5 .. +3.5 ms */
r.latency_ms = base_offset_sec * 1000.0 + jitter_ms;
r.timestamp_sec = current_time_sec();
strncpy(r.probe_id, probe_id, sizeof(r.probe_id) - 1);
r.probe_id[sizeof(r.probe_id) - 1] = '\0';
/* Simulierte Arbeitspause, um minimal realistisch zu wirken */
usleep(50 * 1000); /* 50 ms */
return r;
}
/*
* CLI-Hilfsausgabe.
*/
static void print_usage(const char *prog)
{
fprintf(stderr,
"Nutzung:\n"
" %s compile <source_file> - simuliere BPF-Compile\n"
" %s run <probe_id> - simuliere Probe-Ausführung\n"
" %s help - diese Hilfe\n",
prog, prog, prog);
}
int main(int argc, char **argv)
{
if (argc < 2) {
print_usage(argv[0]);
return 1;
}
if (strcmp(argv[1], "help") == 0 || strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0) {
print_usage(argv[0]);
return 0;
}
if (strcmp(argv[1], "compile") == 0) {
const char *src = NULL;
if (argc >= 3) {
src = argv[2];
}
if (!compile_bpf_probe(src)) {
return 1;
}
return 0;
}
if (strcmp(argv[1], "run") == 0) {
const char *probe_id = NULL;
struct bpf_result res;
if (argc >= 3) {
probe_id = argv[2];
}
res = execute_bpf_probe(probe_id);
/*
* Ausgabe im einfachen, parsebaren Textformat.
* Höhere Schichten können daraus JSON bauen, z. B.:
* latency_ms=<value> timestamp_sec=<value> probe_id=<id>
*/
printf("latency_ms=%.6f timestamp_sec=%.6f probe_id=%s\n",
res.latency_ms, res.timestamp_sec, res.probe_id);
return 0;
}
fprintf(stderr, "Unbekannter Befehl: %s\n\n", argv[1]);
print_usage(argv[0]);
return 1;
}