-
Notifications
You must be signed in to change notification settings - Fork 287
/
tcx.rs
134 lines (128 loc) · 4.51 KB
/
tcx.rs
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
use std::collections::HashMap;
use aya::{
programs::{
tc::{SchedClassifierLink, TcAttachOptions},
LinkOrder, ProgramId, SchedClassifier, TcAttachType,
},
util::KernelVersion,
Ebpf, EbpfLoader,
};
use test_log::test;
use crate::utils::NetNsGuard;
#[test(tokio::test)]
async fn tcx() {
let kernel_version = KernelVersion::current().unwrap();
if kernel_version < KernelVersion::new(6, 6, 0) {
eprintln!("skipping tcx_attach test on kernel {kernel_version:?}");
return;
}
let _netns = NetNsGuard::new();
// We need a dedicated `Ebpf` instance for each program that we load
// since TCX does not allow the same program ID to be attached multiple
// times to the same interface/direction.
let mut attached_programs: HashMap<&str, (Ebpf, SchedClassifierLink)> = HashMap::new();
macro_rules! attach_program_with_linkorder {
($name:literal,$link_order:expr) => {{
let mut loader = EbpfLoader::new().load(crate::TCX).unwrap();
let program: &mut SchedClassifier =
loader.program_mut("tcx_next").unwrap().try_into().unwrap();
program.load().unwrap();
let options = TcAttachOptions::TcxOrder($link_order);
let link_id = program
.attach_with_options("lo", TcAttachType::Ingress, options)
.unwrap();
let link = program.take_link(link_id).unwrap();
attached_programs.insert($name, (loader, link));
}};
}
// TODO: Assert in position 4 at the end of the test.
attach_program_with_linkorder!("default", LinkOrder::default());
// TODO: Assert in position 1 at the end of the test.
attach_program_with_linkorder!("first", LinkOrder::first());
// TODO: Assert in position 7 at the end of the test.
attach_program_with_linkorder!("last", LinkOrder::last());
// TODO: Assert in position 6 at the end of the test.
attach_program_with_linkorder!(
"before_last",
LinkOrder::before_link(&attached_programs.get("last").unwrap().1).unwrap()
);
// TODO: Assert in position 8 at the end of the test.
attach_program_with_linkorder!(
"after_last",
LinkOrder::after_link(&attached_programs.get("last").unwrap().1).unwrap()
);
// TODO: Assert in position 3 at the end of the test.
attach_program_with_linkorder!(
"before_default",
LinkOrder::before_program(
TryInto::<&SchedClassifier>::try_into(
attached_programs
.get("default")
.unwrap()
.0
.program("tcx_next")
.unwrap(),
)
.unwrap()
)
.unwrap()
);
// TODO: Assert in position 5 at the end of the test.
attach_program_with_linkorder!(
"after_default",
LinkOrder::after_program(
TryInto::<&SchedClassifier>::try_into(
attached_programs
.get("default")
.unwrap()
.0
.program("tcx_next")
.unwrap(),
)
.unwrap()
)
.unwrap()
);
// TODO: Assert in position 0 at the end of the test.
attach_program_with_linkorder!(
"before_first",
LinkOrder::before_program_id(unsafe {
ProgramId::new(
TryInto::<&SchedClassifier>::try_into(
attached_programs
.get("first")
.unwrap()
.0
.program("tcx_next")
.unwrap(),
)
.unwrap()
.info()
.unwrap()
.id(),
)
})
);
// TODO: Assert in position 2 at the end of the test.
attach_program_with_linkorder!(
"after_first",
LinkOrder::after_program_id(unsafe {
ProgramId::new(
TryInto::<&SchedClassifier>::try_into(
attached_programs
.get("first")
.unwrap()
.0
.program("tcx_next")
.unwrap(),
)
.unwrap()
.info()
.unwrap()
.id(),
)
})
);
// TODO: Add code here to automatically verify the order after the API based
// on the BPF_PROG_QUERY syscall is implemented.
}