Skip to content

Commit

Permalink
vrrp: add granular modifications.
Browse files Browse the repository at this point in the history
- add change state reason.
- initialize recording of last events.
- introduce Arc<AtomicU64> for adv_sent.

Signed-off-by: Paul Wekesa <[email protected]>
  • Loading branch information
Paul-weqe committed Oct 18, 2024
1 parent 1f5b304 commit 574ebc1
Show file tree
Hide file tree
Showing 6 changed files with 47 additions and 14 deletions.
23 changes: 18 additions & 5 deletions holo-vrrp/src/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use std::time::Duration;
use tracing::{debug, debug_span};

use crate::error::{Error, IoError};
use crate::instance::State;
use crate::instance::{Event, MasterReason, State};
use crate::interface::Interface;
use crate::packet::{DecodeResult, VrrpHdr};
use crate::tasks;
Expand Down Expand Up @@ -130,14 +130,22 @@ fn handle_vrrp_actions(interface: &mut Interface, action: VrrpAction) {

if vrid == 255 {
interface.send_vrrp_advert(vrid);
interface.change_state(vrid, State::Master);
interface.change_state(
vrid,
State::Master,
MasterReason::Priority,
);
if let Some(instance) =
interface.instances.get_mut(&vrid).take()
{
instance.send_gratuitous_arp();
}
} else {
interface.change_state(vrid, State::Backup);
interface.change_state(
vrid,
State::Backup,
MasterReason::NotMaster,
);
}
}
VrrpAction::Backup(_src, pkt) => {
Expand Down Expand Up @@ -194,7 +202,11 @@ fn handle_vrrp_actions(interface: &mut Interface, action: VrrpAction) {
.unwrap()
.network())
{
interface.change_state(vrid, State::Backup);
interface.change_state(
vrid,
State::Backup,
MasterReason::NotMaster,
);
}
}

Expand All @@ -214,10 +226,11 @@ pub(crate) fn handle_master_down_timer(
) -> Result<(), Error> {
interface.send_vrrp_advert(vrid);
if let Some(instance) = interface.instances.get_mut(&vrid) {
instance.state.last_event = Event::MasterTimeout;
instance.send_gratuitous_arp();
}

interface.change_state(vrid, State::Master);
interface.change_state(vrid, State::Master, MasterReason::NoResponse);

Ok(())
}
8 changes: 6 additions & 2 deletions holo-vrrp/src/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
//

use std::net::Ipv4Addr;
use std::sync::atomic::AtomicU64;
use std::sync::Arc;
use std::time::Duration;

use chrono::{DateTime, Utc};
Expand Down Expand Up @@ -52,6 +54,7 @@ pub struct InstanceState {
pub new_master_reason: MasterReason,
pub skew_time: f32,
pub master_down_interval: u32,
pub is_owner: bool,

// TODO: interval/timer tasks
pub statistics: Statistics,
Expand Down Expand Up @@ -95,7 +98,7 @@ pub struct Statistics {
pub discontinuity_time: DateTime<Utc>,
pub master_transitions: u32,
pub adv_rcvd: u64,
pub adv_sent: u64,
pub adv_sent: Arc<AtomicU64>,
pub interval_errors: u64,
pub priority_zero_pkts_rcvd: u64,
pub priority_zero_pkts_sent: u64,
Expand Down Expand Up @@ -250,6 +253,7 @@ impl InstanceState {
statistics: Default::default(),
skew_time: 0.0,
master_down_interval: 0,
is_owner: false,
}
}
}
Expand All @@ -262,7 +266,7 @@ impl Default for Statistics {
discontinuity_time: Utc::now(),
master_transitions: 0,
adv_rcvd: 0,
adv_sent: 0,
adv_sent: Arc::new(AtomicU64::new(0)),
interval_errors: 0,
priority_zero_pkts_rcvd: 0,
priority_zero_pkts_sent: 0,
Expand Down
12 changes: 9 additions & 3 deletions holo-vrrp/src/interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ use tokio::sync::mpsc;
use tracing::{debug, debug_span, error, error_span};

use crate::error::{Error, IoError};
use crate::instance::{Instance, State};
use crate::instance::{Instance, MasterReason, State};
use crate::packet::{DecodeError, VrrpPacket};
use crate::tasks::messages::input::{MasterDownTimerMsg, VrrpNetRxPacketMsg};
use crate::tasks::messages::output::NetTxPacketMsg;
Expand Down Expand Up @@ -155,7 +155,12 @@ impl Interface {
}
}

