diff --git a/aya/src/programs/sock_ops.rs b/aya/src/programs/sock_ops.rs index 3f068c54..60f4e08f 100644 --- a/aya/src/programs/sock_ops.rs +++ b/aya/src/programs/sock_ops.rs @@ -4,9 +4,11 @@ use std::os::fd::AsFd; use crate::{ generated::{bpf_attach_type::BPF_CGROUP_SOCK_OPS, bpf_prog_type::BPF_PROG_TYPE_SOCK_OPS}, programs::{ - define_link_wrapper, load_program, CgroupAttachMode, ProgAttachLink, ProgAttachLinkId, + define_link_wrapper, load_program, CgroupAttachMode, FdLink, Link, ProgAttachLink, ProgramData, ProgramError, }, + sys::{bpf_link_create, LinkTarget, SyscallError}, + util::KernelVersion, }; /// A program used to work with sockets. @@ -63,10 +65,31 @@ impl SockOps { mode: CgroupAttachMode, ) -> Result { let prog_fd = self.fd()?; + let prog_fd = prog_fd.as_fd(); + let cgroup_fd = cgroup.as_fd(); + let attach_type = BPF_CGROUP_SOCK_OPS; + if KernelVersion::current().unwrap() >= KernelVersion::new(5, 7, 0) { + let link_fd = bpf_link_create( + prog_fd, + LinkTarget::Fd(cgroup_fd), + attach_type, + None, + mode.into(), + ) + .map_err(|(_, io_error)| SyscallError { + call: "bpf_link_create", + io_error, + })?; + self.data + .links + .insert(SockOpsLink::new(SockOpsLinkInner::Fd(FdLink::new(link_fd)))) + } else { + let link = ProgAttachLink::attach(prog_fd, cgroup_fd, attach_type, mode)?; - let link = - ProgAttachLink::attach(prog_fd.as_fd(), cgroup.as_fd(), BPF_CGROUP_SOCK_OPS, mode)?; - self.data.links.insert(SockOpsLink::new(link)) + self.data + .links + .insert(SockOpsLink::new(SockOpsLinkInner::ProgAttach(link))) + } } /// Detaches the program. @@ -85,11 +108,41 @@ impl SockOps { } } +#[derive(Debug, Hash, Eq, PartialEq)] +enum SockOpsLinkIdInner { + Fd(::Id), + ProgAttach(::Id), +} + +#[derive(Debug)] +enum SockOpsLinkInner { + Fd(FdLink), + ProgAttach(ProgAttachLink), +} + +impl Link for SockOpsLinkInner { + type Id = SockOpsLinkIdInner; + + fn id(&self) -> Self::Id { + match self { + Self::Fd(fd) => SockOpsLinkIdInner::Fd(fd.id()), + Self::ProgAttach(p) => SockOpsLinkIdInner::ProgAttach(p.id()), + } + } + + fn detach(self) -> Result<(), ProgramError> { + match self { + Self::Fd(fd) => fd.detach(), + Self::ProgAttach(p) => p.detach(), + } + } +} + define_link_wrapper!( /// The link used by [SockOps] programs. SockOpsLink, /// The type returned by [SockOps::attach]. Can be passed to [SockOps::detach]. SockOpsLinkId, - ProgAttachLink, - ProgAttachLinkId + SockOpsLinkInner, + SockOpsLinkIdInner ); diff --git a/xtask/public-api/aya.txt b/xtask/public-api/aya.txt index 3422ee2a..c9ff22f4 100644 --- a/xtask/public-api/aya.txt +++ b/xtask/public-api/aya.txt @@ -4048,14 +4048,10 @@ impl core::convert::From for aya::programs pub fn aya::programs::sk_msg::SkMsgLink::from(b: aya::programs::links::ProgAttachLink) -> aya::programs::sk_msg::SkMsgLink impl core::convert::From for aya::programs::sk_skb::SkSkbLink pub fn aya::programs::sk_skb::SkSkbLink::from(b: aya::programs::links::ProgAttachLink) -> aya::programs::sk_skb::SkSkbLink -impl core::convert::From for aya::programs::sock_ops::SockOpsLink -pub fn aya::programs::sock_ops::SockOpsLink::from(b: aya::programs::links::ProgAttachLink) -> aya::programs::sock_ops::SockOpsLink impl core::convert::From for aya::programs::links::ProgAttachLink pub fn aya::programs::links::ProgAttachLink::from(w: aya::programs::sk_msg::SkMsgLink) -> aya::programs::links::ProgAttachLink impl core::convert::From for aya::programs::links::ProgAttachLink pub fn aya::programs::links::ProgAttachLink::from(w: aya::programs::sk_skb::SkSkbLink) -> aya::programs::links::ProgAttachLink -impl core::convert::From for aya::programs::links::ProgAttachLink -pub fn aya::programs::links::ProgAttachLink::from(w: aya::programs::sock_ops::SockOpsLink) -> aya::programs::links::ProgAttachLink impl core::fmt::Debug for aya::programs::links::ProgAttachLink pub fn aya::programs::links::ProgAttachLink::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result impl core::marker::Freeze for aya::programs::links::ProgAttachLink @@ -5343,10 +5339,6 @@ impl aya::programs::links::Link for aya::programs::sock_ops::SockOpsLink pub type aya::programs::sock_ops::SockOpsLink::Id = aya::programs::sock_ops::SockOpsLinkId pub fn aya::programs::sock_ops::SockOpsLink::detach(self) -> core::result::Result<(), aya::programs::ProgramError> pub fn aya::programs::sock_ops::SockOpsLink::id(&self) -> Self::Id -impl core::convert::From for aya::programs::sock_ops::SockOpsLink -pub fn aya::programs::sock_ops::SockOpsLink::from(b: aya::programs::links::ProgAttachLink) -> aya::programs::sock_ops::SockOpsLink -impl core::convert::From for aya::programs::links::ProgAttachLink -pub fn aya::programs::links::ProgAttachLink::from(w: aya::programs::sock_ops::SockOpsLink) -> aya::programs::links::ProgAttachLink impl core::fmt::Debug for aya::programs::sock_ops::SockOpsLink pub fn aya::programs::sock_ops::SockOpsLink::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result impl core::ops::drop::Drop for aya::programs::sock_ops::SockOpsLink