Skip to main content

air_sys_types/
ebpf.rs

1// This Source Code Form is subject to the terms of the Mozilla Public
2// License, v. 2.0. If a copy of the MPL was not distributed with this
3// file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
5//! Types purs de la famille `ebpf` (couche 0).
6//!
7//! Cf. `docs/specs/layer-0/family-ebpf.md`. Ce module ne fait **aucun**
8//! syscall : il décrit le miroir d'instruction `BpfInstruction`, les
9//! énumérations typées (`BpfMapType`, `BpfProgramType`, `BpfAttachType`…), les
10//! bitflags, le miroir `PerfEventAttr`, les portées `PerfEventScope`, et les
11//! structs-requête passées aux wrappers de `air-sys-syscall::ebpf`.
12//!
13//! Frontière couche 0/1 : on **charge** des programmes/BTF déjà assemblés ; on
14//! n'assemble, ne compile, ni ne relocalise rien (logique → couche 1).
15
16use core::ffi::CStr;
17
18use bitflags::bitflags;
19
20use crate::fd::BorrowedFd;
21use crate::process::Pid;
22
23// ─────────────────────────────────────────────────────────────────────────
24// Instruction.
25// ─────────────────────────────────────────────────────────────────────────
26
27/// Miroir `#[repr(C)]` de `struct bpf_insn` (8 octets).
28///
29/// Type « miroir » : nom de type explicite (ADR-029), champs aux noms kernel.
30#[repr(C)]
31#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
32pub struct BpfInstruction {
33    /// Opcode.
34    pub code: u8,
35    /// 4 bits `dst_reg` (poids faible) + 4 bits `src_reg` (poids fort).
36    pub registers: u8,
37    /// Décalage signé (saut, accès mémoire).
38    pub offset: i16,
39    /// Immédiat 32 bits.
40    pub immediate: i32,
41}
42
43impl BpfInstruction {
44    /// Construit une instruction depuis ses champs.
45    #[must_use]
46    pub const fn new(code: u8, dst_reg: u8, src_reg: u8, offset: i16, immediate: i32) -> Self {
47        let registers = (dst_reg & 0x0f) | ((src_reg & 0x0f) << 4);
48        Self {
49            code,
50            registers,
51            offset,
52            immediate,
53        }
54    }
55
56    /// Registre destination (4 bits de poids faible de `registers`).
57    #[must_use]
58    pub const fn dst_reg(self) -> u8 {
59        self.registers & 0x0f
60    }
61
62    /// Registre source (4 bits de poids fort de `registers`).
63    #[must_use]
64    pub const fn src_reg(self) -> u8 {
65        self.registers >> 4
66    }
67}
68
69// ─────────────────────────────────────────────────────────────────────────
70// Énumérations typées.
71// ─────────────────────────────────────────────────────────────────────────
72
73/// `enum bpf_map_type`. Variante `Other(u32)` pour les types non nommés.
74#[derive(Debug, Clone, Copy, PartialEq, Eq)]
75#[allow(missing_docs)]
76pub enum BpfMapType {
77    Hash,
78    Array,
79    ProgramArray,
80    PerfEventArray,
81    PercpuHash,
82    PercpuArray,
83    StackTrace,
84    CgroupArray,
85    LruHash,
86    LruPercpuHash,
87    LpmTrie,
88    ArrayOfMaps,
89    HashOfMaps,
90    DevMap,
91    SockMap,
92    Cpumap,
93    XskMap,
94    SockHash,
95    CgroupStorage,
96    ReuseportSockArray,
97    PercpuCgroupStorage,
98    Queue,
99    Stack,
100    SkStorage,
101    DevmapHash,
102    StructOps,
103    RingBuf,
104    InodeStorage,
105    TaskStorage,
106    BloomFilter,
107    UserRingBuf,
108    CgrpStorage,
109    Arena,
110    /// Type ajouté par un kernel postérieur à 6.12.
111    Other(u32),
112}
113
114impl BpfMapType {
115    /// Valeur kernel `BPF_MAP_TYPE_*`.
116    #[must_use]
117    pub const fn to_raw(self) -> u32 {
118        match self {
119            Self::Hash => 1,
120            Self::Array => 2,
121            Self::ProgramArray => 3,
122            Self::PerfEventArray => 4,
123            Self::PercpuHash => 5,
124            Self::PercpuArray => 6,
125            Self::StackTrace => 7,
126            Self::CgroupArray => 8,
127            Self::LruHash => 9,
128            Self::LruPercpuHash => 10,
129            Self::LpmTrie => 11,
130            Self::ArrayOfMaps => 12,
131            Self::HashOfMaps => 13,
132            Self::DevMap => 14,
133            Self::SockMap => 15,
134            Self::Cpumap => 16,
135            Self::XskMap => 17,
136            Self::SockHash => 18,
137            Self::CgroupStorage => 19,
138            Self::ReuseportSockArray => 20,
139            Self::PercpuCgroupStorage => 21,
140            Self::Queue => 22,
141            Self::Stack => 23,
142            Self::SkStorage => 24,
143            Self::DevmapHash => 25,
144            Self::StructOps => 26,
145            Self::RingBuf => 27,
146            Self::InodeStorage => 28,
147            Self::TaskStorage => 29,
148            Self::BloomFilter => 30,
149            Self::UserRingBuf => 31,
150            Self::CgrpStorage => 32,
151            Self::Arena => 33,
152            Self::Other(value) => value,
153        }
154    }
155}
156
157/// `enum bpf_prog_type`. Variante `Other(u32)` de repli.
158#[derive(Debug, Clone, Copy, PartialEq, Eq)]
159#[allow(missing_docs)]
160pub enum BpfProgramType {
161    SocketFilter,
162    Kprobe,
163    SchedCls,
164    SchedAct,
165    Tracepoint,
166    Xdp,
167    PerfEvent,
168    CgroupSkb,
169    CgroupSock,
170    LwtIn,
171    LwtOut,
172    LwtXmit,
173    SockOps,
174    SkSkb,
175    CgroupDevice,
176    SkMsg,
177    RawTracepoint,
178    CgroupSockAddr,
179    LwtSeg6local,
180    LircMode2,
181    SkReuseport,
182    FlowDissector,
183    CgroupSysctl,
184    RawTracepointWritable,
185    CgroupSockopt,
186    Tracing,
187    StructOps,
188    Ext,
189    Lsm,
190    SkLookup,
191    Syscall,
192    Netfilter,
193    /// Type ajouté par un kernel postérieur à 6.12.
194    Other(u32),
195}
196
197impl BpfProgramType {
198    /// Valeur kernel `BPF_PROG_TYPE_*`.
199    #[must_use]
200    pub const fn to_raw(self) -> u32 {
201        match self {
202            Self::SocketFilter => 1,
203            Self::Kprobe => 2,
204            Self::SchedCls => 3,
205            Self::SchedAct => 4,
206            Self::Tracepoint => 5,
207            Self::Xdp => 6,
208            Self::PerfEvent => 7,
209            Self::CgroupSkb => 8,
210            Self::CgroupSock => 9,
211            Self::LwtIn => 10,
212            Self::LwtOut => 11,
213            Self::LwtXmit => 12,
214            Self::SockOps => 13,
215            Self::SkSkb => 14,
216            Self::CgroupDevice => 15,
217            Self::SkMsg => 16,
218            Self::RawTracepoint => 17,
219            Self::CgroupSockAddr => 18,
220            Self::LwtSeg6local => 19,
221            Self::LircMode2 => 20,
222            Self::SkReuseport => 21,
223            Self::FlowDissector => 22,
224            Self::CgroupSysctl => 23,
225            Self::RawTracepointWritable => 24,
226            Self::CgroupSockopt => 25,
227            Self::Tracing => 26,
228            Self::StructOps => 27,
229            Self::Ext => 28,
230            Self::Lsm => 29,
231            Self::SkLookup => 30,
232            Self::Syscall => 31,
233            Self::Netfilter => 32,
234            Self::Other(value) => value,
235        }
236    }
237}
238
239/// `enum bpf_attach_type` (sous-ensemble typé + repli).
240#[derive(Debug, Clone, Copy, PartialEq, Eq)]
241#[allow(missing_docs)]
242pub enum BpfAttachType {
243    CgroupInetIngress,
244    CgroupInetEgress,
245    CgroupInetSockCreate,
246    CgroupSockOps,
247    SkSkbStreamParser,
248    SkSkbStreamVerdict,
249    CgroupDevice,
250    SkMsgVerdict,
251    CgroupInet4Bind,
252    CgroupInet6Bind,
253    CgroupInet4Connect,
254    CgroupInet6Connect,
255    TraceFentry,
256    TraceFexit,
257    ModifyReturn,
258    LsmMac,
259    TraceIter,
260    XdpDevmap,
261    XdpCpumap,
262    SkLookup,
263    Xdp,
264    /// Type d'attache ajouté par un kernel postérieur à 6.12.
265    Other(u32),
266}
267
268impl BpfAttachType {
269    /// Valeur kernel `BPF_*` (`bpf_attach_type`).
270    #[must_use]
271    pub const fn to_raw(self) -> u32 {
272        match self {
273            Self::CgroupInetIngress => 0,
274            Self::CgroupInetEgress => 1,
275            Self::CgroupInetSockCreate => 2,
276            Self::CgroupSockOps => 3,
277            Self::SkSkbStreamParser => 4,
278            Self::SkSkbStreamVerdict => 5,
279            Self::CgroupDevice => 6,
280            Self::SkMsgVerdict => 7,
281            Self::CgroupInet4Bind => 8,
282            Self::CgroupInet6Bind => 9,
283            Self::CgroupInet4Connect => 10,
284            Self::CgroupInet6Connect => 11,
285            Self::TraceFentry => 24,
286            Self::TraceFexit => 25,
287            Self::ModifyReturn => 26,
288            Self::LsmMac => 27,
289            Self::TraceIter => 28,
290            Self::XdpDevmap => 33,
291            Self::XdpCpumap => 35,
292            Self::SkLookup => 36,
293            Self::Xdp => 37,
294            Self::Other(value) => value,
295        }
296    }
297}
298
299/// Type de statistiques `BPF_ENABLE_STATS`.
300#[derive(Debug, Clone, Copy, PartialEq, Eq)]
301pub enum BpfStatsType {
302    /// `BPF_STATS_RUN_TIME` — temps CPU passé dans les programmes.
303    RunTime,
304}
305
306impl BpfStatsType {
307    /// Valeur kernel `BPF_STATS_*`.
308    #[must_use]
309    pub const fn to_raw(self) -> u32 {
310        match self {
311            Self::RunTime => 0,
312        }
313    }
314}
315
316/// Niveau de verbosité du log du vérifieur (`log_level`).
317#[derive(Debug, Clone, Copy, PartialEq, Eq)]
318pub enum BpfVerifierLogLevel {
319    /// Aucun log.
320    Disabled,
321    /// Log de base (`BPF_LOG_LEVEL1`).
322    Basic,
323    /// Log détaillé (`BPF_LOG_LEVEL2`).
324    Verbose,
325    /// Statistiques (`BPF_LOG_STATS`).
326    Stats,
327}
328
329impl BpfVerifierLogLevel {
330    /// Bits `log_level` kernel.
331    #[must_use]
332    pub const fn to_raw(self) -> u32 {
333        match self {
334            Self::Disabled => 0,
335            Self::Basic => 1,
336            Self::Verbose => 2,
337            Self::Stats => 4,
338        }
339    }
340}
341
342// ─────────────────────────────────────────────────────────────────────────
343// Bitflags.
344// ─────────────────────────────────────────────────────────────────────────
345
346bitflags! {
347    /// Drapeaux de création de carte (`BPF_F_*`).
348    #[derive(Debug, Clone, Copy, PartialEq, Eq)]
349    pub struct BpfMapCreateFlags: u32 {
350        /// `BPF_F_NO_PREALLOC`.
351        const NO_PREALLOC = 1 << 0;
352        /// `BPF_F_NO_COMMON_LRU`.
353        const NO_COMMON_LRU = 1 << 1;
354        /// `BPF_F_NUMA_NODE`.
355        const NUMA_NODE = 1 << 2;
356        /// `BPF_F_RDONLY`.
357        const READ_ONLY = 1 << 3;
358        /// `BPF_F_WRONLY`.
359        const WRITE_ONLY = 1 << 4;
360        /// `BPF_F_STACK_BUILD_ID`.
361        const STACK_BUILD_ID = 1 << 5;
362        /// `BPF_F_ZERO_SEED`.
363        const ZERO_SEED = 1 << 6;
364        /// `BPF_F_RDONLY_PROG`.
365        const READ_ONLY_PROG = 1 << 7;
366        /// `BPF_F_WRONLY_PROG`.
367        const WRITE_ONLY_PROG = 1 << 8;
368        /// `BPF_F_CLONE`.
369        const CLONE = 1 << 9;
370        /// `BPF_F_MMAPABLE`.
371        const MMAPABLE = 1 << 10;
372        /// `BPF_F_PRESERVE_ELEMS`.
373        const PRESERVE_ELEMS = 1 << 11;
374        /// `BPF_F_INNER_MAP`.
375        const INNER_LOCK = 1 << 12;
376    }
377}
378
379bitflags! {
380    /// Drapeaux de mise à jour d'élément (`BPF_*`).
381    #[derive(Debug, Clone, Copy, PartialEq, Eq)]
382    pub struct BpfMapUpdateFlags: u64 {
383        /// `BPF_ANY` — créer ou remplacer.
384        const ANY = 0;
385        /// `BPF_NOEXIST` — créer seulement si absent.
386        const NO_EXIST = 1;
387        /// `BPF_EXIST` — remplacer seulement si présent.
388        const EXIST = 2;
389        /// `BPF_F_LOCK` — verrou spin de l'entrée.
390        const F_LOCK = 4;
391    }
392}
393
394bitflags! {
395    /// Drapeaux de lookup d'élément (`BPF_F_*`).
396    #[derive(Debug, Clone, Copy, PartialEq, Eq)]
397    pub struct BpfMapLookupFlags: u64 {
398        /// `BPF_F_LOCK`.
399        const F_LOCK = 4;
400    }
401}
402
403bitflags! {
404    /// Drapeaux de chargement de programme (`BPF_F_*`).
405    #[derive(Debug, Clone, Copy, PartialEq, Eq)]
406    pub struct BpfProgramLoadFlags: u32 {
407        /// `BPF_F_STRICT_ALIGNMENT`.
408        const STRICT_ALIGNMENT = 1 << 0;
409        /// `BPF_F_ANY_ALIGNMENT`.
410        const ANY_ALIGNMENT = 1 << 1;
411        /// `BPF_F_TEST_RND_HI32`.
412        const TEST_RND_HI32 = 1 << 2;
413        /// `BPF_F_TEST_STATE_FREQ`.
414        const TEST_STATE_FREQ = 1 << 3;
415        /// `BPF_F_SLEEPABLE`.
416        const SLEEPABLE = 1 << 4;
417        /// `BPF_F_XDP_HAS_FRAGS`.
418        const XDP_HAS_FRAGS = 1 << 5;
419    }
420}
421
422bitflags! {
423    /// Drapeaux d'attache historique (`BPF_F_*`).
424    #[derive(Debug, Clone, Copy, PartialEq, Eq)]
425    pub struct BpfAttachFlags: u32 {
426        /// `BPF_F_ALLOW_OVERRIDE`.
427        const ALLOW_OVERRIDE = 1 << 0;
428        /// `BPF_F_ALLOW_MULTI`.
429        const ALLOW_MULTI = 1 << 1;
430        /// `BPF_F_REPLACE`.
431        const REPLACE = 1 << 2;
432    }
433}
434
435bitflags! {
436    /// Drapeaux de récupération d'objet épinglé (`BPF_F_*`).
437    #[derive(Debug, Clone, Copy, PartialEq, Eq)]
438    pub struct BpfObjectGetFlags: u32 {
439        /// `BPF_F_RDONLY`.
440        const RDONLY = 1 << 3;
441        /// `BPF_F_WRONLY`.
442        const WRONLY = 1 << 4;
443    }
444}
445
446bitflags! {
447    /// Drapeaux de chargement BTF (`BPF_F_*`).
448    #[derive(Debug, Clone, Copy, PartialEq, Eq)]
449    pub struct BpfBtfLoadFlags: u32 {
450        /// `BPF_F_TOKEN_FD`.
451        const TOKEN_FD = 1 << 0;
452    }
453}
454
455bitflags! {
456    /// Drapeaux de `perf_event_open` (`PERF_FLAG_*`).
457    #[derive(Debug, Clone, Copy, PartialEq, Eq)]
458    pub struct PerfEventOpenFlags: u64 {
459        /// `PERF_FLAG_FD_NO_GROUP`.
460        const FD_NO_GROUP = 1 << 0;
461        /// `PERF_FLAG_FD_OUTPUT`.
462        const FD_OUTPUT = 1 << 1;
463        /// `PERF_FLAG_FD_CLOEXEC` (toujours posé par le wrapper).
464        const FD_CLOEXEC = 1 << 3;
465    }
466}
467
468// ─────────────────────────────────────────────────────────────────────────
469// perf_event — type/config et miroir d'attributs.
470// ─────────────────────────────────────────────────────────────────────────
471
472/// Valeurs courantes du champ `perf_event_attr.type` (`PERF_TYPE_*`).
473#[derive(Debug, Clone, Copy, PartialEq, Eq)]
474pub enum PerfTypeId {
475    /// `PERF_TYPE_HARDWARE`.
476    Hardware,
477    /// `PERF_TYPE_SOFTWARE`.
478    Software,
479    /// `PERF_TYPE_TRACEPOINT`.
480    Tracepoint,
481    /// `PERF_TYPE_HW_CACHE`.
482    HwCache,
483    /// `PERF_TYPE_RAW`.
484    Raw,
485    /// `PERF_TYPE_BREAKPOINT`.
486    Breakpoint,
487}
488
489impl PerfTypeId {
490    /// Valeur kernel `PERF_TYPE_*`.
491    #[must_use]
492    pub const fn to_raw(self) -> u32 {
493        match self {
494            Self::Hardware => 0,
495            Self::Software => 1,
496            Self::Tracepoint => 2,
497            Self::HwCache => 3,
498            Self::Raw => 4,
499            Self::Breakpoint => 5,
500        }
501    }
502}
503
504/// Compteurs matériels courants (`PERF_COUNT_HW_*`), champ `config`.
505#[derive(Debug, Clone, Copy, PartialEq, Eq)]
506pub enum PerfHardwareCounter {
507    /// `PERF_COUNT_HW_CPU_CYCLES`.
508    CpuCycles,
509    /// `PERF_COUNT_HW_INSTRUCTIONS`.
510    Instructions,
511    /// `PERF_COUNT_HW_CACHE_REFERENCES`.
512    CacheReferences,
513    /// `PERF_COUNT_HW_CACHE_MISSES`.
514    CacheMisses,
515    /// `PERF_COUNT_HW_BRANCH_INSTRUCTIONS`.
516    BranchInstructions,
517    /// `PERF_COUNT_HW_BRANCH_MISSES`.
518    BranchMisses,
519    /// `PERF_COUNT_HW_BUS_CYCLES`.
520    BusCycles,
521    /// `PERF_COUNT_HW_REF_CPU_CYCLES`.
522    RefCpuCycles,
523}
524
525impl PerfHardwareCounter {
526    /// Valeur kernel `PERF_COUNT_HW_*`.
527    #[must_use]
528    pub const fn to_raw(self) -> u64 {
529        match self {
530            Self::CpuCycles => 0,
531            Self::Instructions => 1,
532            Self::CacheReferences => 2,
533            Self::CacheMisses => 3,
534            Self::BranchInstructions => 4,
535            Self::BranchMisses => 5,
536            Self::BusCycles => 6,
537            Self::RefCpuCycles => 9,
538        }
539    }
540}
541
542/// Compteurs logiciels courants (`PERF_COUNT_SW_*`), champ `config`.
543#[derive(Debug, Clone, Copy, PartialEq, Eq)]
544pub enum PerfSoftwareCounter {
545    /// `PERF_COUNT_SW_CPU_CLOCK`.
546    CpuClock,
547    /// `PERF_COUNT_SW_TASK_CLOCK`.
548    TaskClock,
549    /// `PERF_COUNT_SW_PAGE_FAULTS`.
550    PageFaults,
551    /// `PERF_COUNT_SW_CONTEXT_SWITCHES`.
552    ContextSwitches,
553    /// `PERF_COUNT_SW_CPU_MIGRATIONS`.
554    CpuMigrations,
555}
556
557impl PerfSoftwareCounter {
558    /// Valeur kernel `PERF_COUNT_SW_*`.
559    #[must_use]
560    pub const fn to_raw(self) -> u64 {
561        match self {
562            Self::CpuClock => 0,
563            Self::TaskClock => 1,
564            Self::PageFaults => 2,
565            Self::ContextSwitches => 3,
566            Self::CpuMigrations => 4,
567        }
568    }
569}
570
571/// Miroir `#[repr(C)]` de `struct perf_event_attr` (136 octets, ver. 6.12).
572///
573/// Champs aux noms kernel ; `Default` (tout à zéro) est un attribut valide.
574/// Le champ `flags` agrège les bitfields kernel (`disabled`, `inherit`,
575/// `exclude_kernel`…) — voir les constantes associées. Un builder ergonomique
576/// relève de la couche 1.
577#[repr(C)]
578#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
579pub struct PerfEventAttr {
580    /// `type` — famille de l'événement (`PERF_TYPE_*`).
581    pub kind: u32,
582    /// `size` — taille de la structure (renseignée par le wrapper).
583    pub size: u32,
584    /// `config` — événement précis dans la famille.
585    pub config: u64,
586    /// `sample_period` / `sample_freq`.
587    pub sample_period_or_freq: u64,
588    /// `sample_type` — champs échantillonnés (`PERF_SAMPLE_*`).
589    pub sample_type: u64,
590    /// `read_format` — format de lecture (`PERF_FORMAT_*`).
591    pub read_format: u64,
592    /// Bitfields agrégés (`disabled`, `inherit`, `exclude_kernel`…).
593    pub flags: u64,
594    /// `wakeup_events` / `wakeup_watermark`.
595    pub wakeup: u32,
596    /// `bp_type`.
597    pub bp_type: u32,
598    /// `bp_addr` / `config1`.
599    pub config1: u64,
600    /// `bp_len` / `config2`.
601    pub config2: u64,
602    /// `branch_sample_type`.
603    pub branch_sample_type: u64,
604    /// `sample_regs_user`.
605    pub sample_regs_user: u64,
606    /// `sample_stack_user`.
607    pub sample_stack_user: u32,
608    /// `clockid`.
609    pub clockid: i32,
610    /// `sample_regs_intr`.
611    pub sample_regs_intr: u64,
612    /// `aux_watermark`.
613    pub aux_watermark: u32,
614    /// `sample_max_stack`.
615    pub sample_max_stack: u16,
616    /// `__reserved_2`.
617    pub reserved_2: u16,
618    /// `aux_sample_size`.
619    pub aux_sample_size: u32,
620    /// `__reserved_3`.
621    pub reserved_3: u32,
622    /// `sig_data`.
623    pub sig_data: u64,
624    /// `config3`.
625    pub config3: u64,
626}
627
628impl PerfEventAttr {
629    /// `disabled:1` — démarre désactivé.
630    pub const FLAG_DISABLED: u64 = 1 << 0;
631    /// `inherit:1` — hérité par les tâches filles.
632    pub const FLAG_INHERIT: u64 = 1 << 1;
633    /// `pinned:1`.
634    pub const FLAG_PINNED: u64 = 1 << 2;
635    /// `exclusive:1`.
636    pub const FLAG_EXCLUSIVE: u64 = 1 << 3;
637    /// `exclude_user:1`.
638    pub const FLAG_EXCLUDE_USER: u64 = 1 << 4;
639    /// `exclude_kernel:1`.
640    pub const FLAG_EXCLUDE_KERNEL: u64 = 1 << 5;
641    /// `exclude_hv:1`.
642    pub const FLAG_EXCLUDE_HV: u64 = 1 << 6;
643    /// `exclude_idle:1`.
644    pub const FLAG_EXCLUDE_IDLE: u64 = 1 << 7;
645}
646
647/// Portée d'un `perf_event_open` : `pid`/`cpu` sans sentinelle `-1`.
648#[derive(Debug, Clone, Copy)]
649pub enum PerfEventScope<'a> {
650    /// Processus courant, n'importe quel CPU (`pid=0, cpu=-1`).
651    CallingProcessAnyCpu,
652    /// Processus courant sur un CPU précis (`pid=0, cpu=N`).
653    CallingProcessOnCpu(u32),
654    /// Un processus précis, n'importe quel CPU (`pid=P, cpu=-1`).
655    ProcessAnyCpu(Pid),
656    /// Un processus précis sur un CPU précis.
657    ProcessOnCpu {
658        /// PID cible.
659        process: Pid,
660        /// CPU cible.
661        cpu: u32,
662    },
663    /// Tous les processus sur un CPU (`pid=-1, cpu=N`).
664    AllProcessesOnCpu(u32),
665    /// Surveillance par cgroup (`flags |= PID_CGROUP`, `pid = cgroup_fd`).
666    Cgroup {
667        /// FD du cgroup à surveiller.
668        cgroup: BorrowedFd<'a>,
669        /// CPU cible.
670        cpu: u32,
671    },
672}
673
674// ─────────────────────────────────────────────────────────────────────────
675// Structs-requête (agrégats purs passés aux wrappers).
676// ─────────────────────────────────────────────────────────────────────────
677
678/// Infos BTF optionnelles pour une carte (clé/valeur typées).
679#[derive(Debug, Clone, Copy)]
680pub struct BpfMapBtfInfo<'a> {
681    /// FD de l'objet BTF décrivant les types.
682    pub btf_fd: BorrowedFd<'a>,
683    /// Id du type de clé dans le BTF.
684    pub key_type_id: u32,
685    /// Id du type de valeur dans le BTF.
686    pub value_type_id: u32,
687}
688
689/// Requête de création de carte (`BPF_MAP_CREATE`).
690#[derive(Debug, Clone, Copy)]
691pub struct BpfMapCreateRequest<'a> {
692    /// Type de carte.
693    pub map_type: BpfMapType,
694    /// Taille de clé en octets.
695    pub key_size: u32,
696    /// Taille de valeur en octets.
697    pub value_size: u32,
698    /// Nombre maximal d'entrées.
699    pub max_entries: u32,
700    /// Drapeaux de création.
701    pub flags: BpfMapCreateFlags,
702    /// Nom (≤ 15 octets utiles + NUL) ou `None` (anonyme).
703    pub name: Option<&'a CStr>,
704    /// Pour map-of-maps : le gabarit de carte interne.
705    pub inner_map: Option<BorrowedFd<'a>>,
706    /// Nœud NUMA préféré.
707    pub numa_node: Option<u32>,
708    /// Infos BTF optionnelles.
709    pub btf: Option<BpfMapBtfInfo<'a>>,
710}
711
712/// Requête de chargement de programme (`BPF_PROG_LOAD`).
713#[derive(Debug, Clone, Copy)]
714pub struct BpfProgramLoadRequest<'a> {
715    /// Type de programme.
716    pub program_type: BpfProgramType,
717    /// Programme **déjà assemblé**.
718    pub instructions: &'a [BpfInstruction],
719    /// Licence (`GPL`, `Dual BSD/GPL`…).
720    pub license: &'a CStr,
721    /// Nom du programme (introspection).
722    pub name: Option<&'a CStr>,
723    /// Type d'attache attendu.
724    pub expected_attach_type: Option<BpfAttachType>,
725    /// BTF cible (fentry/fexit/LSM/tracing).
726    pub attach_btf: Option<BorrowedFd<'a>>,
727    /// Id du point d'attache dans le BTF cible.
728    pub attach_btf_id: Option<u32>,
729    /// Programme à étendre (`Ext` / freplace).
730    pub attach_program: Option<BorrowedFd<'a>>,
731    /// Drapeaux de chargement.
732    pub flags: BpfProgramLoadFlags,
733    /// Verbosité du vérifieur.
734    pub log_level: BpfVerifierLogLevel,
735}
736
737/// Requête de création de lien moderne (`BPF_LINK_CREATE`).
738#[derive(Debug, Clone, Copy)]
739pub struct BpfLinkCreateRequest<'a> {
740    /// Programme à attacher.
741    pub program: BorrowedFd<'a>,
742    /// Cible (cgroup, ifindex encodé, BTF…) ; `None` pour les attaches sans
743    /// FD cible (tracing).
744    pub target: Option<BorrowedFd<'a>>,
745    /// Type d'attache.
746    pub attach_type: BpfAttachType,
747    /// Drapeaux (selon le type d'attache).
748    pub flags: u32,
749}
750
751/// Requête d'exécution de test (`BPF_PROG_TEST_RUN`).
752#[derive(Debug)]
753pub struct BpfProgramTestRunRequest<'a> {
754    /// Données d'entrée fournies au programme.
755    pub data_in: &'a [u8],
756    /// Tampon de sortie (rempli par le kernel).
757    pub data_out: &'a mut [u8],
758    /// Contexte d'entrée optionnel.
759    pub context_in: &'a [u8],
760    /// Tampon de contexte de sortie optionnel.
761    pub context_out: &'a mut [u8],
762    /// Nombre de répétitions.
763    pub repeat: u32,
764    /// Drapeaux.
765    pub flags: u32,
766}
767
768/// Résultat d'une exécution de test.
769#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
770pub struct BpfProgramTestRunResult {
771    /// Valeur de retour du programme.
772    pub return_value: u32,
773    /// Durée moyenne d'exécution (ns).
774    pub duration: u32,
775    /// Octets de données de sortie effectivement écrits.
776    pub data_size_out: u32,
777    /// Octets de contexte de sortie effectivement écrits.
778    pub context_size_out: u32,
779}
780
781/// Requête d'opération batch en lecture (`BPF_MAP_LOOKUP_BATCH`…).
782#[derive(Debug)]
783pub struct BpfMapBatchRequest<'a> {
784    /// Curseur d'entrée opaque (`None` = début).
785    pub in_batch: Option<u64>,
786    /// Curseur de sortie opaque, écrit par le kernel.
787    pub out_batch: u64,
788    /// Tampon de clés.
789    pub keys: &'a mut [u8],
790    /// Tampon de valeurs.
791    pub values: &'a mut [u8],
792    /// Nombre d'éléments demandés.
793    pub count: u32,
794    /// Drapeaux élément.
795    pub elem_flags: u64,
796    /// Drapeaux opération.
797    pub flags: u64,
798}
799
800/// Requête d'opération batch en écriture (`BPF_MAP_UPDATE_BATCH`…).
801#[derive(Debug, Clone, Copy)]
802pub struct BpfMapBatchInput<'a> {
803    /// Tampon de clés.
804    pub keys: &'a [u8],
805    /// Tampon de valeurs (vide pour `delete_batch`).
806    pub values: &'a [u8],
807    /// Nombre d'éléments.
808    pub count: u32,
809    /// Drapeaux élément.
810    pub elem_flags: u64,
811    /// Drapeaux opération.
812    pub flags: u64,
813}
814
815/// Requête d'interrogation des programmes attachés (`BPF_PROG_QUERY`).
816#[derive(Debug)]
817pub struct BpfProgramQueryRequest<'a> {
818    /// Cible (cgroup…).
819    pub target: BorrowedFd<'a>,
820    /// Type d'attache interrogé.
821    pub attach_type: BpfAttachType,
822    /// Drapeaux de requête.
823    pub query_flags: u32,
824    /// Tampon d'ids de programmes (rempli par le kernel).
825    pub program_ids: &'a mut [u32],
826}
827
828/// Requête d'introspection d'un fd perf/tracepoint (`BPF_TASK_FD_QUERY`).
829#[derive(Debug)]
830pub struct BpfTaskFdQueryRequest<'a> {
831    /// PID de la tâche.
832    pub pid: Pid,
833    /// FD perf/tracepoint dans la tâche.
834    pub fd: BorrowedFd<'a>,
835    /// Tampon recevant le nom du point d'attache.
836    pub name_buffer: &'a mut [u8],
837}
838
839#[cfg(test)]
840mod tests;
841
842#[cfg(test)]
843// Sous `tests/`, et pas à côté : le filtre par défaut de `cargo-llvm-cov` écarte
844// `tests.rs`, `*_tests.rs` et les répertoires `tests/` — mais PAS un `proptests.rs`
845// posé en voisin, dont les lignes retomberaient dans la mesure de production.
846// `#[path]` déplace le FICHIER sans toucher l'arbre des modules : `super::` désigne
847// toujours le parent, et le contenu n'a pas à changer.
848#[path = "ebpf/tests/proptests.rs"]
849mod proptests;