Add support for lirc programs

Signed-off-by: Sean Young <sean@mess.org>
pull/3/head
Sean Young 3 years ago
parent 304abfbfeb
commit b49ba69d09

@ -19,8 +19,9 @@ use crate::{
Object, ParseError, ProgramKind,
},
programs::{
CgroupSkb, CgroupSkbAttachType, KProbe, ProbeKind, Program, ProgramData, ProgramError,
SchedClassifier, SkMsg, SkSkb, SkSkbKind, SockOps, SocketFilter, TracePoint, UProbe, Xdp,
CgroupSkb, CgroupSkbAttachType, KProbe, LircMode2, ProbeKind, Program, ProgramData,
ProgramError, SchedClassifier, SkMsg, SkSkb, SkSkbKind, SockOps, SocketFilter, TracePoint,
UProbe, Xdp,
},
sys::bpf_map_update_elem_ptr,
util::{possible_cpus, POSSIBLE_CPUS},
@ -195,6 +196,7 @@ impl Bpf {
data,
expected_attach_type: Some(CgroupSkbAttachType::Egress),
}),
ProgramKind::LircMode2 => Program::LircMode2(LircMode2 { data }),
};
(name, program)

@ -80,6 +80,7 @@ pub enum ProgramKind {
SchedClassifier,
CgroupSkbIngress,
CgroupSkbEgress,
LircMode2,
}
impl FromStr for ProgramKind {
@ -102,6 +103,7 @@ impl FromStr for ProgramKind {
"classifier" => SchedClassifier,
"cgroup_skb/ingress" => CgroupSkbIngress,
"cgroup_skb/egress" => CgroupSkbEgress,
"lirc_mode2" => LircMode2,
_ => {
return Err(ParseError::InvalidProgramKind {
kind: kind.to_string(),
@ -302,7 +304,8 @@ impl Object {
| &[ty @ "classifier", name]
| &[ty @ "cgroup_skb/ingress", name]
| &[ty @ "cgroup_skb/egress", name]
| &[ty @ "cgroup/skb", name] => {
| &[ty @ "cgroup/skb", name]
| &[ty @ "lirc_mode2", name] => {
self.programs
.insert(name.to_string(), self.parse_program(&section, ty, name)?);
if !section.relocations.is_empty() {

@ -0,0 +1,101 @@
use std::os::unix::prelude::{AsRawFd, RawFd};
use crate::{
generated::{bpf_attach_type::BPF_LIRC_MODE2, bpf_prog_type::BPF_PROG_TYPE_LIRC_MODE2},
programs::{load_program, Link, LinkRef, ProgramData, ProgramError},
sys::{bpf_prog_attach, bpf_prog_detach},
};
use libc::{close, dup};
/// A program used to decode IR into key events for a lirc device.
///
/// [`LircMode2`] programs can be used to inspect infrared pulses, spaces,
/// and timeouts received by a lirc IR receiver.
///
/// [lirc]: https://www.kernel.org/doc/html/latest/userspace-api/media/rc/lirc-dev.html
///
/// # Examples
///
/// ```no_run
/// use std::fs::File;
/// use std::convert::TryInto;
/// use aya::programs::LircMode2;
///
/// let file = File::open("/dev/lirc0").unwrap();
/// let mut bpf = Bpf::load_file("imon_rsc.o").unwrap();
/// let decoder: &mut LircMode2 = bpf.program_mut("imon_rsc").unwrap().try_into().unwrap();
/// decoder.load().unwrap();
/// decoder.attach(file).unwrap();
/// # Ok::<(), Error>(())
/// ```
#[derive(Debug)]
#[doc(alias = "BPF_PROG_TYPE_LIRC_MODE2")]
pub struct LircMode2 {
pub(crate) data: ProgramData,
}
impl LircMode2 {
/// Loads the program inside the kernel.
///
/// See also [`Program::load`](crate::programs::Program::load).
pub fn load(&mut self) -> Result<(), ProgramError> {
load_program(BPF_PROG_TYPE_LIRC_MODE2, &mut self.data)
}
/// Returns the name of the program.
pub fn name(&self) -> String {
self.data.name.to_string()
}
/// Attaches the program to the given lirc device.
pub fn attach<T: AsRawFd>(&mut self, lircdev: T) -> Result<LinkRef, ProgramError> {
let prog_fd = self.data.fd_or_err()?;
let lircdev_fd = lircdev.as_raw_fd();
bpf_prog_attach(prog_fd, lircdev_fd, BPF_LIRC_MODE2).map_err(|(_, io_error)| {
ProgramError::SyscallError {
call: "bpf_prog_attach".to_owned(),
io_error,
}
})?;
Ok(self.data.link(LircLink::new(prog_fd, lircdev_fd)))
}
}
#[derive(Debug)]
struct LircLink {
prog_fd: Option<RawFd>,
target_fd: Option<RawFd>,
}
impl LircLink {
pub(crate) fn new(prog_fd: RawFd, target_fd: RawFd) -> LircLink {
LircLink {
prog_fd: Some(prog_fd),
target_fd: Some(unsafe { dup(target_fd) }),
}
}
}
impl Link for LircLink {
fn detach(&mut self) -> Result<(), ProgramError> {
if let Some(prog_fd) = self.prog_fd.take() {
let target_fd = self.target_fd.take().unwrap();
let _ = bpf_prog_detach(prog_fd, target_fd, BPF_LIRC_MODE2);
unsafe { close(target_fd) };
Ok(())
} else {
Err(ProgramError::AlreadyDetached)
}
}
}
impl Drop for LircLink {
fn drop(&mut self) {
if let Some(target_fd) = self.target_fd.take() {
unsafe { close(target_fd) };
}
}
}

@ -38,6 +38,7 @@
//! [`maps`]: crate::maps
mod cgroup_skb;
mod kprobe;
mod lirc_mode2;
mod perf_attach;
mod probe;
mod sk_msg;
@ -55,6 +56,7 @@ use thiserror::Error;
pub use cgroup_skb::{CgroupSkb, CgroupSkbAttachType};
pub use kprobe::{KProbe, KProbeError};
pub use lirc_mode2::LircMode2;
use perf_attach::*;
pub use probe::ProbeKind;
pub use sk_msg::SkMsg;
@ -170,6 +172,7 @@ pub enum Program {
SockOps(SockOps),
SchedClassifier(SchedClassifier),
CgroupSkb(CgroupSkb),
LircMode2(LircMode2),
}
impl Program {
@ -201,6 +204,7 @@ impl Program {
Program::SockOps(_) => BPF_PROG_TYPE_SOCK_OPS,
Program::SchedClassifier(_) => BPF_PROG_TYPE_SCHED_CLS,
Program::CgroupSkb(_) => BPF_PROG_TYPE_CGROUP_SKB,
Program::LircMode2(_) => BPF_PROG_TYPE_LIRC_MODE2,
}
}
@ -221,6 +225,7 @@ impl Program {
Program::SockOps(p) => &p.data,
Program::SchedClassifier(p) => &p.data,
Program::CgroupSkb(p) => &p.data,
Program::LircMode2(p) => &p.data,
}
}
@ -236,6 +241,7 @@ impl Program {
Program::SockOps(p) => &mut p.data,
Program::SchedClassifier(p) => &mut p.data,
Program::CgroupSkb(p) => &mut p.data,
Program::LircMode2(p) => &mut p.data,
}
}
}
@ -482,7 +488,8 @@ impl_program_fd!(
SkMsg,
SkSkb,
SchedClassifier,
CgroupSkb
CgroupSkb,
LircMode2
);
macro_rules! impl_try_from_program {
@ -523,5 +530,6 @@ impl_try_from_program!(
SkSkb,
SockOps,
SchedClassifier,
CgroupSkb
CgroupSkb,
LircMode2
);

Loading…
Cancel
Save