tc: add SchedClassifier::attach_to_link

Similar to Xdp::attach_to_link, can be used to replace/upgrade the
program attached to a link.
pull/861/head
Alessandro Decina 10 months ago
parent b13645b13d
commit 2257cbeccb

@ -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,

@ -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,

Loading…
Cancel
Save