programs: add support for attaching and detaching TC programs

This change adds support for attaching TC programs directly from aya, without
having to use iproute2/tc.
pull/1/head
Arnabjyoti Kalita 3 years ago committed by GitHub
parent d085bdb89f
commit 6974d349e8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -4,8 +4,10 @@
#include <linux/if_link.h>
#include <linux/rtnetlink.h>
#include <asm-generic/socket.h>
#include <linux/pkt_sched.h>
#include <linux/pkt_cls.h>
/* workaround the fact that bindgen can't parse the IOC macros */
int AYA_PERF_EVENT_IOC_ENABLE = PERF_EVENT_IOC_ENABLE;
int AYA_PERF_EVENT_IOC_DISABLE = PERF_EVENT_IOC_DISABLE;
int AYA_PERF_EVENT_IOC_SET_BPF = PERF_EVENT_IOC_SET_BPF;
int AYA_PERF_EVENT_IOC_SET_BPF = PERF_EVENT_IOC_SET_BPF;

@ -136,6 +136,16 @@ pub const XDP_FLAGS_MODES: u32 = 14;
pub const XDP_FLAGS_MASK: u32 = 31;
pub const SO_ATTACH_BPF: u32 = 50;
pub const SO_DETACH_BPF: u32 = 27;
pub const TC_H_MAJ_MASK: u32 = 4294901760;
pub const TC_H_MIN_MASK: u32 = 65535;
pub const TC_H_UNSPEC: u32 = 0;
pub const TC_H_ROOT: u32 = 4294967295;
pub const TC_H_INGRESS: u32 = 4294967281;
pub const TC_H_CLSACT: u32 = 4294967281;
pub const TC_H_MIN_PRIORITY: u32 = 65504;
pub const TC_H_MIN_INGRESS: u32 = 65522;
pub const TC_H_MIN_EGRESS: u32 = 65523;
pub const TCA_BPF_FLAG_ACT_DIRECT: u32 = 1;
pub type __u8 = ::std::os::raw::c_uchar;
pub type __s16 = ::std::os::raw::c_short;
pub type __u16 = ::std::os::raw::c_ushort;
@ -600,6 +610,68 @@ pub struct bpf_attr__bindgen_ty_19 {
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct bpf_prog_info {
pub type_: __u32,
pub id: __u32,
pub tag: [__u8; 8usize],
pub jited_prog_len: __u32,
pub xlated_prog_len: __u32,
pub jited_prog_insns: __u64,
pub xlated_prog_insns: __u64,
pub load_time: __u64,
pub created_by_uid: __u32,
pub nr_map_ids: __u32,
pub map_ids: __u64,
pub name: [::std::os::raw::c_char; 16usize],
pub ifindex: __u32,
pub _bitfield_align_1: [u8; 0],
pub _bitfield_1: __BindgenBitfieldUnit<[u8; 4usize]>,
pub netns_dev: __u64,
pub netns_ino: __u64,
pub nr_jited_ksyms: __u32,
pub nr_jited_func_lens: __u32,
pub jited_ksyms: __u64,
pub jited_func_lens: __u64,
pub btf_id: __u32,
pub func_info_rec_size: __u32,
pub func_info: __u64,
pub nr_func_info: __u32,
pub nr_line_info: __u32,
pub line_info: __u64,
pub jited_line_info: __u64,
pub nr_jited_line_info: __u32,
pub line_info_rec_size: __u32,
pub jited_line_info_rec_size: __u32,
pub nr_prog_tags: __u32,
pub prog_tags: __u64,
pub run_time_ns: __u64,
pub run_cnt: __u64,
pub recursion_misses: __u64,
}
impl bpf_prog_info {
#[inline]
pub fn gpl_compatible(&self) -> __u32 {
unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u32) }
}
#[inline]
pub fn set_gpl_compatible(&mut self, val: __u32) {
unsafe {
let val: u32 = ::std::mem::transmute(val);
self._bitfield_1.set(0usize, 1u8, val as u64)
}
}
#[inline]
pub fn new_bitfield_1(gpl_compatible: __u32) -> __BindgenBitfieldUnit<[u8; 4usize]> {
let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 4usize]> = Default::default();
__bindgen_bitfield_unit.set(0usize, 1u8, {
let gpl_compatible: u32 = unsafe { ::std::mem::transmute(gpl_compatible) };
gpl_compatible as u64
});
__bindgen_bitfield_unit
}
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct btf_header {
pub magic: __u16,
pub version: __u8,
@ -689,7 +761,7 @@ pub enum perf_sw_ids {
PERF_COUNT_SW_BPF_OUTPUT = 10,
PERF_COUNT_SW_MAX = 11,
}
#[repr(u64)]
#[repr(u32)]
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub enum perf_event_sample_format {
PERF_SAMPLE_IP = 1,
@ -713,7 +785,6 @@ pub enum perf_event_sample_format {
PERF_SAMPLE_REGS_INTR = 262144,
PERF_SAMPLE_PHYS_ADDR = 524288,
PERF_SAMPLE_MAX = 1048576,
__PERF_SAMPLE_CALLCHAIN_EARLY = 9223372036854775808,
}
#[repr(C)]
#[derive(Copy, Clone)]
@ -724,7 +795,7 @@ pub struct perf_event_attr {
pub __bindgen_anon_1: perf_event_attr__bindgen_ty_1,
pub sample_type: __u64,
pub read_format: __u64,
pub _bitfield_align_1: [u32; 0],
pub _bitfield_align_1: [u64; 0],
pub _bitfield_1: __BindgenBitfieldUnit<[u8; 8usize]>,
pub __bindgen_anon_2: perf_event_attr__bindgen_ty_2,
pub bp_type: __u32,
@ -757,8 +828,6 @@ pub union perf_event_attr__bindgen_ty_2 {
#[derive(Copy, Clone)]
pub union perf_event_attr__bindgen_ty_3 {
pub bp_addr: __u64,
pub kprobe_func: __u64,
pub uprobe_path: __u64,
pub config1: __u64,
_bindgen_union_align: u64,
}
@ -766,8 +835,6 @@ pub union perf_event_attr__bindgen_ty_3 {
#[derive(Copy, Clone)]
pub union perf_event_attr__bindgen_ty_4 {
pub bp_len: __u64,
pub kprobe_addr: __u64,
pub probe_offset: __u64,
pub config2: __u64,
_bindgen_union_align: u64,
}
@ -1081,47 +1148,14 @@ impl perf_event_attr {
}
}
#[inline]
pub fn ksymbol(&self) -> __u64 {
unsafe { ::std::mem::transmute(self._bitfield_1.get(29usize, 1u8) as u64) }
}
#[inline]
pub fn set_ksymbol(&mut self, val: __u64) {
unsafe {
let val: u64 = ::std::mem::transmute(val);
self._bitfield_1.set(29usize, 1u8, val as u64)
}
}
#[inline]
pub fn bpf_event(&self) -> __u64 {
unsafe { ::std::mem::transmute(self._bitfield_1.get(30usize, 1u8) as u64) }
}
#[inline]
pub fn set_bpf_event(&mut self, val: __u64) {
unsafe {
let val: u64 = ::std::mem::transmute(val);
self._bitfield_1.set(30usize, 1u8, val as u64)
}
}
#[inline]
pub fn aux_output(&self) -> __u64 {
unsafe { ::std::mem::transmute(self._bitfield_1.get(31usize, 1u8) as u64) }
}
#[inline]
pub fn set_aux_output(&mut self, val: __u64) {
unsafe {
let val: u64 = ::std::mem::transmute(val);
self._bitfield_1.set(31usize, 1u8, val as u64)
}
}
#[inline]
pub fn __reserved_1(&self) -> __u64 {
unsafe { ::std::mem::transmute(self._bitfield_1.get(32usize, 32u8) as u64) }
unsafe { ::std::mem::transmute(self._bitfield_1.get(29usize, 35u8) as u64) }
}
#[inline]
pub fn set___reserved_1(&mut self, val: __u64) {
unsafe {
let val: u64 = ::std::mem::transmute(val);
self._bitfield_1.set(32usize, 32u8, val as u64)
self._bitfield_1.set(29usize, 35u8, val as u64)
}
}
#[inline]
@ -1154,9 +1188,6 @@ impl perf_event_attr {
context_switch: __u64,
write_backward: __u64,
namespaces: __u64,
ksymbol: __u64,
bpf_event: __u64,
aux_output: __u64,
__reserved_1: __u64,
) -> __BindgenBitfieldUnit<[u8; 8usize]> {
let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 8usize]> = Default::default();
@ -1274,19 +1305,7 @@ impl perf_event_attr {
let namespaces: u64 = unsafe { ::std::mem::transmute(namespaces) };
namespaces as u64
});
__bindgen_bitfield_unit.set(29usize, 1u8, {
let ksymbol: u64 = unsafe { ::std::mem::transmute(ksymbol) };
ksymbol as u64
});
__bindgen_bitfield_unit.set(30usize, 1u8, {
let bpf_event: u64 = unsafe { ::std::mem::transmute(bpf_event) };
bpf_event as u64
});
__bindgen_bitfield_unit.set(31usize, 1u8, {
let aux_output: u64 = unsafe { ::std::mem::transmute(aux_output) };
aux_output as u64
});
__bindgen_bitfield_unit.set(32usize, 32u8, {
__bindgen_bitfield_unit.set(29usize, 35u8, {
let __reserved_1: u64 = unsafe { ::std::mem::transmute(__reserved_1) };
__reserved_1 as u64
});
@ -1465,9 +1484,7 @@ pub enum perf_event_type {
PERF_RECORD_SWITCH = 14,
PERF_RECORD_SWITCH_CPU_WIDE = 15,
PERF_RECORD_NAMESPACES = 16,
PERF_RECORD_KSYMBOL = 17,
PERF_RECORD_BPF_EVENT = 18,
PERF_RECORD_MAX = 19,
PERF_RECORD_MAX = 17,
}
pub const IFLA_XDP_UNSPEC: _bindgen_ty_79 = _bindgen_ty_79::IFLA_XDP_UNSPEC;
pub const IFLA_XDP_FD: _bindgen_ty_79 = _bindgen_ty_79::IFLA_XDP_FD;
@ -1503,6 +1520,79 @@ pub struct ifinfomsg {
pub ifi_flags: ::std::os::raw::c_uint,
pub ifi_change: ::std::os::raw::c_uint,
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct tcmsg {
pub tcm_family: ::std::os::raw::c_uchar,
pub tcm__pad1: ::std::os::raw::c_uchar,
pub tcm__pad2: ::std::os::raw::c_ushort,
pub tcm_ifindex: ::std::os::raw::c_int,
pub tcm_handle: __u32,
pub tcm_parent: __u32,
pub tcm_info: __u32,
}
pub const TCA_UNSPEC: _bindgen_ty_91 = _bindgen_ty_91::TCA_UNSPEC;
pub const TCA_KIND: _bindgen_ty_91 = _bindgen_ty_91::TCA_KIND;
pub const TCA_OPTIONS: _bindgen_ty_91 = _bindgen_ty_91::TCA_OPTIONS;
pub const TCA_STATS: _bindgen_ty_91 = _bindgen_ty_91::TCA_STATS;
pub const TCA_XSTATS: _bindgen_ty_91 = _bindgen_ty_91::TCA_XSTATS;
pub const TCA_RATE: _bindgen_ty_91 = _bindgen_ty_91::TCA_RATE;
pub const TCA_FCNT: _bindgen_ty_91 = _bindgen_ty_91::TCA_FCNT;
pub const TCA_STATS2: _bindgen_ty_91 = _bindgen_ty_91::TCA_STATS2;
pub const TCA_STAB: _bindgen_ty_91 = _bindgen_ty_91::TCA_STAB;
pub const TCA_PAD: _bindgen_ty_91 = _bindgen_ty_91::TCA_PAD;
pub const TCA_DUMP_INVISIBLE: _bindgen_ty_91 = _bindgen_ty_91::TCA_DUMP_INVISIBLE;
pub const TCA_CHAIN: _bindgen_ty_91 = _bindgen_ty_91::TCA_CHAIN;
pub const TCA_HW_OFFLOAD: _bindgen_ty_91 = _bindgen_ty_91::TCA_HW_OFFLOAD;
pub const __TCA_MAX: _bindgen_ty_91 = _bindgen_ty_91::__TCA_MAX;
#[repr(u32)]
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub enum _bindgen_ty_91 {
TCA_UNSPEC = 0,
TCA_KIND = 1,
TCA_OPTIONS = 2,
TCA_STATS = 3,
TCA_XSTATS = 4,
TCA_RATE = 5,
TCA_FCNT = 6,
TCA_STATS2 = 7,
TCA_STAB = 8,
TCA_PAD = 9,
TCA_DUMP_INVISIBLE = 10,
TCA_CHAIN = 11,
TCA_HW_OFFLOAD = 12,
__TCA_MAX = 13,
}
pub const TCA_BPF_UNSPEC: _bindgen_ty_133 = _bindgen_ty_133::TCA_BPF_UNSPEC;
pub const TCA_BPF_ACT: _bindgen_ty_133 = _bindgen_ty_133::TCA_BPF_ACT;
pub const TCA_BPF_POLICE: _bindgen_ty_133 = _bindgen_ty_133::TCA_BPF_POLICE;
pub const TCA_BPF_CLASSID: _bindgen_ty_133 = _bindgen_ty_133::TCA_BPF_CLASSID;
pub const TCA_BPF_OPS_LEN: _bindgen_ty_133 = _bindgen_ty_133::TCA_BPF_OPS_LEN;
pub const TCA_BPF_OPS: _bindgen_ty_133 = _bindgen_ty_133::TCA_BPF_OPS;
pub const TCA_BPF_FD: _bindgen_ty_133 = _bindgen_ty_133::TCA_BPF_FD;
pub const TCA_BPF_NAME: _bindgen_ty_133 = _bindgen_ty_133::TCA_BPF_NAME;
pub const TCA_BPF_FLAGS: _bindgen_ty_133 = _bindgen_ty_133::TCA_BPF_FLAGS;
pub const TCA_BPF_FLAGS_GEN: _bindgen_ty_133 = _bindgen_ty_133::TCA_BPF_FLAGS_GEN;
pub const TCA_BPF_TAG: _bindgen_ty_133 = _bindgen_ty_133::TCA_BPF_TAG;
pub const TCA_BPF_ID: _bindgen_ty_133 = _bindgen_ty_133::TCA_BPF_ID;
pub const __TCA_BPF_MAX: _bindgen_ty_133 = _bindgen_ty_133::__TCA_BPF_MAX;
#[repr(u32)]
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub enum _bindgen_ty_133 {
TCA_BPF_UNSPEC = 0,
TCA_BPF_ACT = 1,
TCA_BPF_POLICE = 2,
TCA_BPF_CLASSID = 3,
TCA_BPF_OPS_LEN = 4,
TCA_BPF_OPS = 5,
TCA_BPF_FD = 6,
TCA_BPF_NAME = 7,
TCA_BPF_FLAGS = 8,
TCA_BPF_FLAGS_GEN = 9,
TCA_BPF_TAG = 10,
TCA_BPF_ID = 11,
__TCA_BPF_MAX = 12,
}
pub const AYA_PERF_EVENT_IOC_ENABLE: ::std::os::raw::c_int = 9216;
pub const AYA_PERF_EVENT_IOC_DISABLE: ::std::os::raw::c_int = 9217;
pub const AYA_PERF_EVENT_IOC_SET_BPF: ::std::os::raw::c_int = 1074013192;

@ -136,6 +136,16 @@ pub const XDP_FLAGS_MODES: u32 = 14;
pub const XDP_FLAGS_MASK: u32 = 31;
pub const SO_ATTACH_BPF: u32 = 50;
pub const SO_DETACH_BPF: u32 = 27;
pub const TC_H_MAJ_MASK: u32 = 4294901760;
pub const TC_H_MIN_MASK: u32 = 65535;
pub const TC_H_UNSPEC: u32 = 0;
pub const TC_H_ROOT: u32 = 4294967295;
pub const TC_H_INGRESS: u32 = 4294967281;
pub const TC_H_CLSACT: u32 = 4294967281;
pub const TC_H_MIN_PRIORITY: u32 = 65504;
pub const TC_H_MIN_INGRESS: u32 = 65522;
pub const TC_H_MIN_EGRESS: u32 = 65523;
pub const TCA_BPF_FLAG_ACT_DIRECT: u32 = 1;
pub type __u8 = ::std::os::raw::c_uchar;
pub type __s16 = ::std::os::raw::c_short;
pub type __u16 = ::std::os::raw::c_ushort;
@ -600,6 +610,68 @@ pub struct bpf_attr__bindgen_ty_19 {
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct bpf_prog_info {
pub type_: __u32,
pub id: __u32,
pub tag: [__u8; 8usize],
pub jited_prog_len: __u32,
pub xlated_prog_len: __u32,
pub jited_prog_insns: __u64,
pub xlated_prog_insns: __u64,
pub load_time: __u64,
pub created_by_uid: __u32,
pub nr_map_ids: __u32,
pub map_ids: __u64,
pub name: [::std::os::raw::c_char; 16usize],
pub ifindex: __u32,
pub _bitfield_align_1: [u8; 0],
pub _bitfield_1: __BindgenBitfieldUnit<[u8; 4usize]>,
pub netns_dev: __u64,
pub netns_ino: __u64,
pub nr_jited_ksyms: __u32,
pub nr_jited_func_lens: __u32,
pub jited_ksyms: __u64,
pub jited_func_lens: __u64,
pub btf_id: __u32,
pub func_info_rec_size: __u32,
pub func_info: __u64,
pub nr_func_info: __u32,
pub nr_line_info: __u32,
pub line_info: __u64,
pub jited_line_info: __u64,
pub nr_jited_line_info: __u32,
pub line_info_rec_size: __u32,
pub jited_line_info_rec_size: __u32,
pub nr_prog_tags: __u32,
pub prog_tags: __u64,
pub run_time_ns: __u64,
pub run_cnt: __u64,
pub recursion_misses: __u64,
}
impl bpf_prog_info {
#[inline]
pub fn gpl_compatible(&self) -> __u32 {
unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u32) }
}
#[inline]
pub fn set_gpl_compatible(&mut self, val: __u32) {
unsafe {
let val: u32 = ::std::mem::transmute(val);
self._bitfield_1.set(0usize, 1u8, val as u64)
}
}
#[inline]
pub fn new_bitfield_1(gpl_compatible: __u32) -> __BindgenBitfieldUnit<[u8; 4usize]> {
let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 4usize]> = Default::default();
__bindgen_bitfield_unit.set(0usize, 1u8, {
let gpl_compatible: u32 = unsafe { ::std::mem::transmute(gpl_compatible) };
gpl_compatible as u64
});
__bindgen_bitfield_unit
}
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct btf_header {
pub magic: __u16,
pub version: __u8,
@ -689,7 +761,7 @@ pub enum perf_sw_ids {
PERF_COUNT_SW_BPF_OUTPUT = 10,
PERF_COUNT_SW_MAX = 11,
}
#[repr(u64)]
#[repr(u32)]
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub enum perf_event_sample_format {
PERF_SAMPLE_IP = 1,
@ -713,7 +785,6 @@ pub enum perf_event_sample_format {
PERF_SAMPLE_REGS_INTR = 262144,
PERF_SAMPLE_PHYS_ADDR = 524288,
PERF_SAMPLE_MAX = 1048576,
__PERF_SAMPLE_CALLCHAIN_EARLY = 9223372036854775808,
}
#[repr(C)]
#[derive(Copy, Clone)]
@ -724,7 +795,7 @@ pub struct perf_event_attr {
pub __bindgen_anon_1: perf_event_attr__bindgen_ty_1,
pub sample_type: __u64,
pub read_format: __u64,
pub _bitfield_align_1: [u32; 0],
pub _bitfield_align_1: [u64; 0],
pub _bitfield_1: __BindgenBitfieldUnit<[u8; 8usize]>,
pub __bindgen_anon_2: perf_event_attr__bindgen_ty_2,
pub bp_type: __u32,
@ -757,8 +828,6 @@ pub union perf_event_attr__bindgen_ty_2 {
#[derive(Copy, Clone)]
pub union perf_event_attr__bindgen_ty_3 {
pub bp_addr: __u64,
pub kprobe_func: __u64,
pub uprobe_path: __u64,
pub config1: __u64,
_bindgen_union_align: u64,
}
@ -766,8 +835,6 @@ pub union perf_event_attr__bindgen_ty_3 {
#[derive(Copy, Clone)]
pub union perf_event_attr__bindgen_ty_4 {
pub bp_len: __u64,
pub kprobe_addr: __u64,
pub probe_offset: __u64,
pub config2: __u64,
_bindgen_union_align: u64,
}
@ -1081,47 +1148,14 @@ impl perf_event_attr {
}
}
#[inline]
pub fn ksymbol(&self) -> __u64 {
unsafe { ::std::mem::transmute(self._bitfield_1.get(29usize, 1u8) as u64) }
}
#[inline]
pub fn set_ksymbol(&mut self, val: __u64) {
unsafe {
let val: u64 = ::std::mem::transmute(val);
self._bitfield_1.set(29usize, 1u8, val as u64)
}
}
#[inline]
pub fn bpf_event(&self) -> __u64 {
unsafe { ::std::mem::transmute(self._bitfield_1.get(30usize, 1u8) as u64) }
}
#[inline]
pub fn set_bpf_event(&mut self, val: __u64) {
unsafe {
let val: u64 = ::std::mem::transmute(val);
self._bitfield_1.set(30usize, 1u8, val as u64)
}
}
#[inline]
pub fn aux_output(&self) -> __u64 {
unsafe { ::std::mem::transmute(self._bitfield_1.get(31usize, 1u8) as u64) }
}
#[inline]
pub fn set_aux_output(&mut self, val: __u64) {
unsafe {
let val: u64 = ::std::mem::transmute(val);
self._bitfield_1.set(31usize, 1u8, val as u64)
}
}
#[inline]
pub fn __reserved_1(&self) -> __u64 {
unsafe { ::std::mem::transmute(self._bitfield_1.get(32usize, 32u8) as u64) }
unsafe { ::std::mem::transmute(self._bitfield_1.get(29usize, 35u8) as u64) }
}
#[inline]
pub fn set___reserved_1(&mut self, val: __u64) {
unsafe {
let val: u64 = ::std::mem::transmute(val);
self._bitfield_1.set(32usize, 32u8, val as u64)
self._bitfield_1.set(29usize, 35u8, val as u64)
}
}
#[inline]
@ -1154,9 +1188,6 @@ impl perf_event_attr {
context_switch: __u64,
write_backward: __u64,
namespaces: __u64,
ksymbol: __u64,
bpf_event: __u64,
aux_output: __u64,
__reserved_1: __u64,
) -> __BindgenBitfieldUnit<[u8; 8usize]> {
let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 8usize]> = Default::default();
@ -1274,19 +1305,7 @@ impl perf_event_attr {
let namespaces: u64 = unsafe { ::std::mem::transmute(namespaces) };
namespaces as u64
});
__bindgen_bitfield_unit.set(29usize, 1u8, {
let ksymbol: u64 = unsafe { ::std::mem::transmute(ksymbol) };
ksymbol as u64
});
__bindgen_bitfield_unit.set(30usize, 1u8, {
let bpf_event: u64 = unsafe { ::std::mem::transmute(bpf_event) };
bpf_event as u64
});
__bindgen_bitfield_unit.set(31usize, 1u8, {
let aux_output: u64 = unsafe { ::std::mem::transmute(aux_output) };
aux_output as u64
});
__bindgen_bitfield_unit.set(32usize, 32u8, {
__bindgen_bitfield_unit.set(29usize, 35u8, {
let __reserved_1: u64 = unsafe { ::std::mem::transmute(__reserved_1) };
__reserved_1 as u64
});
@ -1465,9 +1484,7 @@ pub enum perf_event_type {
PERF_RECORD_SWITCH = 14,
PERF_RECORD_SWITCH_CPU_WIDE = 15,
PERF_RECORD_NAMESPACES = 16,
PERF_RECORD_KSYMBOL = 17,
PERF_RECORD_BPF_EVENT = 18,
PERF_RECORD_MAX = 19,
PERF_RECORD_MAX = 17,
}
pub const IFLA_XDP_UNSPEC: _bindgen_ty_79 = _bindgen_ty_79::IFLA_XDP_UNSPEC;
pub const IFLA_XDP_FD: _bindgen_ty_79 = _bindgen_ty_79::IFLA_XDP_FD;
@ -1503,6 +1520,79 @@ pub struct ifinfomsg {
pub ifi_flags: ::std::os::raw::c_uint,
pub ifi_change: ::std::os::raw::c_uint,
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct tcmsg {
pub tcm_family: ::std::os::raw::c_uchar,
pub tcm__pad1: ::std::os::raw::c_uchar,
pub tcm__pad2: ::std::os::raw::c_ushort,
pub tcm_ifindex: ::std::os::raw::c_int,
pub tcm_handle: __u32,
pub tcm_parent: __u32,
pub tcm_info: __u32,
}
pub const TCA_UNSPEC: _bindgen_ty_91 = _bindgen_ty_91::TCA_UNSPEC;
pub const TCA_KIND: _bindgen_ty_91 = _bindgen_ty_91::TCA_KIND;
pub const TCA_OPTIONS: _bindgen_ty_91 = _bindgen_ty_91::TCA_OPTIONS;
pub const TCA_STATS: _bindgen_ty_91 = _bindgen_ty_91::TCA_STATS;
pub const TCA_XSTATS: _bindgen_ty_91 = _bindgen_ty_91::TCA_XSTATS;
pub const TCA_RATE: _bindgen_ty_91 = _bindgen_ty_91::TCA_RATE;
pub const TCA_FCNT: _bindgen_ty_91 = _bindgen_ty_91::TCA_FCNT;
pub const TCA_STATS2: _bindgen_ty_91 = _bindgen_ty_91::TCA_STATS2;
pub const TCA_STAB: _bindgen_ty_91 = _bindgen_ty_91::TCA_STAB;
pub const TCA_PAD: _bindgen_ty_91 = _bindgen_ty_91::TCA_PAD;
pub const TCA_DUMP_INVISIBLE: _bindgen_ty_91 = _bindgen_ty_91::TCA_DUMP_INVISIBLE;
pub const TCA_CHAIN: _bindgen_ty_91 = _bindgen_ty_91::TCA_CHAIN;
pub const TCA_HW_OFFLOAD: _bindgen_ty_91 = _bindgen_ty_91::TCA_HW_OFFLOAD;
pub const __TCA_MAX: _bindgen_ty_91 = _bindgen_ty_91::__TCA_MAX;
#[repr(u32)]
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub enum _bindgen_ty_91 {
TCA_UNSPEC = 0,
TCA_KIND = 1,
TCA_OPTIONS = 2,
TCA_STATS = 3,
TCA_XSTATS = 4,
TCA_RATE = 5,
TCA_FCNT = 6,
TCA_STATS2 = 7,
TCA_STAB = 8,
TCA_PAD = 9,
TCA_DUMP_INVISIBLE = 10,
TCA_CHAIN = 11,
TCA_HW_OFFLOAD = 12,
__TCA_MAX = 13,
}
pub const TCA_BPF_UNSPEC: _bindgen_ty_133 = _bindgen_ty_133::TCA_BPF_UNSPEC;
pub const TCA_BPF_ACT: _bindgen_ty_133 = _bindgen_ty_133::TCA_BPF_ACT;
pub const TCA_BPF_POLICE: _bindgen_ty_133 = _bindgen_ty_133::TCA_BPF_POLICE;
pub const TCA_BPF_CLASSID: _bindgen_ty_133 = _bindgen_ty_133::TCA_BPF_CLASSID;
pub const TCA_BPF_OPS_LEN: _bindgen_ty_133 = _bindgen_ty_133::TCA_BPF_OPS_LEN;
pub const TCA_BPF_OPS: _bindgen_ty_133 = _bindgen_ty_133::TCA_BPF_OPS;
pub const TCA_BPF_FD: _bindgen_ty_133 = _bindgen_ty_133::TCA_BPF_FD;
pub const TCA_BPF_NAME: _bindgen_ty_133 = _bindgen_ty_133::TCA_BPF_NAME;
pub const TCA_BPF_FLAGS: _bindgen_ty_133 = _bindgen_ty_133::TCA_BPF_FLAGS;
pub const TCA_BPF_FLAGS_GEN: _bindgen_ty_133 = _bindgen_ty_133::TCA_BPF_FLAGS_GEN;
pub const TCA_BPF_TAG: _bindgen_ty_133 = _bindgen_ty_133::TCA_BPF_TAG;
pub const TCA_BPF_ID: _bindgen_ty_133 = _bindgen_ty_133::TCA_BPF_ID;
pub const __TCA_BPF_MAX: _bindgen_ty_133 = _bindgen_ty_133::__TCA_BPF_MAX;
#[repr(u32)]
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub enum _bindgen_ty_133 {
TCA_BPF_UNSPEC = 0,
TCA_BPF_ACT = 1,
TCA_BPF_POLICE = 2,
TCA_BPF_CLASSID = 3,
TCA_BPF_OPS_LEN = 4,
TCA_BPF_OPS = 5,
TCA_BPF_FD = 6,
TCA_BPF_NAME = 7,
TCA_BPF_FLAGS = 8,
TCA_BPF_FLAGS_GEN = 9,
TCA_BPF_TAG = 10,
TCA_BPF_ID = 11,
__TCA_BPF_MAX = 12,
}
pub const AYA_PERF_EVENT_IOC_ENABLE: ::std::os::raw::c_int = 9216;
pub const AYA_PERF_EVENT_IOC_DISABLE: ::std::os::raw::c_int = 9217;
pub const AYA_PERF_EVENT_IOC_SET_BPF: ::std::os::raw::c_int = 1074013192;

@ -1,42 +0,0 @@
use crate::{
generated::bpf_prog_type::{BPF_PROG_TYPE_SCHED_ACT, BPF_PROG_TYPE_SCHED_CLS},
programs::{load_program, ProgramData, ProgramError},
};
#[derive(Debug)]
pub struct SchedClassifier {
pub(crate) data: ProgramData,
}
impl SchedClassifier {
/// 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_SCHED_CLS, &mut self.data)
}
/// Returns the name of the program.
pub fn name(&self) -> String {
self.data.name.to_string()
}
}
#[derive(Debug)]
pub struct SchedAction {
pub(crate) data: ProgramData,
}
impl SchedAction {
/// 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_SCHED_ACT, &mut self.data)
}
/// Returns the name of the program.
pub fn name(&self) -> String {
self.data.name.to_string()
}
}

@ -44,7 +44,7 @@
//! [`Bpf::program`]: crate::Bpf::program
//! [`Bpf::program_mut`]: crate::Bpf::program_mut
//! [maps]: crate::maps
mod cls;
mod tc;
mod kprobe;
mod perf_attach;
mod probe;
@ -60,7 +60,7 @@ use libc::{close, ENOSPC};
use std::{cell::RefCell, cmp, convert::TryFrom, ffi::CStr, io, os::unix::io::RawFd, rc::Rc};
use thiserror::Error;
pub use cls::{SchedAction, SchedClassifier};
pub use tc::{SchedClassifier, TcError, TcAttachPoint};
pub use kprobe::{KProbe, KProbeError};
use perf_attach::*;
pub use probe::ProbeKind;
@ -132,6 +132,9 @@ pub enum ProgramError {
#[error(transparent)]
XdpError(#[from] XdpError),
#[error(transparent)]
TcError(#[from] TcError),
}
pub trait ProgramFd {

@ -0,0 +1,118 @@
use thiserror::Error;
use std::{io, os::unix::io::RawFd};
use crate::{
generated::{
TC_H_CLSACT, TC_H_MIN_INGRESS, TC_H_MIN_EGRESS,
bpf_prog_type::BPF_PROG_TYPE_SCHED_CLS,
},
programs::{Link, LinkRef, load_program, ProgramData, ProgramError},
sys::{netlink_qdisc_add_clsact, netlink_qdisc_attach, netlink_qdisc_detach},
util::{ifindex_from_ifname, tc_handler_make},
};
#[derive(Debug, Clone, Copy)]
#[repr(u32)]
pub enum TcAttachPoint {
Ingress = TC_H_MIN_INGRESS,
Egress = TC_H_MIN_EGRESS,
Custom,
}
#[derive(Debug)]
pub struct SchedClassifier {
pub(crate) data: ProgramData,
}
#[derive(Debug, Error)]
pub enum TcError {
#[error("netlink error while attaching ebpf program to tc")]
NetlinkError {
#[source]
io_error: io::Error,
},
#[error("the clsact qdisc is already attached")]
AlreadyAttached,
}
#[derive(Debug)]
struct TcLink {
if_index: i32,
attach_point: TcAttachPoint,
prog_fd: Option<RawFd>,
priority: u32,
}
impl TcAttachPoint {
pub fn tcm_parent(&self, parent: u32) -> Result<u32, io::Error> {
match *self {
TcAttachPoint::Custom => {
if parent == 0 {
return Err(io::Error::new(io::ErrorKind::Other, "Parent must be non-zero for Custom attach points"));
}
Ok(parent)
}
_ => Ok(tc_handler_make(TC_H_CLSACT, (*self).clone() as u32))
}
}
}
impl SchedClassifier {
/// 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_SCHED_CLS, &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 `interface` and `attach-point`
pub fn attach(&mut self, interface: &str, attach_point: TcAttachPoint) -> Result<LinkRef, ProgramError> {
let prog_fd = self.data.fd_or_err()?;
let if_index = unsafe { ifindex_from_ifname(interface) }
.map_err(|io_error| TcError::NetlinkError { io_error })?;
let prog_name = self.name();
let priority = unsafe { netlink_qdisc_attach(if_index as i32, &attach_point, prog_fd, &prog_name[..]) }
.map_err(|io_error| TcError::NetlinkError { io_error })?;
Ok(self.data.link(TcLink {
if_index: if_index as i32,
attach_point,
prog_fd: Some(prog_fd),
priority,
}))
}
/// Add "clasct" qdisc to an interface
pub fn qdisc_add_clsact_to_interface(if_name: &str) -> Result<(), ProgramError> {
// unsafe wrapper
let if_index = unsafe { ifindex_from_ifname(if_name) }
.map_err(|_| ProgramError::UnknownInterface {name: if_name.to_string()})?;
unsafe { netlink_qdisc_add_clsact(if_index as i32) }
.map_err(|io_error| TcError::NetlinkError { io_error })?;
Ok(())
}
}
impl Drop for TcLink {
fn drop(&mut self) {
let _ = self.detach();
}
}
impl Link for TcLink {
fn detach(&mut self) -> Result<(), ProgramError> {
if let Some(_) = self.prog_fd.take() {
unsafe { netlink_qdisc_detach(self.if_index, &self.attach_point, self.priority) }
.map_err(|io_error| TcError::NetlinkError { io_error })?;
Ok(())
} else {
Err(ProgramError::AlreadyDetached)
}
}
}

@ -1,14 +1,28 @@
use std::{io, mem, os::unix::io::RawFd, ptr};
use std::{
io,
mem,
os::unix::io::RawFd,
ptr,
slice,
};
use libc::{
c_int, close, getsockname, nlattr, nlmsgerr, nlmsghdr, recv, send, setsockopt, sockaddr_nl,
socket, AF_NETLINK, AF_UNSPEC, IFLA_XDP, NETLINK_ROUTE, NLA_ALIGNTO, NLA_F_NESTED, NLMSG_DONE,
NLMSG_ERROR, NLM_F_ACK, NLM_F_MULTI, NLM_F_REQUEST, RTM_SETLINK, SOCK_RAW, SOL_NETLINK,
NLMSG_ERROR, NLM_F_ACK, NLM_F_EXCL, NLM_F_ECHO, NLM_F_CREATE, NLM_F_MULTI, NLM_F_REQUEST, RTM_SETLINK, SOCK_RAW,
SOL_NETLINK, RTM_NEWQDISC, RTM_NEWTFILTER, RTM_DELTFILTER, ETH_P_ALL,
};
use crate::generated::{
use crate::{
generated::{
_bindgen_ty_79::{IFLA_XDP_EXPECTED_FD, IFLA_XDP_FD, IFLA_XDP_FLAGS},
ifinfomsg, NLMSG_ALIGNTO, XDP_FLAGS_REPLACE,
_bindgen_ty_91::{TCA_KIND, TCA_OPTIONS},
_bindgen_ty_133::{TCA_BPF_FD, TCA_BPF_NAME, TCA_BPF_FLAGS},
ifinfomsg, tcmsg, NLMSG_ALIGNTO, XDP_FLAGS_REPLACE,
TC_H_UNSPEC, TCA_BPF_FLAG_ACT_DIRECT, TC_H_CLSACT, TC_H_INGRESS, TC_H_MAJ_MASK,
},
util::{htons, tc_handler_make},
programs::TcAttachPoint,
};
const NETLINK_EXT_ACK: c_int = 11;
@ -21,7 +35,7 @@ pub(crate) unsafe fn netlink_set_xdp_fd(
old_fd: Option<RawFd>,
flags: u32,
) -> Result<(), io::Error> {
let sock = NetlinkSocket::open().unwrap();
let sock = NetlinkSocket::open()?;
let seq = 1;
// Safety: Request is POD so this is safe
@ -116,6 +130,233 @@ pub(crate) unsafe fn netlink_set_xdp_fd(
Ok(())
}
pub(crate) unsafe fn netlink_qdisc_add_clsact(
if_index: i32
) -> Result<(), io::Error> {
let sock = NetlinkSocket::open()?;
let seq = 1;
let mut req = mem::zeroed::<QdiscRequest>();
req.header = nlmsghdr {
nlmsg_len: (mem::size_of::<nlmsghdr>() + mem::size_of::<tcmsg>()) as u32,
nlmsg_flags: (NLM_F_REQUEST | NLM_F_ACK | NLM_F_EXCL | NLM_F_CREATE) as u16,
nlmsg_type: RTM_NEWQDISC,
nlmsg_pid: 0,
nlmsg_seq: seq,
};
req.tc_info.tcm_family = AF_UNSPEC as u8;
req.tc_info.tcm_ifindex = if_index;
req.tc_info.tcm_handle = tc_handler_make(TC_H_CLSACT, TC_H_UNSPEC);
req.tc_info.tcm_parent = tc_handler_make(TC_H_CLSACT, TC_H_INGRESS);
req.tc_info.tcm_info = 0;
let attrs_addr = &req as *const _ as usize + req.header.nlmsg_len as usize;
let attrs_addr = align_to(attrs_addr, NLMSG_ALIGNTO as usize);
let nla_hdr_len = align_to(mem::size_of::<nlattr>(), NLA_ALIGNTO as usize);
// length of the root attribute
let mut nla_len = nla_hdr_len as u16;
let mut offset = attrs_addr as usize;
let attr = nlattr {
nla_type: TCA_KIND as u16,
// size of payload
nla_len: (nla_hdr_len + 7) as u16,
};
// write header
ptr::write(offset as *mut nlattr, attr);
offset += nla_hdr_len;
// write the "clsact" string
let buf = slice::from_raw_parts_mut(offset as *mut u8, 7);
buf.copy_from_slice(b"clsact\0");
nla_len += attr.nla_len;
req.header.nlmsg_len += align_to(nla_len as usize, NLA_ALIGNTO as usize) as u32;
if send(
sock.sock,
&req as *const _ as *const _,
req.header.nlmsg_len as usize,
0,
) < 0
{
return Err(io::Error::last_os_error())?;
}
sock.recv()?;
Ok(())
}
pub(crate) unsafe fn netlink_qdisc_detach(
if_index: i32,
attach_point: &TcAttachPoint,
priority: u32,
) -> Result<(), io::Error> {
let sock = NetlinkSocket::open()?;
let seq = 1;
let mut req = mem::zeroed::<QdiscRequest>();
req.header = nlmsghdr{
nlmsg_len: (mem::size_of::<nlmsghdr>() + mem::size_of::<tcmsg>()) as u32,
nlmsg_flags: (NLM_F_REQUEST | NLM_F_ACK) as u16,
nlmsg_type: RTM_DELTFILTER,
nlmsg_pid: 0,
nlmsg_seq: seq,
};
req.tc_info.tcm_family = AF_UNSPEC as u8;
req.tc_info.tcm_handle = 0; // auto-assigned, if not provided
req.tc_info.tcm_info = tc_handler_make(priority << 16, htons(ETH_P_ALL as u16) as u32);
req.tc_info.tcm_parent = attach_point.tcm_parent(0)?;
req.tc_info.tcm_ifindex = if_index;
if send(
sock.sock,
&req as *const _ as *const _,
req.header.nlmsg_len as usize,
0,
) < 0
{
return Err(io::Error::last_os_error())?;
}
sock.recv()?;
Ok(())
}
pub(crate) unsafe fn netlink_qdisc_attach(
if_index: i32,
attach_point: &TcAttachPoint,
prog_fd: RawFd,
prog_name: &str,
) -> Result<u32, io::Error> {
let sock = NetlinkSocket::open()?;
let seq = 1;
let priority = 0;
let mut req = mem::zeroed::<QdiscRequest>();
req.header = nlmsghdr{
nlmsg_len: (mem::size_of::<nlmsghdr>() + mem::size_of::<tcmsg>()) as u32,
nlmsg_flags: (NLM_F_REQUEST | NLM_F_ACK | NLM_F_EXCL | NLM_F_CREATE | NLM_F_ECHO) as u16,
nlmsg_type: RTM_NEWTFILTER,
nlmsg_pid: 0,
nlmsg_seq: seq,
};
req.tc_info.tcm_family = AF_UNSPEC as u8;
req.tc_info.tcm_handle = 0; // auto-assigned, if not provided
req.tc_info.tcm_ifindex = if_index;
req.tc_info.tcm_parent = attach_point.tcm_parent(0)?;
req.tc_info.tcm_info = tc_handler_make(priority << 16, htons(ETH_P_ALL as u16) as u32);
let attrs_addr = &req as *const _ as usize + req.header.nlmsg_len as usize;
let attrs_addr = align_to(attrs_addr, NLMSG_ALIGNTO as usize);
let nla_hdr_len = align_to(mem::size_of::<nlattr>(), NLA_ALIGNTO as usize);
let mut nla_len = nla_hdr_len as u16;
let mut offset = attrs_addr as usize;
let attr = nlattr {
nla_type: TCA_KIND as u16,
nla_len: (nla_hdr_len + 4) as u16,
};
// write header
ptr::write(offset as *mut nlattr, attr);
offset += nla_hdr_len;
// now write the actual "bpf" string
let buf = slice::from_raw_parts_mut(offset as *mut u8, 4);
buf.copy_from_slice(b"bpf\0");
offset += 4;
nla_len += attr.nla_len;
let nested_tca_options_start = nla_len;
let nested_attr_offset = offset;
// now write the nested portion
let mut nested_attr = nlattr {
nla_type: TCA_OPTIONS as u16 | NLA_F_NESTED as u16,
nla_len: nla_hdr_len as u16, // no data
};
offset += nla_hdr_len;
nla_len += attr.nla_len;
// add program fd and name.
let attr = nlattr {
nla_type: TCA_BPF_FD as u16,
nla_len: (nla_hdr_len + mem::size_of::<RawFd>()) as u16,
};
ptr::write(offset as *mut nlattr, attr);
offset += nla_hdr_len;
ptr::write(offset as *mut RawFd, prog_fd);
offset += mem::size_of::<i32>();
nla_len += attr.nla_len;
let prog_name_null = prog_name.to_string() + "\0";
let prog_name_len = prog_name_null.len();
let attr = nlattr {
nla_type: TCA_BPF_NAME as u16,
nla_len: (nla_hdr_len + prog_name_len) as u16,
};
ptr::write(offset as *mut nlattr, attr);
offset += nla_hdr_len;
let buf = slice::from_raw_parts_mut(offset as *mut u8, prog_name_len);
buf.copy_from_slice(prog_name_null.as_bytes());
offset += prog_name_len;
nla_len += attr.nla_len;
// write bpf flags for direct action, direct action is the default
let bpf_flags = TCA_BPF_FLAG_ACT_DIRECT;
let attr = nlattr {
nla_type: TCA_BPF_FLAGS as u16,
nla_len: (nla_hdr_len + mem::size_of::<u32>()) as u16,
};
ptr::write(offset as *mut nlattr, attr);
offset += nla_hdr_len;
ptr::write(offset as *mut u32, bpf_flags);
nla_len += attr.nla_len;
// now write the NESTED nlattr
nested_attr.nla_len = nla_len - nested_tca_options_start;
ptr::write(nested_attr_offset as *mut nlattr, nested_attr);
req.header.nlmsg_len += align_to(nla_len as usize, NLA_ALIGNTO as usize) as u32;
if send(
sock.sock,
&req as *const _ as *const _,
req.header.nlmsg_len as usize,
0,
) < 0
{
return Err(io::Error::last_os_error())?;
}
let reply_msg = sock.recv()?;
let mut tcinfo = 0;
for reply in &reply_msg {
if reply.header.nlmsg_type == RTM_NEWTFILTER {
let _tcmsg = reply._data.as_ptr() as *const tcmsg;
tcinfo = (*_tcmsg).tcm_info;
break;
}
}
let priority = ((tcinfo & TC_H_MAJ_MASK) >> 16) as u32;
Ok(priority)
}
#[repr(C)]
struct Request {
header: nlmsghdr,
@ -123,6 +364,12 @@ struct Request {
attrs: [u8; 64],
}
#[repr(C)]
struct QdiscRequest {
header: nlmsghdr,
tc_info: tcmsg,
}
struct NetlinkSocket {
sock: RawFd,
_nl_pid: u32,
@ -164,9 +411,9 @@ impl NetlinkSocket {
})
}
fn recv(&self) -> Result<(), io::Error> {
fn recv(&self) -> Result<Vec<NetlinkMessage>, io::Error> {
let mut buf = [0u8; 4096];
let mut messages = Vec::new();
let mut multipart = true;
while multipart {
multipart = false;
@ -184,9 +431,7 @@ impl NetlinkSocket {
while offset < len {
let message = NetlinkMessage::read(&buf[offset..])?;
offset += align_to(message.header.nlmsg_len as usize, NLMSG_ALIGNTO as usize);
multipart = message.header.nlmsg_flags & NLM_F_MULTI as u16 != 0;
match message.header.nlmsg_type as i32 {
NLMSG_ERROR => {
let err = message.error.unwrap();
@ -197,12 +442,12 @@ impl NetlinkSocket {
return Err(io::Error::from_raw_os_error(-err.error));
}
NLMSG_DONE => break,
_ => {}
_ => messages.push(message),
}
}
}
Ok(())
Ok(messages)
}
}
@ -258,3 +503,4 @@ impl Drop for NetlinkSocket {
fn align_to(v: usize, align: usize) -> usize {
(v + (align - 1)) & !(align - 1)
}

@ -2,10 +2,18 @@
use std::{
collections::BTreeMap,
fs::{self, File},
ffi::CString,
os::raw::c_char,
io::{self, BufReader},
str::FromStr,
};
use crate::{
generated::{TC_H_MAJ_MASK, TC_H_MIN_MASK},
};
use libc::if_nametoindex;
use io::BufRead;
const ONLINE_CPUS: &str = "/sys/devices/system/cpu/online";
@ -26,6 +34,10 @@ pub fn nr_cpus() -> Result<usize, io::Error> {
Ok(possible_cpus()?.len())
}
pub(crate) fn tc_handler_make(major: u32, minor: u32) -> u32 {
(major & TC_H_MAJ_MASK) | (minor & TC_H_MIN_MASK)
}
pub(crate) fn possible_cpus() -> Result<Vec<u32>, io::Error> {
let data = fs::read_to_string(POSSIBLE_CPUS)?;
parse_cpu_ranges(data.trim()).map_err(|_| {
@ -57,6 +69,28 @@ fn parse_cpu_ranges(data: &str) -> Result<Vec<u32>, ()> {
Ok(cpus)
}
/// Gets interface index from interface name.
pub unsafe fn ifindex_from_ifname(if_name: &str) -> Result<u32, io::Error> {
let c_str_if_name = CString::new(if_name)?;
let c_if_name: *const c_char = c_str_if_name.as_ptr() as *const c_char;
// unsafe libc wrapper
let if_index = if_nametoindex(c_if_name);
if if_index == 0 {
return Err(io::Error::last_os_error());
}
Ok(if_index)
}
/// htons and ntohs util functions
pub fn htons(u: u16) -> u16 {
u.to_be()
}
pub fn ntohs(u: u16) -> u16 {
u16::from_be(u)
}
/// Loads kernel symbols from `/proc/kallsyms`.
///
/// The symbols can be passed to [`StackTrace::resolve`](crate::maps::stack_trace::StackTrace::resolve).

@ -4,7 +4,7 @@ use aya_bpf_cty::{c_long, c_void};
use crate::{
bindings::{bpf_map_def, bpf_map_type::BPF_MAP_TYPE_HASH},
helpers::{bpf_map_lookup_elem, bpf_map_update_elem},
helpers::{bpf_map_lookup_elem, bpf_map_update_elem, bpf_map_delete_elem},
};
#[repr(transparent)]

@ -59,6 +59,7 @@ fn codegen_bindings(opts: &Options) -> Result<(), anyhow::Error> {
"bpf_map_type",
"bpf_prog_type",
"bpf_attach_type",
"bpf_prog_info",
// BTF
"btf_header",
"btf_ext_info",
@ -80,6 +81,7 @@ fn codegen_bindings(opts: &Options) -> Result<(), anyhow::Error> {
"perf_event_type",
// NETLINK
"ifinfomsg",
"tcmsg",
];
let vars = [
@ -112,7 +114,22 @@ fn codegen_bindings(opts: &Options) -> Result<(), anyhow::Error> {
// NETLINK
"NLMSG_ALIGNTO",
"IFLA_XDP_FD",
"TCA_KIND",
"TCA_OPTIONS",
"TCA_BPF_FD",
"TCA_BPF_NAME",
"TCA_BPF_FLAGS",
"TCA_BPF_FLAG_ACT_DIRECT",
"XDP_FLAGS_.*",
"TC_H_MAJ_MASK",
"TC_H_MIN_MASK",
"TC_H_UNSPEC",
"TC_H_ROOT",
"TC_H_INGRESS",
"TC_H_CLSACT",
"TC_H_MIN_PRIORITY",
"TC_H_MIN_INGRESS",
"TC_H_MIN_EGRESS",
];
let dir = PathBuf::from("aya");

Loading…
Cancel
Save