Skip to content

Commit a82d8be

Browse files
ver-nyandanielocfb
authored andcommitted
query: add iter link info
1 parent aa49252 commit a82d8be

4 files changed

Lines changed: 132 additions & 3 deletions

File tree

examples/bpf_query/src/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ fn link() {
8383
query::LinkTypeInfo::RawTracepoint(_) => "raw_tracepoint",
8484
query::LinkTypeInfo::Tracing(_) => "tracing",
8585
query::LinkTypeInfo::Cgroup(_) => "cgroup",
86-
query::LinkTypeInfo::Iter => "iter",
86+
query::LinkTypeInfo::Iter(_) => "iter",
8787
query::LinkTypeInfo::NetNs(_) => "netns",
8888
query::LinkTypeInfo::Unknown => "unknown",
8989
query::LinkTypeInfo::Netfilter(_) => "netfilter",

libbpf-rs/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ Unreleased
33
- Added `KprobeMultiLinkInfo` & `UprobeMultiLinkInfo` fields that required a
44
second info call.
55
- Added `key_size`, `value_size` and more getters to `OpenMap{,Mut}`
6+
- Added specific `IterLinkInfo` fields for `LinkTypeInfo::Iter`.
67

78

89
0.26.2

libbpf-rs/src/query.rs

Lines changed: 95 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ use std::ptr;
2929
use std::time::Duration;
3030

3131
use crate::util;
32+
use crate::CgroupIterOrder;
3233
use crate::MapType;
3334
use crate::ProgramAttachType;
3435
use crate::ProgramType;
@@ -651,6 +652,39 @@ pub struct CgroupLinkInfo {
651652
pub attach_type: ProgramAttachType,
652653
}
653654

655+
/// Information about a BPF iterator link.
656+
#[derive(Debug, Clone)]
657+
pub struct IterLinkInfo {
658+
/// The `bpf_iter__*` target name.
659+
pub target_name: Option<CString>,
660+
/// Specific BPF iterator information.
661+
pub iter_type: Option<IterType>,
662+
}
663+
664+
/// Specific BPF iterator types with decoded information.
665+
#[derive(Debug, Clone)]
666+
pub enum IterType {
667+
/// A map type iterator.
668+
Map {
669+
/// The ID of the map being iterated.
670+
map_id: u32,
671+
},
672+
/// A cgroup type iterator.
673+
Cgroup {
674+
/// The cgroup ID of where the iterator starts.
675+
cgroup_id: u64,
676+
/// The order in how the iterator traverses.
677+
order: CgroupIterOrder,
678+
},
679+
/// A task type iterator.
680+
Task {
681+
/// Specific thread that is iterated over.
682+
tid: u32,
683+
/// Specific process that is iterated over.
684+
pid: u32,
685+
},
686+
}
687+
654688
/// Information about a network namespace link.
655689
#[derive(Debug, Clone)]
656690
pub struct NetNsLinkInfo {
@@ -823,7 +857,7 @@ pub enum LinkTypeInfo {
823857
/// Contains information about the cgroups and its attachment type.
824858
Cgroup(CgroupLinkInfo),
825859
/// Iterator link type.
826-
Iter,
860+
Iter(IterLinkInfo),
827861
/// Network namespace link type.
828862
NetNs(NetNsLinkInfo),
829863
/// Link type for XDP programs.
@@ -925,7 +959,66 @@ impl LinkInfo {
925959
s.__bindgen_anon_1.cgroup.attach_type
926960
}),
927961
}),
928-
libbpf_sys::BPF_LINK_TYPE_ITER => LinkTypeInfo::Iter,
962+
libbpf_sys::BPF_LINK_TYPE_ITER => {
963+
let mut buf = [0; 256];
964+
s.__bindgen_anon_1.iter.target_name = buf.as_mut_ptr() as u64;
965+
s.__bindgen_anon_1.iter.target_name_len = buf.len() as u32;
966+
let item_ptr: *mut libbpf_sys::bpf_link_info = &mut s;
967+
let mut len = size_of_val(&s) as u32;
968+
969+
let ret = unsafe {
970+
libbpf_sys::bpf_obj_get_info_by_fd(fd.as_raw_fd(), item_ptr.cast(), &mut len)
971+
};
972+
if ret != 0 {
973+
return None;
974+
}
975+
976+
let iter_info = unsafe { s.__bindgen_anon_1.iter };
977+
let (target_name, iter_type) = if iter_info.target_name_len != 0 {
978+
let target_name = unsafe {
979+
CStr::from_ptr(iter_info.target_name as *const c_char).to_owned()
980+
};
981+
982+
let iter_type = match target_name.as_bytes() {
983+
b"bpf_map_elem" | b"bpf_sk_storage_map" => Some(IterType::Map {
984+
map_id: unsafe { iter_info.__bindgen_anon_1.map.map_id },
985+
}),
986+
b"cgroup" => {
987+
let order = match unsafe { iter_info.__bindgen_anon_2.cgroup.order } {
988+
libbpf_sys::BPF_CGROUP_ITER_SELF_ONLY => CgroupIterOrder::SelfOnly,
989+
libbpf_sys::BPF_CGROUP_ITER_DESCENDANTS_PRE => {
990+
CgroupIterOrder::DescendantsPre
991+
}
992+
libbpf_sys::BPF_CGROUP_ITER_DESCENDANTS_POST => {
993+
CgroupIterOrder::DescendantsPost
994+
}
995+
libbpf_sys::BPF_CGROUP_ITER_ANCESTORS_UP => {
996+
CgroupIterOrder::AncestorsUp
997+
}
998+
_ => CgroupIterOrder::Default,
999+
};
1000+
Some(IterType::Cgroup {
1001+
cgroup_id: unsafe { iter_info.__bindgen_anon_2.cgroup.cgroup_id },
1002+
order,
1003+
})
1004+
}
1005+
b"task" | b"task_file" | b"task_vma" => Some(IterType::Task {
1006+
tid: unsafe { iter_info.__bindgen_anon_2.task.tid },
1007+
pid: unsafe { iter_info.__bindgen_anon_2.task.pid },
1008+
}),
1009+
_ => None,
1010+
};
1011+
1012+
(Some(target_name), iter_type)
1013+
} else {
1014+
(None, None)
1015+
};
1016+
1017+
LinkTypeInfo::Iter(IterLinkInfo {
1018+
target_name,
1019+
iter_type,
1020+
})
1021+
}
9291022
libbpf_sys::BPF_LINK_TYPE_NETNS => LinkTypeInfo::NetNs(NetNsLinkInfo {
9301023
ino: unsafe { s.__bindgen_anon_1.netns.netns_ino },
9311024
attach_type: ProgramAttachType::from(unsafe {

libbpf-rs/tests/test.rs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ use std::sync::mpsc::channel;
3838
use std::time::Duration;
3939

4040
use libbpf_rs::num_possible_cpus;
41+
use libbpf_rs::query::IterLinkInfo;
42+
use libbpf_rs::query::IterType;
4143
use libbpf_rs::query::KprobeMultiLinkInfo;
4244
use libbpf_rs::query::LinkTypeInfo;
4345
use libbpf_rs::query::PerfEventType;
@@ -1487,6 +1489,23 @@ fn test_object_task_iter() {
14871489
assert!(items.windows(2).all(|w| w[0].i + 1 == w[1].i));
14881490
// Check for init
14891491
assert!(items.iter().any(|&item| item.pid == 1));
1492+
1493+
let link_info = link.info().expect("failed to get iter link info");
1494+
let LinkTypeInfo::Iter(iter_info) = link_info.info else {
1495+
panic!("Expected LinkTypeInfo::Iter, got: {:?}", link_info.info);
1496+
};
1497+
1498+
let IterLinkInfo {
1499+
target_name,
1500+
iter_type,
1501+
} = iter_info;
1502+
assert_eq!(target_name, CString::new("task").ok());
1503+
1504+
let Some(IterType::Task { tid, pid }) = iter_type else {
1505+
panic!("Expected IterType::Task, got: {iter_type:?}");
1506+
};
1507+
assert_eq!(tid, 0); // all threads
1508+
assert_eq!(pid, 0); // all processes
14901509
}
14911510

14921511
// Test using auto-attachment.
@@ -1552,6 +1571,22 @@ fn test_object_map_iter() {
15521571
assert!(buf.contains(&0));
15531572
assert!(buf.contains(&1));
15541573
assert!(buf.contains(&2));
1574+
1575+
let link_info = link.info().expect("failed to get iter link info");
1576+
let LinkTypeInfo::Iter(iter_info) = link_info.info else {
1577+
panic!("Expected LinkTypeInfo::Iter, got: {:?}", link_info.info);
1578+
};
1579+
1580+
let IterLinkInfo {
1581+
target_name,
1582+
iter_type,
1583+
} = iter_info;
1584+
assert_eq!(target_name, CString::new("bpf_map_elem").ok());
1585+
1586+
let Some(IterType::Map { map_id }) = iter_type else {
1587+
panic!("Expected IterType::Map, got: {iter_type:?}");
1588+
};
1589+
assert_eq!(map_id, map.info().unwrap().info.id);
15551590
}
15561591

15571592
#[tag(root)]

0 commit comments

Comments
 (0)