Add support for setting priority for classifier programs

Addresses issue #358

Signed-off-by: Andre Fredette <afredette@redhat.com>
pull/361/head
Andre Fredette 2 years ago committed by Alessandro Decina
parent 2f715f0036
commit 207c689f56

@ -64,7 +64,7 @@ pub enum TcAttachType {
/// ///
/// let prog: &mut SchedClassifier = bpf.program_mut("redirect_ingress").unwrap().try_into()?; /// let prog: &mut SchedClassifier = bpf.program_mut("redirect_ingress").unwrap().try_into()?;
/// prog.load()?; /// prog.load()?;
/// prog.attach("eth0", TcAttachType::Ingress)?; /// prog.attach("eth0", TcAttachType::Ingress, 0)?;
/// ///
/// # Ok::<(), Error>(()) /// # Ok::<(), Error>(())
/// ``` /// ```
@ -108,6 +108,10 @@ impl SchedClassifier {
/// Attaches the program to the given `interface`. /// Attaches the program to the given `interface`.
/// ///
/// Valid priority values range from 0 - 65535 with lower number = higher priority.
/// 0 means let the system choose the next highest priority, or 49152 if no filters exist yet.
/// All other values in the range are taken as an explicit priority setting (aka "preference").
///
/// The returned value can be used to detach, see [SchedClassifier::detach]. /// The returned value can be used to detach, see [SchedClassifier::detach].
/// ///
/// # Errors /// # Errors
@ -120,13 +124,15 @@ impl SchedClassifier {
&mut self, &mut self,
interface: &str, interface: &str,
attach_type: TcAttachType, attach_type: TcAttachType,
priority: u16,
) -> Result<SchedClassifierLinkId, ProgramError> { ) -> Result<SchedClassifierLinkId, ProgramError> {
let prog_fd = self.data.fd_or_err()?; let prog_fd = self.data.fd_or_err()?;
let if_index = ifindex_from_ifname(interface) let if_index = ifindex_from_ifname(interface)
.map_err(|io_error| TcError::NetlinkError { io_error })?; .map_err(|io_error| TcError::NetlinkError { io_error })?;
let priority = let priority = unsafe {
unsafe { netlink_qdisc_attach(if_index as i32, &attach_type, prog_fd, &self.name) } netlink_qdisc_attach(if_index as i32, &attach_type, prog_fd, &self.name, priority)
.map_err(|io_error| TcError::NetlinkError { io_error })?; }
.map_err(|io_error| TcError::NetlinkError { io_error })?;
self.data.links.insert(SchedClassifierLink(TcLink { self.data.links.insert(SchedClassifierLink(TcLink {
if_index: if_index as i32, if_index: if_index as i32,
@ -155,13 +161,13 @@ impl SchedClassifier {
} }
#[derive(Debug, Hash, Eq, PartialEq)] #[derive(Debug, Hash, Eq, PartialEq)]
pub(crate) struct TcLinkId(i32, TcAttachType, u32); pub(crate) struct TcLinkId(i32, TcAttachType, u16);
#[derive(Debug)] #[derive(Debug)]
struct TcLink { struct TcLink {
if_index: i32, if_index: i32,
attach_type: TcAttachType, attach_type: TcAttachType,
priority: u32, priority: u16,
} }
impl Link for TcLink { impl Link for TcLink {

@ -103,9 +103,9 @@ pub(crate) unsafe fn netlink_qdisc_attach(
attach_type: &TcAttachType, attach_type: &TcAttachType,
prog_fd: RawFd, prog_fd: RawFd,
prog_name: &CStr, prog_name: &CStr,
) -> Result<u32, io::Error> { priority: u16,
) -> Result<u16, io::Error> {
let sock = NetlinkSocket::open()?; let sock = NetlinkSocket::open()?;
let priority = 0;
let mut req = mem::zeroed::<TcRequest>(); let mut req = mem::zeroed::<TcRequest>();
let nlmsg_len = mem::size_of::<nlmsghdr>() + mem::size_of::<tcmsg>(); let nlmsg_len = mem::size_of::<nlmsghdr>() + mem::size_of::<tcmsg>();
@ -120,7 +120,7 @@ pub(crate) unsafe fn netlink_qdisc_attach(
req.tc_info.tcm_handle = 0; // auto-assigned, if not provided req.tc_info.tcm_handle = 0; // auto-assigned, if not provided
req.tc_info.tcm_ifindex = if_index; req.tc_info.tcm_ifindex = if_index;
req.tc_info.tcm_parent = attach_type.parent(); req.tc_info.tcm_parent = attach_type.parent();
req.tc_info.tcm_info = tc_handler_make(priority << 16, htons(ETH_P_ALL as u16) as u32); req.tc_info.tcm_info = tc_handler_make((priority as u32) << 16, htons(ETH_P_ALL as u16) as u32);
let attrs_buf = request_attributes(&mut req, nlmsg_len); let attrs_buf = request_attributes(&mut req, nlmsg_len);
@ -159,14 +159,14 @@ pub(crate) unsafe fn netlink_qdisc_attach(
} }
}; };
let priority = ((tc_info & TC_H_MAJ_MASK) >> 16) as u32; let priority = ((tc_info & TC_H_MAJ_MASK) >> 16) as u16;
Ok(priority) Ok(priority)
} }
pub(crate) unsafe fn netlink_qdisc_detach( pub(crate) unsafe fn netlink_qdisc_detach(
if_index: i32, if_index: i32,
attach_type: &TcAttachType, attach_type: &TcAttachType,
priority: u32, priority: u16,
) -> Result<(), io::Error> { ) -> Result<(), io::Error> {
let sock = NetlinkSocket::open()?; let sock = NetlinkSocket::open()?;
let mut req = mem::zeroed::<TcRequest>(); let mut req = mem::zeroed::<TcRequest>();
@ -181,7 +181,7 @@ pub(crate) unsafe fn netlink_qdisc_detach(
req.tc_info.tcm_family = AF_UNSPEC as u8; req.tc_info.tcm_family = AF_UNSPEC as u8;
req.tc_info.tcm_handle = 0; // auto-assigned, if not provided 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_info = tc_handler_make((priority as u32) << 16, htons(ETH_P_ALL as u16) as u32);
req.tc_info.tcm_parent = attach_type.parent(); req.tc_info.tcm_parent = attach_type.parent();
req.tc_info.tcm_ifindex = if_index; req.tc_info.tcm_ifindex = if_index;
@ -196,7 +196,7 @@ pub(crate) unsafe fn netlink_find_filter_with_name(
if_index: i32, if_index: i32,
attach_type: TcAttachType, attach_type: TcAttachType,
name: &CStr, name: &CStr,
) -> Result<Vec<u32>, io::Error> { ) -> Result<Vec<u16>, io::Error> {
let mut req = mem::zeroed::<TcRequest>(); let mut req = mem::zeroed::<TcRequest>();
let nlmsg_len = mem::size_of::<nlmsghdr>() + mem::size_of::<tcmsg>(); let nlmsg_len = mem::size_of::<nlmsghdr>() + mem::size_of::<tcmsg>();
@ -222,7 +222,7 @@ pub(crate) unsafe fn netlink_find_filter_with_name(
} }
let tc_msg = ptr::read_unaligned(msg.data.as_ptr() as *const tcmsg); let tc_msg = ptr::read_unaligned(msg.data.as_ptr() as *const tcmsg);
let priority = tc_msg.tcm_info >> 16; let priority = (tc_msg.tcm_info >> 16) as u16;
let attrs = parse_attrs(&msg.data[mem::size_of::<tcmsg>()..])?; let attrs = parse_attrs(&msg.data[mem::size_of::<tcmsg>()..])?;
if let Some(opts) = attrs.get(&(TCA_OPTIONS as u16)) { if let Some(opts) = attrs.get(&(TCA_OPTIONS as u16)) {

Loading…
Cancel
Save