1#include "internal.h"
2
3#include <cmdline.h>
4#include <math/range.h>
5#include <string.h>
6#include <time/time.h>
7
8/* This is a necessary evil, as the command line will
9 * pass in nanoseconds, and we map to milliseconds in the config
10 *
11 * It also helps us expand the command line options without
12 * bloating up a config file, if said options are operated
13 * upon to arrive at the final value in the config */
14static const char *nightmare_selector;
15static fx32_32_t nightmare_intensity = NIGHTMARE_INTENSITY_SENTINEL;
16static uint64_t nightmare_seed;
17static enum nightmare_seed_mode nightmare_seed_mode = NIGHTMARE_SEED_SPLIT;
18static time_ns_t nightmare_duration_ns;
19static time_ns_t nightmare_drain_grace_ns = SECONDS_TO_NS(20);
20static time_ns_t nightmare_stat_interval_ns = SECONDS_TO_NS(5);
21static time_ns_t nightmare_stall_threshold_ns = MS_TO_NS(3000);
22static enum nightmare_on_stall nightmare_on_stall = NIGHTMARE_ON_STALL_REPORT;
23static uint64_t nightmare_boot_index;
24static const char *nightmare_campaign_id;
25
26CMDLINE_DECLARE_VAR(
27 nightmare_root, nightmare_selector, .name = "nightmare",
28 .types = CMDLINE_TYPES(CMDLINE_TYPE_STRING),
29 .desc = "Select the single nightmare subject for this boot");
30
31CMDLINE_CHILDREN_DECLARE(
32 nightmare_root,
33 CMDLINE_INNER_FX(intensity, nightmare_intensity,
34 .desc = "Nightmare intensity in [0,1]",
35 .range = RANGE(0, FX_ONE)),
36 CMDLINE_INNER_VAR(seed, nightmare_seed, .desc = "Nightmare seed"),
37 CMDLINE_INNER_VAR(seed_mode, nightmare_seed_mode,
38 .desc = "Seed application mode",
39 .mappings = CMDLINE_MAPPINGS(
40 CMDLINE_MAP("split", NIGHTMARE_SEED_SPLIT),
41 CMDLINE_MAP("seedful", NIGHTMARE_SEED_SEEDFUL),
42 CMDLINE_MAP("seedless", NIGHTMARE_SEED_SEEDLESS))),
43 CMDLINE_INNER_DURATION(duration_ms, nightmare_duration_ns,
44 .desc = "Soft runtime budget"),
45 CMDLINE_INNER_DURATION(drain_grace_ms, nightmare_drain_grace_ns,
46 .desc = "Soft-to-hard deadline grace"),
47 CMDLINE_INNER_DURATION(stat_interval_ms, nightmare_stat_interval_ns,
48 .desc = "Heartbeat record cadence"),
49 CMDLINE_INNER_DURATION(stall_threshold_ms, nightmare_stall_threshold_ns,
50 .desc = "Liveness stall threshold duration",
51 .range = RANGE(MS_TO_NS(100), TIME_NS_MAX)),
52 CMDLINE_INNER_VAR(on_stall, nightmare_on_stall, .desc = "Stall response",
53 .mappings = CMDLINE_MAPPINGS(
54 CMDLINE_MAP("report", NIGHTMARE_ON_STALL_REPORT),
55 CMDLINE_MAP("crash", NIGHTMARE_ON_STALL_CRASH),
56 CMDLINE_MAP("snapshot", NIGHTMARE_ON_STALL_CRASH),
57 CMDLINE_MAP("terminal", NIGHTMARE_ON_STALL_CRASH))),
58 CMDLINE_INNER_VAR(boot_index, nightmare_boot_index,
59 .desc = "Opaque campaign boot index"),
60 CMDLINE_INNER_STRING(campaign_id, nightmare_campaign_id,
61 .desc = "Opaque campaign identifier"),
62 CMDLINE_INNER(perturb,
63 .types = CMDLINE_TYPES(CMDLINE_TYPE_STRING,
64 CMDLINE_TYPE_LIST),
65 .desc = "Comma-separated perturbation services"));
66
67void nightmare_cmdline_get(struct nightmare_cmdline_config *config) {
68 *config = (struct nightmare_cmdline_config){
69 .selector = nightmare_selector,
70 .intensity = nightmare_intensity,
71 .seed = nightmare_seed,
72 .seed_present =
73 CMDLINE_CHILD(nightmare_root, seed)->status == CMDLINE_ENTRY_FOUND,
74 .seed_mode = nightmare_seed_mode,
75 .duration_ms = NS_TO_MS(nightmare_duration_ns),
76 .drain_grace_ms = NS_TO_MS(nightmare_drain_grace_ns),
77 .stat_interval_ms = NS_TO_MS(nightmare_stat_interval_ns),
78 .stall_threshold_ms = NS_TO_MS(nightmare_stall_threshold_ns),
79 .on_stall = nightmare_on_stall,
80 .boot_index = nightmare_boot_index,
81 .campaign_id = nightmare_campaign_id,
82 };
83
84 struct cmdline_entry *perturb = CMDLINE_CHILD(nightmare_root, perturb);
85 if (perturb->status != CMDLINE_ENTRY_FOUND)
86 return;
87
88 if (perturb->value.type == CMDLINE_TYPE_LIST) {
89 config->perturb_present =
90 CMDLINE_EXTRACT(&perturb->value, config->perturb) == ERR_OK;
91 return;
92 }
93
94 if (perturb->value.type == CMDLINE_TYPE_STRING) {
95 config->perturb = (struct cmdline_list){
96 .count = 1,
97 .items = &perturb->value,
98 };
99 config->perturb_present = true;
100 }
101}
102