Skip to content

Commit

Permalink
Merge branch 'vrrp' into vrrp-init
Browse files Browse the repository at this point in the history
  • Loading branch information
Paul-weqe authored Jun 24, 2024
2 parents 7db409d + 46e3db0 commit 4219aef
Show file tree
Hide file tree
Showing 24 changed files with 822 additions and 455 deletions.
4 changes: 2 additions & 2 deletions holo-daemon/src/northbound/yang.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,8 @@ pub(crate) fn create_context() {
}
#[cfg(feature = "vrrp")]
{
use holo_vrrp::instance::Instance;
modules_add::<Instance>(&mut modules);
use holo_vrrp::interface::Interface;
modules_add::<Interface>(&mut modules);
}

// Create YANG context and load all required modules and their deviations.
Expand Down
6 changes: 6 additions & 0 deletions holo-interface/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ ipnetwork.workspace = true
netlink-packet-route.workspace = true
netlink-packet-core.workspace = true
netlink-sys.workspace = true
regex.workspace = true
rtnetlink.workspace = true
tokio.workspace = true
tracing.workspace = true
Expand All @@ -26,5 +27,10 @@ holo-northbound = { path = "../holo-northbound" }
holo-utils = { path = "../holo-utils" }
holo-yang = { path = "../holo-yang" }

holo-vrrp = { path = "../holo-vrrp", optional = true }

[lints]
workspace = true

[features]
vrrp = ["holo-vrrp"]
4 changes: 4 additions & 0 deletions holo-interface/src/interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use std::net::{IpAddr, Ipv4Addr};

use bitflags::bitflags;
use generational_arena::{Arena, Index};
use holo_northbound::NbDaemonSender;
use holo_utils::ibus::IbusSender;
use holo_utils::ip::Ipv4NetworkExt;
use holo_utils::southbound::{AddressFlags, InterfaceFlags};
Expand Down Expand Up @@ -38,6 +39,7 @@ pub struct Interface {
pub flags: InterfaceFlags,
pub addresses: BTreeMap<IpNetwork, InterfaceAddress>,
pub owner: Owner,
pub vrrp: Option<NbDaemonSender>,
}

#[derive(Debug)]
Expand Down Expand Up @@ -123,6 +125,7 @@ impl Interfaces {
flags: InterfaceFlags::default(),
addresses: Default::default(),
owner: Owner::CONFIG,
vrrp: None,
};

let iface_idx = self.arena.insert(iface);
Expand Down Expand Up @@ -214,6 +217,7 @@ impl Interfaces {
flags,
addresses: Default::default(),
owner: Owner::SYSTEM,
vrrp: None,
};

// Notify protocol instances about the interface update.
Expand Down
45 changes: 41 additions & 4 deletions holo-interface/src/northbound/configuration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,23 @@
// SPDX-License-Identifier: MIT
//

use std::collections::BTreeMap;
use std::collections::{BTreeMap, HashMap};
use std::net::IpAddr;
use std::sync::LazyLock as Lazy;

use async_trait::async_trait;
use enum_as_inner::EnumAsInner;
use holo_northbound::configuration::{
self, Callbacks, CallbacksBuilder, Provider, ValidationCallbacks,
ValidationCallbacksBuilder,
self, Callbacks, CallbacksBuilder, ConfigChanges, Provider,
ValidationCallbacks, ValidationCallbacksBuilder,
};
use holo_northbound::yang::interfaces;
use holo_northbound::{CallbackKey, NbDaemonSender};
use holo_utils::yang::DataNodeRefExt;
use ipnetwork::IpNetwork;

use crate::interface::Owner;
use crate::northbound::REGEX_VRRP;
use crate::{netlink, Master};

