Browse Source

Add support for setting priority for classifier programs

Addresses issue #358

Signed-off-by: Andre Fredette <[email protected]>
Andre Fredette 2 years ago
parent
commit
207c689f56
2 changed files with 20 additions and 14 deletions
  1. 12 6
      aya/src/programs/tc.rs
  2. 8 8
      aya/src/sys/netlink.rs

+ 12 - 6
aya/src/programs/tc.rs

@@ -64,7 +64,7 @@ pub enum TcAttachType {
 ///
 /// let prog: &mut SchedClassifier = bpf.program_mut("redirect_ingress").unwrap().try_into()?;
 /// prog.load()?;
-/// prog.attach("eth0", TcAttachType::Ingress)?;
+/// prog.attach("eth0", TcAttachType::Ingress, 0)?;
 ///
 /// # Ok::<(), Error>(())
 /// ```
@@ -108,6 +108,10 @@ impl SchedClassifier {
 
     /// 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].
     ///
     /// # Errors
@@ -120,13 +124,15 @@ impl SchedClassifier {
         &mut self,
         interface: &str,
         attach_type: TcAttachType,
+        priority: u16,
     ) -> Result<SchedClassifierLinkId, ProgramError> {
         let prog_fd = self.data.fd_or_err()?;
         let if_index = ifindex_from_ifname(interface)
             .map_err(|io_error| TcError::NetlinkError { io_error })?;
-        let priority =
-            unsafe { netlink_qdisc_attach(if_index as i32, &attach_type, prog_fd, &self.name) }
-                .map_err(|io_error| TcError::NetlinkError { io_error })?;
+        let priority = unsafe {
+            netlink_qdisc_attach(if_index as i32, &attach_type, prog_fd, &self.name, priority)
+        }
+        .map_err(|io_error| TcError::NetlinkError { io_error })?;
 
         self.data.links.insert(SchedClassifierLink(TcLink {
             if_index: if_index as i32,
@@ -155,13 +161,13 @@ impl SchedClassifier {
 }
 
 #[derive(Debug, Hash, Eq, PartialEq)]
-pub(crate) struct TcLinkId(i32, TcAttachType, u32);
+pub(crate) struct TcLinkId(i32, TcAttachType, u16);
 
 #[derive(Debug)]
 struct TcLink {
     if_index: i32,
     attach_type: TcAttachType,
-    priority: u32,
+    priority: u16,
 }
 
 impl Link for TcLink {

+ 8 - 8
aya/src/sys/netlink.rs

@@ -103,9 +103,9 @@ pub(crate) unsafe fn netlink_qdisc_attach(
     attach_type: &TcAttachType,
     prog_fd: RawFd,
     prog_name: &CStr,
-) -> Result<u32, io::Error> {
+    priority: u16,
+) -> Result<u16, io::Error> {
     let sock = NetlinkSocket::open()?;
-    let priority = 0;
     let mut req = mem::zeroed::<TcRequest>();
 
     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_ifindex = if_index;
     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);
 
@@ -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)
 }
 
 pub(crate) unsafe fn netlink_qdisc_detach(
     if_index: i32,
     attach_type: &TcAttachType,
-    priority: u32,
+    priority: u16,
 ) -> Result<(), io::Error> {
     let sock = NetlinkSocket::open()?;
     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_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_ifindex = if_index;
 
@@ -196,7 +196,7 @@ pub(crate) unsafe fn netlink_find_filter_with_name(
     if_index: i32,
     attach_type: TcAttachType,
     name: &CStr,
-) -> Result<Vec<u32>, io::Error> {
+) -> Result<Vec<u16>, io::Error> {
     let mut req = mem::zeroed::<TcRequest>();
 
     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 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>()..])?;
 
         if let Some(opts) = attrs.get(&(TCA_OPTIONS as u16)) {