1use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};
6
7pub const BPF_STACK_SIZE: usize = 512;
9
10pub const BPF_MAX_INSTS: usize = 65536;
12
13pub const REGISTER_COUNT: u8 = 11;
15
16pub const GENERAL_REGISTER_COUNT: u8 = 10;
18
19#[derive(Clone, Copy, Debug, Eq, PartialEq)]
20pub enum DataWidth {
21 U8,
22 U16,
23 U32,
24 U64,
25}
26
27impl DataWidth {
29 pub fn bits(&self) -> usize {
30 match self {
31 Self::U8 => 8,
32 Self::U16 => 16,
33 Self::U32 => 32,
34 Self::U64 => 64,
35 }
36 }
37
38 pub fn bytes(&self) -> usize {
39 match self {
40 Self::U8 => 1,
41 Self::U16 => 2,
42 Self::U32 => 4,
43 Self::U64 => 8,
44 }
45 }
46
47 pub fn str(&self) -> &'static str {
48 match self {
49 Self::U8 => "b",
50 Self::U16 => "h",
51 Self::U32 => "w",
52 Self::U64 => "dw",
53 }
54 }
55
56 pub fn instruction_bits(&self) -> u8 {
57 match self {
58 Self::U8 => BPF_B,
59 Self::U16 => BPF_H,
60 Self::U32 => BPF_W,
61 Self::U64 => BPF_DW,
62 }
63 }
64}
65
66#[repr(transparent)]
71#[derive(Copy, Clone, Eq, PartialEq, FromBytes, IntoBytes, KnownLayout, Immutable)]
72pub struct EbpfInstruction(u64);
73
74impl std::fmt::Debug for EbpfInstruction {
75 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
76 f.debug_struct("EbpfInstruction")
77 .field("code", &self.code())
78 .field("dst", &self.dst_reg())
79 .field("src", &self.src_reg())
80 .field("offset", &self.offset())
81 .field("imm", &self.imm())
82 .finish()
83 }
84}
85
86impl From<u64> for EbpfInstruction {
87 fn from(value: u64) -> Self {
88 Self(value)
89 }
90}
91
92#[cfg(target_endian = "little")]
94impl EbpfInstruction {
95 pub fn new(code: u8, dst: u8, src: u8, offset: i16, imm: i32) -> Self {
96 assert!(dst < 16);
97 assert!(src < 16);
98
99 Self(
100 (code as u64)
101 | (dst as u64) << 8
102 | (src as u64) << 12
103 | (offset as u16 as u64) << 16
104 | (imm as u32 as u64) << 32,
105 )
106 }
107
108 #[inline(always)]
109 pub fn code(&self) -> u8 {
110 self.0 as u8
111 }
112
113 pub fn set_code(&mut self, code: u8) {
114 *self = EbpfInstruction((self.0 & !0x00ff) | code as u64)
115 }
116
117 #[inline(always)]
118 pub fn dst_reg(&self) -> u8 {
119 ((self.0 & 0x0f00) >> 8) as u8
120 }
121
122 pub fn set_dst_reg(&mut self, dst_reg: u8) {
123 assert!(dst_reg < 16);
124 *self = EbpfInstruction((self.0 & !0x0f00) | ((dst_reg as u64) << 8))
125 }
126
127 #[inline(always)]
128 pub fn src_reg(&self) -> u8 {
129 ((self.0 & 0xf000) >> 12) as u8
130 }
131
132 pub fn set_src_reg(&mut self, src_reg: u8) {
133 assert!(src_reg < 16);
134 *self = EbpfInstruction((self.0 & !0xf000) | ((src_reg as u64) << 12))
135 }
136
137 #[inline(always)]
138 pub fn offset(&self) -> i16 {
139 (self.0 >> 16) as u16 as i16
140 }
141
142 pub fn set_offset(&mut self, offset: i16) {
143 *self = EbpfInstruction((self.0 & !0xffff_0000) | ((offset as u16 as u64) << 16))
144 }
145
146 #[inline(always)]
147 pub fn imm(&self) -> i32 {
148 (self.0 >> 32 as u32) as i32
149 }
150
151 pub fn set_imm(&mut self, imm: i32) {
152 *self = EbpfInstruction((self.0 & 0xffff_ffff) | ((imm as u32 as u64) << 32))
153 }
154}
155
156pub const BPF_LD: u8 = linux_uapi::BPF_LD as u8;
158pub const BPF_LDX: u8 = linux_uapi::BPF_LDX as u8;
159pub const BPF_ST: u8 = linux_uapi::BPF_ST as u8;
160pub const BPF_STX: u8 = linux_uapi::BPF_STX as u8;
161pub const BPF_ALU: u8 = linux_uapi::BPF_ALU as u8;
162pub const BPF_JMP: u8 = linux_uapi::BPF_JMP as u8;
163pub const BPF_JMP32: u8 = linux_uapi::BPF_JMP32 as u8;
164pub const BPF_ALU64: u8 = linux_uapi::BPF_ALU64 as u8;
165pub const BPF_CLS_MASK: u8 =
166 BPF_LD | BPF_LDX | BPF_ST | BPF_STX | BPF_ALU | BPF_JMP | BPF_JMP | BPF_JMP32 | BPF_ALU64;
167
168pub const BPF_SUB_OP_MASK: u8 = 0xf0;
170
171pub const BPF_SRC_REG: u8 = linux_uapi::BPF_X as u8;
173pub const BPF_SRC_IMM: u8 = linux_uapi::BPF_K as u8;
174pub const BPF_SRC_MASK: u8 = BPF_SRC_REG | BPF_SRC_IMM;
175
176pub const BPF_IMM: u8 = linux_uapi::BPF_IMM as u8;
179pub const BPF_MEM: u8 = linux_uapi::BPF_MEM as u8;
180pub const BPF_ATOMIC: u8 = linux_uapi::BPF_ATOMIC as u8;
181pub const BPF_ABS: u8 = linux_uapi::BPF_ABS as u8;
182pub const BPF_IND: u8 = linux_uapi::BPF_IND as u8;
183pub const BPF_LOAD_STORE_MASK: u8 = BPF_IMM | BPF_MEM | BPF_ATOMIC | BPF_ABS | BPF_IND;
184
185pub const BPF_TO_BE: u8 = linux_uapi::BPF_TO_BE as u8;
187pub const BPF_TO_LE: u8 = linux_uapi::BPF_TO_LE as u8;
188pub const BPF_END_TYPE_MASK: u8 = BPF_TO_BE | BPF_TO_LE;
189
190pub const BPF_B: u8 = linux_uapi::BPF_B as u8;
192pub const BPF_H: u8 = linux_uapi::BPF_H as u8;
193pub const BPF_W: u8 = linux_uapi::BPF_W as u8;
194pub const BPF_DW: u8 = linux_uapi::BPF_DW as u8;
195pub const BPF_SIZE_MASK: u8 = BPF_B | BPF_H | BPF_W | BPF_DW;
196
197pub const BPF_ADD: u8 = linux_uapi::BPF_ADD as u8;
199pub const BPF_SUB: u8 = linux_uapi::BPF_SUB as u8;
200pub const BPF_MUL: u8 = linux_uapi::BPF_MUL as u8;
201pub const BPF_DIV: u8 = linux_uapi::BPF_DIV as u8;
202pub const BPF_OR: u8 = linux_uapi::BPF_OR as u8;
203pub const BPF_AND: u8 = linux_uapi::BPF_AND as u8;
204pub const BPF_LSH: u8 = linux_uapi::BPF_LSH as u8;
205pub const BPF_RSH: u8 = linux_uapi::BPF_RSH as u8;
206pub const BPF_NEG: u8 = linux_uapi::BPF_NEG as u8;
207pub const BPF_MOD: u8 = linux_uapi::BPF_MOD as u8;
208pub const BPF_XOR: u8 = linux_uapi::BPF_XOR as u8;
209pub const BPF_MOV: u8 = linux_uapi::BPF_MOV as u8;
210pub const BPF_ARSH: u8 = linux_uapi::BPF_ARSH as u8;
211pub const BPF_END: u8 = linux_uapi::BPF_END as u8;
212
213pub const BPF_JA: u8 = linux_uapi::BPF_JA as u8;
215pub const BPF_JEQ: u8 = linux_uapi::BPF_JEQ as u8;
216pub const BPF_JGT: u8 = linux_uapi::BPF_JGT as u8;
217pub const BPF_JGE: u8 = linux_uapi::BPF_JGE as u8;
218pub const BPF_JSET: u8 = linux_uapi::BPF_JSET as u8;
219pub const BPF_JNE: u8 = linux_uapi::BPF_JNE as u8;
220pub const BPF_JSGT: u8 = linux_uapi::BPF_JSGT as u8;
221pub const BPF_JSGE: u8 = linux_uapi::BPF_JSGE as u8;
222pub const BPF_CALL: u8 = linux_uapi::BPF_CALL as u8;
223pub const BPF_EXIT: u8 = linux_uapi::BPF_EXIT as u8;
224pub const BPF_JLT: u8 = linux_uapi::BPF_JLT as u8;
225pub const BPF_JLE: u8 = linux_uapi::BPF_JLE as u8;
226pub const BPF_JSLT: u8 = linux_uapi::BPF_JSLT as u8;
227pub const BPF_JSLE: u8 = linux_uapi::BPF_JSLE as u8;
228
229pub const BPF_FETCH: u8 = linux_uapi::BPF_FETCH as u8;
231pub const BPF_XCHG: u8 = linux_uapi::BPF_XCHG as u8;
232pub const BPF_CMPXCHG: u8 = linux_uapi::BPF_CMPXCHG as u8;
233
234pub const BPF_LDDW: u8 = BPF_LD | BPF_DW;
236
237pub const BPF_LEN: u8 = linux_uapi::BPF_LEN as u8;
239pub const BPF_MISC: u8 = linux_uapi::BPF_MISC as u8;
240pub const BPF_RET: u8 = linux_uapi::BPF_RET as u8;
241pub const BPF_MSH: u8 = linux_uapi::BPF_MSH as u8;
242pub const BPF_A: u8 = linux_uapi::BPF_A as u8;
243pub const BPF_K: u8 = linux_uapi::BPF_K as u8;
244pub const BPF_X: u8 = linux_uapi::BPF_X as u8;
245pub const BPF_TXA: u8 = linux_uapi::BPF_TXA as u8;
246pub const BPF_TAX: u8 = linux_uapi::BPF_TAX as u8;
247
248pub const BPF_PSEUDO_MAP_FD: u8 = linux_uapi::BPF_PSEUDO_MAP_FD as u8;
251pub const BPF_PSEUDO_MAP_IDX: u8 = linux_uapi::BPF_PSEUDO_MAP_IDX as u8;
252pub const BPF_PSEUDO_MAP_VALUE: u8 = linux_uapi::BPF_PSEUDO_MAP_VALUE as u8;
253pub const BPF_PSEUDO_MAP_IDX_VALUE: u8 = linux_uapi::BPF_PSEUDO_MAP_IDX_VALUE as u8;
254pub const BPF_PSEUDO_BTF_ID: u8 = linux_uapi::BPF_PSEUDO_BTF_ID as u8;
255pub const BPF_PSEUDO_FUNC: u8 = linux_uapi::BPF_PSEUDO_FUNC as u8;
256
257pub const BPF_PSEUDO_CALL: u8 = linux_uapi::BPF_PSEUDO_CALL as u8;
260pub const BPF_PSEUDO_KFUNC_CALL: u8 = linux_uapi::BPF_PSEUDO_KFUNC_CALL as u8;
261
262pub type CbpfInstruction = linux_uapi::sock_filter;
263pub type EbpfMapType = linux_uapi::bpf_map_type;