I'm seeking to understand the purpose of the "custom" hook here, a snippet of which is reproduced below:
My original interpretation of this code was that it was a way to assign some kind of fixed ID to a BPF program that was loaded, but the custom hook's parent is only set to ingress.
I only need an ingress hook, so I was going to do away with the egress hook - but unsure what to make of the custom hook here
let mut egress = tc_builder.hook(TC_EGRESS);
let mut ingress = tc_builder.hook(TC_INGRESS);
let mut custom = tc_builder.hook(TC_CUSTOM);
custom.parent(TC_H_CLSACT, TC_H_MIN_INGRESS).handle(2);
// we can create a TcHook w/o the builder
let mut destroy_all = libbpf_rs::TcHook::new(progs.handle_tc().as_fd());
destroy_all
.ifindex(ifidx)
.attach_point(TC_EGRESS | TC_INGRESS);
if opts.query {
match custom.query() {
Err(e) => println!("failed to find custom hook: {e}"),
Ok(prog_id) => println!("found custom hook prog_id: {prog_id}"),
}
match egress.query() {
Err(e) => println!("failed to find custom hook: {e}"),
Ok(prog_id) => println!("found custom hook prog_id: {prog_id}"),
}
match ingress.query() {
Err(e) => println!("failed to find custom hook: {e}"),
Ok(prog_id) => println!("found custom hook prog_id: {prog_id}"),
}
}
if opts.detach {
if let Err(e) = ingress.detach() {
println!("failed to detach ingress hook {e}");
}
if let Err(e) = egress.detach() {
println!("failed to detach egress hook {e}");
}
if let Err(e) = custom.detach() {
println!("failed to detach custom hook {e}");
}
}
if opts.attach {
for (i, port) in opts.ports.iter().enumerate() {
let key = (i as u32).to_ne_bytes();
let val = port.to_ne_bytes();
let () = skel
.maps_mut()
.ports()
.update(&key, &val, MapFlags::ANY)
.context("Example limited to 10 ports")?;
}
ingress.create()?;
if let Err(e) = egress.attach() {
println!("failed to attach egress hook {e}");
}
if let Err(e) = ingress.attach() {
println!("failed to attach ingress hook {e}");
}
if let Err(e) = custom.attach() {
println!("failed to attach custom hook {e}");
}
}
if opts.destroy {
if let Err(e) = destroy_all.destroy() {
println!("failed to destroy all {e}");
}
}