Skip to content

Commit

Permalink
tc: add SchedClassifier::attach_to_link
Browse files Browse the repository at this point in the history
Similar to Xdp::attach_to_link, can be used to replace/upgrade the
program attached to a link.
  • Loading branch information
alessandrod committed Jan 2, 2024
1 parent b13645b commit 2257cbe
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 5 deletions.
35 changes: 31 additions & 4 deletions aya/src/programs/tc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,27 +152,54 @@ impl SchedClassifier {
attach_type: TcAttachType,
options: TcOptions,
) -> Result<SchedClassifierLinkId, ProgramError> {
let prog_fd = self.fd()?;
let prog_fd = prog_fd.as_fd();
let if_index = ifindex_from_ifname(interface)
.map_err(|io_error| TcError::NetlinkError { io_error })?;
self.do_attach(if_index as i32, attach_type, options, true)
}

/// Atomically replaces the program referenced by the provided link.
///
/// Ownership of the link will transfer to this program.
pub fn attach_to_link(
&mut self,
link: SchedClassifierLink,
) -> Result<SchedClassifierLinkId, ProgramError> {
let TcLink {
if_index,
attach_type,
priority,
handle,
} = link.into_inner();
self.do_attach(if_index, attach_type, TcOptions { priority, handle }, false)
}

fn do_attach(
&mut self,
if_index: i32,
attach_type: TcAttachType,
options: TcOptions,
create: bool,
) -> Result<SchedClassifierLinkId, ProgramError> {
let prog_fd = self.fd()?;
let prog_fd = prog_fd.as_fd();
let name = self.data.name.as_deref().unwrap_or_default();
// TODO: avoid this unwrap by adding a new error variant.
let name = CString::new(name).unwrap();
let (priority, handle) = unsafe {
netlink_qdisc_attach(
if_index as i32,
if_index,
&attach_type,
prog_fd,
&name,
options.priority,
options.handle,
create,
)
}
.map_err(|io_error| TcError::NetlinkError { io_error })?;

self.data.links.insert(SchedClassifierLink::new(TcLink {
if_index: if_index as i32,
if_index,
attach_type,
priority,
handle,
Expand Down
16 changes: 15 additions & 1 deletion aya/src/sys/netlink.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,14 +117,28 @@ pub(crate) unsafe fn netlink_qdisc_attach(
prog_name: &CStr,
priority: u16,
handle: u32,
create: bool,
) -> Result<(u16, u32), io::Error> {
let sock = NetlinkSocket::open()?;
let mut req = mem::zeroed::<TcRequest>();

let nlmsg_len = mem::size_of::<nlmsghdr>() + mem::size_of::<tcmsg>();
// When create=true, we're creating a new attachment so we must set NLM_F_CREATE. Then we also
// set NLM_F_EXCL so that attaching fails if there's already a program attached to the given
// handle.
//
// When create=false we're replacing an existing attachment so we must not set either flags.
//
// See https://github.com/torvalds/linux/blob/3a87498/net/sched/cls_api.c#L2304
let request_flags = if create {
NLM_F_CREATE | NLM_F_EXCL
} else {
// NLM_F_REPLACE exists, but seems unused by cls_bpf
0
};
req.header = nlmsghdr {
nlmsg_len: nlmsg_len as u32,
nlmsg_flags: (NLM_F_REQUEST | NLM_F_ACK | NLM_F_EXCL | NLM_F_CREATE | NLM_F_ECHO) as u16,
nlmsg_flags: (NLM_F_REQUEST | NLM_F_ACK | NLM_F_ECHO | request_flags) as u16,
nlmsg_type: RTM_NEWTFILTER,
nlmsg_pid: 0,
nlmsg_seq: 1,
Expand Down

0 comments on commit 2257cbe

Please sign in to comment.