-
Notifications
You must be signed in to change notification settings - Fork 24
Expand file tree
/
Copy pathcontext_codegen.ml
More file actions
299 lines (266 loc) · 10.4 KB
/
Copy pathcontext_codegen.ml
File metadata and controls
299 lines (266 loc) · 10.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
(*
* Copyright 2025 Multikernel Technologies, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*)
(** Context Code Generation Interface
This module defines the interface for context-specific code generators
*)
open Printf
type context_field_access = {
field_name: string;
c_expression: string -> string; (* ctx_var -> C expression *)
requires_cast: bool;
field_type: string; (* C type of the field *)
}
(** BTF type information for context codegen *)
type btf_type_info = {
name: string;
kind: string;
size: int option;
members: (string * string) list option; (* field_name * field_type *)
kernel_defined: bool;
}
type context_codegen = {
name: string;
c_type: string;
section_prefix: string;
field_mappings: (string * context_field_access) list;
generate_includes: unit -> string list;
generate_field_access: string -> string -> string; (* ctx_var -> field_name -> C expression *)
map_action_constant: int -> string option; (* Map integer to action constant *)
generate_function_signature: (string -> (string * string) list -> string -> string) option; (* func_name -> parameters -> return_type -> signature *)
generate_section_name: (string option -> string) option; (* Optional function to generate SEC(...) attribute with target *)
}
(** Registry for context code generators *)
let context_generators = Hashtbl.create 8
(** Register a context code generator *)
let register_context_codegen ctx_type codegen =
Hashtbl.replace context_generators ctx_type codegen
(** Get a context code generator by type *)
let get_context_codegen ctx_type =
try
Some (Hashtbl.find context_generators ctx_type)
with Not_found -> None
(** Initialize all context code generators *)
let init_context_codegens () =
(* This will be called by the individual modules *)
()
(** Generate field access for a context type *)
let generate_context_field_access ctx_type ctx_var field_name =
match get_context_codegen ctx_type with
| Some codegen -> codegen.generate_field_access ctx_var field_name
| None -> failwith ("Unknown context type: " ^ ctx_type)
(** Get context-specific includes *)
let get_context_includes ctx_type =
match get_context_codegen ctx_type with
| Some codegen -> codegen.generate_includes ()
| None -> []
(** Map action constant for a context type *)
let map_context_action_constant ctx_type action_value =
match get_context_codegen ctx_type with
| Some codegen -> codegen.map_action_constant action_value
| None -> None
(** Get all action constants for a context type as (name, value) pairs *)
let get_context_action_constants ctx_type =
match get_context_codegen ctx_type with
| Some codegen ->
(* Generate constants by testing integer values *)
let rec collect_constants acc value =
if value > 10 then acc (* Reasonable limit *)
else
match codegen.map_action_constant value with
| Some name -> collect_constants ((name, value) :: acc) (value + 1)
| None -> collect_constants acc (value + 1)
in
List.rev (collect_constants [] 0)
| None -> []
(** Generate custom function signature for a context type *)
let generate_context_function_signature ctx_type func_name parameters return_type =
match get_context_codegen ctx_type with
| Some codegen ->
(match codegen.generate_function_signature with
| Some gen_func -> Some (gen_func func_name parameters return_type)
| None -> None)
| None -> None
(** Get struct field definitions for a context type as (name, c_type) pairs *)
let get_context_struct_fields ctx_type =
match get_context_codegen ctx_type with
| Some codegen ->
List.map (fun (field_name, field_access) ->
(field_name, field_access.field_type)
) codegen.field_mappings
| None -> []
(** Get program description for a context type *)
let get_context_program_description ctx_type =
match ctx_type with
| "xdp" -> "XDP (eXpress Data Path) program for high-performance packet processing"
| "tc" -> "TC (Traffic Control) program for network traffic shaping and filtering"
| "probe" -> "Probe program for dynamic kernel tracing (fprobe/kprobe)"
| "kprobe" -> "Kprobe program for dynamic kernel tracing with offset support"
| "tracepoint" -> "Tracepoint program for static kernel tracing"
| "fprobe" -> "Fprobe program for function entry/exit tracing"
| _ -> sprintf "eBPF %s program" ctx_type
(** Get the C type string for a context field *)
let get_context_field_c_type ctx_type field_name =
match get_context_codegen ctx_type with
| Some codegen ->
(try
let (_, field_access) = List.find (fun (name, _) -> name = field_name) codegen.field_mappings in
Some field_access.field_type
with Not_found -> None)
| None -> None
(** Create context field access from BTF field information *)
let create_btf_field_access field_name field_type =
(* Determine if casting is needed based on field type *)
let requires_cast =
String.contains field_type '*' ||
(String.contains field_type 'u' && String.contains field_type '6') (* __u64 *)
in
let c_expression = fun ctx_var ->
if requires_cast then
Printf.sprintf "(%s)(long)%s->%s" field_type ctx_var field_name
else
Printf.sprintf "%s->%s" ctx_var field_name
in
{
field_name;
c_expression;
requires_cast;
field_type;
}
(** Create context codegen from BTF type information *)
let create_context_codegen_from_btf ctx_type_name btf_type_info =
let field_mappings = match btf_type_info.members with
| Some members ->
List.map (fun (field_name, field_type) ->
(field_name, create_btf_field_access field_name field_type)
) members
| None -> []
in
let generate_field_access ctx_var field_name =
try
let (_, field_access) = List.find (fun (name, _) -> name = field_name) field_mappings in
field_access.c_expression ctx_var
with Not_found ->
failwith ("Unknown BTF context field: " ^ field_name ^ " for type: " ^ ctx_type_name)
in
let generate_includes () =
(* Generate appropriate includes based on context type *)
match ctx_type_name with
| "xdp" -> [
"#include <linux/bpf.h>";
"#include <bpf/bpf_helpers.h>";
"#include <linux/if_ether.h>";
"#include <linux/ip.h>";
"#include <linux/in.h>";
"#include <linux/if_xdp.h>";
]
| "tc" -> [
"#include <linux/bpf.h>";
"#include <bpf/bpf_helpers.h>";
"#include <linux/if_ether.h>";
"#include <linux/ip.h>";
"#include <linux/in.h>";
"#include <linux/pkt_cls.h>";
]
| _ -> [
"#include <linux/bpf.h>";
"#include <bpf/bpf_helpers.h>";
]
in
let map_action_constant = match ctx_type_name with
| "xdp" -> (function
| 0 -> Some "XDP_ABORTED"
| 1 -> Some "XDP_DROP"
| 2 -> Some "XDP_PASS"
| 3 -> Some "XDP_REDIRECT"
| 4 -> Some "XDP_TX"
| _ -> None)
| "tc" -> (function
| 255 -> Some "TC_ACT_UNSPEC"
| 0 -> Some "TC_ACT_OK"
| 1 -> Some "TC_ACT_RECLASSIFY"
| 2 -> Some "TC_ACT_SHOT"
| 3 -> Some "TC_ACT_PIPE"
| 4 -> Some "TC_ACT_STOLEN"
| 5 -> Some "TC_ACT_QUEUED"
| 6 -> Some "TC_ACT_REPEAT"
| 7 -> Some "TC_ACT_REDIRECT"
| _ -> None)
| _ -> (fun _ -> None)
in
let c_type = match ctx_type_name with
| "xdp" -> "struct xdp_md*"
| "tc" -> "struct __sk_buff*"
| _ -> Printf.sprintf "struct %s*" btf_type_info.name
in
let section_prefix = match ctx_type_name with
| "xdp" -> "xdp"
| "tc" -> "classifier"
| _ -> ctx_type_name
in
{
name = Printf.sprintf "%s (BTF)" ctx_type_name;
c_type;
section_prefix;
field_mappings;
generate_includes;
generate_field_access;
map_action_constant;
generate_function_signature = None;
generate_section_name = None;
}
(** Register context codegen from BTF type information *)
let register_btf_context_codegen ctx_type_name btf_type_info =
let codegen = create_context_codegen_from_btf ctx_type_name btf_type_info in
register_context_codegen ctx_type_name codegen;
Printf.printf "🔧 Registered BTF-based context codegen for %s with %d fields\n"
ctx_type_name (List.length codegen.field_mappings)
(** Update context codegen with BTF information if available *)
let update_context_codegen_with_btf ctx_type_name btf_type_info =
match get_context_codegen ctx_type_name with
| Some existing_codegen ->
(* Merge BTF fields with existing hardcoded fields *)
let btf_fields = match btf_type_info.members with
| Some members ->
List.map (fun (field_name, field_type) ->
(field_name, create_btf_field_access field_name field_type)
) members
| None -> []
in
(* Combine existing and BTF fields, with BTF fields taking precedence *)
let existing_field_names = List.map fst existing_codegen.field_mappings in
let btf_only_fields = List.filter (fun (name, _) ->
not (List.mem name existing_field_names)
) btf_fields in
let combined_fields = existing_codegen.field_mappings @ btf_only_fields in
let updated_codegen = {
existing_codegen with
field_mappings = combined_fields;
name = Printf.sprintf "%s (BTF-enhanced)" ctx_type_name;
} in
register_context_codegen ctx_type_name updated_codegen;
Printf.printf "🔧 Enhanced context codegen for %s with %d additional BTF fields\n"
ctx_type_name (List.length btf_only_fields)
| None ->
(* No existing codegen, create new one from BTF *)
register_btf_context_codegen ctx_type_name btf_type_info
(** Generate section name for a context type with optional direction *)
let generate_context_section_name ctx_type direction =
match get_context_codegen ctx_type with
| Some codegen ->
(match codegen.generate_section_name with
| Some section_fn -> Some (section_fn direction)
| None -> None)
| None -> None