Merge pull request #3 from aya-rs/skel
Use cargo-generate conditionals to provide skeletons for all supported program typespull/9/head
commit
566934ccb6
@ -0,0 +1,54 @@
|
|||||||
|
name: CI
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
|
||||||
|
env:
|
||||||
|
CARGO_TERM_COLOR: always
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
program:
|
||||||
|
- kprobe
|
||||||
|
- kretprobe
|
||||||
|
- uprobe
|
||||||
|
- uretprobe
|
||||||
|
- sock_ops
|
||||||
|
- sk_msg
|
||||||
|
- xdp
|
||||||
|
- classifier
|
||||||
|
- cgroup_skb
|
||||||
|
- tracepoint
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Install latest stable
|
||||||
|
uses: actions-rs/toolchain@v1
|
||||||
|
with:
|
||||||
|
toolchain: stable
|
||||||
|
|
||||||
|
- name: Install latest nightly
|
||||||
|
uses: actions-rs/toolchain@v1
|
||||||
|
with:
|
||||||
|
toolchain: nightly
|
||||||
|
components: rust-src
|
||||||
|
|
||||||
|
- name: Install bpf-linker
|
||||||
|
run: cargo +nightly install bpf-linker
|
||||||
|
|
||||||
|
- name: Install Cargo Generate
|
||||||
|
run: cargo install --git https://github.com/cargo-generate/cargo-generate
|
||||||
|
|
||||||
|
- name: Run tests
|
||||||
|
run: ./test.sh ${{ github.workspace }} ${{ matrix.program }}
|
@ -0,0 +1,41 @@
|
|||||||
|
[template]
|
||||||
|
cargo_generate_version = ">=0.9.0"
|
||||||
|
ignore = [".github", "test.sh"]
|
||||||
|
|
||||||
|
[placeholders.program_type]
|
||||||
|
type = "string"
|
||||||
|
prompt = "Which type of eBPF program?"
|
||||||
|
choices = ["kprobe", "kretprobe", "uprobe", "uretprobe", "sock_ops", "sk_msg", "xdp", "classifier", "cgroup_skb", "tracepoint"]
|
||||||
|
default = "xdp"
|
||||||
|
|
||||||
|
[conditional.'program_type == "kprobe" || program_type == "kretprobe"'.placeholders.kprobe]
|
||||||
|
type = "string"
|
||||||
|
prompt = "Where to attach the (k|kret)probe? (e.g try_to_wake_up)"
|
||||||
|
|
||||||
|
[conditional.'program_type == "uprobe" || program_type == "uretprobe"'.placeholders.uprobe_target]
|
||||||
|
type = "string"
|
||||||
|
prompt = "Target to attach the (u|uret)probe? (e.g libc)"
|
||||||
|
|
||||||
|
[conditional.'program_type == "uprobe" || program_type == "uretprobe"'.placeholders.uprobe_fn_name]
|
||||||
|
type = "string"
|
||||||
|
prompt = "Function name to attach the (u|uret)probe? (e.g getaddrinfo)"
|
||||||
|
|
||||||
|
[conditional.'program_type == "cgroup_skb" || program_type == "classifier"'.placeholders.direction]
|
||||||
|
type = "string"
|
||||||
|
prompt = "Attach direction?"
|
||||||
|
choices = [ "Ingress", "Egress" ]
|
||||||
|
|
||||||
|
[conditional.'program_type == "sk_msg"'.placeholders.sock_map]
|
||||||
|
type = "string"
|
||||||
|
prompt = "Map Name (UPPER_CASE)?"
|
||||||
|
regex = "[A-Z_]+"
|
||||||
|
|
||||||
|
[conditional.'program_type == "tracepoint"'.placeholders.tracepoint_category]
|
||||||
|
type = "string"
|
||||||
|
prompt = "Which tracepoint category? (e.g sched, net etc...)"
|
||||||
|
regex = "[a-z]+"
|
||||||
|
|
||||||
|
[conditional.'program_type == "tracepoint"'.placeholders.tracepoint_name]
|
||||||
|
type = "string"
|
||||||
|
prompt = "Which tracepoint name? (e.g sched_switch, net_dev_queue)"
|
||||||
|
regex = "[a-z]+"
|
@ -0,0 +1,42 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -ex
|
||||||
|
|
||||||
|
TEMPLATE_DIR=$1
|
||||||
|
if [ -z "$TEMPLATE_DIR" ]; then echo "template dir required"; exit 1; fi
|
||||||
|
PROG_TYPE=$2
|
||||||
|
if [ -z "$PROG_TYPE" ]; then echo "program type required"; exit 1; fi
|
||||||
|
|
||||||
|
TMP_DIR=$(mktemp -d)
|
||||||
|
clean_up() {
|
||||||
|
rm -rf "${TMP_DIR}"
|
||||||
|
}
|
||||||
|
trap clean_up EXIT
|
||||||
|
|
||||||
|
pushd $TMP_DIR
|
||||||
|
case "$PROG_TYPE" in
|
||||||
|
"kprobe"|"kretprobe")
|
||||||
|
ADDITIONAL_ARGS="-d kprobe=test"
|
||||||
|
;;
|
||||||
|
"uprobe"|"uretprobe")
|
||||||
|
ADDITIONAL_ARGS="-d uprobe_target=testlib -d uprobe_fn_name=testfn"
|
||||||
|
;;
|
||||||
|
"tracepoint")
|
||||||
|
ADDITIONAL_ARGS="-d tracepoint_category=net -d tracepoint_name=net_dev_queue"
|
||||||
|
;;
|
||||||
|
"classifier"|"cgroup_skb")
|
||||||
|
ADDITIONAL_ARGS="-d direction=Ingress"
|
||||||
|
;;
|
||||||
|
"sk_msg")
|
||||||
|
ADDITIONAL_ARGS="-d sock_map=TEST"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
ADDITIONAL_ARGS=''
|
||||||
|
esac
|
||||||
|
|
||||||
|
cargo generate -v --path "${TEMPLATE_DIR}" -n test -d program_type="${PROG_TYPE}" ${ADDITIONAL_ARGS}
|
||||||
|
pushd test
|
||||||
|
cargo build
|
||||||
|
cargo xtask build-ebpf
|
||||||
|
popd
|
||||||
|
exit 0
|
@ -1 +1,15 @@
|
|||||||
#![no_std]
|
#![no_std]
|
||||||
|
{%- if program_type == "sk_msg" %}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct SockKey {
|
||||||
|
pub remote_ip4: u32,
|
||||||
|
pub local_ip4: u32,
|
||||||
|
pub remote_port: u32,
|
||||||
|
pub local_port: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "userspace")]
|
||||||
|
unsafe impl aya::Pod for SockKey {}
|
||||||
|
{%- endif -%}
|
@ -1,9 +1,106 @@
|
|||||||
|
use aya::Bpf;
|
||||||
|
{% case program_type -%}
|
||||||
|
{%- when "kprobe", "kretprobe" -%}
|
||||||
|
use aya::programs::KProbe;
|
||||||
|
{%- when "uprobe", "uretprobe" -%}
|
||||||
|
use aya::programs::UProbe;
|
||||||
|
{%- when "sock_ops" -%}
|
||||||
|
use aya::programs::SockOps;
|
||||||
|
{%- when "sk_msg" -%}
|
||||||
|
use aya::maps::{MapRefMut,SockHash};
|
||||||
|
use aya::programs::SkMsg;
|
||||||
|
use {{crate_name}}_common::SockKey;
|
||||||
|
{%- when "xdp" -%}
|
||||||
|
use aya::programs::{Xdp, XdpFlags};
|
||||||
|
{%- when "classifier" -%}
|
||||||
|
use aya::programs::{tc, SchedClassifier, TcAttachType};
|
||||||
|
{%- when "cgroup_skb" -%}
|
||||||
|
use aya::programs::{CgroupSkb, CgroupSkbAttachType};
|
||||||
|
{%- when "tracepoint" -%}
|
||||||
|
use aya::programs::TracePoint;
|
||||||
|
{%- endcase %}
|
||||||
|
use std::{
|
||||||
|
convert::{TryFrom,TryInto},
|
||||||
|
sync::Arc,
|
||||||
|
sync::atomic::{AtomicBool, Ordering},
|
||||||
|
};
|
||||||
|
use structopt::StructOpt;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
if let Err(e) = try_main() {
|
if let Err(e) = try_main() {
|
||||||
eprintln!("error: {:#}", e);
|
eprintln!("error: {:#}", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, StructOpt)]
|
||||||
|
struct Opt {
|
||||||
|
#[structopt(short, long)]
|
||||||
|
path: String,
|
||||||
|
{% if program_type == "xdp" or program_type == "classifier" -%}
|
||||||
|
#[structopt(short, long, default_value = "eth0")]
|
||||||
|
iface: String,
|
||||||
|
{%- elsif program_type == "sock_ops" or program_type == "cgroup_skb" -%}
|
||||||
|
#[structopt(short, long, default_value = "/sys/fs/cgroup/unified")]
|
||||||
|
cgroup_path: String,
|
||||||
|
{%- elsif program_type == "uprobe" or program_type == "uretprobe" -%}
|
||||||
|
#[structopt(short, long)]
|
||||||
|
pid: Option<i32>
|
||||||
|
{%- endif %}
|
||||||
|
}
|
||||||
|
|
||||||
fn try_main() -> Result<(), anyhow::Error> {
|
fn try_main() -> Result<(), anyhow::Error> {
|
||||||
|
let opt = Opt::from_args();
|
||||||
|
let mut bpf = Bpf::load_file(&opt.path)?;
|
||||||
|
{% case program_type -%}
|
||||||
|
{%- when "kprobe", "kretprobe" -%}
|
||||||
|
let program: &mut KProbe = bpf.program_mut("{{crate_name}}")?.try_into()?;
|
||||||
|
program.load()?;
|
||||||
|
program.attach("{{probe}}", 0)?;
|
||||||
|
{%- when "uprobe", "uretprobe" -%}
|
||||||
|
let program: &mut UProbe = bpf.program_mut("{{crate_name}}")?.try_into()?;
|
||||||
|
program.load()?;
|
||||||
|
program.attach(Some("{{uprobe_fn_name}}"), 0, "{{uprobe_target}}", opt.pid.try_into()?)?;
|
||||||
|
{%- when "sock_ops" -%}
|
||||||
|
let program: &mut SockOps = bpf.program_mut("{{crate_name}}")?.try_into()?;
|
||||||
|
let cgroup = std::fs::File::open(opt.cgroup_path)?;
|
||||||
|
program.load()?;
|
||||||
|
program.attach(cgroup)?;
|
||||||
|
{%- when "sk_msg" -%}
|
||||||
|
let sock_map = SockHash::<MapRefMut, SockKey>::try_from(bpf.map_mut("{{sock_map}}")?)?;
|
||||||
|
let prog: &mut SkMsg = bpf.program_mut("{{crate_name}}")?.try_into()?;
|
||||||
|
prog.load()?;
|
||||||
|
prog.attach(&sock_map)?;
|
||||||
|
// insert sockets to the map using sock_map.insert here, or from a sock_ops program
|
||||||
|
{%- when "xdp" -%}
|
||||||
|
let program: &mut Xdp = bpf.program_mut("{{crate_name}}")?.try_into()?;
|
||||||
|
program.load()?;
|
||||||
|
program.attach(&opt.iface, XdpFlags::default())?;
|
||||||
|
{%- when "classifier" -%}
|
||||||
|
tc::qdisc_add_clsact(&opt.iface)?;
|
||||||
|
let program: &mut SchedClassifier = bpf.program_mut("{{crate_name}}")?.try_into()?;
|
||||||
|
program.load()?;
|
||||||
|
program.attach(&opt.iface, TcAttachType::{{direction}})?;
|
||||||
|
{%- when "cgroup_skb" -%}
|
||||||
|
let program: &mut CgroupSkb = bpf.program_mut("{{crate_name}}")?.try_into()?;
|
||||||
|
let cgroup = std::fs::File::open(opt.cgroup_path)?;
|
||||||
|
program.load()?;
|
||||||
|
program.attach(cgroup, CgroupSkbAttachType::{{direction}})?;
|
||||||
|
{%- when "tracepoint" -%}
|
||||||
|
let program: &mut TracePoint = bpf.program_mut("{{crate_name}}")?.try_into()?;
|
||||||
|
program.load()?;
|
||||||
|
program.attach("{{tracepoint_category}}", "{{tracepoint_name}}")?;
|
||||||
|
{%- endcase %}
|
||||||
|
|
||||||
|
let running = Arc::new(AtomicBool::new(true));
|
||||||
|
let r = running.clone();
|
||||||
|
|
||||||
|
ctrlc::set_handler(move || {
|
||||||
|
r.store(false, Ordering::SeqCst);
|
||||||
|
}).expect("Error setting Ctrl-C handler");
|
||||||
|
|
||||||
|
println!("Waiting for Ctrl-C...");
|
||||||
|
while running.load(Ordering::SeqCst) {}
|
||||||
|
println!("Exiting...");
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
Loading…
Reference in New Issue