aya: add netlink_clsact_qdisc_exists function

This function is used to check if the clasct qdisc exists on a given interface.
This check should be performed before adding the mentioned qdisc.
reviewable/pr728/r3
Mohammad Javad Pooladkhay 2 years ago
parent e99e800390
commit 5d608c5485

@ -14,8 +14,8 @@ use crate::{
}, },
programs::{define_link_wrapper, load_program, Link, ProgramData, ProgramError}, programs::{define_link_wrapper, load_program, Link, ProgramData, ProgramError},
sys::{ sys::{
netlink_find_filter_with_name, netlink_qdisc_add_clsact, netlink_qdisc_attach, netlink_clsact_qdisc_exists, netlink_find_filter_with_name, netlink_qdisc_add_clsact,
netlink_qdisc_detach, netlink_qdisc_attach, netlink_qdisc_detach,
}, },
util::{ifindex_from_ifname, tc_handler_make}, util::{ifindex_from_ifname, tc_handler_make},
VerifierLogLevel, VerifierLogLevel,
@ -314,6 +314,12 @@ pub fn qdisc_add_clsact(if_name: &str) -> Result<(), io::Error> {
unsafe { netlink_qdisc_add_clsact(if_index as i32) } unsafe { netlink_qdisc_add_clsact(if_index as i32) }
} }
/// Check if the `clasct` qdisc exists on the given interface.
pub fn clsact_qdisc_exists(if_name: &str) -> Result<bool, io::Error> {
let if_index = ifindex_from_ifname(if_name)?;
unsafe { netlink_clsact_qdisc_exists(if_index as i32) }
}
/// Detaches the programs with the given name. /// Detaches the programs with the given name.
/// ///
/// # Errors /// # Errors

@ -1,12 +1,19 @@
use std::{collections::HashMap, ffi::CStr, io, mem, os::fd::RawFd, ptr, slice}; use std::{
collections::HashMap,
ffi::CStr,
io,
mem::{self},
os::fd::RawFd,
ptr, slice,
};
use thiserror::Error; use thiserror::Error;
use libc::{ use libc::{
close, getsockname, nlattr, nlmsgerr, nlmsghdr, recv, send, setsockopt, sockaddr_nl, socket, close, getsockname, nlattr, nlmsgerr, nlmsghdr, recv, send, setsockopt, sockaddr_nl, socket,
AF_NETLINK, AF_UNSPEC, ETH_P_ALL, IFF_UP, IFLA_XDP, NETLINK_EXT_ACK, NETLINK_ROUTE, AF_NETLINK, AF_UNSPEC, ETH_P_ALL, IFF_UP, IFLA_XDP, NETLINK_EXT_ACK, NETLINK_ROUTE,
NLA_ALIGNTO, NLA_F_NESTED, NLA_TYPE_MASK, NLMSG_DONE, NLMSG_ERROR, NLM_F_ACK, NLM_F_CREATE, NLA_ALIGNTO, NLA_F_NESTED, NLA_TYPE_MASK, NLMSG_DONE, NLMSG_ERROR, NLM_F_ACK, NLM_F_CREATE,
NLM_F_DUMP, NLM_F_ECHO, NLM_F_EXCL, NLM_F_MULTI, NLM_F_REQUEST, RTM_DELTFILTER, RTM_GETTFILTER, NLM_F_DUMP, NLM_F_ECHO, NLM_F_EXCL, NLM_F_MULTI, NLM_F_REQUEST, RTM_DELTFILTER, RTM_GETQDISC,
RTM_NEWQDISC, RTM_NEWTFILTER, RTM_SETLINK, SOCK_RAW, SOL_NETLINK, RTM_GETTFILTER, RTM_NEWQDISC, RTM_NEWTFILTER, RTM_SETLINK, SOCK_RAW, SOL_NETLINK,
}; };
use crate::{ use crate::{
@ -68,6 +75,46 @@ pub(crate) unsafe fn netlink_set_xdp_fd(
Ok(()) Ok(())
} }
pub(crate) unsafe fn netlink_clsact_qdisc_exists(if_index: i32) -> Result<bool, io::Error> {
let sock = NetlinkSocket::open()?;
let mut req = mem::zeroed::<TcRequest>();
let nlmsg_len = mem::size_of::<nlmsghdr>() + mem::size_of::<tcmsg>();
req.header = nlmsghdr {
nlmsg_len: nlmsg_len as u32,
nlmsg_flags: (NLM_F_REQUEST | NLM_F_ACK | NLM_F_DUMP) as u16,
nlmsg_type: RTM_GETQDISC,
nlmsg_pid: 0,
nlmsg_seq: 1,
};
req.tc_info.tcm_family = AF_UNSPEC as u8;
sock.send(&bytes_of(&req)[..req.header.nlmsg_len as usize])?;
for msg in sock.recv()? {
if msg.header.nlmsg_type != RTM_NEWQDISC {
continue;
}
let tc_msg = ptr::read_unaligned(msg.data.as_ptr() as *const tcmsg);
if tc_msg.tcm_ifindex != if_index {
continue;
}
let attrs = parse_attrs(&msg.data[mem::size_of::<tcmsg>()..])?;
if let Some(opts) = attrs.get(&(TCA_KIND as u16)) {
if opts.data == b"clsact\0" {
return Ok(true);
}
}
}
Ok(false)
}
pub(crate) unsafe fn netlink_qdisc_add_clsact(if_index: i32) -> Result<(), io::Error> { pub(crate) unsafe fn netlink_qdisc_add_clsact(if_index: i32) -> Result<(), io::Error> {
let sock = NetlinkSocket::open()?; let sock = NetlinkSocket::open()?;

@ -5,7 +5,7 @@ use aya::{
programs::{ programs::{
links::{FdLink, PinnedLink}, links::{FdLink, PinnedLink},
loaded_links, loaded_programs, loaded_links, loaded_programs,
tc::qdisc_add_clsact, tc::{clsact_qdisc_exists, qdisc_add_clsact},
KProbe, SchedClassifier, TcAttachType, TracePoint, UProbe, Xdp, XdpFlags, KProbe, SchedClassifier, TcAttachType, TracePoint, UProbe, Xdp, XdpFlags,
}, },
util::KernelVersion, util::KernelVersion,
@ -17,7 +17,10 @@ const RETRY_DURATION: time::Duration = time::Duration::from_millis(10);
#[test] #[test]
fn tc_name_limit() { fn tc_name_limit() {
let _ = qdisc_add_clsact("lo"); let clsact_exists = clsact_qdisc_exists("lo").unwrap();
if !clsact_exists {
qdisc_add_clsact("lo").unwrap();
}
let mut bpf = Bpf::load(crate::TC_NAME_LIMIT_TEST).unwrap(); let mut bpf = Bpf::load(crate::TC_NAME_LIMIT_TEST).unwrap();

Loading…
Cancel
Save