commit 06db195c9403b59a5eca7354bd20feab5c415c48 Author: Mika Date: Fri Dec 19 16:32:36 2025 +0000 Add bpf_probe_tool/main.c diff --git a/bpf_probe_tool/main.c b/bpf_probe_tool/main.c new file mode 100644 index 0000000..4311956 --- /dev/null +++ b/bpf_probe_tool/main.c @@ -0,0 +1,189 @@ +#include +#include +#include +#include +#include + +/* + * 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 - simuliere BPF-Compile\n" + " %s run - 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= timestamp_sec= probe_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; +}