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