4
0

tcx.rs 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. use aya::{
  2. programs::{tc::TcAttachOptions, LinkOrder, ProgramId, SchedClassifier, TcAttachType},
  3. util::KernelVersion,
  4. Ebpf,
  5. };
  6. use test_log::test;
  7. use crate::utils::NetNsGuard;
  8. #[test]
  9. fn tcx() {
  10. let kernel_version = KernelVersion::current().unwrap();
  11. if kernel_version < KernelVersion::new(6, 6, 0) {
  12. eprintln!("skipping tcx_attach test on kernel {kernel_version:?}");
  13. return;
  14. }
  15. let _netns = NetNsGuard::new();
  16. // We need a dedicated `Ebpf` instance for each program that we load
  17. // since TCX does not allow the same program ID to be attached multiple
  18. // times to the same interface/direction.
  19. //
  20. // Variables declared within this macro are within a closure scope to avoid
  21. // variable name conflicts.
  22. //
  23. // Yields a tuple of the `Ebpf` which must remain in scope for the duration
  24. // of the test, and the link ID of the attached program.
  25. macro_rules! attach_program_with_link_order_inner {
  26. ($program_name:ident, $link_order:expr) => {
  27. let mut ebpf = Ebpf::load(crate::TCX).unwrap();
  28. let $program_name: &mut SchedClassifier =
  29. ebpf.program_mut("tcx_next").unwrap().try_into().unwrap();
  30. $program_name.load().unwrap();
  31. };
  32. }
  33. macro_rules! attach_program_with_link_order {
  34. ($program_name:ident, $link_order:expr) => {
  35. attach_program_with_link_order_inner!($program_name, $link_order);
  36. $program_name
  37. .attach_with_options(
  38. "lo",
  39. TcAttachType::Ingress,
  40. TcAttachOptions::TcxOrder($link_order),
  41. )
  42. .unwrap();
  43. };
  44. ($program_name:ident, $link_id_name:ident, $link_order:expr) => {
  45. attach_program_with_link_order_inner!($program_name, $link_order);
  46. let $link_id_name = $program_name
  47. .attach_with_options(
  48. "lo",
  49. TcAttachType::Ingress,
  50. TcAttachOptions::TcxOrder($link_order),
  51. )
  52. .unwrap();
  53. };
  54. }
  55. attach_program_with_link_order!(default, LinkOrder::default());
  56. attach_program_with_link_order!(first, LinkOrder::first());
  57. attach_program_with_link_order!(last, last_link_id, LinkOrder::last());
  58. let last_link = last.take_link(last_link_id).unwrap();
  59. attach_program_with_link_order!(before_last, LinkOrder::before_link(&last_link).unwrap());
  60. attach_program_with_link_order!(after_last, LinkOrder::after_link(&last_link).unwrap());
  61. attach_program_with_link_order!(before_default, LinkOrder::before_program(default).unwrap());
  62. attach_program_with_link_order!(after_default, LinkOrder::after_program(default).unwrap());
  63. attach_program_with_link_order!(
  64. before_first,
  65. LinkOrder::before_program_id(unsafe { ProgramId::new(first.info().unwrap().id()) })
  66. );
  67. attach_program_with_link_order!(
  68. after_first,
  69. LinkOrder::after_program_id(unsafe { ProgramId::new(first.info().unwrap().id()) })
  70. );
  71. let expected_order = [
  72. before_first,
  73. first,
  74. after_first,
  75. before_default,
  76. default,
  77. after_default,
  78. before_last,
  79. last,
  80. after_last,
  81. ]
  82. .iter()
  83. .map(|program| program.info().unwrap().id())
  84. .collect::<Vec<_>>();
  85. let (revision, got_order) = SchedClassifier::query_tcx("lo", TcAttachType::Ingress).unwrap();
  86. assert_eq!(revision, (expected_order.len() + 1) as u64);
  87. assert_eq!(
  88. got_order.iter().map(|p| p.id()).collect::<Vec<_>>(),
  89. expected_order
  90. );
  91. }