aya: fix tc name limit

The buffer for attributes should be sized to hold at least 256 bytes, based on `CLS_BPF_NAME_LEN = 256` from the kernel:
https://github.com/torvalds/linux/blob/02aee814/net/sched/cls_bpf.c#L28

This commit also includes integration tests with an eBPF program of type classifier with a 256-byte-long name.

Fixes: #610

integration-ebpf: fix Cargo.toml formatting
reviewable/pr728/r3
Mohammad Javad Pooladkhay 2 years ago
parent 761e4ddbe3
commit 4859705fbc

@ -277,7 +277,10 @@ struct Request {
struct TcRequest { struct TcRequest {
header: nlmsghdr, header: nlmsghdr,
tc_info: tcmsg, tc_info: tcmsg,
attrs: [u8; 64], // The buffer for attributes should be sized to hold at least 256 bytes,
// based on `CLS_BPF_NAME_LEN = 256` from the kernel:
// https://github.com/torvalds/linux/blob/02aee814/net/sched/cls_bpf.c#L28
attrs: [u8; 512],
} }
struct NetlinkSocket { struct NetlinkSocket {

@ -42,3 +42,7 @@ path = "src/bpf_probe_read.rs"
[[bin]] [[bin]]
name = "two_progs" name = "two_progs"
path = "src/two_progs.rs" path = "src/two_progs.rs"
[[bin]]
name = "tc_name_limit"
path = "src/tc_name_limit.rs"

@ -0,0 +1,28 @@
#![no_std]
#![no_main]
use aya_bpf::{macros::classifier, programs::TcContext};
// This macro generates a function with arbitrary name
macro_rules! generate_ebpf_function {
($fn_name:ident) => {
#[classifier]
pub fn $fn_name(_ctx: TcContext) -> i32 {
0
}
};
}
/*
Generating a function with a 256-byte-long name (all 'a's) to be used as
the ebpf program. This name must match the name passed to userspace side.
256 is the maximum length allowed by the kernel:
https://github.com/torvalds/linux/blob/02aee814/net/sched/cls_bpf.c#L28
*/
generate_ebpf_function!(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa);
#[cfg(not(test))]
#[panic_handler]
fn panic(_info: &core::panic::PanicInfo) -> ! {
loop {}
}

@ -12,6 +12,8 @@ pub const TEXT_64_64_RELOC: &[u8] =
pub const LOG: &[u8] = include_bytes_aligned!(concat!(env!("OUT_DIR"), "/log")); pub const LOG: &[u8] = include_bytes_aligned!(concat!(env!("OUT_DIR"), "/log"));
pub const MAP_TEST: &[u8] = include_bytes_aligned!(concat!(env!("OUT_DIR"), "/map_test")); pub const MAP_TEST: &[u8] = include_bytes_aligned!(concat!(env!("OUT_DIR"), "/map_test"));
pub const NAME_TEST: &[u8] = include_bytes_aligned!(concat!(env!("OUT_DIR"), "/name_test")); pub const NAME_TEST: &[u8] = include_bytes_aligned!(concat!(env!("OUT_DIR"), "/name_test"));
pub const TC_NAME_LIMIT_TEST: &[u8] =
include_bytes_aligned!(concat!(env!("OUT_DIR"), "/tc_name_limit"));
pub const PASS: &[u8] = include_bytes_aligned!(concat!(env!("OUT_DIR"), "/pass")); pub const PASS: &[u8] = include_bytes_aligned!(concat!(env!("OUT_DIR"), "/pass"));
pub const TEST: &[u8] = include_bytes_aligned!(concat!(env!("OUT_DIR"), "/test")); pub const TEST: &[u8] = include_bytes_aligned!(concat!(env!("OUT_DIR"), "/test"));
pub const RELOCATIONS: &[u8] = include_bytes_aligned!(concat!(env!("OUT_DIR"), "/relocations")); pub const RELOCATIONS: &[u8] = include_bytes_aligned!(concat!(env!("OUT_DIR"), "/relocations"));

@ -4,7 +4,9 @@ use aya::{
maps::Array, maps::Array,
programs::{ programs::{
links::{FdLink, PinnedLink}, links::{FdLink, PinnedLink},
loaded_links, loaded_programs, KProbe, TracePoint, UProbe, Xdp, XdpFlags, loaded_links, loaded_programs,
tc::qdisc_add_clsact,
KProbe, SchedClassifier, TcAttachType, TracePoint, UProbe, Xdp, XdpFlags,
}, },
util::KernelVersion, util::KernelVersion,
Bpf, Bpf,
@ -13,6 +15,27 @@ use aya::{
const MAX_RETRIES: usize = 100; const MAX_RETRIES: usize = 100;
const RETRY_DURATION: time::Duration = time::Duration::from_millis(10); const RETRY_DURATION: time::Duration = time::Duration::from_millis(10);
#[test]
fn tc_name_limit() {
let _ = qdisc_add_clsact("lo");
let mut bpf = Bpf::load(crate::TC_NAME_LIMIT_TEST).unwrap();
// This magic number (256) is derived from the fact that the kernel
// permits names with a maximum length of 256 bytes:
// https://github.com/torvalds/linux/blob/02aee814/net/sched/cls_bpf.c#L28
// In this case, the name is 256 'a's
let long_name = "a".repeat(256);
let program: &mut SchedClassifier = bpf
.program_mut(long_name.as_str())
.unwrap()
.try_into()
.unwrap();
program.load().unwrap();
program.attach("lo", TcAttachType::Ingress).unwrap();
}
#[test] #[test]
fn long_name() { fn long_name() {
let mut bpf = Bpf::load(crate::NAME_TEST).unwrap(); let mut bpf = Bpf::load(crate::NAME_TEST).unwrap();

Loading…
Cancel
Save