pub(crate) fn change_state(&mut self, vrid: u8, state: State) {
pub(crate) fn change_state(
&mut self,
vrid: u8,
state: State,
new_master_reason: MasterReason,
) {
if let Some(instance) = self.instances.get_mut(&vrid) {
debug_span!("change-state").in_scope(|| {
if state == State::Backup {
Expand All @@ -169,6 +174,7 @@ impl Interface {
);
}
}
instance.state.new_master_reason = new_master_reason;
} else if state == State::Master {
debug!(%vrid, "state to MASTER.");
if let Some(ifindex) = instance.mac_vlan.system.ifindex {
Expand All @@ -180,6 +186,7 @@ impl Interface {
);
}
}
instance.state.new_master_reason = new_master_reason;
}
});

Expand Down Expand Up @@ -239,7 +246,6 @@ impl Interface {

// check for the exists instance...
if let Some(instance) = self.instances.get_mut(&vrid)

// ...and confirm if the instance's parent Interface has an IP address
&& let Some(addr) = self.system.addresses.first()
{
Expand Down
10 changes: 8 additions & 2 deletions holo-vrrp/src/northbound/configuration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ use holo_northbound::yang::interfaces;
use holo_utils::yang::DataNodeRefExt;
use ipnetwork::Ipv4Network;

use crate::instance::Event as LastEvent;
use crate::instance::Instance;
use crate::interface::Interface;

Expand Down Expand Up @@ -70,7 +71,8 @@ fn load_callbacks() -> Callbacks<Interface> {
.path(interfaces::interface::ipv4::vrrp::vrrp_instance::PATH)
.create_apply(|interface, args| {
let vrid = args.dnode.get_u8_relative("./vrid").unwrap();
let instance = Instance::new(vrid);
let mut instance = Instance::new(vrid);
instance.state.last_event = LastEvent::Startup;
interface.instances.insert(vrid, instance);

let event_queue = args.event_queue;
Expand Down Expand Up @@ -184,7 +186,11 @@ impl Provider for Interface {

// reminder to remove the following line.
// currently up due to state not being properly maintained on startup.
self.change_state(vrid, crate::instance::State::Backup);
self.change_state(
vrid,
crate::instance::State::Backup,
crate::instance::MasterReason::NotMaster,
);
}
Event::InstanceDelete { vrid } => {
self.delete_instance(vrid);
Expand Down
3 changes: 2 additions & 1 deletion holo-vrrp/src/northbound/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
//

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

use enum_as_inner::EnumAsInner;
Expand Down Expand Up @@ -66,7 +67,7 @@ fn load_callbacks() -> Callbacks<Interface> {
discontinuity_datetime: Some(Cow::Borrowed(&statistics.discontinuity_time)).ignore_in_testing(),
master_transitions: Some(statistics.master_transitions).ignore_in_testing(),
advertisement_rcvd: Some(statistics.adv_rcvd).ignore_in_testing(),
advertisement_sent: Some(statistics.adv_sent).ignore_in_testing(),
advertisement_sent: Some(statistics.adv_sent.load(Ordering::Relaxed)).ignore_in_testing(),
interval_errors: Some(statistics.interval_errors).ignore_in_testing(),
priority_zero_pkts_rcvd: Some(statistics.priority_zero_pkts_rcvd).ignore_in_testing(),
priority_zero_pkts_sent: Some(statistics.priority_zero_pkts_sent).ignore_in_testing(),
Expand Down
5 changes: 4 additions & 1 deletion holo-vrrp/src/tasks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
// See: https://nlnet.nl/NGI0
//

use std::sync::atomic::Ordering;
use std::sync::Arc;
use std::time::Duration;

Expand Down Expand Up @@ -200,7 +201,6 @@ pub(crate) fn set_timer(
// in case we are Master, we will be sending VRRP advertisements
// every ADVERT_INTERVAL seconds until otherwise.
crate::instance::State::Master => {
// -----------------
let src_ip = interface.system.addresses.first().unwrap().ip();

let ip_hdr = instance.adver_ipv4_pkt(src_ip);
Expand All @@ -211,6 +211,7 @@ pub(crate) fn set_timer(
vrrp: vrrp_hdr,
};
let ifname = instance.mac_vlan.name.clone();
let adv_sent = instance.state.statistics.adv_sent.clone();
// -----------------
if let Some(net) = &instance.mac_vlan.net {
let net_tx = net.net_tx_packetp.clone();
Expand All @@ -220,10 +221,12 @@ pub(crate) fn set_timer(
),
true,
move || {
let adv_sent = adv_sent.clone();
let ifname = ifname.clone();
let net_tx = net_tx.clone();
let pkt = pkt.clone();
async move {
adv_sent.fetch_add(1, Ordering::Relaxed);
let msg = NetTxPacketMsg::Vrrp { ifname, pkt };
let _ = net_tx.send(msg);
}
Expand Down

0 comments on commit 574ebc1

Please sign in to comment.