cgroup_sockopt.rs 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. use std::borrow::Cow;
  2. use proc_macro2::TokenStream;
  3. use proc_macro2_diagnostics::{Diagnostic, SpanDiagnosticExt as _};
  4. use quote::quote;
  5. use syn::{spanned::Spanned as _, Ident, ItemFn};
  6. pub(crate) struct CgroupSockopt {
  7. item: ItemFn,
  8. attach_type: Ident,
  9. }
  10. impl CgroupSockopt {
  11. pub(crate) fn parse(
  12. attrs: TokenStream,
  13. item: TokenStream,
  14. ) -> Result<CgroupSockopt, Diagnostic> {
  15. if attrs.is_empty() {
  16. return Err(attrs.span().error("missing attach type"));
  17. }
  18. let item = syn::parse2(item)?;
  19. let attach_type: Ident = syn::parse2(attrs)?;
  20. if attach_type != "getsockopt" && attach_type != "setsockopt" {
  21. return Err(attach_type.span().error("invalid attach type"));
  22. }
  23. Ok(Self { item, attach_type })
  24. }
  25. pub(crate) fn expand(&self) -> TokenStream {
  26. let Self { item, attach_type } = self;
  27. let ItemFn {
  28. attrs: _,
  29. vis,
  30. sig,
  31. block: _,
  32. } = item;
  33. let section_name: Cow<'_, _> = format!("cgroup/{attach_type}").into();
  34. let fn_name = &sig.ident;
  35. quote! {
  36. #[no_mangle]
  37. #[link_section = #section_name]
  38. #vis fn #fn_name(ctx: *mut ::aya_ebpf::bindings::bpf_sockopt) -> i32 {
  39. return #fn_name(::aya_ebpf::programs::SockoptContext::new(ctx));
  40. #item
  41. }
  42. }
  43. }
  44. }
  45. #[cfg(test)]
  46. mod tests {
  47. use syn::parse_quote;
  48. use super::*;
  49. #[test]
  50. fn cgroup_sockopt_getsockopt() {
  51. let prog = CgroupSockopt::parse(
  52. parse_quote!(getsockopt),
  53. parse_quote!(
  54. fn foo(ctx: SockoptContext) -> i32 {
  55. 0
  56. }
  57. ),
  58. )
  59. .unwrap();
  60. let expanded = prog.expand();
  61. let expected = quote!(
  62. #[no_mangle]
  63. #[link_section = "cgroup/getsockopt"]
  64. fn foo(ctx: *mut ::aya_ebpf::bindings::bpf_sockopt) -> i32 {
  65. return foo(::aya_ebpf::programs::SockoptContext::new(ctx));
  66. fn foo(ctx: SockoptContext) -> i32 {
  67. 0
  68. }
  69. }
  70. );
  71. assert_eq!(expected.to_string(), expanded.to_string());
  72. }
  73. #[test]
  74. fn cgroup_sockopt_setsockopt() {
  75. let prog = CgroupSockopt::parse(
  76. parse_quote!(setsockopt),
  77. parse_quote!(
  78. fn foo(ctx: SockoptContext) -> i32 {
  79. 0
  80. }
  81. ),
  82. )
  83. .unwrap();
  84. let expanded = prog.expand();
  85. let expected = quote!(
  86. #[no_mangle]
  87. #[link_section = "cgroup/setsockopt"]
  88. fn foo(ctx: *mut ::aya_ebpf::bindings::bpf_sockopt) -> i32 {
  89. return foo(::aya_ebpf::programs::SockoptContext::new(ctx));
  90. fn foo(ctx: SockoptContext) -> i32 {
  91. 0
  92. }
  93. }
  94. );
  95. assert_eq!(expected.to_string(), expanded.to_string());
  96. }
  97. }