diff --git a/Cargo.toml b/Cargo.toml index 6c7f3bc5..9c9cc6a0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -52,7 +52,8 @@ maplit = "1.0" md5 = "0.7" nix = { version = "0.29", features = ["fs", "net", "socket", "uio", "user"] } netlink-packet-core = "0.7" -netlink-packet-route = "0.17" +netlink-packet-route = "0.19" +netlink-packet-utils = "0.5" netlink-sys = "0.8" num-derive = "0.4" num-traits = "0.2" @@ -61,7 +62,7 @@ prefix-trie = { version = "0.4.1", default-features = false, features = ["ipnetw prost = "0.12" rand = "0.8.5" regex = "1.10" -rtnetlink = "0.13" +rtnetlink = "0.14.1" serde = { version = "1.0", features = ["derive", "rc"] } serde_json = "1.0" serde_with = "3.7" diff --git a/holo-interface/Cargo.toml b/holo-interface/Cargo.toml index a5bddb87..fce24554 100644 --- a/holo-interface/Cargo.toml +++ b/holo-interface/Cargo.toml @@ -16,11 +16,13 @@ generational-arena.workspace = true ipnetwork.workspace = true netlink-packet-route.workspace = true netlink-packet-core.workspace = true +netlink-packet-utils.workspace = true netlink-sys.workspace = true rtnetlink.workspace = true tokio.workspace = true tracing.workspace = true yang3.workspace = true +libc.workspace = true holo-northbound = { path = "../holo-northbound" } holo-utils = { path = "../holo-utils" } diff --git a/holo-interface/src/netlink.rs b/holo-interface/src/netlink.rs index 57eea362..139264ee 100644 --- a/holo-interface/src/netlink.rs +++ b/holo-interface/src/netlink.rs @@ -9,15 +9,16 @@ use std::net::{Ipv4Addr, Ipv6Addr}; use capctl::caps::CapState; use futures::channel::mpsc::UnboundedReceiver; use futures::TryStreamExt; +use holo_utils::ip::IpAddrExt; use holo_utils::southbound::InterfaceFlags; use ipnetwork::IpNetwork; +use libc::{RTNLGRP_IPV4_IFADDR, RTNLGRP_IPV6_IFADDR, RTNLGRP_LINK}; use netlink_packet_core::{NetlinkMessage, NetlinkPayload}; -use netlink_packet_route::constants::{ - AF_INET, AF_INET6, ARPHRD_LOOPBACK, IFF_BROADCAST, IFF_RUNNING, - RTNLGRP_IPV4_IFADDR, RTNLGRP_IPV6_IFADDR, RTNLGRP_LINK, +use netlink_packet_route::address::{AddressAttribute, AddressMessage}; +use netlink_packet_route::link::{ + LinkAttribute, LinkFlag, LinkLayerType, LinkMessage, }; -use netlink_packet_route::rtnl::RtnlMessage; -use netlink_packet_route::{AddressMessage, LinkMessage}; +use netlink_packet_route::RouteNetlinkMessage; use netlink_sys::{AsyncSocket, SocketAddr}; use rtnetlink::{new_connection, Handle}; use tracing::{error, trace}; @@ -26,7 +27,7 @@ use crate::interface::Owner; use crate::Master; pub type NetlinkMonitor = - UnboundedReceiver<(NetlinkMessage, SocketAddr)>; + UnboundedReceiver<(NetlinkMessage, SocketAddr)>; // ===== helper functions ===== @@ -35,8 +36,6 @@ async fn process_newlink_msg( msg: LinkMessage, notify: bool, ) { - use netlink_packet_route::link::nlas::Nla; - trace!(?msg, "received RTM_NEWLINK message"); // Fetch interface attributes. @@ -46,20 +45,22 @@ async fn process_newlink_msg( let mut mac_address: [u8; 6] = [0u8; 6]; let mut flags = InterfaceFlags::empty(); - if msg.header.link_layer_type == ARPHRD_LOOPBACK { + if msg.header.link_layer_type == LinkLayerType::Loopback { flags.insert(InterfaceFlags::LOOPBACK); } - if msg.header.flags & IFF_RUNNING != 0 { + + if msg.header.flags.contains(&LinkFlag::Running) { flags.insert(InterfaceFlags::OPERATIVE); } - if msg.header.flags & IFF_BROADCAST != 0 { - flags.insert(InterfaceFlags::BROADCAST); + if msg.header.flags.contains(&LinkFlag::Broadcast) { + flags.insert(InterfaceFlags::BROADCAST) } - for nla in msg.nlas.into_iter() { + + for nla in msg.attributes.into_iter() { match nla { - Nla::IfName(nla_ifname) => ifname = Some(nla_ifname), - Nla::Mtu(nla_mtu) => mtu = Some(nla_mtu), - Nla::Address(addr) => { + LinkAttribute::IfName(nla_ifname) => ifname = Some(nla_ifname), + LinkAttribute::Mtu(nla_mtu) => mtu = Some(nla_mtu), + LinkAttribute::Address(addr) => { mac_address = addr.try_into().unwrap_or([0u8; 6]); } _ => (), @@ -107,16 +108,14 @@ async fn process_dellink_msg( } fn process_newaddr_msg(master: &mut Master, msg: AddressMessage, notify: bool) { - use netlink_packet_route::address::nlas::Nla; - trace!(?msg, "received RTM_NEWADDR message"); // Fetch address attributes. let mut addr = None; let ifindex = msg.header.index; - for nla in msg.nlas.into_iter() { + for nla in msg.attributes.into_iter() { match nla { - Nla::Address(nla_addr) => addr = Some(nla_addr), + AddressAttribute::Address(nla_addr) => addr = Some(nla_addr), _ => (), } } @@ -125,9 +124,11 @@ fn process_newaddr_msg(master: &mut Master, msg: AddressMessage, notify: bool) { }; // Parse address. - let Some(addr) = - parse_address(msg.header.family, msg.header.prefix_len, addr) - else { + let Some(addr) = parse_address( + msg.header.family.into(), + msg.header.prefix_len, + addr.bytes(), + ) else { return; }; @@ -137,16 +138,14 @@ fn process_newaddr_msg(master: &mut Master, msg: AddressMessage, notify: bool) { } fn process_deladdr_msg(master: &mut Master, msg: AddressMessage, notify: bool) { - use netlink_packet_route::address::nlas::Nla; - trace!(?msg, "received RTM_DELADDR message"); // Fetch address attributes. let mut addr = None; let ifindex = msg.header.index; - for nla in msg.nlas.into_iter() { + for nla in msg.attributes.into_iter() { match nla { - Nla::Address(nla_addr) => addr = Some(nla_addr), + AddressAttribute::Address(nla_addr) => addr = Some(nla_addr), _ => (), } } @@ -155,9 +154,11 @@ fn process_deladdr_msg(master: &mut Master, msg: AddressMessage, notify: bool) { }; // Parse address. - let Some(addr) = - parse_address(msg.header.family, msg.header.prefix_len, addr) - else { + let Some(addr) = parse_address( + msg.header.family.into(), + msg.header.prefix_len, + addr.bytes(), + ) else { return; }; @@ -171,13 +172,13 @@ fn parse_address( prefixlen: u8, bytes: Vec, ) -> Option { - let addr = match family as u16 { - AF_INET => { + let addr = match family as i32 { + libc::AF_INET => { let mut addr_array: [u8; 4] = [0; 4]; addr_array.copy_from_slice(&bytes); Ipv4Addr::from(addr_array).into() } - AF_INET6 => { + libc::AF_INET6 => { let mut addr_array: [u8; 16] = [0; 16]; addr_array.copy_from_slice(&bytes); Ipv6Addr::from(addr_array).into() @@ -264,20 +265,20 @@ pub(crate) async fn addr_uninstall( pub(crate) async fn process_msg( master: &mut Master, - msg: NetlinkMessage, + msg: NetlinkMessage, ) { if let NetlinkPayload::InnerMessage(msg) = msg.payload { match msg { - RtnlMessage::NewLink(msg) => { + RouteNetlinkMessage::NewLink(msg) => { process_newlink_msg(master, msg, true).await } - RtnlMessage::DelLink(msg) => { + RouteNetlinkMessage::DelLink(msg) => { process_dellink_msg(master, msg, true).await } - RtnlMessage::NewAddress(msg) => { + RouteNetlinkMessage::NewAddress(msg) => { process_newaddr_msg(master, msg, true) } - RtnlMessage::DelAddress(msg) => { + RouteNetlinkMessage::DelAddress(msg) => { process_deladdr_msg(master, msg, true) } _ => (), diff --git a/holo-routing/Cargo.toml b/holo-routing/Cargo.toml index d0dbfc89..d9220ff0 100644 --- a/holo-routing/Cargo.toml +++ b/holo-routing/Cargo.toml @@ -17,6 +17,7 @@ ipnetwork.workspace = true prefix-trie.workspace = true regex.workspace = true rtnetlink.workspace = true +netlink-packet-route.workspace = true tokio.workspace = true tracing.workspace = true yang3.workspace = true diff --git a/holo-routing/src/netlink.rs b/holo-routing/src/netlink.rs index 4e0d3e21..195ada1c 100644 --- a/holo-routing/src/netlink.rs +++ b/holo-routing/src/netlink.rs @@ -11,25 +11,19 @@ use holo_utils::mpls::Label; use holo_utils::protocol::Protocol; use holo_utils::southbound::Nexthop; use ipnetwork::IpNetwork; +use netlink_packet_route::route::RouteProtocol; use rtnetlink::{new_connection, Handle, RouteAddRequest}; use tracing::error; use crate::rib::Route; -// Route protocol types as defined in the rtnetlink.h kernel header. -const NETLINK_PROTO_UNSPEC: u8 = 0; -const NETLINK_PROTO_STATIC: u8 = 4; -const NETLINK_PROTO_BGP: u8 = 186; -const NETLINK_PROTO_OSPF: u8 = 188; -const NETLINK_PROTO_RIP: u8 = 189; - -fn netlink_protocol(protocol: Protocol) -> u8 { +fn netlink_protocol(protocol: Protocol) -> RouteProtocol { match protocol { - Protocol::BGP => NETLINK_PROTO_BGP, - Protocol::OSPFV2 | Protocol::OSPFV3 => NETLINK_PROTO_OSPF, - Protocol::RIPV2 | Protocol::RIPNG => NETLINK_PROTO_RIP, - Protocol::STATIC => NETLINK_PROTO_STATIC, - _ => NETLINK_PROTO_UNSPEC, + Protocol::BGP => RouteProtocol::Bgp, + Protocol::OSPFV2 | Protocol::OSPFV3 => RouteProtocol::Ospf, + Protocol::RIPV2 | Protocol::RIPNG => RouteProtocol::Rip, + Protocol::STATIC => RouteProtocol::Static, + _ => RouteProtocol::Unspec, } }