static VALIDATION_CALLBACKS: Lazy<ValidationCallbacks> =
Expand Down Expand Up @@ -189,7 +191,7 @@ fn load_callbacks() -> Callbacks<Master> {
let old_plen = iface.config.addr_list.insert(addr, plen).unwrap();

let event_queue = args.event_queue;
event_queue.insert(Event::AddressUninstall(ifname.clone(), addr, old_plen));
//event_queue.insert(Event::AddressUninstall(ifname.clone(), addr, old_plen));
event_queue.insert(Event::AddressInstall(ifname, addr, plen));
})
.delete_apply(|_master, _args| {
Expand Down Expand Up @@ -298,6 +300,41 @@ impl Provider for Master {
Some(&CALLBACKS)
}

fn nested_callbacks() -> Option<Vec<CallbackKey>> {
let keys: Vec<Vec<CallbackKey>> = vec![
#[cfg(feature = "vrrp")]
holo_vrrp::northbound::configuration::CALLBACKS.keys(),
];

Some(keys.concat())
}

fn relay_changes(
&self,
changes: ConfigChanges,
) -> Vec<(ConfigChanges, NbDaemonSender)> {
// Create hash table that maps changes to the appropriate child
// instances.
let mut changes_map: HashMap<String, ConfigChanges> = HashMap::new();
for change in changes {
// HACK: parse interface name from VRRP configuration changes.
let caps = REGEX_VRRP.captures(&change.1).unwrap();
let ifname = caps.get(1).unwrap().as_str().to_owned();

// Move configuration change to the appropriate interface bucket.
changes_map.entry(ifname).or_default().push(change);
}
changes_map
.into_iter()
.filter_map(|(ifname, changes)| {
self.interfaces
.get_by_name(&ifname)
.and_then(|iface| iface.vrrp.clone())
.map(|nb_tx| (changes, nb_tx))
})
.collect::<Vec<_>>()
}

async fn process_event(&mut self, event: Event) {
match event {
Event::InterfaceDelete(ifname) => {
Expand Down
16 changes: 16 additions & 0 deletions holo-interface/src/northbound/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,12 @@
pub mod configuration;
pub mod state;

use std::sync::LazyLock as Lazy;

use holo_northbound::rpc::Provider;
use holo_northbound::yang::interfaces;
use holo_northbound::ProviderBase;
use regex::Regex;
use tracing::{debug_span, Span};

use crate::Master;
Expand Down Expand Up @@ -36,3 +40,15 @@ impl ProviderBase for Master {

// No RPC/Actions to implement.
impl Provider for Master {}

// ===== regular expressions =====

// Matches on the protocol type and instance name of a YANG path.
static REGEX_VRRP_STR: Lazy<String> = Lazy::new(|| {
format!(
r"{}\[name='(.+?)'\]/ietf-ip:ipv4/ietf-vrrp:vrrp/*",
interfaces::interface::PATH
)
});
pub static REGEX_VRRP: Lazy<Regex> =
Lazy::new(|| Regex::new(&REGEX_VRRP_STR).unwrap());
45 changes: 40 additions & 5 deletions holo-interface/src/northbound/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,40 +4,75 @@
// SPDX-License-Identifier: MIT
//

use std::borrow::Cow;
use std::sync::LazyLock as Lazy;

use enum_as_inner::EnumAsInner;
use holo_northbound::state::{
Callbacks, CallbacksBuilder, ListEntryKind, Provider,
};
use holo_northbound::yang::interfaces;
use holo_northbound::{CallbackKey, NbDaemonSender};

use crate::interface::Interface;
use crate::Master;

pub static CALLBACKS: Lazy<Callbacks<Master>> = Lazy::new(load_callbacks);

#[derive(Debug, Default)]
pub enum ListEntry {
#[derive(Debug, Default, EnumAsInner)]
pub enum ListEntry<'a> {
#[default]
None,
Interface(&'a Interface),
}

// ===== callbacks =====

fn load_callbacks() -> Callbacks<Master> {
CallbacksBuilder::default().build()
CallbacksBuilder::<Master>::default()
.path(interfaces::interface::PATH)
.get_iterate(|master, _args| {
let iter = master.interfaces.iter().map(ListEntry::Interface);
Some(Box::new(iter))
})
.get_object(|_master, args| {
use interfaces::interface::Interface;
let iface = args.list_entry.as_interface().unwrap();
Box::new(Interface {
name: Cow::Borrowed(&iface.name),
})
})
.build()
}

// ===== impl Master =====

impl Provider for Master {
const STATE_PATH: &'static str = "/ietf-interfaces:interfaces";

type ListEntry<'a> = ListEntry;
type ListEntry<'a> = ListEntry<'a>;

fn callbacks() -> Option<&'static Callbacks<Master>> {
Some(&CALLBACKS)
}

fn nested_callbacks() -> Option<Vec<CallbackKey>> {
let keys: Vec<Vec<CallbackKey>> = vec![
#[cfg(feature = "vrrp")]
holo_vrrp::northbound::state::CALLBACKS.keys(),
];

Some(keys.concat())
}
}

// ===== impl ListEntry =====

impl ListEntryKind for ListEntry {}
impl<'a> ListEntryKind for ListEntry<'a> {
fn child_task(&self) -> Option<NbDaemonSender> {
match self {
ListEntry::Interface(iface) => iface.vrrp.clone(),
_ => None,
}
}
}
2 changes: 0 additions & 2 deletions holo-vrrp/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,5 +43,3 @@ workspace = true
[features]
default = []
testing = []


39 changes: 5 additions & 34 deletions holo-vrrp/src/debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,17 @@ use std::net::IpAddr;

use tracing::{debug, debug_span};

use crate::packet::VRRPPacket;
use crate::packet::VRRPPacket as Packet;

// VRRP debug messages.
#[derive(Debug)]
pub enum Debug<'a> {
InstanceCreate,
InstanceDelete,
InstanceStart,
InstanceStop(InstanceInactiveReason),
// Network
PacketRx(&'a IpAddr, &'a VRRPPacket),
PacketTx(&'a IpAddr, &'a VRRPPacket),
}

// Reason why an VRRP instance is inactive.
#[derive(Debug)]
pub enum InstanceInactiveReason {
AdminDown,
MissingRouterId,
// Network
PacketRx(&'a IpAddr, &'a Packet),
PacketTx(&'a IpAddr, &'a Packet),
}

// ===== impl Debug =====
Expand All @@ -35,16 +27,10 @@ impl<'a> Debug<'a> {
// Log debug message using the tracing API.
pub(crate) fn log(&self) {
match self {
Debug::InstanceCreate
| Debug::InstanceDelete
| Debug::InstanceStart => {
Debug::InstanceCreate | Debug::InstanceDelete => {
// Parent span(s): vrrp-instance
debug!("{}", self);
}
Debug::InstanceStop(reason) => {
// Parent span(s): vrrp-instance
debug!(%reason, "{}", self);
}
Debug::PacketRx(src, packet) => {
// Parent span(s): vrrp-instance
debug_span!("network").in_scope(|| {
Expand Down Expand Up @@ -84,18 +70,3 @@ impl<'a> std::fmt::Display for Debug<'a> {
}
}
}

// ===== impl InstanceInactiveReason =====

impl std::fmt::Display for InstanceInactiveReason {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
InstanceInactiveReason::AdminDown => {
write!(f, "administrative status down")
}
InstanceInactiveReason::MissingRouterId => {
write!(f, "missing router-id")
}
}
}
}
2 changes: 1 addition & 1 deletion holo-vrrp/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,4 +161,4 @@ fn with_source<E: std::error::Error>(error: E) -> String {
} else {
error.to_string()
}
}
}
1 change: 1 addition & 0 deletions holo-vrrp/src/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ pub(crate) fn process_packet(
_instance: &mut Instance,
_src: IpAddr,
_packet: DecodeResult<VRRPPacket>,

) -> Result<(), Error> {
// TODO

Expand Down
Loading

0 comments on commit 4219aef

Please sign in to comment.