Skip to content

Commit

Permalink
netlink: upgrade rtnetlink
Browse files Browse the repository at this point in the history
- upgrade rtnetlink to latest version: 0.4.1.
    Still unstable
- upgrade netlink-packet-route to version 0.19.
- Introduce netlink-packet-utils. Some of the
    items we were previously using in
    netlink-packet-route are now only accessible
    via that library.

Majority of the changes have been made in
the `netlink.rs` files that exist both in
`holo-routing` and `holo-interface`.

There have been several changes on rtnetlink &
netlink-packet-route and key files, functions and
structs have also been moved in the library.
The changes have been reflected in this commit.

Signed-off-by: Paul Wekesa <[email protected]>
  • Loading branch information
Paul-weqe committed Sep 14, 2024
1 parent 754a2a3 commit 5aab6be
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 48 deletions.
5 changes: 3 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ maplit = "1.0"
md5 = "0.7"
nix = "0.26"
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"
Expand All @@ -60,7 +61,7 @@ prefix-trie = { version = "0.4.1", features = ["ipnetwork"] }
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"
Expand Down
2 changes: 2 additions & 0 deletions holo-interface/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,14 @@ 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
regex.workspace = true
rtnetlink.workspace = true
tokio.workspace = true
tracing.workspace = true
yang2.workspace = true
libc.workspace = true

holo-northbound = { path = "../holo-northbound" }
holo-protocol = { path = "../holo-protocol" }
Expand Down
78 changes: 45 additions & 33 deletions holo-interface/src/netlink.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,24 +11,29 @@ 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_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, MACVLAN_MODE_BRIDGE};
use netlink_packet_route::RouteNetlinkMessage;
use netlink_sys::{AsyncSocket, SocketAddr};
use rtnetlink::{new_connection, Handle};
use tracing::{error, trace};

use crate::interface::Owner;
use crate::Master;

const AF_INET: u16 = libc::AF_INET as u16;
const AF_INET6: u16 = libc::AF_INET6 as u16;
pub const MACVLAN_MODE_BRIDGE: u32 = 4;

pub type NetlinkMonitor =
UnboundedReceiver<(NetlinkMessage<RtnlMessage>, SocketAddr)>;
UnboundedReceiver<(NetlinkMessage<RouteNetlinkMessage>, SocketAddr)>;

// ===== helper functions =====

Expand All @@ -37,8 +42,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.
Expand All @@ -48,17 +51,26 @@ 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 {

// conversion to u32 has been adapted from VecLinkFlags
// method of conversion to u32
// as implemented from VecLinkFlag:
// https://github.com/rust-netlink/netlink-packet-route/blob/aec3fc64b662447da2fbed5f9c9bd565cdea14ec/src/link/link_flag.rs#L174
let mut flgs: u32 = 0;
for flg in &msg.header.flags {
flgs += u32::from(*flg);
}
if flgs & u32::from(LinkFlag::Running) != 0 {
flags.insert(InterfaceFlags::OPERATIVE);
}
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]);
}
_ => (),
Expand Down Expand Up @@ -106,16 +118,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),
_ => (),
}
}
Expand All @@ -124,9 +134,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;
};

Expand All @@ -136,16 +148,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),
_ => (),
}
}
Expand All @@ -154,9 +164,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;
};

Expand Down Expand Up @@ -304,20 +316,20 @@ pub(crate) async fn addr_uninstall(

pub(crate) async fn process_msg(
master: &mut Master,
msg: NetlinkMessage<RtnlMessage>,
msg: NetlinkMessage<RouteNetlinkMessage>,
) {
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)
}
_ => (),
Expand Down
1 change: 1 addition & 0 deletions holo-routing/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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
yang2.workspace = true
Expand Down
20 changes: 7 additions & 13 deletions holo-routing/src/netlink.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}
}

Expand Down

0 comments on commit 5aab6be

Please sign in to comment.